diff --git a/scripts/generate-kernel-with-srp-patches b/scripts/generate-kernel-with-srp-patches index 2f7a203a9..627bb8a81 100755 --- a/scripts/generate-kernel-with-srp-patches +++ b/scripts/generate-kernel-with-srp-patches @@ -13,6 +13,710 @@ usage() { echo "$0 " } +apply_locking_per_lun_patch() { +patch -p1 <done); + } + ++static bool srp_port_change_state(struct srp_target_port *target, ++ enum srp_target_state old, ++ enum srp_target_state new) ++{ ++ unsigned long flags; ++ bool ret; ++ ++ spin_lock_irqsave(&target->lock, flags); ++ if (target->state == old) { ++ target->state = new; ++ ret = true; ++ } else ++ ret = false; ++ spin_unlock_irqrestore(&target->lock, flags); ++ return ret; ++} ++ + static void srp_remove_work(struct work_struct *work) + { + struct srp_target_port *target = + container_of(work, struct srp_target_port, work); + +- spin_lock_irq(target->scsi_host->host_lock); +- if (target->state != SRP_TARGET_DEAD) { +- spin_unlock_irq(target->scsi_host->host_lock); ++ if (!srp_port_change_state(target, SRP_TARGET_DEAD, SRP_TARGET_REMOVED)) + return; +- } +- target->state = SRP_TARGET_REMOVED; +- spin_unlock_irq(target->scsi_host->host_lock); + + spin_lock(&target->srp_host->target_lock); + list_del(&target->list); +@@ -541,8 +553,13 @@ static void srp_unmap_data(struct scsi_cmnd *scmnd, + + static void srp_remove_req(struct srp_target_port *target, struct srp_request *req) + { ++ unsigned long flags; ++ + srp_unmap_data(req->scmnd, target, req); +- list_move_tail(&req->list, &target->free_reqs); ++ req->scmnd = NULL; ++ spin_lock_irqsave(&target->lock, flags); ++ list_add_tail(&req->list, &target->free_reqs); ++ spin_unlock_irqrestore(&target->lock, flags); + } + + static void srp_reset_req(struct srp_target_port *target, struct srp_request *req) +@@ -555,17 +572,14 @@ static void srp_reset_req(struct srp_target_port *target, struct srp_request *re + static int srp_reconnect_target(struct srp_target_port *target) + { + struct ib_qp_attr qp_attr; +- struct srp_request *req, *tmp; + struct ib_wc wc; + int ret; ++ int i; + +- spin_lock_irq(target->scsi_host->host_lock); +- if (target->state != SRP_TARGET_LIVE) { +- spin_unlock_irq(target->scsi_host->host_lock); ++ if (!srp_port_change_state(target, SRP_TARGET_LIVE, ++ SRP_TARGET_CONNECTING)) { + return -EAGAIN; + } +- target->state = SRP_TARGET_CONNECTING; +- spin_unlock_irq(target->scsi_host->host_lock); + + srp_disconnect_target(target); + /* +@@ -590,27 +604,20 @@ static int srp_reconnect_target(struct srp_target_port *target) + while (ib_poll_cq(target->send_cq, 1, &wc) > 0) + ; /* nothing */ + +- spin_lock_irq(target->scsi_host->host_lock); +- list_for_each_entry_safe(req, tmp, &target->req_queue, list) +- srp_reset_req(target, req); +- spin_unlock_irq(target->scsi_host->host_lock); +- +- target->rx_head = 0; +- target->tx_head = 0; +- target->tx_tail = 0; ++ for (i = 0; i < ARRAY_SIZE(target->req_ring); ++i) ++ if (target->req_ring[i].scmnd) ++ srp_reset_req(target, &target->req_ring[i]); + + target->qp_in_error = 0; + ret = srp_connect_target(target); + if (ret) + goto err; + +- spin_lock_irq(target->scsi_host->host_lock); +- if (target->state == SRP_TARGET_CONNECTING) { ++ if (srp_port_change_state(target, SRP_TARGET_CONNECTING, ++ SRP_TARGET_LIVE)) + ret = 0; +- target->state = SRP_TARGET_LIVE; +- } else ++ else + ret = -EAGAIN; +- spin_unlock_irq(target->scsi_host->host_lock); + + return ret; + +@@ -624,13 +631,11 @@ err: + * be in the context of the SCSI error handler now, which + * would deadlock if we call scsi_remove_host(). + */ +- spin_lock_irq(target->scsi_host->host_lock); +- if (target->state == SRP_TARGET_CONNECTING) { +- target->state = SRP_TARGET_DEAD; ++ if (srp_port_change_state(target, SRP_TARGET_CONNECTING, ++ SRP_TARGET_DEAD)) { + INIT_WORK(&target->work, srp_remove_work); + schedule_work(&target->work); + } +- spin_unlock_irq(target->scsi_host->host_lock); + + return ret; + } +@@ -811,20 +816,12 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target, + return len; + } + +-static int srp_post_recv(struct srp_target_port *target) ++static int srp_post_recv(struct srp_target_port *target, struct srp_iu *iu) + { +- unsigned long flags; +- struct srp_iu *iu; + struct ib_sge list; + struct ib_recv_wr wr, *bad_wr; +- unsigned int next; +- int ret; + +- spin_lock_irqsave(target->scsi_host->host_lock, flags); +- +- next = target->rx_head & SRP_RQ_MASK; +- wr.wr_id = next; +- iu = target->rx_ring[next]; ++ wr.wr_id = iu->index; + + list.addr = iu->dma; + list.length = iu->size; +@@ -834,13 +831,7 @@ static int srp_post_recv(struct srp_target_port *target) + wr.sg_list = &list; + wr.num_sge = 1; + +- ret = ib_post_recv(target->qp, &wr, &bad_wr); +- if (!ret) +- ++target->rx_head; +- +- spin_unlock_irqrestore(target->scsi_host->host_lock, flags); +- +- return ret; ++ return ib_post_recv(target->qp, &wr, &bad_wr); + } + + static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp) +@@ -852,9 +843,9 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp) + + delta = (s32) be32_to_cpu(rsp->req_lim_delta); + +- spin_lock_irqsave(target->scsi_host->host_lock, flags); +- ++ spin_lock_irqsave(&target->lock, flags); + target->req_lim += delta; ++ spin_unlock_irqrestore(&target->lock, flags); + + req = &target->req_ring[rsp->tag & ~SRP_TAG_TSK_MGMT]; + +@@ -892,14 +883,12 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp) + } else + req->cmd_done = 1; + } +- +- spin_unlock_irqrestore(target->scsi_host->host_lock, flags); + } + + /* +- * Must be called with target->scsi_host->host_lock held to protect +- * req_lim and tx_head. Lock cannot be dropped between call here and +- * call to __srp_post_send(). ++ * It is the responsability of the caller to put back the returned information ++ * unit in the target->tx_free list and to increment target->req_lim if an ++ * error occurs before __srp_post_send() is called. + * + * Note: + * An upper limit for the number of allocated information units for each +@@ -914,24 +903,28 @@ static struct srp_iu *__srp_get_tx_iu(struct srp_target_port *target, + enum srp_tx_iu_type iu_type) + { + s32 rsv = (iu_type == SRP_IU_TSK_MGMT) ? 0 : SRP_TSK_MGMT_SQ_SIZE; ++ struct srp_iu *res = NULL; ++ unsigned long flags; + + srp_send_completion(target->send_cq, target); + +- if (target->tx_head - target->tx_tail >= SRP_SQ_SIZE) +- return NULL; ++ spin_lock_irqsave(&target->lock, flags); ++ ++ if (list_empty(&target->tx_free)) ++ goto out; + + if (iu_type != SRP_IU_RSP && target->req_lim <= rsv) { + ++target->zero_req_lim; +- return NULL; ++ goto out; + } + +- return target->tx_ring[target->tx_head & SRP_SQ_MASK]; ++ res = list_first_entry(&target->tx_free, struct srp_iu, list); ++ list_del(&res->list); ++out: ++ spin_unlock_irqrestore(&target->lock, flags); ++ return res; + } + +-/* +- * Must be called with target->scsi_host->host_lock held to protect +- * req_lim and tx_head. +- */ + static int __srp_post_send(struct srp_target_port *target, + struct srp_iu *iu, int len, + enum srp_send_iu_type iu_type) +@@ -945,7 +938,7 @@ static int __srp_post_send(struct srp_target_port *target, + list.lkey = target->srp_host->srp_dev->mr->lkey; + + wr.next = NULL; +- wr.wr_id = target->tx_head & SRP_SQ_MASK; ++ wr.wr_id = iu->index; + wr.sg_list = &list; + wr.num_sge = 1; + wr.opcode = IB_WR_SEND; +@@ -953,43 +946,45 @@ static int __srp_post_send(struct srp_target_port *target, + + ret = ib_post_send(target->qp, &wr, &bad_wr); + +- if (!ret) { +- ++target->tx_head; ++ if (ret) { ++ unsigned long flags; ++ ++ spin_lock_irqsave(&target->lock, flags); + if (iu_type == SRP_SEND_REQ) +- --target->req_lim; ++ target->req_lim++; ++ list_add(&iu->list, &target->tx_free); ++ spin_unlock_irqrestore(&target->lock, flags); + } + + return ret; + } + +-/* +- * Must be called with target->scsi_host->host_lock locked to protect +- * target->req_lim. +- */ +-static void __srp_handle_cred_req(struct srp_target_port *target, +- void *req_ptr, void *rsp_ptr) ++static void srp_handle_cred_req(struct srp_target_port *target, ++ void *req_ptr, void *rsp_ptr) + { ++ unsigned long flags; + struct srp_cred_req *req = req_ptr; + struct srp_cred_rsp *rsp = rsp_ptr; + ++ spin_lock_irqsave(&target->lock, flags); + target->req_lim += be32_to_cpu(req->req_lim_delta); ++ spin_unlock_irqrestore(&target->lock, flags); + + memset(rsp, 0, sizeof *rsp); + rsp->opcode = SRP_CRED_RSP; + rsp->tag = req->tag; + } + +-/* +- * Must be called with target->scsi_host->host_lock locked to protect +- * target->req_lim. +- */ +-static void __srp_handle_aer_req(struct srp_target_port *target, +- void *req_ptr, void *rsp_ptr) ++static void srp_handle_aer_req(struct srp_target_port *target, ++ void *req_ptr, void *rsp_ptr) + { ++ unsigned long flags; + struct srp_aer_req *req = req_ptr; + struct srp_aer_rsp *rsp = rsp_ptr; + ++ spin_lock_irqsave(&target->lock, flags); + target->req_lim += be32_to_cpu(req->req_lim_delta); ++ spin_unlock_irqrestore(&target->lock, flags); + + shost_printk(KERN_ERR, target->scsi_host, + PFX "ignoring AER for LUN %llu\n", be64_to_cpu(req->lun)); +@@ -1006,7 +1001,6 @@ static void srp_handle_req(struct srp_target_port *target, + { + struct ib_device *dev; + u8 *req_buf; +- unsigned long flags; + struct srp_iu *rsp_iu; + u8 *rsp_buf; + int res; +@@ -1014,11 +1008,9 @@ static void srp_handle_req(struct srp_target_port *target, + dev = target->srp_host->srp_dev->dev; + req_buf = req_iu->buf; + +- spin_lock_irqsave(target->scsi_host->host_lock, flags); +- + rsp_iu = __srp_get_tx_iu(target, SRP_IU_RSP); + if (!rsp_iu) +- goto out_unlock; ++ return; + + rsp_buf = rsp_iu->buf; + +@@ -1031,9 +1023,6 @@ static void srp_handle_req(struct srp_target_port *target, + if (res) + shost_printk(KERN_ERR, target->scsi_host, + PFX "Sending response failed -- res = %d\n", res); +- +-out_unlock: +- spin_unlock_irqrestore(target->scsi_host->host_lock, flags); + } + + static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc) +@@ -1070,11 +1059,11 @@ static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc) + break; + + case SRP_CRED_REQ: +- srp_handle_req(target, iu, __srp_handle_cred_req); ++ srp_handle_req(target, iu, srp_handle_cred_req); + break; + + case SRP_AER_REQ: +- srp_handle_req(target, iu, __srp_handle_aer_req); ++ srp_handle_req(target, iu, srp_handle_aer_req); + break; + + default: +@@ -1086,7 +1075,7 @@ static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc) + ib_dma_sync_single_for_device(dev, iu->dma, target->max_ti_iu_len, + DMA_FROM_DEVICE); + +- res = srp_post_recv(target); ++ res = srp_post_recv(target, iu); + if (res != 0) + shost_printk(KERN_ERR, target->scsi_host, + PFX "Recv failed with error code %d\n", res); +@@ -1095,38 +1084,53 @@ static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc) + static void srp_recv_completion(struct ib_cq *cq, void *target_ptr) + { + struct srp_target_port *target = target_ptr; +- struct ib_wc wc; ++ struct ib_wc wc[16]; ++ int i, n; + + ib_req_notify_cq(cq, IB_CQ_NEXT_COMP); +- while (ib_poll_cq(cq, 1, &wc) > 0) { +- if (wc.status) { +- shost_printk(KERN_ERR, target->scsi_host, +- PFX "failed receive status %d\n", +- wc.status); +- target->qp_in_error = 1; +- break; +- } ++ while ((n = ib_poll_cq(cq, ARRAY_SIZE(wc), wc)) > 0) { ++ for (i = 0; i < n; ++i) { ++ if (wc[i].status) { ++ shost_printk(KERN_ERR, target->scsi_host, ++ PFX "failed receive status %d\n", ++ wc[i].status); ++ target->qp_in_error = 1; ++ goto out; ++ } + +- srp_handle_recv(target, &wc); ++ srp_handle_recv(target, &wc[i]); ++ } + } ++out: ++ return; + } + + static void srp_send_completion(struct ib_cq *cq, void *target_ptr) + { + struct srp_target_port *target = target_ptr; +- struct ib_wc wc; ++ struct ib_wc wc[16]; ++ int i, n; ++ unsigned long flags; + +- while (ib_poll_cq(cq, 1, &wc) > 0) { +- if (wc.status) { +- shost_printk(KERN_ERR, target->scsi_host, +- PFX "failed send status %d\n", +- wc.status); +- target->qp_in_error = 1; +- break; +- } ++ while ((n = ib_poll_cq(cq, ARRAY_SIZE(wc), wc)) > 0) { ++ spin_lock_irqsave(&target->lock, flags); ++ for (i = 0; i < n; ++i) { ++ if (wc[i].status) { ++ shost_printk(KERN_ERR, target->scsi_host, ++ PFX "failed send status %d\n", ++ wc[i].status); ++ target->qp_in_error = 1; ++ spin_unlock_irqrestore(&target->lock, flags); ++ goto out; ++ } + +- ++target->tx_tail; ++ list_add_tail(&target->tx_ring[wc[i].wr_id]->list, ++ &target->tx_free); ++ } ++ spin_unlock_irqrestore(&target->lock, flags); + } ++out: ++ return; + } + + static int srp_queuecommand(struct scsi_cmnd *scmnd, +@@ -1138,6 +1142,7 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd, + struct srp_cmd *cmd; + struct ib_device *dev; + int len; ++ unsigned long flags; + + if (target->state == SRP_TARGET_CONNECTING) + goto err; +@@ -1157,7 +1162,10 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd, + ib_dma_sync_single_for_cpu(dev, iu->dma, srp_max_iu_len, + DMA_TO_DEVICE); + ++ spin_lock_irqsave(&target->lock, flags); + req = list_first_entry(&target->free_reqs, struct srp_request, list); ++ list_del(&req->list); ++ spin_unlock_irqrestore(&target->lock, flags); + + scmnd->scsi_done = done; + scmnd->result = 0; +@@ -1180,7 +1188,7 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd, + if (len < 0) { + shost_printk(KERN_ERR, target->scsi_host, + PFX "Failed to map data\n"); +- goto err; ++ goto err_putback; + } + + ib_dma_sync_single_for_device(dev, iu->dma, srp_max_iu_len, +@@ -1188,16 +1196,22 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd, + + if (__srp_post_send(target, iu, len, SRP_SEND_REQ)) { + shost_printk(KERN_ERR, target->scsi_host, PFX "Send failed\n"); ++ spin_lock_irqsave(&target->lock, flags); ++ list_del(&req->list); ++ spin_unlock_irqrestore(&target->lock, flags); + goto err_unmap; + } + +- list_move_tail(&req->list, &target->req_queue); +- + return 0; + + err_unmap: + srp_unmap_data(scmnd, target, req); + ++err_putback: ++ spin_lock_irqsave(&target->lock, flags); ++ list_add(&req->list, &target->free_reqs); ++ spin_unlock_irqrestore(&target->lock, flags); ++ + err: + return SCSI_MLQUEUE_HOST_BUSY; + } +@@ -1212,14 +1226,19 @@ static int srp_alloc_iu_bufs(struct srp_target_port *target) + GFP_KERNEL, DMA_FROM_DEVICE); + if (!target->rx_ring[i]) + goto err; ++ target->rx_ring[i]->index = i; + } + ++ INIT_LIST_HEAD(&target->tx_free); ++ + for (i = 0; i < SRP_SQ_SIZE; ++i) { + target->tx_ring[i] = srp_alloc_iu(target->srp_host, + srp_max_iu_len, + GFP_KERNEL, DMA_TO_DEVICE); + if (!target->tx_ring[i]) + goto err; ++ target->tx_ring[i]->index = i; ++ list_add_tail(&target->tx_ring[i]->list, &target->tx_free); + } + + return 0; +@@ -1381,7 +1400,8 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event) + break; + + for (i = 0; i < SRP_RQ_SIZE; i++) { +- target->status = srp_post_recv(target); ++ target->status = srp_post_recv(target, ++ target->rx_ring[i]); + if (target->status) + break; + } +@@ -1451,8 +1471,6 @@ static int srp_send_tsk_mgmt(struct srp_target_port *target, + struct srp_iu *iu; + struct srp_tsk_mgmt *tsk_mgmt; + +- spin_lock_irq(target->scsi_host->host_lock); +- + if (target->state == SRP_TARGET_DEAD || + target->state == SRP_TARGET_REMOVED) { + req->scmnd->result = DID_BAD_TARGET << 16; +@@ -1479,8 +1497,6 @@ static int srp_send_tsk_mgmt(struct srp_target_port *target, + + req->tsk_mgmt = iu; + +- spin_unlock_irq(target->scsi_host->host_lock); +- + if (!wait_for_completion_timeout(&req->done, + msecs_to_jiffies(SRP_ABORT_TIMEOUT_MS))) + return -1; +@@ -1488,7 +1504,6 @@ static int srp_send_tsk_mgmt(struct srp_target_port *target, + return 0; + + out: +- spin_unlock_irq(target->scsi_host->host_lock); + return -1; + } + +@@ -1519,8 +1534,6 @@ static int srp_abort(struct scsi_cmnd *scmnd) + if (srp_send_tsk_mgmt(target, req, SRP_TSK_ABORT_TASK)) + return FAILED; + +- spin_lock_irq(target->scsi_host->host_lock); +- + if (req->cmd_done) { + srp_remove_req(target, req); + scmnd->scsi_done(scmnd); +@@ -1530,15 +1543,14 @@ static int srp_abort(struct scsi_cmnd *scmnd) + } else + ret = FAILED; + +- spin_unlock_irq(target->scsi_host->host_lock); +- + return ret; + } + + static int srp_reset_device(struct scsi_cmnd *scmnd) + { + struct srp_target_port *target = host_to_target(scmnd->device->host); +- struct srp_request *req, *tmp; ++ struct srp_request *req; ++ int i; + + shost_printk(KERN_ERR, target->scsi_host, "SRP reset_device called\n"); + +@@ -1551,14 +1563,10 @@ static int srp_reset_device(struct scsi_cmnd *scmnd) + if (req->tsk_status) + return FAILED; + +- spin_lock_irq(target->scsi_host->host_lock); +- +- list_for_each_entry_safe(req, tmp, &target->req_queue, list) +- if (req->scmnd->device == scmnd->device) ++ for (i = 0; i < ARRAY_SIZE(target->req_ring); ++i) ++ if (req->scmnd && req->scmnd->device == scmnd->device) + srp_reset_req(target, req); + +- spin_unlock_irq(target->scsi_host->host_lock); +- + return SUCCESS; + } + +@@ -1981,6 +1989,7 @@ static ssize_t srp_create_target(struct device *dev, + target_host->transportt = ib_srp_transport_template; + target_host->max_lun = SRP_MAX_LUN; + target_host->max_cmd_len = sizeof ((struct srp_cmd *) (void *) 0L)->cdb; ++ target_host->unlocked_qcmds = true, + + target = host_to_target(target_host); + +@@ -1988,8 +1997,9 @@ static ssize_t srp_create_target(struct device *dev, + target->scsi_host = target_host; + target->srp_host = host; + ++ spin_lock_init(&target->lock); ++ + INIT_LIST_HEAD(&target->free_reqs); +- INIT_LIST_HEAD(&target->req_queue); + for (i = 0; i < SRP_CMD_SQ_SIZE; ++i) { + target->req_ring[i].index = i; + list_add_tail(&target->req_ring[i].list, &target->free_reqs); +@@ -2200,6 +2210,7 @@ static void srp_remove_one(struct ib_device *device) + struct srp_host *host, *tmp_host; + LIST_HEAD(target_list); + struct srp_target_port *target, *tmp_target; ++ unsigned long flags; + + srp_dev = ib_get_client_data(device, &srp_client); + +@@ -2217,9 +2228,9 @@ static void srp_remove_one(struct ib_device *device) + */ + spin_lock(&host->target_lock); + list_for_each_entry(target, &host->target_list, list) { +- spin_lock_irq(target->scsi_host->host_lock); ++ spin_lock_irqsave(&target->lock, flags); + target->state = SRP_TARGET_REMOVED; +- spin_unlock_irq(target->scsi_host->host_lock); ++ spin_unlock_irqrestore(&target->lock, flags); + } + spin_unlock(&host->target_lock); + +diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h +index 854ec81..f665cea 100644 +--- a/drivers/infiniband/ulp/srp/ib_srp.h ++++ b/drivers/infiniband/ulp/srp/ib_srp.h +@@ -148,19 +148,19 @@ struct srp_target_port { + struct ib_qp *qp; + + int max_ti_iu_len; ++ ++ spinlock_t lock; ++ + s32 req_lim; + + int zero_req_lim; + +- unsigned rx_head; + struct srp_iu *rx_ring[SRP_RQ_SIZE]; + +- unsigned tx_head; +- unsigned tx_tail; ++ struct list_head tx_free; + struct srp_iu *tx_ring[SRP_SQ_SIZE]; + + struct list_head free_reqs; +- struct list_head req_queue; + struct srp_request req_ring[SRP_CMD_SQ_SIZE]; + + struct work_struct work; +@@ -173,9 +173,11 @@ struct srp_target_port { + }; + + struct srp_iu { ++ struct list_head list; + u64 dma; + void *buf; + size_t size; ++ short index; + enum dma_data_direction direction; + }; + +diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c +index ad0ed21..3819d66 100644 +--- a/drivers/scsi/scsi.c ++++ b/drivers/scsi/scsi.c +@@ -749,11 +749,16 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) + if (unlikely(host->shost_state == SHOST_DEL)) { + cmd->result = (DID_NO_CONNECT << 16); + scsi_done(cmd); ++ spin_unlock_irqrestore(host->host_lock, flags); + } else { + trace_scsi_dispatch_cmd_start(cmd); ++ if (host->unlocked_qcmds) ++ spin_unlock_irqrestore(host->host_lock, flags); + rtn = host->hostt->queuecommand(cmd, scsi_done); ++ if (!host->unlocked_qcmds) ++ spin_unlock_irqrestore(host->host_lock, flags); + } +- spin_unlock_irqrestore(host->host_lock, flags); ++ + if (rtn) { + trace_scsi_dispatch_cmd_error(cmd, rtn); + if (rtn != SCSI_MLQUEUE_DEVICE_BUSY && +diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h +index b7bdecb..1814c51 100644 +--- a/include/scsi/scsi_host.h ++++ b/include/scsi/scsi_host.h +@@ -636,6 +636,9 @@ struct Scsi_Host { + /* Asynchronous scan in progress */ + unsigned async_scan:1; + ++ /* call queuecommand without Scsi_Host lock held */ ++ unsigned unlocked_qcmds:1; ++ + /* + * Optional work queue to be utilized by the transport + */ + +EOF +} + # Argument processing if [ $# != 1 ]; then @@ -68,12 +772,15 @@ fi # IB/srp: Reduce number of BUSY conditions # IB/srp: use multiple CPU cores more effectively for p in \ - 119771 \ - 119772 \ - 119773 \ - 116774 + 143381 \ + 143391 \ + 143401 \ + 143411 \ + 143421 do echo "Applying patch $p ..." url="https://patchwork.kernel.org/patch/$p/raw/" wget -O- -q "$url" | patch -p1 -s done + +apply_locking_per_lun_patch