diff mbox

[v1] scsi: mpt3sas: Use lo_hi_writeq() helper

Message ID 20180214181034.36529-1-andriy.shevchenko@linux.intel.com (mailing list archive)
State Rejected
Headers show

Commit Message

Andy Shevchenko Feb. 14, 2018, 6:10 p.m. UTC
Since we have a writeq() for 32-bit architectures as provided by IO
non-atomic helpers, there is no need to open code it.

Moreover sparse complains about this:

drivers/scsi/mpt3sas/mpt3sas_base.c:2975:16: expected unsigned long long val
drivers/scsi/mpt3sas/mpt3sas_base.c:2975:16: got restricted __le64 <noident>

Fixing this by replacing custom writeq() with one provided by
io-64-nonatomic-lo-hi.h header.

Reported-by: kbuild test robot <fengguang.wu@intel.com>
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
 drivers/scsi/mpt3sas/mpt3sas_base.c | 14 +++-----------
 1 file changed, 3 insertions(+), 11 deletions(-)

Comments

James Bottomley Feb. 14, 2018, 7:40 p.m. UTC | #1
On Wed, 2018-02-14 at 20:10 +0200, Andy Shevchenko wrote:
> Since we have a writeq() for 32-bit architectures as provided by IO
> non-atomic helpers, there is no need to open code it.
> 
> Moreover sparse complains about this:
> 
> drivers/scsi/mpt3sas/mpt3sas_base.c:2975:16: expected unsigned long
> long val
> drivers/scsi/mpt3sas/mpt3sas_base.c:2975:16: got restricted __le64
> <noident>
> 
> Fixing this by replacing custom writeq() with one provided by
> io-64-nonatomic-lo-hi.h header.
> 
> Reported-by: kbuild test robot <fengguang.wu@intel.com>
> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> ---
>  drivers/scsi/mpt3sas/mpt3sas_base.c | 14 +++-----------
>  1 file changed, 3 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c
> b/drivers/scsi/mpt3sas/mpt3sas_base.c
> index 59a87ca328d3..a92ab4a801d7 100644
> --- a/drivers/scsi/mpt3sas/mpt3sas_base.c
> +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
> @@ -56,6 +56,7 @@
>  #include <linux/interrupt.h>
>  #include <linux/dma-mapping.h>
>  #include <linux/io.h>
> +#include <linux/io-64-nonatomic-lo-hi.h>
>  #include <linux/time.h>
>  #include <linux/ktime.h>
>  #include <linux/kthread.h>
> @@ -2968,16 +2969,9 @@ mpt3sas_base_free_smid(struct MPT3SAS_ADAPTER
> *ioc, u16 smid)
>   * @writeq_lock: spin lock
>   *
>   * Glue for handling an atomic 64 bit word to MMIO. This special
> handling takes
> - * care of 32 bit environment where its not quarenteed to send the
> entire word
> + * care of 32 bit environment where its not guaranteed to send the
> entire word
>   * in one transfer.
>   */
> -#if defined(writeq) && defined(CONFIG_64BIT)
> -static inline void
> -_base_writeq(__u64 b, volatile void __iomem *addr, spinlock_t
> *writeq_lock)
> -{
> -	writeq(cpu_to_le64(b), addr);
> -}
> -#else
>  static inline void
>  _base_writeq(__u64 b, volatile void __iomem *addr, spinlock_t
> *writeq_lock)
>  {
> @@ -2985,11 +2979,9 @@ _base_writeq(__u64 b, volatile void __iomem
> *addr, spinlock_t *writeq_lock)
>  	__u64 data_out = cpu_to_le64(b);
>  
>  	spin_lock_irqsave(writeq_lock, flags);
> -	writel((u32)(data_out), addr);
> -	writel((u32)(data_out >> 32), (addr + 4));
> +	writeq(data_out, addr);
>  	spin_unlock_irqrestore(writeq_lock, flags);
>  }
> -#endif

This would rather defeat the purpose of the original code, I think.
 The coding seems to indicate that if the platform can do a writeq
atomically (i.e. it's 64 bit and has the primitive) then it should and
not take the hit of using a lock.  Otherwise the 64 bit value is
updated by two 32 bit writes protected by a lock to ensure we don't get
interleaving of the write.

So I think you can replace the double writel with a lo_hi_writeq but
you have to lose the lock if the platform supports the atomic 64 bit
write for performance reasons.

James
Andy Shevchenko Feb. 14, 2018, 7:48 p.m. UTC | #2
On Wed, 2018-02-14 at 11:40 -0800, James Bottomley wrote:
> On Wed, 2018-02-14 at 20:10 +0200, Andy Shevchenko wrote:
> > Since we have a writeq() for 32-bit architectures as provided by IO
> > non-atomic helpers, there is no need to open code it.
> > 
> > Moreover sparse complains about this:
> > 
> > drivers/scsi/mpt3sas/mpt3sas_base.c:2975:16: expected unsigned long
> > long val
> > drivers/scsi/mpt3sas/mpt3sas_base.c:2975:16: got restricted __le64
> > <noident>
> > 
> > Fixing this by replacing custom writeq() with one provided by
> > io-64-nonatomic-lo-hi.h header.
> > 

> > -#if defined(writeq) && defined(CONFIG_64BIT)
> > -static inline void
> > -_base_writeq(__u64 b, volatile void __iomem *addr, spinlock_t
> > *writeq_lock)
> > -{
> > -	writeq(cpu_to_le64(b), addr);
> > -}
> > -#else
> >  static inline void
> >  _base_writeq(__u64 b, volatile void __iomem *addr, spinlock_t
> > *writeq_lock)
> >  {
> > @@ -2985,11 +2979,9 @@ _base_writeq(__u64 b, volatile void __iomem
> > *addr, spinlock_t *writeq_lock)
> >  	__u64 data_out = cpu_to_le64(b);
> >  
> >  	spin_lock_irqsave(writeq_lock, flags);
> > -	writel((u32)(data_out), addr);
> > -	writel((u32)(data_out >> 32), (addr + 4));
> > +	writeq(data_out, addr);
> >  	spin_unlock_irqrestore(writeq_lock, flags);
> >  }
> > -#endif
> 
> This would rather defeat the purpose of the original code, I think.

James, TBH, I don't see any value of that lock. What it's protecting
from? simultaneous thread doing writeq()? But this is pointless if at
the same time you will have writel() to the device.

For my opinion perhaps complete removal of the custom writeq() and
replacing it by just writeq() with enabled non-atomic helpers will do
the job.

The code is very old, and I have no idea why it's done this (strange)
way.

>  The coding seems to indicate that if the platform can do a writeq
> atomically (i.e. it's 64 bit and has the primitive) then it should and
> not take the hit of using a lock.  Otherwise the 64 bit value is
> updated by two 32 bit writes protected by a lock to ensure we don't
> get
> interleaving of the write.
> 
> So I think you can replace the double writel with a lo_hi_writeq but
> you have to lose the lock if the platform supports the atomic 64 bit
> write for performance reasons.
James Bottomley Feb. 14, 2018, 8:01 p.m. UTC | #3
On Wed, 2018-02-14 at 21:48 +0200, Andy Shevchenko wrote:
> On Wed, 2018-02-14 at 11:40 -0800, James Bottomley wrote:
> > 
> > On Wed, 2018-02-14 at 20:10 +0200, Andy Shevchenko wrote:
> > > 
> > > Since we have a writeq() for 32-bit architectures as provided by
> > > IO
> > > non-atomic helpers, there is no need to open code it.
> > > 
> > > Moreover sparse complains about this:
> > > 
> > > drivers/scsi/mpt3sas/mpt3sas_base.c:2975:16: expected unsigned
> > > long
> > > long val
> > > drivers/scsi/mpt3sas/mpt3sas_base.c:2975:16: got restricted
> > > __le64
> > > <noident>
> > > 
> > > Fixing this by replacing custom writeq() with one provided by
> > > io-64-nonatomic-lo-hi.h header.
> > > 
> 
> > 
> > > 
> > > -#if defined(writeq) && defined(CONFIG_64BIT)
> > > -static inline void
> > > -_base_writeq(__u64 b, volatile void __iomem *addr, spinlock_t
> > > *writeq_lock)
> > > -{
> > > -	writeq(cpu_to_le64(b), addr);
> > > -}
> > > -#else
> > >  static inline void
> > >  _base_writeq(__u64 b, volatile void __iomem *addr, spinlock_t
> > > *writeq_lock)
> > >  {
> > > @@ -2985,11 +2979,9 @@ _base_writeq(__u64 b, volatile void
> > > __iomem
> > > *addr, spinlock_t *writeq_lock)
> > >  	__u64 data_out = cpu_to_le64(b);
> > >  
> > >  	spin_lock_irqsave(writeq_lock, flags);
> > > -	writel((u32)(data_out), addr);
> > > -	writel((u32)(data_out >> 32), (addr + 4));
> > > +	writeq(data_out, addr);
> > >  	spin_unlock_irqrestore(writeq_lock, flags);
> > >  }
> > > -#endif
> > 
> > This would rather defeat the purpose of the original code, I think.
> 
> James, TBH, I don't see any value of that lock. What it's protecting
> from? simultaneous thread doing writeq()? But this is pointless if at
> the same time you will have writel() to the device.

The lock prevents two threads doing an interleaved write to this
specific address which could be caused by two threads writing to the
same address.  If I remember correctly the firmware hangs in that case.

> For my opinion perhaps complete removal of the custom writeq() and
> replacing it by just writeq() with enabled non-atomic helpers will do
> the job.
> 
> The code is very old, and I have no idea why it's done this (strange)
> way.

The write seems to trigger starting the engine on the HBA if you look
at the code, which is why it must be written completely and in order.
 It's equivalent to a mailbox post.

James
Sathya Prakash Veerichetty Feb. 14, 2018, 10:15 p.m. UTC | #4
The writeq is defined to ensure both the registers are written without any
interleaved access in between the two writels in 32 bit systems.  Also we
want to retain the order of writing the registers.  If needed I can dig out
the issue we have faced using writeq in 32 bit systems (happened five/six
years back).  So I would prefer leave the code as it is.

Thanks
Sathya
-----Original Message-----
From: mpt-fusionlinux.pdl@broadcom.com
[mailto:mpt-fusionlinux.pdl@broadcom.com] On Behalf Of James Bottomley
Sent: Wednesday, February 14, 2018 1:02 PM
To: Andy Shevchenko; Sathya Prakash; Chaitra P B; Suganath Prabu Subramani;
MPT-FusionLinux.pdl@broadcom.com; Martin K. Petersen;
linux-scsi@vger.kernel.org
Subject: Re: [PATCH v1] scsi: mpt3sas: Use lo_hi_writeq() helper

On Wed, 2018-02-14 at 21:48 +0200, Andy Shevchenko wrote:
> On Wed, 2018-02-14 at 11:40 -0800, James Bottomley wrote:
> >
> > On Wed, 2018-02-14 at 20:10 +0200, Andy Shevchenko wrote:
> > >
> > > Since we have a writeq() for 32-bit architectures as provided by
> > > IO non-atomic helpers, there is no need to open code it.
> > >
> > > Moreover sparse complains about this:
> > >
> > > drivers/scsi/mpt3sas/mpt3sas_base.c:2975:16: expected unsigned
> > > long long val
> > > drivers/scsi/mpt3sas/mpt3sas_base.c:2975:16: got restricted
> > > __le64
> > > <noident>
> > >
> > > Fixing this by replacing custom writeq() with one provided by
> > > io-64-nonatomic-lo-hi.h header.
> > >
>
> >
> > >
> > > -#if defined(writeq) && defined(CONFIG_64BIT) -static inline void
> > > -_base_writeq(__u64 b, volatile void __iomem *addr, spinlock_t
> > > *writeq_lock)
> > > -{
> > > -	writeq(cpu_to_le64(b), addr);
> > > -}
> > > -#else
> > >  static inline void
> > >  _base_writeq(__u64 b, volatile void __iomem *addr, spinlock_t
> > > *writeq_lock)
> > >  {
> > > @@ -2985,11 +2979,9 @@ _base_writeq(__u64 b, volatile void __iomem
> > > *addr, spinlock_t *writeq_lock)
> > >  	__u64 data_out = cpu_to_le64(b);
> > >
> > >  	spin_lock_irqsave(writeq_lock, flags);
> > > -	writel((u32)(data_out), addr);
> > > -	writel((u32)(data_out >> 32), (addr + 4));
> > > +	writeq(data_out, addr);
> > >  	spin_unlock_irqrestore(writeq_lock, flags);
> > >  }
> > > -#endif
> >
> > This would rather defeat the purpose of the original code, I think.
>
> James, TBH, I don't see any value of that lock. What it's protecting
> from? simultaneous thread doing writeq()? But this is pointless if at
> the same time you will have writel() to the device.

The lock prevents two threads doing an interleaved write to this specific
address which could be caused by two threads writing to the same address.
If I remember correctly the firmware hangs in that case.

> For my opinion perhaps complete removal of the custom writeq() and
> replacing it by just writeq() with enabled non-atomic helpers will do
> the job.
>
> The code is very old, and I have no idea why it's done this (strange)
> way.

The write seems to trigger starting the engine on the HBA if you look at the
code, which is why it must be written completely and in order.
 It's equivalent to a mailbox post.

James
diff mbox

Patch

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 59a87ca328d3..a92ab4a801d7 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -56,6 +56,7 @@ 
 #include <linux/interrupt.h>
 #include <linux/dma-mapping.h>
 #include <linux/io.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
 #include <linux/time.h>
 #include <linux/ktime.h>
 #include <linux/kthread.h>
@@ -2968,16 +2969,9 @@  mpt3sas_base_free_smid(struct MPT3SAS_ADAPTER *ioc, u16 smid)
  * @writeq_lock: spin lock
  *
  * Glue for handling an atomic 64 bit word to MMIO. This special handling takes
- * care of 32 bit environment where its not quarenteed to send the entire word
+ * care of 32 bit environment where its not guaranteed to send the entire word
  * in one transfer.
  */
-#if defined(writeq) && defined(CONFIG_64BIT)
-static inline void
-_base_writeq(__u64 b, volatile void __iomem *addr, spinlock_t *writeq_lock)
-{
-	writeq(cpu_to_le64(b), addr);
-}
-#else
 static inline void
 _base_writeq(__u64 b, volatile void __iomem *addr, spinlock_t *writeq_lock)
 {
@@ -2985,11 +2979,9 @@  _base_writeq(__u64 b, volatile void __iomem *addr, spinlock_t *writeq_lock)
 	__u64 data_out = cpu_to_le64(b);
 
 	spin_lock_irqsave(writeq_lock, flags);
-	writel((u32)(data_out), addr);
-	writel((u32)(data_out >> 32), (addr + 4));
+	writeq(data_out, addr);
 	spin_unlock_irqrestore(writeq_lock, flags);
 }
-#endif
 
 /**
  * _base_put_smid_scsi_io - send SCSI_IO request to firmware