mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-06 05:06:29 +00:00
SCSI misc on 20210508
This is a set of minor fixes in various drivers (qla2xxx, ufs, scsi_debug, lpfc) one doc fix and a fairly large update to the fnic driver to remove the open coded iteration functions in favour of the scsi provided ones. Signed-off-by: James E.J. Bottomley <jejb@linux.ibm.com> -----BEGIN PGP SIGNATURE----- iJwEABMIAEQWIQTnYEDbdso9F2cI+arnQslM7pishQUCYJa23iYcamFtZXMuYm90 dG9tbGV5QGhhbnNlbnBhcnRuZXJzaGlwLmNvbQAKCRDnQslM7pishVhnAP0WVxjv V+L6SAyssgzN3Nbq/nY18qMU1/yeA5jVljRW1gD+JaQKpkOmU+lsldauwW2a3v0G 9XPGTricrtYOu1j3t7c= =F0aC -----END PGP SIGNATURE----- Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi Pull more SCSI updates from James Bottomley: "This is a set of minor fixes in various drivers (qla2xxx, ufs, scsi_debug, lpfc) one doc fix and a fairly large update to the fnic driver to remove the open coded iteration functions in favour of the scsi provided ones" * tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: scsi: fnic: Use scsi_host_busy_iter() to traverse commands scsi: fnic: Kill 'exclude_id' argument to fnic_cleanup_io() scsi: scsi_debug: Fix cmd_per_lun, set to max_queue scsi: ufs: core: Narrow down fast path in system suspend path scsi: ufs: core: Cancel rpm_dev_flush_recheck_work during system suspend scsi: ufs: core: Do not put UFS power into LPM if link is broken scsi: qla2xxx: Prevent PRLI in target mode scsi: qla2xxx: Add marginal path handling support scsi: target: tcmu: Return from tcmu_handle_completions() if cmd_id not found scsi: ufs: core: Fix a typo in ufs-sysfs.c scsi: lpfc: Fix bad memory access during VPD DUMP mailbox command scsi: lpfc: Fix DMA virtual address ptr assignment in bsg scsi: lpfc: Fix illegal memory access on Abort IOCBs scsi: blk-mq: Fix build warning when making htmldocs
This commit is contained in:
commit
07db05638a
@ -102,7 +102,7 @@ static const char *fnic_fcpio_status_to_str(unsigned int status)
|
||||
return fcpio_status_str[status];
|
||||
}
|
||||
|
||||
static void fnic_cleanup_io(struct fnic *fnic, int exclude_id);
|
||||
static void fnic_cleanup_io(struct fnic *fnic);
|
||||
|
||||
static inline spinlock_t *fnic_io_lock_hash(struct fnic *fnic,
|
||||
struct scsi_cmnd *sc)
|
||||
@ -638,7 +638,7 @@ static int fnic_fcpio_fw_reset_cmpl_handler(struct fnic *fnic,
|
||||
atomic64_inc(&reset_stats->fw_reset_completions);
|
||||
|
||||
/* Clean up all outstanding io requests */
|
||||
fnic_cleanup_io(fnic, SCSI_NO_TAG);
|
||||
fnic_cleanup_io(fnic);
|
||||
|
||||
atomic64_set(&fnic->fnic_stats.fw_stats.active_fw_reqs, 0);
|
||||
atomic64_set(&fnic->fnic_stats.io_stats.active_ios, 0);
|
||||
@ -1361,93 +1361,90 @@ int fnic_wq_copy_cmpl_handler(struct fnic *fnic, int copy_work_to_do)
|
||||
return wq_work_done;
|
||||
}
|
||||
|
||||
static void fnic_cleanup_io(struct fnic *fnic, int exclude_id)
|
||||
static bool fnic_cleanup_io_iter(struct scsi_cmnd *sc, void *data,
|
||||
bool reserved)
|
||||
{
|
||||
int i;
|
||||
struct fnic *fnic = data;
|
||||
struct fnic_io_req *io_req;
|
||||
unsigned long flags = 0;
|
||||
struct scsi_cmnd *sc;
|
||||
spinlock_t *io_lock;
|
||||
unsigned long start_time = 0;
|
||||
struct fnic_stats *fnic_stats = &fnic->fnic_stats;
|
||||
|
||||
for (i = 0; i < fnic->fnic_max_tag_id; i++) {
|
||||
if (i == exclude_id)
|
||||
continue;
|
||||
|
||||
io_lock = fnic_io_lock_tag(fnic, i);
|
||||
spin_lock_irqsave(io_lock, flags);
|
||||
sc = scsi_host_find_tag(fnic->lport->host, i);
|
||||
if (!sc) {
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
continue;
|
||||
}
|
||||
|
||||
io_req = (struct fnic_io_req *)CMD_SP(sc);
|
||||
if ((CMD_FLAGS(sc) & FNIC_DEVICE_RESET) &&
|
||||
!(CMD_FLAGS(sc) & FNIC_DEV_RST_DONE)) {
|
||||
/*
|
||||
* We will be here only when FW completes reset
|
||||
* without sending completions for outstanding ios.
|
||||
*/
|
||||
CMD_FLAGS(sc) |= FNIC_DEV_RST_DONE;
|
||||
if (io_req && io_req->dr_done)
|
||||
complete(io_req->dr_done);
|
||||
else if (io_req && io_req->abts_done)
|
||||
complete(io_req->abts_done);
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
continue;
|
||||
} else if (CMD_FLAGS(sc) & FNIC_DEVICE_RESET) {
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
continue;
|
||||
}
|
||||
if (!io_req) {
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
continue;
|
||||
}
|
||||
|
||||
CMD_SP(sc) = NULL;
|
||||
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
io_lock = fnic_io_lock_tag(fnic, sc->request->tag);
|
||||
spin_lock_irqsave(io_lock, flags);
|
||||
|
||||
io_req = (struct fnic_io_req *)CMD_SP(sc);
|
||||
if ((CMD_FLAGS(sc) & FNIC_DEVICE_RESET) &&
|
||||
!(CMD_FLAGS(sc) & FNIC_DEV_RST_DONE)) {
|
||||
/*
|
||||
* If there is a scsi_cmnd associated with this io_req, then
|
||||
* free the corresponding state
|
||||
* We will be here only when FW completes reset
|
||||
* without sending completions for outstanding ios.
|
||||
*/
|
||||
start_time = io_req->start_time;
|
||||
fnic_release_ioreq_buf(fnic, io_req, sc);
|
||||
mempool_free(io_req, fnic->io_req_pool);
|
||||
|
||||
sc->result = DID_TRANSPORT_DISRUPTED << 16;
|
||||
FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
|
||||
"%s: tag:0x%x : sc:0x%p duration = %lu DID_TRANSPORT_DISRUPTED\n",
|
||||
__func__, sc->request->tag, sc,
|
||||
(jiffies - start_time));
|
||||
|
||||
if (atomic64_read(&fnic->io_cmpl_skip))
|
||||
atomic64_dec(&fnic->io_cmpl_skip);
|
||||
else
|
||||
atomic64_inc(&fnic_stats->io_stats.io_completions);
|
||||
|
||||
/* Complete the command to SCSI */
|
||||
if (sc->scsi_done) {
|
||||
if (!(CMD_FLAGS(sc) & FNIC_IO_ISSUED))
|
||||
shost_printk(KERN_ERR, fnic->lport->host,
|
||||
"Calling done for IO not issued to fw: tag:0x%x sc:0x%p\n",
|
||||
sc->request->tag, sc);
|
||||
|
||||
FNIC_TRACE(fnic_cleanup_io,
|
||||
sc->device->host->host_no, i, sc,
|
||||
jiffies_to_msecs(jiffies - start_time),
|
||||
0, ((u64)sc->cmnd[0] << 32 |
|
||||
(u64)sc->cmnd[2] << 24 |
|
||||
(u64)sc->cmnd[3] << 16 |
|
||||
(u64)sc->cmnd[4] << 8 | sc->cmnd[5]),
|
||||
(((u64)CMD_FLAGS(sc) << 32) | CMD_STATE(sc)));
|
||||
|
||||
sc->scsi_done(sc);
|
||||
}
|
||||
CMD_FLAGS(sc) |= FNIC_DEV_RST_DONE;
|
||||
if (io_req && io_req->dr_done)
|
||||
complete(io_req->dr_done);
|
||||
else if (io_req && io_req->abts_done)
|
||||
complete(io_req->abts_done);
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
return true;
|
||||
} else if (CMD_FLAGS(sc) & FNIC_DEVICE_RESET) {
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
return true;
|
||||
}
|
||||
if (!io_req) {
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
goto cleanup_scsi_cmd;
|
||||
}
|
||||
|
||||
CMD_SP(sc) = NULL;
|
||||
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
|
||||
/*
|
||||
* If there is a scsi_cmnd associated with this io_req, then
|
||||
* free the corresponding state
|
||||
*/
|
||||
start_time = io_req->start_time;
|
||||
fnic_release_ioreq_buf(fnic, io_req, sc);
|
||||
mempool_free(io_req, fnic->io_req_pool);
|
||||
|
||||
cleanup_scsi_cmd:
|
||||
sc->result = DID_TRANSPORT_DISRUPTED << 16;
|
||||
FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
|
||||
"fnic_cleanup_io: tag:0x%x : sc:0x%p duration = %lu DID_TRANSPORT_DISRUPTED\n",
|
||||
sc->request->tag, sc, (jiffies - start_time));
|
||||
|
||||
if (atomic64_read(&fnic->io_cmpl_skip))
|
||||
atomic64_dec(&fnic->io_cmpl_skip);
|
||||
else
|
||||
atomic64_inc(&fnic_stats->io_stats.io_completions);
|
||||
|
||||
/* Complete the command to SCSI */
|
||||
if (sc->scsi_done) {
|
||||
if (!(CMD_FLAGS(sc) & FNIC_IO_ISSUED))
|
||||
shost_printk(KERN_ERR, fnic->lport->host,
|
||||
"Calling done for IO not issued to fw: tag:0x%x sc:0x%p\n",
|
||||
sc->request->tag, sc);
|
||||
|
||||
FNIC_TRACE(fnic_cleanup_io,
|
||||
sc->device->host->host_no, sc->request->tag, sc,
|
||||
jiffies_to_msecs(jiffies - start_time),
|
||||
0, ((u64)sc->cmnd[0] << 32 |
|
||||
(u64)sc->cmnd[2] << 24 |
|
||||
(u64)sc->cmnd[3] << 16 |
|
||||
(u64)sc->cmnd[4] << 8 | sc->cmnd[5]),
|
||||
(((u64)CMD_FLAGS(sc) << 32) | CMD_STATE(sc)));
|
||||
|
||||
sc->scsi_done(sc);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void fnic_cleanup_io(struct fnic *fnic)
|
||||
{
|
||||
scsi_host_busy_iter(fnic->lport->host,
|
||||
fnic_cleanup_io_iter, fnic);
|
||||
}
|
||||
|
||||
void fnic_wq_copy_cleanup_handler(struct vnic_wq_copy *wq,
|
||||
@ -1558,20 +1555,121 @@ static inline int fnic_queue_abort_io_req(struct fnic *fnic, int tag,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void fnic_rport_exch_reset(struct fnic *fnic, u32 port_id)
|
||||
struct fnic_rport_abort_io_iter_data {
|
||||
struct fnic *fnic;
|
||||
u32 port_id;
|
||||
int term_cnt;
|
||||
};
|
||||
|
||||
static bool fnic_rport_abort_io_iter(struct scsi_cmnd *sc, void *data,
|
||||
bool reserved)
|
||||
{
|
||||
int tag;
|
||||
int abt_tag;
|
||||
int term_cnt = 0;
|
||||
struct fnic_rport_abort_io_iter_data *iter_data = data;
|
||||
struct fnic *fnic = iter_data->fnic;
|
||||
int abt_tag = sc->request->tag;
|
||||
struct fnic_io_req *io_req;
|
||||
spinlock_t *io_lock;
|
||||
unsigned long flags;
|
||||
struct scsi_cmnd *sc;
|
||||
struct reset_stats *reset_stats = &fnic->fnic_stats.reset_stats;
|
||||
struct terminate_stats *term_stats = &fnic->fnic_stats.term_stats;
|
||||
struct scsi_lun fc_lun;
|
||||
enum fnic_ioreq_state old_ioreq_state;
|
||||
|
||||
io_lock = fnic_io_lock_tag(fnic, abt_tag);
|
||||
spin_lock_irqsave(io_lock, flags);
|
||||
|
||||
io_req = (struct fnic_io_req *)CMD_SP(sc);
|
||||
|
||||
if (!io_req || io_req->port_id != iter_data->port_id) {
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((CMD_FLAGS(sc) & FNIC_DEVICE_RESET) &&
|
||||
(!(CMD_FLAGS(sc) & FNIC_DEV_RST_ISSUED))) {
|
||||
FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
|
||||
"fnic_rport_exch_reset dev rst not pending sc 0x%p\n",
|
||||
sc);
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Found IO that is still pending with firmware and
|
||||
* belongs to rport that went away
|
||||
*/
|
||||
if (CMD_STATE(sc) == FNIC_IOREQ_ABTS_PENDING) {
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
return true;
|
||||
}
|
||||
if (io_req->abts_done) {
|
||||
shost_printk(KERN_ERR, fnic->lport->host,
|
||||
"fnic_rport_exch_reset: io_req->abts_done is set "
|
||||
"state is %s\n",
|
||||
fnic_ioreq_state_to_str(CMD_STATE(sc)));
|
||||
}
|
||||
|
||||
if (!(CMD_FLAGS(sc) & FNIC_IO_ISSUED)) {
|
||||
shost_printk(KERN_ERR, fnic->lport->host,
|
||||
"rport_exch_reset "
|
||||
"IO not yet issued %p tag 0x%x flags "
|
||||
"%x state %d\n",
|
||||
sc, abt_tag, CMD_FLAGS(sc), CMD_STATE(sc));
|
||||
}
|
||||
old_ioreq_state = CMD_STATE(sc);
|
||||
CMD_STATE(sc) = FNIC_IOREQ_ABTS_PENDING;
|
||||
CMD_ABTS_STATUS(sc) = FCPIO_INVALID_CODE;
|
||||
if (CMD_FLAGS(sc) & FNIC_DEVICE_RESET) {
|
||||
atomic64_inc(&reset_stats->device_reset_terminates);
|
||||
abt_tag |= FNIC_TAG_DEV_RST;
|
||||
}
|
||||
FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
|
||||
"fnic_rport_exch_reset dev rst sc 0x%p\n", sc);
|
||||
BUG_ON(io_req->abts_done);
|
||||
|
||||
FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
|
||||
"fnic_rport_reset_exch: Issuing abts\n");
|
||||
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
|
||||
/* Now queue the abort command to firmware */
|
||||
int_to_scsilun(sc->device->lun, &fc_lun);
|
||||
|
||||
if (fnic_queue_abort_io_req(fnic, abt_tag,
|
||||
FCPIO_ITMF_ABT_TASK_TERM,
|
||||
fc_lun.scsi_lun, io_req)) {
|
||||
/*
|
||||
* Revert the cmd state back to old state, if
|
||||
* it hasn't changed in between. This cmd will get
|
||||
* aborted later by scsi_eh, or cleaned up during
|
||||
* lun reset
|
||||
*/
|
||||
spin_lock_irqsave(io_lock, flags);
|
||||
if (CMD_STATE(sc) == FNIC_IOREQ_ABTS_PENDING)
|
||||
CMD_STATE(sc) = old_ioreq_state;
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
} else {
|
||||
spin_lock_irqsave(io_lock, flags);
|
||||
if (CMD_FLAGS(sc) & FNIC_DEVICE_RESET)
|
||||
CMD_FLAGS(sc) |= FNIC_DEV_RST_TERM_ISSUED;
|
||||
else
|
||||
CMD_FLAGS(sc) |= FNIC_IO_INTERNAL_TERM_ISSUED;
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
atomic64_inc(&term_stats->terminates);
|
||||
iter_data->term_cnt++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void fnic_rport_exch_reset(struct fnic *fnic, u32 port_id)
|
||||
{
|
||||
struct terminate_stats *term_stats = &fnic->fnic_stats.term_stats;
|
||||
struct fnic_rport_abort_io_iter_data iter_data = {
|
||||
.fnic = fnic,
|
||||
.port_id = port_id,
|
||||
.term_cnt = 0,
|
||||
};
|
||||
|
||||
FNIC_SCSI_DBG(KERN_DEBUG,
|
||||
fnic->lport->host,
|
||||
"fnic_rport_exch_reset called portid 0x%06x\n",
|
||||
@ -1580,121 +1678,18 @@ static void fnic_rport_exch_reset(struct fnic *fnic, u32 port_id)
|
||||
if (fnic->in_remove)
|
||||
return;
|
||||
|
||||
for (tag = 0; tag < fnic->fnic_max_tag_id; tag++) {
|
||||
abt_tag = tag;
|
||||
io_lock = fnic_io_lock_tag(fnic, tag);
|
||||
spin_lock_irqsave(io_lock, flags);
|
||||
sc = scsi_host_find_tag(fnic->lport->host, tag);
|
||||
if (!sc) {
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
continue;
|
||||
}
|
||||
|
||||
io_req = (struct fnic_io_req *)CMD_SP(sc);
|
||||
|
||||
if (!io_req || io_req->port_id != port_id) {
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((CMD_FLAGS(sc) & FNIC_DEVICE_RESET) &&
|
||||
(!(CMD_FLAGS(sc) & FNIC_DEV_RST_ISSUED))) {
|
||||
FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
|
||||
"fnic_rport_exch_reset dev rst not pending sc 0x%p\n",
|
||||
sc);
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Found IO that is still pending with firmware and
|
||||
* belongs to rport that went away
|
||||
*/
|
||||
if (CMD_STATE(sc) == FNIC_IOREQ_ABTS_PENDING) {
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
continue;
|
||||
}
|
||||
if (io_req->abts_done) {
|
||||
shost_printk(KERN_ERR, fnic->lport->host,
|
||||
"fnic_rport_exch_reset: io_req->abts_done is set "
|
||||
"state is %s\n",
|
||||
fnic_ioreq_state_to_str(CMD_STATE(sc)));
|
||||
}
|
||||
|
||||
if (!(CMD_FLAGS(sc) & FNIC_IO_ISSUED)) {
|
||||
shost_printk(KERN_ERR, fnic->lport->host,
|
||||
"rport_exch_reset "
|
||||
"IO not yet issued %p tag 0x%x flags "
|
||||
"%x state %d\n",
|
||||
sc, tag, CMD_FLAGS(sc), CMD_STATE(sc));
|
||||
}
|
||||
old_ioreq_state = CMD_STATE(sc);
|
||||
CMD_STATE(sc) = FNIC_IOREQ_ABTS_PENDING;
|
||||
CMD_ABTS_STATUS(sc) = FCPIO_INVALID_CODE;
|
||||
if (CMD_FLAGS(sc) & FNIC_DEVICE_RESET) {
|
||||
atomic64_inc(&reset_stats->device_reset_terminates);
|
||||
abt_tag = (tag | FNIC_TAG_DEV_RST);
|
||||
FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
|
||||
"fnic_rport_exch_reset dev rst sc 0x%p\n",
|
||||
sc);
|
||||
}
|
||||
|
||||
BUG_ON(io_req->abts_done);
|
||||
|
||||
FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
|
||||
"fnic_rport_reset_exch: Issuing abts\n");
|
||||
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
|
||||
/* Now queue the abort command to firmware */
|
||||
int_to_scsilun(sc->device->lun, &fc_lun);
|
||||
|
||||
if (fnic_queue_abort_io_req(fnic, abt_tag,
|
||||
FCPIO_ITMF_ABT_TASK_TERM,
|
||||
fc_lun.scsi_lun, io_req)) {
|
||||
/*
|
||||
* Revert the cmd state back to old state, if
|
||||
* it hasn't changed in between. This cmd will get
|
||||
* aborted later by scsi_eh, or cleaned up during
|
||||
* lun reset
|
||||
*/
|
||||
spin_lock_irqsave(io_lock, flags);
|
||||
if (CMD_STATE(sc) == FNIC_IOREQ_ABTS_PENDING)
|
||||
CMD_STATE(sc) = old_ioreq_state;
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
} else {
|
||||
spin_lock_irqsave(io_lock, flags);
|
||||
if (CMD_FLAGS(sc) & FNIC_DEVICE_RESET)
|
||||
CMD_FLAGS(sc) |= FNIC_DEV_RST_TERM_ISSUED;
|
||||
else
|
||||
CMD_FLAGS(sc) |= FNIC_IO_INTERNAL_TERM_ISSUED;
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
atomic64_inc(&term_stats->terminates);
|
||||
term_cnt++;
|
||||
}
|
||||
}
|
||||
if (term_cnt > atomic64_read(&term_stats->max_terminates))
|
||||
atomic64_set(&term_stats->max_terminates, term_cnt);
|
||||
scsi_host_busy_iter(fnic->lport->host, fnic_rport_abort_io_iter,
|
||||
&iter_data);
|
||||
if (iter_data.term_cnt > atomic64_read(&term_stats->max_terminates))
|
||||
atomic64_set(&term_stats->max_terminates, iter_data.term_cnt);
|
||||
|
||||
}
|
||||
|
||||
void fnic_terminate_rport_io(struct fc_rport *rport)
|
||||
{
|
||||
int tag;
|
||||
int abt_tag;
|
||||
int term_cnt = 0;
|
||||
struct fnic_io_req *io_req;
|
||||
spinlock_t *io_lock;
|
||||
unsigned long flags;
|
||||
struct scsi_cmnd *sc;
|
||||
struct scsi_lun fc_lun;
|
||||
struct fc_rport_libfc_priv *rdata;
|
||||
struct fc_lport *lport;
|
||||
struct fnic *fnic;
|
||||
struct fc_rport *cmd_rport;
|
||||
struct reset_stats *reset_stats;
|
||||
struct terminate_stats *term_stats;
|
||||
enum fnic_ioreq_state old_ioreq_state;
|
||||
|
||||
if (!rport) {
|
||||
printk(KERN_ERR "fnic_terminate_rport_io: rport is NULL\n");
|
||||
@ -1722,108 +1717,7 @@ void fnic_terminate_rport_io(struct fc_rport *rport)
|
||||
if (fnic->in_remove)
|
||||
return;
|
||||
|
||||
reset_stats = &fnic->fnic_stats.reset_stats;
|
||||
term_stats = &fnic->fnic_stats.term_stats;
|
||||
|
||||
for (tag = 0; tag < fnic->fnic_max_tag_id; tag++) {
|
||||
abt_tag = tag;
|
||||
io_lock = fnic_io_lock_tag(fnic, tag);
|
||||
spin_lock_irqsave(io_lock, flags);
|
||||
sc = scsi_host_find_tag(fnic->lport->host, tag);
|
||||
if (!sc) {
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
continue;
|
||||
}
|
||||
|
||||
io_req = (struct fnic_io_req *)CMD_SP(sc);
|
||||
if (!io_req) {
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
continue;
|
||||
}
|
||||
|
||||
cmd_rport = starget_to_rport(scsi_target(sc->device));
|
||||
if (rport != cmd_rport) {
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((CMD_FLAGS(sc) & FNIC_DEVICE_RESET) &&
|
||||
(!(CMD_FLAGS(sc) & FNIC_DEV_RST_ISSUED))) {
|
||||
FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
|
||||
"fnic_terminate_rport_io dev rst not pending sc 0x%p\n",
|
||||
sc);
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* Found IO that is still pending with firmware and
|
||||
* belongs to rport that went away
|
||||
*/
|
||||
if (CMD_STATE(sc) == FNIC_IOREQ_ABTS_PENDING) {
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
continue;
|
||||
}
|
||||
if (io_req->abts_done) {
|
||||
shost_printk(KERN_ERR, fnic->lport->host,
|
||||
"fnic_terminate_rport_io: io_req->abts_done is set "
|
||||
"state is %s\n",
|
||||
fnic_ioreq_state_to_str(CMD_STATE(sc)));
|
||||
}
|
||||
if (!(CMD_FLAGS(sc) & FNIC_IO_ISSUED)) {
|
||||
FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host,
|
||||
"fnic_terminate_rport_io "
|
||||
"IO not yet issued %p tag 0x%x flags "
|
||||
"%x state %d\n",
|
||||
sc, tag, CMD_FLAGS(sc), CMD_STATE(sc));
|
||||
}
|
||||
old_ioreq_state = CMD_STATE(sc);
|
||||
CMD_STATE(sc) = FNIC_IOREQ_ABTS_PENDING;
|
||||
CMD_ABTS_STATUS(sc) = FCPIO_INVALID_CODE;
|
||||
if (CMD_FLAGS(sc) & FNIC_DEVICE_RESET) {
|
||||
atomic64_inc(&reset_stats->device_reset_terminates);
|
||||
abt_tag = (tag | FNIC_TAG_DEV_RST);
|
||||
FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
|
||||
"fnic_terminate_rport_io dev rst sc 0x%p\n", sc);
|
||||
}
|
||||
|
||||
BUG_ON(io_req->abts_done);
|
||||
|
||||
FNIC_SCSI_DBG(KERN_DEBUG,
|
||||
fnic->lport->host,
|
||||
"fnic_terminate_rport_io: Issuing abts\n");
|
||||
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
|
||||
/* Now queue the abort command to firmware */
|
||||
int_to_scsilun(sc->device->lun, &fc_lun);
|
||||
|
||||
if (fnic_queue_abort_io_req(fnic, abt_tag,
|
||||
FCPIO_ITMF_ABT_TASK_TERM,
|
||||
fc_lun.scsi_lun, io_req)) {
|
||||
/*
|
||||
* Revert the cmd state back to old state, if
|
||||
* it hasn't changed in between. This cmd will get
|
||||
* aborted later by scsi_eh, or cleaned up during
|
||||
* lun reset
|
||||
*/
|
||||
spin_lock_irqsave(io_lock, flags);
|
||||
if (CMD_STATE(sc) == FNIC_IOREQ_ABTS_PENDING)
|
||||
CMD_STATE(sc) = old_ioreq_state;
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
} else {
|
||||
spin_lock_irqsave(io_lock, flags);
|
||||
if (CMD_FLAGS(sc) & FNIC_DEVICE_RESET)
|
||||
CMD_FLAGS(sc) |= FNIC_DEV_RST_TERM_ISSUED;
|
||||
else
|
||||
CMD_FLAGS(sc) |= FNIC_IO_INTERNAL_TERM_ISSUED;
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
atomic64_inc(&term_stats->terminates);
|
||||
term_cnt++;
|
||||
}
|
||||
}
|
||||
if (term_cnt > atomic64_read(&term_stats->max_terminates))
|
||||
atomic64_set(&term_stats->max_terminates, term_cnt);
|
||||
|
||||
fnic_rport_exch_reset(fnic, rport->port_id);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2118,6 +2012,156 @@ static inline int fnic_queue_dr_io_req(struct fnic *fnic,
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct fnic_pending_aborts_iter_data {
|
||||
struct fnic *fnic;
|
||||
struct scsi_cmnd *lr_sc;
|
||||
struct scsi_device *lun_dev;
|
||||
int ret;
|
||||
};
|
||||
|
||||
static bool fnic_pending_aborts_iter(struct scsi_cmnd *sc,
|
||||
void *data, bool reserved)
|
||||
{
|
||||
struct fnic_pending_aborts_iter_data *iter_data = data;
|
||||
struct fnic *fnic = iter_data->fnic;
|
||||
struct scsi_device *lun_dev = iter_data->lun_dev;
|
||||
int abt_tag = sc->request->tag;
|
||||
struct fnic_io_req *io_req;
|
||||
spinlock_t *io_lock;
|
||||
unsigned long flags;
|
||||
struct scsi_lun fc_lun;
|
||||
DECLARE_COMPLETION_ONSTACK(tm_done);
|
||||
enum fnic_ioreq_state old_ioreq_state;
|
||||
|
||||
if (sc == iter_data->lr_sc || sc->device != lun_dev)
|
||||
return true;
|
||||
if (reserved)
|
||||
return true;
|
||||
|
||||
io_lock = fnic_io_lock_tag(fnic, abt_tag);
|
||||
spin_lock_irqsave(io_lock, flags);
|
||||
io_req = (struct fnic_io_req *)CMD_SP(sc);
|
||||
if (!io_req) {
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Found IO that is still pending with firmware and
|
||||
* belongs to the LUN that we are resetting
|
||||
*/
|
||||
FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
|
||||
"Found IO in %s on lun\n",
|
||||
fnic_ioreq_state_to_str(CMD_STATE(sc)));
|
||||
|
||||
if (CMD_STATE(sc) == FNIC_IOREQ_ABTS_PENDING) {
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
return true;
|
||||
}
|
||||
if ((CMD_FLAGS(sc) & FNIC_DEVICE_RESET) &&
|
||||
(!(CMD_FLAGS(sc) & FNIC_DEV_RST_ISSUED))) {
|
||||
FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host,
|
||||
"%s dev rst not pending sc 0x%p\n", __func__,
|
||||
sc);
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (io_req->abts_done)
|
||||
shost_printk(KERN_ERR, fnic->lport->host,
|
||||
"%s: io_req->abts_done is set state is %s\n",
|
||||
__func__, fnic_ioreq_state_to_str(CMD_STATE(sc)));
|
||||
old_ioreq_state = CMD_STATE(sc);
|
||||
/*
|
||||
* Any pending IO issued prior to reset is expected to be
|
||||
* in abts pending state, if not we need to set
|
||||
* FNIC_IOREQ_ABTS_PENDING to indicate the IO is abort pending.
|
||||
* When IO is completed, the IO will be handed over and
|
||||
* handled in this function.
|
||||
*/
|
||||
CMD_STATE(sc) = FNIC_IOREQ_ABTS_PENDING;
|
||||
|
||||
BUG_ON(io_req->abts_done);
|
||||
|
||||
if (CMD_FLAGS(sc) & FNIC_DEVICE_RESET) {
|
||||
abt_tag |= FNIC_TAG_DEV_RST;
|
||||
FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host,
|
||||
"%s: dev rst sc 0x%p\n", __func__, sc);
|
||||
}
|
||||
|
||||
CMD_ABTS_STATUS(sc) = FCPIO_INVALID_CODE;
|
||||
io_req->abts_done = &tm_done;
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
|
||||
/* Now queue the abort command to firmware */
|
||||
int_to_scsilun(sc->device->lun, &fc_lun);
|
||||
|
||||
if (fnic_queue_abort_io_req(fnic, abt_tag,
|
||||
FCPIO_ITMF_ABT_TASK_TERM,
|
||||
fc_lun.scsi_lun, io_req)) {
|
||||
spin_lock_irqsave(io_lock, flags);
|
||||
io_req = (struct fnic_io_req *)CMD_SP(sc);
|
||||
if (io_req)
|
||||
io_req->abts_done = NULL;
|
||||
if (CMD_STATE(sc) == FNIC_IOREQ_ABTS_PENDING)
|
||||
CMD_STATE(sc) = old_ioreq_state;
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
iter_data->ret = FAILED;
|
||||
return false;
|
||||
} else {
|
||||
spin_lock_irqsave(io_lock, flags);
|
||||
if (CMD_FLAGS(sc) & FNIC_DEVICE_RESET)
|
||||
CMD_FLAGS(sc) |= FNIC_DEV_RST_TERM_ISSUED;
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
}
|
||||
CMD_FLAGS(sc) |= FNIC_IO_INTERNAL_TERM_ISSUED;
|
||||
|
||||
wait_for_completion_timeout(&tm_done, msecs_to_jiffies
|
||||
(fnic->config.ed_tov));
|
||||
|
||||
/* Recheck cmd state to check if it is now aborted */
|
||||
spin_lock_irqsave(io_lock, flags);
|
||||
io_req = (struct fnic_io_req *)CMD_SP(sc);
|
||||
if (!io_req) {
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
CMD_FLAGS(sc) |= FNIC_IO_ABT_TERM_REQ_NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
io_req->abts_done = NULL;
|
||||
|
||||
/* if abort is still pending with fw, fail */
|
||||
if (CMD_ABTS_STATUS(sc) == FCPIO_INVALID_CODE) {
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
CMD_FLAGS(sc) |= FNIC_IO_ABT_TERM_DONE;
|
||||
iter_data->ret = FAILED;
|
||||
return false;
|
||||
}
|
||||
CMD_STATE(sc) = FNIC_IOREQ_ABTS_COMPLETE;
|
||||
|
||||
/* original sc used for lr is handled by dev reset code */
|
||||
if (sc != iter_data->lr_sc)
|
||||
CMD_SP(sc) = NULL;
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
|
||||
/* original sc used for lr is handled by dev reset code */
|
||||
if (sc != iter_data->lr_sc) {
|
||||
fnic_release_ioreq_buf(fnic, io_req, sc);
|
||||
mempool_free(io_req, fnic->io_req_pool);
|
||||
}
|
||||
|
||||
/*
|
||||
* Any IO is returned during reset, it needs to call scsi_done
|
||||
* to return the scsi_cmnd to upper layer.
|
||||
*/
|
||||
if (sc->scsi_done) {
|
||||
/* Set result to let upper SCSI layer retry */
|
||||
sc->result = DID_RESET << 16;
|
||||
sc->scsi_done(sc);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clean up any pending aborts on the lun
|
||||
* For each outstanding IO on this lun, whose abort is not completed by fw,
|
||||
@ -2126,157 +2170,25 @@ static inline int fnic_queue_dr_io_req(struct fnic *fnic,
|
||||
*/
|
||||
static int fnic_clean_pending_aborts(struct fnic *fnic,
|
||||
struct scsi_cmnd *lr_sc,
|
||||
bool new_sc)
|
||||
bool new_sc)
|
||||
|
||||
{
|
||||
int tag, abt_tag;
|
||||
struct fnic_io_req *io_req;
|
||||
spinlock_t *io_lock;
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
struct scsi_cmnd *sc;
|
||||
struct scsi_lun fc_lun;
|
||||
struct scsi_device *lun_dev = lr_sc->device;
|
||||
DECLARE_COMPLETION_ONSTACK(tm_done);
|
||||
enum fnic_ioreq_state old_ioreq_state;
|
||||
int ret = SUCCESS;
|
||||
struct fnic_pending_aborts_iter_data iter_data = {
|
||||
.fnic = fnic,
|
||||
.lun_dev = lr_sc->device,
|
||||
.ret = SUCCESS,
|
||||
};
|
||||
|
||||
for (tag = 0; tag < fnic->fnic_max_tag_id; tag++) {
|
||||
io_lock = fnic_io_lock_tag(fnic, tag);
|
||||
spin_lock_irqsave(io_lock, flags);
|
||||
sc = scsi_host_find_tag(fnic->lport->host, tag);
|
||||
/*
|
||||
* ignore this lun reset cmd if issued using new SC
|
||||
* or cmds that do not belong to this lun
|
||||
*/
|
||||
if (!sc || ((sc == lr_sc) && new_sc) || sc->device != lun_dev) {
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
continue;
|
||||
}
|
||||
if (new_sc)
|
||||
iter_data.lr_sc = lr_sc;
|
||||
|
||||
io_req = (struct fnic_io_req *)CMD_SP(sc);
|
||||
|
||||
if (!io_req || sc->device != lun_dev) {
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Found IO that is still pending with firmware and
|
||||
* belongs to the LUN that we are resetting
|
||||
*/
|
||||
FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
|
||||
"Found IO in %s on lun\n",
|
||||
fnic_ioreq_state_to_str(CMD_STATE(sc)));
|
||||
|
||||
if (CMD_STATE(sc) == FNIC_IOREQ_ABTS_PENDING) {
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
continue;
|
||||
}
|
||||
if ((CMD_FLAGS(sc) & FNIC_DEVICE_RESET) &&
|
||||
(!(CMD_FLAGS(sc) & FNIC_DEV_RST_ISSUED))) {
|
||||
FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host,
|
||||
"%s dev rst not pending sc 0x%p\n", __func__,
|
||||
sc);
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (io_req->abts_done)
|
||||
shost_printk(KERN_ERR, fnic->lport->host,
|
||||
"%s: io_req->abts_done is set state is %s\n",
|
||||
__func__, fnic_ioreq_state_to_str(CMD_STATE(sc)));
|
||||
old_ioreq_state = CMD_STATE(sc);
|
||||
/*
|
||||
* Any pending IO issued prior to reset is expected to be
|
||||
* in abts pending state, if not we need to set
|
||||
* FNIC_IOREQ_ABTS_PENDING to indicate the IO is abort pending.
|
||||
* When IO is completed, the IO will be handed over and
|
||||
* handled in this function.
|
||||
*/
|
||||
CMD_STATE(sc) = FNIC_IOREQ_ABTS_PENDING;
|
||||
|
||||
BUG_ON(io_req->abts_done);
|
||||
|
||||
abt_tag = tag;
|
||||
if (CMD_FLAGS(sc) & FNIC_DEVICE_RESET) {
|
||||
abt_tag |= FNIC_TAG_DEV_RST;
|
||||
FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host,
|
||||
"%s: dev rst sc 0x%p\n", __func__, sc);
|
||||
}
|
||||
|
||||
CMD_ABTS_STATUS(sc) = FCPIO_INVALID_CODE;
|
||||
io_req->abts_done = &tm_done;
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
|
||||
/* Now queue the abort command to firmware */
|
||||
int_to_scsilun(sc->device->lun, &fc_lun);
|
||||
|
||||
if (fnic_queue_abort_io_req(fnic, abt_tag,
|
||||
FCPIO_ITMF_ABT_TASK_TERM,
|
||||
fc_lun.scsi_lun, io_req)) {
|
||||
spin_lock_irqsave(io_lock, flags);
|
||||
io_req = (struct fnic_io_req *)CMD_SP(sc);
|
||||
if (io_req)
|
||||
io_req->abts_done = NULL;
|
||||
if (CMD_STATE(sc) == FNIC_IOREQ_ABTS_PENDING)
|
||||
CMD_STATE(sc) = old_ioreq_state;
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
ret = 1;
|
||||
goto clean_pending_aborts_end;
|
||||
} else {
|
||||
spin_lock_irqsave(io_lock, flags);
|
||||
if (CMD_FLAGS(sc) & FNIC_DEVICE_RESET)
|
||||
CMD_FLAGS(sc) |= FNIC_DEV_RST_TERM_ISSUED;
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
}
|
||||
CMD_FLAGS(sc) |= FNIC_IO_INTERNAL_TERM_ISSUED;
|
||||
|
||||
wait_for_completion_timeout(&tm_done,
|
||||
msecs_to_jiffies
|
||||
(fnic->config.ed_tov));
|
||||
|
||||
/* Recheck cmd state to check if it is now aborted */
|
||||
spin_lock_irqsave(io_lock, flags);
|
||||
io_req = (struct fnic_io_req *)CMD_SP(sc);
|
||||
if (!io_req) {
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
CMD_FLAGS(sc) |= FNIC_IO_ABT_TERM_REQ_NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
io_req->abts_done = NULL;
|
||||
|
||||
/* if abort is still pending with fw, fail */
|
||||
if (CMD_ABTS_STATUS(sc) == FCPIO_INVALID_CODE) {
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
CMD_FLAGS(sc) |= FNIC_IO_ABT_TERM_DONE;
|
||||
ret = 1;
|
||||
goto clean_pending_aborts_end;
|
||||
}
|
||||
CMD_STATE(sc) = FNIC_IOREQ_ABTS_COMPLETE;
|
||||
|
||||
/* original sc used for lr is handled by dev reset code */
|
||||
if (sc != lr_sc)
|
||||
CMD_SP(sc) = NULL;
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
|
||||
/* original sc used for lr is handled by dev reset code */
|
||||
if (sc != lr_sc) {
|
||||
fnic_release_ioreq_buf(fnic, io_req, sc);
|
||||
mempool_free(io_req, fnic->io_req_pool);
|
||||
}
|
||||
|
||||
/*
|
||||
* Any IO is returned during reset, it needs to call scsi_done
|
||||
* to return the scsi_cmnd to upper layer.
|
||||
*/
|
||||
if (sc->scsi_done) {
|
||||
/* Set result to let upper SCSI layer retry */
|
||||
sc->result = DID_RESET << 16;
|
||||
sc->scsi_done(sc);
|
||||
}
|
||||
scsi_host_busy_iter(fnic->lport->host,
|
||||
fnic_pending_aborts_iter, &iter_data);
|
||||
if (iter_data.ret == FAILED) {
|
||||
ret = iter_data.ret;
|
||||
goto clean_pending_aborts_end;
|
||||
}
|
||||
|
||||
schedule_timeout(msecs_to_jiffies(2 * fnic->config.ed_tov));
|
||||
|
||||
/* walk again to check, if IOs are still pending in fw */
|
||||
@ -2775,6 +2687,49 @@ void fnic_exch_mgr_reset(struct fc_lport *lp, u32 sid, u32 did)
|
||||
|
||||
}
|
||||
|
||||
static bool fnic_abts_pending_iter(struct scsi_cmnd *sc, void *data,
|
||||
bool reserved)
|
||||
{
|
||||
struct fnic_pending_aborts_iter_data *iter_data = data;
|
||||
struct fnic *fnic = iter_data->fnic;
|
||||
int cmd_state;
|
||||
struct fnic_io_req *io_req;
|
||||
spinlock_t *io_lock;
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* ignore this lun reset cmd or cmds that do not belong to
|
||||
* this lun
|
||||
*/
|
||||
if (iter_data->lr_sc && sc == iter_data->lr_sc)
|
||||
return true;
|
||||
if (iter_data->lun_dev && sc->device != iter_data->lun_dev)
|
||||
return true;
|
||||
|
||||
io_lock = fnic_io_lock_hash(fnic, sc);
|
||||
spin_lock_irqsave(io_lock, flags);
|
||||
|
||||
io_req = (struct fnic_io_req *)CMD_SP(sc);
|
||||
if (!io_req) {
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Found IO that is still pending with firmware and
|
||||
* belongs to the LUN that we are resetting
|
||||
*/
|
||||
FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host,
|
||||
"Found IO in %s on lun\n",
|
||||
fnic_ioreq_state_to_str(CMD_STATE(sc)));
|
||||
cmd_state = CMD_STATE(sc);
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
if (cmd_state == FNIC_IOREQ_ABTS_PENDING)
|
||||
iter_data->ret = 1;
|
||||
|
||||
return iter_data->ret ? false : true;
|
||||
}
|
||||
|
||||
/*
|
||||
* fnic_is_abts_pending() is a helper function that
|
||||
* walks through tag map to check if there is any IOs pending,if there is one,
|
||||
@ -2784,49 +2739,20 @@ void fnic_exch_mgr_reset(struct fc_lport *lp, u32 sid, u32 did)
|
||||
*/
|
||||
int fnic_is_abts_pending(struct fnic *fnic, struct scsi_cmnd *lr_sc)
|
||||
{
|
||||
int tag;
|
||||
struct fnic_io_req *io_req;
|
||||
spinlock_t *io_lock;
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
struct scsi_cmnd *sc;
|
||||
struct scsi_device *lun_dev = NULL;
|
||||
struct fnic_pending_aborts_iter_data iter_data = {
|
||||
.fnic = fnic,
|
||||
.lun_dev = NULL,
|
||||
.ret = 0,
|
||||
};
|
||||
|
||||
if (lr_sc)
|
||||
lun_dev = lr_sc->device;
|
||||
|
||||
/* walk again to check, if IOs are still pending in fw */
|
||||
for (tag = 0; tag < fnic->fnic_max_tag_id; tag++) {
|
||||
sc = scsi_host_find_tag(fnic->lport->host, tag);
|
||||
/*
|
||||
* ignore this lun reset cmd or cmds that do not belong to
|
||||
* this lun
|
||||
*/
|
||||
if (!sc || (lr_sc && (sc->device != lun_dev || sc == lr_sc)))
|
||||
continue;
|
||||
|
||||
io_lock = fnic_io_lock_hash(fnic, sc);
|
||||
spin_lock_irqsave(io_lock, flags);
|
||||
|
||||
io_req = (struct fnic_io_req *)CMD_SP(sc);
|
||||
|
||||
if (!io_req || sc->device != lun_dev) {
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Found IO that is still pending with firmware and
|
||||
* belongs to the LUN that we are resetting
|
||||
*/
|
||||
FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host,
|
||||
"Found IO in %s on lun\n",
|
||||
fnic_ioreq_state_to_str(CMD_STATE(sc)));
|
||||
|
||||
if (CMD_STATE(sc) == FNIC_IOREQ_ABTS_PENDING)
|
||||
ret = 1;
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
if (lr_sc) {
|
||||
iter_data.lun_dev = lr_sc->device;
|
||||
iter_data.lr_sc = lr_sc;
|
||||
}
|
||||
|
||||
return ret;
|
||||
/* walk again to check, if IOs are still pending in fw */
|
||||
scsi_host_busy_iter(fnic->lport->host,
|
||||
fnic_abts_pending_iter, &iter_data);
|
||||
|
||||
return iter_data.ret;
|
||||
}
|
||||
|
@ -934,7 +934,7 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
||||
INIT_LIST_HEAD(&head);
|
||||
list_add_tail(&head, &piocbq->list);
|
||||
|
||||
ct_req = (struct lpfc_sli_ct_request *)bdeBuf1;
|
||||
ct_req = (struct lpfc_sli_ct_request *)bdeBuf1->virt;
|
||||
evt_req_id = ct_req->FsType;
|
||||
cmd = ct_req->CommandResponse.bits.CmdRsp;
|
||||
|
||||
|
@ -254,13 +254,13 @@ lpfc_config_port_prep(struct lpfc_hba *phba)
|
||||
if (mb->un.varDmp.word_cnt == 0)
|
||||
break;
|
||||
|
||||
i = mb->un.varDmp.word_cnt * sizeof(uint32_t);
|
||||
if (offset + i > DMP_VPD_SIZE)
|
||||
i = DMP_VPD_SIZE - offset;
|
||||
if (mb->un.varDmp.word_cnt > DMP_VPD_SIZE - offset)
|
||||
mb->un.varDmp.word_cnt = DMP_VPD_SIZE - offset;
|
||||
lpfc_sli_pcimem_bcopy(((uint8_t *)mb) + DMP_RSP_OFFSET,
|
||||
lpfc_vpd_data + offset, i);
|
||||
offset += i;
|
||||
} while (offset < DMP_VPD_SIZE);
|
||||
lpfc_vpd_data + offset,
|
||||
mb->un.varDmp.word_cnt);
|
||||
offset += mb->un.varDmp.word_cnt;
|
||||
} while (mb->un.varDmp.word_cnt && offset < DMP_VPD_SIZE);
|
||||
|
||||
lpfc_parse_vpd(phba, lpfc_vpd_data, offset);
|
||||
|
||||
|
@ -11804,13 +11804,20 @@ lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, struct lpfc_vport *vport,
|
||||
lpfc_ctx_cmd ctx_cmd)
|
||||
{
|
||||
struct lpfc_io_buf *lpfc_cmd;
|
||||
IOCB_t *icmd = NULL;
|
||||
int rc = 1;
|
||||
|
||||
if (!iocbq || iocbq->vport != vport)
|
||||
return rc;
|
||||
|
||||
if (!(iocbq->iocb_flag & LPFC_IO_FCP) ||
|
||||
!(iocbq->iocb_flag & LPFC_IO_ON_TXCMPLQ))
|
||||
if (!(iocbq->iocb_flag & LPFC_IO_FCP) ||
|
||||
!(iocbq->iocb_flag & LPFC_IO_ON_TXCMPLQ) ||
|
||||
iocbq->iocb_flag & LPFC_DRIVER_ABORTED)
|
||||
return rc;
|
||||
|
||||
icmd = &iocbq->iocb;
|
||||
if (icmd->ulpCommand == CMD_ABORT_XRI_CN ||
|
||||
icmd->ulpCommand == CMD_CLOSE_XRI_CN)
|
||||
return rc;
|
||||
|
||||
lpfc_cmd = container_of(iocbq, struct lpfc_io_buf, cur_iocbq);
|
||||
@ -19770,7 +19777,7 @@ lpfc_sli_get_config_region23(struct lpfc_hba *phba, char *rgn23_data)
|
||||
LPFC_MBOXQ_t *pmb = NULL;
|
||||
MAILBOX_t *mb;
|
||||
uint32_t offset = 0;
|
||||
int i, rc;
|
||||
int rc;
|
||||
|
||||
if (!rgn23_data)
|
||||
return 0;
|
||||
@ -19801,13 +19808,14 @@ lpfc_sli_get_config_region23(struct lpfc_hba *phba, char *rgn23_data)
|
||||
if (mb->un.varDmp.word_cnt == 0)
|
||||
break;
|
||||
|
||||
i = mb->un.varDmp.word_cnt * sizeof(uint32_t);
|
||||
if (offset + i > DMP_RGN23_SIZE)
|
||||
i = DMP_RGN23_SIZE - offset;
|
||||
if (mb->un.varDmp.word_cnt > DMP_RGN23_SIZE - offset)
|
||||
mb->un.varDmp.word_cnt = DMP_RGN23_SIZE - offset;
|
||||
|
||||
lpfc_sli_pcimem_bcopy(((uint8_t *)mb) + DMP_RSP_OFFSET,
|
||||
rgn23_data + offset, i);
|
||||
offset += i;
|
||||
} while (offset < DMP_RGN23_SIZE);
|
||||
rgn23_data + offset,
|
||||
mb->un.varDmp.word_cnt);
|
||||
offset += mb->un.varDmp.word_cnt;
|
||||
} while (mb->un.varDmp.word_cnt && offset < DMP_RGN23_SIZE);
|
||||
|
||||
mempool_free(pmb, phba->mbox_mem_pool);
|
||||
return offset;
|
||||
|
@ -1195,6 +1195,9 @@ static int qla24xx_post_prli_work(struct scsi_qla_host *vha, fc_port_t *fcport)
|
||||
{
|
||||
struct qla_work_evt *e;
|
||||
|
||||
if (vha->host->active_mode == MODE_TARGET)
|
||||
return QLA_FUNCTION_FAILED;
|
||||
|
||||
e = qla2x00_alloc_work(vha, QLA_EVT_PRLI);
|
||||
if (!e)
|
||||
return QLA_FUNCTION_FAILED;
|
||||
|
@ -7707,6 +7707,7 @@ struct scsi_host_template qla2xxx_driver_template = {
|
||||
|
||||
.eh_timed_out = fc_eh_timed_out,
|
||||
.eh_abort_handler = qla2xxx_eh_abort,
|
||||
.eh_should_retry_cmd = fc_eh_should_retry_cmd,
|
||||
.eh_device_reset_handler = qla2xxx_eh_device_reset,
|
||||
.eh_target_reset_handler = qla2xxx_eh_target_reset,
|
||||
.eh_bus_reset_handler = qla2xxx_eh_bus_reset,
|
||||
|
@ -218,7 +218,7 @@ static const char *sdebug_version_date = "20200710";
|
||||
*/
|
||||
#define SDEBUG_CANQUEUE_WORDS 3 /* a WORD is bits in a long */
|
||||
#define SDEBUG_CANQUEUE (SDEBUG_CANQUEUE_WORDS * BITS_PER_LONG)
|
||||
#define DEF_CMD_PER_LUN 255
|
||||
#define DEF_CMD_PER_LUN SDEBUG_CANQUEUE
|
||||
|
||||
/* UA - Unit Attention; SA - Service Action; SSU - Start Stop Unit */
|
||||
#define F_D_IN 1 /* Data-in command (e.g. READ) */
|
||||
@ -5695,8 +5695,8 @@ MODULE_PARM_DESC(lbpu, "enable LBP, support UNMAP command (def=0)");
|
||||
MODULE_PARM_DESC(lbpws, "enable LBP, support WRITE SAME(16) with UNMAP bit (def=0)");
|
||||
MODULE_PARM_DESC(lbpws10, "enable LBP, support WRITE SAME(10) with UNMAP bit (def=0)");
|
||||
MODULE_PARM_DESC(lowest_aligned, "lowest aligned lba (def=0)");
|
||||
MODULE_PARM_DESC(max_luns, "number of LUNs per target to simulate(def=1)");
|
||||
MODULE_PARM_DESC(lun_format, "LUN format: 0->peripheral (def); 1 --> flat address method");
|
||||
MODULE_PARM_DESC(max_luns, "number of LUNs per target to simulate(def=1)");
|
||||
MODULE_PARM_DESC(max_queue, "max number of queued commands (1 to max(def))");
|
||||
MODULE_PARM_DESC(medium_error_count, "count of sectors to return follow on MEDIUM error");
|
||||
MODULE_PARM_DESC(medium_error_start, "starting sector number to return MEDIUM error");
|
||||
@ -5710,7 +5710,7 @@ MODULE_PARM_DESC(opt_xferlen_exp, "optimal transfer length granularity exponent
|
||||
MODULE_PARM_DESC(opts, "1->noise, 2->medium_err, 4->timeout, 8->recovered_err... (def=0)");
|
||||
MODULE_PARM_DESC(per_host_store, "If set, next positive add_host will get new store (def=0)");
|
||||
MODULE_PARM_DESC(physblk_exp, "physical block exponent (def=0)");
|
||||
MODULE_PARM_DESC(poll_queues, "support for iouring iopoll queues (1 to max(submit_queues - 1)");
|
||||
MODULE_PARM_DESC(poll_queues, "support for iouring iopoll queues (1 to max(submit_queues - 1))");
|
||||
MODULE_PARM_DESC(ptype, "SCSI peripheral type(def=0[disk])");
|
||||
MODULE_PARM_DESC(random, "If set, uniformly randomize command duration between 0 and delay_in_ns");
|
||||
MODULE_PARM_DESC(removable, "claim to have removable media (def=0)");
|
||||
@ -7165,12 +7165,15 @@ static int sdebug_change_qdepth(struct scsi_device *sdev, int qdepth)
|
||||
}
|
||||
num_in_q = atomic_read(&devip->num_in_q);
|
||||
|
||||
if (qdepth > SDEBUG_CANQUEUE) {
|
||||
qdepth = SDEBUG_CANQUEUE;
|
||||
pr_warn("%s: requested qdepth [%d] exceeds canqueue [%d], trim\n", __func__,
|
||||
qdepth, SDEBUG_CANQUEUE);
|
||||
}
|
||||
if (qdepth < 1)
|
||||
qdepth = 1;
|
||||
/* allow to exceed max host qc_arr elements for testing */
|
||||
if (qdepth > SDEBUG_CANQUEUE + 10)
|
||||
qdepth = SDEBUG_CANQUEUE + 10;
|
||||
scsi_change_queue_depth(sdev, qdepth);
|
||||
if (qdepth != sdev->queue_depth)
|
||||
scsi_change_queue_depth(sdev, qdepth);
|
||||
|
||||
if (SDEBUG_OPT_Q_NOISE & sdebug_opts) {
|
||||
sdev_printk(KERN_INFO, sdev, "%s: qdepth=%d, num_in_q=%d\n",
|
||||
@ -7558,6 +7561,7 @@ static int sdebug_driver_probe(struct device *dev)
|
||||
sdbg_host = to_sdebug_host(dev);
|
||||
|
||||
sdebug_driver_template.can_queue = sdebug_max_queue;
|
||||
sdebug_driver_template.cmd_per_lun = sdebug_max_queue;
|
||||
if (!sdebug_clustering)
|
||||
sdebug_driver_template.dma_boundary = PAGE_SIZE - 1;
|
||||
|
||||
@ -7593,7 +7597,11 @@ static int sdebug_driver_probe(struct device *dev)
|
||||
* If condition not met, trim poll_queues to 1 (just for simplicity).
|
||||
*/
|
||||
if (poll_queues >= submit_queues) {
|
||||
pr_warn("%s: trim poll_queues to 1\n", my_name);
|
||||
if (submit_queues < 3)
|
||||
pr_warn("%s: trim poll_queues to 1\n", my_name);
|
||||
else
|
||||
pr_warn("%s: trim poll_queues to 1. Perhaps try poll_queues=%d\n",
|
||||
my_name, submit_queues - 1);
|
||||
poll_queues = 1;
|
||||
}
|
||||
if (poll_queues)
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include "ufs.h"
|
||||
#include "ufs-sysfs.h"
|
||||
|
||||
static const char *ufschd_uic_link_state_to_string(
|
||||
static const char *ufshcd_uic_link_state_to_string(
|
||||
enum uic_link_state state)
|
||||
{
|
||||
switch (state) {
|
||||
@ -21,7 +21,7 @@ static const char *ufschd_uic_link_state_to_string(
|
||||
}
|
||||
}
|
||||
|
||||
static const char *ufschd_ufs_dev_pwr_mode_to_string(
|
||||
static const char *ufshcd_ufs_dev_pwr_mode_to_string(
|
||||
enum ufs_dev_pwr_mode state)
|
||||
{
|
||||
switch (state) {
|
||||
@ -81,7 +81,7 @@ static ssize_t rpm_target_dev_state_show(struct device *dev,
|
||||
{
|
||||
struct ufs_hba *hba = dev_get_drvdata(dev);
|
||||
|
||||
return sysfs_emit(buf, "%s\n", ufschd_ufs_dev_pwr_mode_to_string(
|
||||
return sysfs_emit(buf, "%s\n", ufshcd_ufs_dev_pwr_mode_to_string(
|
||||
ufs_pm_lvl_states[hba->rpm_lvl].dev_state));
|
||||
}
|
||||
|
||||
@ -90,7 +90,7 @@ static ssize_t rpm_target_link_state_show(struct device *dev,
|
||||
{
|
||||
struct ufs_hba *hba = dev_get_drvdata(dev);
|
||||
|
||||
return sysfs_emit(buf, "%s\n", ufschd_uic_link_state_to_string(
|
||||
return sysfs_emit(buf, "%s\n", ufshcd_uic_link_state_to_string(
|
||||
ufs_pm_lvl_states[hba->rpm_lvl].link_state));
|
||||
}
|
||||
|
||||
@ -113,7 +113,7 @@ static ssize_t spm_target_dev_state_show(struct device *dev,
|
||||
{
|
||||
struct ufs_hba *hba = dev_get_drvdata(dev);
|
||||
|
||||
return sysfs_emit(buf, "%s\n", ufschd_ufs_dev_pwr_mode_to_string(
|
||||
return sysfs_emit(buf, "%s\n", ufshcd_ufs_dev_pwr_mode_to_string(
|
||||
ufs_pm_lvl_states[hba->spm_lvl].dev_state));
|
||||
}
|
||||
|
||||
@ -122,7 +122,7 @@ static ssize_t spm_target_link_state_show(struct device *dev,
|
||||
{
|
||||
struct ufs_hba *hba = dev_get_drvdata(dev);
|
||||
|
||||
return sysfs_emit(buf, "%s\n", ufschd_uic_link_state_to_string(
|
||||
return sysfs_emit(buf, "%s\n", ufshcd_uic_link_state_to_string(
|
||||
ufs_pm_lvl_states[hba->spm_lvl].link_state));
|
||||
}
|
||||
|
||||
|
@ -8593,7 +8593,7 @@ static void ufshcd_vreg_set_lpm(struct ufs_hba *hba)
|
||||
} else if (!ufshcd_is_ufs_dev_active(hba)) {
|
||||
ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vcc, false);
|
||||
vcc_off = true;
|
||||
if (!ufshcd_is_link_active(hba)) {
|
||||
if (ufshcd_is_link_hibern8(hba) || ufshcd_is_link_off(hba)) {
|
||||
ufshcd_config_vreg_lpm(hba, hba->vreg_info.vccq);
|
||||
ufshcd_config_vreg_lpm(hba, hba->vreg_info.vccq2);
|
||||
}
|
||||
@ -8615,7 +8615,7 @@ static int ufshcd_vreg_set_hpm(struct ufs_hba *hba)
|
||||
!hba->dev_info.is_lu_power_on_wp) {
|
||||
ret = ufshcd_setup_vreg(hba, true);
|
||||
} else if (!ufshcd_is_ufs_dev_active(hba)) {
|
||||
if (!ret && !ufshcd_is_link_active(hba)) {
|
||||
if (!ufshcd_is_link_active(hba)) {
|
||||
ret = ufshcd_config_vreg_hpm(hba, hba->vreg_info.vccq);
|
||||
if (ret)
|
||||
goto vcc_disable;
|
||||
@ -8975,10 +8975,13 @@ int ufshcd_system_suspend(struct ufs_hba *hba)
|
||||
if (!hba->is_powered)
|
||||
return 0;
|
||||
|
||||
cancel_delayed_work_sync(&hba->rpm_dev_flush_recheck_work);
|
||||
|
||||
if ((ufs_get_pm_lvl_to_dev_pwr_mode(hba->spm_lvl) ==
|
||||
hba->curr_dev_pwr_mode) &&
|
||||
(ufs_get_pm_lvl_to_link_pwr_state(hba->spm_lvl) ==
|
||||
hba->uic_link_state) &&
|
||||
pm_runtime_suspended(hba->dev) &&
|
||||
!hba->dev_info.b_rpm_dev_flush_capable)
|
||||
goto out;
|
||||
|
||||
|
@ -1413,7 +1413,7 @@ static int tcmu_run_tmr_queue(struct tcmu_dev *udev)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static unsigned int tcmu_handle_completions(struct tcmu_dev *udev)
|
||||
static bool tcmu_handle_completions(struct tcmu_dev *udev)
|
||||
{
|
||||
struct tcmu_mailbox *mb;
|
||||
struct tcmu_cmd *cmd;
|
||||
@ -1456,7 +1456,7 @@ static unsigned int tcmu_handle_completions(struct tcmu_dev *udev)
|
||||
pr_err("cmd_id %u not found, ring is broken\n",
|
||||
entry->hdr.cmd_id);
|
||||
set_bit(TCMU_DEV_BIT_BROKEN, &udev->flags);
|
||||
break;
|
||||
return false;
|
||||
}
|
||||
|
||||
tcmu_handle_completion(cmd, entry);
|
||||
|
@ -313,12 +313,12 @@ struct blk_mq_ops {
|
||||
*/
|
||||
void (*put_budget)(struct request_queue *, int);
|
||||
|
||||
/*
|
||||
* @set_rq_budget_toekn: store rq's budget token
|
||||
/**
|
||||
* @set_rq_budget_token: store rq's budget token
|
||||
*/
|
||||
void (*set_rq_budget_token)(struct request *, int);
|
||||
/*
|
||||
* @get_rq_budget_toekn: retrieve rq's budget token
|
||||
/**
|
||||
* @get_rq_budget_token: retrieve rq's budget token
|
||||
*/
|
||||
int (*get_rq_budget_token)(struct request *);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user