From f15ec3451daf137a63d9cdc65ac5f863ce91fce5 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Sat, 31 May 2014 19:40:45 +0200 Subject: b43: disable 5 GHz on G-PHY MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes regression introduced by adding some G-PHY devices to the list of dual band devices. There is simply no support for 5 GHz on G-PHY devices in b43. It results in: WARNING: CPU: 0 PID: 79 at drivers/net/wireless/b43/phy_g.c:75 b43_gphy_channel_switch+0x125/0x130 [b43]() b43-phy1 ERROR: PHY init: Channel switch to default failed Regression was introduced by the following commit: commit 773cfc508f4d64c14547ff8751b5cbd473124364 Author: Rafał Miłecki Date: Mon May 19 23:18:55 2014 +0200 b43: add more devices to the bands database Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 32538ac5f7e4..0d6a0bb1f876 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -5221,6 +5221,7 @@ static int b43_wireless_core_attach(struct b43_wldev *dev) /* We don't support 5 GHz on some PHYs yet */ switch (dev->phy.type) { case B43_PHYTYPE_A: + case B43_PHYTYPE_G: case B43_PHYTYPE_N: case B43_PHYTYPE_LP: case B43_PHYTYPE_HT: -- cgit v1.2.3 From bca463e80825433203f0c0de4bf6518f50a9b30d Mon Sep 17 00:00:00 2001 From: Chin-Ran Lo Date: Fri, 6 Jun 2014 19:37:10 -0700 Subject: mwifiex: fix tx_info/rx_info overlap with PCIe dma_mapping On PCIe Tx data path, network interface specific tx_info parameters such as bss_num and bss_type are saved at "skb->cb + sizeof(dma_addr_t)" (returned by MWIFIEX_SKB_TXCB). Later mwifiex_map_pci_memory() called from mwifiex_pcie_send_data() will memcpy sizeof(struct mwifiex_dma_mapping) bytes to save PCIe DMA address and length information at beginning of skb->cb. This accidently overwrites bss_num and bss_type saved in skb->cb previously because bss_num/bss_type and mwifiex_dma_mapping data overlap. Similarly, on PCIe Rx data path, rx_info parameters overlaps with PCIe DMA address and length information too. Fix it by defining mwifiex_cb structure and having MWIFIEX_SKB_TXCB and MWIFIEX_SKB_RXCB return the correct address of tx_info/rx_info using the structure members. Also add a BUILD_BUG_ON to maks sure that mwifiex_cb structure doesn't exceed the size of skb->cb. Reviewed-by: Aaron Durbin Signed-off-by: Chin-Ran Lo Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/pcie.c | 4 ++-- drivers/net/wireless/mwifiex/util.h | 43 ++++++++++++++++++++++++++++--------- 2 files changed, 35 insertions(+), 12 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c index 574d4b597468..2cc9b6fca490 100644 --- a/drivers/net/wireless/mwifiex/pcie.c +++ b/drivers/net/wireless/mwifiex/pcie.c @@ -50,7 +50,7 @@ mwifiex_map_pci_memory(struct mwifiex_adapter *adapter, struct sk_buff *skb, return -1; } mapping.len = size; - memcpy(skb->cb, &mapping, sizeof(mapping)); + mwifiex_store_mapping(skb, &mapping); return 0; } @@ -60,7 +60,7 @@ static void mwifiex_unmap_pci_memory(struct mwifiex_adapter *adapter, struct pcie_service_card *card = adapter->card; struct mwifiex_dma_mapping mapping; - MWIFIEX_SKB_PACB(skb, &mapping); + mwifiex_get_mapping(skb, &mapping); pci_unmap_single(card->dev, mapping.addr, mapping.len, flags); } diff --git a/drivers/net/wireless/mwifiex/util.h b/drivers/net/wireless/mwifiex/util.h index ddae57021397..caadb3737b9e 100644 --- a/drivers/net/wireless/mwifiex/util.h +++ b/drivers/net/wireless/mwifiex/util.h @@ -20,32 +20,55 @@ #ifndef _MWIFIEX_UTIL_H_ #define _MWIFIEX_UTIL_H_ +struct mwifiex_dma_mapping { + dma_addr_t addr; + size_t len; +}; + +struct mwifiex_cb { + struct mwifiex_dma_mapping dma_mapping; + union { + struct mwifiex_rxinfo rx_info; + struct mwifiex_txinfo tx_info; + }; +}; + static inline struct mwifiex_rxinfo *MWIFIEX_SKB_RXCB(struct sk_buff *skb) { - return (struct mwifiex_rxinfo *)(skb->cb + sizeof(dma_addr_t)); + struct mwifiex_cb *cb = (struct mwifiex_cb *)skb->cb; + + BUILD_BUG_ON(sizeof(struct mwifiex_cb) > sizeof(skb->cb)); + return &cb->rx_info; } static inline struct mwifiex_txinfo *MWIFIEX_SKB_TXCB(struct sk_buff *skb) { - return (struct mwifiex_txinfo *)(skb->cb + sizeof(dma_addr_t)); + struct mwifiex_cb *cb = (struct mwifiex_cb *)skb->cb; + + return &cb->tx_info; } -struct mwifiex_dma_mapping { - dma_addr_t addr; - size_t len; -}; +static inline void mwifiex_store_mapping(struct sk_buff *skb, + struct mwifiex_dma_mapping *mapping) +{ + struct mwifiex_cb *cb = (struct mwifiex_cb *)skb->cb; + + memcpy(&cb->dma_mapping, mapping, sizeof(*mapping)); +} -static inline void MWIFIEX_SKB_PACB(struct sk_buff *skb, - struct mwifiex_dma_mapping *mapping) +static inline void mwifiex_get_mapping(struct sk_buff *skb, + struct mwifiex_dma_mapping *mapping) { - memcpy(mapping, skb->cb, sizeof(*mapping)); + struct mwifiex_cb *cb = (struct mwifiex_cb *)skb->cb; + + memcpy(mapping, &cb->dma_mapping, sizeof(*mapping)); } static inline dma_addr_t MWIFIEX_SKB_DMA_ADDR(struct sk_buff *skb) { struct mwifiex_dma_mapping mapping; - MWIFIEX_SKB_PACB(skb, &mapping); + mwifiex_get_mapping(skb, &mapping); return mapping.addr; } -- cgit v1.2.3 From 8edcb0ba0d56f5914eef11eda6db8bfe74eb9ca8 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Tue, 10 Jun 2014 12:51:06 +0200 Subject: rt2x00: disable TKIP on USB On USB we can not get atomically TKIP key. We have to disable support for TKIP acceleration on USB hardware to avoid bug as showed bellow. [ 860.827243] BUG: scheduling while atomic: hostapd/3397/0x00000002 [ 860.827280] Call Trace: [ 860.827282] [] dump_stack+0x4d/0x66 [ 860.827284] [] __schedule_bug+0x47/0x55 [ 860.827285] [] __schedule+0x733/0x7b0 [ 860.827287] [] schedule+0x29/0x70 [ 860.827289] [] schedule_timeout+0x15a/0x2b0 [ 860.827291] [] ? ftrace_raw_event_tick_stop+0xc0/0xc0 [ 860.827294] [] ? __module_text_address+0x12/0x70 [ 860.827296] [] wait_for_completion_timeout+0xb3/0x140 [ 860.827298] [] ? wake_up_state+0x20/0x20 [ 860.827301] [] usb_start_wait_urb+0x7d/0x150 [ 860.827303] [] usb_control_msg+0xc5/0x110 [ 860.827305] [] rt2x00usb_vendor_request+0xc6/0x160 [rt2x00usb] [ 860.827307] [] rt2x00usb_vendor_req_buff_lock+0x75/0x150 [rt2x00usb] [ 860.827309] [] rt2x00usb_vendor_request_buff+0xa3/0xe0 [rt2x00usb] [ 860.827311] [] rt2x00usb_register_multiread+0x33/0x40 [rt2800usb] [ 860.827314] [] rt2800_get_tkip_seq+0x39/0x50 [rt2800lib] [ 860.827321] [] ieee80211_get_key+0x218/0x2a0 [mac80211] [ 860.827322] [] ? __nlmsg_put+0x6c/0x80 [ 860.827329] [] nl80211_get_key+0x22e/0x360 [cfg80211] Cc: stable@vger.kernel.org Reported-and-tested-by: Peter Wu Reported-and-tested-by: Pontus Fuchs Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00mac.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 212ac4842c16..004dff9b962d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -487,6 +487,8 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, crypto.cipher = rt2x00crypto_key_to_cipher(key); if (crypto.cipher == CIPHER_NONE) return -EOPNOTSUPP; + if (crypto.cipher == CIPHER_TKIP && rt2x00_is_usb(rt2x00dev)) + return -EOPNOTSUPP; crypto.cmd = cmd; -- cgit v1.2.3 From 740bb82b7655770c09a19af5528a131ac741eaf1 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Tue, 10 Jun 2014 13:32:05 +0200 Subject: b43: fix typo in Kconfig (make B43_BUSES_BCMA_AND_SSB the default for real) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reported-by: Paul Bolle Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig index e3f67b8d3f80..40fd9b7b1426 100644 --- a/drivers/net/wireless/b43/Kconfig +++ b/drivers/net/wireless/b43/Kconfig @@ -36,7 +36,7 @@ config B43_SSB choice prompt "Supported bus types" depends on B43 - default B43_BCMA_AND_SSB + default B43_BUSES_BCMA_AND_SSB config B43_BUSES_BCMA_AND_SSB bool "BCMA and SSB" -- cgit v1.2.3 From de51b35d506f9f9e8ab7bb5987ed5d50a76bd906 Mon Sep 17 00:00:00 2001 From: Michael Braun Date: Thu, 12 Jun 2014 19:33:36 +0200 Subject: rt2800usb:fix efuse detection The device 057c:8501 (AVM Fritz! WLAN v2 rev. B) currently does not load. One thing observed is that the vendors driver detects EFUSE mode for this device, but rt2800usb does not. This is due to rt2800usb lacking a check for the firmware mode present in the vendors driver, that this patch adopts for rt2800usb. With this patch applied, the 'RF chipset' detection does no longer fail. Signed-off-by: Michael Braun Acked-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800usb.c | 30 +++++++++++++++++++++++++++++- drivers/net/wireless/rt2x00/rt2x00usb.h | 1 + 2 files changed, 30 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index a49c3d73ea2c..11583ca3facb 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -229,6 +229,27 @@ static enum hrtimer_restart rt2800usb_tx_sta_fifo_timeout(struct hrtimer *timer) /* * Firmware functions */ +static int rt2800usb_autorun_detect(struct rt2x00_dev *rt2x00dev) +{ + __le32 reg; + u32 fw_mode; + + /* cannot use rt2x00usb_register_read here as it uses different + * mode (MULTI_READ vs. DEVICE_MODE) and does not pass the + * magic value USB_MODE_AUTORUN (0x11) to the device, thus the + * returned value would be invalid. + */ + rt2x00usb_vendor_request(rt2x00dev, USB_DEVICE_MODE, + USB_VENDOR_REQUEST_IN, 0, USB_MODE_AUTORUN, + ®, sizeof(reg), REGISTER_TIMEOUT_FIRMWARE); + fw_mode = le32_to_cpu(reg); + + if ((fw_mode & 0x00000003) == 2) + return 1; + + return 0; +} + static char *rt2800usb_get_firmware_name(struct rt2x00_dev *rt2x00dev) { return FIRMWARE_RT2870; @@ -735,11 +756,18 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry, /* * Device probe functions. */ +static int rt2800usb_efuse_detect(struct rt2x00_dev *rt2x00dev) +{ + if (rt2800usb_autorun_detect(rt2x00dev)) + return 1; + return rt2800_efuse_detect(rt2x00dev); +} + static int rt2800usb_read_eeprom(struct rt2x00_dev *rt2x00dev) { int retval; - if (rt2800_efuse_detect(rt2x00dev)) + if (rt2800usb_efuse_detect(rt2x00dev)) retval = rt2800_read_eeprom_efuse(rt2x00dev); else retval = rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom, diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h index e7bcf62347d5..831b65f93feb 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.h +++ b/drivers/net/wireless/rt2x00/rt2x00usb.h @@ -93,6 +93,7 @@ enum rt2x00usb_mode_offset { USB_MODE_SLEEP = 7, /* RT73USB */ USB_MODE_FIRMWARE = 8, /* RT73USB */ USB_MODE_WAKEUP = 9, /* RT73USB */ + USB_MODE_AUTORUN = 17, /* RT2800USB */ }; /** -- cgit v1.2.3 From b663cd10f0ba351ae520fa3627e13061d7f8e714 Mon Sep 17 00:00:00 2001 From: Michael Braun Date: Thu, 12 Jun 2014 19:33:41 +0200 Subject: rt2800usb:fix hang during firmware load The device 057c:8501 (AVM Fritz! WLAN v2 rev. B) boots into a state that does not actually require loading a firmware file. The vendors driver finds out about this by checking a firmware state register, so this patch adds this here. Finally, with this patch applied, my wifi dongle actually becomes useful (scan + connect to wpa network works). Signed-off-by: Michael Braun Acked-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800usb.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 11583ca3facb..e11dab2216c6 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -278,8 +278,13 @@ static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev, /* * Write firmware to device. */ - rt2x00usb_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, - data + offset, length); + if (rt2800usb_autorun_detect(rt2x00dev)) { + rt2x00_info(rt2x00dev, + "Firmware loading not required - NIC in AutoRun mode\n"); + } else { + rt2x00usb_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, + data + offset, length); + } rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); -- cgit v1.2.3 From 2fc68eb122c7ea6cd5be1fe7d6650c0beb2f4f40 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Thu, 12 Jun 2014 22:28:22 +0200 Subject: b43: fix frequency reported on G-PHY with /new/ firmware MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Support for firmware rev 508+ was added years ago, but we never noticed it reports channel in a different way for G-PHY devices. Instead of offset from 2400 MHz it simply passes channel id (AKA hw_value). So far it was (most probably) affecting monitor mode users only, but the following recent commit made it noticeable for quite everybody: commit 3afc2167f60a327a2c1e1e2600ef209a3c2b75b7 Author: Emmanuel Grumbach Date: Tue Mar 4 16:50:13 2014 +0200 cfg80211/mac80211: ignore signal if the frame was heard on wrong channel Reported-by: Aaro Koskinen Signed-off-by: Rafał Miłecki Cc: stable@vger.kernel.org Tested-by: Aaro Koskinen Signed-off-by: John W. Linville --- drivers/net/wireless/b43/xmit.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index 4f38f19b8e3d..6e6ef3fc2247 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c @@ -811,9 +811,13 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) break; case B43_PHYTYPE_G: status.band = IEEE80211_BAND_2GHZ; - /* chanid is the radio channel cookie value as used - * to tune the radio. */ - status.freq = chanid + 2400; + /* Somewhere between 478.104 and 508.1084 firmware for G-PHY + * has been modified to be compatible with N-PHY and others. + */ + if (dev->fw.rev >= 508) + status.freq = ieee80211_channel_to_frequency(chanid, status.band); + else + status.freq = chanid + 2400; break; case B43_PHYTYPE_N: case B43_PHYTYPE_LP: -- cgit v1.2.3 From 616a8394b5df8c88f4dd416f4527439a4e365034 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Mon, 16 Jun 2014 18:45:15 +0200 Subject: rt2x00: fix rfkill regression on rt2500pci As reported by Niels, starting rfkill polling during device probe (commit e2bc7c5, generally sane change) broke rfkill on rt2500pci device. I considered that bug as some initalization issue, which should be fixed on rt2500pci specific code. But after several attempts (see bug report for details) we fail to find working solution. Hence I decided to revert to old behaviour on rt2500pci to fix regression. Additionally patch also unregister rfkill on device remove instead of ifconfig down, what was another issue introduced by bad commit. Bug report: https://bugzilla.kernel.org/show_bug.cgi?id=73821 Fixes: e2bc7c5f3cb8 ("rt2x00: Fix rfkill_polling register function.") Cc: stable@vger.kernel.org Bisected-by: Niels Reported-and-tested-by: Niels Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2500pci.c | 7 ++++++- drivers/net/wireless/rt2x00/rt2x00.h | 1 + drivers/net/wireless/rt2x00/rt2x00dev.c | 24 +++++++++++++++++++++--- 3 files changed, 28 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 2f1cd929c6f6..a511cccc9f01 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1681,8 +1681,13 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev) /* * Detect if this device has an hardware controlled radio. */ - if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO)) + if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO)) { __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags); + /* + * On this device RFKILL initialized during probe does not work. + */ + __set_bit(REQUIRE_DELAYED_RFKILL, &rt2x00dev->cap_flags); + } /* * Check if the BBP tuning should be enabled. diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 010b76505243..d13f25cd70d5 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -693,6 +693,7 @@ enum rt2x00_capability_flags { REQUIRE_SW_SEQNO, REQUIRE_HT_TX_DESC, REQUIRE_PS_AUTOWAKE, + REQUIRE_DELAYED_RFKILL, /* * Capabilities diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 2bde6729f5e6..4fa43a2eeb73 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -1126,9 +1126,10 @@ static void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev) return; /* - * Unregister extra components. + * Stop rfkill polling. */ - rt2x00rfkill_unregister(rt2x00dev); + if (test_bit(REQUIRE_DELAYED_RFKILL, &rt2x00dev->cap_flags)) + rt2x00rfkill_unregister(rt2x00dev); /* * Allow the HW to uninitialize. @@ -1166,6 +1167,12 @@ static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev) set_bit(DEVICE_STATE_INITIALIZED, &rt2x00dev->flags); + /* + * Start rfkill polling. + */ + if (test_bit(REQUIRE_DELAYED_RFKILL, &rt2x00dev->cap_flags)) + rt2x00rfkill_register(rt2x00dev); + return 0; } @@ -1375,7 +1382,12 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) rt2x00link_register(rt2x00dev); rt2x00leds_register(rt2x00dev); rt2x00debug_register(rt2x00dev); - rt2x00rfkill_register(rt2x00dev); + + /* + * Start rfkill polling. + */ + if (!test_bit(REQUIRE_DELAYED_RFKILL, &rt2x00dev->cap_flags)) + rt2x00rfkill_register(rt2x00dev); return 0; @@ -1390,6 +1402,12 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) { clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); + /* + * Stop rfkill polling. + */ + if (!test_bit(REQUIRE_DELAYED_RFKILL, &rt2x00dev->cap_flags)) + rt2x00rfkill_unregister(rt2x00dev); + /* * Disable radio. */ -- cgit v1.2.3