linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] [SCSI] mvsas: fix multiple shift issues
@ 2012-11-05 19:53 Xi Wang
  2012-11-05 19:53 ` [PATCH 1/3] [SCSI] mvsas: fix shift in mvs_94xx_assign_reg_set() Xi Wang
                   ` (3 more replies)
  0 siblings, 4 replies; 10+ messages in thread
From: Xi Wang @ 2012-11-05 19:53 UTC (permalink / raw)
  To: Xiangliang Yu; +Cc: Xi Wang, James E.J. Bottomley, linux-scsi, linux-kernel

The main issue is that bit(n) is defined as:

	(u32)1 << n

Thus bit(n) with n >= 32 will produce 0 or 1, depending on the
architecture.  This is also undefined behavior in C.

The OR with sata_reg_set (u64) then doesn't work because bit()
does a 32-bit shift, which should have been a 64-bit shift:

	if (i >= 32) {
		mvi->sata_reg_set |= bit(i);
		...
	}

The other two patches fix similar oversized shift issues.

Xi Wang (3):
  [SCSI] mvsas: fix shift in mvs_94xx_assign_reg_set()
  [SCSI] mvsas: fix shift in mvs_94xx_free_reg_set()
  [SCSI] mvsas: fix shift in mv_ffc64()

 drivers/scsi/mvsas/mv_94xx.c |    8 +++++---
 drivers/scsi/mvsas/mv_94xx.h |   14 ++------------
 drivers/scsi/mvsas/mv_sas.h  |    2 +-
 3 files changed, 8 insertions(+), 16 deletions(-)

-- 
1.7.10.4


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/3] [SCSI] mvsas: fix shift in mvs_94xx_assign_reg_set()
  2012-11-05 19:53 [PATCH 0/3] [SCSI] mvsas: fix multiple shift issues Xi Wang
@ 2012-11-05 19:53 ` Xi Wang
  2012-11-05 19:53 ` [PATCH 2/3] [SCSI] mvsas: fix shift in mvs_94xx_free_reg_set() Xi Wang
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 10+ messages in thread
From: Xi Wang @ 2012-11-05 19:53 UTC (permalink / raw)
  To: Xiangliang Yu; +Cc: Xi Wang, James E.J. Bottomley, linux-scsi, linux-kernel

The macro bit(n) is defined as ((u32)1 << n), and thus it doesn't
work with n >= 32, such as in mvs_94xx_assign_reg_set():

	if (i >= 32) {
		mvi->sata_reg_set |= bit(i);
		...
	}

The shift ((u32)1 << n) with n >= 32 also leads to undefined behavior.
The result varies depending on the architecture.

This patch changes bit(n) to do a 64-bit shift.

Signed-off-by: Xi Wang <xi.wang@gmail.com>
---
 drivers/scsi/mvsas/mv_sas.h |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/mvsas/mv_sas.h b/drivers/scsi/mvsas/mv_sas.h
index c04a4f5..da24955 100644
--- a/drivers/scsi/mvsas/mv_sas.h
+++ b/drivers/scsi/mvsas/mv_sas.h
@@ -69,7 +69,7 @@ extern struct kmem_cache *mvs_task_list_cache;
 #define DEV_IS_EXPANDER(type)	\
 	((type == EDGE_DEV) || (type == FANOUT_DEV))
 
-#define bit(n) ((u32)1 << n)
+#define bit(n) ((u64)1 << n)
 
 #define for_each_phy(__lseq_mask, __mc, __lseq)			\
 	for ((__mc) = (__lseq_mask), (__lseq) = 0;		\
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/3] [SCSI] mvsas: fix shift in mvs_94xx_free_reg_set()
  2012-11-05 19:53 [PATCH 0/3] [SCSI] mvsas: fix multiple shift issues Xi Wang
  2012-11-05 19:53 ` [PATCH 1/3] [SCSI] mvsas: fix shift in mvs_94xx_assign_reg_set() Xi Wang
@ 2012-11-05 19:53 ` Xi Wang
  2012-11-06 12:06   ` James Bottomley
  2012-11-05 19:53 ` [PATCH 3/3] [SCSI] mvsas: fix shift in mv_ffc64() Xi Wang
  2012-11-16 19:40 ` [PATCH v2] [SCSI] mvsas: fix undefined bit shift Xi Wang
  3 siblings, 1 reply; 10+ messages in thread
From: Xi Wang @ 2012-11-05 19:53 UTC (permalink / raw)
  To: Xiangliang Yu; +Cc: Xi Wang, James E.J. Bottomley, linux-scsi, linux-kernel

Invoking bit(n) with n >= 64 is undefined behavior, since bit(n) does
a 64-bit shift.  This patch adds a check on the shifting amount.

Signed-off-by: Xi Wang <xi.wang@gmail.com>
---
 drivers/scsi/mvsas/mv_94xx.c |    8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/mvsas/mv_94xx.c b/drivers/scsi/mvsas/mv_94xx.c
index 7e423e5..e1f35d4 100644
--- a/drivers/scsi/mvsas/mv_94xx.c
+++ b/drivers/scsi/mvsas/mv_94xx.c
@@ -715,11 +715,13 @@ static void mvs_94xx_free_reg_set(struct mvs_info *mvi, u8 *tfs)
 	if (*tfs == MVS_ID_NOT_MAPPED)
 		return;
 
-	mvi->sata_reg_set &= ~bit(reg_set);
-	if (reg_set < 32)
+	if (reg_set < 32) {
+		mvi->sata_reg_set &= ~bit(reg_set);
 		w_reg_set_enable(reg_set, (u32)mvi->sata_reg_set);
-	else
+	} else if (reg_set < 64) {
+		mvi->sata_reg_set &= ~bit(reg_set);
 		w_reg_set_enable(reg_set, (u32)(mvi->sata_reg_set >> 32));
+	}
 
 	*tfs = MVS_ID_NOT_MAPPED;
 
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 3/3] [SCSI] mvsas: fix shift in mv_ffc64()
  2012-11-05 19:53 [PATCH 0/3] [SCSI] mvsas: fix multiple shift issues Xi Wang
  2012-11-05 19:53 ` [PATCH 1/3] [SCSI] mvsas: fix shift in mvs_94xx_assign_reg_set() Xi Wang
  2012-11-05 19:53 ` [PATCH 2/3] [SCSI] mvsas: fix shift in mvs_94xx_free_reg_set() Xi Wang
@ 2012-11-05 19:53 ` Xi Wang
  2012-11-16 19:40 ` [PATCH v2] [SCSI] mvsas: fix undefined bit shift Xi Wang
  3 siblings, 0 replies; 10+ messages in thread
From: Xi Wang @ 2012-11-05 19:53 UTC (permalink / raw)
  To: Xiangliang Yu; +Cc: Xi Wang, James E.J. Bottomley, linux-scsi, linux-kernel

Invoking ffz(x) with x = ~0 is undefined.  This patch returns -1
for this case, and invokes __ffs64() instead.

Signed-off-by: Xi Wang <xi.wang@gmail.com>
---
 drivers/scsi/mvsas/mv_94xx.h |   14 ++------------
 1 file changed, 2 insertions(+), 12 deletions(-)

diff --git a/drivers/scsi/mvsas/mv_94xx.h b/drivers/scsi/mvsas/mv_94xx.h
index 8f7eb4f..487aa6f 100644
--- a/drivers/scsi/mvsas/mv_94xx.h
+++ b/drivers/scsi/mvsas/mv_94xx.h
@@ -258,21 +258,11 @@ enum sas_sata_phy_regs {
 #define SPI_ADDR_VLD_94XX         	(1U << 1)
 #define SPI_CTRL_SpiStart_94XX     	(1U << 0)
 
-#define mv_ffc(x)   ffz(x)
-
 static inline int
 mv_ffc64(u64 v)
 {
-	int i;
-	i = mv_ffc((u32)v);
-	if (i >= 0)
-		return i;
-	i = mv_ffc((u32)(v>>32));
-
-	if (i != 0)
-		return 32 + i;
-
-	return -1;
+	u64 x = ~v;
+	return x ? __ffs64(x) : -1;
 }
 
 #define r_reg_set_enable(i) \
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/3] [SCSI] mvsas: fix shift in mvs_94xx_free_reg_set()
  2012-11-05 19:53 ` [PATCH 2/3] [SCSI] mvsas: fix shift in mvs_94xx_free_reg_set() Xi Wang
@ 2012-11-06 12:06   ` James Bottomley
  2012-11-06 20:55     ` Xi Wang
  0 siblings, 1 reply; 10+ messages in thread
From: James Bottomley @ 2012-11-06 12:06 UTC (permalink / raw)
  To: Xi Wang; +Cc: Xiangliang Yu, linux-scsi, linux-kernel

On Mon, 2012-11-05 at 14:53 -0500, Xi Wang wrote:
> Invoking bit(n) with n >= 64 is undefined behavior, since bit(n) does
> a 64-bit shift.  This patch adds a check on the shifting amount.

Why is this necessary?  As I read the reg set assignment code, it finds
a free bit in the 64 bit register and uses that ... which can never be
greater than 64 so there's no need for the check.

The other two look OK (probably redone as a single patch with a stable
tag), but I'd like the input of the mvs people since it seems with the
current code, we only use 32 bit regsets and probably hang if we go over
that.  The bug fix is either to enable the full 64 if it works, or
possibly cap at 32 ... what works with all released devices?

James



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/3] [SCSI] mvsas: fix shift in mvs_94xx_free_reg_set()
  2012-11-06 12:06   ` James Bottomley
@ 2012-11-06 20:55     ` Xi Wang
  2012-11-09  7:30       ` Xiangliang Yu
  0 siblings, 1 reply; 10+ messages in thread
From: Xi Wang @ 2012-11-06 20:55 UTC (permalink / raw)
  To: James Bottomley; +Cc: Xiangliang Yu, linux-scsi, linux-kernel

On 11/6/12 7:06 AM, James Bottomley wrote:
>
> Why is this necessary?  As I read the reg set assignment code, it finds
> a free bit in the 64 bit register and uses that ... which can never be
> greater than 64 so there's no need for the check.

This patch just tries to be more defensive for bit(reg_set) with a
broken reg_set value.  I agree with you that it's not that necessary.

> The other two look OK (probably redone as a single patch with a stable
> tag), but I'd like the input of the mvs people since it seems with the
> current code, we only use 32 bit regsets and probably hang if we go over
> that.  The bug fix is either to enable the full 64 if it works, or
> possibly cap at 32 ... what works with all released devices?

Thanks for reviewing.  Yeah we'd better to wait for the input from
the mvs people.

- xi

^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: [PATCH 2/3] [SCSI] mvsas: fix shift in mvs_94xx_free_reg_set()
  2012-11-06 20:55     ` Xi Wang
@ 2012-11-09  7:30       ` Xiangliang Yu
  2012-11-09 13:44         ` Xi Wang
  0 siblings, 1 reply; 10+ messages in thread
From: Xiangliang Yu @ 2012-11-09  7:30 UTC (permalink / raw)
  To: Xi Wang, James Bottomley; +Cc: linux-scsi, linux-kernel


> On 11/6/12 7:06 AM, James Bottomley wrote:
> >
> > Why is this necessary?  As I read the reg set assignment code, it finds
> > a free bit in the 64 bit register and uses that ... which can never be
> > greater than 64 so there's no need for the check.
> 
> This patch just tries to be more defensive for bit(reg_set) with a
> broken reg_set value.  I agree with you that it's not that necessary.

Agree with James, and just need to do NOT operation one time

> 
> > The other two look OK (probably redone as a single patch with a stable
> > tag), but I'd like the input of the mvs people since it seems with the
> > current code, we only use 32 bit regsets and probably hang if we go over
> > that.  The bug fix is either to enable the full 64 if it works, or
> > possibly cap at 32 ... what works with all released devices?
> 
> Thanks for reviewing.  Yeah we'd better to wait for the input from
> the mvs people.

About patch 3, I check the ffz code and found it will check ~0 conditions.



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/3] [SCSI] mvsas: fix shift in mvs_94xx_free_reg_set()
  2012-11-09  7:30       ` Xiangliang Yu
@ 2012-11-09 13:44         ` Xi Wang
  2012-11-16  7:39           ` Xiangliang Yu
  0 siblings, 1 reply; 10+ messages in thread
From: Xi Wang @ 2012-11-09 13:44 UTC (permalink / raw)
  To: Xiangliang Yu; +Cc: James Bottomley, linux-scsi, linux-kernel

On 11/9/12 2:30 AM, Xiangliang Yu wrote:
> Agree with James, and just need to do NOT operation one time

Thanks for reviewing the patches.

Okay I'll remove patch 2 in v2 then.

> About patch 3, I check the ffz code and found it will check ~0 conditions.

Can you point me to the ~0 check in ffz code?  I also feel like using
__ffs64 makes the code simpler.

Does patch 1 look good to you?  Thanks.

- xi

^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: [PATCH 2/3] [SCSI] mvsas: fix shift in mvs_94xx_free_reg_set()
  2012-11-09 13:44         ` Xi Wang
@ 2012-11-16  7:39           ` Xiangliang Yu
  0 siblings, 0 replies; 10+ messages in thread
From: Xiangliang Yu @ 2012-11-16  7:39 UTC (permalink / raw)
  To: Xi Wang; +Cc: James Bottomley, linux-scsi, linux-kernel

Hi, Xi

> > About patch 3, I check the ffz code and found it will check ~0 conditions.
> 
> Can you point me to the ~0 check in ffz code?  I also feel like using
> __ffs64 makes the code simpler.
Yes, it seem to be ok

> 
> Does patch 1 look good to you?  Thanks.
> 
Yes

Thanks!


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v2] [SCSI] mvsas: fix undefined bit shift
  2012-11-05 19:53 [PATCH 0/3] [SCSI] mvsas: fix multiple shift issues Xi Wang
                   ` (2 preceding siblings ...)
  2012-11-05 19:53 ` [PATCH 3/3] [SCSI] mvsas: fix shift in mv_ffc64() Xi Wang
@ 2012-11-16 19:40 ` Xi Wang
  3 siblings, 0 replies; 10+ messages in thread
From: Xi Wang @ 2012-11-16 19:40 UTC (permalink / raw)
  To: Xiangliang Yu, James E.J. Bottomley; +Cc: linux-scsi, linux-kernel, stable

The macro bit(n) is defined as ((u32)1 << n), and thus it doesn't work
with n >= 32, such as in mvs_94xx_assign_reg_set():

	if (i >= 32) {
		mvi->sata_reg_set |= bit(i);
		...
	}

The shift ((u32)1 << n) with n >= 32 also leads to undefined behavior.
The result varies depending on the architecture.

This patch changes bit(n) to do a 64-bit shift.  It also simplifies
mv_ffc64() using __ffs64(), since invoking ffz() with ~0 is undefined.

Signed-off-by: Xi Wang <xi.wang@gmail.com>
Cc: Xiangliang Yu <yuxiangl@marvell.com>
Cc: James Bottomley <JBottomley@Parallels.com>
Cc: stable@vger.kernel.org
---
As suggested by James, v2 is a single patch with a stable tag.
---
 drivers/scsi/mvsas/mv_94xx.h |   14 ++------------
 drivers/scsi/mvsas/mv_sas.h  |    2 +-
 2 files changed, 3 insertions(+), 13 deletions(-)

diff --git a/drivers/scsi/mvsas/mv_94xx.h b/drivers/scsi/mvsas/mv_94xx.h
index 8f7eb4f..487aa6f 100644
--- a/drivers/scsi/mvsas/mv_94xx.h
+++ b/drivers/scsi/mvsas/mv_94xx.h
@@ -258,21 +258,11 @@ enum sas_sata_phy_regs {
 #define SPI_ADDR_VLD_94XX         	(1U << 1)
 #define SPI_CTRL_SpiStart_94XX     	(1U << 0)
 
-#define mv_ffc(x)   ffz(x)
-
 static inline int
 mv_ffc64(u64 v)
 {
-	int i;
-	i = mv_ffc((u32)v);
-	if (i >= 0)
-		return i;
-	i = mv_ffc((u32)(v>>32));
-
-	if (i != 0)
-		return 32 + i;
-
-	return -1;
+	u64 x = ~v;
+	return x ? __ffs64(x) : -1;
 }
 
 #define r_reg_set_enable(i) \
diff --git a/drivers/scsi/mvsas/mv_sas.h b/drivers/scsi/mvsas/mv_sas.h
index c04a4f5..da24955 100644
--- a/drivers/scsi/mvsas/mv_sas.h
+++ b/drivers/scsi/mvsas/mv_sas.h
@@ -69,7 +69,7 @@ extern struct kmem_cache *mvs_task_list_cache;
 #define DEV_IS_EXPANDER(type)	\
 	((type == EDGE_DEV) || (type == FANOUT_DEV))
 
-#define bit(n) ((u32)1 << n)
+#define bit(n) ((u64)1 << n)
 
 #define for_each_phy(__lseq_mask, __mc, __lseq)			\
 	for ((__mc) = (__lseq_mask), (__lseq) = 0;		\
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2012-11-16 19:40 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-11-05 19:53 [PATCH 0/3] [SCSI] mvsas: fix multiple shift issues Xi Wang
2012-11-05 19:53 ` [PATCH 1/3] [SCSI] mvsas: fix shift in mvs_94xx_assign_reg_set() Xi Wang
2012-11-05 19:53 ` [PATCH 2/3] [SCSI] mvsas: fix shift in mvs_94xx_free_reg_set() Xi Wang
2012-11-06 12:06   ` James Bottomley
2012-11-06 20:55     ` Xi Wang
2012-11-09  7:30       ` Xiangliang Yu
2012-11-09 13:44         ` Xi Wang
2012-11-16  7:39           ` Xiangliang Yu
2012-11-05 19:53 ` [PATCH 3/3] [SCSI] mvsas: fix shift in mv_ffc64() Xi Wang
2012-11-16 19:40 ` [PATCH v2] [SCSI] mvsas: fix undefined bit shift Xi Wang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).