Commit 67ff377b authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull SCSI fixes from James Bottomley:
 "Four driver fixes and one core fix.

  The core fix closes a race window where we could kick off a second
  asynchronous scan because the test and set of the variable preventing
  it isn't atomic"

* tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi:
  scsi: hisi_sas: Stop using queue #0 always for v2 hw
  scsi: ibmvscsi: Fix potential race after loss of transport
  scsi: mptfusion: Fix null pointer dereferences in mptscsih_remove()
  scsi: qla2xxx: Return EBUSY on fcport deletion
  scsi: core: Don't start concurrent async scan on same host
parents 5fc6b075 fab09aae
Loading
Loading
Loading
Loading
+8 −5
Original line number Diff line number Diff line
@@ -1176,8 +1176,10 @@ mptscsih_remove(struct pci_dev *pdev)
	MPT_SCSI_HOST		*hd;
	int sz1;

	if((hd = shost_priv(host)) == NULL)
		return;
	if (host == NULL)
		hd = NULL;
	else
		hd = shost_priv(host);

	mptscsih_shutdown(pdev);

@@ -1193,14 +1195,15 @@ mptscsih_remove(struct pci_dev *pdev)
	    "Free'd ScsiLookup (%d) memory\n",
	    ioc->name, sz1));

	if (hd)
		kfree(hd->info_kbuf);

	/* NULL the Scsi_Host pointer
	 */
	ioc->sh = NULL;

	if (host)
		scsi_host_put(host);

	mpt_detach(pdev);

}
+1 −1
Original line number Diff line number Diff line
@@ -445,7 +445,7 @@ static int hisi_sas_task_prep(struct sas_task *task,
		}
	}

	if (scmd) {
	if (scmd && hisi_hba->shost->nr_hw_queues) {
		unsigned int dq_index;
		u32 blk_tag;

+26 −10
Original line number Diff line number Diff line
@@ -806,6 +806,22 @@ static void purge_requests(struct ibmvscsi_host_data *hostdata, int error_code)
	spin_unlock_irqrestore(hostdata->host->host_lock, flags);
}

/**
 * ibmvscsi_set_request_limit - Set the adapter request_limit in response to
 * an adapter failure, reset, or SRP Login. Done under host lock to prevent
 * race with SCSI command submission.
 * @hostdata:	adapter to adjust
 * @limit:	new request limit
 */
static void ibmvscsi_set_request_limit(struct ibmvscsi_host_data *hostdata, int limit)
{
	unsigned long flags;

	spin_lock_irqsave(hostdata->host->host_lock, flags);
	atomic_set(&hostdata->request_limit, limit);
	spin_unlock_irqrestore(hostdata->host->host_lock, flags);
}

/**
 * ibmvscsi_reset_host - Reset the connection to the server
 * @hostdata:	struct ibmvscsi_host_data to reset
@@ -813,7 +829,7 @@ static void purge_requests(struct ibmvscsi_host_data *hostdata, int error_code)
static void ibmvscsi_reset_host(struct ibmvscsi_host_data *hostdata)
{
	scsi_block_requests(hostdata->host);
	atomic_set(&hostdata->request_limit, 0);
	ibmvscsi_set_request_limit(hostdata, 0);

	purge_requests(hostdata, DID_ERROR);
	hostdata->action = IBMVSCSI_HOST_ACTION_RESET;
@@ -1146,13 +1162,13 @@ static void login_rsp(struct srp_event_struct *evt_struct)
		dev_info(hostdata->dev, "SRP_LOGIN_REJ reason %u\n",
			 evt_struct->xfer_iu->srp.login_rej.reason);
		/* Login failed.  */
		atomic_set(&hostdata->request_limit, -1);
		ibmvscsi_set_request_limit(hostdata, -1);
		return;
	default:
		dev_err(hostdata->dev, "Invalid login response typecode 0x%02x!\n",
			evt_struct->xfer_iu->srp.login_rsp.opcode);
		/* Login failed.  */
		atomic_set(&hostdata->request_limit, -1);
		ibmvscsi_set_request_limit(hostdata, -1);
		return;
	}

@@ -1163,7 +1179,7 @@ static void login_rsp(struct srp_event_struct *evt_struct)
	 * This value is set rather than added to request_limit because
	 * request_limit could have been set to -1 by this client.
	 */
	atomic_set(&hostdata->request_limit,
	ibmvscsi_set_request_limit(hostdata,
		   be32_to_cpu(evt_struct->xfer_iu->srp.login_rsp.req_lim_delta));

	/* If we had any pending I/Os, kick them */
@@ -1195,13 +1211,13 @@ static int send_srp_login(struct ibmvscsi_host_data *hostdata)
	login->req_buf_fmt = cpu_to_be16(SRP_BUF_FORMAT_DIRECT |
					 SRP_BUF_FORMAT_INDIRECT);

	spin_lock_irqsave(hostdata->host->host_lock, flags);
	/* Start out with a request limit of 0, since this is negotiated in
	 * the login request we are just sending and login requests always
	 * get sent by the driver regardless of request_limit.
	 */
	atomic_set(&hostdata->request_limit, 0);
	ibmvscsi_set_request_limit(hostdata, 0);

	spin_lock_irqsave(hostdata->host->host_lock, flags);
	rc = ibmvscsi_send_srp_event(evt_struct, hostdata, login_timeout * 2);
	spin_unlock_irqrestore(hostdata->host->host_lock, flags);
	dev_info(hostdata->dev, "sent SRP login\n");
@@ -1781,7 +1797,7 @@ static void ibmvscsi_handle_crq(struct viosrp_crq *crq,
		return;
	case VIOSRP_CRQ_XPORT_EVENT:	/* Hypervisor telling us the connection is closed */
		scsi_block_requests(hostdata->host);
		atomic_set(&hostdata->request_limit, 0);
		ibmvscsi_set_request_limit(hostdata, 0);
		if (crq->format == 0x06) {
			/* We need to re-setup the interpartition connection */
			dev_info(hostdata->dev, "Re-enabling adapter!\n");
@@ -2137,12 +2153,12 @@ static void ibmvscsi_do_work(struct ibmvscsi_host_data *hostdata)
	}

	hostdata->action = IBMVSCSI_HOST_ACTION_NONE;
	spin_unlock_irqrestore(hostdata->host->host_lock, flags);

	if (rc) {
		atomic_set(&hostdata->request_limit, -1);
		ibmvscsi_set_request_limit(hostdata, -1);
		dev_err(hostdata->dev, "error after %s\n", action);
	}
	spin_unlock_irqrestore(hostdata->host->host_lock, flags);

	scsi_unblock_requests(hostdata->host);
}
@@ -2226,7 +2242,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
	init_waitqueue_head(&hostdata->work_wait_q);
	hostdata->host = host;
	hostdata->dev = dev;
	atomic_set(&hostdata->request_limit, -1);
	ibmvscsi_set_request_limit(hostdata, -1);
	hostdata->host->max_sectors = IBMVSCSI_MAX_SECTORS_DEFAULT;

	if (map_persist_bufs(hostdata)) {
+4 −2
Original line number Diff line number Diff line
@@ -554,10 +554,12 @@ static int qla_nvme_post_cmd(struct nvme_fc_local_port *lport,

	fcport = qla_rport->fcport;

	if (!qpair || !fcport || (qpair && !qpair->fw_started) ||
	    (fcport && fcport->deleted))
	if (!qpair || !fcport)
		return -ENODEV;

	if (!qpair->fw_started || fcport->deleted)
		return -EBUSY;

	vha = fcport->vha;

	if (!(fcport->nvme_flag & NVME_FLAG_REGISTERED))
+4 −3
Original line number Diff line number Diff line
@@ -1714,15 +1714,16 @@ static void scsi_sysfs_add_devices(struct Scsi_Host *shost)
 */
static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost)
{
	struct async_scan_data *data;
	struct async_scan_data *data = NULL;
	unsigned long flags;

	if (strncmp(scsi_scan_type, "sync", 4) == 0)
		return NULL;

	mutex_lock(&shost->scan_mutex);
	if (shost->async_scan) {
		shost_printk(KERN_DEBUG, shost, "%s called twice\n", __func__);
		return NULL;
		goto err;
	}

	data = kmalloc(sizeof(*data), GFP_KERNEL);
@@ -1733,7 +1734,6 @@ static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost)
		goto err;
	init_completion(&data->prev_finished);

	mutex_lock(&shost->scan_mutex);
	spin_lock_irqsave(shost->host_lock, flags);
	shost->async_scan = 1;
	spin_unlock_irqrestore(shost->host_lock, flags);
@@ -1748,6 +1748,7 @@ static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost)
	return data;

 err:
	mutex_unlock(&shost->scan_mutex);
	kfree(data);
	return NULL;
}