Message ID | 20180214181034.36529-1-andriy.shevchenko@linux.intel.com (mailing list archive) |
---|---|
State | Rejected |
Headers | show |
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
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.
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
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 --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
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(-)