Commit df838f92 authored by Sreekanth Reddy's avatar Sreekanth Reddy Committed by James Bottomley

mpt3sas: When device is blocked followed by unblock fails, unfreeze the I/Os

Issue: When the disks are getting discovered and assigned device
handles by the kernel, a device block followed by an unblock
(due to broadcast primitives) issued by the driver is
interspersed by the kernel changing the state of the device.
Therefore the unblock by the driver results in a no operation
within the kernel API.

To fix this one, the below patch checks the return of the unblock API
and performs a block followed by an unblock to unfreeze the block
layer's I/O queue. Sufficient checks and prints are also added in the
driver to identify this condition caused by the kernel.
Signed-off-by: default avatarSreekanth Reddy <Sreekanth.Reddy@avagotech.com>
Reviewed-by: default avatarJohannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: default avatarJames Bottomley <JBottomley@Odin.com>
parent 36814028
...@@ -2604,6 +2604,75 @@ _scsih_fw_event_cleanup_queue(struct MPT3SAS_ADAPTER *ioc) ...@@ -2604,6 +2604,75 @@ _scsih_fw_event_cleanup_queue(struct MPT3SAS_ADAPTER *ioc)
} }
} }
/**
* _scsih_internal_device_block - block the sdev device
* @sdev: per device object
* @sas_device_priv_data : per device driver private data
*
* make sure device is blocked without error, if not
* print an error
*/
static void
_scsih_internal_device_block(struct scsi_device *sdev,
struct MPT3SAS_DEVICE *sas_device_priv_data)
{
int r = 0;
sdev_printk(KERN_INFO, sdev, "device_block, handle(0x%04x)\n",
sas_device_priv_data->sas_target->handle);
sas_device_priv_data->block = 1;
r = scsi_internal_device_block(sdev);
if (r == -EINVAL)
sdev_printk(KERN_WARNING, sdev,
"device_block failed with return(%d) for handle(0x%04x)\n",
sas_device_priv_data->sas_target->handle, r);
}
/**
* _scsih_internal_device_unblock - unblock the sdev device
* @sdev: per device object
* @sas_device_priv_data : per device driver private data
* make sure device is unblocked without error, if not retry
* by blocking and then unblocking
*/
static void
_scsih_internal_device_unblock(struct scsi_device *sdev,
struct MPT3SAS_DEVICE *sas_device_priv_data)
{
int r = 0;
sdev_printk(KERN_WARNING, sdev, "device_unblock and setting to running, "
"handle(0x%04x)\n", sas_device_priv_data->sas_target->handle);
sas_device_priv_data->block = 0;
r = scsi_internal_device_unblock(sdev, SDEV_RUNNING);
if (r == -EINVAL) {
/* The device has been set to SDEV_RUNNING by SD layer during
* device addition but the request queue is still stopped by
* our earlier block call. We need to perform a block again
* to get the device to SDEV_BLOCK and then to SDEV_RUNNING */
sdev_printk(KERN_WARNING, sdev,
"device_unblock failed with return(%d) for handle(0x%04x) "
"performing a block followed by an unblock\n",
sas_device_priv_data->sas_target->handle, r);
sas_device_priv_data->block = 1;
r = scsi_internal_device_block(sdev);
if (r)
sdev_printk(KERN_WARNING, sdev, "retried device_block "
"failed with return(%d) for handle(0x%04x)\n",
sas_device_priv_data->sas_target->handle, r);
sas_device_priv_data->block = 0;
r = scsi_internal_device_unblock(sdev, SDEV_RUNNING);
if (r)
sdev_printk(KERN_WARNING, sdev, "retried device_unblock"
" failed with return(%d) for handle(0x%04x)\n",
sas_device_priv_data->sas_target->handle, r);
}
}
/** /**
* _scsih_ublock_io_all_device - unblock every device * _scsih_ublock_io_all_device - unblock every device
* @ioc: per adapter object * @ioc: per adapter object
...@@ -2623,11 +2692,10 @@ _scsih_ublock_io_all_device(struct MPT3SAS_ADAPTER *ioc) ...@@ -2623,11 +2692,10 @@ _scsih_ublock_io_all_device(struct MPT3SAS_ADAPTER *ioc)
if (!sas_device_priv_data->block) if (!sas_device_priv_data->block)
continue; continue;
sas_device_priv_data->block = 0;
dewtprintk(ioc, sdev_printk(KERN_INFO, sdev, dewtprintk(ioc, sdev_printk(KERN_INFO, sdev,
"device_running, handle(0x%04x)\n", "device_running, handle(0x%04x)\n",
sas_device_priv_data->sas_target->handle)); sas_device_priv_data->sas_target->handle));
scsi_internal_device_unblock(sdev, SDEV_RUNNING); _scsih_internal_device_unblock(sdev, sas_device_priv_data);
} }
} }
...@@ -2652,10 +2720,9 @@ _scsih_ublock_io_device(struct MPT3SAS_ADAPTER *ioc, u64 sas_address) ...@@ -2652,10 +2720,9 @@ _scsih_ublock_io_device(struct MPT3SAS_ADAPTER *ioc, u64 sas_address)
if (sas_device_priv_data->sas_target->sas_address if (sas_device_priv_data->sas_target->sas_address
!= sas_address) != sas_address)
continue; continue;
if (sas_device_priv_data->block) { if (sas_device_priv_data->block)
sas_device_priv_data->block = 0; _scsih_internal_device_unblock(sdev,
scsi_internal_device_unblock(sdev, SDEV_RUNNING); sas_device_priv_data);
}
} }
} }
...@@ -2678,10 +2745,7 @@ _scsih_block_io_all_device(struct MPT3SAS_ADAPTER *ioc) ...@@ -2678,10 +2745,7 @@ _scsih_block_io_all_device(struct MPT3SAS_ADAPTER *ioc)
continue; continue;
if (sas_device_priv_data->block) if (sas_device_priv_data->block)
continue; continue;
sas_device_priv_data->block = 1; _scsih_internal_device_block(sdev, sas_device_priv_data);
scsi_internal_device_block(sdev);
sdev_printk(KERN_INFO, sdev, "device_blocked, handle(0x%04x)\n",
sas_device_priv_data->sas_target->handle);
} }
} }
...@@ -2713,10 +2777,7 @@ _scsih_block_io_device(struct MPT3SAS_ADAPTER *ioc, u16 handle) ...@@ -2713,10 +2777,7 @@ _scsih_block_io_device(struct MPT3SAS_ADAPTER *ioc, u16 handle)
continue; continue;
if (sas_device->pend_sas_rphy_add) if (sas_device->pend_sas_rphy_add)
continue; continue;
sas_device_priv_data->block = 1; _scsih_internal_device_block(sdev, sas_device_priv_data);
scsi_internal_device_block(sdev);
sdev_printk(KERN_INFO, sdev,
"device_blocked, handle(0x%04x)\n", handle);
} }
} }
......
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