Commit 514f0c40 authored by Karan Tilak Kumar's avatar Karan Tilak Kumar Committed by Martin K. Petersen

scsi: fnic: Fix sg_reset success path

sg_reset performs a target or LUN reset. Since the command is issued by the
user, it does not come into the driver with a tag or a queue id. Fix the
fnic driver to create an io_req and use a SCSI command tag.  Fix the ITMF
path to special case the sg_reset response.
Reviewed-by: default avatarSesidhar Baddela <sebaddel@cisco.com>
Reviewed-by: default avatarArulprabhu Ponnusamy <arulponn@cisco.com>
Tested-by: default avatarKaran Tilak Kumar <kartilak@cisco.com>
Signed-off-by: default avatarKaran Tilak Kumar <kartilak@cisco.com>
Link: https://lore.kernel.org/r/20230919182436.6895-1-kartilak@cisco.comSigned-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent a154f5f6
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
#define DRV_NAME "fnic" #define DRV_NAME "fnic"
#define DRV_DESCRIPTION "Cisco FCoE HBA Driver" #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 PFX DRV_NAME ": "
#define DFX DRV_NAME "%d: " #define DFX DRV_NAME "%d: "
...@@ -237,6 +237,8 @@ struct fnic { ...@@ -237,6 +237,8 @@ struct fnic {
unsigned int cq_count; unsigned int cq_count;
struct mutex sgreset_mutex; 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_host;
struct dentry *fnic_stats_debugfs_file; struct dentry *fnic_stats_debugfs_file;
struct dentry *fnic_reset_debugfs_file; struct dentry *fnic_reset_debugfs_file;
......
...@@ -52,6 +52,8 @@ struct fnic_io_req { ...@@ -52,6 +52,8 @@ struct fnic_io_req {
unsigned long start_time; /* in jiffies */ unsigned long start_time; /* in jiffies */
struct completion *abts_done; /* completion for abts */ struct completion *abts_done; /* completion for abts */
struct completion *dr_done; /* completion for device reset */ struct completion *dr_done; /* completion for device reset */
unsigned int tag;
struct scsi_cmnd *sc; /* midlayer's cmd pointer */
}; };
enum fnic_port_speeds { enum fnic_port_speeds {
......
...@@ -754,6 +754,8 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -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++) for (i = 0; i < FNIC_IO_LOCKS; i++)
spin_lock_init(&fnic->io_req_lock[i]); spin_lock_init(&fnic->io_req_lock[i]);
spin_lock_init(&fnic->sgreset_lock);
err = -ENOMEM; err = -ENOMEM;
fnic->io_req_pool = mempool_create_slab_pool(2, fnic_io_req_cache); fnic->io_req_pool = mempool_create_slab_pool(2, fnic_io_req_cache);
if (!fnic->io_req_pool) if (!fnic->io_req_pool)
......
...@@ -1047,9 +1047,9 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic, ...@@ -1047,9 +1047,9 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic,
{ {
u8 type; u8 type;
u8 hdr_status; u8 hdr_status;
struct fcpio_tag tag; struct fcpio_tag ftag;
u32 id; u32 id;
struct scsi_cmnd *sc; struct scsi_cmnd *sc = NULL;
struct fnic_io_req *io_req; struct fnic_io_req *io_req;
struct fnic_stats *fnic_stats = &fnic->fnic_stats; struct fnic_stats *fnic_stats = &fnic->fnic_stats;
struct abort_stats *abts_stats = &fnic->fnic_stats.abts_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, ...@@ -1058,27 +1058,43 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic,
unsigned long flags; unsigned long flags;
spinlock_t *io_lock; spinlock_t *io_lock;
unsigned long start_time; unsigned long start_time;
unsigned int tag;
fcpio_header_dec(&desc->hdr, &type, &hdr_status, &tag); fcpio_header_dec(&desc->hdr, &type, &hdr_status, &ftag);
fcpio_tag_id_dec(&tag, &id); 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 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, shost_printk(KERN_ERR, fnic->lport->host,
"Tag out of range tag %x hdr status = %s\n", "Tag out of range tag 0x%x hdr status = %s\n",
id, fnic_fcpio_status_to_str(hdr_status)); tag, fnic_fcpio_status_to_str(hdr_status));
return; return;
} }
sc = scsi_host_find_tag(fnic->lport->host, id & FNIC_TAG_MASK); 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); WARN_ON_ONCE(!sc);
if (!sc) { if (!sc) {
atomic64_inc(&fnic_stats->io_stats.sc_null); atomic64_inc(&fnic_stats->io_stats.sc_null);
shost_printk(KERN_ERR, fnic->lport->host, shost_printk(KERN_ERR, fnic->lport->host,
"itmf_cmpl sc is null - hdr status = %s tag = 0x%x\n", "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; return;
} }
io_lock = fnic_io_lock_hash(fnic, sc);
spin_lock_irqsave(io_lock, flags); spin_lock_irqsave(io_lock, flags);
io_req = fnic_priv(sc)->io_req; io_req = fnic_priv(sc)->io_req;
WARN_ON_ONCE(!io_req); WARN_ON_ONCE(!io_req);
...@@ -1089,7 +1105,7 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic, ...@@ -1089,7 +1105,7 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic,
shost_printk(KERN_ERR, fnic->lport->host, shost_printk(KERN_ERR, fnic->lport->host,
"itmf_cmpl io_req is null - " "itmf_cmpl io_req is null - "
"hdr status = %s tag = 0x%x sc 0x%p\n", "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; return;
} }
start_time = io_req->start_time; start_time = io_req->start_time;
...@@ -1938,6 +1954,10 @@ static inline int fnic_queue_dr_io_req(struct fnic *fnic, ...@@ -1938,6 +1954,10 @@ static inline int fnic_queue_dr_io_req(struct fnic *fnic,
struct scsi_lun fc_lun; struct scsi_lun fc_lun;
int ret = 0; int ret = 0;
unsigned long intr_flags; 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); spin_lock_irqsave(host->host_lock, intr_flags);
if (unlikely(fnic_chk_state_flags_locked(fnic, if (unlikely(fnic_chk_state_flags_locked(fnic,
...@@ -1964,7 +1984,8 @@ static inline int fnic_queue_dr_io_req(struct fnic *fnic, ...@@ -1964,7 +1984,8 @@ static inline int fnic_queue_dr_io_req(struct fnic *fnic,
/* fill in the lun info */ /* fill in the lun info */
int_to_scsilun(sc->device->lun, &fc_lun); 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, 0, FCPIO_ITMF_LUN_RESET, SCSI_NO_TAG,
fc_lun.scsi_lun, io_req->port_id, fc_lun.scsi_lun, io_req->port_id,
fnic->config.ra_tov, fnic->config.ed_tov); fnic->config.ra_tov, fnic->config.ed_tov);
...@@ -2146,8 +2167,7 @@ static int fnic_clean_pending_aborts(struct fnic *fnic, ...@@ -2146,8 +2167,7 @@ static int fnic_clean_pending_aborts(struct fnic *fnic,
.ret = SUCCESS, .ret = SUCCESS,
}; };
if (new_sc) iter_data.lr_sc = lr_sc;
iter_data.lr_sc = lr_sc;
scsi_host_busy_iter(fnic->lport->host, scsi_host_busy_iter(fnic->lport->host,
fnic_pending_aborts_iter, &iter_data); fnic_pending_aborts_iter, &iter_data);
...@@ -2230,8 +2250,14 @@ int fnic_device_reset(struct scsi_cmnd *sc) ...@@ -2230,8 +2250,14 @@ int fnic_device_reset(struct scsi_cmnd *sc)
mutex_lock(&fnic->sgreset_mutex); mutex_lock(&fnic->sgreset_mutex);
tag = fnic->fnic_max_tag_id; tag = fnic->fnic_max_tag_id;
new_sc = 1; new_sc = 1;
} fnic->sgreset_sc = sc;
io_lock = fnic_io_lock_hash(fnic, 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); spin_lock_irqsave(io_lock, flags);
io_req = fnic_priv(sc)->io_req; io_req = fnic_priv(sc)->io_req;
...@@ -2247,6 +2273,8 @@ int fnic_device_reset(struct scsi_cmnd *sc) ...@@ -2247,6 +2273,8 @@ int fnic_device_reset(struct scsi_cmnd *sc)
} }
memset(io_req, 0, sizeof(*io_req)); memset(io_req, 0, sizeof(*io_req));
io_req->port_id = rport->port_id; io_req->port_id = rport->port_id;
io_req->tag = tag;
io_req->sc = sc;
fnic_priv(sc)->io_req = io_req; fnic_priv(sc)->io_req = io_req;
} }
io_req->dr_done = &tm_done; io_req->dr_done = &tm_done;
...@@ -2400,8 +2428,10 @@ int fnic_device_reset(struct scsi_cmnd *sc) ...@@ -2400,8 +2428,10 @@ int fnic_device_reset(struct scsi_cmnd *sc)
(u64)sc->cmnd[4] << 8 | sc->cmnd[5]), (u64)sc->cmnd[4] << 8 | sc->cmnd[5]),
fnic_flags_and_state(sc)); fnic_flags_and_state(sc));
if (new_sc) if (new_sc) {
fnic->sgreset_sc = NULL;
mutex_unlock(&fnic->sgreset_mutex); mutex_unlock(&fnic->sgreset_mutex);
}
FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
"Returning from device reset %s\n", "Returning from device reset %s\n",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment