SCSI fixes on 20211009

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.
 
 Signed-off-by: James E.J. Bottomley <jejb@linux.ibm.com>
 -----BEGIN PGP SIGNATURE-----
 
 iJwEABMIAEQWIQTnYEDbdso9F2cI+arnQslM7pishQUCYWIPiiYcamFtZXMuYm90
 dG9tbGV5QGhhbnNlbnBhcnRuZXJzaGlwLmNvbQAKCRDnQslM7pishUSEAP42mqta
 /gnTiF8f0uImcTyEuejT0ujbGNWnViMnNd2WawD/astuYIZjkGnrPFCGP4ABK6Mh
 uRg8HqcFXXgj2Rb7nzs=
 =ZwGg
 -----END PGP SIGNATURE-----

Merge tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi

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
This commit is contained in:
Linus Torvalds 2021-10-09 14:57:26 -07:00
commit 0950fcbf99
6 changed files with 41 additions and 43 deletions

View File

@ -1776,7 +1776,7 @@ int acornscsi_reconnect_finish(AS_Host *host)
host->scsi.disconnectable = 0; host->scsi.disconnectable = 0;
if (host->SCpnt->device->id == host->scsi.reconnected.target && if (host->SCpnt->device->id == host->scsi.reconnected.target &&
host->SCpnt->device->lun == host->scsi.reconnected.lun && 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)) #if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON))
DBG(host->SCpnt, printk("scsi%d.%c: reconnected", DBG(host->SCpnt, printk("scsi%d.%c: reconnected",
host->host->host_no, acornscsi_target(host))); host->host->host_no, acornscsi_target(host)));

View File

@ -32,7 +32,7 @@ efct_scsi_io_alloc(struct efct_node *node)
struct efct *efct; struct efct *efct;
struct efct_xport *xport; struct efct_xport *xport;
struct efct_io *io; struct efct_io *io;
unsigned long flags = 0; unsigned long flags;
efct = node->efct; efct = node->efct;
@ -44,7 +44,6 @@ efct_scsi_io_alloc(struct efct_node *node)
if (!io) { if (!io) {
efc_log_err(efct, "IO alloc Failed\n"); efc_log_err(efct, "IO alloc Failed\n");
atomic_add_return(1, &xport->io_alloc_failed_count); atomic_add_return(1, &xport->io_alloc_failed_count);
spin_unlock_irqrestore(&node->active_ios_lock, flags);
return NULL; return NULL;
} }

View File

@ -2281,11 +2281,6 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
return FAILED; return FAILED;
} }
conn = session->leadconn;
iscsi_get_conn(conn->cls_conn);
conn->eh_abort_cnt++;
age = session->age;
spin_lock(&session->back_lock); spin_lock(&session->back_lock);
task = (struct iscsi_task *)sc->SCp.ptr; task = (struct iscsi_task *)sc->SCp.ptr;
if (!task || !task->sc) { 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"); ISCSI_DBG_EH(session, "sc completed while abort in progress\n");
spin_unlock(&session->back_lock); 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_DBG_EH(session, "aborting [sc %p itt 0x%x]\n", sc, task->itt);
__iscsi_get_task(task); __iscsi_get_task(task);
spin_unlock(&session->back_lock); spin_unlock(&session->back_lock);

View File

@ -12292,12 +12292,12 @@ void
lpfc_ignore_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_ignore_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb) struct lpfc_iocbq *rspiocb)
{ {
struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1; struct lpfc_nodelist *ndlp = NULL;
IOCB_t *irsp = &rspiocb->iocb; IOCB_t *irsp = &rspiocb->iocb;
/* ELS cmd tag <ulpIoTag> completes */ /* ELS cmd tag <ulpIoTag> completes */
lpfc_printf_log(phba, KERN_INFO, LOG_ELS, 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", "x%x x%x x%x\n",
irsp->ulpIoTag, irsp->ulpStatus, irsp->ulpIoTag, irsp->ulpStatus,
irsp->un.ulpWord[4], irsp->ulpTimeout); 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 * Deref the ndlp after free_iocb. sli_release_iocb will access the ndlp
* if exchange is busy. * 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); lpfc_ct_free_iocb(phba, cmdiocb);
else } else {
ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
lpfc_els_free_iocb(phba, cmdiocb); lpfc_els_free_iocb(phba, cmdiocb);
}
lpfc_nlp_put(ndlp); lpfc_nlp_put(ndlp);
} }

View File

@ -6377,27 +6377,6 @@ static irqreturn_t ufshcd_check_errors(struct ufs_hba *hba, u32 intr_status)
return retval; 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 * ufshcd_tmc_handler - handle task management function completion
* @hba: per adapter instance * @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) static irqreturn_t ufshcd_tmc_handler(struct ufs_hba *hba)
{ {
unsigned long flags; unsigned long flags, pending, issued;
struct request_queue *q = hba->tmf_queue; irqreturn_t ret = IRQ_NONE;
struct ctm_info ci = { int tag;
.hba = hba,
}; pending = ufshcd_readl(hba, REG_UTP_TASK_REQ_DOOR_BELL);
spin_lock_irqsave(hba->host->host_lock, flags); spin_lock_irqsave(hba->host->host_lock, flags);
ci.pending = ufshcd_readl(hba, REG_UTP_TASK_REQ_DOOR_BELL); issued = hba->outstanding_tasks & ~pending;
blk_mq_tagset_busy_iter(q->tag_set, ufshcd_compl_tm, &ci); 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); 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); ufshcd_hold(hba, false);
spin_lock_irqsave(host->host_lock, flags); spin_lock_irqsave(host->host_lock, flags);
blk_mq_start_request(req);
task_tag = req->tag; task_tag = req->tag;
hba->tmf_rqs[req->tag] = req;
treq->upiu_req.req_header.dword_0 |= cpu_to_be32(task_tag); treq->upiu_req.req_header.dword_0 |= cpu_to_be32(task_tag);
memcpy(hba->utmrdl_base_addr + task_tag, treq, sizeof(*treq)); 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); spin_lock_irqsave(hba->host->host_lock, flags);
hba->tmf_rqs[req->tag] = NULL;
__clear_bit(task_tag, &hba->outstanding_tasks); __clear_bit(task_tag, &hba->outstanding_tasks);
spin_unlock_irqrestore(hba->host->host_lock, flags); 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); err = PTR_ERR(hba->tmf_queue);
goto free_tmf_tag_set; 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 */ /* Reset the attached device */
ufshcd_device_reset(hba); ufshcd_device_reset(hba);

View File

@ -828,6 +828,7 @@ struct ufs_hba {
struct blk_mq_tag_set tmf_tag_set; struct blk_mq_tag_set tmf_tag_set;
struct request_queue *tmf_queue; struct request_queue *tmf_queue;
struct request **tmf_rqs;
struct uic_command *active_uic_cmd; struct uic_command *active_uic_cmd;
struct mutex uic_cmd_mutex; struct mutex uic_cmd_mutex;