b43: flush some writes on Broadcom MIPS SoCs
authorRafał Miłecki <zajec5@gmail.com>
Thu, 7 Aug 2014 05:45:37 +0000 (07:45 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 25 Aug 2014 20:00:42 +0000 (16:00 -0400)
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>
drivers/net/wireless/b43/b43.h
drivers/net/wireless/b43/bus.c
drivers/net/wireless/b43/bus.h
drivers/net/wireless/b43/main.c
drivers/net/wireless/b43/phy_a.c
drivers/net/wireless/b43/phy_common.c
drivers/net/wireless/b43/phy_g.c
drivers/net/wireless/b43/phy_ht.c
drivers/net/wireless/b43/phy_lcn.c
drivers/net/wireless/b43/phy_lp.c
drivers/net/wireless/b43/phy_n.c

index 4113b69347640359aa22020eb0dcfd7efe0b7c14..9b2d0c9bfb8eb51604c7f2e071aca5a386eb2ce0 100644 (file)
@@ -1012,6 +1012,16 @@ static inline void b43_write16(struct b43_wldev *dev, u16 offset, u16 value)
        dev->dev->write16(dev->dev, offset, value);
 }
 
+/* To optimize this check for flush_writes on BCM47XX_BCMA only. */
+static inline void b43_write16f(struct b43_wldev *dev, u16 offset, u16 value)
+{
+       b43_write16(dev, offset, value);
+#if defined(CONFIG_BCM47XX_BCMA)
+       if (dev->dev->flush_writes)
+               b43_read16(dev, offset);
+#endif
+}
+
 static inline void b43_maskset16(struct b43_wldev *dev, u16 offset, u16 mask,
                                 u16 set)
 {
index 565fdbdd6915f33e36cdbea616db209cf633bc4e..17d16a391fe6556dc66ab9a6bd5e4d0bd0c954a3 100644 (file)
 
 */
 
+#ifdef CONFIG_BCM47XX_BCMA
+#include <asm/mach-bcm47xx/bcm47xx.h>
+#endif
+
 #include "b43.h"
 #include "bus.h"
 
@@ -102,6 +106,12 @@ struct b43_bus_dev *b43_bus_dev_bcma_init(struct bcma_device *core)
        dev->write32 = b43_bus_bcma_write32;
        dev->block_read = b43_bus_bcma_block_read;
        dev->block_write = b43_bus_bcma_block_write;
+#ifdef CONFIG_BCM47XX_BCMA
+       if (b43_bus_host_is_pci(dev) &&
+           bcm47xx_bus_type == BCM47XX_BUS_TYPE_BCMA &&
+           bcm47xx_bus.bcma.bus.chipinfo.id == BCMA_CHIP_ID_BCM4716)
+               dev->flush_writes = true;
+#endif
 
        dev->dev = &core->dev;
        dev->dma_dev = core->dma_dev;
index 460d9d90bddebe4bccfac2ed76413a3192918f9e..256c2c17939afe7720a643bae1c32187a9850bc5 100644 (file)
@@ -33,6 +33,7 @@ struct b43_bus_dev {
                           size_t count, u16 offset, u8 reg_width);
        void (*block_write)(struct b43_bus_dev *dev, const void *buffer,
                            size_t count, u16 offset, u8 reg_width);
+       bool flush_writes;
 
        struct device *dev;
        struct device *dma_dev;
index 2af1ac396eb451897371f6ff576f565843781e69..66ff718cc4129298d169e40300deeb3c8bb50583 100644 (file)
@@ -4466,10 +4466,10 @@ static int b43_phy_versioning(struct b43_wldev *dev)
        if (core_rev == 40 || core_rev == 42) {
                radio_manuf = 0x17F;
 
-               b43_write16(dev, B43_MMIO_RADIO24_CONTROL, 0);
+               b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, 0);
                radio_rev = b43_read16(dev, B43_MMIO_RADIO24_DATA);
 
-               b43_write16(dev, B43_MMIO_RADIO24_CONTROL, 1);
+               b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, 1);
                radio_id = b43_read16(dev, B43_MMIO_RADIO24_DATA);
 
                radio_ver = 0; /* Is there version somewhere? */
@@ -4477,7 +4477,7 @@ static int b43_phy_versioning(struct b43_wldev *dev)
                u16 radio24[3];
 
                for (tmp = 0; tmp < 3; tmp++) {
-                       b43_write16(dev, B43_MMIO_RADIO24_CONTROL, tmp);
+                       b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, tmp);
                        radio24[tmp] = b43_read16(dev, B43_MMIO_RADIO24_DATA);
                }
 
@@ -4494,13 +4494,12 @@ static int b43_phy_versioning(struct b43_wldev *dev)
                        else
                                tmp = 0x5205017F;
                } else {
-                       b43_write16(dev, B43_MMIO_RADIO_CONTROL,
-                                   B43_RADIOCTL_ID);
+                       b43_write16f(dev, B43_MMIO_RADIO_CONTROL,
+                                    B43_RADIOCTL_ID);
                        tmp = b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
-                       b43_write16(dev, B43_MMIO_RADIO_CONTROL,
-                                   B43_RADIOCTL_ID);
-                       tmp |= (u32)b43_read16(dev, B43_MMIO_RADIO_DATA_HIGH)
-                               << 16;
+                       b43_write16f(dev, B43_MMIO_RADIO_CONTROL,
+                                    B43_RADIOCTL_ID);
+                       tmp |= b43_read16(dev, B43_MMIO_RADIO_DATA_HIGH) << 16;
                }
                radio_manuf = (tmp & 0x00000FFF);
                radio_id = (tmp & 0x0FFFF000) >> 12;
index 25e40432d68b9c0c9dcc25ff44f2386b56e6ca68..99c036f5ecb7b51319d4c2b26d9b3719af028947 100644 (file)
@@ -444,14 +444,14 @@ static inline u16 adjust_phyreg(struct b43_wldev *dev, u16 offset)
 static u16 b43_aphy_op_read(struct b43_wldev *dev, u16 reg)
 {
        reg = adjust_phyreg(dev, reg);
-       b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
+       b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg);
        return b43_read16(dev, B43_MMIO_PHY_DATA);
 }
 
 static void b43_aphy_op_write(struct b43_wldev *dev, u16 reg, u16 value)
 {
        reg = adjust_phyreg(dev, reg);
-       b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
+       b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg);
        b43_write16(dev, B43_MMIO_PHY_DATA, value);
 }
 
index 08ca524664e6acfe49f3a4fd2a14abc691af118f..1dfc682a805513f5e5d160f6198f6d17bec644fc 100644 (file)
@@ -278,7 +278,7 @@ u16 b43_phy_read(struct b43_wldev *dev, u16 reg)
        if (dev->phy.ops->phy_read)
                return dev->phy.ops->phy_read(dev, reg);
 
-       b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
+       b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg);
        return b43_read16(dev, B43_MMIO_PHY_DATA);
 }
 
@@ -294,7 +294,7 @@ void b43_phy_write(struct b43_wldev *dev, u16 reg, u16 value)
        if (dev->phy.ops->phy_write)
                return dev->phy.ops->phy_write(dev, reg, value);
 
-       b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
+       b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg);
        b43_write16(dev, B43_MMIO_PHY_DATA, value);
 }
 
index 8f5c14bc10e6fedcab2d7b88a0009470772dad8a..727ce6edb4b3831faf6d254ad789b4a9a1a7c336 100644 (file)
@@ -2555,13 +2555,13 @@ static void b43_gphy_op_exit(struct b43_wldev *dev)
 
 static u16 b43_gphy_op_read(struct b43_wldev *dev, u16 reg)
 {
-       b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
+       b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg);
        return b43_read16(dev, B43_MMIO_PHY_DATA);
 }
 
 static void b43_gphy_op_write(struct b43_wldev *dev, u16 reg, u16 value)
 {
-       b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
+       b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg);
        b43_write16(dev, B43_MMIO_PHY_DATA, value);
 }
 
@@ -2572,7 +2572,7 @@ static u16 b43_gphy_op_radio_read(struct b43_wldev *dev, u16 reg)
        /* G-PHY needs 0x80 for read access. */
        reg |= 0x80;
 
-       b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
+       b43_write16f(dev, B43_MMIO_RADIO_CONTROL, reg);
        return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
 }
 
@@ -2581,7 +2581,7 @@ static void b43_gphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
        /* Register 1 is a 32-bit register. */
        B43_WARN_ON(reg == 1);
 
-       b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
+       b43_write16f(dev, B43_MMIO_RADIO_CONTROL, reg);
        b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value);
 }
 
index 8b0b4b6852fddc4180968e0af9fb297858af1943..c4dc8b020f604ed51d585a790d931ef2b668f350 100644 (file)
@@ -1074,7 +1074,7 @@ static unsigned int b43_phy_ht_op_get_default_chan(struct b43_wldev *dev)
 static void b43_phy_ht_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask,
                                 u16 set)
 {
-       b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
+       b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg);
        b43_write16(dev, B43_MMIO_PHY_DATA,
                    (b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set);
 }
@@ -1084,14 +1084,14 @@ static u16 b43_phy_ht_op_radio_read(struct b43_wldev *dev, u16 reg)
        /* HT-PHY needs 0x200 for read access */
        reg |= 0x200;
 
-       b43_write16(dev, B43_MMIO_RADIO24_CONTROL, reg);
+       b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, reg);
        return b43_read16(dev, B43_MMIO_RADIO24_DATA);
 }
 
 static void b43_phy_ht_op_radio_write(struct b43_wldev *dev, u16 reg,
                                      u16 value)
 {
-       b43_write16(dev, B43_MMIO_RADIO24_CONTROL, reg);
+       b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, reg);
        b43_write16(dev, B43_MMIO_RADIO24_DATA, value);
 }
 
index bf29c3eb00953d0faef6ea4d4a4bb6a23e406a1b..97461ccf3e1e58ba4033b97756c0dd50491b13bf 100644 (file)
@@ -813,7 +813,7 @@ static void b43_phy_lcn_op_adjust_txpower(struct b43_wldev *dev)
 static void b43_phy_lcn_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask,
                                   u16 set)
 {
-       b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
+       b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg);
        b43_write16(dev, B43_MMIO_PHY_DATA,
                    (b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set);
 }
@@ -823,14 +823,14 @@ static u16 b43_phy_lcn_op_radio_read(struct b43_wldev *dev, u16 reg)
        /* LCN-PHY needs 0x200 for read access */
        reg |= 0x200;
 
-       b43_write16(dev, B43_MMIO_RADIO24_CONTROL, reg);
+       b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, reg);
        return b43_read16(dev, B43_MMIO_RADIO24_DATA);
 }
 
 static void b43_phy_lcn_op_radio_write(struct b43_wldev *dev, u16 reg,
                                       u16 value)
 {
-       b43_write16(dev, B43_MMIO_RADIO24_CONTROL, reg);
+       b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, reg);
        b43_write16(dev, B43_MMIO_RADIO24_DATA, value);
 }
 
index 1e9bae68b62157e3b3d2f1875906bb6fa982a615..058a9f2320503ef623748ed595ccbfdb8dbd9414 100644 (file)
@@ -1988,7 +1988,7 @@ static void lpphy_calibration(struct b43_wldev *dev)
 static void b43_lpphy_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask,
                                 u16 set)
 {
-       b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
+       b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg);
        b43_write16(dev, B43_MMIO_PHY_DATA,
                    (b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set);
 }
@@ -2004,7 +2004,7 @@ static u16 b43_lpphy_op_radio_read(struct b43_wldev *dev, u16 reg)
        } else
                reg |= 0x200;
 
-       b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
+       b43_write16f(dev, B43_MMIO_RADIO_CONTROL, reg);
        return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
 }
 
@@ -2013,7 +2013,7 @@ static void b43_lpphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
        /* Register 1 is a 32-bit register. */
        B43_WARN_ON(reg == 1);
 
-       b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
+       b43_write16f(dev, B43_MMIO_RADIO_CONTROL, reg);
        b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value);
 }
 
index 55653186b575d7b7976ff1fc247a8a22b506736c..df640325aa154cf35bad706d19cb589c4761a436 100644 (file)
@@ -6501,7 +6501,7 @@ static void b43_nphy_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask,
                                 u16 set)
 {
        check_phyreg(dev, reg);
-       b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
+       b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg);
        b43_maskset16(dev, B43_MMIO_PHY_DATA, mask, set);
        dev->phy.writes_counter = 1;
 }
@@ -6516,7 +6516,7 @@ static u16 b43_nphy_op_radio_read(struct b43_wldev *dev, u16 reg)
        else
                reg |= 0x100;
 
-       b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
+       b43_write16f(dev, B43_MMIO_RADIO_CONTROL, reg);
        return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
 }
 
@@ -6525,7 +6525,7 @@ static void b43_nphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
        /* Register 1 is a 32-bit register. */
        B43_WARN_ON(dev->phy.rev < 7 && reg == 1);
 
-       b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
+       b43_write16f(dev, B43_MMIO_RADIO_CONTROL, reg);
        b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value);
 }