Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[SCSI] mvsas: fix undefined bit shift

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>
Acked-by: Xiangliang Yu <yuxiangl@marvell.com>
Cc: stable@vger.kernel.org
Signed-off-by: James Bottomley <JBottomley@Parallels.com>

authored by

Xi Wang and committed by
James Bottomley
beecadea 072f19b4

+3 -13
+2 -12
drivers/scsi/mvsas/mv_94xx.h
··· 258 258 #define SPI_ADDR_VLD_94XX (1U << 1) 259 259 #define SPI_CTRL_SpiStart_94XX (1U << 0) 260 260 261 - #define mv_ffc(x) ffz(x) 262 - 263 261 static inline int 264 262 mv_ffc64(u64 v) 265 263 { 266 - int i; 267 - i = mv_ffc((u32)v); 268 - if (i >= 0) 269 - return i; 270 - i = mv_ffc((u32)(v>>32)); 271 - 272 - if (i != 0) 273 - return 32 + i; 274 - 275 - return -1; 264 + u64 x = ~v; 265 + return x ? __ffs64(x) : -1; 276 266 } 277 267 278 268 #define r_reg_set_enable(i) \
+1 -1
drivers/scsi/mvsas/mv_sas.h
··· 69 69 #define DEV_IS_EXPANDER(type) \ 70 70 ((type == EDGE_DEV) || (type == FANOUT_DEV)) 71 71 72 - #define bit(n) ((u32)1 << n) 72 + #define bit(n) ((u64)1 << n) 73 73 74 74 #define for_each_phy(__lseq_mask, __mc, __lseq) \ 75 75 for ((__mc) = (__lseq_mask), (__lseq) = 0; \