Re: [PATCH 0/2] mpt3sas: Reference counting fixes from in-flight mpt2sas

2015-08-27 Thread Nicholas A. Bellinger
Hi Sreekanth,

On Thu, 2015-08-27 at 10:37 +0530, Sreekanth Reddy wrote:
> HI Nicholas & Calvin,
> 
> Thanks for the patchset. Sure We will review and we do some unit
> testing on this patch series. Currently my bandwidth is occupied with
> some internal activity, so by end of next week I will acknowledge this
> series if all the thing are fine with this patch series.
> 

Thanks for the quick response.

So Calvin's mpt2sas series has been merged into scsi.git/for-next.

Since this series is AFAICT functionally identical to Calvin's changes,
I assume JEJB will be merging it up for v4.3-rc1 soon too.

Also, we're probably not the only ones hitting this class of OOPsen, so
it will certainly need to be picked up for stable at some point, and any
further regressions will need to be addressed.

Please keep the list posted of your testing progress.

For reference, here are prerequisites need to apply atop v3.14.y:

4dc06fd mpt3sas: delay scsi_add_host call to work with scsi-mq
35b6236 mpt3sas: combine fw_event_work and its event_data
62c4da4 mpt3sas: correct scsi_{target,device} hostdata allocation

--nab

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] aic94xx: Skip reading user settings if flash is not found

2015-08-27 Thread Christoph Hellwig
On Mon, Jul 06, 2015 at 01:07:58PM +0200, Hannes Reinecke wrote:
> If no user settings are found it's pointless trying to
> read them from flash. So skip that step.
> This also fixes a compilation warning about uninitialized variables in
> aic94xx.

This looks okay to me.

Reviewed-by: Christoph Hellwig 
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


RE: [PATCH V6 08/10] [SCSI] aacraid: Send commit-config to controller firmware

2015-08-27 Thread Mahesh Rajashekhara
Hi Christoph, Hi Tomas,

After discussed internally, this driver patch is required only if "auto commit" 
support is not available in the controller firmware.  

We have fix in the released controller firmware, so this driver patch is not 
needed. 

I'm removing this patch in V7.

Hi James,

As you suggested, will keep the review-tags going V6->V7 and add reviewers in 
CC list.

Thanks,
Mahesh

-Original Message-
From: Christoph Hellwig [mailto:h...@infradead.org] 
Sent: Tuesday, August 25, 2015 8:41 PM
To: Tomas Henzl
Cc: Mahesh Rajashekhara; jbottom...@parallels.com; linux-scsi@vger.kernel.org; 
aacr...@pmc-sierra.com; Harry Yang; Rich Bono
Subject: Re: [PATCH V6 08/10] [SCSI] aacraid: Send commit-config to controller 
firmware

On Tue, Aug 25, 2015 at 04:57:26PM +0200, Tomas Henzl wrote:
> On 11.8.2015 07:58, Mahesh Rajashekhara wrote:
> > +#if defined(__powerpc__) || defined(__PPC__) || defined(__ppc__)
> > +   aac_get_config_status(aac, 1);
> > +#else
> > aac_get_config_status(aac, 0);
> > +#endif
> 
> If we use instead
> + aac_get_config_status(aac, 1);
> on all archs will it make problems ?

Yes, that should be our first choice.  If that doesn't work it should be a 
#ifndef CONFIG_X86 with a comment explaining it.
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH V7 0/9] [SCSI] aacraid: Patchset for aacraid driver version 41010

2015-08-27 Thread Mahesh Rajashekhara
This patchset includes the following changes (bug fixes and new feature 
support) specific to aacraid driver.

V7:
Removed patch 08 of V6.
Keep the review-tags going V6->V7.

V6:
Applied driver update change at the end.
Merged 10 and 11 of V5 into 9 of V6.
AAC_MAX_MSIX definition change.
aac_msi option description and subject change.
Removed 'reviewed-by' tag.

V5:
Splited patch 10 from V4 into 2
Added one more patch to request minimum 2 MSIx.

V4:
Updated code with pci_enable_msix_range instead of exact.

V3:
Increased msleep() time from 1 to 20.
Created new patch for pci_enable_msix() replacement.
Changed subject/description of patch 03.

Mahesh Rajashekhara (9):
  [SCSI] aacraid: Fix for logical device name and UID not exposed to the
OS
  [SCSI] aacraid: Add Power Management support
  [SCSI] aacraid: Change interrupt mode to MSI for series-6 controller
  [SCSI] aacraid: Enable 64-bit write to controller register
  [SCSI] aacraid: Tune response path if IsFastPath bit set
  [SCSI] aacraid: Reset irq affinity hints before releasing irq
  [SCSI] aacraid: Unblock IOCTLs to controller once system resumed from
suspend
  [SCSI] aacraid: Replace pci_enable_msix() with pci_enable_msix_range()
  [SCSI] aacraid: Update driver version

 drivers/scsi/aacraid/aachba.c   | 265 +---
 drivers/scsi/aacraid/aacraid.h  |  20 ++-
 drivers/scsi/aacraid/comminit.c | 147 +++---
 drivers/scsi/aacraid/commsup.c  | 113 -
 drivers/scsi/aacraid/linit.c| 152 +++
 drivers/scsi/aacraid/rx.c   |   1 +
 drivers/scsi/aacraid/sa.c   |   1 +
 drivers/scsi/aacraid/src.c  |  64 +++---
 8 files changed, 480 insertions(+), 283 deletions(-)

-- 
1.9.3

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH V7 1/9] [SCSI] aacraid: Fix for logical device name and UID not exposed to the OS

2015-08-27 Thread Mahesh Rajashekhara
Description:
Driver sends the right size of the response buffer.

Changes from V2:
None

Reviewed By: Tomas Henzl , Murthy Bhat 
, Karthikeya Sunkesula 

Signed-off-by: Mahesh Rajashekhara 
---
 drivers/scsi/aacraid/aachba.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index 9b3dd6e..fe59b00 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -570,7 +570,7 @@ static int aac_get_container_name(struct scsi_cmnd * 
scsicmd)
 
status = aac_fib_send(ContainerCommand,
  cmd_fibcontext,
- sizeof (struct aac_get_name),
+ sizeof(struct aac_get_name_resp),
  FsaNormal,
  0, 1,
  (fib_callback)get_container_name_callback,
@@ -1052,7 +1052,7 @@ static int aac_get_container_serial(struct scsi_cmnd * 
scsicmd)
 
status = aac_fib_send(ContainerCommand,
  cmd_fibcontext,
- sizeof (struct aac_get_serial),
+ sizeof(struct aac_get_serial_resp),
  FsaNormal,
  0, 1,
  (fib_callback) get_container_serial_callback,
-- 
1.9.3

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH V7 4/9] [SCSI] aacraid: Enable 64-bit write to controller register

2015-08-27 Thread Mahesh Rajashekhara
Description:
If writeq() not supported, then do atomic two 32bit write

Changes from V2:
None

Reviewed-by: Tomas Henzl , Murthy Bhat 
, Karthikeya Sunkesula 
Signed-off-by: Mahesh Rajashekhara 
---
 drivers/scsi/aacraid/aacraid.h  |  9 +
 drivers/scsi/aacraid/comminit.c |  1 +
 drivers/scsi/aacraid/src.c  | 12 ++--
 3 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index 62b0999..e54f597 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -844,6 +844,10 @@ struct src_registers {
&((AEP)->regs.src.bar0->CSR))
 #define src_writel(AEP, CSR, value)writel(value, \
&((AEP)->regs.src.bar0->CSR))
+#if defined(writeq)
+#definesrc_writeq(AEP, CSR, value) writeq(value, \
+   &((AEP)->regs.src.bar0->CSR))
+#endif
 
 #define SRC_ODR_SHIFT  12
 #define SRC_IDR_SHIFT  9
@@ -1163,6 +1167,11 @@ struct aac_dev
struct fsa_dev_info *fsa_dev;
struct task_struct  *thread;
int cardtype;
+   /*
+*This lock will protect the two 32-bit
+*writes to the Inbound Queue
+*/
+   spinlock_t  iq_lock;
 
/*
 *  The following is the device specific extension.
diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c
index 45a0a04..b4b6088 100644
--- a/drivers/scsi/aacraid/comminit.c
+++ b/drivers/scsi/aacraid/comminit.c
@@ -424,6 +424,7 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
dev->management_fib_count = 0;
spin_lock_init(&dev->manage_lock);
spin_lock_init(&dev->sync_lock);
+   spin_lock_init(&dev->iq_lock);
dev->max_fib_size = sizeof(struct hw_fib);
dev->sg_tablesize = host->sg_tablesize = (dev->max_fib_size
- sizeof(struct aac_fibhdr)
diff --git a/drivers/scsi/aacraid/src.c b/drivers/scsi/aacraid/src.c
index eb07b3d..1409a0b 100644
--- a/drivers/scsi/aacraid/src.c
+++ b/drivers/scsi/aacraid/src.c
@@ -447,6 +447,10 @@ static int aac_src_deliver_message(struct fib *fib)
u32 fibsize;
dma_addr_t address;
struct aac_fib_xporthdr *pFibX;
+#if !defined(writeq)
+   unsigned long flags;
+#endif
+
u16 hdr_size = le16_to_cpu(fib->hw_fib_va->header.Size);
 
atomic_inc(&q->numpending);
@@ -511,10 +515,14 @@ static int aac_src_deliver_message(struct fib *fib)
return -EINVAL;
address |= fibsize;
}
-
+#if defined(writeq)
+   src_writeq(dev, MUnit.IQ_L, (u64)address);
+#else
+   spin_lock_irqsave(&fib->dev->iq_lock, flags);
src_writel(dev, MUnit.IQ_H, upper_32_bits(address) & 0x);
src_writel(dev, MUnit.IQ_L, address & 0x);
-
+   spin_unlock_irqrestore(&fib->dev->iq_lock, flags);
+#endif
return 0;
 }
 
-- 
1.9.3

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH V7 7/9] [SCSI] aacraid: Unblock IOCTLs to controller once system resumed from suspend

2015-08-27 Thread Mahesh Rajashekhara
Description:
Driver blocks ioctls once it received shutdown/suspend request during
suspend/hybernation. This patch unblocks ioctls on resume path.

Changes from V2:
None

Reviewed-by: Tomas Henzl , Murthy Bhat 
, Karthikeya Sunkesula 
Signed-off-by: Mahesh Rajashekhara 
---
 drivers/scsi/aacraid/linit.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 37375cf..3b6e5c6 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -1448,6 +1448,11 @@ static int aac_resume(struct pci_dev *pdev)
pci_set_master(pdev);
if (aac_acquire_resources(aac))
goto fail_device;
+   /*
+   * reset this flag to unblock ioctl() as it was set at
+   * aac_send_shutdown() to block ioctls from upperlayer
+   */
+   aac->adapter_shutdown = 0;
scsi_unblock_requests(shost);
 
return 0;
-- 
1.9.3

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH V7 8/9] [SCSI] aacraid: Replace pci_enable_msix() with pci_enable_msix_range()

2015-08-27 Thread Mahesh Rajashekhara
Description:
As pci_enable_msix() deprecated, replaced with pci_enable_msix_range()

Changes from V5:
Merged 10 and 11 of V5 into this patch.
AAC_MAX_MSIX definition change.

Reviewed-by: Tomas Henzl , Murthy Bhat 
, Karthikeya Sunkesula 
Signed-off-by: Mahesh Rajashekhara 
---
 drivers/scsi/aacraid/aacraid.h  |  2 +-
 drivers/scsi/aacraid/comminit.c | 20 ++--
 2 files changed, 7 insertions(+), 15 deletions(-)

diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index 7b95227..2de5ebc 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -12,7 +12,7 @@
  *  D E F I N E S
  
**/
 
-#define AAC_MAX_MSIX   8   /* vectors */
+#define AAC_MAX_MSIX   32  /* vectors */
 #define AAC_PCI_MSI_ENABLE 0x8000
 
 enum {
diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c
index b4b6088..0e954e3 100644
--- a/drivers/scsi/aacraid/comminit.c
+++ b/drivers/scsi/aacraid/comminit.c
@@ -338,7 +338,7 @@ static int aac_comm_init(struct aac_dev * dev)
 
 void aac_define_int_mode(struct aac_dev *dev)
 {
-   int i, msi_count;
+   int i, msi_count, min_msix;
 
msi_count = i = 0;
/* max. vectors from GET_COMM_PREFERRED_SETTINGS */
@@ -366,22 +366,14 @@ void aac_define_int_mode(struct aac_dev *dev)
 
if (msi_count > 1 &&
pci_find_capability(dev->pdev, PCI_CAP_ID_MSIX)) {
-   i = pci_enable_msix(dev->pdev,
+   min_msix = 2;
+   i = pci_enable_msix_range(dev->pdev,
dev->msixentry,
+   min_msix,
msi_count);
-/* Check how many MSIX vectors are allocated */
-   if (i >= 0) {
+   if (i > 0) {
dev->msi_enabled = 1;
-   if (i) {
-   msi_count = i;
-   if (pci_enable_msix(dev->pdev,
-   dev->msixentry,
-   msi_count)) {
-   dev->msi_enabled = 0;
-   printk(KERN_ERR "%s%d: MSIX not 
supported!! Will try MSI 0x%x.\n",
-   dev->name, dev->id, i);
-   }
-   }
+   msi_count = i;
} else {
dev->msi_enabled = 0;
printk(KERN_ERR "%s%d: MSIX not supported!! Will try 
MSI 0x%x.\n",
-- 
1.9.3

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH V7 9/9] [SCSI] aacraid: Update driver version

2015-08-27 Thread Mahesh Rajashekhara
Reviewed-by: Tomas Henzl , Murthy Bhat 
, Karthikeya Sunkesula 
Signed-off-by: Mahesh Rajashekhara 
---
 drivers/scsi/aacraid/aacraid.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index 2de5ebc..074878b 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -62,7 +62,7 @@ enum {
 #definePMC_GLOBAL_INT_BIT0 0x0001
 
 #ifndef AAC_DRIVER_BUILD
-# define AAC_DRIVER_BUILD 40709
+# define AAC_DRIVER_BUILD 41010
 # define AAC_DRIVER_BRANCH "-ms"
 #endif
 #define MAXIMUM_NUM_CONTAINERS 32
-- 
1.9.3

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH V7 5/9] [SCSI] aacraid: Tune response path if IsFastPath bit set

2015-08-27 Thread Mahesh Rajashekhara
Description:
If 'IsFastPath' bit is set, then response path assumes no error and 
skips error check.

Changes from V2:
None

Reviewed-by: Murthy Bhat , Karthikeya Sunkesula 

Signed-off-by: Mahesh Rajashekhara 
---
 drivers/scsi/aacraid/aachba.c | 259 ++
 1 file changed, 137 insertions(+), 122 deletions(-)

diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index 05f2a02..e4c2437 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -2977,11 +2977,16 @@ static void aac_srb_callback(void *context, struct fib 
* fibptr)
return;
 
BUG_ON(fibptr == NULL);
-
dev = fibptr->dev;
 
-   srbreply = (struct aac_srb_reply *) fib_data(fibptr);
+   scsi_dma_unmap(scsicmd);
 
+   /* expose physical device if expose_physicald flag is on */
+   if (scsicmd->cmnd[0] == INQUIRY && !(scsicmd->cmnd[1] & 0x01)
+ && expose_physicals > 0)
+   aac_expose_phy_device(scsicmd);
+
+   srbreply = (struct aac_srb_reply *) fib_data(fibptr);
scsicmd->sense_buffer[0] = '\0';  /* Initialize sense valid flag to 
false */
 
if (fibptr->flags & FIB_CONTEXT_FLAG_FASTRESP) {
@@ -2994,147 +2999,157 @@ static void aac_srb_callback(void *context, struct 
fib * fibptr)
 */
scsi_set_resid(scsicmd, scsi_bufflen(scsicmd)
   - le32_to_cpu(srbreply->data_xfer_length));
-   }
-
-   scsi_dma_unmap(scsicmd);
-
-   /* expose physical device if expose_physicald flag is on */
-   if (scsicmd->cmnd[0] == INQUIRY && !(scsicmd->cmnd[1] & 0x01)
- && expose_physicals > 0)
-   aac_expose_phy_device(scsicmd);
+   /*
+* First check the fib status
+*/
 
-   /*
-* First check the fib status
-*/
+   if (le32_to_cpu(srbreply->status) != ST_OK) {
+   int len;
 
-   if (le32_to_cpu(srbreply->status) != ST_OK){
-   int len;
-   printk(KERN_WARNING "aac_srb_callback: srb failed, status = 
%d\n", le32_to_cpu(srbreply->status));
-   len = min_t(u32, le32_to_cpu(srbreply->sense_data_size),
-   SCSI_SENSE_BUFFERSIZE);
-   scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8 | 
SAM_STAT_CHECK_CONDITION;
-   memcpy(scsicmd->sense_buffer, srbreply->sense_data, len);
-   }
+   printk(KERN_WARNING "aac_srb_callback: srb failed, 
status = %d\n", le32_to_cpu(srbreply->status));
+   len = min_t(u32, le32_to_cpu(srbreply->sense_data_size),
+   SCSI_SENSE_BUFFERSIZE);
+   scsicmd->result = DID_ERROR << 16
+   | COMMAND_COMPLETE << 8
+   | SAM_STAT_CHECK_CONDITION;
+   memcpy(scsicmd->sense_buffer,
+   srbreply->sense_data, len);
+   }
 
-   /*
-* Next check the srb status
-*/
-   switch( (le32_to_cpu(srbreply->srb_status))&0x3f){
-   case SRB_STATUS_ERROR_RECOVERY:
-   case SRB_STATUS_PENDING:
-   case SRB_STATUS_SUCCESS:
-   scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
-   break;
-   case SRB_STATUS_DATA_OVERRUN:
-   switch(scsicmd->cmnd[0]){
-   case  READ_6:
-   case  WRITE_6:
-   case  READ_10:
-   case  WRITE_10:
-   case  READ_12:
-   case  WRITE_12:
-   case  READ_16:
-   case  WRITE_16:
-   if (le32_to_cpu(srbreply->data_xfer_length) < 
scsicmd->underflow) {
-   printk(KERN_WARNING"aacraid: SCSI CMD 
underflow\n");
-   } else {
-   printk(KERN_WARNING"aacraid: SCSI CMD Data 
Overrun\n");
+   /*
+* Next check the srb status
+*/
+   switch ((le32_to_cpu(srbreply->srb_status))&0x3f) {
+   case SRB_STATUS_ERROR_RECOVERY:
+   case SRB_STATUS_PENDING:
+   case SRB_STATUS_SUCCESS:
+   scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
+   break;
+   case SRB_STATUS_DATA_OVERRUN:
+   switch (scsicmd->cmnd[0]) {
+   case  READ_6:
+   case  WRITE_6:
+   case  READ_10:
+   case  WRITE_10:
+   case  READ_12:
+   case  WRITE_12:
+   case  READ_16:
+   case  WRITE_16:
+   if (le32_to_cpu(srbreply->data_xfer_length)
+ 

[PATCH V7 3/9] [SCSI] aacraid: Change interrupt mode to MSI for series-6 controller

2015-08-27 Thread Mahesh Rajashekhara
Description:
This change always sets MSI interrupt mode for series-6 controller.

Changes from V2:
aac_msi option description and subject change.

Reviewed-by: Tomas Henzl , Murthy Bhat 
, Karthikeya Sunkesula 
Signed-off-by: Mahesh Rajashekhara 
---
 drivers/scsi/aacraid/aachba.c | 2 +-
 drivers/scsi/aacraid/src.c| 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index fe59b00..05f2a02 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -259,7 +259,7 @@ MODULE_PARM_DESC(commit, "Control whether a COMMIT_CONFIG 
is issued to the"
" 0=off, 1=on");
 module_param_named(msi, aac_msi, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(msi, "IRQ handling."
-   " 0=PIC(default), 1=MSI, 2=MSI-X(unsupported, uses MSI)");
+   " 0=PIC(default), 1=MSI, 2=MSI-X)");
 module_param(startup_timeout, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(startup_timeout, "The duration of time in seconds to wait for"
" adapter to have it's kernel up and\n"
diff --git a/drivers/scsi/aacraid/src.c b/drivers/scsi/aacraid/src.c
index b147341..eb07b3d 100644
--- a/drivers/scsi/aacraid/src.c
+++ b/drivers/scsi/aacraid/src.c
@@ -742,7 +742,7 @@ int aac_src_init(struct aac_dev *dev)
if (dev->comm_interface != AAC_COMM_MESSAGE_TYPE1)
goto error_iounmap;
 
-   dev->msi = aac_msi && !pci_enable_msi(dev->pdev);
+   dev->msi = !pci_enable_msi(dev->pdev);
 
dev->aac_msix[0].vector_no = 0;
dev->aac_msix[0].dev = dev;
-- 
1.9.3

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH V7 6/9] [SCSI] aacraid: Reset irq affinity hints before releasing irq

2015-08-27 Thread Mahesh Rajashekhara
Description:
Reset irq affinity hints before releasing IRQ
Removed duplicate code of IRQ acquire/release

Changes from V2:
None

Reviewed-by: Tomas Henzl , Murthy Bhat 
, Karthikeya Sunkesula 
Signed-off-by: Mahesh Rajashekhara 
---
 drivers/scsi/aacraid/aacraid.h |   2 +
 drivers/scsi/aacraid/commsup.c | 113 ++---
 drivers/scsi/aacraid/src.c |  48 ++---
 3 files changed, 88 insertions(+), 75 deletions(-)

diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index e54f597..7b95227 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -2110,6 +2110,8 @@ static inline unsigned int cap_to_cyls(sector_t capacity, 
unsigned divisor)
 #define AAC_OWNER_ERROR_HANDLER0x103
 #define AAC_OWNER_FIRMWARE 0x106
 
+int aac_acquire_irq(struct aac_dev *dev);
+void aac_free_irq(struct aac_dev *dev);
 const char *aac_driverinfo(struct Scsi_Host *);
 struct fib *aac_fib_alloc(struct aac_dev *dev);
 int aac_fib_setup(struct aac_dev *dev);
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index 4da5749..a1f90fe 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -1270,13 +1270,12 @@ retry_next:
 static int _aac_reset_adapter(struct aac_dev *aac, int forced)
 {
int index, quirks;
-   int retval, i;
+   int retval;
struct Scsi_Host *host;
struct scsi_device *dev;
struct scsi_cmnd *command;
struct scsi_cmnd *command_list;
int jafo = 0;
-   int cpu;
 
/*
 * Assumptions:
@@ -1339,35 +1338,7 @@ static int _aac_reset_adapter(struct aac_dev *aac, int 
forced)
aac->comm_phys = 0;
kfree(aac->queues);
aac->queues = NULL;
-   cpu = cpumask_first(cpu_online_mask);
-   if (aac->pdev->device == PMC_DEVICE_S6 ||
-   aac->pdev->device == PMC_DEVICE_S7 ||
-   aac->pdev->device == PMC_DEVICE_S8 ||
-   aac->pdev->device == PMC_DEVICE_S9) {
-   if (aac->max_msix > 1) {
-   for (i = 0; i < aac->max_msix; i++) {
-   if (irq_set_affinity_hint(
-   aac->msixentry[i].vector,
-   NULL)) {
-   printk(KERN_ERR "%s%d: Failed to reset 
IRQ affinity for cpu %d\n",
-   aac->name,
-   aac->id,
-   cpu);
-   }
-   cpu = cpumask_next(cpu,
-   cpu_online_mask);
-   free_irq(aac->msixentry[i].vector,
-&(aac->aac_msix[i]));
-   }
-   pci_disable_msix(aac->pdev);
-   } else {
-   free_irq(aac->pdev->irq, &(aac->aac_msix[0]));
-   }
-   } else {
-   free_irq(aac->pdev->irq, aac);
-   }
-   if (aac->msi)
-   pci_disable_msi(aac->pdev);
+   aac_free_irq(aac);
kfree(aac->fsa_dev);
aac->fsa_dev = NULL;
quirks = aac_get_driver_ident(index)->quirks;
@@ -1978,3 +1949,83 @@ int aac_command_thread(void *data)
dev->aif_thread = 0;
return 0;
 }
+
+int aac_acquire_irq(struct aac_dev *dev)
+{
+   int i;
+   int j;
+   int ret = 0;
+   int cpu;
+
+   cpu = cpumask_first(cpu_online_mask);
+   if (!dev->sync_mode && dev->msi_enabled && dev->max_msix > 1) {
+   for (i = 0; i < dev->max_msix; i++) {
+   dev->aac_msix[i].vector_no = i;
+   dev->aac_msix[i].dev = dev;
+   if (request_irq(dev->msixentry[i].vector,
+   dev->a_ops.adapter_intr,
+   0, "aacraid", &(dev->aac_msix[i]))) {
+   printk(KERN_ERR "%s%d: Failed to register IRQ 
for vector %d.\n",
+   dev->name, dev->id, i);
+   for (j = 0 ; j < i ; j++)
+   free_irq(dev->msixentry[j].vector,
+&(dev->aac_msix[j]));
+   pci_disable_msix(dev->pdev);
+   ret = -1;
+   }
+   if (irq_set_affinity_hint(dev->msixentry[i].vector,
+   get_cpu_mask(cpu))) {
+   printk(KERN_ERR "%s%d: Failed to set IRQ 
affinity for cpu %d\n",
+   dev->name, dev->id, cpu);
+   }
+   cpu = cpumask_next(cpu, cpu_online_mask);
+

[PATCH V7 2/9] [SCSI] aacraid: Add Power Management support

2015-08-27 Thread Mahesh Rajashekhara
Description:
* .suspend() and .resume() routines implemented in the driver
* aac_release_resources() initiates firmware shutdown
* aac_acquire_resources re-initializes the host interface

Changes from V2:
Increased msleep(1) to msleep(20)
Reverted pci_enable_msix_exact() to pci_enable_msix() as this change has moved 
into a separate patch

Reviewed-by: Tomas Henzl , Murthy Bhat 
, Karthikeya Sunkesula 
Signed-off-by: Mahesh Rajashekhara 
---
 drivers/scsi/aacraid/aacraid.h  |   5 ++
 drivers/scsi/aacraid/comminit.c | 154 
 drivers/scsi/aacraid/linit.c| 147 ++
 drivers/scsi/aacraid/rx.c   |   1 +
 drivers/scsi/aacraid/sa.c   |   1 +
 drivers/scsi/aacraid/src.c  |   2 +
 6 files changed, 232 insertions(+), 78 deletions(-)

diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index 40fe65c..62b0999 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -547,6 +547,7 @@ struct adapter_ops
int  (*adapter_sync_cmd)(struct aac_dev *dev, u32 command, u32 p1, u32 
p2, u32 p3, u32 p4, u32 p5, u32 p6, u32 *status, u32 *r1, u32 *r2, u32 *r3, u32 
*r4);
int  (*adapter_check_health)(struct aac_dev *dev);
int  (*adapter_restart)(struct aac_dev *dev, int bled);
+   void (*adapter_start)(struct aac_dev *dev);
/* Transport operations */
int  (*adapter_ioremap)(struct aac_dev * dev, u32 size);
irq_handler_t adapter_intr;
@@ -1247,6 +1248,9 @@ struct aac_dev
 #define aac_adapter_restart(dev,bled) \
(dev)->a_ops.adapter_restart(dev,bled)
 
+#define aac_adapter_start(dev) \
+   ((dev)->a_ops.adapter_start(dev))
+
 #define aac_adapter_ioremap(dev, size) \
(dev)->a_ops.adapter_ioremap(dev, size)
 
@@ -2127,6 +2131,7 @@ int aac_sa_init(struct aac_dev *dev);
 int aac_src_init(struct aac_dev *dev);
 int aac_srcv_init(struct aac_dev *dev);
 int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_fib * 
hw_fib, int wait, struct fib * fibptr, unsigned long *nonotify);
+void aac_define_int_mode(struct aac_dev *dev);
 unsigned int aac_response_normal(struct aac_queue * q);
 unsigned int aac_command_normal(struct aac_queue * q);
 unsigned int aac_intr_normal(struct aac_dev *dev, u32 Index,
diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c
index 45db84a..45a0a04 100644
--- a/drivers/scsi/aacraid/comminit.c
+++ b/drivers/scsi/aacraid/comminit.c
@@ -43,8 +43,6 @@
 
 #include "aacraid.h"
 
-static void aac_define_int_mode(struct aac_dev *dev);
-
 struct aac_common aac_config = {
.irq_mod = 1
 };
@@ -338,6 +336,82 @@ static int aac_comm_init(struct aac_dev * dev)
return 0;
 }
 
+void aac_define_int_mode(struct aac_dev *dev)
+{
+   int i, msi_count;
+
+   msi_count = i = 0;
+   /* max. vectors from GET_COMM_PREFERRED_SETTINGS */
+   if (dev->max_msix == 0 ||
+   dev->pdev->device == PMC_DEVICE_S6 ||
+   dev->sync_mode) {
+   dev->max_msix = 1;
+   dev->vector_cap =
+   dev->scsi_host_ptr->can_queue +
+   AAC_NUM_MGT_FIB;
+   return;
+   }
+
+   /* Don't bother allocating more MSI-X vectors than cpus */
+   msi_count = min(dev->max_msix,
+   (unsigned int)num_online_cpus());
+
+   dev->max_msix = msi_count;
+
+   if (msi_count > AAC_MAX_MSIX)
+   msi_count = AAC_MAX_MSIX;
+
+   for (i = 0; i < msi_count; i++)
+   dev->msixentry[i].entry = i;
+
+   if (msi_count > 1 &&
+   pci_find_capability(dev->pdev, PCI_CAP_ID_MSIX)) {
+   i = pci_enable_msix(dev->pdev,
+   dev->msixentry,
+   msi_count);
+/* Check how many MSIX vectors are allocated */
+   if (i >= 0) {
+   dev->msi_enabled = 1;
+   if (i) {
+   msi_count = i;
+   if (pci_enable_msix(dev->pdev,
+   dev->msixentry,
+   msi_count)) {
+   dev->msi_enabled = 0;
+   printk(KERN_ERR "%s%d: MSIX not 
supported!! Will try MSI 0x%x.\n",
+   dev->name, dev->id, i);
+   }
+   }
+   } else {
+   dev->msi_enabled = 0;
+   printk(KERN_ERR "%s%d: MSIX not supported!! Will try 
MSI 0x%x.\n",
+   dev->name, dev->id, i);
+   }
+   }
+
+   if (!dev->msi_enabled) {
+   msi_count = 1;
+   i = pci_enable_msi(dev->pdev);
+
+   if (!i) {
+   dev->msi_ena

Re: [PATCH v1 14/15] scsi: ufs: commit descriptors before setting the doorbell

2015-08-27 Thread ygardi
> On Tue, Aug 25, 2015 at 7:36 AM,   wrote:
>>> On Aug 21, 2015 3:10 PM, "Yaniv Gardi"  wrote:

 Add a write memory barrier to make sure descriptors prepared are
 actually
 written to memory before ringing the doorbell. We have also added the
 write memory barrier after ringing the doorbell register so that
 controller sees the new request immediately.

 Signed-off-by: Yaniv Gardi 

 ---
  drivers/scsi/ufs/ufshcd.c | 6 ++
  1 file changed, 6 insertions(+)

 diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
 index fef0660..876148b 100644
 --- a/drivers/scsi/ufs/ufshcd.c
 +++ b/drivers/scsi/ufs/ufshcd.c
 @@ -833,6 +833,8 @@ void ufshcd_send_command(struct ufs_hba *hba,
 unsigned int task_tag)
 ufshcd_clk_scaling_start_busy(hba);
 __set_bit(task_tag, &hba->outstanding_reqs);
 ufshcd_writel(hba, 1 << task_tag,
 REG_UTP_TRANSFER_REQ_DOOR_BELL);
 +   /* Make sure that doorbell is committed immediately */
 +   wmb();
>>>
>>> Is this really necessary? Is there a measurable difference?
>>
>> I'm not sure if there is a measurable difference, but as the Door-Bell
>> register is the one that actually responsible for the HW execution of
>> the
>> requests, anyhow, it's recommended to its value will be written
>> instantly to the memory.
>
> A barrier doesn't guarantee speed, only ordering. Unless you can
> measure the difference, you should not have it.

Rob,
let me have an example:
context#1 updates outstanding_reqs variable and write(DOOR_BELL)
context#2 upon interrupt of a request completion the following happens:
  report completion on each one of the bits in:
  outstanding_reqs ^ read(DOOR_BELL);

0. let's assume the DOOR_BELL = 0x1 (which means 1 active request in slot 0)
1. context#1: update the DOOR_BELL to be 0x3; (2 active requests: in slot
0 and 1)
2. the new value 0x3 is still not written to the DR so DORR_BELL is still
0x1, but outstanding_reqs is already updated = 0x3
3. the request in slot 0 just completed, and interrupt happens, so
DORR_BELL is now 0 (request in slot 0 completed)
4. context#2: outstanding_reqs ^ read(DOOR_BELL) = 0x3 ^ 0x0 = 0x3 =>
wrong conclusion since the request in slot 1 never completed, and actually
never started.


>
>> Also, as the Interrupt context reads this register, and compare it to
>> the
>> SW mirroring value (hba->outstanding_reqs) in order to realize what
>> requests are already completed, it's important to get the correct value
>> by reading this register, otherwise we might realize a request
>> completion
>> while it was never even submitted.
>
> If a register read can pass a register write out of order, then your
> h/w is broken. Plus what if the interrupt occurs before the barrier.
>
> Rob
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 09/10] scsi_dh: return SCSI_DH_NOTCONN in scsi_dh_activate()

2015-08-27 Thread Hannes Reinecke
When calling scsi_dh_activate() we should be returning
SCSI_DH_NOTCONN if the device handler couldn't be attached.

Reviewed-by: Bart van Assche 
Reviewed-by: Christoph Hellwig 
Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/scsi_dh.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/scsi/scsi_dh.c b/drivers/scsi/scsi_dh.c
index 954ca5e..2d93bc9 100644
--- a/drivers/scsi/scsi_dh.c
+++ b/drivers/scsi/scsi_dh.c
@@ -325,6 +325,7 @@ int scsi_dh_activate(struct request_queue *q, 
activate_complete fn, void *data)
 
if (!sdev->handler)
goto out_fn;
+   err = SCSI_DH_NOTCONN;
if (sdev->sdev_state == SDEV_CANCEL ||
sdev->sdev_state == SDEV_DEL)
goto out_fn;
-- 
1.8.5.6

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 08/10] scsi_dh: don't allow to detach device handlers at runtime

2015-08-27 Thread Hannes Reinecke
From: Christoph Hellwig 

The I/O submission and completion pathes call into the device handler
without any synchronization agains detachment.  So disallow detaching
device handlers at runtime.

Signed-off-by: Christoph Hellwig 
Reviewed-by: Martin K. Petersen 
Reviewed-by: Hannes Reinecke 
---
 drivers/scsi/scsi_dh.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/scsi_dh.c b/drivers/scsi/scsi_dh.c
index 489083c..954ca5e 100644
--- a/drivers/scsi/scsi_dh.c
+++ b/drivers/scsi/scsi_dh.c
@@ -180,8 +180,10 @@ store_dh_state(struct device *dev, struct device_attribute 
*attr,
/*
 * Detach from a device handler
 */
-   scsi_dh_handler_detach(sdev);
-   err = 0;
+   sdev_printk(KERN_WARNING, sdev,
+   "can't detach handler %s.\n",
+   sdev->handler->name);
+   err = -EINVAL;
} else if (!strncmp(buf, "activate", 8)) {
/*
 * Activate a device handler
-- 
1.8.5.6

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 07/10] scsi_dh: add a common helper to get a scsi_device from a request_queue

2015-08-27 Thread Hannes Reinecke
From: Christoph Hellwig 

And cleanup the various messy opencoded versions of this.  Note that this
moves the sdev_state checks outside the queue_lock coverage, but as
we don't hold the lock over the activation they are only advisory anyway.

Signed-off-by: Christoph Hellwig 
Reviewed-by: Martin K. Petersen 
Reviewed-by: Hannes Reinecke 
---
 drivers/scsi/scsi_dh.c | 99 +++---
 1 file changed, 46 insertions(+), 53 deletions(-)

diff --git a/drivers/scsi/scsi_dh.c b/drivers/scsi/scsi_dh.c
index f752a45..489083c 100644
--- a/drivers/scsi/scsi_dh.c
+++ b/drivers/scsi/scsi_dh.c
@@ -282,6 +282,20 @@ int scsi_unregister_device_handler(struct 
scsi_device_handler *scsi_dh)
 }
 EXPORT_SYMBOL_GPL(scsi_unregister_device_handler);
 
+static struct scsi_device *get_sdev_from_queue(struct request_queue *q)
+{
+   struct scsi_device *sdev;
+   unsigned long flags;
+
+   spin_lock_irqsave(q->queue_lock, flags);
+   sdev = q->queuedata;
+   if (!sdev || !get_device(&sdev->sdev_gendev))
+   sdev = NULL;
+   spin_unlock_irqrestore(q->queue_lock, flags);
+
+   return sdev;
+}
+
 /*
  * scsi_dh_activate - activate the path associated with the scsi_device
  *  corresponding to the given request queue.
@@ -297,41 +311,37 @@ EXPORT_SYMBOL_GPL(scsi_unregister_device_handler);
  */
 int scsi_dh_activate(struct request_queue *q, activate_complete fn, void *data)
 {
-   int err = 0;
-   unsigned long flags;
struct scsi_device *sdev;
-   struct device *dev = NULL;
+   int err = SCSI_DH_NOSYS;
 
-   spin_lock_irqsave(q->queue_lock, flags);
-   sdev = q->queuedata;
+   sdev = get_sdev_from_queue(q);
if (!sdev) {
-   spin_unlock_irqrestore(q->queue_lock, flags);
-   err = SCSI_DH_NOSYS;
if (fn)
fn(data, err);
return err;
}
 
-   dev = get_device(&sdev->sdev_gendev);
-   if (!sdev->handler || !dev ||
-   sdev->sdev_state == SDEV_CANCEL ||
+   if (!sdev->handler)
+   goto out_fn;
+   if (sdev->sdev_state == SDEV_CANCEL ||
sdev->sdev_state == SDEV_DEL)
-   err = SCSI_DH_NOSYS;
-   if (sdev->sdev_state == SDEV_OFFLINE)
-   err = SCSI_DH_DEV_OFFLINED;
-   spin_unlock_irqrestore(q->queue_lock, flags);
+   goto out_fn;
 
-   if (err) {
-   if (fn)
-   fn(data, err);
-   goto out;
-   }
+   err = SCSI_DH_DEV_OFFLINED;
+   if (sdev->sdev_state == SDEV_OFFLINE)
+   goto out_fn;
 
if (sdev->handler->activate)
err = sdev->handler->activate(sdev, fn, data);
-out:
-   put_device(dev);
+
+out_put_device:
+   put_device(&sdev->sdev_gendev);
return err;
+
+out_fn:
+   if (fn)
+   fn(data, err);
+   goto out_put_device;
 }
 EXPORT_SYMBOL_GPL(scsi_dh_activate);
 
@@ -347,21 +357,15 @@ EXPORT_SYMBOL_GPL(scsi_dh_activate);
  */
 int scsi_dh_set_params(struct request_queue *q, const char *params)
 {
-   int err = -SCSI_DH_NOSYS;
-   unsigned long flags;
struct scsi_device *sdev;
+   int err = -SCSI_DH_NOSYS;
 
-   spin_lock_irqsave(q->queue_lock, flags);
-   sdev = q->queuedata;
-   if (sdev->handler &&
-   sdev->handler->set_params &&
-   get_device(&sdev->sdev_gendev))
-   err = 0;
-   spin_unlock_irqrestore(q->queue_lock, flags);
-
-   if (err)
+   sdev = get_sdev_from_queue(q);
+   if (!sdev)
return err;
-   err = sdev->handler->set_params(sdev, params);
+
+   if (sdev->handler && sdev->handler->set_params)
+   err = sdev->handler->set_params(sdev, params);
put_device(&sdev->sdev_gendev);
return err;
 }
@@ -375,23 +379,19 @@ EXPORT_SYMBOL_GPL(scsi_dh_set_params);
  */
 int scsi_dh_attach(struct request_queue *q, const char *name)
 {
-   unsigned long flags;
struct scsi_device *sdev;
struct scsi_device_handler *scsi_dh;
int err = 0;
 
-   scsi_dh = scsi_dh_lookup(name);
-   if (!scsi_dh)
-   return -EINVAL;
-
-   spin_lock_irqsave(q->queue_lock, flags);
-   sdev = q->queuedata;
-   if (!sdev || !get_device(&sdev->sdev_gendev))
-   err = -ENODEV;
-   spin_unlock_irqrestore(q->queue_lock, flags);
+   sdev = get_sdev_from_queue(q);
+   if (!sdev)
+   return -ENODEV;
 
-   if (err)
-   return err;
+   scsi_dh = scsi_dh_lookup(name);
+   if (!scsi_dh) {
+   err = -EINVAL;
+   goto out_put_device;
+   }
 
if (sdev->handler) {
if (sdev->handler != scsi_dh)
@@ -418,22 +418,15 @@ EXPORT_SYMBOL_GPL(scsi_dh_attach);
  */
 const char *scsi_dh_attached_handler_name(struct request_queue *q, gfp_t gfp)
 {
-   unsigned long flags;
  

[PATCH 05/10] scsi_dh: move device matching to the core code

2015-08-27 Thread Hannes Reinecke
From: Christoph Hellwig 

Add a single list of devices that need non-ALUA device handlers to the core
scsi_dh code so that we can autoload the modules for them at probe time.

While this is a little ugly in terms of architecture it actually
significantly simplifies the code in addition to the new autoloading
functionality.

Signed-off-by: Christoph Hellwig 
Reviewed-by: Martin K. Petersen 
Reviewed-by: Hannes Reinecke 
Acked-by: Mike Snitzer 
---
 drivers/scsi/device_handler/scsi_dh_alua.c  |  6 ---
 drivers/scsi/device_handler/scsi_dh_emc.c   | 29 --
 drivers/scsi/device_handler/scsi_dh_hp_sw.c | 30 ---
 drivers/scsi/device_handler/scsi_dh_rdac.c  | 50 -
 drivers/scsi/scsi_dh.c  | 84 ++---
 include/scsi/scsi_device.h  |  1 -
 6 files changed, 66 insertions(+), 134 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index 854b568..ace2457 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -819,11 +819,6 @@ static int alua_prep_fn(struct scsi_device *sdev, struct 
request *req)
 
 }
 
-static bool alua_match(struct scsi_device *sdev)
-{
-   return (scsi_device_tpgs(sdev) != 0);
-}
-
 /*
  * alua_bus_attach - Attach device handler
  * @sdev: device to be attached to
@@ -877,7 +872,6 @@ static struct scsi_device_handler alua_dh = {
.check_sense = alua_check_sense,
.activate = alua_activate,
.set_params = alua_set_params,
-   .match = alua_match,
 };
 
 static int __init alua_init(void)
diff --git a/drivers/scsi/device_handler/scsi_dh_emc.c 
b/drivers/scsi/device_handler/scsi_dh_emc.c
index 6ed1caa..fd31e67 100644
--- a/drivers/scsi/device_handler/scsi_dh_emc.c
+++ b/drivers/scsi/device_handler/scsi_dh_emc.c
@@ -622,34 +622,6 @@ done:
return result;
 }
 
-static const struct {
-   char *vendor;
-   char *model;
-} clariion_dev_list[] = {
-   {"DGC", "RAID"},
-   {"DGC", "DISK"},
-   {"DGC", "VRAID"},
-   {NULL, NULL},
-};
-
-static bool clariion_match(struct scsi_device *sdev)
-{
-   int i;
-
-   if (scsi_device_tpgs(sdev))
-   return false;
-
-   for (i = 0; clariion_dev_list[i].vendor; i++) {
-   if (!strncmp(sdev->vendor, clariion_dev_list[i].vendor,
-   strlen(clariion_dev_list[i].vendor)) &&
-   !strncmp(sdev->model, clariion_dev_list[i].model,
-   strlen(clariion_dev_list[i].model))) {
-   return true;
-   }
-   }
-   return false;
-}
-
 static struct scsi_dh_data *clariion_bus_attach(struct scsi_device *sdev)
 {
struct clariion_dh_data *h;
@@ -698,7 +670,6 @@ static struct scsi_device_handler clariion_dh = {
.activate   = clariion_activate,
.prep_fn= clariion_prep_fn,
.set_params = clariion_set_params,
-   .match  = clariion_match,
 };
 
 static int __init clariion_init(void)
diff --git a/drivers/scsi/device_handler/scsi_dh_hp_sw.c 
b/drivers/scsi/device_handler/scsi_dh_hp_sw.c
index 485d995..1bf10d3 100644
--- a/drivers/scsi/device_handler/scsi_dh_hp_sw.c
+++ b/drivers/scsi/device_handler/scsi_dh_hp_sw.c
@@ -311,35 +311,6 @@ static int hp_sw_activate(struct scsi_device *sdev,
return 0;
 }
 
-static const struct {
-   char *vendor;
-   char *model;
-} hp_sw_dh_data_list[] = {
-   {"COMPAQ", "MSA1000 VOLUME"},
-   {"COMPAQ", "HSV110"},
-   {"HP", "HSV100"},
-   {"DEC", "HSG80"},
-   {NULL, NULL},
-};
-
-static bool hp_sw_match(struct scsi_device *sdev)
-{
-   int i;
-
-   if (scsi_device_tpgs(sdev))
-   return false;
-
-   for (i = 0; hp_sw_dh_data_list[i].vendor; i++) {
-   if (!strncmp(sdev->vendor, hp_sw_dh_data_list[i].vendor,
-   strlen(hp_sw_dh_data_list[i].vendor)) &&
-   !strncmp(sdev->model, hp_sw_dh_data_list[i].model,
-   strlen(hp_sw_dh_data_list[i].model))) {
-   return true;
-   }
-   }
-   return false;
-}
-
 static struct scsi_dh_data *hp_sw_bus_attach(struct scsi_device *sdev)
 {
struct hp_sw_dh_data *h;
@@ -379,7 +350,6 @@ static struct scsi_device_handler hp_sw_dh = {
.detach = hp_sw_bus_detach,
.activate   = hp_sw_activate,
.prep_fn= hp_sw_prep_fn,
-   .match  = hp_sw_match,
 };
 
 static int __init hp_sw_init(void)
diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c 
b/drivers/scsi/device_handler/scsi_dh_rdac.c
index b46ace3..d89616f 100644
--- a/drivers/scsi/device_handler/scsi_dh_rdac.c
+++ b/drivers/scsi/device_handler/scsi_dh_rdac.c
@@ -778,55 +778,6 @@ static int rdac_check_sense(struct scsi_device *sdev,
return SCSI_RETURN_NOT_HANDLED;
 }
 
-static const struct {
-   char *v

[PATCH 01/10] dm-mpath, scsi_dh: don't let dm detach device handlers

2015-08-27 Thread Hannes Reinecke
From: Christoph Hellwig 

While allowing dm-mpath to attach device handlers is a functionality we need
for backwards compatibility reason there is no reason to reference count
them and detach them if dm-mpath stops using the device for some reason.

If the device handler works for the given device it can just stay attached,
and we can take the retain_hw_handler codepath.

Signed-off-by: Christoph Hellwig 
Acked-by: Mike Snitzer 
Acked-by: Hannes Reinecke 
---
 drivers/md/dm-mpath.c | 21 +++-
 drivers/scsi/device_handler/scsi_dh.c | 96 ---
 include/scsi/scsi_device.h|  1 -
 include/scsi/scsi_dh.h|  5 --
 4 files changed, 28 insertions(+), 95 deletions(-)

diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index eff7bdd..a9f58fd 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -159,12 +159,9 @@ static struct priority_group *alloc_priority_group(void)
 static void free_pgpaths(struct list_head *pgpaths, struct dm_target *ti)
 {
struct pgpath *pgpath, *tmp;
-   struct multipath *m = ti->private;
 
list_for_each_entry_safe(pgpath, tmp, pgpaths, list) {
list_del(&pgpath->list);
-   if (m->hw_handler_name)
-   scsi_dh_detach(bdev_get_queue(pgpath->path.dev->bdev));
dm_put_device(ti, pgpath->path.dev);
free_pgpath(pgpath);
}
@@ -580,6 +577,7 @@ static struct pgpath *parse_path(struct dm_arg_set *as, 
struct path_selector *ps
q = bdev_get_queue(p->path.dev->bdev);
 
if (m->retain_attached_hw_handler) {
+retain:
attached_handler_name = scsi_dh_attached_handler_name(q, 
GFP_KERNEL);
if (attached_handler_name) {
/*
@@ -599,20 +597,14 @@ static struct pgpath *parse_path(struct dm_arg_set *as, 
struct path_selector *ps
}
 
if (m->hw_handler_name) {
-   /*
-* Increments scsi_dh reference, even when using an
-* already-attached handler.
-*/
r = scsi_dh_attach(q, m->hw_handler_name);
if (r == -EBUSY) {
-   /*
-* Already attached to different hw_handler:
-* try to reattach with correct one.
-*/
-   scsi_dh_detach(q);
-   r = scsi_dh_attach(q, m->hw_handler_name);
-   }
+   char b[BDEVNAME_SIZE];
 
+   printk(KERN_INFO "dm-mpath: retaining handler on device 
%s\n",
+   bdevname(p->path.dev->bdev, b));
+   goto retain;
+   }
if (r < 0) {
ti->error = "error attaching hardware handler";
dm_put_device(ti, p->path.dev);
@@ -624,7 +616,6 @@ static struct pgpath *parse_path(struct dm_arg_set *as, 
struct path_selector *ps
if (r < 0) {
ti->error = "unable to set hardware "
"handler parameters";
-   scsi_dh_detach(q);
dm_put_device(ti, p->path.dev);
goto bad;
}
diff --git a/drivers/scsi/device_handler/scsi_dh.c 
b/drivers/scsi/device_handler/scsi_dh.c
index 1efebc9..869b5bd 100644
--- a/drivers/scsi/device_handler/scsi_dh.c
+++ b/drivers/scsi/device_handler/scsi_dh.c
@@ -100,14 +100,6 @@ static int scsi_dh_handler_attach(struct scsi_device *sdev,
 {
struct scsi_dh_data *d;
 
-   if (sdev->scsi_dh_data) {
-   if (sdev->scsi_dh_data->scsi_dh != scsi_dh)
-   return -EBUSY;
-
-   kref_get(&sdev->scsi_dh_data->kref);
-   return 0;
-   }
-
if (!try_module_get(scsi_dh->module))
return -EINVAL;
 
@@ -120,7 +112,6 @@ static int scsi_dh_handler_attach(struct scsi_device *sdev,
}
 
d->scsi_dh = scsi_dh;
-   kref_init(&d->kref);
d->sdev = sdev;
 
spin_lock_irq(sdev->request_queue->queue_lock);
@@ -129,12 +120,14 @@ static int scsi_dh_handler_attach(struct scsi_device 
*sdev,
return 0;
 }
 
-static void __detach_handler (struct kref *kref)
+/*
+ * scsi_dh_handler_detach - Detach a device handler from a device
+ * @sdev - SCSI device the device handler should be detached from
+ */
+static void scsi_dh_handler_detach(struct scsi_device *sdev)
 {
-   struct scsi_dh_data *scsi_dh_data =
-   container_of(kref, struct scsi_dh_data, kref);
+   struct scsi_dh_data *scsi_dh_data = sdev->scsi_dh_data;
struct scsi_device_handler *scsi_dh = scsi_dh_data->scsi_dh;
-   struct scsi_device *sdev = scsi_dh_data->sdev;
 
scsi_dh->detach(sdev);
 
@@ -147,30 +140,6 @@ st

[PATCH 03/10] scsi_dh: move to drivers/scsi

2015-08-27 Thread Hannes Reinecke
From: Christoph Hellwig 

Prepare for building scsi_dh.c into the core SCSI module by moving it to
drivers/scsi.

Signed-off-by: Christoph Hellwig 
Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/Makefile |   1 +
 drivers/scsi/device_handler/Makefile  |   1 -
 drivers/scsi/device_handler/scsi_dh.c | 570 --
 drivers/scsi/scsi_dh.c| 570 ++
 4 files changed, 571 insertions(+), 571 deletions(-)
 delete mode 100644 drivers/scsi/device_handler/scsi_dh.c
 create mode 100644 drivers/scsi/scsi_dh.c

diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 91209e3..22f54b0 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -171,6 +171,7 @@ scsi_mod-$(CONFIG_SYSCTL)   += scsi_sysctl.o
 scsi_mod-$(CONFIG_SCSI_PROC_FS)+= scsi_proc.o
 scsi_mod-y += scsi_trace.o scsi_logging.o
 scsi_mod-$(CONFIG_PM)  += scsi_pm.o
+obj-$(CONFIG_SCSI_DH)  += scsi_dh.o
 
 hv_storvsc-y   := storvsc_drv.o
 
diff --git a/drivers/scsi/device_handler/Makefile 
b/drivers/scsi/device_handler/Makefile
index e1d2ea0..09866c5 100644
--- a/drivers/scsi/device_handler/Makefile
+++ b/drivers/scsi/device_handler/Makefile
@@ -1,7 +1,6 @@
 #
 # SCSI Device Handler
 #
-obj-$(CONFIG_SCSI_DH)  += scsi_dh.o
 obj-$(CONFIG_SCSI_DH_RDAC) += scsi_dh_rdac.o
 obj-$(CONFIG_SCSI_DH_HP_SW)+= scsi_dh_hp_sw.o
 obj-$(CONFIG_SCSI_DH_EMC)  += scsi_dh_emc.o
diff --git a/drivers/scsi/device_handler/scsi_dh.c 
b/drivers/scsi/device_handler/scsi_dh.c
deleted file mode 100644
index 5bd0af6..000
--- a/drivers/scsi/device_handler/scsi_dh.c
+++ /dev/null
@@ -1,570 +0,0 @@
-/*
- * SCSI device handler infrastruture.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * Copyright IBM Corporation, 2007
- *  Authors:
- *   Chandra Seetharaman 
- *   Mike Anderson 
- */
-
-#include 
-#include 
-#include 
-#include "../scsi_priv.h"
-
-static DEFINE_SPINLOCK(list_lock);
-static LIST_HEAD(scsi_dh_list);
-
-static struct scsi_device_handler *__scsi_dh_lookup(const char *name)
-{
-   struct scsi_device_handler *tmp, *found = NULL;
-
-   spin_lock(&list_lock);
-   list_for_each_entry(tmp, &scsi_dh_list, list) {
-   if (!strncmp(tmp->name, name, strlen(tmp->name))) {
-   found = tmp;
-   break;
-   }
-   }
-   spin_unlock(&list_lock);
-   return found;
-}
-
-static struct scsi_device_handler *scsi_dh_lookup(const char *name)
-{
-   struct scsi_device_handler *dh;
-
-   dh = __scsi_dh_lookup(name);
-   if (!dh) {
-   request_module(name);
-   dh = __scsi_dh_lookup(name);
-   }
-
-   return dh;
-}
-
-/*
- * device_handler_match_function - Match a device handler to a device
- * @sdev - SCSI device to be tested
- *
- * Tests @sdev against the match function of all registered device_handler.
- * Returns the found device handler or NULL if not found.
- */
-static struct scsi_device_handler *
-device_handler_match_function(struct scsi_device *sdev)
-{
-   struct scsi_device_handler *tmp_dh, *found_dh = NULL;
-
-   spin_lock(&list_lock);
-   list_for_each_entry(tmp_dh, &scsi_dh_list, list) {
-   if (tmp_dh->match && tmp_dh->match(sdev)) {
-   found_dh = tmp_dh;
-   break;
-   }
-   }
-   spin_unlock(&list_lock);
-   return found_dh;
-}
-
-/*
- * device_handler_match - Attach a device handler to a device
- * @scsi_dh - The device handler to match against or NULL
- * @sdev - SCSI device to be tested against @scsi_dh
- *
- * Tests @sdev against the device handler @scsi_dh or against
- * all registered device_handler if @scsi_dh == NULL.
- * Returns the found device handler or NULL if not found.
- */
-static struct scsi_device_handler *
-device_handler_match(struct scsi_device_handler *scsi_dh,
-struct scsi_device *sdev)
-{
-   struct scsi_device_handler *found_dh;
-
-   found_dh = device_handler_match_function(sdev);
-
-   if (scsi_dh && found_dh != scsi_dh)
-   found_dh = NULL;
-
-   return found_dh;
-}
-
-/*
- * scsi_dh_handler_attach - Att

[PATCH 06/10] scsi_dh: kill struct scsi_dh_data

2015-08-27 Thread Hannes Reinecke
From: Christoph Hellwig 

Add a ->handler and a ->handler_data field to struct scsi_device and kill
this indirection.  Also move struct scsi_device_handler to scsi_dh.h so that
changes to it don't require rebuilding every SCSI LLDD.

Signed-off-by: Christoph Hellwig 
Reviewed-by: Martin K. Petersen 
Reviewed-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c  | 25 --
 drivers/scsi/device_handler/scsi_dh_emc.c   | 29 +--
 drivers/scsi/device_handler/scsi_dh_hp_sw.c | 25 --
 drivers/scsi/device_handler/scsi_dh_rdac.c  | 30 +---
 drivers/scsi/scsi_dh.c  | 75 +++--
 drivers/scsi/scsi_error.c   |  6 +--
 drivers/scsi/scsi_lib.c |  6 +--
 include/scsi/scsi_device.h  | 25 ++
 include/scsi/scsi_dh.h  | 17 +++
 9 files changed, 98 insertions(+), 140 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index ace2457..cc2773b 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -62,7 +62,6 @@
 #define ALUA_OPTIMIZE_STPG 1
 
 struct alua_dh_data {
-   struct scsi_dh_data dh_data;
int group_id;
int rel_port;
int tpgs;
@@ -86,11 +85,6 @@ struct alua_dh_data {
 static char print_alua_state(int);
 static int alua_check_sense(struct scsi_device *, struct scsi_sense_hdr *);
 
-static inline struct alua_dh_data *get_alua_data(struct scsi_device *sdev)
-{
-   return container_of(sdev->scsi_dh_data, struct alua_dh_data, dh_data);
-}
-
 static int realloc_buffer(struct alua_dh_data *h, unsigned len)
 {
if (h->buff && h->buff != h->inq)
@@ -708,7 +702,7 @@ out:
  */
 static int alua_set_params(struct scsi_device *sdev, const char *params)
 {
-   struct alua_dh_data *h = get_alua_data(sdev);
+   struct alua_dh_data *h = sdev->handler_data;
unsigned int optimize = 0, argc;
const char *p = params;
int result = SCSI_DH_OK;
@@ -746,7 +740,7 @@ MODULE_PARM_DESC(optimize_stpg, "Allow use of a 
non-optimized path, rather than
 static int alua_activate(struct scsi_device *sdev,
activate_complete fn, void *data)
 {
-   struct alua_dh_data *h = get_alua_data(sdev);
+   struct alua_dh_data *h = sdev->handler_data;
int err = SCSI_DH_OK;
int stpg = 0;
 
@@ -804,7 +798,7 @@ out:
  */
 static int alua_prep_fn(struct scsi_device *sdev, struct request *req)
 {
-   struct alua_dh_data *h = get_alua_data(sdev);
+   struct alua_dh_data *h = sdev->handler_data;
int ret = BLKPREP_OK;
 
if (h->state == TPGS_STATE_TRANSITIONING)
@@ -823,14 +817,14 @@ static int alua_prep_fn(struct scsi_device *sdev, struct 
request *req)
  * alua_bus_attach - Attach device handler
  * @sdev: device to be attached to
  */
-static struct scsi_dh_data *alua_bus_attach(struct scsi_device *sdev)
+static int alua_bus_attach(struct scsi_device *sdev)
 {
struct alua_dh_data *h;
int err;
 
h = kzalloc(sizeof(*h) , GFP_KERNEL);
if (!h)
-   return ERR_PTR(-ENOMEM);
+   return -ENOMEM;
h->tpgs = TPGS_MODE_UNINITIALIZED;
h->state = TPGS_STATE_OPTIMIZED;
h->group_id = -1;
@@ -843,11 +837,11 @@ static struct scsi_dh_data *alua_bus_attach(struct 
scsi_device *sdev)
if (err != SCSI_DH_OK && err != SCSI_DH_DEV_OFFLINED)
goto failed;
 
-   sdev_printk(KERN_NOTICE, sdev, "%s: Attached\n", ALUA_DH_NAME);
-   return &h->dh_data;
+   sdev->handler_data = h;
+   return 0;
 failed:
kfree(h);
-   return ERR_PTR(-EINVAL);
+   return -EINVAL;
 }
 
 /*
@@ -856,10 +850,11 @@ failed:
  */
 static void alua_bus_detach(struct scsi_device *sdev)
 {
-   struct alua_dh_data *h = get_alua_data(sdev);
+   struct alua_dh_data *h = sdev->handler_data;
 
if (h->buff && h->inq != h->buff)
kfree(h->buff);
+   sdev->handler_data = NULL;
kfree(h);
 }
 
diff --git a/drivers/scsi/device_handler/scsi_dh_emc.c 
b/drivers/scsi/device_handler/scsi_dh_emc.c
index fd31e67..e6fb97c 100644
--- a/drivers/scsi/device_handler/scsi_dh_emc.c
+++ b/drivers/scsi/device_handler/scsi_dh_emc.c
@@ -72,7 +72,6 @@ static const char * lun_state[] =
 };
 
 struct clariion_dh_data {
-   struct scsi_dh_data dh_data;
/*
 * Flags:
 *  CLARIION_SHORT_TRESPASS
@@ -114,13 +113,6 @@ struct clariion_dh_data {
int current_sp;
 };
 
-static inline struct clariion_dh_data
-   *get_clariion_data(struct scsi_device *sdev)
-{
-   return container_of(sdev->scsi_dh_data, struct clariion_dh_data,
-   dh_data);
-}
-
 /*
  * Parse MODE_SELECT cmd reply.
  */
@@ -450,7 +442,7 @@ static int clariion

[PATCH 04/10] scsi_dh: integrate into the core SCSI code

2015-08-27 Thread Hannes Reinecke
From: Christoph Hellwig 

Stop building scsi_dh as a separate module and integrate it fully into the
core SCSI code with explicit callouts at bus scan time.  For now the
callouts are placed at the same point as the old bus notifiers were called,
but in the future we will be able to look at ALUA INQUIRY data earlier on.

Note that this also means that the device handler modules need to be loaded
by the time we scan the bus.  The next patches will add support for
autoloading device handlers at bus scan time to make sure they are always
loaded if they are enabled in the kernel config.

Signed-off-by: Christoph Hellwig 
Reviewed-by: Martin K. Petersen 
Reviewed-by: Hannes Reinecke 
Acked-by: Mike Snitzer 
---
 drivers/scsi/Makefile   |   2 +-
 drivers/scsi/device_handler/Kconfig |   2 +-
 drivers/scsi/scsi_dh.c  | 183 +++-
 drivers/scsi/scsi_priv.h|   9 ++
 drivers/scsi/scsi_sysfs.c   |  10 ++
 include/scsi/scsi_dh.h  |   2 +-
 6 files changed, 34 insertions(+), 174 deletions(-)

diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 22f54b0..ef260bb 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -171,7 +171,7 @@ scsi_mod-$(CONFIG_SYSCTL)   += scsi_sysctl.o
 scsi_mod-$(CONFIG_SCSI_PROC_FS)+= scsi_proc.o
 scsi_mod-y += scsi_trace.o scsi_logging.o
 scsi_mod-$(CONFIG_PM)  += scsi_pm.o
-obj-$(CONFIG_SCSI_DH)  += scsi_dh.o
+scsi_mod-$(CONFIG_SCSI_DH) += scsi_dh.o
 
 hv_storvsc-y   := storvsc_drv.o
 
diff --git a/drivers/scsi/device_handler/Kconfig 
b/drivers/scsi/device_handler/Kconfig
index 69abd0a..e5647d5 100644
--- a/drivers/scsi/device_handler/Kconfig
+++ b/drivers/scsi/device_handler/Kconfig
@@ -3,7 +3,7 @@
 #
 
 menuconfig SCSI_DH
-   tristate "SCSI Device Handlers"
+   bool "SCSI Device Handlers"
depends on SCSI
default n
help
diff --git a/drivers/scsi/scsi_dh.c b/drivers/scsi/scsi_dh.c
index 3c06c72..2d6a8bd 100644
--- a/drivers/scsi/scsi_dh.c
+++ b/drivers/scsi/scsi_dh.c
@@ -57,15 +57,8 @@ static struct scsi_device_handler *scsi_dh_lookup(const char 
*name)
return dh;
 }
 
-/*
- * device_handler_match_function - Match a device handler to a device
- * @sdev - SCSI device to be tested
- *
- * Tests @sdev against the match function of all registered device_handler.
- * Returns the found device handler or NULL if not found.
- */
 static struct scsi_device_handler *
-device_handler_match_function(struct scsi_device *sdev)
+device_handler_match(struct scsi_device *sdev)
 {
struct scsi_device_handler *tmp_dh, *found_dh = NULL;
 
@@ -81,29 +74,6 @@ device_handler_match_function(struct scsi_device *sdev)
 }
 
 /*
- * device_handler_match - Attach a device handler to a device
- * @scsi_dh - The device handler to match against or NULL
- * @sdev - SCSI device to be tested against @scsi_dh
- *
- * Tests @sdev against the device handler @scsi_dh or against
- * all registered device_handler if @scsi_dh == NULL.
- * Returns the found device handler or NULL if not found.
- */
-static struct scsi_device_handler *
-device_handler_match(struct scsi_device_handler *scsi_dh,
-struct scsi_device *sdev)
-{
-   struct scsi_device_handler *found_dh;
-
-   found_dh = device_handler_match_function(sdev);
-
-   if (scsi_dh && found_dh != scsi_dh)
-   found_dh = NULL;
-
-   return found_dh;
-}
-
-/*
  * scsi_dh_handler_attach - Attach a device handler to a device
  * @sdev - SCSI device the device handler should attach to
  * @scsi_dh - The device handler to attach
@@ -211,119 +181,26 @@ static struct device_attribute scsi_dh_state_attr =
__ATTR(dh_state, S_IRUGO | S_IWUSR, show_dh_state,
   store_dh_state);
 
-/*
- * scsi_dh_sysfs_attr_add - Callback for scsi_init_dh
- */
-static int scsi_dh_sysfs_attr_add(struct device *dev, void *data)
+int scsi_dh_add_device(struct scsi_device *sdev)
 {
-   struct scsi_device *sdev;
+   struct scsi_device_handler *devinfo;
int err;
 
-   if (!scsi_is_sdev_device(dev))
-   return 0;
-
-   sdev = to_scsi_device(dev);
-
-   err = device_create_file(&sdev->sdev_gendev,
-&scsi_dh_state_attr);
-
-   return 0;
-}
-
-/*
- * scsi_dh_sysfs_attr_remove - Callback for scsi_exit_dh
- */
-static int scsi_dh_sysfs_attr_remove(struct device *dev, void *data)
-{
-   struct scsi_device *sdev;
-
-   if (!scsi_is_sdev_device(dev))
-   return 0;
-
-   sdev = to_scsi_device(dev);
-
-   device_remove_file(&sdev->sdev_gendev,
-  &scsi_dh_state_attr);
-
-   return 0;
-}
+   err = device_create_file(&sdev->sdev_gendev, &scsi_dh_state_attr);
+   if (err)
+   return err;
 
-/*
- * scsi_dh_notifier - notifier chain callback
- */
-static int scsi_dh_notifier(struct notifier_block *nb,
-

[PATCH 00/10] Integrate scsi_dh better into the scsi core V4

2015-08-27 Thread Hannes Reinecke
This series ties scsi_dh deeper into the scsi core, and fixes all kinds
of issues in it, most importantly the race between using and detaching
device handlers.

Changes since V1:
  - updated comments / strings based on review feedback
  - moved scsi_dh.c to drivers/scsi to fix the srcdir = objdir build
  - changed the old patch 2 to have saner handling of mismatching device
handlers in dm.
  - dropped patch 1: not having a hw handler is fine if we don't plan to
change it anyway
  - dropped patch 3: not necessary anymore.
Changes since V2:
  - Fixup issues during attaching device_handler from dm-multipath
  - Add patch to clarify scsi_dh_activate() error codes
Changes since V3:
  - Fixup minor bugs discovered during testing
  - Fixup patch description

Christoph Hellwig (8):
  dm-mpath, scsi_dh: don't let dm detach device handlers
  dm-mpath, scsi_dh: request scsi_dh modules in scsi_dh, not dm-mpath
  scsi_dh: move to drivers/scsi
  scsi_dh: integrate into the core SCSI code
  scsi_dh: move device matching to the core code
  scsi_dh: kill struct scsi_dh_data
  scsi_dh: add a common helper to get a scsi_device from a request_queue
  scsi_dh: don't allow to detach device handlers at runtime

Hannes Reinecke (2):
  scsi_dh: return SCSI_DH_NOTCONN in scsi_dh_activate()
  scsi_dh: move 'dh_state' sysfs attribute to generic code

 drivers/md/dm-mpath.c   |  27 +-
 drivers/scsi/Makefile   |   1 +
 drivers/scsi/device_handler/Kconfig |   2 +-
 drivers/scsi/device_handler/Makefile|   1 -
 drivers/scsi/device_handler/scsi_dh.c   | 621 
 drivers/scsi/device_handler/scsi_dh_alua.c  |  31 +-
 drivers/scsi/device_handler/scsi_dh_emc.c   |  58 +--
 drivers/scsi/device_handler/scsi_dh_hp_sw.c |  55 +--
 drivers/scsi/device_handler/scsi_dh_rdac.c  |  80 +---
 drivers/scsi/scsi_dh.c  | 371 +
 drivers/scsi/scsi_error.c   |   6 +-
 drivers/scsi/scsi_lib.c |   6 +-
 drivers/scsi/scsi_priv.h|   9 +
 drivers/scsi/scsi_sysfs.c   |  68 +++
 include/scsi/scsi_device.h  |  27 +-
 include/scsi/scsi_dh.h  |  29 +-
 16 files changed, 527 insertions(+), 865 deletions(-)
 delete mode 100644 drivers/scsi/device_handler/scsi_dh.c
 create mode 100644 drivers/scsi/scsi_dh.c

-- 
1.8.5.6

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 10/10] scsi_dh: move 'dh_state' sysfs attribute to generic code

2015-08-27 Thread Hannes Reinecke
As scsi_dh.c is now always compiled in we should be moving
the 'dh_state' attribute to the generic code.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/scsi_dh.c| 67 +--
 drivers/scsi/scsi_sysfs.c | 58 
 2 files changed, 59 insertions(+), 66 deletions(-)

diff --git a/drivers/scsi/scsi_dh.c b/drivers/scsi/scsi_dh.c
index 2d93bc9..1584080 100644
--- a/drivers/scsi/scsi_dh.c
+++ b/drivers/scsi/scsi_dh.c
@@ -153,75 +153,11 @@ static void scsi_dh_handler_detach(struct scsi_device 
*sdev)
module_put(sdev->handler->module);
 }
 
-/*
- * Functions for sysfs attribute 'dh_state'
- */
-static ssize_t
-store_dh_state(struct device *dev, struct device_attribute *attr,
-  const char *buf, size_t count)
-{
-   struct scsi_device *sdev = to_scsi_device(dev);
-   struct scsi_device_handler *scsi_dh;
-   int err = -EINVAL;
-
-   if (sdev->sdev_state == SDEV_CANCEL ||
-   sdev->sdev_state == SDEV_DEL)
-   return -ENODEV;
-
-   if (!sdev->handler) {
-   /*
-* Attach to a device handler
-*/
-   if (!(scsi_dh = scsi_dh_lookup(buf)))
-   return err;
-   err = scsi_dh_handler_attach(sdev, scsi_dh);
-   } else {
-   if (!strncmp(buf, "detach", 6)) {
-   /*
-* Detach from a device handler
-*/
-   sdev_printk(KERN_WARNING, sdev,
-   "can't detach handler %s.\n",
-   sdev->handler->name);
-   err = -EINVAL;
-   } else if (!strncmp(buf, "activate", 8)) {
-   /*
-* Activate a device handler
-*/
-   if (sdev->handler->activate)
-   err = sdev->handler->activate(sdev, NULL, NULL);
-   else
-   err = 0;
-   }
-   }
-
-   return err<0?err:count;
-}
-
-static ssize_t
-show_dh_state(struct device *dev, struct device_attribute *attr, char *buf)
-{
-   struct scsi_device *sdev = to_scsi_device(dev);
-
-   if (!sdev->handler)
-   return snprintf(buf, 20, "detached\n");
-
-   return snprintf(buf, 20, "%s\n", sdev->handler->name);
-}
-
-static struct device_attribute scsi_dh_state_attr =
-   __ATTR(dh_state, S_IRUGO | S_IWUSR, show_dh_state,
-  store_dh_state);
-
 int scsi_dh_add_device(struct scsi_device *sdev)
 {
struct scsi_device_handler *devinfo = NULL;
const char *drv;
-   int err;
-
-   err = device_create_file(&sdev->sdev_gendev, &scsi_dh_state_attr);
-   if (err)
-   return err;
+   int err = 0;
 
drv = scsi_dh_find_driver(sdev);
if (drv)
@@ -235,7 +171,6 @@ void scsi_dh_remove_device(struct scsi_device *sdev)
 {
if (sdev->handler)
scsi_dh_handler_detach(sdev);
-   device_remove_file(&sdev->sdev_gendev, &scsi_dh_state_attr);
 }
 
 /*
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index b89..5d64c3f 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -875,6 +876,60 @@ sdev_show_function(queue_depth, "%d\n");
 static DEVICE_ATTR(queue_depth, S_IRUGO | S_IWUSR, sdev_show_queue_depth,
   sdev_store_queue_depth);
 
+#ifdef CONFIG_SCSI_DH
+static ssize_t
+sdev_show_dh_state(struct device *dev, struct device_attribute *attr,
+  char *buf)
+{
+   struct scsi_device *sdev = to_scsi_device(dev);
+
+   if (!sdev->handler)
+   return snprintf(buf, 20, "detached\n");
+
+   return snprintf(buf, 20, "%s\n", sdev->handler->name);
+}
+
+static ssize_t
+sdev_store_dh_state(struct device *dev, struct device_attribute *attr,
+   const char *buf, size_t count)
+{
+   struct scsi_device *sdev = to_scsi_device(dev);
+   int err = -EINVAL;
+
+   if (sdev->sdev_state == SDEV_CANCEL ||
+   sdev->sdev_state == SDEV_DEL)
+   return -ENODEV;
+
+   if (!sdev->handler) {
+   /*
+* Attach to a device handler
+*/
+   err = scsi_dh_attach(sdev->request_queue, buf);
+   } else if (!strncmp(buf, "activate", 8)) {
+   /*
+* Activate a device handler
+*/
+   if (sdev->handler->activate)
+   err = sdev->handler->activate(sdev, NULL, NULL);
+   else
+   err = 0;
+   } else if (!strncmp(buf, "detach", 6)) {
+   /*
+* Detach from a device handler
+*/
+   sdev_printk(KERN_WARNING, 

[PATCH 02/10] dm-mpath, scsi_dh: request scsi_dh modules in scsi_dh, not dm-mpath

2015-08-27 Thread Hannes Reinecke
From: Christoph Hellwig 

This way we can reused the same code any attachment method, not just those
requested from dm-mpath.

Signed-off-by: Christoph Hellwig 
Reviewed-by: Martin K. Petersen 
Reviewed-by: Hannes Reinecke 
Acked-by: Mike Snitzer 
---
 drivers/md/dm-mpath.c |  6 --
 drivers/scsi/device_handler/scsi_dh.c | 35 ++-
 include/scsi/scsi_dh.h|  5 -
 3 files changed, 18 insertions(+), 28 deletions(-)

diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index a9f58fd..5a67671 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -725,12 +725,6 @@ static int parse_hw_handler(struct dm_arg_set *as, struct 
multipath *m)
return 0;
 
m->hw_handler_name = kstrdup(dm_shift_arg(as), GFP_KERNEL);
-   if (!try_then_request_module(scsi_dh_handler_exist(m->hw_handler_name),
-"scsi_dh_%s", m->hw_handler_name)) {
-   ti->error = "unknown hardware handler type";
-   ret = -EINVAL;
-   goto fail;
-   }
 
if (hw_argc > 1) {
char *p;
diff --git a/drivers/scsi/device_handler/scsi_dh.c 
b/drivers/scsi/device_handler/scsi_dh.c
index 869b5bd..5bd0af6 100644
--- a/drivers/scsi/device_handler/scsi_dh.c
+++ b/drivers/scsi/device_handler/scsi_dh.c
@@ -29,7 +29,7 @@
 static DEFINE_SPINLOCK(list_lock);
 static LIST_HEAD(scsi_dh_list);
 
-static struct scsi_device_handler *get_device_handler(const char *name)
+static struct scsi_device_handler *__scsi_dh_lookup(const char *name)
 {
struct scsi_device_handler *tmp, *found = NULL;
 
@@ -44,6 +44,19 @@ static struct scsi_device_handler *get_device_handler(const 
char *name)
return found;
 }
 
+static struct scsi_device_handler *scsi_dh_lookup(const char *name)
+{
+   struct scsi_device_handler *dh;
+
+   dh = __scsi_dh_lookup(name);
+   if (!dh) {
+   request_module(name);
+   dh = __scsi_dh_lookup(name);
+   }
+
+   return dh;
+}
+
 /*
  * device_handler_match_function - Match a device handler to a device
  * @sdev - SCSI device to be tested
@@ -158,7 +171,7 @@ store_dh_state(struct device *dev, struct device_attribute 
*attr,
/*
 * Attach to a device handler
 */
-   if (!(scsi_dh = get_device_handler(buf)))
+   if (!(scsi_dh = scsi_dh_lookup(buf)))
return err;
err = scsi_dh_handler_attach(sdev, scsi_dh);
} else {
@@ -322,8 +335,7 @@ static int scsi_dh_notifier_remove(struct device *dev, void 
*data)
  */
 int scsi_register_device_handler(struct scsi_device_handler *scsi_dh)
 {
-
-   if (get_device_handler(scsi_dh->name))
+   if (__scsi_dh_lookup(scsi_dh->name))
return -EBUSY;
 
if (!scsi_dh->attach || !scsi_dh->detach)
@@ -350,7 +362,7 @@ EXPORT_SYMBOL_GPL(scsi_register_device_handler);
 int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh)
 {
 
-   if (!get_device_handler(scsi_dh->name))
+   if (!__scsi_dh_lookup(scsi_dh->name))
return -ENODEV;
 
bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh,
@@ -455,17 +467,6 @@ int scsi_dh_set_params(struct request_queue *q, const char 
*params)
 EXPORT_SYMBOL_GPL(scsi_dh_set_params);
 
 /*
- * scsi_dh_handler_exist - Return TRUE(1) if a device handler exists for
- * the given name. FALSE(0) otherwise.
- * @name - name of the device handler.
- */
-int scsi_dh_handler_exist(const char *name)
-{
-   return (get_device_handler(name) != NULL);
-}
-EXPORT_SYMBOL_GPL(scsi_dh_handler_exist);
-
-/*
  * scsi_dh_attach - Attach device handler
  * @q - Request queue that is associated with the scsi_device
  *  the handler should be attached to
@@ -478,7 +479,7 @@ int scsi_dh_attach(struct request_queue *q, const char 
*name)
struct scsi_device_handler *scsi_dh;
int err = 0;
 
-   scsi_dh = get_device_handler(name);
+   scsi_dh = scsi_dh_lookup(name);
if (!scsi_dh)
return -EINVAL;
 
diff --git a/include/scsi/scsi_dh.h b/include/scsi/scsi_dh.h
index 99c9196..966b921 100644
--- a/include/scsi/scsi_dh.h
+++ b/include/scsi/scsi_dh.h
@@ -57,7 +57,6 @@ enum {
 };
 #if defined(CONFIG_SCSI_DH) || defined(CONFIG_SCSI_DH_MODULE)
 extern int scsi_dh_activate(struct request_queue *, activate_complete, void *);
-extern int scsi_dh_handler_exist(const char *);
 extern int scsi_dh_attach(struct request_queue *, const char *);
 extern const char *scsi_dh_attached_handler_name(struct request_queue *, 
gfp_t);
 extern int scsi_dh_set_params(struct request_queue *, const char *);
@@ -68,10 +67,6 @@ static inline int scsi_dh_activate(struct request_queue *req,
fn(data, 0);
return 0;
 }
-static inline int scsi_dh_handler_exist(const char *name)
-{
-   return 0;
-}
 static inline int scsi_dh_attach(struct request_queue *re

Re: [PATCH v1 14/15] scsi: ufs: commit descriptors before setting the doorbell

2015-08-27 Thread ygardi
>> On Aug 21, 2015 3:10 PM, "Yaniv Gardi"  wrote:
>>>
>>> Add a write memory barrier to make sure descriptors prepared are
>>> actually
>>> written to memory before ringing the doorbell. We have also added the
>>> write memory barrier after ringing the doorbell register so that
>>> controller sees the new request immediately.
>>>
>>> Signed-off-by: Yaniv Gardi 
>>>
>>> ---
>>>  drivers/scsi/ufs/ufshcd.c | 6 ++
>>>  1 file changed, 6 insertions(+)
>>>
>>> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
>>> index fef0660..876148b 100644
>>> --- a/drivers/scsi/ufs/ufshcd.c
>>> +++ b/drivers/scsi/ufs/ufshcd.c
>>> @@ -833,6 +833,8 @@ void ufshcd_send_command(struct ufs_hba *hba,
>>> unsigned int task_tag)
>>> ufshcd_clk_scaling_start_busy(hba);
>>> __set_bit(task_tag, &hba->outstanding_reqs);
>>> ufshcd_writel(hba, 1 << task_tag,
>>> REG_UTP_TRANSFER_REQ_DOOR_BELL);
>>> +   /* Make sure that doorbell is committed immediately */
>>> +   wmb();
>>
>> Is this really necessary? Is there a measurable difference?
>
> I'm not sure if there is a measurable difference, but as the Door-Bell
> register is the one that actually responsible for the HW execution of the
> requests, anyhow, it's recommended to its value will be written
> instantly to the memory.
>
> Also, as the Interrupt context reads this register, and compare it to the
> SW mirroring value (hba->outstanding_reqs) in order to realize what
> requests are already completed, it's important to get the correct value
> by reading this register, otherwise we might realize a request completion
> while it was never even submitted.
>
>>
>>>  }
>>>
>>>  /**
>>> @@ -1418,6 +1420,8 @@ static int ufshcd_queuecommand(struct Scsi_Host
>>> *host, struct scsi_cmnd *cmd)
>>> goto out;
>>> }
>>>
>>> +   /* Make sure descriptors are ready before ringing the doorbell
>>> */
>>> +   wmb();
>>
>> The writel for the doorbell will do a barrier first. (I didn't check
>> what exactly ufshcd_writel does, but that is why I don't like these
>> private access wrappers.)

the barrier here is important and a must.
before it we prepare descriptors.
after it we write to DOOR-BELL.
(and after the DOOR-BELL we have another one.)
if we remove it, we might get the DOOR-BELL written, before the
descriptors written.




>>
>>> /* issue command to the controller */
>>> spin_lock_irqsave(hba->host->host_lock, flags);
>>> ufshcd_send_command(hba, tag);
>>> @@ -1627,6 +1631,8 @@ static int ufshcd_exec_dev_cmd(struct ufs_hba
>>> *hba,
>>>
>>> hba->dev_cmd.complete = &wait;
>>>
>>> +   /* Make sure descriptors are ready before ringing the doorbell
>>> */
>>> +   wmb();
>>> spin_lock_irqsave(hba->host->host_lock, flags);
>>> ufshcd_send_command(hba, tag);
>>> spin_unlock_irqrestore(hba->host->host_lock, flags);
>>> --
>>> 1.8.5.2
>>>
>>> --
>>> QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a
>>> member of Code Aurora Forum, hosted by The Linux Foundation
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
>> the body of a message to majord...@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 09/23] scsi_dh_alua: use unaligned access macros

2015-08-27 Thread Hannes Reinecke
Use 'get_unaligned_XX' and 'put_unaligned_XX' instead of
open-coding it.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 23 ---
 1 file changed, 8 insertions(+), 15 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index 9d8fc53..0636721 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -153,10 +154,7 @@ static unsigned submit_rtpg(struct scsi_device *sdev, 
struct alua_dh_data *h)
rq->cmd[1] = MI_REPORT_TARGET_PGS | MI_EXT_HDR_PARAM_FMT;
else
rq->cmd[1] = MI_REPORT_TARGET_PGS;
-   rq->cmd[6] = (h->bufflen >> 24) & 0xff;
-   rq->cmd[7] = (h->bufflen >> 16) & 0xff;
-   rq->cmd[8] = (h->bufflen >>  8) & 0xff;
-   rq->cmd[9] = h->bufflen & 0xff;
+   put_unaligned_be32(h->bufflen, &rq->cmd[6]);
rq->cmd_len = COMMAND_SIZE(MAINTENANCE_IN);
 
rq->sense = h->sense;
@@ -239,8 +237,7 @@ static unsigned submit_stpg(struct alua_dh_data *h)
/* Prepare the data buffer */
memset(h->buff, 0, stpg_len);
h->buff[4] = TPGS_STATE_OPTIMIZED & 0x0f;
-   h->buff[6] = (h->group_id >> 8) & 0xff;
-   h->buff[7] = h->group_id & 0xff;
+   put_unaligned_be16(h->group_id, &h->buff[6]);
 
rq = get_alua_req(sdev, h->buff, stpg_len, WRITE);
if (!rq)
@@ -249,10 +246,7 @@ static unsigned submit_stpg(struct alua_dh_data *h)
/* Prepare the command. */
rq->cmd[0] = MAINTENANCE_OUT;
rq->cmd[1] = MO_SET_TARGET_PGS;
-   rq->cmd[6] = (stpg_len >> 24) & 0xff;
-   rq->cmd[7] = (stpg_len >> 16) & 0xff;
-   rq->cmd[8] = (stpg_len >>  8) & 0xff;
-   rq->cmd[9] = stpg_len & 0xff;
+   put_unaligned_be32(stpg_len, &rq->cmd[6]);
rq->cmd_len = COMMAND_SIZE(MAINTENANCE_OUT);
 
rq->sense = h->sense;
@@ -341,11 +335,11 @@ static int alua_check_vpd(struct scsi_device *sdev, 
struct alua_dh_data *h)
switch (d[1] & 0xf) {
case 0x4:
/* Relative target port */
-   h->rel_port = (d[6] << 8) + d[7];
+   h->rel_port = get_unaligned_be16(&d[6]);
break;
case 0x5:
/* Target port group */
-   h->group_id = (d[6] << 8) + d[7];
+   h->group_id = get_unaligned_be16(&d[6]);
break;
default:
break;
@@ -540,8 +534,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct 
alua_dh_data *h, int wait_
return SCSI_DH_IO;
}
 
-   len = (h->buff[0] << 24) + (h->buff[1] << 16) +
-   (h->buff[2] << 8) + h->buff[3] + 4;
+   len = get_unaligned_be32(&h->buff[0]) + 4;
 
if (len > h->bufflen) {
/* Resubmit with the correct length */
@@ -576,7 +569,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct 
alua_dh_data *h, int wait_
 k < len;
 k += off, ucp += off) {
 
-   if (h->group_id == (ucp[2] << 8) + ucp[3]) {
+   if (h->group_id == get_unaligned_be16(&ucp[2])) {
h->state = ucp[0] & 0x0f;
h->pref = ucp[0] >> 7;
valid_states = ucp[1];
-- 
1.8.5.6

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCHv4 00/23] asynchronous ALUA device handler

2015-08-27 Thread Hannes Reinecke
Hi all,

here is an update to the ALUA device handler. The main
features are:

- Topology discovery: the device handler creates a separate
  port_group structure, which is used to update all paths to
  the same port group. With that we achieve a significant
  reduction of the number of RTPGs.
- Asynchronous state update: The ALUA state is now updated
  from a workqueue item, so all concurrent RTPG calls are
  coaleasced. The ALUA state update is also triggered by
  sense codes indicating an ALUA state change.
- Use the existing vpd page 0x83 to detect device IDs

The patchset is relative to the V4 version of the scsi_dh update.
The entire tree can be found at

kernel/hare/scsi-devel branch alua.v4

on git.kernel.org

As usual, reviews and comments are welcome.

Changes to v1:
  - Split off rtpg workqueue into separate items
  - User per-port workqueues
  - Incorporate review from Bart
  - Incorporate review from hch
Changes to v2:
  - Fixup patch descriptions
  - Split off 'Improve error handling' patch
Changes to v3:
  - Implement generic 'scsi_vpd_lun_id()' function to parse vpd page 0x83

Hannes Reinecke (23):
  scsi_dh_alua: Disable ALUA handling for non-disk devices
  scsi_dh_alua: Use vpd_pg83 information
  scsi_dh_alua: improved logging
  scsi_dh_alua: use standard logging functions
  scsi_dh_alua: return standard SCSI return codes in submit_rtpg
  scsi_dh_alua: fixup description of stpg_endio()
  scsi: remove scsi_show_sense_hdr()
  scsi_dh_alua: use flag for RTPG extended header
  scsi_dh_alua: use unaligned access macros
  scsi_dh_alua: Pass buffer as function argument
  scsi_dh_alua: Make stpg synchronous
  scsi_dh_alua: switch to scsi_execute_req_flags()
  scsi_dh_alua: Use separate alua_port_group structure
  scsi_dh_alua: allocate RTPG buffer separately
  scsi_dh_alua: simplify sense code handling
  scsi: Add scsi_vpd_lun_id()
  scsi_dh_alua: use unique device id
  revert "scsi_dh_alua: ALUA hander attach should succeed while TPG is
transitioning"
  scsi_dh_alua: Use workqueue for RTPG
  scsi_dh_alua: Recheck state on unit attention
  scsi_dh_alua: update all port states
  scsi_dh_alua: Send TEST UNIT READY to poll for transitioning
  scsi_dh_alua: Update version to 2.0

 drivers/scsi/device_handler/scsi_dh_alua.c | 1140 +---
 drivers/scsi/scsi_lib.c|  121 +++
 include/scsi/scsi_dbg.h|2 -
 include/scsi/scsi_device.h |1 +
 4 files changed, 838 insertions(+), 426 deletions(-)

-- 
1.8.5.6

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 08/15] scsi: ufs: add retries to dme_peer get and set attribute

2015-08-27 Thread Yaniv Gardi
The dme_peer get/set attribute commands are prone to errors, therefore
we add three retries for the UIC command sending.
Error code returned from ufshcd_send_uic_cmd() is checked, and unless
it was successful or the retries have finished, another command will be
sent.

Signed-off-by: Lee Susman 
Signed-off-by: Yaniv Gardi 

---
 drivers/scsi/ufs/ufshcd.c | 40 +---
 1 file changed, 29 insertions(+), 11 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 217b5cf..8d5bdf0 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -69,6 +69,9 @@
 /* Task management command timeout */
 #define TM_CMD_TIMEOUT 100 /* msecs */
 
+/* maximum number of retries for a general UIC command  */
+#define UFS_UIC_COMMAND_RETRIES 3
+
 /* maximum number of link-startup retries */
 #define DME_LINKSTARTUP_RETRIES 3
 
@@ -2184,6 +2187,7 @@ int ufshcd_dme_set_attr(struct ufs_hba *hba, u32 attr_sel,
};
const char *set = action[!!peer];
int ret;
+   int retries = UFS_UIC_COMMAND_RETRIES;
 
uic_cmd.command = peer ?
UIC_CMD_DME_PEER_SET : UIC_CMD_DME_SET;
@@ -2191,10 +2195,18 @@ int ufshcd_dme_set_attr(struct ufs_hba *hba, u32 
attr_sel,
uic_cmd.argument2 = UIC_ARG_ATTR_TYPE(attr_set);
uic_cmd.argument3 = mib_val;
 
-   ret = ufshcd_send_uic_cmd(hba, &uic_cmd);
-   if (ret)
-   dev_err(hba->dev, "%s: attr-id 0x%x val 0x%x error code %d\n",
-   set, UIC_GET_ATTR_ID(attr_sel), mib_val, ret);
+   do {
+   /* for peer attributes we retry upon failure */
+   ret = ufshcd_send_uic_cmd(hba, &uic_cmd);
+   if (ret)
+   dev_dbg(hba->dev, "%s: attr-id 0x%x val 0x%x error code 
%d\n",
+   set, UIC_GET_ATTR_ID(attr_sel), mib_val, ret);
+   } while (ret && peer && --retries);
+
+   if (!retries)
+   dev_err(hba->dev, "%s: attr-id 0x%x val 0x%x failed %d 
retries\n",
+   set, UIC_GET_ATTR_ID(attr_sel), mib_val,
+   retries);
 
return ret;
 }
@@ -2219,6 +2231,7 @@ int ufshcd_dme_get_attr(struct ufs_hba *hba, u32 attr_sel,
};
const char *get = action[!!peer];
int ret;
+   int retries = UFS_UIC_COMMAND_RETRIES;
struct ufs_pa_layer_attr orig_pwr_info;
struct ufs_pa_layer_attr temp_pwr_info;
bool pwr_mode_change = false;
@@ -2249,14 +2262,19 @@ int ufshcd_dme_get_attr(struct ufs_hba *hba, u32 
attr_sel,
UIC_CMD_DME_PEER_GET : UIC_CMD_DME_GET;
uic_cmd.argument1 = attr_sel;
 
-   ret = ufshcd_send_uic_cmd(hba, &uic_cmd);
-   if (ret) {
-   dev_err(hba->dev, "%s: attr-id 0x%x error code %d\n",
-   get, UIC_GET_ATTR_ID(attr_sel), ret);
-   goto out;
-   }
+   do {
+   /* for peer attributes we retry upon failure */
+   ret = ufshcd_send_uic_cmd(hba, &uic_cmd);
+   if (ret)
+   dev_dbg(hba->dev, "%s: attr-id 0x%x error code %d\n",
+   get, UIC_GET_ATTR_ID(attr_sel), ret);
+   } while (ret && peer && --retries);
+
+   if (!retries)
+   dev_err(hba->dev, "%s: attr-id 0x%x failed %d retries\n",
+   get, UIC_GET_ATTR_ID(attr_sel), retries);
 
-   if (mib_val)
+   if (mib_val && !ret)
*mib_val = uic_cmd.argument3;
 
if (peer && (hba->quirks & UFSHCD_QUIRK_DME_PEER_ACCESS_AUTO_MODE)
-- 
1.8.5.2

-- 
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 15/15] scsi: ufs: add wrapper for retrying sending query attribute

2015-08-27 Thread Yaniv Gardi
Sometimes queries from the device might return a failure so it is
recommended to retry sending the query, before giving up.
This change adds a wrapper to retry sending a query attribute,
in cases where we need to wait longer, before we continue,
or before reporting a failure.

Signed-off-by: Yaniv Gardi 

---
 drivers/scsi/ufs/ufshcd.c | 51 ---
 1 file changed, 44 insertions(+), 7 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 024cc86..1c37a7d 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -1827,6 +1827,43 @@ out:
 }
 
 /**
+ * ufshcd_query_attr_retry() - API function for sending query
+ * attribute with retries
+ * @hba: per-adapter instance
+ * @opcode: attribute opcode
+ * @idn: attribute idn to access
+ * @index: index field
+ * @selector: selector field
+ * @attr_val: the attribute value after the query request
+ * completes
+ *
+ * Returns 0 for success, non-zero in case of failure
+*/
+static int ufshcd_query_attr_retry(struct ufs_hba *hba,
+   enum query_opcode opcode, enum attr_idn idn, u8 index, u8 selector,
+   u32 *attr_val)
+{
+   int ret = 0;
+   u32 retries;
+
+for (retries = QUERY_REQ_RETRIES; retries > 0; retries--) {
+   ret = ufshcd_query_attr(hba, opcode, idn, index,
+   selector, attr_val);
+   if (ret)
+   dev_dbg(hba->dev, "%s: failed with error %d, retries 
%d\n",
+   __func__, ret, retries);
+   else
+   break;
+   }
+
+   if (ret)
+   dev_err(hba->dev,
+   "%s: query attribute, idn %d, failed with error %d 
after %d retires\n",
+   __func__, idn, ret, QUERY_REQ_RETRIES);
+   return ret;
+}
+
+/**
  * ufshcd_query_descriptor - API function for sending descriptor requests
  * hba: per-adapter instance
  * opcode: attribute opcode
@@ -3407,7 +3444,7 @@ static int ufshcd_disable_ee(struct ufs_hba *hba, u16 
mask)
 
val = hba->ee_ctrl_mask & ~mask;
val &= 0x; /* 2 bytes */
-   err = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
+   err = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
QUERY_ATTR_IDN_EE_CONTROL, 0, 0, &val);
if (!err)
hba->ee_ctrl_mask &= ~mask;
@@ -3435,7 +3472,7 @@ static int ufshcd_enable_ee(struct ufs_hba *hba, u16 mask)
 
val = hba->ee_ctrl_mask | mask;
val &= 0x; /* 2 bytes */
-   err = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
+   err = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
QUERY_ATTR_IDN_EE_CONTROL, 0, 0, &val);
if (!err)
hba->ee_ctrl_mask |= mask;
@@ -3541,7 +3578,7 @@ static void  ufshcd_force_reset_auto_bkops(struct ufs_hba 
*hba)
 
 static inline int ufshcd_get_bkops_status(struct ufs_hba *hba, u32 *status)
 {
-   return ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR,
+   return ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_READ_ATTR,
QUERY_ATTR_IDN_BKOPS_STATUS, 0, 0, status);
 }
 
@@ -3604,7 +3641,7 @@ static int ufshcd_urgent_bkops(struct ufs_hba *hba)
 
 static inline int ufshcd_get_ee_status(struct ufs_hba *hba, u32 *status)
 {
-   return ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR,
+   return ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_READ_ATTR,
QUERY_ATTR_IDN_EE_STATUS, 0, 0, status);
 }
 
@@ -4360,9 +4397,9 @@ static void ufshcd_init_icc_levels(struct ufs_hba *hba)
dev_dbg(hba->dev, "%s: setting icc_level 0x%x",
__func__, hba->init_prefetch_data.icc_level);
 
-   ret = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
-   QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0,
-   &hba->init_prefetch_data.icc_level);
+   ret = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
+   QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0,
+   &hba->init_prefetch_data.icc_level);
 
if (ret)
dev_err(hba->dev,
-- 
1.8.5.2

-- 
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 14/15] scsi: ufs: commit descriptors before setting the doorbell

2015-08-27 Thread Yaniv Gardi
Add a write memory barrier to make sure descriptors prepared are actually
written to memory before ringing the doorbell. We have also added the
write memory barrier after ringing the doorbell register so that
controller sees the new request immediately.

Signed-off-by: Gilad Broner 
Signed-off-by: Subhash Jadavani 
Signed-off-by: Yaniv Gardi 

---
 drivers/scsi/ufs/ufshcd.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 298511a..024cc86 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -833,6 +833,8 @@ void ufshcd_send_command(struct ufs_hba *hba, unsigned int 
task_tag)
ufshcd_clk_scaling_start_busy(hba);
__set_bit(task_tag, &hba->outstanding_reqs);
ufshcd_writel(hba, 1 << task_tag, REG_UTP_TRANSFER_REQ_DOOR_BELL);
+   /* Make sure that doorbell is committed immediately */
+   wmb();
 }
 
 /**
@@ -1418,6 +1420,8 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, 
struct scsi_cmnd *cmd)
goto out;
}
 
+   /* Make sure descriptors are ready before ringing the doorbell */
+   wmb();
/* issue command to the controller */
spin_lock_irqsave(hba->host->host_lock, flags);
ufshcd_send_command(hba, tag);
@@ -1627,6 +1631,8 @@ static int ufshcd_exec_dev_cmd(struct ufs_hba *hba,
 
hba->dev_cmd.complete = &wait;
 
+   /* Make sure descriptors are ready before ringing the doorbell */
+   wmb();
spin_lock_irqsave(hba->host->host_lock, flags);
ufshcd_send_command(hba, tag);
spin_unlock_irqrestore(hba->host->host_lock, flags);
-- 
1.8.5.2

-- 
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 13/15] scsi: ufs: add missing memory barriers

2015-08-27 Thread Yaniv Gardi
Performing several writes to UFS host controller registers has
no gurrantee of ordering, so we must make sure register writes
to setup request list base address etc. are performed before the
run/stop register is enabled.
In addition, when setting up a task request, we must make sure
the updating of descriptors takes places before ringing the
doorbell, similarly to setting up a transfer request.

Signed-off-by: Gilad Broner 
Signed-off-by: Yaniv Gardi 

---
 drivers/scsi/ufs/ufshcd.c | 21 +++--
 1 file changed, 15 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index fc2a52d..298511a 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -401,11 +401,9 @@ static inline int ufshcd_get_lists_status(u32 reg)
 *  1   UTRLRDY
 *  2   UTMRLRDY
 *  3   UCRDY
-*  4   HEI
-*  5   DEI
-* 6-7  reserved
+* 4-7  reserved
 */
-   return (((reg) & (0xFF)) >> 1) ^ (0x07);
+   return ((reg & 0xFF) >> 1) ^ 0x07;
 }
 
 /**
@@ -2726,7 +2724,7 @@ out:
  * To bring UFS host controller to operational state,
  * 1. Enable required interrupts
  * 2. Configure interrupt aggregation
- * 3. Program UTRL and UTMRL base addres
+ * 3. Program UTRL and UTMRL base address
  * 4. Configure run-stop-registers
  *
  * Returns 0 on success, non-zero value on failure
@@ -2756,8 +2754,13 @@ static int ufshcd_make_hba_operational(struct ufs_hba 
*hba)
REG_UTP_TASK_REQ_LIST_BASE_H);
 
/*
+* Make sure base address and interrupt setup are updated before
+* enabling the run/stop registers below.
+*/
+   wmb();
+
+   /*
 * UCRDY, UTMRLDY and UTRLRDY bits must be 1
-* DEI, HEI bits must be 0
 */
reg = ufshcd_readl(hba, REG_CONTROLLER_STATUS);
if (!(ufshcd_get_lists_status(reg))) {
@@ -3920,7 +3923,13 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int 
lun_id, int task_id,
 
/* send command to the controller */
__set_bit(free_slot, &hba->outstanding_tasks);
+
+   /* Make sure descriptors are ready before ringing the task doorbell */
+   wmb();
+
ufshcd_writel(hba, 1 << free_slot, REG_UTP_TASK_REQ_DOOR_BELL);
+   /* Make sure that doorbell is committed immediately */
+   wmb();
 
spin_unlock_irqrestore(host->host_lock, flags);
 
-- 
1.8.5.2

-- 
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 12/15] scsi: ufs: reduce the interrupts for power mode change requests

2015-08-27 Thread Yaniv Gardi
DME commands such as Hibern8 enter/exit and gear switch generate 2
completion interrupts, one for confirmation that command is received
by local UniPro and 2nd one is the final confirmation after communication
with remote UniPro. Currently both of these completions are registered
as interrupt events which is not quite necessary and instead we can
just wait for the interrupt of 2nd completion, this should reduce
the number of interrupts and could reduce the unnecessary CPU wakeups
to handle extra interrupts.

Signed-off-by: Subhash Jadavani 
Signed-off-by: Yaniv Gardi 

---
 drivers/scsi/ufs/ufshcd.c | 41 +++--
 1 file changed, 27 insertions(+), 14 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index f2d4301..fc2a52d 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -986,13 +986,15 @@ ufshcd_wait_for_uic_cmd(struct ufs_hba *hba, struct 
uic_command *uic_cmd)
  * __ufshcd_send_uic_cmd - Send UIC commands and retrieve the result
  * @hba: per adapter instance
  * @uic_cmd: UIC command
+ * @completion: initialize the completion only if this is set to true
  *
  * Identical to ufshcd_send_uic_cmd() expect mutex. Must be called
  * with mutex held and host_lock locked.
  * Returns 0 only if success.
  */
 static int
-__ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
+__ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd,
+ bool completion)
 {
if (!ufshcd_ready_for_uic_cmd(hba)) {
dev_err(hba->dev,
@@ -1000,7 +1002,8 @@ __ufshcd_send_uic_cmd(struct ufs_hba *hba, struct 
uic_command *uic_cmd)
return -EIO;
}
 
-   init_completion(&uic_cmd->done);
+   if (completion)
+   init_completion(&uic_cmd->done);
 
ufshcd_dispatch_uic_cmd(hba, uic_cmd);
 
@@ -1025,7 +1028,7 @@ ufshcd_send_uic_cmd(struct ufs_hba *hba, struct 
uic_command *uic_cmd)
ufshcd_add_delay_before_dme_cmd(hba);
 
spin_lock_irqsave(hba->host->host_lock, flags);
-   ret = __ufshcd_send_uic_cmd(hba, uic_cmd);
+   ret = __ufshcd_send_uic_cmd(hba, uic_cmd, true);
spin_unlock_irqrestore(hba->host->host_lock, flags);
if (!ret)
ret = ufshcd_wait_for_uic_cmd(hba, uic_cmd);
@@ -2346,6 +2349,7 @@ static int ufshcd_uic_pwr_ctrl(struct ufs_hba *hba, 
struct uic_command *cmd)
unsigned long flags;
u8 status;
int ret;
+   bool reenable_intr = false;
 
mutex_lock(&hba->uic_cmd_mutex);
init_completion(&uic_async_done);
@@ -2353,15 +2357,17 @@ static int ufshcd_uic_pwr_ctrl(struct ufs_hba *hba, 
struct uic_command *cmd)
 
spin_lock_irqsave(hba->host->host_lock, flags);
hba->uic_async_done = &uic_async_done;
-   ret = __ufshcd_send_uic_cmd(hba, cmd);
-   spin_unlock_irqrestore(hba->host->host_lock, flags);
-   if (ret) {
-   dev_err(hba->dev,
-   "pwr ctrl cmd 0x%x with mode 0x%x uic error %d\n",
-   cmd->command, cmd->argument3, ret);
-   goto out;
+   if (ufshcd_readl(hba, REG_INTERRUPT_ENABLE) & UIC_COMMAND_COMPL) {
+   ufshcd_disable_intr(hba, UIC_COMMAND_COMPL);
+   /*
+* Make sure UIC command completion interrupt is disabled before
+* issuing UIC command.
+*/
+   wmb();
+   reenable_intr = true;
}
-   ret = ufshcd_wait_for_uic_cmd(hba, cmd);
+   ret = __ufshcd_send_uic_cmd(hba, cmd, false);
+   spin_unlock_irqrestore(hba->host->host_lock, flags);
if (ret) {
dev_err(hba->dev,
"pwr ctrl cmd 0x%x with mode 0x%x uic error %d\n",
@@ -2387,7 +2393,10 @@ static int ufshcd_uic_pwr_ctrl(struct ufs_hba *hba, 
struct uic_command *cmd)
}
 out:
spin_lock_irqsave(hba->host->host_lock, flags);
+   hba->active_uic_cmd = NULL;
hba->uic_async_done = NULL;
+   if (reenable_intr)
+   ufshcd_enable_intr(hba, UIC_COMMAND_COMPL);
spin_unlock_irqrestore(hba->host->host_lock, flags);
mutex_unlock(&hba->uic_cmd_mutex);
 
@@ -3812,16 +3821,20 @@ static void ufshcd_sl_intr(struct ufs_hba *hba, u32 
intr_status)
  */
 static irqreturn_t ufshcd_intr(int irq, void *__hba)
 {
-   u32 intr_status;
+   u32 intr_status, enabled_intr_status;
irqreturn_t retval = IRQ_NONE;
struct ufs_hba *hba = __hba;
 
spin_lock(hba->host->host_lock);
intr_status = ufshcd_readl(hba, REG_INTERRUPT_STATUS);
+   enabled_intr_status =
+   intr_status & ufshcd_readl(hba, REG_INTERRUPT_ENABLE);
 
-   if (intr_status) {
+   if (intr_status)
ufshcd_writel(hba, intr_status, REG_INTERRUPT_STATUS);
-   ufshcd_sl_intr(hba, intr_status);
+
+   if (enabled_intr_status) {
+   ufshcd_sl_intr(

[PATCH v2 11/15] scsi: ufs: retry failed query flag requests

2015-08-27 Thread Yaniv Gardi
UFS flag query requests may fail sometimes due to timeouts etc.
Add a wrapper function to retry up to 10 times in case of such
failure, similar to retries being made for attribute queries.

Signed-off-by: Gilad Broner 
Signed-off-by: Yaniv Gardi 

---
 drivers/scsi/ufs/ufshcd.c | 63 ---
 drivers/scsi/ufs/ufshcd.h |  4 +++
 2 files changed, 41 insertions(+), 26 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 1dbef7d..f2d4301 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -1662,6 +1662,29 @@ static inline void ufshcd_init_query(struct ufs_hba *hba,
(*request)->upiu_req.selector = selector;
 }
 
+static int ufshcd_query_flag_retry(struct ufs_hba *hba,
+   enum query_opcode opcode, enum flag_idn idn, bool *flag_res)
+{
+   int ret;
+   int retries;
+
+   for (retries = 0; retries < QUERY_REQ_RETRIES; retries++) {
+   ret = ufshcd_query_flag(hba, opcode, idn, flag_res);
+   if (ret)
+   dev_dbg(hba->dev,
+   "%s: failed with error %d, retries %d\n",
+   __func__, ret, retries);
+   else
+   break;
+   }
+
+   if (ret)
+   dev_err(hba->dev,
+   "%s: query attribute, opcode %d, idn %d, failed with 
error %d after %d retires\n",
+   __func__, opcode, idn, ret, retries);
+   return ret;
+}
+
 /**
  * ufshcd_query_flag() - API function for sending flag query requests
  * hba: per-adapter instance
@@ -1671,7 +1694,7 @@ static inline void ufshcd_init_query(struct ufs_hba *hba,
  *
  * Returns 0 for success, non-zero in case of failure
  */
-static int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
+int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
enum flag_idn idn, bool *flag_res)
 {
struct ufs_query_req *request = NULL;
@@ -2656,17 +2679,12 @@ static int ufshcd_config_pwr_mode(struct ufs_hba *hba,
  */
 static int ufshcd_complete_dev_init(struct ufs_hba *hba)
 {
-   int i, retries, err = 0;
+   int i;
+   int err;
bool flag_res = 1;
 
-   for (retries = QUERY_REQ_RETRIES; retries > 0; retries--) {
-   /* Set the fDeviceInit flag */
-   err = ufshcd_query_flag(hba, UPIU_QUERY_OPCODE_SET_FLAG,
-   QUERY_FLAG_IDN_FDEVICEINIT, NULL);
-   if (!err || err == -ETIMEDOUT)
-   break;
-   dev_dbg(hba->dev, "%s: error %d retrying\n", __func__, err);
-   }
+   err = ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_SET_FLAG,
+   QUERY_FLAG_IDN_FDEVICEINIT, NULL);
if (err) {
dev_err(hba->dev,
"%s setting fDeviceInit flag failed with error %d\n",
@@ -2674,18 +2692,11 @@ static int ufshcd_complete_dev_init(struct ufs_hba *hba)
goto out;
}
 
-   /* poll for max. 100 iterations for fDeviceInit flag to clear */
-   for (i = 0; i < 100 && !err && flag_res; i++) {
-   for (retries = QUERY_REQ_RETRIES; retries > 0; retries--) {
-   err = ufshcd_query_flag(hba,
-   UPIU_QUERY_OPCODE_READ_FLAG,
-   QUERY_FLAG_IDN_FDEVICEINIT, &flag_res);
-   if (!err || err == -ETIMEDOUT)
-   break;
-   dev_dbg(hba->dev, "%s: error %d retrying\n", __func__,
-   err);
-   }
-   }
+   /* poll for max. 1000 iterations for fDeviceInit flag to clear */
+   for (i = 0; i < 1000 && !err && flag_res; i++)
+   err = ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_READ_FLAG,
+   QUERY_FLAG_IDN_FDEVICEINIT, &flag_res);
+
if (err)
dev_err(hba->dev,
"%s reading fDeviceInit flag failed with error %d\n",
@@ -3432,7 +3443,7 @@ static int ufshcd_enable_auto_bkops(struct ufs_hba *hba)
if (hba->auto_bkops_enabled)
goto out;
 
-   err = ufshcd_query_flag(hba, UPIU_QUERY_OPCODE_SET_FLAG,
+   err = ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_SET_FLAG,
QUERY_FLAG_IDN_BKOPS_EN, NULL);
if (err) {
dev_err(hba->dev, "%s: failed to enable bkops %d\n",
@@ -3481,7 +3492,7 @@ static int ufshcd_disable_auto_bkops(struct ufs_hba *hba)
goto out;
}
 
-   err = ufshcd_query_flag(hba, UPIU_QUERY_OPCODE_CLEAR_FLAG,
+   err = ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_CLEAR_FLAG,
QUERY_FLAG_IDN_BKOPS_EN, NULL);
if (err) {
dev_err(hba->dev, "%s: failed to disable bkops %d\n",
@@ -4452,8 +4463,8 @@ static int ufshc

[PATCH v2 09/15] scsi: ufs: add retries for hibern8 enter

2015-08-27 Thread Yaniv Gardi
If hibern8 enter command fails then UFS link state may be unknown which
may result into timeout of all the commands issued after failure.

This change does 2 things (for pre-defined number of retry counts) after
hibern8 enter failure:
1. Recovers the UFS link to active state
2. If link is recovered to active state, tries to put the UFS link in
   hibern8 enter again until retry count expires.

Signed-off-by: Subhash Jadavani 
Signed-off-by: Yaniv Gardi 

---
 drivers/scsi/ufs/ufshcd.c | 26 --
 1 file changed, 24 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 8d5bdf0..5800b08 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -75,6 +75,9 @@
 /* maximum number of link-startup retries */
 #define DME_LINKSTARTUP_RETRIES 3
 
+/* Maximum retries for Hibern8 enter */
+#define UIC_HIBERN8_ENTER_RETRIES 3
+
 /* maximum number of reset retries before giving up */
 #define MAX_HOST_RESET_RETRIES 5
 
@@ -2389,13 +2392,32 @@ out:
return ret;
 }
 
-static int ufshcd_uic_hibern8_enter(struct ufs_hba *hba)
+static int __ufshcd_uic_hibern8_enter(struct ufs_hba *hba)
 {
+   int ret;
struct uic_command uic_cmd = {0};
 
uic_cmd.command = UIC_CMD_DME_HIBER_ENTER;
+   ret = ufshcd_uic_pwr_ctrl(hba, &uic_cmd);
+
+   if (ret)
+   dev_err(hba->dev, "%s: hibern8 enter failed. ret = %d",
+   __func__, ret);
+
+   return ret;
+}
+
+static int ufshcd_uic_hibern8_enter(struct ufs_hba *hba)
+{
+   int ret = 0, retries;
 
-   return ufshcd_uic_pwr_ctrl(hba, &uic_cmd);
+   for (retries = UIC_HIBERN8_ENTER_RETRIES; retries > 0; retries--) {
+   ret = __ufshcd_uic_hibern8_enter(hba);
+   if (!ret || ret == -ENOLINK)
+   goto out;
+   }
+out:
+   return ret;
 }
 
 static int ufshcd_uic_hibern8_exit(struct ufs_hba *hba)
-- 
1.8.5.2

-- 
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 10/15] scsi: ufs: fix error recovery after the hibern8 exit failure

2015-08-27 Thread Yaniv Gardi
Hibern8 exit can be called from 3 different context:
- ufshcd_hibern8_exit_work
- ufshcd_ungate_work
- runtime/system resume

If hibern8 exit fails for some reason then we try to bring the link to
active state by link startup but this recovery mechanism results into
deadlock or errors from first 2 context listed above. This change fixes
the recovery by adding proper error handling mechanism.

Signed-off-by: Subhash Jadavani 
Signed-off-by: Yaniv Gardi 

---
 drivers/scsi/ufs/ufshcd.c | 58 +++
 1 file changed, 53 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 5800b08..1dbef7d 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -609,6 +609,11 @@ int ufshcd_hold(struct ufs_hba *hba, bool async)
spin_lock_irqsave(hba->host->host_lock, flags);
hba->clk_gating.active_reqs++;
 
+   if (ufshcd_eh_in_progress(hba)) {
+   spin_unlock_irqrestore(hba->host->host_lock, flags);
+   return 0;
+   }
+
 start:
switch (hba->clk_gating.state) {
case CLKS_ON:
@@ -724,7 +729,8 @@ static void __ufshcd_release(struct ufs_hba *hba)
if (hba->clk_gating.active_reqs || hba->clk_gating.is_suspended
|| hba->ufshcd_state != UFSHCD_STATE_OPERATIONAL
|| hba->lrb_in_use || hba->outstanding_tasks
-   || hba->active_uic_cmd || hba->uic_async_done)
+   || hba->active_uic_cmd || hba->uic_async_done
+   || ufshcd_eh_in_progress(hba))
return;
 
hba->clk_gating.state = REQ_CLKS_OFF;
@@ -1362,6 +1368,13 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, 
struct scsi_cmnd *cmd)
cmd->scsi_done(cmd);
goto out_unlock;
}
+
+   /* if error handling is in progress, don't issue commands */
+   if (ufshcd_eh_in_progress(hba)) {
+   set_host_byte(cmd, DID_ERROR);
+   cmd->scsi_done(cmd);
+   goto out_unlock;
+   }
spin_unlock_irqrestore(hba->host->host_lock, flags);
 
/* acquire the tag to make sure device cmds don't use it */
@@ -2392,6 +2405,31 @@ out:
return ret;
 }
 
+static int ufshcd_link_recovery(struct ufs_hba *hba)
+{
+   int ret;
+   unsigned long flags;
+
+   spin_lock_irqsave(hba->host->host_lock, flags);
+   hba->ufshcd_state = UFSHCD_STATE_RESET;
+   ufshcd_set_eh_in_progress(hba);
+   spin_unlock_irqrestore(hba->host->host_lock, flags);
+
+   ret = ufshcd_host_reset_and_restore(hba);
+
+   spin_lock_irqsave(hba->host->host_lock, flags);
+   if (ret)
+   hba->ufshcd_state = UFSHCD_STATE_ERROR;
+   ufshcd_clear_eh_in_progress(hba);
+   spin_unlock_irqrestore(hba->host->host_lock, flags);
+
+   if (ret)
+   dev_err(hba->dev, "%s: link recovery failed, err %d",
+   __func__, ret);
+
+   return ret;
+}
+
 static int __ufshcd_uic_hibern8_enter(struct ufs_hba *hba)
 {
int ret;
@@ -2400,10 +2438,18 @@ static int __ufshcd_uic_hibern8_enter(struct ufs_hba 
*hba)
uic_cmd.command = UIC_CMD_DME_HIBER_ENTER;
ret = ufshcd_uic_pwr_ctrl(hba, &uic_cmd);
 
-   if (ret)
+   if (ret) {
dev_err(hba->dev, "%s: hibern8 enter failed. ret = %d",
__func__, ret);
 
+   /*
+* If link recovery fails then return error so that caller
+* don't retry the hibern8 enter again.
+*/
+   if (ufshcd_link_recovery(hba))
+   ret = -ENOLINK;
+   }
+
return ret;
 }
 
@@ -2428,8 +2474,9 @@ static int ufshcd_uic_hibern8_exit(struct ufs_hba *hba)
uic_cmd.command = UIC_CMD_DME_HIBER_EXIT;
ret = ufshcd_uic_pwr_ctrl(hba, &uic_cmd);
if (ret) {
-   ufshcd_set_link_off(hba);
-   ret = ufshcd_host_reset_and_restore(hba);
+   dev_err(hba->dev, "%s: hibern8 exit failed. ret = %d",
+   __func__, ret);
+   ret = ufshcd_link_recovery(hba);
}
 
return ret;
@@ -4381,7 +4428,6 @@ static int ufshcd_probe_hba(struct ufs_hba *hba)
/* UFS device is also active now */
ufshcd_set_ufs_dev_active(hba);
ufshcd_force_reset_auto_bkops(hba);
-   hba->ufshcd_state = UFSHCD_STATE_OPERATIONAL;
hba->wlun_dev_clr_ua = true;
 
if (ufshcd_get_max_pwr_mode(hba)) {
@@ -4395,6 +4441,8 @@ static int ufshcd_probe_hba(struct ufs_hba *hba)
__func__, ret);
}
 
+   /* set the state as operational after switching to desired gear */
+   hba->ufshcd_state = UFSHCD_STATE_OPERATIONAL;
/*
 * If we are in error handling context or in power management callbacks
 * context, no need to scan the host
-- 
1.8.5.2

-- 
QUALCOMM ISRAEL, on

[PATCH v2 06/15] scsi: ufs: avoid exception event handler racing with PM callbacks

2015-08-27 Thread Yaniv Gardi
If device raises the exception event in the response to the commands
sent during the runtime/system PM callbacks, exception event handler
might run in parallel with PM callbacks and may see unclocked register
accesses. This change fixes this issue by not scheduling the exception
event handler while PM callbacks are running.

Signed-off-by: Subhash Jadavani 
Signed-off-by: Yaniv Gardi 

---
 drivers/scsi/ufs/ufshcd.c | 15 ++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 573a8cb..0e54183 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -3145,7 +3145,20 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct 
ufshcd_lrb *lrbp)
scsi_status = result & MASK_SCSI_STATUS;
result = ufshcd_scsi_cmd_status(lrbp, scsi_status);
 
-   if (ufshcd_is_exception_event(lrbp->ucd_rsp_ptr))
+   /*
+* Currently we are only supporting BKOPs exception
+* events hence we can ignore BKOPs exception event
+* during power management callbacks. BKOPs exception
+* event is not expected to be raised in runtime suspend
+* callback as it allows the urgent bkops.
+* During system suspend, we are anyway forcefully
+* disabling the bkops and if urgent bkops is needed
+* it will be enabled on system resume. Long term
+* solution could be to abort the system suspend if
+* UFS device needs urgent BKOPs.
+*/
+   if (!hba->pm_op_in_progress &&
+   ufshcd_is_exception_event(lrbp->ucd_rsp_ptr))
schedule_work(&hba->eeh_work);
break;
case UPIU_TRANSACTION_REJECT_UPIU:
-- 
1.8.5.2

-- 
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 07/15] scsi: ufs: set REQUEST_SENSE command size to 18 bytes

2015-08-27 Thread Yaniv Gardi
According to UFS device specification REQUEST_SENSE command can
only report back up to 18 bytes of data.

Signed-off-by: Gilad Broner 
Signed-off-by: Yaniv Gardi 

---
 drivers/scsi/ufs/ufshcd.c | 11 ++-
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 0e54183..217b5cf 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -42,6 +42,7 @@
 
 #include "ufshcd.h"
 #include "unipro.h"
+#define UFSHCD_REQ_SENSE_SIZE  18
 
 #define UFSHCD_ENABLE_INTRS(UTP_TRANSFER_REQ_COMPL |\
 UTP_TASK_REQ_COMPL |\
@@ -836,7 +837,7 @@ static inline void ufshcd_copy_sense_data(struct ufshcd_lrb 
*lrbp)
len = be16_to_cpu(lrbp->ucd_rsp_ptr->sr.sense_data_len);
memcpy(lrbp->sense_buffer,
lrbp->ucd_rsp_ptr->sr.sense_data,
-   min_t(int, len, SCSI_SENSE_BUFFERSIZE));
+   min_t(int, len, UFSHCD_REQ_SENSE_SIZE));
}
 }
 
@@ -1381,7 +1382,7 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, 
struct scsi_cmnd *cmd)
 
WARN_ON(lrbp->cmd);
lrbp->cmd = cmd;
-   lrbp->sense_bufflen = SCSI_SENSE_BUFFERSIZE;
+   lrbp->sense_bufflen = UFSHCD_REQ_SENSE_SIZE;
lrbp->sense_buffer = cmd->sense_buffer;
lrbp->task_tag = tag;
lrbp->lun = ufshcd_scsi_to_upiu_lun(cmd->device->lun);
@@ -4817,19 +4818,19 @@ ufshcd_send_request_sense(struct ufs_hba *hba, struct 
scsi_device *sdp)
0,
0,
0,
-   SCSI_SENSE_BUFFERSIZE,
+   UFSHCD_REQ_SENSE_SIZE,
0};
char *buffer;
int ret;
 
-   buffer = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);
+   buffer = kzalloc(UFSHCD_REQ_SENSE_SIZE, GFP_KERNEL);
if (!buffer) {
ret = -ENOMEM;
goto out;
}
 
ret = scsi_execute_req_flags(sdp, cmd, DMA_FROM_DEVICE, buffer,
-   SCSI_SENSE_BUFFERSIZE, NULL,
+   UFSHCD_REQ_SENSE_SIZE, NULL,
msecs_to_jiffies(1000), 3, NULL, REQ_PM);
if (ret)
pr_err("%s: failed with err %d\n", __func__, ret);
-- 
1.8.5.2

-- 
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 19/23] scsi_dh_alua: Use workqueue for RTPG

2015-08-27 Thread Hannes Reinecke
The current ALUA device_handler has two drawbacks:
- We're sending a 'SET TARGET PORT GROUP' command to every LUN,
  disregarding the fact that several LUNs might be in a port group
  and will be automatically switched whenever _any_ LUN within
  that port group receives the command.
- Whenever a LUN is in 'transitioning' mode we cannot block I/O
  to that LUN, instead the controller has to abort the command.
  This leads to increased traffic across the wire and heavy load
  on the controller during switchover.

With this patch the RTPG handling is moved to a per-portgroup
workqueue. This reduces the number of 'REPORT TARGET PORT GROUP'
and 'SET TARGET PORT GROUPS' sent to the controller as we're sending
them now per port group, and not per device as previously.
It also allows us to block I/O to any LUN / port group found to be
in 'transitioning' ALUA mode, as the workqueue item will be requeued
until the controller moves out of transitioning.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 414 -
 1 file changed, 349 insertions(+), 65 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index b52db8b..85fd597 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -22,6 +22,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -59,10 +61,15 @@
 #define ALUA_RTPG_SIZE 128
 #define ALUA_FAILOVER_TIMEOUT  60
 #define ALUA_FAILOVER_RETRIES  5
+#define ALUA_RTPG_DELAY_MSECS  5
 
 /* device handler flags */
-#define ALUA_OPTIMIZE_STPG 1
-#define ALUA_RTPG_EXT_HDR_UNSUPP   2
+#define ALUA_OPTIMIZE_STPG 0x01
+#define ALUA_RTPG_EXT_HDR_UNSUPP   0x02
+/* State machine flags */
+#define ALUA_PG_RUN_RTPG   0x10
+#define ALUA_PG_RUN_STPG   0x20
+
 
 static LIST_HEAD(port_group_list);
 static DEFINE_SPINLOCK(port_group_lock);
@@ -78,13 +85,28 @@ struct alua_port_group {
int pref;
unsignedflags; /* used for optimizing STPG */
unsigned char   transition_tmo;
+   unsigned long   expiry;
+   unsigned long   interval;
+   struct workqueue_struct *work_q;
+   struct delayed_work rtpg_work;
+   struct delayed_work stpg_work;
+   struct delayed_work qdata_work;
+   spinlock_t  rtpg_lock;
+   struct list_headrtpg_list;
+   struct scsi_device  *rtpg_sdev;
 };
 
 struct alua_dh_data {
struct alua_port_group  *pg;
+   spinlock_t  pg_lock;
int rel_port;
int tpgs;
-   struct scsi_device  *sdev;
+   int init_error;
+   struct mutexinit_mutex;
+};
+
+struct alua_queue_data {
+   struct list_headentry;
activate_complete   callback_fn;
void*callback_data;
 };
@@ -93,6 +115,10 @@ struct alua_dh_data {
 #define ALUA_POLICY_SWITCH_ALL 1
 
 static char print_alua_state(int);
+static void alua_rtpg_work(struct work_struct *work);
+static void alua_stpg_work(struct work_struct *work);
+static void alua_qdata_work(struct work_struct *work);
+static void alua_check(struct scsi_device *sdev);
 
 static void release_port_group(struct kref *kref)
 {
@@ -103,6 +129,9 @@ static void release_port_group(struct kref *kref)
spin_lock(&port_group_lock);
list_del(&pg->node);
spin_unlock(&port_group_lock);
+   WARN_ON(pg->rtpg_sdev);
+   if (pg->work_q)
+   destroy_workqueue(pg->work_q);
kfree(pg);
 }
 
@@ -296,13 +325,17 @@ static int alua_check_vpd(struct scsi_device *sdev, 
struct alua_dh_data *h)
if (strncmp(tmp_pg->device_id_str, device_id_str,
device_id_size))
continue;
-   h->pg = tmp_pg;
kref_get(&tmp_pg->kref);
+   spin_lock(&h->pg_lock);
+   rcu_assign_pointer(h->pg, tmp_pg);
+   spin_unlock(&h->pg_lock);
break;
}
spin_unlock(&port_group_lock);
-   if (h->pg)
+   if (h->pg) {
+   synchronize_rcu();
return SCSI_DH_OK;
+   }
 
pg = kzalloc(sizeof(struct alua_port_group), GFP_KERNEL);
if (!pg) {
@@ -322,6 +355,19 @@ static int alua_check_vpd(struct scsi_device *sdev, struct 
alua_dh_data *h)
pg->tpgs = h->tpgs;
pg->state = TPGS_STATE_OPTIMIZED;
kref_init(&pg->kref);
+   INIT_DELAYED_WORK(&pg->rtpg_work, alua_rtpg_work);
+   INIT_DELAYED_WORK(&pg->stpg_work, alua_stpg_work);
+   INIT_DELAYED_WORK(&pg->qdata_work, alua_qdata_work);
+   INIT_LIST_HEAD(&pg->rtpg_list);
+   INIT_LIST_HEAD(&pg->node

[PATCH v2 04/15] scsi: ufs: clear outstanding_request bit in case query timeout

2015-08-27 Thread Yaniv Gardi
When sending a query to the device returns with a timeout error,
we clear the corresponding bit in the DOORBELL register but
we don't clear the outstanding_request field as we should.
This patch fixes this bug.

Signed-off-by: Yaniv Gardi 

---
 drivers/scsi/ufs/ufshcd.c | 22 --
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 8860a57..e0b8755 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -364,6 +364,16 @@ static inline void ufshcd_utrl_clear(struct ufs_hba *hba, 
u32 pos)
 }
 
 /**
+ * ufshcd_outstanding_req_clear - Clear a bit in outstanding request field
+ * @hba: per adapter instance
+ * @tag: position of the bit to be cleared
+ */
+static inline void ufshcd_outstanding_req_clear(struct ufs_hba *hba, int tag)
+{
+   __clear_bit(tag, &hba->outstanding_reqs);
+}
+
+/**
  * ufshcd_get_lists_status - Check UCRDY, UTRLRDY and UTMRLRDY
  * @reg: Register value of host controller status
  *
@@ -1502,9 +1512,17 @@ static int ufshcd_wait_for_dev_cmd(struct ufs_hba *hba,
 
if (!time_left) {
err = -ETIMEDOUT;
+   dev_dbg(hba->dev, "%s: dev_cmd request timedout, tag %d\n",
+   __func__, lrbp->task_tag);
if (!ufshcd_clear_cmd(hba, lrbp->task_tag))
-   /* sucessfully cleared the command, retry if needed */
+   /* successfully cleared the command, retry if needed */
err = -EAGAIN;
+   /*
+* in case of an error, after clearing the doorbell,
+* we also need to clear the outstanding_request
+* field in hba
+*/
+   ufshcd_outstanding_req_clear(hba, lrbp->task_tag);
}
 
return err;
@@ -3942,7 +3960,7 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)
scsi_dma_unmap(cmd);
 
spin_lock_irqsave(host->host_lock, flags);
-   __clear_bit(tag, &hba->outstanding_reqs);
+   ufshcd_outstanding_req_clear(hba, tag);
hba->lrb[tag].cmd = NULL;
spin_unlock_irqrestore(host->host_lock, flags);
 
-- 
1.8.5.2

-- 
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 05/15] scsi: ufs: increase fDeviceInit query response timeout

2015-08-27 Thread Yaniv Gardi
fDeviceInit query response time for some devices is too long that default
query request timeout of 100ms may not be enough. Experiments show that
fDeviceInit response sometimes takes 500ms so to be on safer side this
change sets the timeout to 600ms. Without this change, we might
unnecessarily have to retry fDeviceInit query requests multiple times and
each query request timeout prints one error message.

Signed-off-by: Subhash Jadavani 
Signed-off-by: Yaniv Gardi 

---
 drivers/scsi/ufs/ufshcd.c | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index e0b8755..573a8cb 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -58,6 +58,12 @@
 #define QUERY_REQ_RETRIES 10
 /* Query request timeout */
 #define QUERY_REQ_TIMEOUT 30 /* msec */
+/*
+ * Query request timeout for fDeviceInit flag
+ * fDeviceInit query response time for some devices is too large that default
+ * QUERY_REQ_TIMEOUT may not be enough for such devices.
+ */
+#define QUERY_FDEVICEINIT_REQ_TIMEOUT 600 /* msec */
 
 /* Task management command timeout */
 #define TM_CMD_TIMEOUT 100 /* msecs */
@@ -1651,6 +1657,7 @@ static int ufshcd_query_flag(struct ufs_hba *hba, enum 
query_opcode opcode,
struct ufs_query_req *request = NULL;
struct ufs_query_res *response = NULL;
int err, index = 0, selector = 0;
+   int timeout = QUERY_REQ_TIMEOUT;
 
BUG_ON(!hba);
 
@@ -1683,7 +1690,10 @@ static int ufshcd_query_flag(struct ufs_hba *hba, enum 
query_opcode opcode,
goto out_unlock;
}
 
-   err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, QUERY_REQ_TIMEOUT);
+   if (idn == QUERY_FLAG_IDN_FDEVICEINIT)
+   timeout = QUERY_FDEVICEINIT_REQ_TIMEOUT;
+
+   err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, timeout);
 
if (err) {
dev_err(hba->dev,
-- 
1.8.5.2

-- 
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 03/15] scsi: ufs: verify command tag validity

2015-08-27 Thread Yaniv Gardi
A race condition appear to exist between request completion when
scsi_done() is called to end the request and set the tag back to
-1 (at blk_queue_end_tag() scsi_end_request), and scsi layer error
handling which aborts the command and reuses it to request sense
data. Sending the request sense is done with tag which was set to -1
and so it is invalid.
Assert command tag passed from scsi layer is valid.

Signed-off-by: Gilad Broner 
Signed-off-by: Yaniv Gardi 

---
 drivers/scsi/ufs/ufshcd.c | 24 ++--
 1 file changed, 22 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 2d3ebca..8860a57 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -190,6 +190,10 @@ static int ufshcd_config_pwr_mode(struct ufs_hba *hba,
struct ufs_pa_layer_attr *desired_pwr_mode);
 static int ufshcd_change_power_mode(struct ufs_hba *hba,
 struct ufs_pa_layer_attr *pwr_mode);
+static inline bool ufshcd_valid_tag(struct ufs_hba *hba, int tag)
+{
+   return tag >= 0 && tag < hba->nutrs;
+}
 
 static inline int ufshcd_enable_irq(struct ufs_hba *hba)
 {
@@ -1310,6 +1314,12 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, 
struct scsi_cmnd *cmd)
hba = shost_priv(host);
 
tag = cmd->request->tag;
+   if (!ufshcd_valid_tag(hba, tag)) {
+   dev_err(hba->dev,
+   "%s: invalid command tag %d: cmd=0x%p, 
cmd->request=0x%p",
+   __func__, tag, cmd, cmd->request);
+   BUG();
+   }
 
spin_lock_irqsave(hba->host->host_lock, flags);
switch (hba->ufshcd_state) {
@@ -3862,13 +3872,23 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)
host = cmd->device->host;
hba = shost_priv(host);
tag = cmd->request->tag;
+   if (!ufshcd_valid_tag(hba, tag)) {
+   dev_err(hba->dev,
+   "%s: invalid command tag %d: cmd=0x%p, 
cmd->request=0x%p",
+   __func__, tag, cmd, cmd->request);
+   BUG();
+   }
 
ufshcd_hold(hba, false);
+   reg = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
/* If command is already aborted/completed, return SUCCESS */
-   if (!(test_bit(tag, &hba->outstanding_reqs)))
+   if (!(test_bit(tag, &hba->outstanding_reqs))) {
+   dev_err(hba->dev,
+   "%s: cmd at tag %d already completed, 
outstanding=0x%lx, doorbell=0x%x\n",
+   __func__, tag, hba->outstanding_reqs, reg);
goto out;
+   }
 
-   reg = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
if (!(reg & (1 << tag))) {
dev_err(hba->dev,
"%s: cmd was completed, but without a notifying intr, tag = %d",
-- 
1.8.5.2

-- 
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 15/23] scsi_dh_alua: simplify sense code handling

2015-08-27 Thread Hannes Reinecke
Most sense code is already handled in the generic
code, so we shouldn't be adding special cases here.
However, when doing so we need to check for
unit attention whenever we're sending an internal
command.

Reviewed-by: Christoph Hellwig 
Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 50 +++---
 1 file changed, 11 insertions(+), 39 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index 4157fe2..dbe9ff2 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -91,7 +91,6 @@ struct alua_dh_data {
 #define ALUA_POLICY_SWITCH_ALL 1
 
 static char print_alua_state(int);
-static int alua_check_sense(struct scsi_device *, struct scsi_sense_hdr *);
 
 static void release_port_group(struct kref *kref)
 {
@@ -323,28 +322,6 @@ static int alua_check_sense(struct scsi_device *sdev,
 * LUN Not Accessible - ALUA state transition
 */
return ADD_TO_MLQUEUE;
-   if (sense_hdr->asc == 0x04 && sense_hdr->ascq == 0x0b)
-   /*
-* LUN Not Accessible -- Target port in standby state
-*/
-   return SUCCESS;
-   if (sense_hdr->asc == 0x04 && sense_hdr->ascq == 0x0c)
-   /*
-* LUN Not Accessible -- Target port in unavailable 
state
-*/
-   return SUCCESS;
-   if (sense_hdr->asc == 0x04 && sense_hdr->ascq == 0x12)
-   /*
-* LUN Not Ready -- Offline
-*/
-   return SUCCESS;
-   if (sdev->allow_restart &&
-   sense_hdr->asc == 0x04 && sense_hdr->ascq == 0x02)
-   /*
-* if the device is not started, we need to wake
-* the error handler to start the motor
-*/
-   return FAILED;
break;
case UNIT_ATTENTION:
if (sense_hdr->asc == 0x29 && sense_hdr->ascq == 0x00)
@@ -359,7 +336,7 @@ static int alua_check_sense(struct scsi_device *sdev,
return ADD_TO_MLQUEUE;
if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x01)
/*
-* Mode Parameters Changed
+* Mode Parameter Changed
 */
return ADD_TO_MLQUEUE;
if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x06)
@@ -372,18 +349,6 @@ static int alua_check_sense(struct scsi_device *sdev,
 * Implicit ALUA state transition failed
 */
return ADD_TO_MLQUEUE;
-   if (sense_hdr->asc == 0x3f && sense_hdr->ascq == 0x03)
-   /*
-* Inquiry data has changed
-*/
-   return ADD_TO_MLQUEUE;
-   if (sense_hdr->asc == 0x3f && sense_hdr->ascq == 0x0e)
-   /*
-* REPORTED_LUNS_DATA_HAS_CHANGED is reported
-* when switching controllers on targets like
-* Intel Multi-Flex. We can just retry.
-*/
-   return ADD_TO_MLQUEUE;
break;
}
 
@@ -448,9 +413,16 @@ static int alua_rtpg(struct scsi_device *sdev, struct 
alua_port_group *pg, int w
pg->flags |= ALUA_RTPG_EXT_HDR_UNSUPP;
goto retry;
}
-
-   err = alua_check_sense(sdev, &sense_hdr);
-   if (err == ADD_TO_MLQUEUE && time_before(jiffies, expiry)) {
+   /*
+* Retry on ALUA state transition or if any
+* UNIT ATTENTION occurred.
+*/
+   if (sense_hdr.sense_key == NOT_READY &&
+   sense_hdr.asc == 0x04 && sense_hdr.ascq == 0x0a)
+   err = SCSI_DH_RETRY;
+   else if (sense_hdr.sense_key == UNIT_ATTENTION)
+   err = SCSI_DH_RETRY;
+   if (err == SCSI_DH_RETRY && time_before(jiffies, expiry)) {
sdev_printk(KERN_ERR, sdev, "%s: rtpg retry\n",
ALUA_DH_NAME);
scsi_print_sense_hdr(sdev, ALUA_DH_NAME, &sense_hdr);
-- 
1.8.5.6

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 22/23] scsi_dh_alua: Send TEST UNIT READY to poll for transitioning

2015-08-27 Thread Hannes Reinecke
Sending a 'REPORT TARGET PORT GROUP' command is a costly operation,
as the array has to gather information about all ports.
So instead of using RTPG to poll for a status update when a port
is in transitioning we should be sending a TEST UNIT READY, and
wait for the sense code to report success.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 33 ++
 1 file changed, 33 insertions(+)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index 2fa985e..3c6b365 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -467,6 +467,30 @@ static int alua_check_sense(struct scsi_device *sdev,
 }
 
 /*
+ * alua_tur - Send a TEST UNIT READY
+ * @sdev: device to which the TEST UNIT READY command should be send
+ *
+ * Send a TEST UNIT READY to @sdev to figure out the device state
+ * Returns SCSI_DH_RETRY if the sense code is NOT READY/ALUA TRANSITIONING,
+ * SCSI_DH_OK if no error occured, and SCSI_DH_IO otherwise.
+ */
+static int alua_tur(struct scsi_device *sdev)
+{
+   struct scsi_sense_hdr sense_hdr;
+   int retval;
+
+   retval = scsi_test_unit_ready(sdev, ALUA_FAILOVER_TIMEOUT * HZ,
+ ALUA_FAILOVER_RETRIES, &sense_hdr);
+   if (sense_hdr.sense_key == NOT_READY &&
+   sense_hdr.asc == 0x04 && sense_hdr.ascq == 0x0a)
+   return SCSI_DH_RETRY;
+   else if (retval)
+   return SCSI_DH_IO;
+   else
+   return SCSI_DH_OK;
+}
+
+/*
  * alua_rtpg - Evaluate REPORT TARGET GROUP STATES
  * @sdev: the device to be evaluated.
  *
@@ -725,7 +749,16 @@ static void alua_rtpg_work(struct work_struct *work)
return;
}
if (pg->flags & ALUA_PG_RUN_RTPG) {
+   int state = pg->state;
spin_unlock_irqrestore(&pg->rtpg_lock, flags);
+   if (state == TPGS_STATE_TRANSITIONING) {
+   if (alua_tur(sdev) == SCSI_DH_RETRY) {
+   queue_delayed_work(pg->work_q, &pg->rtpg_work,
+  pg->interval * HZ);
+   return;
+   }
+   /* Send RTPG on failure or if TUR indicates SUCCESS */
+   }
err = alua_rtpg(sdev, pg);
if (err == SCSI_DH_RETRY) {
queue_delayed_work(pg->work_q, &pg->rtpg_work,
-- 
1.8.5.6

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 20/23] scsi_dh_alua: Recheck state on unit attention

2015-08-27 Thread Hannes Reinecke
When we receive a unit attention code of 'ALUA state changed'
we should recheck the state, as it might be due to an implicit
ALUA state transition.
At the same time a workqueue item might already be queued, which
should be started immediately to avoid any delays.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 48 +++---
 1 file changed, 24 insertions(+), 24 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index 85fd597..8717fd3 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -118,7 +118,7 @@ static char print_alua_state(int);
 static void alua_rtpg_work(struct work_struct *work);
 static void alua_stpg_work(struct work_struct *work);
 static void alua_qdata_work(struct work_struct *work);
-static void alua_check(struct scsi_device *sdev);
+static void alua_check(struct scsi_device *sdev, bool force);
 
 static void release_port_group(struct kref *kref)
 {
@@ -423,7 +423,7 @@ static char print_alua_state(int state)
 }
 
 static int alua_check_sense(struct scsi_device *sdev,
-   struct scsi_sense_hdr *sense_hdr)
+struct scsi_sense_hdr *sense_hdr)
 {
switch (sense_hdr->sense_key) {
case NOT_READY:
@@ -432,36 +432,34 @@ static int alua_check_sense(struct scsi_device *sdev,
 * LUN Not Accessible - ALUA state transition
 * Kickoff worker to update internal state.
 */
-   alua_check(sdev);
-   return ADD_TO_MLQUEUE;
+   alua_check(sdev, false);
+   return NEEDS_RETRY;
}
break;
case UNIT_ATTENTION:
-   if (sense_hdr->asc == 0x29 && sense_hdr->ascq == 0x00)
-   /*
-* Power On, Reset, or Bus Device Reset, just retry.
-*/
-   return ADD_TO_MLQUEUE;
-   if (sense_hdr->asc == 0x29 && sense_hdr->ascq == 0x04)
-   /*
-* Device internal reset
-*/
-   return ADD_TO_MLQUEUE;
-   if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x01)
+   if (sense_hdr->asc == 0x29 && sense_hdr->ascq == 0x00) {
/*
-* Mode Parameter Changed
+* Power On, Reset, or Bus Device Reset.
+* Might have obscured a state transition,
+* so schedule a recheck.
 */
+   alua_check(sdev, true);
return ADD_TO_MLQUEUE;
-   if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x06)
+   }
+   if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x06) {
/*
 * ALUA state changed
 */
+   alua_check(sdev, true);
return ADD_TO_MLQUEUE;
-   if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x07)
+   }
+   if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x07) {
/*
 * Implicit ALUA state transition failed
 */
+   alua_check(sdev, true);
return ADD_TO_MLQUEUE;
+   }
break;
}
 
@@ -811,7 +809,7 @@ static void alua_qdata_work(struct work_struct *work)
 
 static void alua_rtpg_queue(struct alua_port_group *pg,
struct scsi_device *sdev,
-   struct alua_queue_data *qdata)
+   struct alua_queue_data *qdata, bool force)
 {
int start_queue = 0;
unsigned long flags;
@@ -832,7 +830,9 @@ static void alua_rtpg_queue(struct alua_port_group *pg,
pg->rtpg_sdev = sdev;
scsi_device_get(sdev);
start_queue = 1;
-   }
+   } else if (!(pg->flags & ALUA_PG_RUN_RTPG) && force)
+   start_queue = 1;
+
spin_unlock_irqrestore(&pg->rtpg_lock, flags);
 
if (start_queue)
@@ -873,7 +873,7 @@ static int alua_initialize(struct scsi_device *sdev, struct 
alua_dh_data *h)
mutex_unlock(&h->init_mutex);
if (pg) {
pg->expiry = 0;
-   alua_rtpg_queue(pg, sdev, NULL);
+   alua_rtpg_queue(pg, sdev, NULL, true);
kref_put(&pg->kref, release_port_group);
}
return error;
@@ -982,7 +982,7 @@ static int alua_activate(struct scsi_device *sdev,
pg->flags |= ALUA_OPTIMIZE_STPG;
spin_unlock_irqrestore(&pg->rtpg_lock, flags);
}
-   alua_rtpg_queue(pg, s

[PATCH 18/23] revert "scsi_dh_alua: ALUA hander attach should succeed while TPG is transitioning"

2015-08-27 Thread Hannes Reinecke
This reverts commit a8e5a2d593cbfccf530c3382c2c328d2edaa7b66

Obsoleted by the next patch.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 29 +++--
 1 file changed, 11 insertions(+), 18 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index c2b2100b..b52db8b 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -418,13 +418,12 @@ static int alua_check_sense(struct scsi_device *sdev,
 /*
  * alua_rtpg - Evaluate REPORT TARGET GROUP STATES
  * @sdev: the device to be evaluated.
- * @wait_for_transition: if nonzero, wait ALUA_FAILOVER_TIMEOUT seconds for 
device to exit transitioning state
  *
  * Evaluate the Target Port Group State.
  * Returns SCSI_DH_DEV_OFFLINED if the path is
  * found to be unusable.
  */
-static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg, int 
wait_for_transition)
+static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg)
 {
struct scsi_sense_hdr sense_hdr;
int len, k, off, valid_states = 0, bufflen = ALUA_RTPG_SIZE;
@@ -517,8 +516,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct 
alua_port_group *pg, int w
else
pg->transition_tmo = ALUA_FAILOVER_TIMEOUT;
 
-   if (wait_for_transition &&
-   (orig_transition_tmo != pg->transition_tmo)) {
+   if (orig_transition_tmo != pg->transition_tmo) {
sdev_printk(KERN_INFO, sdev,
"%s: transition timeout set to %d seconds\n",
ALUA_DH_NAME, pg->transition_tmo);
@@ -556,19 +554,14 @@ static int alua_rtpg(struct scsi_device *sdev, struct 
alua_port_group *pg, int w
 
switch (pg->state) {
case TPGS_STATE_TRANSITIONING:
-   if (wait_for_transition) {
-   if (time_before(jiffies, expiry)) {
-   /* State transition, retry */
-   interval += 2000;
-   msleep(interval);
-   goto retry;
-   }
-   err = SCSI_DH_RETRY;
-   } else {
-   err = SCSI_DH_OK;
+   if (time_before(jiffies, expiry)) {
+   /* State transition, retry */
+   interval += 2000;
+   msleep(interval);
+   goto retry;
}
-
/* Transitioning time exceeded, set port to standby */
+   err = SCSI_DH_RETRY;
pg->state = TPGS_STATE_STANDBY;
break;
case TPGS_STATE_OFFLINE:
@@ -665,7 +658,7 @@ static int alua_initialize(struct scsi_device *sdev, struct 
alua_dh_data *h)
goto out;
 
kref_get(&h->pg->kref);
-   err = alua_rtpg(sdev, h->pg, 0);
+   err = alua_rtpg(sdev, h->pg);
kref_put(&h->pg->kref, release_port_group);
 out:
return err;
@@ -739,14 +732,14 @@ static int alua_activate(struct scsi_device *sdev,
if (optimize_stpg)
h->pg->flags |= ALUA_OPTIMIZE_STPG;
 
-   err = alua_rtpg(sdev, h->pg, 1);
+   err = alua_rtpg(sdev, h->pg);
if (err != SCSI_DH_OK) {
kref_put(&h->pg->kref, release_port_group);
goto out;
}
err = alua_stpg(sdev, h->pg);
if (err == SCSI_DH_RETRY)
-   err = alua_rtpg(sdev, h->pg, 1);
+   err = alua_rtpg(sdev, h->pg);
kref_put(&h->pg->kref, release_port_group);
 out:
if (fn)
-- 
1.8.5.6

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 14/23] scsi_dh_alua: allocate RTPG buffer separately

2015-08-27 Thread Hannes Reinecke
The RTPG buffer will only evaluated within alua_rtpg(),
so we can allocate it locally there and avoid having to
put it into the global structure.

Reviewed-by: Christoph Hellwig 
Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 56 +++---
 1 file changed, 21 insertions(+), 35 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index d1010dd..4157fe2 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -56,7 +56,7 @@
 #define TPGS_MODE_IMPLICIT 0x1
 #define TPGS_MODE_EXPLICIT 0x2
 
-#define ALUA_INQUIRY_SIZE  36
+#define ALUA_RTPG_SIZE 128
 #define ALUA_FAILOVER_TIMEOUT  60
 #define ALUA_FAILOVER_RETRIES  5
 
@@ -75,9 +75,6 @@ struct alua_port_group {
int state;
int pref;
unsignedflags; /* used for optimizing STPG */
-   unsigned char   inq[ALUA_INQUIRY_SIZE];
-   unsigned char   *buff;
-   int bufflen;
unsigned char   transition_tmo;
 };
 
@@ -96,21 +93,6 @@ struct alua_dh_data {
 static char print_alua_state(int);
 static int alua_check_sense(struct scsi_device *, struct scsi_sense_hdr *);
 
-static int realloc_buffer(struct alua_port_group *pg, unsigned len)
-{
-   if (pg->buff && pg->buff != pg->inq)
-   kfree(pg->buff);
-
-   pg->buff = kmalloc(len, GFP_NOIO);
-   if (!pg->buff) {
-   pg->buff = pg->inq;
-   pg->bufflen = ALUA_INQUIRY_SIZE;
-   return 1;
-   }
-   pg->bufflen = len;
-   return 0;
-}
-
 static void release_port_group(struct kref *kref)
 {
struct alua_port_group *pg;
@@ -120,8 +102,6 @@ static void release_port_group(struct kref *kref)
spin_lock(&port_group_lock);
list_del(&pg->node);
spin_unlock(&port_group_lock);
-   if (pg->buff && pg->inq != pg->buff)
-   kfree(pg->buff);
kfree(pg);
 }
 
@@ -300,8 +280,6 @@ static int alua_check_vpd(struct scsi_device *sdev, struct 
alua_dh_data *h)
return SCSI_DH_DEV_TEMP_BUSY;
}
pg->group_id = group_id;
-   pg->buff = pg->inq;
-   pg->bufflen = ALUA_INQUIRY_SIZE;
pg->tpgs = h->tpgs;
pg->state = TPGS_STATE_OPTIMIZED;
kref_init(&pg->kref);
@@ -424,8 +402,8 @@ static int alua_check_sense(struct scsi_device *sdev,
 static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg, int 
wait_for_transition)
 {
struct scsi_sense_hdr sense_hdr;
-   int len, k, off, valid_states = 0;
-   unsigned char *ucp;
+   int len, k, off, valid_states = 0, bufflen = ALUA_RTPG_SIZE;
+   unsigned char *ucp, *buff;
unsigned err, retval;
unsigned long expiry, interval = 0;
unsigned int tpg_desc_tbl_off;
@@ -436,9 +414,12 @@ static int alua_rtpg(struct scsi_device *sdev, struct 
alua_port_group *pg, int w
else
expiry = round_jiffies_up(jiffies + pg->transition_tmo * HZ);
 
+   buff = kzalloc(bufflen, GFP_KERNEL);
+   if (!buff)
+   return SCSI_DH_DEV_TEMP_BUSY;
+
  retry:
-   retval = submit_rtpg(sdev, pg->buff, pg->bufflen,
-&sense_hdr, pg->flags);
+   retval = submit_rtpg(sdev, buff, bufflen, &sense_hdr, pg->flags);
 
if (retval) {
if (!scsi_sense_valid(&sense_hdr)) {
@@ -449,6 +430,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct 
alua_port_group *pg, int w
err = SCSI_DH_DEV_TEMP_BUSY;
else
err = SCSI_DH_IO;
+   kfree(buff);
return err;
}
 
@@ -477,14 +459,18 @@ static int alua_rtpg(struct scsi_device *sdev, struct 
alua_port_group *pg, int w
sdev_printk(KERN_ERR, sdev, "%s: rtpg failed\n",
ALUA_DH_NAME);
scsi_print_sense_hdr(sdev, ALUA_DH_NAME, &sense_hdr);
+   kfree(buff);
return SCSI_DH_IO;
}
 
-   len = get_unaligned_be32(&pg->buff[0]) + 4;
+   len = get_unaligned_be32(&buff[0]) + 4;
 
-   if (len > pg->bufflen) {
+   if (len > bufflen) {
/* Resubmit with the correct length */
-   if (realloc_buffer(pg, len)) {
+   kfree(buff);
+   bufflen = len;
+   buff = kmalloc(bufflen, GFP_KERNEL);
+   if (!buff) {
sdev_printk(KERN_WARNING, sdev,
"%s: kmalloc buffer failed\n",__func__);
/* Temporary failure, bypass */
@@ -494,9 +480,8 @@ static int alua_rtpg(struct scsi_device *sdev, struct 
alua_port_group *pg, int w
}
 

[PATCH 17/23] scsi_dh_alua: use unique device id

2015-08-27 Thread Hannes Reinecke
Use scsi_vpd_lun_id() to assign a unique device identification
to the alua port group structure.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 70 +++---
 1 file changed, 65 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index dbe9ff2..c2b2100b 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -70,6 +70,8 @@ static DEFINE_SPINLOCK(port_group_lock);
 struct alua_port_group {
struct kref kref;
struct list_headnode;
+   unsigned char   device_id_str[256];
+   int device_id_size;
int group_id;
int tpgs;
int state;
@@ -229,7 +231,9 @@ static int alua_check_vpd(struct scsi_device *sdev, struct 
alua_dh_data *h)
 {
unsigned char *d;
int group_id = -1;
-   struct alua_port_group *pg = NULL;
+   char device_id_str[256];
+   int device_id_size;
+   struct alua_port_group *tmp_pg, *pg = NULL;
 
if (!sdev->vpd_pg83)
return SCSI_DH_DEV_UNSUPP;
@@ -266,9 +270,39 @@ static int alua_check_vpd(struct scsi_device *sdev, struct 
alua_dh_data *h)
h->tpgs = TPGS_MODE_NONE;
return SCSI_DH_DEV_UNSUPP;
}
+   device_id_size = scsi_vpd_lun_id(sdev, device_id_str, 256);
+   if (device_id_size <= 0) {
+   /*
+* Internal error: TPGS supported by no
+* device identifcation found.
+* Disable ALUA support.
+*/
+   sdev_printk(KERN_INFO, sdev,
+   "%s: No device descriptors found\n",
+   ALUA_DH_NAME);
+   h->tpgs = TPGS_MODE_NONE;
+   return SCSI_DH_DEV_UNSUPP;
+   }
sdev_printk(KERN_INFO, sdev,
-   "%s: port group %02x rel port %02x\n",
-   ALUA_DH_NAME, group_id, h->rel_port);
+   "%s: device %s port group %02x "
+   "rel port %02x\n", ALUA_DH_NAME,
+   device_id_str, group_id, h->rel_port);
+   spin_lock(&port_group_lock);
+   list_for_each_entry(tmp_pg, &port_group_list, node) {
+   if (tmp_pg->group_id != group_id)
+   continue;
+   if (tmp_pg->device_id_size != device_id_size)
+   continue;
+   if (strncmp(tmp_pg->device_id_str, device_id_str,
+   device_id_size))
+   continue;
+   h->pg = tmp_pg;
+   kref_get(&tmp_pg->kref);
+   break;
+   }
+   spin_unlock(&port_group_lock);
+   if (h->pg)
+   return SCSI_DH_OK;
 
pg = kzalloc(sizeof(struct alua_port_group), GFP_KERNEL);
if (!pg) {
@@ -278,13 +312,39 @@ static int alua_check_vpd(struct scsi_device *sdev, 
struct alua_dh_data *h)
/* Temporary failure, bypass */
return SCSI_DH_DEV_TEMP_BUSY;
}
+   if (device_id_size)
+   strncpy(pg->device_id_str, device_id_str, 256);
+   else
+   pg->device_id_str[0] = '\0';
+
+   pg->device_id_size = device_id_size;
pg->group_id = group_id;
pg->tpgs = h->tpgs;
pg->state = TPGS_STATE_OPTIMIZED;
kref_init(&pg->kref);
spin_lock(&port_group_lock);
-   list_add(&pg->node, &port_group_list);
-   h->pg = pg;
+   /*
+* Re-check list again to catch
+* concurrent updates
+*/
+   list_for_each_entry(tmp_pg, &port_group_list, node) {
+   if (tmp_pg->group_id != pg->group_id)
+   continue;
+   if (tmp_pg->device_id_size != pg->device_id_size)
+   continue;
+   if (strncmp(tmp_pg->device_id_str, pg->device_id_str,
+   device_id_size))
+   continue;
+   h->pg = tmp_pg;
+   kref_get(&tmp_pg->kref);
+   kfree(pg);
+   pg = NULL;
+   break;
+   }
+   if (pg) {
+   list_add(&pg->node, &port_group_list);
+   h->pg = pg;
+   }
spin_unlock(&port_group_lock);
 
return SCSI_DH_OK;
-- 
1.8.5.6

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 13/23] scsi_dh_alua: Use separate alua_port_group structure

2015-08-27 Thread Hannes Reinecke
The port group needs to be a separate structure as several
LUNs might belong to the same group.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 211 +++--
 1 file changed, 139 insertions(+), 72 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index ef4363a..d1010dd 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -64,9 +64,13 @@
 #define ALUA_OPTIMIZE_STPG 1
 #define ALUA_RTPG_EXT_HDR_UNSUPP   2
 
-struct alua_dh_data {
+static LIST_HEAD(port_group_list);
+static DEFINE_SPINLOCK(port_group_lock);
+
+struct alua_port_group {
+   struct kref kref;
+   struct list_headnode;
int group_id;
-   int rel_port;
int tpgs;
int state;
int pref;
@@ -75,6 +79,12 @@ struct alua_dh_data {
unsigned char   *buff;
int bufflen;
unsigned char   transition_tmo;
+};
+
+struct alua_dh_data {
+   struct alua_port_group  *pg;
+   int rel_port;
+   int tpgs;
struct scsi_device  *sdev;
activate_complete   callback_fn;
void*callback_data;
@@ -86,21 +96,35 @@ struct alua_dh_data {
 static char print_alua_state(int);
 static int alua_check_sense(struct scsi_device *, struct scsi_sense_hdr *);
 
-static int realloc_buffer(struct alua_dh_data *h, unsigned len)
+static int realloc_buffer(struct alua_port_group *pg, unsigned len)
 {
-   if (h->buff && h->buff != h->inq)
-   kfree(h->buff);
+   if (pg->buff && pg->buff != pg->inq)
+   kfree(pg->buff);
 
-   h->buff = kmalloc(len, GFP_NOIO);
-   if (!h->buff) {
-   h->buff = h->inq;
-   h->bufflen = ALUA_INQUIRY_SIZE;
+   pg->buff = kmalloc(len, GFP_NOIO);
+   if (!pg->buff) {
+   pg->buff = pg->inq;
+   pg->bufflen = ALUA_INQUIRY_SIZE;
return 1;
}
-   h->bufflen = len;
+   pg->bufflen = len;
return 0;
 }
 
+static void release_port_group(struct kref *kref)
+{
+   struct alua_port_group *pg;
+
+   pg = container_of(kref, struct alua_port_group, kref);
+   printk(KERN_WARNING "alua: release port group %d\n", pg->group_id);
+   spin_lock(&port_group_lock);
+   list_del(&pg->node);
+   spin_unlock(&port_group_lock);
+   if (pg->buff && pg->inq != pg->buff)
+   kfree(pg->buff);
+   kfree(pg);
+}
+
 /*
  * submit_rtpg - Issue a REPORT TARGET GROUP STATES command
  * @sdev: sdev the command should be sent to
@@ -225,6 +249,8 @@ static int alua_check_tpgs(struct scsi_device *sdev, struct 
alua_dh_data *h)
 static int alua_check_vpd(struct scsi_device *sdev, struct alua_dh_data *h)
 {
unsigned char *d;
+   int group_id = -1;
+   struct alua_port_group *pg = NULL;
 
if (!sdev->vpd_pg83)
return SCSI_DH_DEV_UNSUPP;
@@ -241,7 +267,7 @@ static int alua_check_vpd(struct scsi_device *sdev, struct 
alua_dh_data *h)
break;
case 0x5:
/* Target port group */
-   h->group_id = get_unaligned_be16(&d[6]);
+   group_id = get_unaligned_be16(&d[6]);
break;
default:
break;
@@ -249,7 +275,7 @@ static int alua_check_vpd(struct scsi_device *sdev, struct 
alua_dh_data *h)
d += d[3] + 4;
}
 
-   if (h->group_id == -1) {
+   if (group_id == -1) {
/*
 * Internal error; TPGS supported but required
 * VPD identification descriptors not present.
@@ -258,15 +284,33 @@ static int alua_check_vpd(struct scsi_device *sdev, 
struct alua_dh_data *h)
sdev_printk(KERN_INFO, sdev,
"%s: No target port descriptors found\n",
ALUA_DH_NAME);
-   h->state = TPGS_STATE_OPTIMIZED;
h->tpgs = TPGS_MODE_NONE;
return SCSI_DH_DEV_UNSUPP;
}
sdev_printk(KERN_INFO, sdev,
"%s: port group %02x rel port %02x\n",
-   ALUA_DH_NAME, h->group_id, h->rel_port);
+   ALUA_DH_NAME, group_id, h->rel_port);
 
-   return 0;
+   pg = kzalloc(sizeof(struct alua_port_group), GFP_KERNEL);
+   if (!pg) {
+   sdev_printk(KERN_WARNING, sdev,
+   "%s: kzalloc port group failed\n",
+   ALUA_DH_NAME);
+   /* Temporary failure, bypass */
+   return SCSI_DH_DEV_TEMP_BUSY;
+   }
+   pg->group_id = group_id;
+   pg->b

[PATCH 16/23] scsi: Add scsi_vpd_lun_id()

2015-08-27 Thread Hannes Reinecke
Add a function scsi_vpd_lun_id() to return a unique device
identifcation based on the designation descriptors of
VPD page 0x83.

As devices might implement several descriptors the order
of preference is:
- NAA IEE Registered Extended
- EUI-64 based 16-byte
- EUI-64 based 12-byte
- NAA IEEE Registered
- NAA IEEE Extended
A SCSI name string descriptor is preferred to all of them
if the identification is longer than 16 bytes.

The returned unique device identification will be formatted
as a SCSI Name string to avoid clashes between different
designator types.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/scsi_lib.c| 121 +
 include/scsi/scsi_device.h |   1 +
 2 files changed, 122 insertions(+)

diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 2a864b8..48d6ff6 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -3145,3 +3145,124 @@ void sdev_enable_disk_events(struct scsi_device *sdev)
atomic_dec(&sdev->disk_events_disable_depth);
 }
 EXPORT_SYMBOL(sdev_enable_disk_events);
+
+/*
+ * scsi_vpd_lun_id - return a unique device identification
+ * @sdev: SCSI device
+ * @id:   buffer for the identification
+ * @id_len:  length of the buffer
+ *
+ * Copies a unique device identification into @id based
+ * on the information in the VPD page 0x83 of the device.
+ * The string will be formatted as a SCSI name string.
+ *
+ * Returns the length of the identification or error on failure.
+ */
+int scsi_vpd_lun_id(struct scsi_device *sdev, char *id, size_t id_len)
+{
+   u8 cur_id_type = 0xff;
+   u8 cur_id_size = 0;
+   unsigned char *d, *cur_id_str;
+   int id_size = -EAGAIN;
+
+   /*
+* Look for the correct descriptor.
+* Order of preference for lun descriptor:
+* - SCSI name string
+* - NAA IEEE Registered Extended
+* - EUI-64 based 16-byte
+* - EUI-64 based 12-byte
+* - NAA IEEE Registered
+* - NAA IEEE Extended
+* as longer descriptors reduce the likelyhood
+* of identification clashes.
+*/
+
+   /* The id string must be at least 20 bytes + terminating NULL byte */
+   if (id_len < 21)
+   return -EINVAL;
+
+   memset(id, 0, id_len);
+   d = sdev->vpd_pg83 + 4;
+   while (d < sdev->vpd_pg83 + sdev->vpd_pg83_len) {
+   /* Skip designators not referring to the LUN */
+   if ((d[1] & 0x30) != 0x00)
+   goto next_desig;
+
+   switch (d[1] & 0xf) {
+   case 0x2:
+   /* EUI-64 */
+   if (cur_id_size > d[3])
+   break;
+   /* Prefer NAA IEEE Registered Extended */
+   if (cur_id_type == 0x3 &&
+   cur_id_size == d[3])
+   break;
+   cur_id_size = d[3];
+   cur_id_str = d + 4;
+   cur_id_type = d[1] & 0xf;
+   switch (cur_id_size) {
+   case 8:
+   id_size = snprintf(id, id_len,
+  "eui.%8phN",
+  cur_id_str);
+   break;
+   case 12:
+   id_size = snprintf(id, id_len,
+  "eui.%12phN",
+  cur_id_str);
+   break;
+   case 16:
+   id_size = snprintf(id, id_len,
+  "eui.%16phN",
+  cur_id_str);
+   break;
+   default:
+   cur_id_size = 0;
+   break;
+   }
+   break;
+   case 0x3:
+   /* NAA */
+   if (cur_id_size > d[3])
+   break;
+   cur_id_size = d[3];
+   cur_id_str = d + 4;
+   cur_id_type = d[1] & 0xf;
+   switch (cur_id_size) {
+   case 8:
+   id_size = snprintf(id, id_len,
+  "naa.%8phN",
+  cur_id_str);
+   break;
+   case 16:
+   id_size = snprintf(id, id_len,
+  "naa.%16phN",
+  cur_id_str);
+   break;
+   default:
+   c

[PATCH 21/23] scsi_dh_alua: update all port states

2015-08-27 Thread Hannes Reinecke
When we read in the target port group state we should be
updating all affected port groups, otherwise we risk
running out of sync.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 21 +
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index 8717fd3..2fa985e 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -477,11 +477,13 @@ static int alua_check_sense(struct scsi_device *sdev,
 static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg)
 {
struct scsi_sense_hdr sense_hdr;
+   struct alua_port_group *tmp_pg;
int len, k, off, valid_states = 0, bufflen = ALUA_RTPG_SIZE;
unsigned char *ucp, *buff;
unsigned err, retval;
unsigned int tpg_desc_tbl_off;
unsigned char orig_transition_tmo;
+   unsigned long flags;
 
if (!pg->expiry) {
if (!pg->transition_tmo)
@@ -584,17 +586,28 @@ static int alua_rtpg(struct scsi_device *sdev, struct 
alua_port_group *pg)
else
tpg_desc_tbl_off = 4;
 
+   spin_lock_irqsave(&port_group_lock, flags);
for (k = tpg_desc_tbl_off, ucp = buff + tpg_desc_tbl_off;
 k < len;
 k += off, ucp += off) {
 
-   if (pg->group_id == get_unaligned_be16(&ucp[2])) {
-   pg->state = ucp[0] & 0x0f;
-   pg->pref = ucp[0] >> 7;
-   valid_states = ucp[1];
+   list_for_each_entry(tmp_pg, &port_group_list, node) {
+   u16 group_id = get_unaligned_be16(&ucp[2]);
+   if (tmp_pg->group_id != group_id)
+   continue;
+   if (tmp_pg->device_id_size != pg->device_id_size)
+   continue;
+   if (strncmp(tmp_pg->device_id_str, pg->device_id_str,
+   tmp_pg->device_id_size))
+   continue;
+   tmp_pg->state = ucp[0] & 0x0f;
+   tmp_pg->pref = ucp[0] >> 7;
+   if (tmp_pg == pg)
+   valid_states = ucp[1];
}
off = 8 + (ucp[7] * 4);
}
+   spin_unlock_irqrestore(&port_group_lock, flags);
 
sdev_printk(KERN_INFO, sdev,
"%s: port group %02x state %c %s supports %c%c%c%c%c%c%c\n",
-- 
1.8.5.6

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 08/23] scsi_dh_alua: use flag for RTPG extended header

2015-08-27 Thread Hannes Reinecke
We should be using a flag when RTPG extended header is not
supported, that saves us sending RTPG twice for older arrays.

Reviewed-by: Bart Van Assche 
Reviewed-by: Christoph Hellwig 
Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 15 +++
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index 25c2045..9d8fc53 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -59,8 +59,9 @@
 #define ALUA_FAILOVER_TIMEOUT  60
 #define ALUA_FAILOVER_RETRIES  5
 
-/* flags passed from user level */
+/* device handler flags */
 #define ALUA_OPTIMIZE_STPG 1
+#define ALUA_RTPG_EXT_HDR_UNSUPP   2
 
 struct alua_dh_data {
int group_id;
@@ -135,8 +136,7 @@ static struct request *get_alua_req(struct scsi_device 
*sdev,
  * submit_rtpg - Issue a REPORT TARGET GROUP STATES command
  * @sdev: sdev the command should be sent to
  */
-static unsigned submit_rtpg(struct scsi_device *sdev, struct alua_dh_data *h,
-   bool rtpg_ext_hdr_req)
+static unsigned submit_rtpg(struct scsi_device *sdev, struct alua_dh_data *h)
 {
struct request *rq;
int err = 0;
@@ -149,7 +149,7 @@ static unsigned submit_rtpg(struct scsi_device *sdev, 
struct alua_dh_data *h,
 
/* Prepare the command. */
rq->cmd[0] = MAINTENANCE_IN;
-   if (rtpg_ext_hdr_req)
+   if (!(h->flags & ALUA_RTPG_EXT_HDR_UNSUPP))
rq->cmd[1] = MI_REPORT_TARGET_PGS | MI_EXT_HDR_PARAM_FMT;
else
rq->cmd[1] = MI_REPORT_TARGET_PGS;
@@ -487,7 +487,6 @@ static int alua_rtpg(struct scsi_device *sdev, struct 
alua_dh_data *h, int wait_
int len, k, off, valid_states = 0;
unsigned char *ucp;
unsigned err, retval;
-   bool rtpg_ext_hdr_req = 1;
unsigned long expiry, interval = 0;
unsigned int tpg_desc_tbl_off;
unsigned char orig_transition_tmo;
@@ -498,7 +497,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct 
alua_dh_data *h, int wait_
expiry = round_jiffies_up(jiffies + h->transition_tmo * HZ);
 
  retry:
-   retval = submit_rtpg(sdev, h, rtpg_ext_hdr_req);
+   retval = submit_rtpg(sdev, h);
 
if (retval) {
if (!scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE,
@@ -521,10 +520,10 @@ static int alua_rtpg(struct scsi_device *sdev, struct 
alua_dh_data *h, int wait_
 * The retry without rtpg_ext_hdr_req set
 * handles this.
 */
-   if (rtpg_ext_hdr_req == 1 &&
+   if (!(h->flags & ALUA_RTPG_EXT_HDR_UNSUPP) &&
sense_hdr.sense_key == ILLEGAL_REQUEST &&
sense_hdr.asc == 0x24 && sense_hdr.ascq == 0) {
-   rtpg_ext_hdr_req = 0;
+   h->flags |= ALUA_RTPG_EXT_HDR_UNSUPP;
goto retry;
}
 
-- 
1.8.5.6

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 07/23] scsi: remove scsi_show_sense_hdr()

2015-08-27 Thread Hannes Reinecke
Last caller is gone, so remove it.

Reviewed-by: Bart Van Assche 
Reviewed-by: Reviewed-by: Christoph Hellwig 
Signed-off-by: Hannes Reinecke 
---
 include/scsi/scsi_dbg.h | 2 --
 1 file changed, 2 deletions(-)

diff --git a/include/scsi/scsi_dbg.h b/include/scsi/scsi_dbg.h
index f8170e9..56710e0 100644
--- a/include/scsi/scsi_dbg.h
+++ b/include/scsi/scsi_dbg.h
@@ -12,8 +12,6 @@ extern size_t __scsi_format_command(char *, size_t,
   const unsigned char *, size_t);
 extern void scsi_show_extd_sense(const struct scsi_device *, const char *,
 unsigned char, unsigned char);
-extern void scsi_show_sense_hdr(const struct scsi_device *, const char *,
-   const struct scsi_sense_hdr *);
 extern void scsi_print_sense_hdr(const struct scsi_device *, const char *,
 const struct scsi_sense_hdr *);
 extern void scsi_print_sense(const struct scsi_cmnd *);
-- 
1.8.5.6

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 23/23] scsi_dh_alua: Update version to 2.0

2015-08-27 Thread Hannes Reinecke
Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index 3c6b365..5b15936 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -31,7 +31,7 @@
 #include 
 
 #define ALUA_DH_NAME "alua"
-#define ALUA_DH_VER "1.3"
+#define ALUA_DH_VER "2.0"
 
 #define TPGS_STATE_OPTIMIZED   0x0
 #define TPGS_STATE_NONOPTIMIZED0x1
-- 
1.8.5.6

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 10/23] scsi_dh_alua: Pass buffer as function argument

2015-08-27 Thread Hannes Reinecke
Pass in the buffer as a function argument for submit_rtpg().

Reviewed-by: Bart Van Assche 
Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 20 ++--
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index 0636721..9e2b3af 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -137,12 +137,13 @@ static struct request *get_alua_req(struct scsi_device 
*sdev,
  * submit_rtpg - Issue a REPORT TARGET GROUP STATES command
  * @sdev: sdev the command should be sent to
  */
-static unsigned submit_rtpg(struct scsi_device *sdev, struct alua_dh_data *h)
+static unsigned submit_rtpg(struct scsi_device *sdev, unsigned char *buff,
+   int bufflen, unsigned char *sense, int flags)
 {
struct request *rq;
int err = 0;
 
-   rq = get_alua_req(sdev, h->buff, h->bufflen, READ);
+   rq = get_alua_req(sdev, buff, bufflen, READ);
if (!rq) {
err = DRIVER_BUSY << 24;
goto done;
@@ -150,22 +151,21 @@ static unsigned submit_rtpg(struct scsi_device *sdev, 
struct alua_dh_data *h)
 
/* Prepare the command. */
rq->cmd[0] = MAINTENANCE_IN;
-   if (!(h->flags & ALUA_RTPG_EXT_HDR_UNSUPP))
+   if (!(flags & ALUA_RTPG_EXT_HDR_UNSUPP))
rq->cmd[1] = MI_REPORT_TARGET_PGS | MI_EXT_HDR_PARAM_FMT;
else
rq->cmd[1] = MI_REPORT_TARGET_PGS;
-   put_unaligned_be32(h->bufflen, &rq->cmd[6]);
+   put_unaligned_be32(bufflen, &rq->cmd[6]);
rq->cmd_len = COMMAND_SIZE(MAINTENANCE_IN);
 
-   rq->sense = h->sense;
+   rq->sense = sense;
memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
-   rq->sense_len = h->senselen = 0;
+   rq->sense_len = 0;
 
blk_execute_rq(rq->q, NULL, rq, 1);
-   if (rq->errors) {
+   if (rq->errors)
err = rq->errors;
-   h->senselen = rq->sense_len;
-   }
+
blk_put_request(rq);
 done:
return err;
@@ -491,7 +491,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct 
alua_dh_data *h, int wait_
expiry = round_jiffies_up(jiffies + h->transition_tmo * HZ);
 
  retry:
-   retval = submit_rtpg(sdev, h);
+   retval = submit_rtpg(sdev, h->buff, h->bufflen, h->sense, h->flags);
 
if (retval) {
if (!scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE,
-- 
1.8.5.6

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 11/23] scsi_dh_alua: Make stpg synchronous

2015-08-27 Thread Hannes Reinecke
We should be issuing STPG synchronously as we need to
evaluate the return code on failure.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 179 +
 1 file changed, 83 insertions(+), 96 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index 9e2b3af..fd0385e 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -172,76 +172,28 @@ done:
 }
 
 /*
- * stpg_endio - Evaluate SET TARGET GROUP STATES
- * @sdev: the device to be evaluated
- * @state: the new target group state
- *
- * Evaluate a SET TARGET GROUP STATES command response.
- */
-static void stpg_endio(struct request *req, int error)
-{
-   struct alua_dh_data *h = req->end_io_data;
-   struct scsi_sense_hdr sense_hdr;
-   unsigned err = SCSI_DH_OK;
-
-   if (host_byte(req->errors) != DID_OK ||
-   msg_byte(req->errors) != COMMAND_COMPLETE) {
-   err = SCSI_DH_IO;
-   goto done;
-   }
-
-   if (scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE,
-&sense_hdr)) {
-   err = alua_check_sense(h->sdev, &sense_hdr);
-   if (err == ADD_TO_MLQUEUE) {
-   err = SCSI_DH_RETRY;
-   goto done;
-   }
-   sdev_printk(KERN_INFO, h->sdev, "%s: stpg failed\n",
-   ALUA_DH_NAME);
-   scsi_print_sense_hdr(h->sdev, ALUA_DH_NAME, &sense_hdr);
-   err = SCSI_DH_IO;
-   } else if (error)
-   err = SCSI_DH_IO;
-
-   if (err == SCSI_DH_OK) {
-   h->state = TPGS_STATE_OPTIMIZED;
-   sdev_printk(KERN_INFO, h->sdev,
-   "%s: port group %02x switched to state %c\n",
-   ALUA_DH_NAME, h->group_id,
-   print_alua_state(h->state));
-   }
-done:
-   req->end_io_data = NULL;
-   __blk_put_request(req->q, req);
-   if (h->callback_fn) {
-   h->callback_fn(h->callback_data, err);
-   h->callback_fn = h->callback_data = NULL;
-   }
-   return;
-}
-
-/*
  * submit_stpg - Issue a SET TARGET GROUP STATES command
  *
  * Currently we're only setting the current target port group state
  * to 'active/optimized' and let the array firmware figure out
  * the states of the remaining groups.
  */
-static unsigned submit_stpg(struct alua_dh_data *h)
+static unsigned submit_stpg(struct scsi_device *sdev, int group_id,
+   unsigned char *sense)
 {
struct request *rq;
+   unsigned char stpg_data[8];
int stpg_len = 8;
-   struct scsi_device *sdev = h->sdev;
+   int err = 0;
 
/* Prepare the data buffer */
-   memset(h->buff, 0, stpg_len);
-   h->buff[4] = TPGS_STATE_OPTIMIZED & 0x0f;
-   put_unaligned_be16(h->group_id, &h->buff[6]);
+   memset(stpg_data, 0, stpg_len);
+   stpg_data[4] = TPGS_STATE_OPTIMIZED & 0x0f;
+   put_unaligned_be16(group_id, &stpg_data[6]);
 
-   rq = get_alua_req(sdev, h->buff, stpg_len, WRITE);
+   rq = get_alua_req(sdev, stpg_data, stpg_len, WRITE);
if (!rq)
-   return SCSI_DH_RES_TEMP_UNAVAIL;
+   return DRIVER_BUSY << 24;
 
/* Prepare the command. */
rq->cmd[0] = MAINTENANCE_OUT;
@@ -249,13 +201,17 @@ static unsigned submit_stpg(struct alua_dh_data *h)
put_unaligned_be32(stpg_len, &rq->cmd[6]);
rq->cmd_len = COMMAND_SIZE(MAINTENANCE_OUT);
 
-   rq->sense = h->sense;
+   rq->sense = sense;
memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
-   rq->sense_len = h->senselen = 0;
-   rq->end_io_data = h;
+   rq->sense_len = 0;
+
+   blk_execute_rq(rq->q, NULL, rq, 1);
+   if (rq->errors)
+   err = rq->errors;
+
+   blk_put_request(rq);
 
-   blk_execute_rq_nowait(rq->q, NULL, rq, 1, stpg_endio);
-   return SCSI_DH_OK;
+   return err;
 }
 
 /*
@@ -619,6 +575,68 @@ static int alua_rtpg(struct scsi_device *sdev, struct 
alua_dh_data *h, int wait_
 }
 
 /*
+ * alua_stpg - Issue a SET TARGET GROUP STATES command
+ *
+ * Issue a SET TARGET GROUP STATES command and evaluate the
+ * response. Returns SCSI_DH_RETRY per default to trigger
+ * a re-evaluation of the target group state.
+ */
+static unsigned alua_stpg(struct scsi_device *sdev, struct alua_dh_data *h)
+{
+   int retval;
+   struct scsi_sense_hdr sense_hdr;
+
+   if (!(h->tpgs & TPGS_MODE_EXPLICIT)) {
+   /* Only implicit ALUA supported, retry */
+   return SCSI_DH_RETRY;
+   }
+   switch (h->state) {
+   case TPGS_STATE_OPTIMIZED:
+   return SCSI_DH_OK;
+   case TPGS_STATE_NONOPTIMIZED:
+   if ((h->flags & ALUA_OPTIMIZE_STPG) &&
+   !h->pref &&
+   (h

[PATCH 04/23] scsi_dh_alua: use standard logging functions

2015-08-27 Thread Hannes Reinecke
Use standard logging functions instead of hand-crafted ones.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 34 +-
 1 file changed, 15 insertions(+), 19 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index a20c8bf..7b43ee3 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -23,6 +23,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -194,22 +195,16 @@ static void stpg_endio(struct request *req, int error)
goto done;
}
 
-   if (req->sense_len > 0) {
-   err = scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE,
-  &sense_hdr);
-   if (!err) {
-   err = SCSI_DH_IO;
-   goto done;
-   }
+   if (scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE,
+&sense_hdr)) {
err = alua_check_sense(h->sdev, &sense_hdr);
if (err == ADD_TO_MLQUEUE) {
err = SCSI_DH_RETRY;
goto done;
}
-   sdev_printk(KERN_INFO, h->sdev,
-   "%s: stpg sense code: %02x/%02x/%02x\n",
-   ALUA_DH_NAME, sense_hdr.sense_key,
-   sense_hdr.asc, sense_hdr.ascq);
+   sdev_printk(KERN_INFO, h->sdev, "%s: stpg failed\n",
+   ALUA_DH_NAME);
+   scsi_print_sense_hdr(h->sdev, ALUA_DH_NAME, &sense_hdr);
err = SCSI_DH_IO;
} else if (error)
err = SCSI_DH_IO;
@@ -530,16 +525,17 @@ static int alua_rtpg(struct scsi_device *sdev, struct 
alua_dh_data *h, int wait_
}
 
err = alua_check_sense(sdev, &sense_hdr);
-   if (err == ADD_TO_MLQUEUE && time_before(jiffies, expiry))
+   if (err == ADD_TO_MLQUEUE && time_before(jiffies, expiry)) {
+   sdev_printk(KERN_ERR, sdev, "%s: rtpg retry\n",
+   ALUA_DH_NAME);
+   scsi_print_sense_hdr(sdev, ALUA_DH_NAME, &sense_hdr);
goto retry;
-   sdev_printk(KERN_INFO, sdev,
-   "%s: rtpg sense code %02x/%02x/%02x\n",
-   ALUA_DH_NAME, sense_hdr.sense_key,
-   sense_hdr.asc, sense_hdr.ascq);
-   err = SCSI_DH_IO;
+   }
+   sdev_printk(KERN_ERR, sdev, "%s: rtpg failed\n",
+   ALUA_DH_NAME);
+   scsi_print_sense_hdr(sdev, ALUA_DH_NAME, &sense_hdr);
+   return SCSI_DH_IO;
}
-   if (err != SCSI_DH_OK)
-   return err;
 
len = (h->buff[0] << 24) + (h->buff[1] << 16) +
(h->buff[2] << 8) + h->buff[3] + 4;
-- 
1.8.5.6

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 05/23] scsi_dh_alua: return standard SCSI return codes in submit_rtpg

2015-08-27 Thread Hannes Reinecke
Fixup submit_rtpg() to always return a standard SCSI return code.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 38 +-
 1 file changed, 22 insertions(+), 16 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index 7b43ee3..c41d662 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -139,11 +139,13 @@ static unsigned submit_rtpg(struct scsi_device *sdev, 
struct alua_dh_data *h,
bool rtpg_ext_hdr_req)
 {
struct request *rq;
-   int err = SCSI_DH_RES_TEMP_UNAVAIL;
+   int err = 0;
 
rq = get_alua_req(sdev, h->buff, h->bufflen, READ);
-   if (!rq)
+   if (!rq) {
+   err = DRIVER_BUSY << 24;
goto done;
+   }
 
/* Prepare the command. */
rq->cmd[0] = MAINTENANCE_IN;
@@ -161,13 +163,10 @@ static unsigned submit_rtpg(struct scsi_device *sdev, 
struct alua_dh_data *h,
memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
rq->sense_len = h->senselen = 0;
 
-   err = blk_execute_rq(rq->q, NULL, rq, 1);
-   if (err == -EIO) {
-   sdev_printk(KERN_INFO, sdev,
-   "%s: rtpg failed with %x\n",
-   ALUA_DH_NAME, rq->errors);
+   blk_execute_rq(rq->q, NULL, rq, 1);
+   if (rq->errors) {
+   err = rq->errors;
h->senselen = rq->sense_len;
-   err = SCSI_DH_IO;
}
blk_put_request(rq);
 done:
@@ -489,7 +488,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct 
alua_dh_data *h, int wait_
struct scsi_sense_hdr sense_hdr;
int len, k, off, valid_states = 0;
unsigned char *ucp;
-   unsigned err;
+   unsigned err, retval;
bool rtpg_ext_hdr_req = 1;
unsigned long expiry, interval = 0;
unsigned int tpg_desc_tbl_off;
@@ -501,13 +500,20 @@ static int alua_rtpg(struct scsi_device *sdev, struct 
alua_dh_data *h, int wait_
expiry = round_jiffies_up(jiffies + h->transition_tmo * HZ);
 
  retry:
-   err = submit_rtpg(sdev, h, rtpg_ext_hdr_req);
-
-   if (err == SCSI_DH_IO && h->senselen > 0) {
-   err = scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE,
-  &sense_hdr);
-   if (!err)
-   return SCSI_DH_IO;
+   retval = submit_rtpg(sdev, h, rtpg_ext_hdr_req);
+
+   if (retval) {
+   if (!scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE,
+ &sense_hdr)) {
+   sdev_printk(KERN_INFO, sdev,
+   "%s: rtpg failed, result %d\n",
+   ALUA_DH_NAME, retval);
+   if (driver_byte(retval) == DRIVER_BUSY)
+   err = SCSI_DH_DEV_TEMP_BUSY;
+   else
+   err = SCSI_DH_IO;
+   return err;
+   }
 
/*
 * submit_rtpg() has failed on existing arrays
-- 
1.8.5.6

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 00/15] Big fixes, retries, handle a race condition

2015-08-27 Thread Yaniv Gardi
Important:
This serie of 15 small patches should be pushed after the series of 8 patches
"Fix error message and present UFS variant probe"

V2:
a few minor changes

V1:
This serie of 15 small patches should be pushed after the series of 8 patches
I have uploaded to the upstream a week ago:
"Fix error message and present UFS variant probe"

Yaniv Gardi (15):
  scsi: ufs: clear UTRD, UPIU req and rsp before new transfers
  scsi: ufs: clear fields UTRD, UPIU req and rsp before new transfers
  scsi: ufs: verify command tag validity
  scsi: ufs: clear outstanding_request bit in case query timeout
  scsi: ufs: increase fDeviceInit query response timeout
  scsi: ufs: avoid exception event handler racing with PM callbacks
  scsi: ufs: set REQUEST_SENSE command size to 18 bytes
  scsi: ufs: add retries to dme_peer get and set attribute
  scsi: ufs: add retries for hibern8 enter
  scsi: ufs: fix error recovery after the hibern8 exit failure
  scsi: ufs: retry failed query flag requests
  scsi: ufs: reduce the interrupts for power mode change requests
  scsi: ufs: add missing memory barriers
  scsi: ufs: commit descriptors before setting the doorbell
  scsi: ufs: add wrapper for retrying sending query attribute

 drivers/scsi/ufs/ufshcd.c | 413 --
 drivers/scsi/ufs/ufshcd.h |   4 +
 2 files changed, 332 insertions(+), 85 deletions(-)

-- 
1.8.5.2

-- 
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 01/23] scsi_dh_alua: Disable ALUA handling for non-disk devices

2015-08-27 Thread Hannes Reinecke
Non-disk devices might support ALUA, but the firmware
implementation is untested and frequently broken.
As we're don't actually need it disable ALUA support
for non-disk device for now.

Signed-off-by: Hannes Reinecke 
Reviewed-by: Bart Van Assche 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index cc2773b..7d01ef0 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -320,6 +320,18 @@ static int alua_check_tpgs(struct scsi_device *sdev, 
struct alua_dh_data *h)
 {
int err = SCSI_DH_OK;
 
+   /*
+* ALUA support for non-disk devices is fraught with
+* difficulties, so disable it for now.
+*/
+   if (sdev->type != TYPE_DISK) {
+   h->tpgs = TPGS_MODE_NONE;
+   sdev_printk(KERN_INFO, sdev,
+   "%s: disable for non-disk devices\n",
+   ALUA_DH_NAME);
+   return SCSI_DH_DEV_UNSUPP;
+   }
+
h->tpgs = scsi_device_tpgs(sdev);
switch (h->tpgs) {
case TPGS_MODE_EXPLICIT|TPGS_MODE_IMPLICIT:
-- 
1.8.5.6

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 12/23] scsi_dh_alua: switch to scsi_execute_req_flags()

2015-08-27 Thread Hannes Reinecke
All commands are issued synchronously, so no need to open-code
scsi_execute_req_flags() anymore. And we can get rid of the
static sense code structure element.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 124 -
 1 file changed, 34 insertions(+), 90 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index fd0385e..ef4363a 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -75,8 +75,6 @@ struct alua_dh_data {
unsigned char   *buff;
int bufflen;
unsigned char   transition_tmo;
-   unsigned char   sense[SCSI_SENSE_BUFFERSIZE];
-   int senselen;
struct scsi_device  *sdev;
activate_complete   callback_fn;
void*callback_data;
@@ -103,72 +101,30 @@ static int realloc_buffer(struct alua_dh_data *h, 
unsigned len)
return 0;
 }
 
-static struct request *get_alua_req(struct scsi_device *sdev,
-   void *buffer, unsigned buflen, int rw)
-{
-   struct request *rq;
-   struct request_queue *q = sdev->request_queue;
-
-   rq = blk_get_request(q, rw, GFP_NOIO);
-
-   if (IS_ERR(rq)) {
-   sdev_printk(KERN_INFO, sdev,
-   "%s: blk_get_request failed\n", __func__);
-   return NULL;
-   }
-   blk_rq_set_block_pc(rq);
-
-   if (buflen && blk_rq_map_kern(q, rq, buffer, buflen, GFP_NOIO)) {
-   blk_put_request(rq);
-   sdev_printk(KERN_INFO, sdev,
-   "%s: blk_rq_map_kern failed\n", __func__);
-   return NULL;
-   }
-
-   rq->cmd_flags |= REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT |
-REQ_FAILFAST_DRIVER;
-   rq->retries = ALUA_FAILOVER_RETRIES;
-   rq->timeout = ALUA_FAILOVER_TIMEOUT * HZ;
-
-   return rq;
-}
-
 /*
  * submit_rtpg - Issue a REPORT TARGET GROUP STATES command
  * @sdev: sdev the command should be sent to
  */
-static unsigned submit_rtpg(struct scsi_device *sdev, unsigned char *buff,
-   int bufflen, unsigned char *sense, int flags)
+static int submit_rtpg(struct scsi_device *sdev, unsigned char *buff,
+  int bufflen, struct scsi_sense_hdr *sshdr, int flags)
 {
-   struct request *rq;
-   int err = 0;
-
-   rq = get_alua_req(sdev, buff, bufflen, READ);
-   if (!rq) {
-   err = DRIVER_BUSY << 24;
-   goto done;
-   }
+   u8 cdb[16];
+   int req_flags = REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT |
+   REQ_FAILFAST_DRIVER;
 
/* Prepare the command. */
-   rq->cmd[0] = MAINTENANCE_IN;
+   memset(cdb, 0x0, 16);
+   cdb[0] = MAINTENANCE_IN;
if (!(flags & ALUA_RTPG_EXT_HDR_UNSUPP))
-   rq->cmd[1] = MI_REPORT_TARGET_PGS | MI_EXT_HDR_PARAM_FMT;
+   cdb[1] = MI_REPORT_TARGET_PGS | MI_EXT_HDR_PARAM_FMT;
else
-   rq->cmd[1] = MI_REPORT_TARGET_PGS;
-   put_unaligned_be32(bufflen, &rq->cmd[6]);
-   rq->cmd_len = COMMAND_SIZE(MAINTENANCE_IN);
-
-   rq->sense = sense;
-   memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
-   rq->sense_len = 0;
+   cdb[1] = MI_REPORT_TARGET_PGS;
+   put_unaligned_be32(bufflen, &cdb[6]);
 
-   blk_execute_rq(rq->q, NULL, rq, 1);
-   if (rq->errors)
-   err = rq->errors;
-
-   blk_put_request(rq);
-done:
-   return err;
+   return scsi_execute_req_flags(sdev, cdb, DMA_FROM_DEVICE,
+ buff, bufflen, sshdr,
+ ALUA_FAILOVER_TIMEOUT * HZ,
+ ALUA_FAILOVER_RETRIES, NULL, req_flags);
 }
 
 /*
@@ -178,40 +134,30 @@ done:
  * to 'active/optimized' and let the array firmware figure out
  * the states of the remaining groups.
  */
-static unsigned submit_stpg(struct scsi_device *sdev, int group_id,
-   unsigned char *sense)
+static int submit_stpg(struct scsi_device *sdev, int group_id,
+  struct scsi_sense_hdr *sshdr)
 {
-   struct request *rq;
+   u8 cdb[COMMAND_SIZE(MAINTENANCE_OUT)];
unsigned char stpg_data[8];
int stpg_len = 8;
-   int err = 0;
+   int req_flags = REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT |
+   REQ_FAILFAST_DRIVER;
 
/* Prepare the data buffer */
memset(stpg_data, 0, stpg_len);
stpg_data[4] = TPGS_STATE_OPTIMIZED & 0x0f;
put_unaligned_be16(group_id, &stpg_data[6]);
 
-   rq = get_alua_req(sdev, stpg_data, stpg_len, WRITE);
-   if (!rq)
-   return DRIVER_BUSY << 24;
-
/* Prepare the command. */
-   rq->cmd[0] = MAINTENANCE_OUT;
-   rq->cmd[1] = MO_SE

[PATCH v2 02/15] scsi: ufs: clear fields UTRD, UPIU req and rsp before new transfers

2015-08-27 Thread Yaniv Gardi
Some of the data structures (like response UPIU) and/or its elements
(unused fields) should be cleared before sending out the respective
command to UFS device.

This change clears the UPIU response data structure for query commands
and NOP command before sending out the command. We also initialize the
PRDT table length to zero which should take care of commands which doesn't
have any data associated with it. We are also clearing the unused fields in
request UPIU for NOP command.

Signed-off-by: Subhash Jadavani 
Signed-off-by: Yaniv Gardi 

---
 drivers/scsi/ufs/ufshcd.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 3428f72..2d3ebca 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -1129,6 +1129,8 @@ static void ufshcd_prepare_req_desc_hdr(struct ufshcd_lrb 
*lrbp,
cpu_to_le32(OCS_INVALID_COMMAND_STATUS);
/* dword_3 is reserved, hence it is set to 0 */
req_desc->header.dword_3 = 0;
+
+   req_desc->prd_table_length = 0;
 }
 
 /**
@@ -1198,6 +1200,7 @@ static void ufshcd_prepare_utp_query_req_upiu(struct 
ufs_hba *hba,
if (query->request.upiu_req.opcode == UPIU_QUERY_OPCODE_WRITE_DESC)
memcpy(descp, query->descriptor, len);
 
+   memset(lrbp->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
 }
 
 static inline void ufshcd_prepare_utp_nop_upiu(struct ufshcd_lrb *lrbp)
@@ -1210,6 +1213,11 @@ static inline void ufshcd_prepare_utp_nop_upiu(struct 
ufshcd_lrb *lrbp)
ucd_req_ptr->header.dword_0 =
UPIU_HEADER_DWORD(
UPIU_TRANSACTION_NOP_OUT, 0, 0, lrbp->task_tag);
+   /* clear rest of the fields of basic header */
+   ucd_req_ptr->header.dword_1 = 0;
+   ucd_req_ptr->header.dword_2 = 0;
+
+   memset(lrbp->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
 }
 
 /**
-- 
1.8.5.2

-- 
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 01/15] scsi: ufs: clear UTRD, UPIU req and rsp before new transfers

2015-08-27 Thread Yaniv Gardi
Clear the UFS data structures before sending new request.

The SCSI command is sent to the device within the UFS UPIU request.
As part of the transfer UPIU preparation, the SCSI command is copied
to the UPIU structure according to the SCSI command size.
As different SCSI commands differ in size from each other, we need
to clear the whole SCSI command field to prevent sending uninitialized
data to the device.

The UPIU response doesn't always include the sense data and can differ
in size.
Hence, the UPIU response should also be cleared before the transfer.

Signed-off-by: Subhash Jadavani 
Signed-off-by: Maya Erez 
Signed-off-by: Yaniv Gardi 

---
 drivers/scsi/ufs/ufshcd.c | 17 +
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 131c720..3428f72 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -3,7 +3,7 @@
  *
  * This code is based on drivers/scsi/ufs/ufshcd.c
  * Copyright (C) 2011-2013 Samsung India Software Operations
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
  *
  * Authors:
  * Santosh Yaraganavi 
@@ -1035,6 +1035,7 @@ static int ufshcd_map_sg(struct ufshcd_lrb *lrbp)
cpu_to_le32(lower_32_bits(sg->dma_address));
prd_table[i].upper_addr =
cpu_to_le32(upper_32_bits(sg->dma_address));
+   prd_table[i].reserved = 0;
}
} else {
lrbp->utr_descriptor_ptr->prd_table_length = 0;
@@ -1117,7 +1118,8 @@ static void ufshcd_prepare_req_desc_hdr(struct ufshcd_lrb 
*lrbp,
 
/* Transfer request descriptor header fields */
req_desc->header.dword_0 = cpu_to_le32(dword_0);
-
+   /* dword_1 is reserved, hence it is set to 0 */
+   req_desc->header.dword_1 = 0;
/*
 * assigning invalid value for command status. Controller
 * updates OCS on command completion, with the command
@@ -1125,6 +1127,8 @@ static void ufshcd_prepare_req_desc_hdr(struct ufshcd_lrb 
*lrbp,
 */
req_desc->header.dword_2 =
cpu_to_le32(OCS_INVALID_COMMAND_STATUS);
+   /* dword_3 is reserved, hence it is set to 0 */
+   req_desc->header.dword_3 = 0;
 }
 
 /**
@@ -1137,6 +1141,7 @@ static
 void ufshcd_prepare_utp_scsi_cmd_upiu(struct ufshcd_lrb *lrbp, u32 upiu_flags)
 {
struct utp_upiu_req *ucd_req_ptr = lrbp->ucd_req_ptr;
+   unsigned short cdb_len;
 
/* command descriptor fields */
ucd_req_ptr->header.dword_0 = UPIU_HEADER_DWORD(
@@ -1151,8 +1156,12 @@ void ufshcd_prepare_utp_scsi_cmd_upiu(struct ufshcd_lrb 
*lrbp, u32 upiu_flags)
ucd_req_ptr->sc.exp_data_transfer_len =
cpu_to_be32(lrbp->cmd->sdb.length);
 
-   memcpy(ucd_req_ptr->sc.cdb, lrbp->cmd->cmnd,
-   (min_t(unsigned short, lrbp->cmd->cmd_len, MAX_CDB_SIZE)));
+   cdb_len = min_t(unsigned short, lrbp->cmd->cmd_len, MAX_CDB_SIZE);
+   memcpy(ucd_req_ptr->sc.cdb, lrbp->cmd->cmnd, cdb_len);
+   if (cdb_len < MAX_CDB_SIZE)
+   memset(ucd_req_ptr->sc.cdb + cdb_len, 0,
+  (MAX_CDB_SIZE - cdb_len));
+   memset(lrbp->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
 }
 
 /**
-- 
1.8.5.2

-- 
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 03/23] scsi_dh_alua: improved logging

2015-08-27 Thread Hannes Reinecke
Issue different logging messages if ALUA is not supported
or the TPGS setting is invalid.

Reviewed-by: Christoph Hellwig 
Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 10 --
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index f15b977..a20c8bf 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -310,12 +310,18 @@ static int alua_check_tpgs(struct scsi_device *sdev, 
struct alua_dh_data *h)
sdev_printk(KERN_INFO, sdev, "%s: supports implicit TPGS\n",
ALUA_DH_NAME);
break;
-   default:
-   h->tpgs = TPGS_MODE_NONE;
+   case TPGS_MODE_NONE:
sdev_printk(KERN_INFO, sdev, "%s: not supported\n",
ALUA_DH_NAME);
err = SCSI_DH_DEV_UNSUPP;
break;
+   default:
+   sdev_printk(KERN_INFO, sdev,
+   "%s: unsupported TPGS setting %d\n",
+   ALUA_DH_NAME, h->tpgs);
+   h->tpgs = TPGS_MODE_NONE;
+   err = SCSI_DH_DEV_UNSUPP;
+   break;
}
 
return err;
-- 
1.8.5.6

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 02/23] scsi_dh_alua: Use vpd_pg83 information

2015-08-27 Thread Hannes Reinecke
The SCSI device now has the VPD page 0x83 information attached,
so there is no need to query it again.

Reviewed-by: Christoph Hellwig 
Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 83 +-
 1 file changed, 13 insertions(+), 70 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index 7d01ef0..f15b977 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -131,43 +131,6 @@ static struct request *get_alua_req(struct scsi_device 
*sdev,
 }
 
 /*
- * submit_vpd_inquiry - Issue an INQUIRY VPD page 0x83 command
- * @sdev: sdev the command should be sent to
- */
-static int submit_vpd_inquiry(struct scsi_device *sdev, struct alua_dh_data *h)
-{
-   struct request *rq;
-   int err = SCSI_DH_RES_TEMP_UNAVAIL;
-
-   rq = get_alua_req(sdev, h->buff, h->bufflen, READ);
-   if (!rq)
-   goto done;
-
-   /* Prepare the command. */
-   rq->cmd[0] = INQUIRY;
-   rq->cmd[1] = 1;
-   rq->cmd[2] = 0x83;
-   rq->cmd[4] = h->bufflen;
-   rq->cmd_len = COMMAND_SIZE(INQUIRY);
-
-   rq->sense = h->sense;
-   memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
-   rq->sense_len = h->senselen = 0;
-
-   err = blk_execute_rq(rq->q, NULL, rq, 1);
-   if (err == -EIO) {
-   sdev_printk(KERN_INFO, sdev,
-   "%s: evpd inquiry failed with %x\n",
-   ALUA_DH_NAME, rq->errors);
-   h->senselen = rq->sense_len;
-   err = SCSI_DH_IO;
-   }
-   blk_put_request(rq);
-done:
-   return err;
-}
-
-/*
  * submit_rtpg - Issue a REPORT TARGET GROUP STATES command
  * @sdev: sdev the command should be sent to
  */
@@ -359,43 +322,24 @@ static int alua_check_tpgs(struct scsi_device *sdev, 
struct alua_dh_data *h)
 }
 
 /*
- * alua_vpd_inquiry - Evaluate INQUIRY vpd page 0x83
+ * alua_check_vpd - Evaluate INQUIRY vpd page 0x83
  * @sdev: device to be checked
  *
  * Extract the relative target port and the target port group
  * descriptor from the list of identificators.
  */
-static int alua_vpd_inquiry(struct scsi_device *sdev, struct alua_dh_data *h)
+static int alua_check_vpd(struct scsi_device *sdev, struct alua_dh_data *h)
 {
-   int len;
-   unsigned err;
unsigned char *d;
 
- retry:
-   err = submit_vpd_inquiry(sdev, h);
-
-   if (err != SCSI_DH_OK)
-   return err;
-
-   /* Check if vpd page exceeds initial buffer */
-   len = (h->buff[2] << 8) + h->buff[3] + 4;
-   if (len > h->bufflen) {
-   /* Resubmit with the correct length */
-   if (realloc_buffer(h, len)) {
-   sdev_printk(KERN_WARNING, sdev,
-   "%s: kmalloc buffer failed\n",
-   ALUA_DH_NAME);
-   /* Temporary failure, bypass */
-   return SCSI_DH_DEV_TEMP_BUSY;
-   }
-   goto retry;
-   }
+   if (!sdev->vpd_pg83)
+   return SCSI_DH_DEV_UNSUPP;
 
/*
-* Now look for the correct descriptor.
+* Look for the correct descriptor.
 */
-   d = h->buff + 4;
-   while (d < h->buff + len) {
+   d = sdev->vpd_pg83 + 4;
+   while (d < sdev->vpd_pg83 + sdev->vpd_pg83_len) {
switch (d[1] & 0xf) {
case 0x4:
/* Relative target port */
@@ -422,14 +366,13 @@ static int alua_vpd_inquiry(struct scsi_device *sdev, 
struct alua_dh_data *h)
ALUA_DH_NAME);
h->state = TPGS_STATE_OPTIMIZED;
h->tpgs = TPGS_MODE_NONE;
-   err = SCSI_DH_DEV_UNSUPP;
-   } else {
-   sdev_printk(KERN_INFO, sdev,
-   "%s: port group %02x rel port %02x\n",
-   ALUA_DH_NAME, h->group_id, h->rel_port);
+   return SCSI_DH_DEV_UNSUPP;
}
+   sdev_printk(KERN_INFO, sdev,
+   "%s: port group %02x rel port %02x\n",
+   ALUA_DH_NAME, h->group_id, h->rel_port);
 
-   return err;
+   return 0;
 }
 
 static char print_alua_state(int state)
@@ -692,7 +635,7 @@ static int alua_initialize(struct scsi_device *sdev, struct 
alua_dh_data *h)
if (err != SCSI_DH_OK)
goto out;
 
-   err = alua_vpd_inquiry(sdev, h);
+   err = alua_check_vpd(sdev, h);
if (err != SCSI_DH_OK)
goto out;
 
-- 
1.8.5.6

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 06/23] scsi_dh_alua: fixup description of stpg_endio()

2015-08-27 Thread Hannes Reinecke
Fixup copy-and-paste error in the description of stpg_endio().

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index c41d662..25c2045 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -174,13 +174,11 @@ done:
 }
 
 /*
- * alua_stpg - Evaluate SET TARGET GROUP STATES
+ * stpg_endio - Evaluate SET TARGET GROUP STATES
  * @sdev: the device to be evaluated
  * @state: the new target group state
  *
- * Send a SET TARGET GROUP STATES command to the device.
- * We only have to test here if we should resubmit the command;
- * any other error is assumed as a failure.
+ * Evaluate a SET TARGET GROUP STATES command response.
  */
 static void stpg_endio(struct request *req, int error)
 {
-- 
1.8.5.6

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] scsi_debug: fix failure to probe with scsi_level=1 or 2 due to NULL devip

2015-08-27 Thread Douglas Gilbert

On 15-08-25 03:47 PM, Ewan D. Milne wrote:

From: "Ewan D. Milne" 

commit cbf67842c3d9 ("scsi_debug: support scsi-mq, queues and locks")
added a test for devip == NULL in schedule_resp which returned
SCSI_MLQUEUE_HOST_BUSY.  Unfortunately, if scsi_level 1 or 2 is specified,
devip will be NULL for the INQUIRY command for the next LUN above the
configured value and it will be retried indefinitely with an error message.
Fix this by returning the command in the same context if no devip exists.

Signed-off-by: Ewan D. Milne 


Acked-by: Douglas Gilbert 


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 0/2] mpt3sas: Reference counting fixes from in-flight mpt2sas

2015-08-27 Thread James Bottomley
On Thu, 2015-08-27 at 10:37 +0530, Sreekanth Reddy wrote:
> HI Nicholas & Calvin,
> 
> Thanks for the patchset. Sure We will review and we do some unit
> testing on this patch series. Currently my bandwidth is occupied with
> some internal activity, so by end of next week I will acknowledge this
> series if all the thing are fine with this patch series.

Calvin responded to your review feedback and that series has been
outstanding for a while, so I'm not going to drop it from the misc tree.
However, I will reorder to make it ready for the second push. You have
until Friday week to find a problem with it.

James


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 0/2] mpt3sas: Reference counting fixes from in-flight mpt2sas

2015-08-27 Thread Sreekanth Reddy
Ok James, by 9/4/2015 we will provide our feedback over this patch series.

Thanks,
Sreekanth


On Thu, Aug 27, 2015 at 8:10 PM, James Bottomley
 wrote:
> On Thu, 2015-08-27 at 10:37 +0530, Sreekanth Reddy wrote:
>> HI Nicholas & Calvin,
>>
>> Thanks for the patchset. Sure We will review and we do some unit
>> testing on this patch series. Currently my bandwidth is occupied with
>> some internal activity, so by end of next week I will acknowledge this
>> series if all the thing are fine with this patch series.
>
> Calvin responded to your review feedback and that series has been
> outstanding for a while, so I'm not going to drop it from the misc tree.
> However, I will reorder to make it ready for the second push. You have
> until Friday week to find a problem with it.
>
> James
>
>
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH V7 1/9] [SCSI] aacraid: Fix for logical device name and UID not exposed to the OS

2015-08-27 Thread James Bottomley
On Thu, 2015-08-27 at 06:50 -0400, Mahesh Rajashekhara wrote:
> Description:
>   Driver sends the right size of the response buffer.
> 
> Changes from V2:
> None
> 
> Reviewed By: Tomas Henzl , Murthy Bhat 
> , Karthikeya Sunkesula 
> 
> Signed-off-by: Mahesh Rajashekhara 

You've had hundreds of upstream confirmation emails over the years.
They've all had one line per tag with no spaces.  Next time can we
please use the right format so I don't have to keep editing your commit
messages.  That is:

Subject: One line summary

Detailed Description of the change (without a Description: prefix)

Reviewed-by: Tomas Henzl 
Reviewed-by: Murthy Bhat 
Reviewed-by: Karthikeya Sunkesula 
Signed-off-by: Mahesh Rajashekhara 

---

Version notices and other context relevant only to the upstream process
come here after the three dashes so it doesn't appear in the patch
detailed description

James
 

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v1 14/15] scsi: ufs: commit descriptors before setting the doorbell

2015-08-27 Thread Rob Herring
On Thu, Aug 27, 2015 at 7:28 AM,   wrote:
>>> On Aug 21, 2015 3:10 PM, "Yaniv Gardi"  wrote:

 Add a write memory barrier to make sure descriptors prepared are
 actually
 written to memory before ringing the doorbell. We have also added the
 write memory barrier after ringing the doorbell register so that
 controller sees the new request immediately.

[...]

 +   /* Make sure descriptors are ready before ringing the doorbell
 */
 +   wmb();
>>>
>>> The writel for the doorbell will do a barrier first. (I didn't check
>>> what exactly ufshcd_writel does, but that is why I don't like these
>>> private access wrappers.)
>
> the barrier here is important and a must.
> before it we prepare descriptors.
> after it we write to DOOR-BELL.
> (and after the DOOR-BELL we have another one.)
> if we remove it, we might get the DOOR-BELL written, before the
> descriptors written.

If you dig into what writel does, you will see that what the code here
ends up being is:

descriptor setup
wmb()
__iomwb() -> wmb on arm64
doorbell register write

So explain why you need 2 barriers.

Barriers in a driver are a red flag. Usually they are not needed, but
sometimes they are. You have to be able to explain why if they are.
Pretty much every descriptor based DMA device works as you describe
and has the ordering problem. Because of that, the core code takes
care of this.

Rob
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v1 14/15] scsi: ufs: commit descriptors before setting the doorbell

2015-08-27 Thread Rob Herring
On Thu, Aug 27, 2015 at 7:11 AM,   wrote:
>> On Tue, Aug 25, 2015 at 7:36 AM,   wrote:
 On Aug 21, 2015 3:10 PM, "Yaniv Gardi"  wrote:
>
> Add a write memory barrier to make sure descriptors prepared are
> actually
> written to memory before ringing the doorbell. We have also added the
> write memory barrier after ringing the doorbell register so that
> controller sees the new request immediately.
>
> Signed-off-by: Yaniv Gardi 
>
> ---
>  drivers/scsi/ufs/ufshcd.c | 6 ++
>  1 file changed, 6 insertions(+)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index fef0660..876148b 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -833,6 +833,8 @@ void ufshcd_send_command(struct ufs_hba *hba,
> unsigned int task_tag)
> ufshcd_clk_scaling_start_busy(hba);
> __set_bit(task_tag, &hba->outstanding_reqs);
> ufshcd_writel(hba, 1 << task_tag,
> REG_UTP_TRANSFER_REQ_DOOR_BELL);
> +   /* Make sure that doorbell is committed immediately */
> +   wmb();

 Is this really necessary? Is there a measurable difference?
>>>
>>> I'm not sure if there is a measurable difference, but as the Door-Bell
>>> register is the one that actually responsible for the HW execution of
>>> the
>>> requests, anyhow, it's recommended to its value will be written
>>> instantly to the memory.
>>
>> A barrier doesn't guarantee speed, only ordering. Unless you can
>> measure the difference, you should not have it.
>
> Rob,
> let me have an example:
> context#1 updates outstanding_reqs variable and write(DOOR_BELL)
> context#2 upon interrupt of a request completion the following happens:
>   report completion on each one of the bits in:
>   outstanding_reqs ^ read(DOOR_BELL);
>
> 0. let's assume the DOOR_BELL = 0x1 (which means 1 active request in slot 0)
> 1. context#1: update the DOOR_BELL to be 0x3; (2 active requests: in slot
> 0 and 1)
> 2. the new value 0x3 is still not written to the DR so DORR_BELL is still
> 0x1, but outstanding_reqs is already updated = 0x3
> 3. the request in slot 0 just completed, and interrupt happens, so
> DORR_BELL is now 0 (request in slot 0 completed)
> 4. context#2: outstanding_reqs ^ read(DOOR_BELL) = 0x3 ^ 0x0 = 0x3 =>
> wrong conclusion since the request in slot 1 never completed, and actually
> never started.

Barriers alone will never solve this problem. They may narrow the
window possibly, but the problem is still there. What you have to have
is a spinlock around all accesses to both outstanding_reqs and
doorbell register. And guess what, spinlocks have appropriate barriers
to ensure visibility of what they protect. Or perhaps the h/w provides
another way to signal what slots have completed. Using the same
register for doorbell and completion status is not ideal.

Rob
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v3 6/8] scsi: ufs: make the UFS variant a platform device

2015-08-27 Thread Rob Herring
On Sun, Aug 23, 2015 at 8:09 AM, Yaniv Gardi  wrote:
> This change turns the UFS variant (SCSI_UFS_QCOM) into a UFS
> a platform device.
> In order to do so a few additional changes are required:
> 1. The ufshcd-pltfrm is no longer serves as a platform device.
>Now it only serves as a group of platform APIs such as PM APIs
>(runtime suspend/resume, system suspend/resume etc), parsers of
>clocks, regulators and pm_levels from DT.
> 2. What used to be the old platform "probe" is now "only"
>a pltfrm_init() routine, that does exactly the same, but only
>being called by the new probe function of the UFS variant.
>
> Signed-off-by: Yaniv Gardi 
>
> ---
>  .../devicetree/bindings/ufs/ufshcd-pltfrm.txt  |  2 +-
>  drivers/scsi/ufs/ufs-qcom.c| 78 +-
>  drivers/scsi/ufs/ufshcd-pltfrm.c   | 92 
> ++
>  drivers/scsi/ufs/ufshcd-pltfrm.h   | 41 ++
>  drivers/scsi/ufs/ufshcd.c  | 10 +++
>  drivers/scsi/ufs/ufshcd.h  |  1 +
>  6 files changed, 152 insertions(+), 72 deletions(-)
>  create mode 100644 drivers/scsi/ufs/ufshcd-pltfrm.h
>
> diff --git a/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt 
> b/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt
> index 5357919..b39e765 100644
> --- a/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt
> +++ b/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt
> @@ -4,7 +4,7 @@ UFSHC nodes are defined to describe on-chip UFS host 
> controllers.
>  Each UFS controller instance should have its own node.
>
>  Required properties:
> -- compatible: compatible list, contains "jedec,ufs-1.1"
> +- compatible: compatible list, contains "jedec,ufs-1.1" or 
> "qcom,ufshc"

Replying again as I inadvertently dropped everyone.

This should also have a more specific compatible string with the SOC
name/number in it. It may be "the same in all SOCs", but there is
always the possibility for bugs/limitations to be found that are
specific to an SOC even if all RTL versions are identical (e.g.
different max clock speeds). It is about making the dtb future proof,
not about what exactly you need today. You can keep qcom,ufshc for
driver matching if you want.

>  - interrupts: 
>  - reg   : 

What about phy properties? No Unipro PHY block that requires setup?

Rob
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] scsi: fix scsi_error_handler vs. scsi_host_dev_release race

2015-08-27 Thread mhocko
From: Michal Hocko 

b9d5c6b7ef57 ("[SCSI] cleanup setting task state in
scsi_error_handler()") has introduced a race between scsi_error_handler
and scsi_host_dev_release resulting in the hang when the device goes
away because scsi_error_handler might miss a wake up:

CPU0CPU1
scsi_error_handler  scsi_host_dev_release
  kthread_stop()
  kthread_should_stop()
test_bit(KTHREAD_SHOULD_STOP)
set_bit(KTHREAD_SHOULD_STOP)
wake_up_process()
wait_for_completion()

  set_current_state(TASK_INTERRUPTIBLE)
  schedule()

The most straightforward solution seems to be to invert the ordering of
the set_current_state and kthread_should_stop.

The issue has been noticed during reboot test on a 3.0 based kernel but
the current code seems to be affected in the same way.

Cc: stable # 3.6+
Reported-and-Debugged-by: Mike Mayer 
Signed-off-by: Michal Hocko 
---
 drivers/scsi/scsi_error.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 6457a8a0db9c..2c0a817d5dbe 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -2169,8 +2169,11 @@ int scsi_error_handler(void *data)
 * We never actually get interrupted because kthread_run
 * disables signal delivery for the created thread.
 */
-   while (!kthread_should_stop()) {
+   while (true) {
set_current_state(TASK_INTERRUPTIBLE);
+   if (kthread_should_stop())
+   break;
+
if ((shost->host_failed == 0 && shost->host_eh_scheduled == 0) 
||
shost->host_failed != atomic_read(&shost->host_busy)) {
SCSI_LOG_ERROR_RECOVERY(1,
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] scsi: fix scsi_error_handler vs. scsi_host_dev_release race

2015-08-27 Thread Dan Williams
On Thu, Aug 27, 2015 at 11:16 AM,   wrote:
> From: Michal Hocko 
>
> b9d5c6b7ef57 ("[SCSI] cleanup setting task state in
> scsi_error_handler()") has introduced a race between scsi_error_handler
> and scsi_host_dev_release resulting in the hang when the device goes
> away because scsi_error_handler might miss a wake up:
>
> CPU0CPU1
> scsi_error_handler  scsi_host_dev_release
>   kthread_stop()
>   kthread_should_stop()
> test_bit(KTHREAD_SHOULD_STOP)
> set_bit(KTHREAD_SHOULD_STOP)
> wake_up_process()
> wait_for_completion()
>
>   set_current_state(TASK_INTERRUPTIBLE)
>   schedule()
>
> The most straightforward solution seems to be to invert the ordering of
> the set_current_state and kthread_should_stop.
>
> The issue has been noticed during reboot test on a 3.0 based kernel but
> the current code seems to be affected in the same way.
>
> Cc: stable # 3.6+
> Reported-and-Debugged-by: Mike Mayer 
> Signed-off-by: Michal Hocko 

Acked-by: Dan Williams 
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 0/2] mpt3sas: Reference counting fixes from in-flight mpt2sas

2015-08-27 Thread Nicholas A. Bellinger
On Thu, 2015-08-27 at 07:40 -0700, James Bottomley wrote:
> On Thu, 2015-08-27 at 10:37 +0530, Sreekanth Reddy wrote:
> > HI Nicholas & Calvin,
> > 
> > Thanks for the patchset. Sure We will review and we do some unit
> > testing on this patch series. Currently my bandwidth is occupied with
> > some internal activity, so by end of next week I will acknowledge this
> > series if all the thing are fine with this patch series.
> 
> Calvin responded to your review feedback and that series has been
> outstanding for a while, so I'm not going to drop it from the misc tree.
> However, I will reorder to make it ready for the second push. You have
> until Friday week to find a problem with it.
> 

James, as mentioned this series is functionally identical to Calvin's
mpt2sas series.

Please consider merging it to scsi.git/for-next, so both series are
together and in-sync.

--nab

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/2] ipr: Enable SIS pipe commands for SIS-32 devices.

2015-08-27 Thread Wendy Xiong

Gabriel Krisman Bertazi  linux.vnet.ibm.com> writes:

> 
> Remove unnecessary check that disabled SIS pipe commands for SIS-32
> devices.  This change was sufficient to enable raw mode and send SIS
> pipe commands for a 57B3 device.
> 

Reviewed-by: Wen Xiong 

Thanks,

Wendy


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [scsi 5/7 RESEND] scsi_debug: schedule_resp fix input variable check

2015-08-27 Thread Ewan Milne
On Wed, 2015-08-26 at 16:38 -0700, James Bottomley wrote:
> On Tue, 2015-08-25 at 21:03 +, Winkler, Tomas wrote:
> > 
> > > > +   /* this should never happen */
> > > > +   if (WARN_ON(!cmnd))
> > > > +   return SCSI_MLQUEUE_HOST_BUSY;
> > > >
> > > > -   if (NULL == cmnd || NULL == devip) {
> > > > -   pr_warn("called with NULL cmnd or devip pointer\n");
> > > > +   if (NULL == devip) {
> > > > +   pr_warn("called devip == NULL\n");
> > > > /* no particularly good error to report back */
> > > > return SCSI_MLQUEUE_HOST_BUSY;
> > > > }
> > > 
> > > Please refer to the patch I just posted, we can't return _HOST_BUSY here
> > > if devip == NULL.  I posted a fix against the current "misc" branch as
> > > I don't see this patch applied, let me know if I need to update it.
> > 
> > 
> > I'm just not sure why the patches are not merged or even rejected.
> 
> Because ideally I want a Maintainer ack.  That's Doug Gilbert.
> 
> > I'm submitting patches to the Linux kernel for more than 10 years to
> > various trees and  I can agree that these are not some  urgent fixes,
> > but  this is the first time my effort is ignored for such long time by
> > the maintainer. 
> 
> Well, OK, I trust martin, I'll override the lack of Maintainer ack if
> you fix as Ewan suggests.
> 

Just to clarify, I didn't have a problem with Tomas' patch per se, it's
just that my patch won't apply on top of his.  I'll submit a v2 if you
want, so you can apply Tomas' patch first.  The problem I'm fixing has
been in there for a while.  Let me know if you want me to do that.

-Ewan

> James
> 
> 
> > Thanks
> > Tomas
> > 
> > NrybXǧv^)޺{.n+{"{ayʇڙ,jfhzwj:+vwjmzZ+ݢj"!
> 
> 
> 


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[scsi:misc 95/113] drivers/scsi/mpt3sas/mpt3sas_base.c:1820:1: sparse: symbol 'mpt3sas_base_unmap_resources' was not declared. Should it be static?

2015-08-27 Thread kbuild test robot
tree:   git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git misc
head:   b9e8a16466e62d46c0b8551fb807173d6a9c529f
commit: 580d4e3153f0d7a9a9235b675b0b7b13e2185a8b [95/113] mpt3sas: Remove 
redundancy code while freeing the controller resources.
reproduce:
  # apt-get install sparse
  git checkout 580d4e3153f0d7a9a9235b675b0b7b13e2185a8b
  make ARCH=x86_64 allmodconfig
  make C=1 CF=-D__CHECK_ENDIAN__


sparse warnings: (new ones prefixed by >>)

   drivers/scsi/mpt3sas/mpt3sas_base.c:1031:52: sparse: incorrect type in 
argument 2 (different address spaces)
   drivers/scsi/mpt3sas/mpt3sas_base.c:1031:52:expected void volatile 
[noderef] *addr
   drivers/scsi/mpt3sas/mpt3sas_base.c:1031:52:got unsigned long long 
[usertype] *
>> drivers/scsi/mpt3sas/mpt3sas_base.c:1820:1: sparse: symbol 
>> 'mpt3sas_base_unmap_resources' was not declared. Should it be static?
   drivers/scsi/mpt3sas/mpt3sas_base.c:1958:32: sparse: cast removes address 
space of expression
   drivers/scsi/mpt3sas/mpt3sas_base.c:2204:16: sparse: incorrect type in 
argument 1 (different base types)
   drivers/scsi/mpt3sas/mpt3sas_base.c:2204:16:expected unsigned long 
[unsigned] val
   drivers/scsi/mpt3sas/mpt3sas_base.c:2204:16:got restricted __le64 
[usertype] 
   drivers/scsi/mpt3sas/mpt3sas_base.c:2204:16: sparse: incorrect type in 
argument 1 (different base types)
   drivers/scsi/mpt3sas/mpt3sas_base.c:2204:16:expected unsigned long 
[unsigned] val
   drivers/scsi/mpt3sas/mpt3sas_base.c:2204:16:got restricted __le64 
[usertype] 
   drivers/scsi/mpt3sas/mpt3sas_base.c:2204:16: sparse: incorrect type in 
argument 1 (different base types)
   drivers/scsi/mpt3sas/mpt3sas_base.c:2204:16:expected unsigned long 
[unsigned] val
   drivers/scsi/mpt3sas/mpt3sas_base.c:2204:16:got restricted __le64 
[usertype] 
   drivers/scsi/mpt3sas/mpt3sas_base.c:2204:16: sparse: incorrect type in 
argument 1 (different base types)
   drivers/scsi/mpt3sas/mpt3sas_base.c:2204:16:expected unsigned long 
[unsigned] val
   drivers/scsi/mpt3sas/mpt3sas_base.c:2204:16:got restricted __le64 
[usertype] 
   drivers/scsi/mpt3sas/mpt3sas_base.c:3446:24: sparse: incorrect type in 
argument 1 (different base types)
   drivers/scsi/mpt3sas/mpt3sas_base.c:3446:24:expected unsigned int 
[unsigned] val
   drivers/scsi/mpt3sas/mpt3sas_base.c:3446:24:got restricted __le32 
[usertype] 
   drivers/scsi/mpt3sas/mpt3sas_base.c:3467:20: sparse: cast to restricted 
__le16
   drivers/scsi/mpt3sas/mpt3sas_base.c:3476:20: sparse: cast to restricted 
__le16
   drivers/scsi/mpt3sas/mpt3sas_base.c:3490:36: sparse: cast to restricted 
__le16
   drivers/scsi/mpt3sas/mpt3sas_base.c:4673:55: sparse: incorrect type in 
argument 2 (different address spaces)
   drivers/scsi/mpt3sas/mpt3sas_base.c:4673:55:expected void volatile 
[noderef] *addr
   drivers/scsi/mpt3sas/mpt3sas_base.c:4673:55:got unsigned long long 
[usertype] *

Please review and possibly fold the followup patch.

---
0-DAY kernel test infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH scsi] mpt3sas: mpt3sas_base_unmap_resources can be static

2015-08-27 Thread kbuild test robot

Signed-off-by: Fengguang Wu 
---
 mpt3sas_base.c |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 7e8ede2..6ee54dd 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -1816,7 +1816,7 @@ _base_enable_msix(struct MPT3SAS_ADAPTER *ioc)
  * mpt3sas_base_unmap_resources - free controller resources
  * @ioc: per adapter object
  */
-void
+static void
 mpt3sas_base_unmap_resources(struct MPT3SAS_ADAPTER *ioc)
 {
struct pci_dev *pdev = ioc->pdev;
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[scsi:misc 97/113] drivers/scsi/mpt3sas/mpt3sas_scsih.c:5013:27: sparse: restricted __le16 degrades to integer

2015-08-27 Thread kbuild test robot
tree:   git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git misc
head:   b9e8a16466e62d46c0b8551fb807173d6a9c529f
commit: e6d45e3e7e6582fa206ef84631639ce70d50e5c5 [97/113] mpt3sas: Provides the 
physical location of sas drives
reproduce:
  # apt-get install sparse
  git checkout e6d45e3e7e6582fa206ef84631639ce70d50e5c5
  make ARCH=x86_64 allmodconfig
  make C=1 CF=-D__CHECK_ENDIAN__


sparse warnings: (new ones prefixed by >>)

>> drivers/scsi/mpt3sas/mpt3sas_scsih.c:5013:27: sparse: restricted __le16 
>> degrades to integer
>> drivers/scsi/mpt3sas/mpt3sas_scsih.c:5015:25: sparse: cast to restricted 
>> __le16
   drivers/scsi/mpt3sas/mpt3sas_scsih.c:3524:61: sparse: incorrect type in 
assignment (different base types)
   drivers/scsi/mpt3sas/mpt3sas_scsih.c:3524:61:expected restricted __le32 
[usertype] PrimaryReferenceTag
   drivers/scsi/mpt3sas/mpt3sas_scsih.c:3524:61:got restricted __be32 
[usertype] 
   drivers/scsi/mpt3sas/mpt3sas_scsih.c:4888:35: sparse: restricted __le16 
degrades to integer
   drivers/scsi/mpt3sas/mpt3sas_scsih.c:4891:33: sparse: cast to restricted 
__le16
>> drivers/scsi/mpt3sas/mpt3sas_scsih.c:6529:63: sparse: restricted __le64 
>> degrades to integer
   drivers/scsi/mpt3sas/mpt3sas_scsih.c:6530:60: sparse: restricted __le16 
degrades to integer
   drivers/scsi/mpt3sas/mpt3sas_scsih.c:6554:43: sparse: restricted __le16 
degrades to integer
   drivers/scsi/mpt3sas/mpt3sas_scsih.c:6557:36: sparse: cast to restricted 
__le16
   drivers/scsi/mpt3sas/mpt3sas_scsih.c:6565:65: sparse: restricted __le16 
degrades to integer
>> drivers/scsi/mpt3sas/mpt3sas_scsih.c:6569:44: sparse: incorrect type in 
>> assignment (different base types)
   drivers/scsi/mpt3sas/mpt3sas_scsih.c:6569:44:expected unsigned short 
[unsigned] [usertype] handle
   drivers/scsi/mpt3sas/mpt3sas_scsih.c:6569:44:got restricted __le16 
[usertype] DevHandle
   drivers/scsi/mpt3sas/mpt3sas_scsih.c:6571:62: sparse: incorrect type in 
assignment (different base types)
   drivers/scsi/mpt3sas/mpt3sas_scsih.c:6571:62:expected unsigned short 
[unsigned] [usertype] handle
   drivers/scsi/mpt3sas/mpt3sas_scsih.c:6571:62:got restricted __le16 
[usertype] DevHandle
>> drivers/scsi/mpt3sas/mpt3sas_scsih.c:6611:51: sparse: incorrect type in 
>> assignment (different base types)
   drivers/scsi/mpt3sas/mpt3sas_scsih.c:6611:51:expected restricted __le16 
[addressable] [usertype] DevHandle
   drivers/scsi/mpt3sas/mpt3sas_scsih.c:6611:51:got unsigned short 
[unsigned] [usertype] 
>> drivers/scsi/mpt3sas/mpt3sas_scsih.c:6616:43: sparse: incorrect type in 
>> assignment (different base types)
   drivers/scsi/mpt3sas/mpt3sas_scsih.c:6616:43:expected restricted __le64 
[addressable] [usertype] SASAddress
   drivers/scsi/mpt3sas/mpt3sas_scsih.c:6616:43:got unsigned long long 
[unsigned] [usertype] 
>> drivers/scsi/mpt3sas/mpt3sas_scsih.c:6618:37: sparse: incorrect type in 
>> assignment (different base types)
   drivers/scsi/mpt3sas/mpt3sas_scsih.c:6618:37:expected restricted __le16 
[addressable] [usertype] Slot
   drivers/scsi/mpt3sas/mpt3sas_scsih.c:6618:37:got unsigned short 
[unsigned] [usertype] 

vim +5013 drivers/scsi/mpt3sas/mpt3sas_scsih.c

  5007  sas_device->device_info = device_info;
  5008  sas_device->sas_address = sas_address;
  5009  sas_device->phy = sas_device_pg0.PhyNum;
  5010  sas_device->fast_path = (le16_to_cpu(sas_device_pg0.Flags) &
  5011  MPI25_SAS_DEVICE0_FLAGS_FAST_PATH_CAPABLE) ? 1 : 0;
  5012  
> 5013  if (sas_device_pg0.Flags & 
> MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) {
  5014  sas_device->enclosure_level =
> 5015  le16_to_cpu(sas_device_pg0.EnclosureLevel);
  5016  memcpy(&sas_device->connector_name[0],
  5017  &sas_device_pg0.ConnectorName[0], 4);
  5018  } else {

---
0-DAY kernel test infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH scsi] mpt3sas: mpt3sas_base_unmap_resources can be static

2015-08-27 Thread Sreekanth Reddy
Hi,

Please consider this patch as Ack-by: Sreekanth Reddy


Thanks,
Sreekanth

On Fri, Aug 28, 2015 at 6:50 AM, kbuild test robot
 wrote:
>
> Signed-off-by: Fengguang Wu 
> ---
>  mpt3sas_base.c |2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
> b/drivers/scsi/mpt3sas/mpt3sas_base.c
> index 7e8ede2..6ee54dd 100644
> --- a/drivers/scsi/mpt3sas/mpt3sas_base.c
> +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
> @@ -1816,7 +1816,7 @@ _base_enable_msix(struct MPT3SAS_ADAPTER *ioc)
>   * mpt3sas_base_unmap_resources - free controller resources
>   * @ioc: per adapter object
>   */
> -void
> +static void
>  mpt3sas_base_unmap_resources(struct MPT3SAS_ADAPTER *ioc)
>  {
> struct pci_dev *pdev = ioc->pdev;
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] scsi: fix scsi_error_handler vs. scsi_host_dev_release race

2015-08-27 Thread Hannes Reinecke
On 08/27/2015 08:16 PM, mho...@kernel.org wrote:
> From: Michal Hocko 
> 
> b9d5c6b7ef57 ("[SCSI] cleanup setting task state in
> scsi_error_handler()") has introduced a race between scsi_error_handler
> and scsi_host_dev_release resulting in the hang when the device goes
> away because scsi_error_handler might miss a wake up:
> 
> CPU0  CPU1
> scsi_error_handlerscsi_host_dev_release
> kthread_stop()
>   kthread_should_stop()
> test_bit(KTHREAD_SHOULD_STOP)
>   set_bit(KTHREAD_SHOULD_STOP)
>   wake_up_process()
>   wait_for_completion()
> 
>   set_current_state(TASK_INTERRUPTIBLE)
>   schedule()
> 
> The most straightforward solution seems to be to invert the ordering of
> the set_current_state and kthread_should_stop.
> 
> The issue has been noticed during reboot test on a 3.0 based kernel but
> the current code seems to be affected in the same way.
> 
> Cc: stable # 3.6+
> Reported-and-Debugged-by: Mike Mayer 
> Signed-off-by: Michal Hocko 
> ---
>  drivers/scsi/scsi_error.c | 5 -
>  1 file changed, 4 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
> index 6457a8a0db9c..2c0a817d5dbe 100644
> --- a/drivers/scsi/scsi_error.c
> +++ b/drivers/scsi/scsi_error.c
> @@ -2169,8 +2169,11 @@ int scsi_error_handler(void *data)
>* We never actually get interrupted because kthread_run
>* disables signal delivery for the created thread.
>*/
> - while (!kthread_should_stop()) {
> + while (true) {
>   set_current_state(TASK_INTERRUPTIBLE);
> + if (kthread_should_stop())
> + break;
> +
>   if ((shost->host_failed == 0 && shost->host_eh_scheduled == 0) 
> ||
>   shost->host_failed != atomic_read(&shost->host_busy)) {
>   SCSI_LOG_ERROR_RECOVERY(1,
> 
Reviewed-by: Hannes Reinecke 

Cheers,

Hannes
-- 
Dr. Hannes ReineckezSeries & Storage
h...@suse.de   +49 911 74053 688
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: F. Imendörffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton
HRB 21284 (AG Nürnberg)
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html