Instead of storing the IO tracker structure in a separate list that we need to pop/push to on every submit and complete (and lock), store it in the pdu associated with a request. This is possible on scsi-mq only, and further cuts the spinlock associated time for higher IOPS IO workloads. At 100K IOPS, this effectively cuts the locking time in half. Signed-off-by: Jens Axboe <axboe@xxxxxx> --- drivers/scsi/mpt2sas/mpt2sas_base.c | 194 +++++++++++++++++++++++++---------- drivers/scsi/mpt2sas/mpt2sas_base.h | 3 + drivers/scsi/mpt2sas/mpt2sas_ctl.c | 119 ++++++++++++++++----- drivers/scsi/mpt2sas/mpt2sas_scsih.c | 89 ++++++++++++---- 4 files changed, 307 insertions(+), 98 deletions(-) diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index 11248de92b3b..b0e4453af64c 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -828,6 +828,20 @@ _base_async_event(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, u32 reply) return; } +struct scsiio_tracker * +mpt2sas_get_st_from_smid(struct MPT2SAS_ADAPTER *ioc, u16 smid) +{ + if (shost_use_blk_mq(ioc->shost)) { + struct scsi_cmnd *scmd; + + scmd = scsi_mq_find_tag(ioc->shost, smid - 1); + if (!scmd) + return NULL; + return scsi_mq_scmd_to_pdu(scmd); + } else + return &ioc->scsi_lookup[smid - 1]; +} + /** * _base_get_cb_idx - obtain the callback index * @ioc: per adapter object @@ -842,8 +856,10 @@ _base_get_cb_idx(struct MPT2SAS_ADAPTER *ioc, u16 smid) u8 cb_idx; if (smid < ioc->hi_priority_smid) { - i = smid - 1; - cb_idx = ioc->scsi_lookup[i].cb_idx; + struct scsiio_tracker *st; + + st = mpt2sas_get_st_from_smid(ioc, smid); + cb_idx = st->cb_idx; } else if (smid < ioc->internal_smid) { i = smid - ioc->hi_priority_smid; cb_idx = ioc->hpr_lookup[i].cb_idx; @@ -962,18 +978,17 @@ _base_interrupt(int irq, void *bus_id) goto next; if (smid) { cb_idx = _base_get_cb_idx(ioc, smid); - if ((likely(cb_idx < MPT_MAX_CALLBACKS)) + if ((likely(cb_idx < MPT_MAX_CALLBACKS)) && (likely(mpt_callbacks[cb_idx] != NULL))) { rc = mpt_callbacks[cb_idx](ioc, smid, msix_index, reply); - if (reply) - _base_display_reply_info(ioc, smid, - msix_index, reply); - if (rc) - mpt2sas_base_free_smid(ioc, smid); + if (reply) + _base_display_reply_info(ioc, smid, + msix_index, reply); + if (rc) + mpt2sas_base_free_smid(ioc, smid); } - } - if (!smid) + } else _base_async_event(ioc, msix_index, reply); /* reply free queue handling */ @@ -1724,6 +1739,18 @@ mpt2sas_base_get_smid_scsiio(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx, struct scsiio_tracker *request; u16 smid; + if (shost_use_blk_mq(ioc->shost)) { + /* + * If we don't have a SCSI command associated with this smid, + * bump it to high-prio + */ + if (!scmd) + return mpt2sas_base_get_smid_hpr(ioc, cb_idx); + + request = scsi_mq_scmd_to_pdu(scmd); + return request->smid; + } + spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); if (list_empty(&ioc->free_list)) { spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); @@ -1771,6 +1798,31 @@ mpt2sas_base_get_smid_hpr(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx) return smid; } +static void +_base_recovery_check(struct MPT2SAS_ADAPTER *ioc) +{ + /* + * See _wait_for_commands_to_complete() call with regards to this code. + */ + if (ioc->shost_recovery && ioc->pending_io_count) { + if (ioc->pending_io_count == 1) + wake_up(&ioc->reset_wq); + ioc->pending_io_count = 0; + } +} + +static void +_dechain_st(struct MPT2SAS_ADAPTER *ioc, struct scsiio_tracker *st) +{ + struct chain_tracker *chain_req; + + while (!list_empty(&st->chain_list)) { + chain_req = list_first_entry(&st->chain_list, + struct chain_tracker, + tracker_list); + list_move(&chain_req->tracker_list, &ioc->free_chain_list); + } +} /** * mpt2sas_base_free_smid - put smid back on free_list @@ -1784,20 +1836,32 @@ mpt2sas_base_free_smid(struct MPT2SAS_ADAPTER *ioc, u16 smid) { unsigned long flags; int i; - struct chain_tracker *chain_req, *next; + + if (shost_use_blk_mq(ioc->shost) && smid < ioc->hi_priority_smid) { + struct scsiio_tracker *st; + + st = mpt2sas_get_st_from_smid(ioc, smid); + if (!st) + return; + + st->direct_io = 0; + + if (!list_empty(&st->chain_list)) { + spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); + _dechain_st(ioc, st); + spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); + } + + _base_recovery_check(ioc); + return; + } spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); if (smid < ioc->hi_priority_smid) { /* scsiio queue */ i = smid - 1; - if (!list_empty(&ioc->scsi_lookup[i].chain_list)) { - list_for_each_entry_safe(chain_req, next, - &ioc->scsi_lookup[i].chain_list, tracker_list) { - list_del_init(&chain_req->tracker_list); - list_add(&chain_req->tracker_list, - &ioc->free_chain_list); - } - } + if (!list_empty(&ioc->scsi_lookup[i].chain_list)) + _dechain_st(ioc, &ioc->scsi_lookup[i]); ioc->scsi_lookup[i].cb_idx = 0xFF; ioc->scsi_lookup[i].scmd = NULL; ioc->scsi_lookup[i].direct_io = 0; @@ -1805,15 +1869,7 @@ mpt2sas_base_free_smid(struct MPT2SAS_ADAPTER *ioc, u16 smid) &ioc->free_list); spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - /* - * See _wait_for_commands_to_complete() call with regards - * to this code. - */ - if (ioc->shost_recovery && ioc->pending_io_count) { - if (ioc->pending_io_count == 1) - wake_up(&ioc->reset_wq); - ioc->pending_io_count--; - } + _base_recovery_check(ioc); return; } else if (smid < ioc->internal_smid) { /* hi-priority */ @@ -2723,14 +2779,23 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) ioc->name, (unsigned long long) ioc->request_dma)); total_sz += sz; - sz = ioc->scsiio_depth * sizeof(struct scsiio_tracker); - ioc->scsi_lookup_pages = get_order(sz); - ioc->scsi_lookup = (struct scsiio_tracker *)__get_free_pages( - GFP_KERNEL, ioc->scsi_lookup_pages); - if (!ioc->scsi_lookup) { - printk(MPT2SAS_ERR_FMT "scsi_lookup: get_free_pages failed, " - "sz(%d)\n", ioc->name, (int)sz); - goto out; + /* + * Don't need to allocate memory for scsiio_tracker array if we + * are using scsi-mq, we embed it in the scsi_cmnd for that case. + */ + if (!shost_use_blk_mq(ioc->shost)) { + sz = ioc->scsiio_depth * sizeof(struct scsiio_tracker); + ioc->scsi_lookup_pages = get_order(sz); + ioc->scsi_lookup = (struct scsiio_tracker *)__get_free_pages( + GFP_KERNEL, ioc->scsi_lookup_pages); + if (!ioc->scsi_lookup) { + printk(MPT2SAS_ERR_FMT "scsi_lookup: get_free_pages " + "failed, sz(%d)\n", ioc->name, (int)sz); + goto out; + } + } else { + ioc->scsi_lookup_pages = 0; + ioc->scsi_lookup = NULL; } dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scsiio(0x%p): " @@ -4299,15 +4364,17 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) /* initialize the scsi lookup free list */ spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); INIT_LIST_HEAD(&ioc->free_list); - smid = 1; - for (i = 0; i < ioc->scsiio_depth; i++, smid++) { - INIT_LIST_HEAD(&ioc->scsi_lookup[i].chain_list); - ioc->scsi_lookup[i].cb_idx = 0xFF; - ioc->scsi_lookup[i].smid = smid; - ioc->scsi_lookup[i].scmd = NULL; - ioc->scsi_lookup[i].direct_io = 0; - list_add_tail(&ioc->scsi_lookup[i].tracker_list, - &ioc->free_list); + if (!shost_use_blk_mq(ioc->shost)) { + smid = 1; + for (i = 0; i < ioc->scsiio_depth; i++, smid++) { + INIT_LIST_HEAD(&ioc->scsi_lookup[i].chain_list); + ioc->scsi_lookup[i].cb_idx = 0xFF; + ioc->scsi_lookup[i].smid = smid; + ioc->scsi_lookup[i].scmd = NULL; + ioc->scsi_lookup[i].direct_io = 0; + list_add_tail(&ioc->scsi_lookup[i].tracker_list, + &ioc->free_list); + } } /* hi-priority queue */ @@ -4772,7 +4839,7 @@ _wait_for_commands_to_complete(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) { u32 ioc_state; unsigned long flags; - u16 i; + u16 i, pending, loops; ioc->pending_io_count = 0; if (sleep_flag != CAN_SLEEP) @@ -4783,17 +4850,34 @@ _wait_for_commands_to_complete(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) return; /* pending command count */ - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - for (i = 0; i < ioc->scsiio_depth; i++) - if (ioc->scsi_lookup[i].cb_idx != 0xFF) - ioc->pending_io_count++; - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); + loops = 0; + do { + pending = 0; + spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); + for (i = 0; i < ioc->scsiio_depth; i++) { + struct scsiio_tracker *st; + struct scsi_cmnd *scmd; + + if (shost_use_blk_mq(ioc->shost)) { + scmd = scsi_mq_find_tag(ioc->shost, i); + if (scsi_mq_scmd_started(scmd)) + pending++; + } else { + st = mpt2sas_get_st_from_smid(ioc, i + 1); + if (st->cb_idx != 0xFF) + pending++; + } + } + spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - if (!ioc->pending_io_count) - return; + if (!pending) + break; + + ioc->pending_io_count = 1; - /* wait for pending commands to complete */ - wait_event_timeout(ioc->reset_wq, ioc->pending_io_count == 0, 10 * HZ); + /* wait for pending commands to complete */ + wait_event_timeout(ioc->reset_wq, ioc->pending_io_count == 0, HZ); + } while (++loops <= 10); } /** diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h index caff8d10cca4..cadb392126e0 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.h +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h @@ -1045,6 +1045,9 @@ u16 mpt2sas_base_get_smid_hpr(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx); u16 mpt2sas_base_get_smid_scsiio(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx, struct scsi_cmnd *scmd); + +struct scsiio_tracker *mpt2sas_get_st_from_smid(struct MPT2SAS_ADAPTER *ioc, + u16 smid); u16 mpt2sas_base_get_smid(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx); void mpt2sas_base_free_smid(struct MPT2SAS_ADAPTER *ioc, u16 smid); void mpt2sas_base_put_smid_scsi_io(struct MPT2SAS_ADAPTER *ioc, u16 smid, diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c index 4e509604b571..409480f8381f 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c +++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c @@ -529,6 +529,94 @@ _ctl_poll(struct file *filep, poll_table *wait) return 0; } +static bool +_scmd_match(struct scsi_cmnd *scmd, u16 handle, u32 lun) +{ + struct MPT2SAS_DEVICE *priv_data; + + if (scmd == NULL || scmd->device == NULL || + scmd->device->hostdata == NULL) + return false; + if (lun != scmd->device->lun) + return false; + priv_data = scmd->device->hostdata; + if (priv_data->sas_target == NULL) + return false; + if (priv_data->sas_target->handle != handle) + return false; + + return true; +} + +struct smid_match_data { + u16 handle; + u16 smid; + u32 lun; +}; + +static bool +_smid_fn(struct scsi_cmnd *scmd, void *data) +{ + struct smid_match_data *smd = data; + struct scsiio_tracker *st; + + if (!_scmd_match(scmd, smd->handle, smd->lun)) + return false; + + st = scsi_mq_scmd_to_pdu(scmd); + smd->smid = st->smid; + return true; +} + +static u16 +_ctl_find_smid_mq(struct MPT2SAS_ADAPTER *ioc, u16 handle, u32 lun) +{ + struct scsi_device *sdev; + struct smid_match_data smd; + + smd.smid = 0; + shost_for_each_device(sdev, ioc->shost) { + scsi_mq_scmd_busy_iter(sdev, _smid_fn, &smd); + if (smd.smid) { + scsi_device_put(sdev); + break; + } + } + + return smd.smid; +} + +static u16 +_ctl_find_smid_legacy(struct MPT2SAS_ADAPTER *ioc, u16 handle, u32 lun) +{ + struct scsi_cmnd *scmd; + unsigned long flags; + u16 smid = 0; + int i; + + spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); + for (i = ioc->scsiio_depth; i; i--) { + scmd = ioc->scsi_lookup[i - 1].scmd; + if (!_scmd_match(scmd, handle, lun)) + continue; + + smid = ioc->scsi_lookup[i - 1].smid; + break; + } + spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); + + return smid; +} + +static u16 +_ctl_find_smid(struct MPT2SAS_ADAPTER *ioc, u16 handle, u32 lun) +{ + if (shost_use_blk_mq(ioc->shost)) + return _ctl_find_smid_mq(ioc, handle, lun); + else + return _ctl_find_smid_legacy(ioc, handle, lun); +} + /** * _ctl_set_task_mid - assign an active smid to tm request * @ioc: per adapter object @@ -542,12 +630,7 @@ static int _ctl_set_task_mid(struct MPT2SAS_ADAPTER *ioc, struct mpt2_ioctl_command *karg, Mpi2SCSITaskManagementRequest_t *tm_request) { - u8 found = 0; - u16 i; - u16 handle; - struct scsi_cmnd *scmd; - struct MPT2SAS_DEVICE *priv_data; - unsigned long flags; + u16 smid, handle; Mpi2SCSITaskManagementReply_t *tm_reply; u32 sz; u32 lun; @@ -561,27 +644,11 @@ _ctl_set_task_mid(struct MPT2SAS_ADAPTER *ioc, struct mpt2_ioctl_command *karg, return 0; lun = scsilun_to_int((struct scsi_lun *)tm_request->LUN); - handle = le16_to_cpu(tm_request->DevHandle); - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - for (i = ioc->scsiio_depth; i && !found; i--) { - scmd = ioc->scsi_lookup[i - 1].scmd; - if (scmd == NULL || scmd->device == NULL || - scmd->device->hostdata == NULL) - continue; - if (lun != scmd->device->lun) - continue; - priv_data = scmd->device->hostdata; - if (priv_data->sas_target == NULL) - continue; - if (priv_data->sas_target->handle != handle) - continue; - tm_request->TaskMID = cpu_to_le16(ioc->scsi_lookup[i - 1].smid); - found = 1; - } - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - if (!found) { + smid = _ctl_find_smid(ioc, handle, lun); + + if (!smid) { dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " "handle(0x%04x), lun(%d), no active mid!!\n", ioc->name, desc, le16_to_cpu(tm_request->DevHandle), lun)); @@ -600,6 +667,8 @@ _ctl_set_task_mid(struct MPT2SAS_ADAPTER *ioc, struct mpt2_ioctl_command *karg, return 1; } + tm_request->TaskMID = cpu_to_le16(smid); + dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " "handle(0x%04x), lun(%d), task_mid(%d)\n", ioc->name, desc, le16_to_cpu(tm_request->DevHandle), lun, diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 3f26147bbc64..287f2b30f38e 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -884,7 +884,10 @@ _scsih_is_end_device(u32 device_info) static struct scsi_cmnd * _scsih_scsi_lookup_get(struct MPT2SAS_ADAPTER *ioc, u16 smid) { - return ioc->scsi_lookup[smid - 1].scmd; + if (shost_use_blk_mq(ioc->shost)) + return scsi_mq_find_tag(ioc->shost, smid - 1); + else + return ioc->scsi_lookup[smid - 1].scmd; } /** @@ -901,6 +904,8 @@ _scsih_scsi_lookup_get_clear(struct MPT2SAS_ADAPTER *ioc, u16 smid) unsigned long flags; struct scsi_cmnd *scmd; + BUG_ON(shost_use_blk_mq(ioc->shost)); + spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); scmd = ioc->scsi_lookup[smid - 1].scmd; ioc->scsi_lookup[smid - 1].scmd = NULL; @@ -927,6 +932,13 @@ _scsih_scsi_lookup_find_by_scmd(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd unsigned long flags; int i; + if (shost_use_blk_mq(ioc->shost)) { + struct scsiio_tracker *st; + + st = scsi_mq_scmd_to_pdu(scmd); + return st->smid; + } + spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); smid = 0; for (i = 0; i < ioc->scsiio_depth; i++) { @@ -961,9 +973,14 @@ _scsih_scsi_lookup_find_by_target(struct MPT2SAS_ADAPTER *ioc, int id, spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); found = 0; for (i = 0 ; i < ioc->scsiio_depth; i++) { - if (ioc->scsi_lookup[i].scmd && - (ioc->scsi_lookup[i].scmd->device->id == id && - ioc->scsi_lookup[i].scmd->device->channel == channel)) { + struct scsiio_tracker *st; + + st = mpt2sas_get_st_from_smid(ioc, i + 1); + if (!st) + continue; + if (st->scmd && + (st->scmd->device->id == id && + st->scmd->device->channel == channel)) { found = 1; goto out; } @@ -995,10 +1012,15 @@ _scsih_scsi_lookup_find_by_lun(struct MPT2SAS_ADAPTER *ioc, int id, spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); found = 0; for (i = 0 ; i < ioc->scsiio_depth; i++) { - if (ioc->scsi_lookup[i].scmd && - (ioc->scsi_lookup[i].scmd->device->id == id && - ioc->scsi_lookup[i].scmd->device->channel == channel && - ioc->scsi_lookup[i].scmd->device->lun == lun)) { + struct scsiio_tracker *st; + + st = mpt2sas_get_st_from_smid(ioc, i + 1); + if (!st) + continue; + if (st->scmd && + (st->scmd->device->id == id && + st->scmd->device->channel == channel && + st->scmd->device->lun == lun)) { found = 1; goto out; } @@ -1019,6 +1041,7 @@ static struct chain_tracker * _scsih_get_chain_buffer_tracker(struct MPT2SAS_ADAPTER *ioc, u16 smid) { struct chain_tracker *chain_req; + struct scsiio_tracker *st; unsigned long flags; spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); @@ -1031,8 +1054,8 @@ _scsih_get_chain_buffer_tracker(struct MPT2SAS_ADAPTER *ioc, u16 smid) chain_req = list_entry(ioc->free_chain_list.next, struct chain_tracker, tracker_list); list_del_init(&chain_req->tracker_list); - list_add_tail(&chain_req->tracker_list, - &ioc->scsi_lookup[smid - 1].chain_list); + st = mpt2sas_get_st_from_smid(ioc, smid); + list_add_tail(&chain_req->tracker_list, &st->chain_list); spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); return chain_req; } @@ -2387,7 +2410,7 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel, } if (type == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK) - scsi_lookup = &ioc->scsi_lookup[smid_task - 1]; + scsi_lookup = mpt2sas_get_st_from_smid(ioc, smid_task); dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "sending tm: handle(0x%04x)," " task_type(0x%02x), smid(%d)\n", ioc->name, handle, type, @@ -3698,7 +3721,13 @@ _scsih_flush_running_cmds(struct MPT2SAS_ADAPTER *ioc) u16 count = 0; for (smid = 1; smid <= ioc->scsiio_depth; smid++) { - scmd = _scsih_scsi_lookup_get_clear(ioc, smid); + if (shost_use_blk_mq(ioc->shost)) { + scmd = _scsih_scsi_lookup_get(ioc, smid); + if (!scsi_mq_scmd_started(scmd)) + scmd = NULL; + } else + scmd = _scsih_scsi_lookup_get_clear(ioc, smid); + if (!scmd) continue; count++; @@ -3809,7 +3838,7 @@ _scsih_eedp_error_handling(struct scsi_cmnd *scmd, u16 ioc_status) static inline u8 _scsih_scsi_direct_io_get(struct MPT2SAS_ADAPTER *ioc, u16 smid) { - return ioc->scsi_lookup[smid - 1].direct_io; + return mpt2sas_get_st_from_smid(ioc, smid)->direct_io; } /** @@ -3823,7 +3852,7 @@ _scsih_scsi_direct_io_get(struct MPT2SAS_ADAPTER *ioc, u16 smid) static inline void _scsih_scsi_direct_io_set(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 direct_io) { - ioc->scsi_lookup[smid - 1].direct_io = direct_io; + mpt2sas_get_st_from_smid(ioc, smid)->direct_io = direct_io; } @@ -4443,7 +4472,11 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) unsigned long flags; mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); - scmd = _scsih_scsi_lookup_get_clear(ioc, smid); + if (shost_use_blk_mq(ioc->shost)) + scmd = scsi_mq_find_tag(ioc->shost, smid - 1); + else + scmd = _scsih_scsi_lookup_get_clear(ioc, smid); + if (scmd == NULL) return 1; @@ -4468,10 +4501,12 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) if (_scsih_scsi_direct_io_get(ioc, smid) && ((ioc_status & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SCSI_TASK_TERMINATED)) { - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - ioc->scsi_lookup[smid - 1].scmd = scmd; + if (ioc->scsi_lookup) { + spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); + ioc->scsi_lookup[smid - 1].scmd = scmd; + spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); + } _scsih_scsi_direct_io_set(ioc, smid, 0); - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); memcpy(mpi_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len); mpi_request->DevHandle = cpu_to_le16(sas_device_priv_data->sas_target->handle); @@ -7623,6 +7658,22 @@ mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, return; } +static int +_scsih_init_command(struct Scsi_Host *shost, struct scsi_cmnd *cmd, + unsigned int request_idx) +{ + struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); + struct scsiio_tracker *st; + + st = (void *) cmd + sizeof(*cmd); + INIT_LIST_HEAD(&st->chain_list); + st->scmd = cmd; + st->cb_idx = ioc->scsi_io_cb_idx; + st->smid = request_idx + 1; + st->direct_io = 0; + return 0; +} + /* shost template */ static struct scsi_host_template scsih_driver_template = { .module = THIS_MODULE, @@ -7651,6 +7702,8 @@ static struct scsi_host_template scsih_driver_template = { .shost_attrs = mpt2sas_host_attrs, .sdev_attrs = mpt2sas_dev_attrs, .track_queue_depth = 1, + .cmd_size = sizeof(struct scsiio_tracker), + .init_command = _scsih_init_command, }; /** -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html