Index: ic/mfi.c =================================================================== RCS file: /cvs/src/sys/dev/ic/mfi.c,v retrieving revision 1.165 diff -u -p -r1.165 mfi.c --- ic/mfi.c 9 Sep 2015 18:23:55 -0000 1.165 +++ ic/mfi.c 12 Jan 2017 04:09:36 -0000 @@ -1366,7 +1366,7 @@ mfi_do_mgmt(struct mfi_softc *sc, struct goto done; dcmd = &ccb->ccb_frame->mfr_dcmd; - memset(dcmd->mdf_mbox, 0, MFI_MBOX_SIZE); + memset(&dcmd->mdf_mbox, 0, MFI_MBOX_SIZE); dcmd->mdf_header.mfh_cmd = MFI_CMD_DCMD; dcmd->mdf_header.mfh_timeout = 0; @@ -1378,7 +1378,7 @@ mfi_do_mgmt(struct mfi_softc *sc, struct /* handle special opcodes */ if (mbox) - memcpy(dcmd->mdf_mbox, mbox, MFI_MBOX_SIZE); + memcpy(dcmd->mdf_mbox.b, mbox, MFI_MBOX_SIZE); if (dir != MFI_DATA_NONE) { if (dir == MFI_DATA_OUT) Index: ic/mfireg.h =================================================================== RCS file: /cvs/src/sys/dev/ic/mfireg.h,v retrieving revision 1.45 diff -u -p -r1.45 mfireg.h --- ic/mfireg.h 14 Aug 2016 04:08:03 -0000 1.45 +++ ic/mfireg.h 12 Jan 2017 04:09:36 -0000 @@ -373,11 +373,17 @@ struct mfi_pass_frame { union mfi_sgl mpf_sgl; } __packed; +union mfi_mbox { + uint8_t b[MFI_MBOX_SIZE]; + uint16_t s[6]; + uint32_t w[3]; +} __packed __aligned(4); + #define MFI_DCMD_FRAME_SIZE 40 struct mfi_dcmd_frame { struct mfi_frame_header mdf_header; uint32_t mdf_opcode; - uint8_t mdf_mbox[MFI_MBOX_SIZE]; + union mfi_mbox mdf_mbox; union mfi_sgl mdf_sgl; } __packed; @@ -436,7 +442,7 @@ struct mfi_evt_log_info { uint32_t mel_clear_seq_num; uint32_t mel_shutdown_seq_num; uint32_t mel_boot_seq_num; -} __packed; +} __packed __aligned(4); struct mfi_progress { uint16_t mp_progress; Index: pci/mfii.c =================================================================== RCS file: /cvs/src/sys/dev/pci/mfii.c,v retrieving revision 1.28 diff -u -p -r1.28 mfii.c --- pci/mfii.c 24 Oct 2016 05:27:52 -0000 1.28 +++ pci/mfii.c 12 Jan 2017 04:09:36 -0000 @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -60,7 +61,7 @@ struct mfii_request_descr { u_int16_t lmid; u_int16_t dev_handle; -} __packed; +} __packed __aligned(8); #define MFII_RAID_CTX_IO_TYPE_SYSPD (0x1 << 4) #define MFII_RAID_CTX_TYPE_CUDA (0x2 << 4) @@ -244,6 +245,11 @@ struct mfii_softc { struct mfii_ccb *sc_ccb; struct mfii_ccb_list sc_ccb_freeq; + struct mfii_ccb *sc_aen_ccb; + struct mutex sc_aen_mtx; + struct mfii_ccb_list sc_aen_list; + struct task sc_aen_task; + struct scsi_link sc_link; struct scsibus_softc *sc_scsibus; struct mfii_pd_softc *sc_pd; @@ -335,6 +341,12 @@ int mfii_scsi_cmd_cdb(struct mfii_soft int mfii_pd_scsi_cmd_cdb(struct mfii_softc *, struct scsi_xfer *); +static int mfii_aen_register(struct mfii_softc *); +static void mfii_aen_start(struct mfii_softc *, + struct mfii_ccb *, uint32_t); +static void mfii_aen_done(struct mfii_softc *, struct mfii_ccb *); +static void mfii_aen_task(void *); +static void mfii_aen_unregister(struct mfii_softc *); #define mfii_fw_state(_sc) mfii_read((_sc), MFI_OSP) @@ -416,6 +428,10 @@ mfii_attach(struct device *parent, struc mtx_init(&sc->sc_reply_postq_mtx, IPL_BIO); scsi_iopool_init(&sc->sc_iopool, sc, mfii_get_ccb, mfii_put_ccb); + mtx_init(&sc->sc_aen_mtx, IPL_BIO); + SIMPLEQ_INIT(&sc->sc_aen_list); + task_set(&sc->sc_aen_task, mfii_aen_task, sc); + /* wire up the bus shizz */ memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, MFII_BAR); if (pci_mapreg_map(pa, MFII_BAR, memtype, 0, @@ -491,10 +507,15 @@ mfii_attach(struct device *parent, struc printf(", %uMB cache", letoh16(sc->sc_info.mci_memory_size)); printf("\n"); + if (mfii_aen_register(sc) != 0) { + /* error printed by mfii_aen_register */ + goto free_sgl; + } + sc->sc_ih = pci_intr_establish(sc->sc_pc, ih, IPL_BIO, mfii_intr, sc, DEVNAME(sc)); if (sc->sc_ih == NULL) - goto free_sgl; + goto aen_unregister; sc->sc_link.openings = sc->sc_max_cmds; sc->sc_link.adapter_softc = sc; @@ -515,6 +536,8 @@ mfii_attach(struct device *parent, struc mfii_write(sc, MFI_OMSK, ~MFII_OSTS_INTR_VALID); return; +aen_unregister: + mfii_aen_unregister(sc); free_sgl: mfii_dmamem_free(sc, sc->sc_sgl); free_requests: @@ -527,6 +550,141 @@ pci_unmap: bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios); } +static int +mfii_aen_register(struct mfii_softc *sc) +{ + struct mfi_evt_log_info mel; + struct mfii_ccb *ccb; + uint32_t seq; + int rv; + + ccb = scsi_io_get(&sc->sc_iopool, 0); + if (ccb == NULL) { + printf("%s: unable to allocate ccb for aen\n", DEVNAME(sc)); + return (ENOMEM); + } + + memset(&mel, 0, sizeof(mel)); + + rv = mfii_mgmt(sc, ccb, MR_DCMD_CTRL_EVENT_GET_INFO, NULL, + &mel, sizeof(mel), SCSI_DATA_IN|SCSI_NOSLEEP); + if (rv != 0) { + scsi_io_put(&sc->sc_iopool, ccb); + printf("%s: unable to get event info\n", DEVNAME(sc)); + return (EIO); + } + + printf("%s: event info\n", DEVNAME(sc)); + seq = lemtoh32(&mel.mel_newest_seq_num); + printf("%s: newest seq: %u %08x\n", DEVNAME(sc), seq, seq); + seq = lemtoh32(&mel.mel_oldest_seq_num); + printf("%s: oldest seq: %u %08x\n", DEVNAME(sc), seq, seq); + seq = lemtoh32(&mel.mel_clear_seq_num); + printf("%s: clear seq: %u %08x\n", DEVNAME(sc), seq, seq); + seq = lemtoh32(&mel.mel_shutdown_seq_num); + printf("%s: shutdown seq: %u %08x\n", DEVNAME(sc), seq, seq); + seq = lemtoh32(&mel.mel_boot_seq_num); + printf("%s: boot seq: %u %08x\n", DEVNAME(sc), seq, seq); + + ccb->ccb_cookie = mfii_dmamem_alloc(sc, sizeof(struct mfi_evt_detail)); + if (ccb->ccb_cookie == NULL) { + scsi_io_put(&sc->sc_iopool, ccb); + printf("%s: unable to allocate event data\n", DEVNAME(sc)); + return (ENOMEM); + } + + sc->sc_aen_ccb = ccb; + mfii_aen_start(sc, ccb, lemtoh32(&mel.mel_boot_seq_num)); + + return (0); +} + +void +mfii_aen_start(struct mfii_softc *sc, struct mfii_ccb *ccb, uint32_t seq) +{ + struct mfi_dcmd_frame *dcmd = ccb->ccb_request; + struct mfi_frame_header *hdr = &dcmd->mdf_header; + union mfi_sgl *sgl = &dcmd->mdf_sgl; + struct mfii_dmamem *mdm = ccb->ccb_cookie; + union mfi_evt_class_locale mec; + + mfii_scrub_ccb(ccb); /* this clears ccb_cookie */ + + memset(MFII_DMA_KVA(mdm), 0, MFII_DMA_LEN(mdm)); + ccb->ccb_cookie = mdm; + ccb->ccb_done = mfii_aen_done; + + mec.mec_members.locale = MFI_EVT_LOCALE_ALL; + mec.mec_members.reserved = 0; + mec.mec_members.class = MFI_EVT_CLASS_DEBUG; + + hdr->mfh_cmd = MFI_CMD_DCMD; + hdr->mfh_context = ccb->ccb_smid; + hdr->mfh_sg_count = 1; + hdr->mfh_flags = htole16(MFI_FRAME_DIR_READ); + hdr->mfh_data_len = htole32(MFII_DMA_LEN(mdm)); + dcmd->mdf_opcode = htole32(MR_DCMD_CTRL_EVENT_WAIT); + dcmd->mdf_mbox.w[0] = htole32(seq); + dcmd->mdf_mbox.w[1] = mec.mec_word; + sgl->sg32[0].addr = htole32(MFII_DMA_DVA(mdm)); + sgl->sg32[0].len = htole32(MFII_DMA_LEN(mdm)); + + ccb->ccb_req.flags = MFII_REQ_TYPE_SCSI; + ccb->ccb_req.smid = letoh16(ccb->ccb_smid); + + mfii_start(sc, ccb); +} + +void +mfii_aen_done(struct mfii_softc *sc, struct mfii_ccb *ccb) +{ + mtx_enter(&sc->sc_aen_mtx); + SIMPLEQ_INSERT_TAIL(&sc->sc_aen_list, ccb, ccb_link); + mtx_leave(&sc->sc_aen_mtx); + + task_add(systqmp, &sc->sc_aen_task); +} + +static void +mfii_aen_task(void *scp) +{ + struct mfii_softc *sc = scp; + struct mfii_ccb *list, *ccb; + + mtx_enter(&sc->sc_aen_mtx); + list = SIMPLEQ_FIRST(&sc->sc_aen_list); + SIMPLEQ_INIT(&sc->sc_aen_list); + mtx_leave(&sc->sc_aen_mtx); + + while (list != NULL) { + struct mfii_dmamem *mdm; + struct mfi_evt_detail *med; + struct mfi_frame_header *hdr; + uint32_t seq; + + ccb = list; + list = SIMPLEQ_NEXT(ccb, ccb_link); + + hdr = ccb->ccb_request; + mdm = ccb->ccb_cookie; + med = MFII_DMA_KVA(mdm); + seq = lemtoh32(&med->med_seq_num); + + printf("%s: %x %u %08x %s\n", DEVNAME(sc), hdr->mfh_cmd_status, + seq, seq, med->med_description); + + tsleep(ccb, PWAIT, "mfiiaen", 100); + + mfii_aen_start(sc, ccb, seq + 1); + } +} + +static void +mfii_aen_unregister(struct mfii_softc *sc) +{ + +} + int mfii_syspd(struct mfii_softc *sc) { @@ -1078,10 +1236,10 @@ mfii_mgmt(struct mfii_softc *sc, struct hdr->mfh_data_len = htole32(len); hdr->mfh_sg_count = ccb->ccb_dmamap->dm_nsegs; - dcmd->mdf_opcode = opc; + dcmd->mdf_opcode = htole32(opc); /* handle special opcodes */ if (mbox != NULL) - memcpy(dcmd->mdf_mbox, mbox, MFI_MBOX_SIZE); + memcpy(dcmd->mdf_mbox.b, mbox, MFI_MBOX_SIZE); if (ISSET(flags, SCSI_NOSLEEP)) mfii_mfa_poll(sc, ccb); @@ -1146,7 +1304,7 @@ mfii_start(struct mfii_softc *sc, struct BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); #if defined(__LP64__) - bus_space_write_raw_8(sc->sc_iot, sc->sc_ioh, MFI_IQPL, *r); + bus_space_write_raw_8(sc->sc_iot, sc->sc_ioh, MFI_IQPL, *r); #else mtx_enter(&sc->sc_post_mtx); bus_space_write_raw_4(sc->sc_iot, sc->sc_ioh, MFI_IQPL, r[0]); @@ -1155,7 +1313,7 @@ mfii_start(struct mfii_softc *sc, struct bus_space_write_raw_4(sc->sc_iot, sc->sc_ioh, MFI_IQPH, r[1]); bus_space_barrier(sc->sc_iot, sc->sc_ioh, - MFI_IQPH, 8, BUS_SPACE_BARRIER_WRITE); + MFI_IQPL, 8, BUS_SPACE_BARRIER_WRITE); mtx_leave(&sc->sc_post_mtx); #endif }