Re: [PATCH 19/20] [SCSI] mpt3sas: When device is blocked followed by unblock fails, unfreeze the I/Os

2015-06-15 Thread Johannes Thumshirn
On Fri, Jun 12, 2015 at 03:12:31PM +0530, Sreekanth Reddy wrote:
 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: Sreekanth Reddy sreekanth.re...@avagotech.com
 ---
  drivers/scsi/mpt3sas/mpt3sas_scsih.c | 89 
 ++--
  1 file changed, 75 insertions(+), 14 deletions(-)
 
 diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
 b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
 index 42bb731..5405a2f 100644
 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
 +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
 @@ -2605,6 +2605,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
   * @ioc: per adapter object
   *
 @@ -2623,11 +2692,10 @@ _scsih_ublock_io_all_device(struct MPT3SAS_ADAPTER 
 *ioc)
   if (!sas_device_priv_data-block)
   continue;
  
 - sas_device_priv_data-block = 0;
   dewtprintk(ioc, sdev_printk(KERN_INFO, sdev,
   device_running, handle(0x%04x)\n,
   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)
   if (sas_device_priv_data-sas_target-sas_address
   != sas_address)
   continue;
 - if (sas_device_priv_data-block) {
 - sas_device_priv_data-block = 0;
 - 

[PATCH 19/20] [SCSI] mpt3sas: When device is blocked followed by unblock fails, unfreeze the I/Os

2015-06-12 Thread Sreekanth Reddy
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: Sreekanth Reddy sreekanth.re...@avagotech.com
---
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 89 ++--
 1 file changed, 75 insertions(+), 14 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 42bb731..5405a2f 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -2605,6 +2605,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
  * @ioc: per adapter object
  *
@@ -2623,11 +2692,10 @@ _scsih_ublock_io_all_device(struct MPT3SAS_ADAPTER *ioc)
if (!sas_device_priv_data-block)
continue;
 
-   sas_device_priv_data-block = 0;
dewtprintk(ioc, sdev_printk(KERN_INFO, sdev,
device_running, handle(0x%04x)\n,
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)
if (sas_device_priv_data-sas_target-sas_address
!= sas_address)
continue;
-   if (sas_device_priv_data-block) {
-   sas_device_priv_data-block = 0;
-   scsi_internal_device_unblock(sdev, SDEV_RUNNING);
-   }
+   if 

[PATCH 19/20] [SCSI] mpt3sas: When device is blocked followed by unblock fails, unfreeze the I/Os

2015-03-30 Thread Sreekanth Reddy
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: Sreekanth Reddy sreekanth.re...@avagotech.com
---
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 96 +---
 1 file changed, 78 insertions(+), 18 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 0070f78..8e324bc 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -2610,6 +2610,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
  * @ioc: per adapter object
  *
@@ -2628,11 +2697,10 @@ _scsih_ublock_io_all_device(struct MPT3SAS_ADAPTER *ioc)
if (!sas_device_priv_data-block)
continue;
 
-   sas_device_priv_data-block = 0;
dewtprintk(ioc, sdev_printk(KERN_INFO, sdev,
device_running, handle(0x%04x)\n,
sas_device_priv_data-sas_target-handle));
-   scsi_internal_device_unblock(sdev, SDEV_RUNNING);
+   _scsih_internal_device_unblock(sdev, sas_device_priv_data);
}
 }
 
@@ -2657,10 +2725,9 @@ _scsih_ublock_io_device(struct MPT3SAS_ADAPTER *ioc, u64 
sas_address)
if (sas_device_priv_data-sas_target-sas_address
!= sas_address)
continue;
-   if (sas_device_priv_data-block) {
-   sas_device_priv_data-block = 0;
-   scsi_internal_device_unblock(sdev, SDEV_RUNNING);
-   }
+