From 1855ba7812dbd294fcfc083dc7d3b14d3b1f38db Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Fri, 18 Apr 2008 20:51:41 +0200 Subject: b43: Workaround invalid bluetooth settings This adds a workaround for invalid bluetooth SPROM settings on ASUS PCI cards. This will stop the microcode from poking with the BT GPIO line. This fixes data transmission on this device, as the BT GPIO line is used for something TX related on this device (probably the power amplifier or the radio). This also adds a modparam knob to help debugging this in the future, as more devices with this bug may show up. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index cf5c046c9fa8..4bc053ffc37e 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -84,6 +84,10 @@ int b43_modparam_qos = 1; module_param_named(qos, b43_modparam_qos, int, 0444); MODULE_PARM_DESC(qos, "Enable QOS support (default on)"); +static int modparam_btcoex = 1; +module_param_named(btcoex, modparam_btcoex, int, 0444); +MODULE_PARM_DESC(btcoex, "Enable Bluetooth coexistance (default on)"); + static const struct ssb_device_id b43_ssb_tbl[] = { SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5), @@ -3708,6 +3712,8 @@ static void b43_bluetooth_coext_enable(struct b43_wldev *dev) struct ssb_sprom *sprom = &dev->dev->bus->sprom; u32 hf; + if (!modparam_btcoex) + return; if (!(sprom->boardflags_lo & B43_BFL_BTCOEXIST)) return; if (dev->phy.type != B43_PHYTYPE_B && !dev->phy.gmode) @@ -3719,11 +3725,13 @@ static void b43_bluetooth_coext_enable(struct b43_wldev *dev) else hf |= B43_HF_BTCOEX; b43_hf_write(dev, hf); - //TODO } static void b43_bluetooth_coext_disable(struct b43_wldev *dev) -{ //TODO +{ + if (!modparam_btcoex) + return; + //TODO } static void b43_imcfglo_timeouts_workaround(struct b43_wldev *dev) @@ -4416,6 +4424,8 @@ static int b43_one_core_attach(struct ssb_device *dev, struct b43_wl *wl) static void b43_sprom_fixup(struct ssb_bus *bus) { + struct pci_dev *pdev; + /* boardflags workarounds */ if (bus->boardinfo.vendor == SSB_BOARDVENDOR_DELL && bus->chip_id == 0x4301 && bus->boardinfo.rev == 0x74) @@ -4423,6 +4433,14 @@ static void b43_sprom_fixup(struct ssb_bus *bus) if (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE && bus->boardinfo.type == 0x4E && bus->boardinfo.rev > 0x40) bus->sprom.boardflags_lo |= B43_BFL_PACTRL; + if (bus->bustype == SSB_BUSTYPE_PCI) { + pdev = bus->host_pci; + if (pdev->vendor == PCI_VENDOR_ID_BROADCOM && + pdev->device == 0x4318 && + pdev->subsystem_vendor == PCI_VENDOR_ID_ASUSTEK && + pdev->subsystem_device == 0x100F) + bus->sprom.boardflags_lo &= ~B43_BFL_BTCOEXIST; + } } static void b43_wireless_exit(struct ssb_device *dev, struct b43_wl *wl) -- cgit v1.2.3 From a259d6a45b915e00e8c6085e35fea7b61e3008a8 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Fri, 18 Apr 2008 21:06:37 +0200 Subject: b43: Fix HostFlags data types The HostFlags are a bitmask of 48bit. So we must use an u64 datatype to hold all bits. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 5 +++-- drivers/net/wireless/b43/phy.c | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 4bc053ffc37e..a90e902f4b3e 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -3710,7 +3710,7 @@ static void setup_struct_wldev_for_init(struct b43_wldev *dev) static void b43_bluetooth_coext_enable(struct b43_wldev *dev) { struct ssb_sprom *sprom = &dev->dev->bus->sprom; - u32 hf; + u64 hf; if (!modparam_btcoex) return; @@ -3860,7 +3860,8 @@ static int b43_wireless_core_init(struct b43_wldev *dev) struct ssb_sprom *sprom = &bus->sprom; struct b43_phy *phy = &dev->phy; int err; - u32 hf, tmp; + u64 hf; + u32 tmp; B43_WARN_ON(b43_status(dev) != B43_STAT_UNINIT); diff --git a/drivers/net/wireless/b43/phy.c b/drivers/net/wireless/b43/phy.c index 575c5436ebdf..de024dc03718 100644 --- a/drivers/net/wireless/b43/phy.c +++ b/drivers/net/wireless/b43/phy.c @@ -2043,7 +2043,7 @@ int b43_phy_init(struct b43_wldev *dev) void b43_set_rx_antenna(struct b43_wldev *dev, int antenna) { struct b43_phy *phy = &dev->phy; - u32 hf; + u64 hf; u16 tmp; int autodiv = 0; -- cgit v1.2.3 From 9fc38458355525f801cd2ab403ac89850489a05e Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sat, 19 Apr 2008 16:53:00 +0200 Subject: b43: Add more btcoexist workarounds This adds more workarounds for devices with broken BT bits. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index a90e902f4b3e..94a0cdeb39a8 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -4423,6 +4423,12 @@ static int b43_one_core_attach(struct ssb_device *dev, struct b43_wl *wl) return err; } +#define IS_PDEV(pdev, _vendor, _device, _subvendor, _subdevice) ( \ + (pdev->vendor == PCI_VENDOR_ID_##_vendor) && \ + (pdev->device == _device) && \ + (pdev->subsystem_vendor == PCI_VENDOR_ID_##_subvendor) && \ + (pdev->subsystem_device == _subdevice) ) + static void b43_sprom_fixup(struct ssb_bus *bus) { struct pci_dev *pdev; @@ -4436,10 +4442,9 @@ static void b43_sprom_fixup(struct ssb_bus *bus) bus->sprom.boardflags_lo |= B43_BFL_PACTRL; if (bus->bustype == SSB_BUSTYPE_PCI) { pdev = bus->host_pci; - if (pdev->vendor == PCI_VENDOR_ID_BROADCOM && - pdev->device == 0x4318 && - pdev->subsystem_vendor == PCI_VENDOR_ID_ASUSTEK && - pdev->subsystem_device == 0x100F) + if (IS_PDEV(pdev, BROADCOM, 0x4318, ASUSTEK, 0x100F) || + IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0015) || + IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0013)) bus->sprom.boardflags_lo &= ~B43_BFL_BTCOEXIST; } } -- cgit v1.2.3 From d1d8f44a4e3c730984283c0bf4b3458e3a88c15a Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Mon, 21 Apr 2008 21:28:24 +0300 Subject: ath5k: Fix radio identification on AR5424/2424 *Fix radio chip identification on AR5424/2424 during ath5k_hw_attach *Try to assign an RF2413 radio on AR2424 for testing Changes-licensed-under: ISC Signed-off-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/hw.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath5k/hw.c b/drivers/net/wireless/ath5k/hw.c index 87e782291a01..5fb1ae6ad3e2 100644 --- a/drivers/net/wireless/ath5k/hw.c +++ b/drivers/net/wireless/ath5k/hw.c @@ -304,14 +304,20 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) ah->ah_radio = AR5K_RF2413; ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A; } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC2) { - ah->ah_radio = AR5K_RF5413; + ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A; + } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5133) { - if (ah->ah_mac_srev <= AR5K_SREV_VER_AR5424 && - ah->ah_mac_srev >= AR5K_SREV_VER_AR2424) + /* AR5424 */ + if (srev >= AR5K_SREV_VER_AR5424) { + ah->ah_radio = AR5K_RF5413; ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5424; - else + /* AR2424 */ + } else { + ah->ah_radio = AR5K_RF2413; /* For testing */ ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A; + } + /* * Register returns 0x4 for radio revision * so ath5k_hw_radio_revision doesn't parse the value -- cgit v1.2.3 From 1033b3ea11820ea1fb1b877207bd6724e9aaedc3 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Wed, 23 Apr 2008 19:13:01 +0200 Subject: b43: Workaround DMA quirks Some mainboards/CPUs don't allow DMA masks bigger than a certain limit. Some VIA crap^h^h^h^hdevices have an upper limit of 0xFFFFFFFF. So in this case a 64-bit b43 device would always fail to acquire the mask. Implement a workaround to fallback to lower DMA mask, as we can always also support a lower mask. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/dma.c | 47 +++++++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 8 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 21c886a9a1d9..6dcbb3c87e72 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -980,6 +980,42 @@ void b43_dma_free(struct b43_wldev *dev) destroy_ring(dma, tx_ring_mcast); } +static int b43_dma_set_mask(struct b43_wldev *dev, u64 mask) +{ + u64 orig_mask = mask; + bool fallback = 0; + int err; + + /* Try to set the DMA mask. If it fails, try falling back to a + * lower mask, as we can always also support a lower one. */ + while (1) { + err = ssb_dma_set_mask(dev->dev, mask); + if (!err) + break; + if (mask == DMA_64BIT_MASK) { + mask = DMA_32BIT_MASK; + fallback = 1; + continue; + } + if (mask == DMA_32BIT_MASK) { + mask = DMA_30BIT_MASK; + fallback = 1; + continue; + } + b43err(dev->wl, "The machine/kernel does not support " + "the required %u-bit DMA mask\n", + (unsigned int)dma_mask_to_engine_type(orig_mask)); + return -EOPNOTSUPP; + } + if (fallback) { + b43info(dev->wl, "DMA mask fallback from %u-bit to %u-bit\n", + (unsigned int)dma_mask_to_engine_type(orig_mask), + (unsigned int)dma_mask_to_engine_type(mask)); + } + + return 0; +} + int b43_dma_init(struct b43_wldev *dev) { struct b43_dma *dma = &dev->dma; @@ -989,14 +1025,9 @@ int b43_dma_init(struct b43_wldev *dev) dmamask = supported_dma_mask(dev); type = dma_mask_to_engine_type(dmamask); - err = ssb_dma_set_mask(dev->dev, dmamask); - if (err) { - b43err(dev->wl, "The machine/kernel does not support " - "the required DMA mask (0x%08X%08X)\n", - (unsigned int)((dmamask & 0xFFFFFFFF00000000ULL) >> 32), - (unsigned int)(dmamask & 0x00000000FFFFFFFFULL)); - return -EOPNOTSUPP; - } + err = b43_dma_set_mask(dev, dmamask); + if (err) + return err; err = -ENOMEM; /* setup TX DMA channels. */ -- cgit v1.2.3 From 8ba82e969f71d088f718f93d64985d5fcdd9c171 Mon Sep 17 00:00:00 2001 From: Roel Kluin <12o3l@tiscali.nl> Date: Wed, 23 Apr 2008 21:56:49 +0200 Subject: prism54: prism54_get_encode() test below 0 on unsigned index previously in this function: u32 index = (dwrq->flags & IW_ENCODE_INDEX) - 1; index is unsigned, so if -1, the original test (below) didn't work. Signed-off-by: Roel Kluin <12o3l@tiscali.nl> Signed-off-by: John W. Linville --- drivers/net/wireless/prism54/isl_ioctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c index e5b3c282009c..5b375b289036 100644 --- a/drivers/net/wireless/prism54/isl_ioctl.c +++ b/drivers/net/wireless/prism54/isl_ioctl.c @@ -1186,7 +1186,7 @@ prism54_get_encode(struct net_device *ndev, struct iw_request_info *info, rvalue |= mgt_get_request(priv, DOT11_OID_DEFKEYID, 0, NULL, &r); devindex = r.u; /* Now get the key, return it */ - if ((index < 0) || (index > 3)) + if (index == -1 || index > 3) /* no index provided, use the current one */ index = devindex; rvalue |= mgt_get_request(priv, DOT11_OID_DEFKEYX, index, NULL, &r); -- cgit v1.2.3 From 4d381ffb02701c3fc976091473aead7c03523133 Mon Sep 17 00:00:00 2001 From: Roel Kluin <12o3l@tiscali.nl> Date: Wed, 23 Apr 2008 22:10:29 +0200 Subject: wireless: rndis_wlan: modparam_workaround_interval is never below 0. priv->param_workaround_interval is unsigned, modparam_workaround_interval not. the former is never < 0. Signed-off-by: Roel Kluin <12o3l@tiscali.nl> Signed-off-by: John W. Linville --- drivers/net/wireless/rndis_wlan.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 977751f372ff..d0b1fb15c709 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -2402,7 +2402,6 @@ static int bcm4320_early_init(struct usbnet *dev) priv->param_power_output = modparam_power_output; priv->param_roamtrigger = modparam_roamtrigger; priv->param_roamdelta = modparam_roamdelta; - priv->param_workaround_interval = modparam_workaround_interval; priv->param_country[0] = toupper(priv->param_country[0]); priv->param_country[1] = toupper(priv->param_country[1]); @@ -2425,8 +2424,10 @@ static int bcm4320_early_init(struct usbnet *dev) else if (priv->param_roamdelta > 2) priv->param_roamdelta = 2; - if (priv->param_workaround_interval < 0) + if (modparam_workaround_interval < 0) priv->param_workaround_interval = 500; + else + priv->param_workaround_interval = modparam_workaround_interval; rndis_set_config_parameter_str(dev, "Country", priv->param_country); rndis_set_config_parameter_str(dev, "FrameBursting", -- cgit v1.2.3 From 099714934d80100624829f1e2961b9dccaef3280 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 23 Apr 2008 16:22:13 -0700 Subject: iwlwifi: Don't unlock priv->mutex if it isn't locked Commit b716bb91 ("iwlwifi: Cancel scanning upon association") moved the test of priv->vif in iwl{3945,4964}_mac_config_interface() outside of where priv->mutex is held, but still tries to do mutex_unlock() on return. This is clearly wrong and triggers a nasty lockdep warning when this codepath is triggered. Fix this by removing the mutex_unlock(). Signed-off-by: Roland Dreier Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 1 - drivers/net/wireless/iwlwifi/iwl4965-base.c | 1 - 2 files changed, 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 1a5678fe4224..a1a0b3c581f1 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -6907,7 +6907,6 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, if (priv->vif != vif) { IWL_DEBUG_MAC80211("leave - priv->vif != vif\n"); - mutex_unlock(&priv->mutex); return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index d7e2358a213a..d0bbcaaeb94c 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -6473,7 +6473,6 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw, if (priv->vif != vif) { IWL_DEBUG_MAC80211("leave - priv->vif != vif\n"); - mutex_unlock(&priv->mutex); return 0; } -- cgit v1.2.3