Commit 09df4697 authored by Hannes Reinecke's avatar Hannes Reinecke Committed by Martin K. Petersen
Browse files

scsi: pmcraid: Select device in pmcraid_eh_bus_reset_handler()



The reset code requires a device to be selected, but we shouldn't rely on
the command to provide a device for us. So select the first device on the
bus when sending down a bus reset.

Signed-off-by: default avatarHannes Reinecke <hare@suse.de>
Link: https://lore.kernel.org/r/20231002154328.43718-17-hare@suse.de


Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent bffebc19
Loading
Loading
Loading
Loading
+38 −8
Original line number Diff line number Diff line
@@ -2691,7 +2691,7 @@ static int pmcraid_error_handler(struct pmcraid_cmd *cmd)
 *	SUCCESS / FAILED
 */
static int pmcraid_reset_device(
	struct scsi_cmnd *scsi_cmd,
	struct scsi_device *scsi_dev,
	unsigned long timeout,
	u8 modifier)
{
@@ -2703,11 +2703,11 @@ static int pmcraid_reset_device(
	u32 ioasc;

	pinstance =
		(struct pmcraid_instance *)scsi_cmd->device->host->hostdata;
	res = scsi_cmd->device->hostdata;
		(struct pmcraid_instance *)scsi_dev->host->hostdata;
	res = scsi_dev->hostdata;

	if (!res) {
		sdev_printk(KERN_ERR, scsi_cmd->device,
		sdev_printk(KERN_ERR, scsi_dev,
			    "reset_device: NULL resource pointer\n");
		return FAILED;
	}
@@ -3018,16 +3018,46 @@ static int pmcraid_eh_device_reset_handler(struct scsi_cmnd *scmd)
{
	scmd_printk(KERN_INFO, scmd,
		    "resetting device due to an I/O command timeout.\n");
	return pmcraid_reset_device(scmd,
	return pmcraid_reset_device(scmd->device,
				    PMCRAID_INTERNAL_TIMEOUT,
				    RESET_DEVICE_LUN);
}

static int pmcraid_eh_bus_reset_handler(struct scsi_cmnd *scmd)
{
	scmd_printk(KERN_INFO, scmd,
	struct Scsi_Host *host = scmd->device->host;
	struct pmcraid_instance *pinstance =
		(struct pmcraid_instance *)host->hostdata;
	struct pmcraid_resource_entry *res = NULL;
	struct pmcraid_resource_entry *temp;
	struct scsi_device *sdev = NULL;
	unsigned long lock_flags;

	/*
	 * The reset device code insists on us passing down
	 * a device, so grab the first device on the bus.
	 */
	spin_lock_irqsave(&pinstance->resource_lock, lock_flags);
	list_for_each_entry(temp, &pinstance->used_res_q, queue) {
		if (scmd->device->channel == PMCRAID_VSET_BUS_ID &&
		    RES_IS_VSET(temp->cfg_entry)) {
			res = temp;
			break;
		} else if (scmd->device->channel == PMCRAID_PHYS_BUS_ID &&
			   RES_IS_GSCSI(temp->cfg_entry)) {
			res = temp;
			break;
		}
	}
	if (res)
		sdev = res->scsi_dev;
	spin_unlock_irqrestore(&pinstance->resource_lock, lock_flags);
	if (!sdev)
		return FAILED;

	sdev_printk(KERN_INFO, sdev,
		    "Doing bus reset due to an I/O command timeout.\n");
	return pmcraid_reset_device(scmd,
	return pmcraid_reset_device(sdev,
				    PMCRAID_RESET_BUS_TIMEOUT,
				    RESET_DEVICE_BUS);
}
@@ -3036,7 +3066,7 @@ static int pmcraid_eh_target_reset_handler(struct scsi_cmnd *scmd)
{
	scmd_printk(KERN_INFO, scmd,
		    "Doing target reset due to an I/O command timeout.\n");
	return pmcraid_reset_device(scmd,
	return pmcraid_reset_device(scmd->device,
				    PMCRAID_INTERNAL_TIMEOUT,
				    RESET_DEVICE_TARGET);
}