aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/b43/main.c
diff options
context:
space:
mode:
authorMichael Buesch <mb@bu3sch.de>2009-07-31 14:51:41 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-08-04 16:44:21 -0400
commitf62ae6cd887a184d6923037d588b5b2466aa2a97 (patch)
tree9017155281a2948f43235439438002779935cb38 /drivers/net/wireless/b43/main.c
parent88d89526a671ba008f59456161b0c513cdfb5d5a (diff)
b43: Fix unaligned 32bit SHM-shared access
This fixes unaligned 32bit SHM-shared read/write access. The low and high 16 bits were swapped. It also adds a testcase for this to the chipaccess validation. (Thanks to Albert Herranz for tracking down this bug.) Signed-off-by: Michael Buesch <mb@bu3sch.de> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/b43/main.c')
-rw-r--r--drivers/net/wireless/b43/main.c31
1 files changed, 24 insertions, 7 deletions
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index f985938962e3..a048de5fcc73 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -395,9 +395,8 @@ u32 __b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset)
395 /* Unaligned access */ 395 /* Unaligned access */
396 b43_shm_control_word(dev, routing, offset >> 2); 396 b43_shm_control_word(dev, routing, offset >> 2);
397 ret = b43_read16(dev, B43_MMIO_SHM_DATA_UNALIGNED); 397 ret = b43_read16(dev, B43_MMIO_SHM_DATA_UNALIGNED);
398 ret <<= 16;
399 b43_shm_control_word(dev, routing, (offset >> 2) + 1); 398 b43_shm_control_word(dev, routing, (offset >> 2) + 1);
400 ret |= b43_read16(dev, B43_MMIO_SHM_DATA); 399 ret |= ((u32)b43_read16(dev, B43_MMIO_SHM_DATA)) << 16;
401 400
402 goto out; 401 goto out;
403 } 402 }
@@ -464,9 +463,10 @@ void __b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value
464 /* Unaligned access */ 463 /* Unaligned access */
465 b43_shm_control_word(dev, routing, offset >> 2); 464 b43_shm_control_word(dev, routing, offset >> 2);
466 b43_write16(dev, B43_MMIO_SHM_DATA_UNALIGNED, 465 b43_write16(dev, B43_MMIO_SHM_DATA_UNALIGNED,
467 (value >> 16) & 0xffff); 466 value & 0xFFFF);
468 b43_shm_control_word(dev, routing, (offset >> 2) + 1); 467 b43_shm_control_word(dev, routing, (offset >> 2) + 1);
469 b43_write16(dev, B43_MMIO_SHM_DATA, value & 0xffff); 468 b43_write16(dev, B43_MMIO_SHM_DATA,
469 (value >> 16) & 0xFFFF);
470 return; 470 return;
471 } 471 }
472 offset >>= 2; 472 offset >>= 2;
@@ -2931,9 +2931,10 @@ static void b43_periodic_tasks_setup(struct b43_wldev *dev)
2931/* Check if communication with the device works correctly. */ 2931/* Check if communication with the device works correctly. */
2932static int b43_validate_chipaccess(struct b43_wldev *dev) 2932static int b43_validate_chipaccess(struct b43_wldev *dev)
2933{ 2933{
2934 u32 v, backup; 2934 u32 v, backup0, backup4;
2935 2935
2936 backup = b43_shm_read32(dev, B43_SHM_SHARED, 0); 2936 backup0 = b43_shm_read32(dev, B43_SHM_SHARED, 0);
2937 backup4 = b43_shm_read32(dev, B43_SHM_SHARED, 4);
2937 2938
2938 /* Check for read/write and endianness problems. */ 2939 /* Check for read/write and endianness problems. */
2939 b43_shm_write32(dev, B43_SHM_SHARED, 0, 0x55AAAA55); 2940 b43_shm_write32(dev, B43_SHM_SHARED, 0, 0x55AAAA55);
@@ -2943,7 +2944,23 @@ static int b43_validate_chipaccess(struct b43_wldev *dev)
2943 if (b43_shm_read32(dev, B43_SHM_SHARED, 0) != 0xAA5555AA) 2944 if (b43_shm_read32(dev, B43_SHM_SHARED, 0) != 0xAA5555AA)
2944 goto error; 2945 goto error;
2945 2946
2946 b43_shm_write32(dev, B43_SHM_SHARED, 0, backup); 2947 /* Check if unaligned 32bit SHM_SHARED access works properly.
2948 * However, don't bail out on failure, because it's noncritical. */
2949 b43_shm_write16(dev, B43_SHM_SHARED, 0, 0x1122);
2950 b43_shm_write16(dev, B43_SHM_SHARED, 2, 0x3344);
2951 b43_shm_write16(dev, B43_SHM_SHARED, 4, 0x5566);
2952 b43_shm_write16(dev, B43_SHM_SHARED, 6, 0x7788);
2953 if (b43_shm_read32(dev, B43_SHM_SHARED, 2) != 0x55663344)
2954 b43warn(dev->wl, "Unaligned 32bit SHM read access is broken\n");
2955 b43_shm_write32(dev, B43_SHM_SHARED, 2, 0xAABBCCDD);
2956 if (b43_shm_read16(dev, B43_SHM_SHARED, 0) != 0x1122 ||
2957 b43_shm_read16(dev, B43_SHM_SHARED, 2) != 0xCCDD ||
2958 b43_shm_read16(dev, B43_SHM_SHARED, 4) != 0xAABB ||
2959 b43_shm_read16(dev, B43_SHM_SHARED, 6) != 0x7788)
2960 b43warn(dev->wl, "Unaligned 32bit SHM write access is broken\n");
2961
2962 b43_shm_write32(dev, B43_SHM_SHARED, 0, backup0);
2963 b43_shm_write32(dev, B43_SHM_SHARED, 4, backup4);
2947 2964
2948 if ((dev->dev->id.revision >= 3) && (dev->dev->id.revision <= 10)) { 2965 if ((dev->dev->id.revision >= 3) && (dev->dev->id.revision <= 10)) {
2949 /* The 32bit register shadows the two 16bit registers 2966 /* The 32bit register shadows the two 16bit registers