Date: Tue, 10 Apr 2012 16:33:19 +0000 (UTC) From: Jim Harris <jimharris@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r234106 - head/sys/dev/isci Message-ID: <201204101633.q3AGXJjG031714@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: jimharris Date: Tue Apr 10 16:33:19 2012 New Revision: 234106 URL: http://svn.freebsd.org/changeset/base/234106 Log: Queue CCBs internally instead of using CAM_REQUEUE_REQ status. This fixes problem where userspace apps such as smartctl fail due to CAM_REQUEUE_REQ status getting returned when tagged commands are outstanding when smartctl sends its I/O using the pass(4) interface. Sponsored by: Intel Found and tested by: Ravi Pokala <rpokala at panasas dot com> Reviewed by: scottl Approved by: scottl MFC after: 1 week Modified: head/sys/dev/isci/isci.h head/sys/dev/isci/isci_controller.c head/sys/dev/isci/isci_io_request.c head/sys/dev/isci/isci_remote_device.c Modified: head/sys/dev/isci/isci.h ============================================================================== --- head/sys/dev/isci/isci.h Tue Apr 10 16:08:46 2012 (r234105) +++ head/sys/dev/isci/isci.h Tue Apr 10 16:33:19 2012 (r234106) @@ -86,6 +86,7 @@ struct ISCI_REMOTE_DEVICE { BOOL is_resetting; uint32_t frozen_lun_mask; SCI_FAST_LIST_ELEMENT_T pending_device_reset_element; + TAILQ_HEAD(,ccb_hdr) queued_ccbs; }; struct ISCI_DOMAIN { Modified: head/sys/dev/isci/isci_controller.c ============================================================================== --- head/sys/dev/isci/isci_controller.c Tue Apr 10 16:08:46 2012 (r234105) +++ head/sys/dev/isci/isci_controller.c Tue Apr 10 16:33:19 2012 (r234106) @@ -430,6 +430,7 @@ int isci_controller_allocate_memory(stru remote_device->frozen_lun_mask = 0; sci_fast_list_element_init(remote_device, &remote_device->pending_device_reset_element); + TAILQ_INIT(&remote_device->queued_ccbs); /* * For the first SCI_MAX_DOMAINS device objects, do not put Modified: head/sys/dev/isci/isci_io_request.c ============================================================================== --- head/sys/dev/isci/isci_io_request.c Tue Apr 10 16:08:46 2012 (r234105) +++ head/sys/dev/isci/isci_io_request.c Tue Apr 10 16:33:19 2012 (r234106) @@ -85,7 +85,9 @@ isci_io_request_complete(SCI_CONTROLLER_ struct ISCI_CONTROLLER *isci_controller; struct ISCI_REMOTE_DEVICE *isci_remote_device; union ccb *ccb; + BOOL complete_ccb; + complete_ccb = TRUE; isci_controller = (struct ISCI_CONTROLLER *) sci_object_get_association(scif_controller); isci_remote_device = (struct ISCI_REMOTE_DEVICE *) sci_object_get_association(remote_device); @@ -163,9 +165,7 @@ isci_io_request_complete(SCI_CONTROLLER_ case SCI_IO_FAILURE_INVALID_STATE: case SCI_IO_FAILURE_INSUFFICIENT_RESOURCES: - ccb->ccb_h.status |= CAM_REQUEUE_REQ; - isci_remote_device_freeze_lun_queue(isci_remote_device, - ccb->ccb_h.target_lun); + complete_ccb = FALSE; break; case SCI_IO_FAILURE_INVALID_REMOTE_DEVICE: @@ -189,7 +189,7 @@ isci_io_request_complete(SCI_CONTROLLER_ scif_remote_device_get_max_queue_depth(remote_device); xpt_action((union ccb *)&ccb_relsim); xpt_free_path(path); - ccb->ccb_h.status |= CAM_REQUEUE_REQ; + complete_ccb = FALSE; } break; @@ -209,17 +209,6 @@ isci_io_request_complete(SCI_CONTROLLER_ break; } - if (ccb->ccb_h.status != CAM_REQ_CMP) { - /* ccb will be completed with some type of non-success - * status. So temporarily freeze the queue until the - * upper layers can act on the status. The CAM_DEV_QFRZN - * flag will then release the queue after the status is - * acted upon. - */ - ccb->ccb_h.status |= CAM_DEV_QFRZN; - xpt_freeze_devq(ccb->ccb_h.path, 1); - } - callout_stop(&isci_request->parent.timer); bus_dmamap_sync(isci_request->parent.dma_tag, isci_request->parent.dma_map, @@ -228,20 +217,43 @@ isci_io_request_complete(SCI_CONTROLLER_ bus_dmamap_unload(isci_request->parent.dma_tag, isci_request->parent.dma_map); - if (isci_remote_device->frozen_lun_mask != 0 && - !(ccb->ccb_h.status & CAM_REQUEUE_REQ)) - isci_remote_device_release_device_queue(isci_remote_device); - - xpt_done(ccb); isci_request->ccb = NULL; - if (isci_controller->is_frozen == TRUE) { - isci_controller->is_frozen = FALSE; - xpt_release_simq(isci_controller->sim, TRUE); - } - sci_pool_put(isci_controller->request_pool, (struct ISCI_REQUEST *)isci_request); + + if (complete_ccb) { + if (ccb->ccb_h.status != CAM_REQ_CMP) { + /* ccb will be completed with some type of non-success + * status. So temporarily freeze the queue until the + * upper layers can act on the status. The + * CAM_DEV_QFRZN flag will then release the queue + * after the status is acted upon. + */ + ccb->ccb_h.status |= CAM_DEV_QFRZN; + xpt_freeze_devq(ccb->ccb_h.path, 1); + } + + if (isci_remote_device->frozen_lun_mask != 0) { + isci_remote_device_release_device_queue(isci_remote_device); + } + + xpt_done(ccb); + + if (isci_controller->is_frozen == TRUE) { + isci_controller->is_frozen = FALSE; + xpt_release_simq(isci_controller->sim, TRUE); + } + } else { + isci_remote_device_freeze_lun_queue(isci_remote_device, + ccb->ccb_h.target_lun); + + isci_log_message(1, "ISCI", "queue %p %x\n", ccb, + ccb->csio.cdb_io.cdb_bytes[0]); + ccb->ccb_h.status |= CAM_SIM_QUEUED; + TAILQ_INSERT_TAIL(&isci_remote_device->queued_ccbs, + &ccb->ccb_h, sim_links.tqe); + } } /** Modified: head/sys/dev/isci/isci_remote_device.c ============================================================================== --- head/sys/dev/isci/isci_remote_device.c Tue Apr 10 16:08:46 2012 (r234105) +++ head/sys/dev/isci/isci_remote_device.c Tue Apr 10 16:33:19 2012 (r234106) @@ -289,9 +289,22 @@ isci_remote_device_release_lun_queue(str void isci_remote_device_release_device_queue( - struct ISCI_REMOTE_DEVICE *remote_device) + struct ISCI_REMOTE_DEVICE *device) { - lun_id_t lun; - for (lun = 0; lun < ISCI_MAX_LUN; lun++) - isci_remote_device_release_lun_queue(remote_device, lun); + if (TAILQ_EMPTY(&device->queued_ccbs)) { + lun_id_t lun; + + for (lun = 0; lun < ISCI_MAX_LUN; lun++) + isci_remote_device_release_lun_queue(device, lun); + } else { + struct ccb_hdr *ccb_h; + + ccb_h = TAILQ_FIRST(&device->queued_ccbs); + TAILQ_REMOVE(&device->queued_ccbs, ccb_h, sim_links.tqe); + ccb_h->status &= ~CAM_SIM_QUEUED; + isci_log_message(1, "ISCI", "release %p %x\n", ccb_h, + ((union ccb*)ccb_h)->csio.cdb_io.cdb_bytes[0]); + isci_io_request_execute_scsi_io((union ccb *)ccb_h, + device->domain->controller); + } }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201204101633.q3AGXJjG031714>