Commit 0950fcbf authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents 50eb0a06 258aad75
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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)));
+1 −2
Original line number Diff line number Diff line
@@ -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;
	}

+9 −6
Original line number Diff line number Diff line
@@ -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);
+7 −4
Original line number Diff line number Diff line
@@ -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);
}
+22 −30
Original line number Diff line number Diff line
@@ -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);
Loading