Merge tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 9 Oct 2021 21:57:26 +0000 (14:57 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 9 Oct 2021 21:57:26 +0000 (14:57 -0700)
Pull SCSI fixes from James Bottomley:
 "Five fixes, all in drivers.

  The big change is the UFS task management rework, with lpfc next and
  the rest being fairly minor and obvious fixes"

* tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi:
  scsi: iscsi: Fix iscsi_task use after free
  scsi: lpfc: Fix memory overwrite during FC-GS I/O abort handling
  scsi: elx: efct: Delete stray unlock statement
  scsi: ufs: core: Fix task management completion
  scsi: acornscsi: Remove scsi_cmd_to_tag() reference

drivers/scsi/arm/acornscsi.c
drivers/scsi/elx/efct/efct_scsi.c
drivers/scsi/libiscsi.c
drivers/scsi/lpfc/lpfc_sli.c
drivers/scsi/ufs/ufshcd.c
drivers/scsi/ufs/ufshcd.h

index b4cb5fb199986b767c7fc4dd869b84694e7deba5..0cc62c1b082544d1b644bc1f4a6c33c7c665f0c9 100644 (file)
@@ -1776,7 +1776,7 @@ int acornscsi_reconnect_finish(AS_Host *host)
        host->scsi.disconnectable = 0;
        if (host->SCpnt->device->id  == host->scsi.reconnected.target &&
            host->SCpnt->device->lun == host->scsi.reconnected.lun &&
-           scsi_cmd_to_tag(host->SCpnt) == host->scsi.reconnected.tag) {
+           scsi_cmd_to_rq(host->SCpnt)->tag == host->scsi.reconnected.tag) {
 #if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON))
            DBG(host->SCpnt, printk("scsi%d.%c: reconnected",
                    host->host->host_no, acornscsi_target(host)));
index 40fb3a724c76d019ce14dc58e6679beca080300c..cf2e41dd354cbc83940ed81382b6ec79e1a2dc44 100644 (file)
@@ -32,7 +32,7 @@ efct_scsi_io_alloc(struct efct_node *node)
        struct efct *efct;
        struct efct_xport *xport;
        struct efct_io *io;
-       unsigned long flags = 0;
+       unsigned long flags;
 
        efct = node->efct;
 
@@ -44,7 +44,6 @@ efct_scsi_io_alloc(struct efct_node *node)
        if (!io) {
                efc_log_err(efct, "IO alloc Failed\n");
                atomic_add_return(1, &xport->io_alloc_failed_count);
-               spin_unlock_irqrestore(&node->active_ios_lock, flags);
                return NULL;
        }
 
index 4683c183e9d411e07a083733c4dd1a7e7b4ed0f1..5bc91d34df634db65d06cf03ab2250aef2940038 100644 (file)
@@ -2281,11 +2281,6 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
                return FAILED;
        }
 
-       conn = session->leadconn;
-       iscsi_get_conn(conn->cls_conn);
-       conn->eh_abort_cnt++;
-       age = session->age;
-
        spin_lock(&session->back_lock);
        task = (struct iscsi_task *)sc->SCp.ptr;
        if (!task || !task->sc) {
@@ -2293,8 +2288,16 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
                ISCSI_DBG_EH(session, "sc completed while abort in progress\n");
 
                spin_unlock(&session->back_lock);
-               goto success;
+               spin_unlock_bh(&session->frwd_lock);
+               mutex_unlock(&session->eh_mutex);
+               return SUCCESS;
        }
+
+       conn = session->leadconn;
+       iscsi_get_conn(conn->cls_conn);
+       conn->eh_abort_cnt++;
+       age = session->age;
+
        ISCSI_DBG_EH(session, "aborting [sc %p itt 0x%x]\n", sc, task->itt);
        __iscsi_get_task(task);
        spin_unlock(&session->back_lock);
index 78ce38d7251c595d797502c5625eab42af2faedf..026a1196a54d5e109a478a7631e6285f5b9a5e0c 100644 (file)
@@ -12292,12 +12292,12 @@ void
 lpfc_ignore_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                     struct lpfc_iocbq *rspiocb)
 {
-       struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
+       struct lpfc_nodelist *ndlp = NULL;
        IOCB_t *irsp = &rspiocb->iocb;
 
        /* ELS cmd tag <ulpIoTag> completes */
        lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-                       "0139 Ignoring ELS cmd tag x%x completion Data: "
+                       "0139 Ignoring ELS cmd code x%x completion Data: "
                        "x%x x%x x%x\n",
                        irsp->ulpIoTag, irsp->ulpStatus,
                        irsp->un.ulpWord[4], irsp->ulpTimeout);
@@ -12305,10 +12305,13 @@ lpfc_ignore_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
         * Deref the ndlp after free_iocb. sli_release_iocb will access the ndlp
         * if exchange is busy.
         */
-       if (cmdiocb->iocb.ulpCommand == CMD_GEN_REQUEST64_CR)
+       if (cmdiocb->iocb.ulpCommand == CMD_GEN_REQUEST64_CR) {
+               ndlp = cmdiocb->context_un.ndlp;
                lpfc_ct_free_iocb(phba, cmdiocb);
-       else
+       } else {
+               ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
                lpfc_els_free_iocb(phba, cmdiocb);
+       }
 
        lpfc_nlp_put(ndlp);
 }
index 188de6f9105000dc69af6e48bc0a24624b5cc0ce..95be7ecdfe10b8c00d166535e2ec54bfe4c4f72e 100644 (file)
@@ -6377,27 +6377,6 @@ static irqreturn_t ufshcd_check_errors(struct ufs_hba *hba, u32 intr_status)
        return retval;
 }
 
-struct ctm_info {
-       struct ufs_hba  *hba;
-       unsigned long   pending;
-       unsigned int    ncpl;
-};
-
-static bool ufshcd_compl_tm(struct request *req, void *priv, bool reserved)
-{
-       struct ctm_info *const ci = priv;
-       struct completion *c;
-
-       WARN_ON_ONCE(reserved);
-       if (test_bit(req->tag, &ci->pending))
-               return true;
-       ci->ncpl++;
-       c = req->end_io_data;
-       if (c)
-               complete(c);
-       return true;
-}
-
 /**
  * ufshcd_tmc_handler - handle task management function completion
  * @hba: per adapter instance
@@ -6408,18 +6387,24 @@ static bool ufshcd_compl_tm(struct request *req, void *priv, bool reserved)
  */
 static irqreturn_t ufshcd_tmc_handler(struct ufs_hba *hba)
 {
-       unsigned long flags;
-       struct request_queue *q = hba->tmf_queue;
-       struct ctm_info ci = {
-               .hba     = hba,
-       };
+       unsigned long flags, pending, issued;
+       irqreturn_t ret = IRQ_NONE;
+       int tag;
+
+       pending = ufshcd_readl(hba, REG_UTP_TASK_REQ_DOOR_BELL);
 
        spin_lock_irqsave(hba->host->host_lock, flags);
-       ci.pending = ufshcd_readl(hba, REG_UTP_TASK_REQ_DOOR_BELL);
-       blk_mq_tagset_busy_iter(q->tag_set, ufshcd_compl_tm, &ci);
+       issued = hba->outstanding_tasks & ~pending;
+       for_each_set_bit(tag, &issued, hba->nutmrs) {
+               struct request *req = hba->tmf_rqs[tag];
+               struct completion *c = req->end_io_data;
+
+               complete(c);
+               ret = IRQ_HANDLED;
+       }
        spin_unlock_irqrestore(hba->host->host_lock, flags);
 
-       return ci.ncpl ? IRQ_HANDLED : IRQ_NONE;
+       return ret;
 }
 
 /**
@@ -6542,9 +6527,9 @@ static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba,
        ufshcd_hold(hba, false);
 
        spin_lock_irqsave(host->host_lock, flags);
-       blk_mq_start_request(req);
 
        task_tag = req->tag;
+       hba->tmf_rqs[req->tag] = req;
        treq->upiu_req.req_header.dword_0 |= cpu_to_be32(task_tag);
 
        memcpy(hba->utmrdl_base_addr + task_tag, treq, sizeof(*treq));
@@ -6585,6 +6570,7 @@ static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba,
        }
 
        spin_lock_irqsave(hba->host->host_lock, flags);
+       hba->tmf_rqs[req->tag] = NULL;
        __clear_bit(task_tag, &hba->outstanding_tasks);
        spin_unlock_irqrestore(hba->host->host_lock, flags);
 
@@ -9635,6 +9621,12 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
                err = PTR_ERR(hba->tmf_queue);
                goto free_tmf_tag_set;
        }
+       hba->tmf_rqs = devm_kcalloc(hba->dev, hba->nutmrs,
+                                   sizeof(*hba->tmf_rqs), GFP_KERNEL);
+       if (!hba->tmf_rqs) {
+               err = -ENOMEM;
+               goto free_tmf_queue;
+       }
 
        /* Reset the attached device */
        ufshcd_device_reset(hba);
index f0da5d3db1fa70e7af38ad40fab4ab914a4f2506..41f6e06f91856469113e2e14f5e4639c935114df 100644 (file)
@@ -828,6 +828,7 @@ struct ufs_hba {
 
        struct blk_mq_tag_set tmf_tag_set;
        struct request_queue *tmf_queue;
+       struct request **tmf_rqs;
 
        struct uic_command *active_uic_cmd;
        struct mutex uic_cmd_mutex;