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

b43: flush some writes on Broadcom MIPS SoCs

Access to PHY and radio registers is indirect on Broadcom hardware and
it seems that addressing on some MIPS SoCs may require flushing. So far
this problem was noticed on 0x4716 SoC only (marketing names: BCM4717,
BCM4718).

Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

authored by

Rafał Miłecki and committed by
John W. Linville
25c15566 d342b95d

+49 -29
+10
drivers/net/wireless/b43/b43.h
··· 1012 1012 dev->dev->write16(dev->dev, offset, value); 1013 1013 } 1014 1014 1015 + /* To optimize this check for flush_writes on BCM47XX_BCMA only. */ 1016 + static inline void b43_write16f(struct b43_wldev *dev, u16 offset, u16 value) 1017 + { 1018 + b43_write16(dev, offset, value); 1019 + #if defined(CONFIG_BCM47XX_BCMA) 1020 + if (dev->dev->flush_writes) 1021 + b43_read16(dev, offset); 1022 + #endif 1023 + } 1024 + 1015 1025 static inline void b43_maskset16(struct b43_wldev *dev, u16 offset, u16 mask, 1016 1026 u16 set) 1017 1027 {
+10
drivers/net/wireless/b43/bus.c
··· 22 22 23 23 */ 24 24 25 + #ifdef CONFIG_BCM47XX_BCMA 26 + #include <asm/mach-bcm47xx/bcm47xx.h> 27 + #endif 28 + 25 29 #include "b43.h" 26 30 #include "bus.h" 27 31 ··· 106 102 dev->write32 = b43_bus_bcma_write32; 107 103 dev->block_read = b43_bus_bcma_block_read; 108 104 dev->block_write = b43_bus_bcma_block_write; 105 + #ifdef CONFIG_BCM47XX_BCMA 106 + if (b43_bus_host_is_pci(dev) && 107 + bcm47xx_bus_type == BCM47XX_BUS_TYPE_BCMA && 108 + bcm47xx_bus.bcma.bus.chipinfo.id == BCMA_CHIP_ID_BCM4716) 109 + dev->flush_writes = true; 110 + #endif 109 111 110 112 dev->dev = &core->dev; 111 113 dev->dma_dev = core->dma_dev;
+1
drivers/net/wireless/b43/bus.h
··· 33 33 size_t count, u16 offset, u8 reg_width); 34 34 void (*block_write)(struct b43_bus_dev *dev, const void *buffer, 35 35 size_t count, u16 offset, u8 reg_width); 36 + bool flush_writes; 36 37 37 38 struct device *dev; 38 39 struct device *dma_dev;
+8 -9
drivers/net/wireless/b43/main.c
··· 4466 4466 if (core_rev == 40 || core_rev == 42) { 4467 4467 radio_manuf = 0x17F; 4468 4468 4469 - b43_write16(dev, B43_MMIO_RADIO24_CONTROL, 0); 4469 + b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, 0); 4470 4470 radio_rev = b43_read16(dev, B43_MMIO_RADIO24_DATA); 4471 4471 4472 - b43_write16(dev, B43_MMIO_RADIO24_CONTROL, 1); 4472 + b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, 1); 4473 4473 radio_id = b43_read16(dev, B43_MMIO_RADIO24_DATA); 4474 4474 4475 4475 radio_ver = 0; /* Is there version somewhere? */ ··· 4477 4477 u16 radio24[3]; 4478 4478 4479 4479 for (tmp = 0; tmp < 3; tmp++) { 4480 - b43_write16(dev, B43_MMIO_RADIO24_CONTROL, tmp); 4480 + b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, tmp); 4481 4481 radio24[tmp] = b43_read16(dev, B43_MMIO_RADIO24_DATA); 4482 4482 } 4483 4483 ··· 4494 4494 else 4495 4495 tmp = 0x5205017F; 4496 4496 } else { 4497 - b43_write16(dev, B43_MMIO_RADIO_CONTROL, 4498 - B43_RADIOCTL_ID); 4497 + b43_write16f(dev, B43_MMIO_RADIO_CONTROL, 4498 + B43_RADIOCTL_ID); 4499 4499 tmp = b43_read16(dev, B43_MMIO_RADIO_DATA_LOW); 4500 - b43_write16(dev, B43_MMIO_RADIO_CONTROL, 4501 - B43_RADIOCTL_ID); 4502 - tmp |= (u32)b43_read16(dev, B43_MMIO_RADIO_DATA_HIGH) 4503 - << 16; 4500 + b43_write16f(dev, B43_MMIO_RADIO_CONTROL, 4501 + B43_RADIOCTL_ID); 4502 + tmp |= b43_read16(dev, B43_MMIO_RADIO_DATA_HIGH) << 16; 4504 4503 } 4505 4504 radio_manuf = (tmp & 0x00000FFF); 4506 4505 radio_id = (tmp & 0x0FFFF000) >> 12;
+2 -2
drivers/net/wireless/b43/phy_a.c
··· 444 444 static u16 b43_aphy_op_read(struct b43_wldev *dev, u16 reg) 445 445 { 446 446 reg = adjust_phyreg(dev, reg); 447 - b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); 447 + b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg); 448 448 return b43_read16(dev, B43_MMIO_PHY_DATA); 449 449 } 450 450 451 451 static void b43_aphy_op_write(struct b43_wldev *dev, u16 reg, u16 value) 452 452 { 453 453 reg = adjust_phyreg(dev, reg); 454 - b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); 454 + b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg); 455 455 b43_write16(dev, B43_MMIO_PHY_DATA, value); 456 456 } 457 457
+2 -2
drivers/net/wireless/b43/phy_common.c
··· 278 278 if (dev->phy.ops->phy_read) 279 279 return dev->phy.ops->phy_read(dev, reg); 280 280 281 - b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); 281 + b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg); 282 282 return b43_read16(dev, B43_MMIO_PHY_DATA); 283 283 } 284 284 ··· 294 294 if (dev->phy.ops->phy_write) 295 295 return dev->phy.ops->phy_write(dev, reg, value); 296 296 297 - b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); 297 + b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg); 298 298 b43_write16(dev, B43_MMIO_PHY_DATA, value); 299 299 } 300 300
+4 -4
drivers/net/wireless/b43/phy_g.c
··· 2555 2555 2556 2556 static u16 b43_gphy_op_read(struct b43_wldev *dev, u16 reg) 2557 2557 { 2558 - b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); 2558 + b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg); 2559 2559 return b43_read16(dev, B43_MMIO_PHY_DATA); 2560 2560 } 2561 2561 2562 2562 static void b43_gphy_op_write(struct b43_wldev *dev, u16 reg, u16 value) 2563 2563 { 2564 - b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); 2564 + b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg); 2565 2565 b43_write16(dev, B43_MMIO_PHY_DATA, value); 2566 2566 } 2567 2567 ··· 2572 2572 /* G-PHY needs 0x80 for read access. */ 2573 2573 reg |= 0x80; 2574 2574 2575 - b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg); 2575 + b43_write16f(dev, B43_MMIO_RADIO_CONTROL, reg); 2576 2576 return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW); 2577 2577 } 2578 2578 ··· 2581 2581 /* Register 1 is a 32-bit register. */ 2582 2582 B43_WARN_ON(reg == 1); 2583 2583 2584 - b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg); 2584 + b43_write16f(dev, B43_MMIO_RADIO_CONTROL, reg); 2585 2585 b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value); 2586 2586 } 2587 2587
+3 -3
drivers/net/wireless/b43/phy_ht.c
··· 1074 1074 static void b43_phy_ht_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask, 1075 1075 u16 set) 1076 1076 { 1077 - b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); 1077 + b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg); 1078 1078 b43_write16(dev, B43_MMIO_PHY_DATA, 1079 1079 (b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set); 1080 1080 } ··· 1084 1084 /* HT-PHY needs 0x200 for read access */ 1085 1085 reg |= 0x200; 1086 1086 1087 - b43_write16(dev, B43_MMIO_RADIO24_CONTROL, reg); 1087 + b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, reg); 1088 1088 return b43_read16(dev, B43_MMIO_RADIO24_DATA); 1089 1089 } 1090 1090 1091 1091 static void b43_phy_ht_op_radio_write(struct b43_wldev *dev, u16 reg, 1092 1092 u16 value) 1093 1093 { 1094 - b43_write16(dev, B43_MMIO_RADIO24_CONTROL, reg); 1094 + b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, reg); 1095 1095 b43_write16(dev, B43_MMIO_RADIO24_DATA, value); 1096 1096 } 1097 1097
+3 -3
drivers/net/wireless/b43/phy_lcn.c
··· 813 813 static void b43_phy_lcn_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask, 814 814 u16 set) 815 815 { 816 - b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); 816 + b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg); 817 817 b43_write16(dev, B43_MMIO_PHY_DATA, 818 818 (b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set); 819 819 } ··· 823 823 /* LCN-PHY needs 0x200 for read access */ 824 824 reg |= 0x200; 825 825 826 - b43_write16(dev, B43_MMIO_RADIO24_CONTROL, reg); 826 + b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, reg); 827 827 return b43_read16(dev, B43_MMIO_RADIO24_DATA); 828 828 } 829 829 830 830 static void b43_phy_lcn_op_radio_write(struct b43_wldev *dev, u16 reg, 831 831 u16 value) 832 832 { 833 - b43_write16(dev, B43_MMIO_RADIO24_CONTROL, reg); 833 + b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, reg); 834 834 b43_write16(dev, B43_MMIO_RADIO24_DATA, value); 835 835 } 836 836
+3 -3
drivers/net/wireless/b43/phy_lp.c
··· 1988 1988 static void b43_lpphy_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask, 1989 1989 u16 set) 1990 1990 { 1991 - b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); 1991 + b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg); 1992 1992 b43_write16(dev, B43_MMIO_PHY_DATA, 1993 1993 (b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set); 1994 1994 } ··· 2004 2004 } else 2005 2005 reg |= 0x200; 2006 2006 2007 - b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg); 2007 + b43_write16f(dev, B43_MMIO_RADIO_CONTROL, reg); 2008 2008 return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW); 2009 2009 } 2010 2010 ··· 2013 2013 /* Register 1 is a 32-bit register. */ 2014 2014 B43_WARN_ON(reg == 1); 2015 2015 2016 - b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg); 2016 + b43_write16f(dev, B43_MMIO_RADIO_CONTROL, reg); 2017 2017 b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value); 2018 2018 } 2019 2019
+3 -3
drivers/net/wireless/b43/phy_n.c
··· 6501 6501 u16 set) 6502 6502 { 6503 6503 check_phyreg(dev, reg); 6504 - b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); 6504 + b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg); 6505 6505 b43_maskset16(dev, B43_MMIO_PHY_DATA, mask, set); 6506 6506 dev->phy.writes_counter = 1; 6507 6507 } ··· 6516 6516 else 6517 6517 reg |= 0x100; 6518 6518 6519 - b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg); 6519 + b43_write16f(dev, B43_MMIO_RADIO_CONTROL, reg); 6520 6520 return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW); 6521 6521 } 6522 6522 ··· 6525 6525 /* Register 1 is a 32-bit register. */ 6526 6526 B43_WARN_ON(dev->phy.rev < 7 && reg == 1); 6527 6527 6528 - b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg); 6528 + b43_write16f(dev, B43_MMIO_RADIO_CONTROL, reg); 6529 6529 b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value); 6530 6530 } 6531 6531