Date: Mon, 3 Dec 2012 18:37:03 +0000 (UTC) From: Xin LI <delphij@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org Subject: svn commit: r243824 - stable/9/sys/dev/mfi Message-ID: <201212031837.qB3Ib3fj006137@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: delphij Date: Mon Dec 3 18:37:02 2012 New Revision: 243824 URL: http://svnweb.freebsd.org/changeset/base/243824 Log: MFC r242681 (ambrisko): - Extend the prior commit to use the generic SCSI command building function use that for JBOD and Thunderbolt disk write command. Now we only have one implementation in mfi. - Fix dumping on Thunderbolt cards. Polled IO commands do not seem to be normally acknowledged by changing cmd_status to MFI_STAT_OK. In order to get acknowledgement of the IO is complete, the Thunderbolt command queue needs to be run through. I added a flag MFI_CMD_SCSI to indicate this command is being polled and to complete the Thunderbolt wrapper and indicate the result. This flag needs to be set in the JBOD case in case if that us using Thunderbolt card. When in the polling loop check for completed commands. - Remove mfi_tbolt_is_ldio and just do the check when needed. - Fix an issue when attaching of disk device happens when a device is already scheduled to be attached but hasn't attached. - add a tunable to allow raw disk attachment to CAM via: hw.mfi.allow_cam_disk_passthrough=1 - fixup aborting of commands (AEN and LD state change). Use a generic abort function and only wait the command being aborted not both. Thunderbolt cards don't seem to abort commands so the abort times out. Modified: stable/9/sys/dev/mfi/mfi.c stable/9/sys/dev/mfi/mfi_cam.c stable/9/sys/dev/mfi/mfi_disk.c stable/9/sys/dev/mfi/mfi_syspd.c stable/9/sys/dev/mfi/mfi_tbolt.c stable/9/sys/dev/mfi/mfivar.h Directory Properties: stable/9/sys/ (props changed) stable/9/sys/dev/ (props changed) Modified: stable/9/sys/dev/mfi/mfi.c ============================================================================== --- stable/9/sys/dev/mfi/mfi.c Mon Dec 3 18:34:54 2012 (r243823) +++ stable/9/sys/dev/mfi/mfi.c Mon Dec 3 18:37:02 2012 (r243824) @@ -106,11 +106,9 @@ static void mfi_add_sys_pd_complete(stru static struct mfi_command * mfi_bio_command(struct mfi_softc *); static void mfi_bio_complete(struct mfi_command *); static struct mfi_command *mfi_build_ldio(struct mfi_softc *,struct bio*); -static int mfi_build_syspd_cdb(struct mfi_pass_frame *pass, uint32_t block_count, - uint64_t lba, uint8_t byte2, int readop); static struct mfi_command *mfi_build_syspdio(struct mfi_softc *,struct bio*); static int mfi_send_frame(struct mfi_softc *, struct mfi_command *); -static int mfi_abort(struct mfi_softc *, struct mfi_command *); +static int mfi_abort(struct mfi_softc *, struct mfi_command **); static int mfi_linux_ioctl_int(struct cdev *, u_long, caddr_t, int, struct thread *); static void mfi_timeout(void *); static int mfi_user_command(struct mfi_softc *, @@ -376,6 +374,8 @@ mfi_attach(struct mfi_softc *sc) sx_init(&sc->mfi_config_lock, "MFI config"); TAILQ_INIT(&sc->mfi_ld_tqh); TAILQ_INIT(&sc->mfi_syspd_tqh); + TAILQ_INIT(&sc->mfi_ld_pend_tqh); + TAILQ_INIT(&sc->mfi_syspd_pend_tqh); TAILQ_INIT(&sc->mfi_evt_queue); TASK_INIT(&sc->mfi_evt_task, 0, mfi_handle_evt, sc); TASK_INIT(&sc->mfi_map_sync_task, 0, mfi_handle_map_sync, sc); @@ -697,6 +697,7 @@ mfi_attach(struct mfi_softc *sc) device_printf(sc->mfi_dev, "Cannot set up interrupt\n"); return (EINVAL); } + sc->mfi_intr_ptr = mfi_intr_tbolt; sc->mfi_enable_intr(sc); } else { if ((error = mfi_comms_init(sc)) != 0) @@ -707,6 +708,7 @@ mfi_attach(struct mfi_softc *sc) device_printf(sc->mfi_dev, "Cannot set up interrupt\n"); return (EINVAL); } + sc->mfi_intr_ptr = mfi_intr; sc->mfi_enable_intr(sc); } if ((error = mfi_get_controller_info(sc)) != 0) @@ -1281,6 +1283,17 @@ mfi_shutdown(struct mfi_softc *sc) struct mfi_command *cm; int error; + + if (sc->mfi_aen_cm) + sc->cm_aen_abort = 1; + if (sc->mfi_aen_cm != NULL) + mfi_abort(sc, &sc->mfi_aen_cm); + + if (sc->mfi_map_sync_cm) + sc->cm_map_abort = 1; + if (sc->mfi_map_sync_cm != NULL) + mfi_abort(sc, &sc->mfi_map_sync_cm); + mtx_lock(&sc->mfi_io_lock); error = mfi_dcmd_command(sc, &cm, MFI_DCMD_CTRL_SHUTDOWN, NULL, 0); if (error) { @@ -1288,12 +1301,6 @@ mfi_shutdown(struct mfi_softc *sc) return (error); } - if (sc->mfi_aen_cm != NULL) - mfi_abort(sc, sc->mfi_aen_cm); - - if (sc->mfi_map_sync_cm != NULL) - mfi_abort(sc, sc->mfi_map_sync_cm); - dcmd = &cm->cm_frame->dcmd; dcmd->header.flags = MFI_FRAME_DIR_NONE; cm->cm_flags = MFI_CMD_POLLED; @@ -1315,6 +1322,7 @@ mfi_syspdprobe(struct mfi_softc *sc) struct mfi_command *cm = NULL; struct mfi_pd_list *pdlist = NULL; struct mfi_system_pd *syspd, *tmp; + struct mfi_system_pending *syspd_pend; int error, i, found; sx_assert(&sc->mfi_config_lock, SA_XLOCKED); @@ -1355,6 +1363,10 @@ mfi_syspdprobe(struct mfi_softc *sc) if (syspd->pd_id == pdlist->addr[i].device_id) found = 1; } + TAILQ_FOREACH(syspd_pend, &sc->mfi_syspd_pend_tqh, pd_link) { + if (syspd_pend->pd_id == pdlist->addr[i].device_id) + found = 1; + } if (found == 0) mfi_add_sys_pd(sc, pdlist->addr[i].device_id); } @@ -1390,6 +1402,7 @@ mfi_ldprobe(struct mfi_softc *sc) struct mfi_command *cm = NULL; struct mfi_ld_list *list = NULL; struct mfi_disk *ld; + struct mfi_disk_pending *ld_pend; int error, i; sx_assert(&sc->mfi_config_lock, SA_XLOCKED); @@ -1418,6 +1431,10 @@ mfi_ldprobe(struct mfi_softc *sc) if (ld->ld_id == list->ld_list[i].ld.v.target_id) goto skip_add; } + TAILQ_FOREACH(ld_pend, &sc->mfi_ld_pend_tqh, ld_link) { + if (ld_pend->ld_id == list->ld_list[i].ld.v.target_id) + goto skip_add; + } mfi_add_ld(sc, list->ld_list[i].ld.v.target_id); skip_add:; } @@ -1620,9 +1637,7 @@ mfi_aen_register(struct mfi_softc *sc, i < current_aen.members.evt_class) current_aen.members.evt_class = prior_aen.members.evt_class; - mtx_lock(&sc->mfi_io_lock); - mfi_abort(sc, sc->mfi_aen_cm); - mtx_unlock(&sc->mfi_io_lock); + mfi_abort(sc, &sc->mfi_aen_cm); } } @@ -1814,10 +1829,17 @@ mfi_add_ld(struct mfi_softc *sc, int id) struct mfi_command *cm; struct mfi_dcmd_frame *dcmd = NULL; struct mfi_ld_info *ld_info = NULL; + struct mfi_disk_pending *ld_pend; int error; mtx_assert(&sc->mfi_io_lock, MA_OWNED); + ld_pend = malloc(sizeof(*ld_pend), M_MFIBUF, M_NOWAIT | M_ZERO); + if (ld_pend != NULL) { + ld_pend->ld_id = id; + TAILQ_INSERT_TAIL(&sc->mfi_ld_pend_tqh, ld_pend, ld_link); + } + error = mfi_dcmd_command(sc, &cm, MFI_DCMD_LD_GET_INFO, (void **)&ld_info, sizeof(*ld_info)); if (error) { @@ -1858,11 +1880,13 @@ mfi_add_ld_complete(struct mfi_command * hdr = &cm->cm_frame->header; ld_info = cm->cm_private; - if (hdr->cmd_status != MFI_STAT_OK) { + if (sc->cm_map_abort || hdr->cmd_status != MFI_STAT_OK) { free(ld_info, M_MFIBUF); + wakeup(&sc->mfi_map_sync_cm); mfi_release_command(cm); return; } + wakeup(&sc->mfi_map_sync_cm); mfi_release_command(cm); mtx_unlock(&sc->mfi_io_lock); @@ -1887,10 +1911,17 @@ static int mfi_add_sys_pd(struct mfi_sof struct mfi_command *cm; struct mfi_dcmd_frame *dcmd = NULL; struct mfi_pd_info *pd_info = NULL; + struct mfi_system_pending *syspd_pend; int error; mtx_assert(&sc->mfi_io_lock, MA_OWNED); + syspd_pend = malloc(sizeof(*syspd_pend), M_MFIBUF, M_NOWAIT | M_ZERO); + if (syspd_pend != NULL) { + syspd_pend->pd_id = id; + TAILQ_INSERT_TAIL(&sc->mfi_syspd_pend_tqh, syspd_pend, pd_link); + } + error = mfi_dcmd_command(sc, &cm, MFI_DCMD_PD_GET_INFO, (void **)&pd_info, sizeof(*pd_info)); if (error) { @@ -1985,9 +2016,12 @@ mfi_bio_command(struct mfi_softc *sc) return cm; } -static int -mfi_build_syspd_cdb(struct mfi_pass_frame *pass, uint32_t block_count, - uint64_t lba, uint8_t byte2, int readop) +/* + * mostly copied from cam/scsi/scsi_all.c:scsi_read_write + */ + +int +mfi_build_cdb(int readop, uint8_t byte2, u_int64_t lba, u_int32_t block_count, uint8_t *cdb) { int cdb_len; @@ -1997,7 +2031,7 @@ mfi_build_syspd_cdb(struct mfi_pass_fram /* We can fit in a 6 byte cdb */ struct scsi_rw_6 *scsi_cmd; - scsi_cmd = (struct scsi_rw_6 *)&pass->cdb; + scsi_cmd = (struct scsi_rw_6 *)cdb; scsi_cmd->opcode = readop ? READ_6 : WRITE_6; scsi_ulto3b(lba, scsi_cmd->addr); scsi_cmd->length = block_count & 0xff; @@ -2007,7 +2041,7 @@ mfi_build_syspd_cdb(struct mfi_pass_fram /* Need a 10 byte CDB */ struct scsi_rw_10 *scsi_cmd; - scsi_cmd = (struct scsi_rw_10 *)&pass->cdb; + scsi_cmd = (struct scsi_rw_10 *)cdb; scsi_cmd->opcode = readop ? READ_10 : WRITE_10; scsi_cmd->byte2 = byte2; scsi_ulto4b(lba, scsi_cmd->addr); @@ -2020,7 +2054,7 @@ mfi_build_syspd_cdb(struct mfi_pass_fram /* Block count is too big for 10 byte CDB use a 12 byte CDB */ struct scsi_rw_12 *scsi_cmd; - scsi_cmd = (struct scsi_rw_12 *)&pass->cdb; + scsi_cmd = (struct scsi_rw_12 *)cdb; scsi_cmd->opcode = readop ? READ_12 : WRITE_12; scsi_cmd->byte2 = byte2; scsi_ulto4b(lba, scsi_cmd->addr); @@ -2035,7 +2069,7 @@ mfi_build_syspd_cdb(struct mfi_pass_fram */ struct scsi_rw_16 *scsi_cmd; - scsi_cmd = (struct scsi_rw_16 *)&pass->cdb; + scsi_cmd = (struct scsi_rw_16 *)cdb; scsi_cmd->opcode = readop ? READ_16 : WRITE_16; scsi_cmd->byte2 = byte2; scsi_u64to8b(lba, scsi_cmd->addr); @@ -2053,15 +2087,15 @@ mfi_build_syspdio(struct mfi_softc *sc, { struct mfi_command *cm; struct mfi_pass_frame *pass; - int flags = 0; + uint32_t context = 0; + int flags = 0, blkcount = 0, readop; uint8_t cdb_len; - uint32_t block_count, context = 0; if ((cm = mfi_dequeue_free(sc)) == NULL) return (NULL); /* Zero out the MFI frame */ - context = cm->cm_frame->header.context; + context = cm->cm_frame->header.context; bzero(cm->cm_frame, sizeof(union mfi_frame)); cm->cm_frame->header.context = context; pass = &cm->cm_frame->pass; @@ -2070,22 +2104,24 @@ mfi_build_syspdio(struct mfi_softc *sc, switch (bio->bio_cmd & 0x03) { case BIO_READ: flags = MFI_CMD_DATAIN; + readop = 1; break; case BIO_WRITE: flags = MFI_CMD_DATAOUT; + readop = 0; break; default: /* TODO: what about BIO_DELETE??? */ - panic("Unsupported bio command"); + panic("Unsupported bio command %x\n", bio->bio_cmd); } /* Cheat with the sector length to avoid a non-constant division */ - block_count = (bio->bio_bcount + MFI_SECTOR_LEN - 1) / MFI_SECTOR_LEN; + blkcount = (bio->bio_bcount + MFI_SECTOR_LEN - 1) / MFI_SECTOR_LEN; /* Fill the LBA and Transfer length in CDB */ - cdb_len = mfi_build_syspd_cdb(pass, block_count, bio->bio_pblkno, 0, - flags == MFI_CMD_DATAIN); - + cdb_len = mfi_build_cdb(readop, 0, bio->bio_pblkno, blkcount, + pass->cdb); pass->header.target_id = (uintptr_t)bio->bio_driver1; + pass->header.lun_id = 0; pass->header.timeout = 0; pass->header.flags = 0; pass->header.scsi_status = 0; @@ -2132,7 +2168,7 @@ mfi_build_ldio(struct mfi_softc *sc, str break; default: /* TODO: what about BIO_DELETE??? */ - panic("Unsupported bio command"); + panic("Unsupported bio command %x\n", bio->bio_cmd); } /* Cheat with the sector length to avoid a non-constant division */ @@ -2422,15 +2458,14 @@ mfi_complete(struct mfi_softc *sc, struc } static int -mfi_abort(struct mfi_softc *sc, struct mfi_command *cm_abort) +mfi_abort(struct mfi_softc *sc, struct mfi_command **cm_abort) { struct mfi_command *cm; struct mfi_abort_frame *abort; int i = 0; uint32_t context = 0; - mtx_assert(&sc->mfi_io_lock, MA_OWNED); - + mtx_lock(&sc->mfi_io_lock); if ((cm = mfi_dequeue_free(sc)) == NULL) { return (EBUSY); } @@ -2444,29 +2479,27 @@ mfi_abort(struct mfi_softc *sc, struct m abort->header.cmd = MFI_CMD_ABORT; abort->header.flags = 0; abort->header.scsi_status = 0; - abort->abort_context = cm_abort->cm_frame->header.context; - abort->abort_mfi_addr_lo = (uint32_t)cm_abort->cm_frame_busaddr; + abort->abort_context = (*cm_abort)->cm_frame->header.context; + abort->abort_mfi_addr_lo = (uint32_t)(*cm_abort)->cm_frame_busaddr; abort->abort_mfi_addr_hi = - (uint32_t)((uint64_t)cm_abort->cm_frame_busaddr >> 32); + (uint32_t)((uint64_t)(*cm_abort)->cm_frame_busaddr >> 32); cm->cm_data = NULL; cm->cm_flags = MFI_CMD_POLLED; - if (sc->mfi_aen_cm) - sc->cm_aen_abort = 1; - if (sc->mfi_map_sync_cm) - sc->cm_map_abort = 1; mfi_mapcmd(sc, cm); mfi_release_command(cm); - while (i < 5 && sc->mfi_aen_cm != NULL) { - msleep(&sc->mfi_aen_cm, &sc->mfi_io_lock, 0, "mfiabort", + mtx_unlock(&sc->mfi_io_lock); + while (i < 5 && *cm_abort != NULL) { + tsleep(cm_abort, 0, "mfiabort", 5 * hz); i++; } - while (i < 5 && sc->mfi_map_sync_cm != NULL) { - msleep(&sc->mfi_map_sync_cm, &sc->mfi_io_lock, 0, "mfiabort", - 5 * hz); - i++; + if (*cm_abort != NULL) { + /* Force a complete if command didn't abort */ + mtx_lock(&sc->mfi_io_lock); + (*cm_abort)->cm_complete(*cm_abort); + mtx_unlock(&sc->mfi_io_lock); } return (0); @@ -2522,7 +2555,7 @@ mfi_dump_syspd_blocks(struct mfi_softc * { struct mfi_command *cm; struct mfi_pass_frame *pass; - int error; + int error, readop, cdb_len; uint32_t blkcount; if ((cm = mfi_dequeue_free(sc)) == NULL) @@ -2531,21 +2564,24 @@ mfi_dump_syspd_blocks(struct mfi_softc * pass = &cm->cm_frame->pass; bzero(pass->cdb, 16); pass->header.cmd = MFI_CMD_PD_SCSI_IO; + + readop = 0; blkcount = (len + MFI_SECTOR_LEN - 1) / MFI_SECTOR_LEN; + cdb_len = mfi_build_cdb(readop, 0, lba, blkcount, pass->cdb); pass->header.target_id = id; pass->header.timeout = 0; pass->header.flags = 0; pass->header.scsi_status = 0; pass->header.sense_len = MFI_SENSE_LEN; pass->header.data_len = len; - pass->header.cdb_len = mfi_build_syspd_cdb(pass, blkcount, lba, 0, 0); + pass->header.cdb_len = cdb_len; pass->sense_addr_lo = (uint32_t)cm->cm_sense_busaddr; pass->sense_addr_hi = (uint32_t)((uint64_t)cm->cm_sense_busaddr >> 32); cm->cm_data = virt; cm->cm_len = len; cm->cm_sg = &pass->sgl; cm->cm_total_frame_size = MFI_PASS_FRAME_SIZE; - cm->cm_flags = MFI_CMD_POLLED | MFI_CMD_DATAOUT; + cm->cm_flags = MFI_CMD_POLLED | MFI_CMD_DATAOUT | MFI_CMD_SCSI; error = mfi_mapcmd(sc, cm); bus_dmamap_sync(sc->mfi_buffer_dmat, cm->cm_dmamap, @@ -2745,16 +2781,24 @@ mfi_check_command_post(struct mfi_softc } } -static int mfi_check_for_sscd(struct mfi_softc *sc, struct mfi_command *cm) +static int +mfi_check_for_sscd(struct mfi_softc *sc, struct mfi_command *cm) { - struct mfi_config_data *conf_data=(struct mfi_config_data *)cm->cm_data; + struct mfi_config_data *conf_data; struct mfi_command *ld_cm = NULL; struct mfi_ld_info *ld_info = NULL; + struct mfi_ld_config *ld; + char *p; int error = 0; - if ((cm->cm_frame->dcmd.opcode == MFI_DCMD_CFG_ADD) && - (conf_data->ld[0].params.isSSCD == 1)) { - error = 1; + conf_data = (struct mfi_config_data *)cm->cm_data; + + if (cm->cm_frame->dcmd.opcode == MFI_DCMD_CFG_ADD) { + p = (char *)conf_data->array; + p += conf_data->array_size * conf_data->array_count; + ld = (struct mfi_ld_config *)p; + if (ld->params.isSSCD == 1) + error = 1; } else if (cm->cm_frame->dcmd.opcode == MFI_DCMD_LD_DELETE) { error = mfi_dcmd_command (sc, &ld_cm, MFI_DCMD_LD_GET_INFO, (void **)&ld_info, sizeof(*ld_info)); Modified: stable/9/sys/dev/mfi/mfi_cam.c ============================================================================== --- stable/9/sys/dev/mfi/mfi_cam.c Mon Dec 3 18:34:54 2012 (r243823) +++ stable/9/sys/dev/mfi/mfi_cam.c Mon Dec 3 18:37:02 2012 (r243824) @@ -79,6 +79,11 @@ static void mfip_cam_poll(struct cam_sim static struct mfi_command * mfip_start(void *); static void mfip_done(struct mfi_command *cm); +static int mfi_allow_disks = 0; +TUNABLE_INT("hw.mfi.allow_cam_disk_passthrough", &mfi_allow_disks); +SYSCTL_INT(_hw_mfi, OID_AUTO, allow_cam_disk_passthrough, CTLFLAG_RD, + &mfi_allow_disks, 0, "event message locale"); + static devclass_t mfip_devclass; static device_method_t mfip_methods[] = { DEVMETHOD(device_probe, mfip_probe), @@ -349,7 +354,8 @@ mfip_done(struct mfi_command *cm) command = csio->cdb_io.cdb_bytes[0]; if (command == INQUIRY) { device = csio->data_ptr[0] & 0x1f; - if ((device == T_DIRECT) || (device == T_PROCESSOR)) + if ((!mfi_allow_disks && device == T_DIRECT) || + (device == T_PROCESSOR)) csio->data_ptr[0] = (csio->data_ptr[0] & 0xe0) | T_NODEVICE; } @@ -392,6 +398,9 @@ mfip_done(struct mfi_command *cm) static void mfip_cam_poll(struct cam_sim *sim) { - return; + struct mfip_softc *sc = cam_sim_softc(sim); + struct mfi_softc *mfisc = sc->mfi_sc; + + mfisc->mfi_intr_ptr(mfisc); } Modified: stable/9/sys/dev/mfi/mfi_disk.c ============================================================================== --- stable/9/sys/dev/mfi/mfi_disk.c Mon Dec 3 18:34:54 2012 (r243823) +++ stable/9/sys/dev/mfi/mfi_disk.c Mon Dec 3 18:37:02 2012 (r243824) @@ -93,6 +93,7 @@ mfi_disk_attach(device_t dev) { struct mfi_disk *sc; struct mfi_ld_info *ld_info; + struct mfi_disk_pending *ld_pend; uint64_t sectors; uint32_t secsize; char *state; @@ -111,6 +112,13 @@ mfi_disk_attach(device_t dev) secsize = MFI_SECTOR_LEN; mtx_lock(&sc->ld_controller->mfi_io_lock); TAILQ_INSERT_TAIL(&sc->ld_controller->mfi_ld_tqh, sc, ld_link); + TAILQ_FOREACH(ld_pend, &sc->ld_controller->mfi_ld_pend_tqh, + ld_link) { + TAILQ_REMOVE(&sc->ld_controller->mfi_ld_pend_tqh, + ld_pend, ld_link); + free(ld_pend, M_MFIBUF); + break; + } mtx_unlock(&sc->ld_controller->mfi_io_lock); switch (ld_info->ld_config.params.state) { @@ -131,16 +139,16 @@ mfi_disk_attach(device_t dev) break; } - if ( strlen(ld_info->ld_config.properties.name) == 0 ) { - device_printf(dev, - "%juMB (%ju sectors) RAID volume (no label) is %s\n", - sectors / (1024 * 1024 / secsize), sectors, state); - } else { - device_printf(dev, - "%juMB (%ju sectors) RAID volume '%s' is %s\n", - sectors / (1024 * 1024 / secsize), sectors, - ld_info->ld_config.properties.name, state); - } + if ( strlen(ld_info->ld_config.properties.name) == 0 ) { + device_printf(dev, + "%juMB (%ju sectors) RAID volume (no label) is %s\n", + sectors / (1024 * 1024 / secsize), sectors, state); + } else { + device_printf(dev, + "%juMB (%ju sectors) RAID volume '%s' is %s\n", + sectors / (1024 * 1024 / secsize), sectors, + ld_info->ld_config.properties.name, state); + } sc->ld_disk = disk_alloc(); sc->ld_disk->d_drv1 = sc; Modified: stable/9/sys/dev/mfi/mfi_syspd.c ============================================================================== --- stable/9/sys/dev/mfi/mfi_syspd.c Mon Dec 3 18:34:54 2012 (r243823) +++ stable/9/sys/dev/mfi/mfi_syspd.c Mon Dec 3 18:37:02 2012 (r243824) @@ -89,7 +89,6 @@ DRIVER_MODULE(mfisyspd, mfi, mfi_syspd_d static int mfi_syspd_probe(device_t dev) { - return (0); } @@ -98,12 +97,12 @@ mfi_syspd_attach(device_t dev) { struct mfi_system_pd *sc; struct mfi_pd_info *pd_info; + struct mfi_system_pending *syspd_pend; uint64_t sectors; uint32_t secsize; sc = device_get_softc(dev); pd_info = device_get_ivars(dev); - sc->pd_dev = dev; sc->pd_id = pd_info->ref.v.device_id; sc->pd_unit = device_get_unit(dev); @@ -115,6 +114,13 @@ mfi_syspd_attach(device_t dev) secsize = MFI_SECTOR_LEN; mtx_lock(&sc->pd_controller->mfi_io_lock); TAILQ_INSERT_TAIL(&sc->pd_controller->mfi_syspd_tqh, sc, pd_link); + TAILQ_FOREACH(syspd_pend, &sc->pd_controller->mfi_syspd_pend_tqh, + pd_link) { + TAILQ_REMOVE(&sc->pd_controller->mfi_syspd_pend_tqh, + syspd_pend, pd_link); + free(syspd_pend, M_MFIBUF); + break; + } mtx_unlock(&sc->pd_controller->mfi_io_lock); device_printf(dev, "%juMB (%ju sectors) SYSPD volume (deviceid: %d)\n", sectors / (1024 * 1024 / secsize), sectors, sc->pd_id); @@ -139,6 +145,7 @@ mfi_syspd_attach(device_t dev) disk_create(sc->pd_disk, DISK_VERSION); device_printf(dev, " SYSPD volume attached\n"); + return (0); } Modified: stable/9/sys/dev/mfi/mfi_tbolt.c ============================================================================== --- stable/9/sys/dev/mfi/mfi_tbolt.c Mon Dec 3 18:34:54 2012 (r243823) +++ stable/9/sys/dev/mfi/mfi_tbolt.c Mon Dec 3 18:37:02 2012 (r243824) @@ -69,13 +69,10 @@ uint8_t mfi_build_mpt_pass_thru(struct mfi_softc *sc, struct mfi_command *mfi_cmd); union mfi_mpi2_request_descriptor *mfi_build_and_issue_cmd(struct mfi_softc *sc, struct mfi_command *mfi_cmd); -int mfi_tbolt_is_ldio(struct mfi_command *mfi_cmd); void mfi_tbolt_build_ldio(struct mfi_softc *sc, struct mfi_command *mfi_cmd, struct mfi_cmd_tbolt *cmd); static int mfi_tbolt_make_sgl(struct mfi_softc *sc, struct mfi_command *mfi_cmd, pMpi25IeeeSgeChain64_t sgl_ptr, struct mfi_cmd_tbolt *cmd); -static int mfi_tbolt_build_cdb(struct mfi_softc *sc, struct mfi_command - *mfi_cmd, uint8_t *cdb); void map_tbolt_cmd_status(struct mfi_command *mfi_cmd, uint8_t status, uint8_t ext_status); @@ -502,6 +499,7 @@ mfi_tbolt_alloc_cmd(struct mfi_softc *sc + i * MEGASAS_MAX_SZ_CHAIN_FRAME); cmd->sg_frame_phys_addr = sc->sg_frame_busaddr + i * MEGASAS_MAX_SZ_CHAIN_FRAME; + cmd->sync_cmd_idx = sc->mfi_max_fw_cmds; TAILQ_INSERT_TAIL(&(sc->mfi_cmd_tbolt_tqh), cmd, next); } @@ -574,11 +572,11 @@ void map_tbolt_cmd_status(struct mfi_command *mfi_cmd, uint8_t status, uint8_t ext_status) { - switch (status) { case MFI_STAT_OK: - mfi_cmd->cm_frame->header.cmd_status = 0; - mfi_cmd->cm_frame->dcmd.header.cmd_status = 0; + mfi_cmd->cm_frame->header.cmd_status = MFI_STAT_OK; + mfi_cmd->cm_frame->dcmd.header.cmd_status = MFI_STAT_OK; + mfi_cmd->cm_error = MFI_STAT_OK; break; case MFI_STAT_SCSI_IO_FAILED: @@ -618,6 +616,7 @@ mfi_tbolt_return_cmd(struct mfi_softc *s { mtx_assert(&sc->mfi_io_lock, MA_OWNED); + cmd->sync_cmd_idx = sc->mfi_max_fw_cmds; TAILQ_INSERT_TAIL(&sc->mfi_cmd_tbolt_tqh, cmd, next); } @@ -667,16 +666,26 @@ mfi_tbolt_complete_cmd(struct mfi_softc extStatus = cmd_mfi->cm_frame->dcmd.header.scsi_status; map_tbolt_cmd_status(cmd_mfi, status, extStatus); - /* remove command from busy queue if not polled */ - TAILQ_FOREACH(cmd_mfi_check, &sc->mfi_busy, cm_link) { - if (cmd_mfi_check == cmd_mfi) { - mfi_remove_busy(cmd_mfi); - break; + if (cmd_mfi->cm_flags & MFI_CMD_SCSI && + (cmd_mfi->cm_flags & MFI_CMD_POLLED) != 0) { + /* polled LD/SYSPD IO command */ + mfi_tbolt_return_cmd(sc, cmd_tbolt); + /* XXX mark okay for now DJA */ + cmd_mfi->cm_frame->header.cmd_status = MFI_STAT_OK; + } else { + + /* remove command from busy queue if not polled */ + TAILQ_FOREACH(cmd_mfi_check, &sc->mfi_busy, cm_link) { + if (cmd_mfi_check == cmd_mfi) { + mfi_remove_busy(cmd_mfi); + break; + } } + + /* complete the command */ + mfi_complete(sc, cmd_mfi); + mfi_tbolt_return_cmd(sc, cmd_tbolt); } - cmd_mfi->cm_error = 0; - mfi_complete(sc, cmd_mfi); - mfi_tbolt_return_cmd(sc, cmd_tbolt); sc->last_reply_idx++; if (sc->last_reply_idx >= sc->mfi_max_fw_cmds) { @@ -811,13 +820,13 @@ mfi_tbolt_build_ldio(struct mfi_softc *s MFI_FRAME_DIR_READ) io_info.isRead = 1; - io_request->RaidContext.timeoutValue - = MFI_FUSION_FP_DEFAULT_TIMEOUT; - io_request->Function = MPI2_FUNCTION_LD_IO_REQUEST; - io_request->DevHandle = device_id; - cmd->request_desc->header.RequestFlags - = (MFI_REQ_DESCRIPT_FLAGS_LD_IO - << MFI_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); + io_request->RaidContext.timeoutValue + = MFI_FUSION_FP_DEFAULT_TIMEOUT; + io_request->Function = MPI2_FUNCTION_LD_IO_REQUEST; + io_request->DevHandle = device_id; + cmd->request_desc->header.RequestFlags + = (MFI_REQ_DESCRIPT_FLAGS_LD_IO + << MFI_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); if ((io_request->IoFlags == 6) && (io_info.numBlocks == 0)) io_request->RaidContext.RegLockLength = 0x100; io_request->DataLength = mfi_cmd->cm_frame->io.header.data_len @@ -825,40 +834,36 @@ mfi_tbolt_build_ldio(struct mfi_softc *s } int -mfi_tbolt_is_ldio(struct mfi_command *mfi_cmd) -{ - if (mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_READ - || mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE) - return 1; - else - return 0; -} - -int mfi_tbolt_build_io(struct mfi_softc *sc, struct mfi_command *mfi_cmd, struct mfi_cmd_tbolt *cmd) { - uint32_t device_id; + struct mfi_mpi2_request_raid_scsi_io *io_request; uint32_t sge_count; - uint8_t cdb[32], cdb_len; - - memset(cdb, 0, 32); - struct mfi_mpi2_request_raid_scsi_io *io_request = cmd->io_request; - - device_id = mfi_cmd->cm_frame->header.target_id; + uint8_t cdb_len; + int readop; + u_int64_t lba; - /* Have to build CDB here for TB as BSD don't have a scsi layer */ - if ((cdb_len = mfi_tbolt_build_cdb(sc, mfi_cmd, cdb)) == 1) + io_request = cmd->io_request; + if (!(mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_READ + || mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE)) return 1; - /* Just the CDB length,rest of the Flags are zero */ - io_request->IoFlags = cdb_len; - memcpy(io_request->CDB.CDB32, cdb, 32); + mfi_tbolt_build_ldio(sc, mfi_cmd, cmd); - if (mfi_tbolt_is_ldio(mfi_cmd)) - mfi_tbolt_build_ldio(sc, mfi_cmd , cmd); + /* Convert to SCSI command CDB */ + bzero(io_request->CDB.CDB32, sizeof(io_request->CDB.CDB32)); + if (mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE) + readop = 0; else - return 1; + readop = 1; + + lba = mfi_cmd->cm_frame->io.lba_hi; + lba = (lba << 32) + mfi_cmd->cm_frame->io.lba_lo; + cdb_len = mfi_build_cdb(readop, 0, lba, + mfi_cmd->cm_frame->io.header.data_len, io_request->CDB.CDB32); + + /* Just the CDB length, rest of the Flags are zero */ + io_request->IoFlags = cdb_len; /* * Construct SGL @@ -883,84 +888,12 @@ mfi_tbolt_build_io(struct mfi_softc *sc, io_request->SenseBufferLowAddress = mfi_cmd->cm_sense_busaddr; io_request->SenseBufferLength = MFI_SENSE_LEN; + io_request->RaidContext.Status = MFI_STAT_INVALID_STATUS; + io_request->RaidContext.exStatus = MFI_STAT_INVALID_STATUS; + return 0; } -static int -mfi_tbolt_build_cdb(struct mfi_softc *sc, struct mfi_command *mfi_cmd, - uint8_t *cdb) -{ - uint32_t lba_lo, lba_hi, num_lba; - uint8_t cdb_len; - - if (mfi_cmd == NULL || cdb == NULL) - return 1; - num_lba = mfi_cmd->cm_frame->io.header.data_len; - lba_lo = mfi_cmd->cm_frame->io.lba_lo; - lba_hi = mfi_cmd->cm_frame->io.lba_hi; - - if (lba_hi == 0 && (num_lba <= 0xFF) && (lba_lo <= 0x1FFFFF)) { - if (mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE) - /* Read 6 or Write 6 */ - cdb[0] = (uint8_t) (0x0A); - else - cdb[0] = (uint8_t) (0x08); - - cdb[4] = (uint8_t) num_lba; - cdb[3] = (uint8_t) (lba_lo & 0xFF); - cdb[2] = (uint8_t) (lba_lo >> 8); - cdb[1] = (uint8_t) ((lba_lo >> 16) & 0x1F); - cdb_len = 6; - } - else if (lba_hi == 0 && (num_lba <= 0xFFFF) && (lba_lo <= 0xFFFFFFFF)) { - if (mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE) - /* Read 10 or Write 10 */ - cdb[0] = (uint8_t) (0x2A); - else - cdb[0] = (uint8_t) (0x28); - cdb[8] = (uint8_t) (num_lba & 0xFF); - cdb[7] = (uint8_t) (num_lba >> 8); - cdb[5] = (uint8_t) (lba_lo & 0xFF); - cdb[4] = (uint8_t) (lba_lo >> 8); - cdb[3] = (uint8_t) (lba_lo >> 16); - cdb[2] = (uint8_t) (lba_lo >> 24); - cdb_len = 10; - } else if ((num_lba > 0xFFFF) && (lba_hi == 0)) { - if (mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE) - /* Read 12 or Write 12 */ - cdb[0] = (uint8_t) (0xAA); - else - cdb[0] = (uint8_t) (0xA8); - cdb[9] = (uint8_t) (num_lba & 0xFF); - cdb[8] = (uint8_t) (num_lba >> 8); - cdb[7] = (uint8_t) (num_lba >> 16); - cdb[6] = (uint8_t) (num_lba >> 24); - cdb[5] = (uint8_t) (lba_lo & 0xFF); - cdb[4] = (uint8_t) (lba_lo >> 8); - cdb[3] = (uint8_t) (lba_lo >> 16); - cdb[2] = (uint8_t) (lba_lo >> 24); - cdb_len = 12; - } else { - if (mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE) - cdb[0] = (uint8_t) (0x8A); - else - cdb[0] = (uint8_t) (0x88); - cdb[13] = (uint8_t) (num_lba & 0xFF); - cdb[12] = (uint8_t) (num_lba >> 8); - cdb[11] = (uint8_t) (num_lba >> 16); - cdb[10] = (uint8_t) (num_lba >> 24); - cdb[9] = (uint8_t) (lba_lo & 0xFF); - cdb[8] = (uint8_t) (lba_lo >> 8); - cdb[7] = (uint8_t) (lba_lo >> 16); - cdb[6] = (uint8_t) (lba_lo >> 24); - cdb[5] = (uint8_t) (lba_hi & 0xFF); - cdb[4] = (uint8_t) (lba_hi >> 8); - cdb[3] = (uint8_t) (lba_hi >> 16); - cdb[2] = (uint8_t) (lba_hi >> 24); - cdb_len = 16; - } - return cdb_len; -} static int mfi_tbolt_make_sgl(struct mfi_softc *sc, struct mfi_command *mfi_cmd, @@ -1100,8 +1033,7 @@ mfi_tbolt_send_frame(struct mfi_softc *s if ((cm->cm_flags & MFI_CMD_POLLED) == 0) { cm->cm_timestamp = time_uptime; mfi_enqueue_busy(cm); - } - else { /* still get interrupts for it */ + } else { /* still get interrupts for it */ hdr->cmd_status = MFI_STAT_INVALID_STATUS; hdr->flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE; } @@ -1118,31 +1050,49 @@ mfi_tbolt_send_frame(struct mfi_softc *s } else device_printf(sc->mfi_dev, "DJA NA XXX SYSPDIO\n"); - } - else if (hdr->cmd == MFI_CMD_LD_SCSI_IO || + } else if (hdr->cmd == MFI_CMD_LD_SCSI_IO || hdr->cmd == MFI_CMD_LD_READ || hdr->cmd == MFI_CMD_LD_WRITE) { + cm->cm_flags |= MFI_CMD_SCSI; if ((req_desc = mfi_build_and_issue_cmd(sc, cm)) == NULL) { device_printf(sc->mfi_dev, "LDIO Failed \n"); return 1; } - } else - if ((req_desc = mfi_tbolt_build_mpt_cmd(sc, cm)) == NULL) { + } else if ((req_desc = mfi_tbolt_build_mpt_cmd(sc, cm)) == NULL) { device_printf(sc->mfi_dev, "Mapping from MFI to MPT " "Failed\n"); return 1; - } + } + + if (cm->cm_flags & MFI_CMD_SCSI) { + /* + * LD IO needs to be posted since it doesn't get + * acknowledged via a status update so have the + * controller reply via mfi_tbolt_complete_cmd. + */ + hdr->flags &= ~MFI_FRAME_DONT_POST_IN_REPLY_QUEUE; + } + MFI_WRITE4(sc, MFI_ILQP, (req_desc->words & 0xFFFFFFFF)); MFI_WRITE4(sc, MFI_IHQP, (req_desc->words >>0x20)); if ((cm->cm_flags & MFI_CMD_POLLED) == 0) return 0; + if (cm->cm_flags & MFI_CMD_SCSI) { + /* check reply queue */ + mfi_tbolt_complete_cmd(sc); + } + /* This is a polled command, so busy-wait for it to complete. */ while (hdr->cmd_status == MFI_STAT_INVALID_STATUS) { DELAY(1000); tm -= 1; if (tm <= 0) - break; + break; + if (cm->cm_flags & MFI_CMD_SCSI) { + /* check reply queue */ + mfi_tbolt_complete_cmd(sc); + } } if (hdr->cmd_status == MFI_STAT_INVALID_STATUS) { @@ -1375,7 +1325,7 @@ mfi_tbolt_sync_map_info(struct mfi_softc free(ld_sync, M_MFIBUF); goto out; } - + context = cmd->cm_frame->header.context; bzero(cmd->cm_frame, sizeof(union mfi_frame)); cmd->cm_frame->header.context = context; Modified: stable/9/sys/dev/mfi/mfivar.h ============================================================================== --- stable/9/sys/dev/mfi/mfivar.h Mon Dec 3 18:34:54 2012 (r243823) +++ stable/9/sys/dev/mfi/mfivar.h Mon Dec 3 18:37:02 2012 (r243824) @@ -106,6 +106,7 @@ struct mfi_command { #define MFI_ON_MFIQ_READY (1<<6) #define MFI_ON_MFIQ_BUSY (1<<7) #define MFI_ON_MFIQ_MASK ((1<<5)|(1<<6)|(1<<7)) +#define MFI_CMD_SCSI (1<<8) uint8_t retry_for_fw_reset; void (* cm_complete)(struct mfi_command *cm); void *cm_private; @@ -126,6 +127,11 @@ struct mfi_disk { #define MFI_DISK_FLAGS_DISABLED 0x02 }; +struct mfi_disk_pending { + TAILQ_ENTRY(mfi_disk_pending) ld_link; + int ld_id; +}; + struct mfi_system_pd { TAILQ_ENTRY(mfi_system_pd) pd_link; device_t pd_dev; @@ -137,6 +143,11 @@ struct mfi_system_pd { int pd_flags; }; +struct mfi_system_pending { + TAILQ_ENTRY(mfi_system_pending) pd_link; + int pd_id; +}; + struct mfi_evt_queue_elm { TAILQ_ENTRY(mfi_evt_queue_elm) link; struct mfi_evt_detail detail; @@ -285,6 +296,8 @@ struct mfi_softc { TAILQ_HEAD(,mfi_disk) mfi_ld_tqh; TAILQ_HEAD(,mfi_system_pd) mfi_syspd_tqh; + TAILQ_HEAD(,mfi_disk_pending) mfi_ld_pend_tqh; + TAILQ_HEAD(,mfi_system_pending) mfi_syspd_pend_tqh; eventhandler_tag mfi_eh; struct cdev *mfi_cdev; @@ -303,6 +316,7 @@ struct mfi_softc { uint32_t frame_cnt); int (*mfi_adp_reset)(struct mfi_softc *sc); int (*mfi_adp_check_reset)(struct mfi_softc *sc); + void (*mfi_intr_ptr)(void *sc); /* ThunderBolt */ uint32_t mfi_tbolt; @@ -421,7 +435,8 @@ extern int mfi_tbolt_reset(struct mfi_so extern void mfi_tbolt_sync_map_info(struct mfi_softc *sc); extern void mfi_handle_map_sync(void *context, int pending); extern int mfi_dcmd_command(struct mfi_softc *, struct mfi_command **, - uint32_t, void **, size_t); + uint32_t, void **, size_t); +extern int mfi_build_cdb(int, uint8_t, u_int64_t, u_int32_t, uint8_t *); #define MFIQ_ADD(sc, qname) \ do { \
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201212031837.qB3Ib3fj006137>