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:
commit
0950fcbf99
|
@ -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)));
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue