Commit 5e62ed3b authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull SCSI fixes from James Bottomley:
 "Three fixes, all in drivers.

  The fnic one is the most extensive because the little used user
  initiated device reset path never tagged the command and adding a tag
  is rather involved. The other two fixes are smaller and more obvious"

* tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi:
  scsi: zfcp: Fix a double put in zfcp_port_enqueue()
  scsi: fnic: Fix sg_reset success path
  scsi: target: core: Fix deadlock due to recursive locking
parents ce36c8b1 b481f644
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -518,12 +518,12 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn,
	if (port) {
		put_device(&port->dev);
		retval = -EEXIST;
		goto err_out;
		goto err_put;
	}

	port = kzalloc(sizeof(struct zfcp_port), GFP_KERNEL);
	if (!port)
		goto err_out;
		goto err_put;

	rwlock_init(&port->unit_list_lock);
	INIT_LIST_HEAD(&port->unit_list);
@@ -546,7 +546,7 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn,

	if (dev_set_name(&port->dev, "0x%016llx", (unsigned long long)wwpn)) {
		kfree(port);
		goto err_out;
		goto err_put;
	}
	retval = -EINVAL;

@@ -563,7 +563,8 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn,

	return port;

err_out:
err_put:
	zfcp_ccw_adapter_put(adapter);
err_out:
	return ERR_PTR(retval);
}
+3 −1
Original line number Diff line number Diff line
@@ -27,7 +27,7 @@

#define DRV_NAME		"fnic"
#define DRV_DESCRIPTION		"Cisco FCoE HBA Driver"
#define DRV_VERSION		"1.6.0.56"
#define DRV_VERSION		"1.6.0.57"
#define PFX			DRV_NAME ": "
#define DFX                     DRV_NAME "%d: "

@@ -237,6 +237,8 @@ struct fnic {
	unsigned int cq_count;

	struct mutex sgreset_mutex;
	spinlock_t sgreset_lock; /* lock for sgreset */
	struct scsi_cmnd *sgreset_sc;
	struct dentry *fnic_stats_debugfs_host;
	struct dentry *fnic_stats_debugfs_file;
	struct dentry *fnic_reset_debugfs_file;
+2 −0
Original line number Diff line number Diff line
@@ -52,6 +52,8 @@ struct fnic_io_req {
	unsigned long start_time; /* in jiffies */
	struct completion *abts_done; /* completion for abts */
	struct completion *dr_done; /* completion for device reset */
	unsigned int tag;
	struct scsi_cmnd *sc; /* midlayer's cmd pointer */
};

enum fnic_port_speeds {
+2 −0
Original line number Diff line number Diff line
@@ -754,6 +754,8 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
	for (i = 0; i < FNIC_IO_LOCKS; i++)
		spin_lock_init(&fnic->io_req_lock[i]);

	spin_lock_init(&fnic->sgreset_lock);

	err = -ENOMEM;
	fnic->io_req_pool = mempool_create_slab_pool(2, fnic_io_req_cache);
	if (!fnic->io_req_pool)
+47 −17
Original line number Diff line number Diff line
@@ -1047,9 +1047,9 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic,
{
	u8 type;
	u8 hdr_status;
	struct fcpio_tag tag;
	struct fcpio_tag ftag;
	u32 id;
	struct scsi_cmnd *sc;
	struct scsi_cmnd *sc = NULL;
	struct fnic_io_req *io_req;
	struct fnic_stats *fnic_stats = &fnic->fnic_stats;
	struct abort_stats *abts_stats = &fnic->fnic_stats.abts_stats;
@@ -1058,27 +1058,43 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic,
	unsigned long flags;
	spinlock_t *io_lock;
	unsigned long start_time;
	unsigned int tag;

	fcpio_header_dec(&desc->hdr, &type, &hdr_status, &tag);
	fcpio_tag_id_dec(&tag, &id);
	fcpio_header_dec(&desc->hdr, &type, &hdr_status, &ftag);
	fcpio_tag_id_dec(&ftag, &id);

	if ((id & FNIC_TAG_MASK) >= fnic->fnic_max_tag_id) {
	tag = id & FNIC_TAG_MASK;
	if (tag == fnic->fnic_max_tag_id) {
		if (!(id & FNIC_TAG_DEV_RST)) {
			shost_printk(KERN_ERR, fnic->lport->host,
		"Tag out of range tag %x hdr status = %s\n",
						"Tag out of range id 0x%x hdr status = %s\n",
						id, fnic_fcpio_status_to_str(hdr_status));
			return;
		}
	} else if (tag > fnic->fnic_max_tag_id) {
		shost_printk(KERN_ERR, fnic->lport->host,
					"Tag out of range tag 0x%x hdr status = %s\n",
					tag, fnic_fcpio_status_to_str(hdr_status));
		return;
	}

	if ((tag == fnic->fnic_max_tag_id) && (id & FNIC_TAG_DEV_RST)) {
		sc = fnic->sgreset_sc;
		io_lock = &fnic->sgreset_lock;
	} else {
		sc = scsi_host_find_tag(fnic->lport->host, id & FNIC_TAG_MASK);
		io_lock = fnic_io_lock_hash(fnic, sc);
	}

	WARN_ON_ONCE(!sc);
	if (!sc) {
		atomic64_inc(&fnic_stats->io_stats.sc_null);
		shost_printk(KERN_ERR, fnic->lport->host,
			  "itmf_cmpl sc is null - hdr status = %s tag = 0x%x\n",
			  fnic_fcpio_status_to_str(hdr_status), id);
			  fnic_fcpio_status_to_str(hdr_status), tag);
		return;
	}
	io_lock = fnic_io_lock_hash(fnic, sc);

	spin_lock_irqsave(io_lock, flags);
	io_req = fnic_priv(sc)->io_req;
	WARN_ON_ONCE(!io_req);
@@ -1089,7 +1105,7 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic,
		shost_printk(KERN_ERR, fnic->lport->host,
			  "itmf_cmpl io_req is null - "
			  "hdr status = %s tag = 0x%x sc 0x%p\n",
			  fnic_fcpio_status_to_str(hdr_status), id, sc);
			  fnic_fcpio_status_to_str(hdr_status), tag, sc);
		return;
	}
	start_time = io_req->start_time;
@@ -1938,6 +1954,10 @@ static inline int fnic_queue_dr_io_req(struct fnic *fnic,
	struct scsi_lun fc_lun;
	int ret = 0;
	unsigned long intr_flags;
	unsigned int tag = scsi_cmd_to_rq(sc)->tag;

	if (tag == SCSI_NO_TAG)
		tag = io_req->tag;

	spin_lock_irqsave(host->host_lock, intr_flags);
	if (unlikely(fnic_chk_state_flags_locked(fnic,
@@ -1964,7 +1984,8 @@ static inline int fnic_queue_dr_io_req(struct fnic *fnic,
	/* fill in the lun info */
	int_to_scsilun(sc->device->lun, &fc_lun);

	fnic_queue_wq_copy_desc_itmf(wq, scsi_cmd_to_rq(sc)->tag | FNIC_TAG_DEV_RST,
	tag |= FNIC_TAG_DEV_RST;
	fnic_queue_wq_copy_desc_itmf(wq, tag,
				     0, FCPIO_ITMF_LUN_RESET, SCSI_NO_TAG,
				     fc_lun.scsi_lun, io_req->port_id,
				     fnic->config.ra_tov, fnic->config.ed_tov);
@@ -2146,7 +2167,6 @@ static int fnic_clean_pending_aborts(struct fnic *fnic,
		.ret = SUCCESS,
	};

	if (new_sc)
	iter_data.lr_sc = lr_sc;

	scsi_host_busy_iter(fnic->lport->host,
@@ -2230,8 +2250,14 @@ int fnic_device_reset(struct scsi_cmnd *sc)
		mutex_lock(&fnic->sgreset_mutex);
		tag = fnic->fnic_max_tag_id;
		new_sc = 1;
	}
		fnic->sgreset_sc = sc;
		io_lock = &fnic->sgreset_lock;
		FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host,
			"fcid: 0x%x lun: 0x%llx flags: 0x%x tag: 0x%x Issuing sgreset\n",
			rport->port_id, sc->device->lun, fnic_priv(sc)->flags, tag);
	} else
		io_lock = fnic_io_lock_hash(fnic, sc);

	spin_lock_irqsave(io_lock, flags);
	io_req = fnic_priv(sc)->io_req;

@@ -2247,6 +2273,8 @@ int fnic_device_reset(struct scsi_cmnd *sc)
		}
		memset(io_req, 0, sizeof(*io_req));
		io_req->port_id = rport->port_id;
		io_req->tag = tag;
		io_req->sc = sc;
		fnic_priv(sc)->io_req = io_req;
	}
	io_req->dr_done = &tm_done;
@@ -2400,8 +2428,10 @@ int fnic_device_reset(struct scsi_cmnd *sc)
		  (u64)sc->cmnd[4] << 8 | sc->cmnd[5]),
		  fnic_flags_and_state(sc));

	if (new_sc)
	if (new_sc) {
		fnic->sgreset_sc = NULL;
		mutex_unlock(&fnic->sgreset_mutex);
	}

	FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
		      "Returning from device reset %s\n",
Loading