Commit f62ae6cd authored by Michael Buesch's avatar Michael Buesch Committed by John W. Linville

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: default avatarMichael Buesch <mb@bu3sch.de>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 88d89526
...@@ -395,9 +395,8 @@ u32 __b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset) ...@@ -395,9 +395,8 @@ u32 __b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset)
/* Unaligned access */ /* Unaligned access */
b43_shm_control_word(dev, routing, offset >> 2); b43_shm_control_word(dev, routing, offset >> 2);
ret = b43_read16(dev, B43_MMIO_SHM_DATA_UNALIGNED); ret = b43_read16(dev, B43_MMIO_SHM_DATA_UNALIGNED);
ret <<= 16;
b43_shm_control_word(dev, routing, (offset >> 2) + 1); b43_shm_control_word(dev, routing, (offset >> 2) + 1);
ret |= b43_read16(dev, B43_MMIO_SHM_DATA); ret |= ((u32)b43_read16(dev, B43_MMIO_SHM_DATA)) << 16;
goto out; goto out;
} }
...@@ -464,9 +463,10 @@ void __b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value ...@@ -464,9 +463,10 @@ void __b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value
/* Unaligned access */ /* Unaligned access */
b43_shm_control_word(dev, routing, offset >> 2); b43_shm_control_word(dev, routing, offset >> 2);
b43_write16(dev, B43_MMIO_SHM_DATA_UNALIGNED, b43_write16(dev, B43_MMIO_SHM_DATA_UNALIGNED,
(value >> 16) & 0xffff); value & 0xFFFF);
b43_shm_control_word(dev, routing, (offset >> 2) + 1); b43_shm_control_word(dev, routing, (offset >> 2) + 1);
b43_write16(dev, B43_MMIO_SHM_DATA, value & 0xffff); b43_write16(dev, B43_MMIO_SHM_DATA,
(value >> 16) & 0xFFFF);
return; return;
} }
offset >>= 2; offset >>= 2;
...@@ -2931,9 +2931,10 @@ static void b43_periodic_tasks_setup(struct b43_wldev *dev) ...@@ -2931,9 +2931,10 @@ static void b43_periodic_tasks_setup(struct b43_wldev *dev)
/* Check if communication with the device works correctly. */ /* Check if communication with the device works correctly. */
static int b43_validate_chipaccess(struct b43_wldev *dev) static int b43_validate_chipaccess(struct b43_wldev *dev)
{ {
u32 v, backup; u32 v, backup0, backup4;
backup = b43_shm_read32(dev, B43_SHM_SHARED, 0); backup0 = b43_shm_read32(dev, B43_SHM_SHARED, 0);
backup4 = b43_shm_read32(dev, B43_SHM_SHARED, 4);
/* Check for read/write and endianness problems. */ /* Check for read/write and endianness problems. */
b43_shm_write32(dev, B43_SHM_SHARED, 0, 0x55AAAA55); b43_shm_write32(dev, B43_SHM_SHARED, 0, 0x55AAAA55);
...@@ -2943,7 +2944,23 @@ static int b43_validate_chipaccess(struct b43_wldev *dev) ...@@ -2943,7 +2944,23 @@ static int b43_validate_chipaccess(struct b43_wldev *dev)
if (b43_shm_read32(dev, B43_SHM_SHARED, 0) != 0xAA5555AA) if (b43_shm_read32(dev, B43_SHM_SHARED, 0) != 0xAA5555AA)
goto error; goto error;
b43_shm_write32(dev, B43_SHM_SHARED, 0, backup); /* Check if unaligned 32bit SHM_SHARED access works properly.
* However, don't bail out on failure, because it's noncritical. */
b43_shm_write16(dev, B43_SHM_SHARED, 0, 0x1122);
b43_shm_write16(dev, B43_SHM_SHARED, 2, 0x3344);
b43_shm_write16(dev, B43_SHM_SHARED, 4, 0x5566);
b43_shm_write16(dev, B43_SHM_SHARED, 6, 0x7788);
if (b43_shm_read32(dev, B43_SHM_SHARED, 2) != 0x55663344)
b43warn(dev->wl, "Unaligned 32bit SHM read access is broken\n");
b43_shm_write32(dev, B43_SHM_SHARED, 2, 0xAABBCCDD);
if (b43_shm_read16(dev, B43_SHM_SHARED, 0) != 0x1122 ||
b43_shm_read16(dev, B43_SHM_SHARED, 2) != 0xCCDD ||
b43_shm_read16(dev, B43_SHM_SHARED, 4) != 0xAABB ||
b43_shm_read16(dev, B43_SHM_SHARED, 6) != 0x7788)
b43warn(dev->wl, "Unaligned 32bit SHM write access is broken\n");
b43_shm_write32(dev, B43_SHM_SHARED, 0, backup0);
b43_shm_write32(dev, B43_SHM_SHARED, 4, backup4);
if ((dev->dev->id.revision >= 3) && (dev->dev->id.revision <= 10)) { if ((dev->dev->id.revision >= 3) && (dev->dev->id.revision <= 10)) {
/* The 32bit register shadows the two 16bit registers /* The 32bit register shadows the two 16bit registers
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment