summaryrefslogtreecommitdiff
path: root/drivers/message
diff options
context:
space:
mode:
authorMartin K. Petersen <martin.petersen@oracle.com>2023-10-13 21:25:20 +0300
committerMartin K. Petersen <martin.petersen@oracle.com>2023-10-13 21:25:20 +0300
commit9f4c887fe64e27413509979b5be3fb2630d813ba (patch)
tree03cc7acf5c670b192709d0c987736fbc048dbe06 /drivers/message
parent78882c7657bb276bab028d92f99fc185b25a2fc1 (diff)
parent82b2fb52d6ecc3c902b46b3f9bb4325ab3f6d50d (diff)
downloadlinux-9f4c887fe64e27413509979b5be3fb2630d813ba.tar.xz
Merge patch series "scsi: EH rework prep patches, part 1"
Hannes Reinecke <hare@suse.de> says: Hi all, (taking up an old thread:) here's the first batch of patches for my EH rework. It modifies the reset callbacks for SCSI drivers such that the final conversion to drop the 'struct scsi_cmnd' argument and use the entity in question (host, bus, target, device) as the argument to the SCSI EH callbacks becomes possible. The first part covers drivers which just requires minor tweaks. Link: https://lore.kernel.org/r/20231002154328.43718-1-hare@suse.de Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/message')
-rw-r--r--drivers/message/fusion/mptfc.c94
-rw-r--r--drivers/message/fusion/mptscsih.c55
-rw-r--r--drivers/message/fusion/mptscsih.h1
3 files changed, 120 insertions, 30 deletions
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index 22e7779a332b..aa6bb764df3e 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -183,73 +183,109 @@ static struct fc_function_template mptfc_transport_functions = {
};
static int
-mptfc_block_error_handler(struct scsi_cmnd *SCpnt,
- int (*func)(struct scsi_cmnd *SCpnt),
- const char *caller)
+mptfc_block_error_handler(struct fc_rport *rport)
{
MPT_SCSI_HOST *hd;
- struct scsi_device *sdev = SCpnt->device;
- struct Scsi_Host *shost = sdev->host;
- struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
+ struct Scsi_Host *shost = rport_to_shost(rport);
unsigned long flags;
int ready;
- MPT_ADAPTER *ioc;
+ MPT_ADAPTER *ioc;
int loops = 40; /* seconds */
- hd = shost_priv(SCpnt->device->host);
+ hd = shost_priv(shost);
ioc = hd->ioc;
spin_lock_irqsave(shost->host_lock, flags);
while ((ready = fc_remote_port_chkready(rport) >> 16) == DID_IMM_RETRY
|| (loops > 0 && ioc->active == 0)) {
spin_unlock_irqrestore(shost->host_lock, flags);
dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
- "mptfc_block_error_handler.%d: %d:%llu, port status is "
- "%x, active flag %d, deferring %s recovery.\n",
+ "mptfc_block_error_handler.%d: %s, port status is "
+ "%x, active flag %d, deferring recovery.\n",
ioc->name, ioc->sh->host_no,
- SCpnt->device->id, SCpnt->device->lun,
- ready, ioc->active, caller));
+ dev_name(&rport->dev), ready, ioc->active));
msleep(1000);
spin_lock_irqsave(shost->host_lock, flags);
loops --;
}
spin_unlock_irqrestore(shost->host_lock, flags);
- if (ready == DID_NO_CONNECT || !SCpnt->device->hostdata
- || ioc->active == 0) {
+ if (ready == DID_NO_CONNECT || ioc->active == 0) {
dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
- "%s.%d: %d:%llu, failing recovery, "
- "port state %x, active %d, vdevice %p.\n", caller,
+ "mpt_block_error_handler.%d: %s, failing recovery, "
+ "port state %x, active %d.\n",
ioc->name, ioc->sh->host_no,
- SCpnt->device->id, SCpnt->device->lun, ready,
- ioc->active, SCpnt->device->hostdata));
+ dev_name(&rport->dev), ready, ioc->active));
return FAILED;
}
- dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
- "%s.%d: %d:%llu, executing recovery.\n", caller,
- ioc->name, ioc->sh->host_no,
- SCpnt->device->id, SCpnt->device->lun));
- return (*func)(SCpnt);
+ return SUCCESS;
}
static int
mptfc_abort(struct scsi_cmnd *SCpnt)
{
- return
- mptfc_block_error_handler(SCpnt, mptscsih_abort, __func__);
+ struct Scsi_Host *shost = SCpnt->device->host;
+ struct fc_rport *rport = starget_to_rport(scsi_target(SCpnt->device));
+ MPT_SCSI_HOST __maybe_unused *hd = shost_priv(shost);
+ int rtn;
+
+ rtn = mptfc_block_error_handler(rport);
+ if (rtn == SUCCESS) {
+ dfcprintk (hd->ioc, printk(MYIOC_s_DEBUG_FMT
+ "%s.%d: %d:%llu, executing recovery.\n", __func__,
+ hd->ioc->name, shost->host_no,
+ SCpnt->device->id, SCpnt->device->lun));
+ rtn = mptscsih_abort(SCpnt);
+ }
+ return rtn;
}
static int
mptfc_dev_reset(struct scsi_cmnd *SCpnt)
{
- return
- mptfc_block_error_handler(SCpnt, mptscsih_dev_reset, __func__);
+ struct Scsi_Host *shost = SCpnt->device->host;
+ struct fc_rport *rport = starget_to_rport(scsi_target(SCpnt->device));
+ MPT_SCSI_HOST __maybe_unused *hd = shost_priv(shost);
+ int rtn;
+
+ rtn = mptfc_block_error_handler(rport);
+ if (rtn == SUCCESS) {
+ dfcprintk (hd->ioc, printk(MYIOC_s_DEBUG_FMT
+ "%s.%d: %d:%llu, executing recovery.\n", __func__,
+ hd->ioc->name, shost->host_no,
+ SCpnt->device->id, SCpnt->device->lun));
+ rtn = mptscsih_dev_reset(SCpnt);
+ }
+ return rtn;
}
static int
mptfc_bus_reset(struct scsi_cmnd *SCpnt)
{
- return
- mptfc_block_error_handler(SCpnt, mptscsih_bus_reset, __func__);
+ struct Scsi_Host *shost = SCpnt->device->host;
+ MPT_SCSI_HOST __maybe_unused *hd = shost_priv(shost);
+ int channel = SCpnt->device->channel;
+ struct mptfc_rport_info *ri;
+ int rtn;
+
+ list_for_each_entry(ri, &hd->ioc->fc_rports, list) {
+ if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
+ VirtTarget *vtarget = ri->starget->hostdata;
+
+ if (!vtarget || vtarget->channel != channel)
+ continue;
+ rtn = fc_block_rport(ri->rport);
+ if (rtn != 0)
+ break;
+ }
+ }
+ if (rtn == 0) {
+ dfcprintk (hd->ioc, printk(MYIOC_s_DEBUG_FMT
+ "%s.%d: %d:%llu, executing recovery.\n", __func__,
+ hd->ioc->name, shost->host_no,
+ SCpnt->device->id, SCpnt->device->lun));
+ rtn = mptscsih_bus_reset(SCpnt);
+ }
+ return rtn;
}
static void
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index 2bc17087d17d..9080a73b4ea6 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -1793,7 +1793,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
- * mptscsih_dev_reset - Perform a SCSI TARGET_RESET! new_eh variant
+ * mptscsih_dev_reset - Perform a SCSI LOGICAL_UNIT_RESET!
* @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
*
* (linux scsi_host_template.eh_dev_reset_handler routine)
@@ -1811,6 +1811,58 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
/* If we can't locate our host adapter structure, return FAILED status.
*/
if ((hd = shost_priv(SCpnt->device->host)) == NULL){
+ printk(KERN_ERR MYNAM ": lun reset: "
+ "Can't locate host! (sc=%p)\n", SCpnt);
+ return FAILED;
+ }
+
+ ioc = hd->ioc;
+ printk(MYIOC_s_INFO_FMT "attempting lun reset! (sc=%p)\n",
+ ioc->name, SCpnt);
+ scsi_print_command(SCpnt);
+
+ vdevice = SCpnt->device->hostdata;
+ if (!vdevice || !vdevice->vtarget) {
+ retval = 0;
+ goto out;
+ }
+
+ retval = mptscsih_IssueTaskMgmt(hd,
+ MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET,
+ vdevice->vtarget->channel,
+ vdevice->vtarget->id, vdevice->lun, 0,
+ mptscsih_get_tm_timeout(ioc));
+
+ out:
+ printk (MYIOC_s_INFO_FMT "lun reset: %s (sc=%p)\n",
+ ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
+
+ if (retval == 0)
+ return SUCCESS;
+ else
+ return FAILED;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ * mptscsih_target_reset - Perform a SCSI TARGET_RESET!
+ * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
+ *
+ * (linux scsi_host_template.eh_target_reset_handler routine)
+ *
+ * Returns SUCCESS or FAILED.
+ **/
+int
+mptscsih_target_reset(struct scsi_cmnd * SCpnt)
+{
+ MPT_SCSI_HOST *hd;
+ int retval;
+ VirtDevice *vdevice;
+ MPT_ADAPTER *ioc;
+
+ /* If we can't locate our host adapter structure, return FAILED status.
+ */
+ if ((hd = shost_priv(SCpnt->device->host)) == NULL){
printk(KERN_ERR MYNAM ": target reset: "
"Can't locate host! (sc=%p)\n", SCpnt);
return FAILED;
@@ -3256,6 +3308,7 @@ EXPORT_SYMBOL(mptscsih_slave_destroy);
EXPORT_SYMBOL(mptscsih_slave_configure);
EXPORT_SYMBOL(mptscsih_abort);
EXPORT_SYMBOL(mptscsih_dev_reset);
+EXPORT_SYMBOL(mptscsih_target_reset);
EXPORT_SYMBOL(mptscsih_bus_reset);
EXPORT_SYMBOL(mptscsih_host_reset);
EXPORT_SYMBOL(mptscsih_bios_param);
diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h
index a22c5eaf703c..e3d92c392673 100644
--- a/drivers/message/fusion/mptscsih.h
+++ b/drivers/message/fusion/mptscsih.h
@@ -120,6 +120,7 @@ extern void mptscsih_slave_destroy(struct scsi_device *device);
extern int mptscsih_slave_configure(struct scsi_device *device);
extern int mptscsih_abort(struct scsi_cmnd * SCpnt);
extern int mptscsih_dev_reset(struct scsi_cmnd * SCpnt);
+extern int mptscsih_target_reset(struct scsi_cmnd * SCpnt);
extern int mptscsih_bus_reset(struct scsi_cmnd * SCpnt);
extern int mptscsih_host_reset(struct scsi_cmnd *SCpnt);
extern int mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev, sector_t capacity, int geom[]);