Skip to content

Commit

Permalink
Merge patch series "scsi: EH rework prep patches, part 1"
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Martin K. Petersen committed Oct 13, 2023
2 parents 78882c7 + 82b2fb5 commit 9f4c887
Show file tree
Hide file tree
Showing 18 changed files with 572 additions and 395 deletions.
94 changes: 65 additions & 29 deletions drivers/message/fusion/mptfc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
55 changes: 54 additions & 1 deletion drivers/message/fusion/mptscsih.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -1808,6 +1808,58 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
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 ": 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){
Expand Down Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions drivers/message/fusion/mptscsih.h
Original file line number Diff line number Diff line change
Expand Up @@ -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[]);
Expand Down
32 changes: 22 additions & 10 deletions drivers/scsi/aic7xxx/aic79xx_osm.c
Original file line number Diff line number Diff line change
Expand Up @@ -536,13 +536,18 @@ ahd_linux_unmap_scb(struct ahd_softc *ahd, struct scb *scb)
struct scsi_cmnd *cmd;

cmd = scb->io_ctx;
ahd_sync_sglist(ahd, scb, BUS_DMASYNC_POSTWRITE);
scsi_dma_unmap(cmd);
if (cmd) {
ahd_sync_sglist(ahd, scb, BUS_DMASYNC_POSTWRITE);
scsi_dma_unmap(cmd);
}
}

/******************************** Macros **************************************/
#define BUILD_SCSIID(ahd, cmd) \
(((scmd_id(cmd) << TID_SHIFT) & TID) | (ahd)->our_id)
static inline unsigned int ahd_build_scsiid(struct ahd_softc *ahd,
struct scsi_device *sdev)
{
return ((sdev_id(sdev) << TID_SHIFT) & TID) | (ahd)->our_id;
}

/*
* Return a string describing the driver.
Expand Down Expand Up @@ -811,14 +816,14 @@ ahd_linux_dev_reset(struct scsi_cmnd *cmd)

tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
cmd->device->id, &tstate);
reset_scb->io_ctx = cmd;
reset_scb->io_ctx = NULL;
reset_scb->platform_data->dev = dev;
reset_scb->sg_count = 0;
ahd_set_residual(reset_scb, 0);
ahd_set_sense_residual(reset_scb, 0);
reset_scb->platform_data->xfer_len = 0;
reset_scb->hscb->control = 0;
reset_scb->hscb->scsiid = BUILD_SCSIID(ahd,cmd);
reset_scb->hscb->scsiid = ahd_build_scsiid(ahd, cmd->device);
reset_scb->hscb->lun = cmd->device->lun;
reset_scb->hscb->cdb_len = 0;
reset_scb->hscb->task_management = SIU_TASKMGMT_LUN_RESET;
Expand Down Expand Up @@ -1577,7 +1582,7 @@ ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev,
* Fill out basics of the HSCB.
*/
hscb->control = 0;
hscb->scsiid = BUILD_SCSIID(ahd, cmd);
hscb->scsiid = ahd_build_scsiid(ahd, cmd->device);
hscb->lun = cmd->device->lun;
scb->hscb->task_management = 0;
mask = SCB_GET_TARGET_MASK(ahd, scb);
Expand Down Expand Up @@ -1766,9 +1771,16 @@ ahd_done(struct ahd_softc *ahd, struct scb *scb)
dev = scb->platform_data->dev;
dev->active--;
dev->openings++;
if ((cmd->result & (CAM_DEV_QFRZN << 16)) != 0) {
cmd->result &= ~(CAM_DEV_QFRZN << 16);
dev->qfrozen--;
if (cmd) {
if ((cmd->result & (CAM_DEV_QFRZN << 16)) != 0) {
cmd->result &= ~(CAM_DEV_QFRZN << 16);
dev->qfrozen--;
}
} else if (scb->flags & SCB_DEVICE_RESET) {
if (ahd->platform_data->eh_done)
complete(ahd->platform_data->eh_done);
ahd_free_scb(ahd, scb);
return;
}
ahd_linux_unmap_scb(ahd, scb);

Expand Down
Loading

0 comments on commit 9f4c887

Please sign in to comment.