From 2574c9bec30abce1a177a4cf3744001b43331541 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Thu, 14 Jul 2011 08:48:32 -0400 Subject: [PATCH] --- yaml --- r: 266645 b: refs/heads/master c: 9fd481e03c1e9c76c814b88b9ea1cbda9afb0812 h: refs/heads/master i: 266643: 0a55de1fa8898d1f3250a99ad59d0ca33b481274 v: v3 --- [refs] | 2 +- trunk/Documentation/DocBook/80211.tmpl | 11 +- .../feature-removal-schedule.txt | 5 - trunk/MAINTAINERS | 2 +- trunk/drivers/bluetooth/btusb.c | 3 +- trunk/drivers/net/wireless/Makefile | 2 +- trunk/drivers/net/wireless/adm8211.c | 3 +- trunk/drivers/net/wireless/at76c50x-usb.c | 18 +- .../net/wireless/ath/ath5k/mac80211-ops.c | 8 +- .../drivers/net/wireless/ath/ath6kl/Makefile | 4 +- trunk/drivers/net/wireless/ath/ath6kl/bmi.c | 23 +- trunk/drivers/net/wireless/ath/ath6kl/bmi.h | 4 +- .../net/wireless/ath/ath6kl/cfg80211.c | 894 ++++--------- .../drivers/net/wireless/ath/ath6kl/common.h | 83 ++ trunk/drivers/net/wireless/ath/ath6kl/core.h | 145 +-- trunk/drivers/net/wireless/ath/ath6kl/debug.c | 784 ------------ trunk/drivers/net/wireless/ath/ath6kl/debug.h | 49 +- .../drivers/net/wireless/ath/ath6kl/hif-ops.h | 5 - trunk/drivers/net/wireless/ath/ath6kl/hif.h | 1 - trunk/drivers/net/wireless/ath/ath6kl/htc.c | 271 ++-- trunk/drivers/net/wireless/ath/ath6kl/init.c | 794 +++--------- trunk/drivers/net/wireless/ath/ath6kl/main.c | 448 +++---- trunk/drivers/net/wireless/ath/ath6kl/node.c | 234 ++++ trunk/drivers/net/wireless/ath/ath6kl/sdio.c | 79 +- .../drivers/net/wireless/ath/ath6kl/target.h | 41 +- .../net/wireless/ath/ath6kl/testmode.c | 167 --- .../net/wireless/ath/ath6kl/testmode.h | 36 - trunk/drivers/net/wireless/ath/ath6kl/txrx.c | 61 +- trunk/drivers/net/wireless/ath/ath6kl/wmi.c | 1126 ++++++----------- trunk/drivers/net/wireless/ath/ath6kl/wmi.h | 350 +---- .../wireless/ath/ath9k/ar9003_2p2_initvals.h | 2 +- trunk/drivers/net/wireless/ath/ath9k/ath9k.h | 3 +- trunk/drivers/net/wireless/ath/ath9k/debug.c | 24 +- trunk/drivers/net/wireless/ath/ath9k/debug.h | 2 - trunk/drivers/net/wireless/ath/ath9k/eeprom.h | 7 +- trunk/drivers/net/wireless/ath/ath9k/gpio.c | 7 +- .../drivers/net/wireless/ath/ath9k/hif_usb.c | 1 - .../net/wireless/ath/ath9k/htc_drv_gpio.c | 10 +- .../net/wireless/ath/ath9k/htc_drv_main.c | 12 +- trunk/drivers/net/wireless/ath/ath9k/hw.c | 11 +- trunk/drivers/net/wireless/ath/ath9k/main.c | 16 +- trunk/drivers/net/wireless/ath/ath9k/rc.c | 6 + trunk/drivers/net/wireless/ath/ath9k/recv.c | 33 +- trunk/drivers/net/wireless/ath/ath9k/xmit.c | 19 +- .../drivers/net/wireless/ath/carl9170/main.c | 6 +- trunk/drivers/net/wireless/b43/b43.h | 40 +- trunk/drivers/net/wireless/b43/main.c | 57 +- trunk/drivers/net/wireless/b43/phy_lcn.c | 2 +- .../drivers/net/wireless/b43/tables_phy_lcn.c | 25 +- trunk/drivers/net/wireless/b43legacy/main.c | 3 +- .../net/wireless/iwlegacy/iwl-4965-tx.c | 2 +- .../drivers/net/wireless/iwlegacy/iwl-core.c | 10 +- .../drivers/net/wireless/iwlegacy/iwl-core.h | 6 +- .../drivers/net/wireless/iwlegacy/iwl-hcmd.c | 2 +- trunk/drivers/net/wireless/iwlegacy/iwl-tx.c | 4 +- .../net/wireless/iwlegacy/iwl3945-base.c | 8 +- .../net/wireless/iwlegacy/iwl4965-base.c | 10 +- trunk/drivers/net/wireless/iwlwifi/Kconfig | 22 +- trunk/drivers/net/wireless/iwlwifi/Makefile | 40 +- .../net/wireless/iwlwifi/iwl-agn-lib.c | 435 ++++++- .../drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 19 +- .../net/wireless/iwlwifi/iwl-agn-rxon.c | 2 +- .../drivers/net/wireless/iwlwifi/iwl-agn-tt.c | 18 +- .../drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 39 +- .../net/wireless/iwlwifi/iwl-agn-ucode.c | 8 +- trunk/drivers/net/wireless/iwlwifi/iwl-agn.c | 15 +- trunk/drivers/net/wireless/iwlwifi/iwl-agn.h | 19 +- trunk/drivers/net/wireless/iwlwifi/iwl-core.c | 11 +- trunk/drivers/net/wireless/iwlwifi/iwl-core.h | 13 +- .../net/wireless/iwlwifi/iwl-debugfs.c | 17 +- trunk/drivers/net/wireless/iwlwifi/iwl-dev.h | 17 +- .../drivers/net/wireless/iwlwifi/iwl-eeprom.c | 5 +- trunk/drivers/net/wireless/iwlwifi/iwl-led.c | 1 + trunk/drivers/net/wireless/iwlwifi/iwl-rx.c | 95 +- trunk/drivers/net/wireless/iwlwifi/iwl-scan.c | 696 ++-------- .../drivers/net/wireless/iwlwifi/iwl-shared.h | 8 +- trunk/drivers/net/wireless/iwlwifi/iwl-sta.c | 37 +- trunk/drivers/net/wireless/iwlwifi/iwl-sta.h | 5 +- .../net/wireless/iwlwifi/iwl-trans-pcie-int.h | 14 +- .../net/wireless/iwlwifi/iwl-trans-pcie-rx.c | 26 +- .../net/wireless/iwlwifi/iwl-trans-pcie-tx.c | 54 +- .../net/wireless/iwlwifi/iwl-trans-pcie.c | 23 +- .../drivers/net/wireless/iwlwifi/iwl-trans.h | 17 +- trunk/drivers/net/wireless/libertas/cfg.c | 33 +- trunk/drivers/net/wireless/libertas/dev.h | 2 +- trunk/drivers/net/wireless/libertas/main.c | 35 - trunk/drivers/net/wireless/mac80211_hwsim.c | 3 +- trunk/drivers/net/wireless/mwifiex/11n_aggr.c | 2 + trunk/drivers/net/wireless/mwifiex/11n_aggr.h | 1 - trunk/drivers/net/wireless/mwifiex/cfg80211.c | 183 +-- trunk/drivers/net/wireless/mwifiex/cfg80211.h | 3 +- trunk/drivers/net/wireless/mwifiex/cmdevt.c | 3 - trunk/drivers/net/wireless/mwifiex/decl.h | 8 + trunk/drivers/net/wireless/mwifiex/init.c | 2 +- trunk/drivers/net/wireless/mwifiex/main.c | 266 +++- trunk/drivers/net/wireless/mwifiex/main.h | 21 +- trunk/drivers/net/wireless/mwifiex/scan.c | 29 +- .../drivers/net/wireless/mwifiex/sta_ioctl.c | 62 +- trunk/drivers/net/wireless/mwifiex/wmm.c | 32 +- trunk/drivers/net/wireless/mwl8k.c | 5 +- trunk/drivers/net/wireless/p54/main.c | 3 +- trunk/drivers/net/wireless/p54/txrx.c | 2 +- trunk/drivers/net/wireless/rt2x00/rt2400pci.c | 10 +- trunk/drivers/net/wireless/rt2x00/rt2500pci.c | 3 +- trunk/drivers/net/wireless/rt2x00/rt2800lib.c | 7 +- trunk/drivers/net/wireless/rt2x00/rt2800lib.h | 5 +- trunk/drivers/net/wireless/rt2x00/rt2x00.h | 3 +- trunk/drivers/net/wireless/rt2x00/rt2x00mac.c | 3 +- trunk/drivers/net/wireless/rt2x00/rt61pci.c | 7 +- trunk/drivers/net/wireless/rt2x00/rt73usb.c | 7 +- .../net/wireless/rtl818x/rtl8180/dev.c | 5 +- .../net/wireless/rtl818x/rtl8187/dev.c | 5 +- trunk/drivers/net/wireless/rtlwifi/core.c | 11 +- trunk/drivers/net/wireless/rtlwifi/usb.c | 41 +- trunk/drivers/net/wireless/rtlwifi/wifi.h | 8 +- trunk/drivers/net/wireless/wl1251/main.c | 3 +- trunk/drivers/net/wireless/wl12xx/Makefile | 6 +- trunk/drivers/net/wireless/wl12xx/cmd.c | 43 +- trunk/drivers/net/wireless/wl12xx/conf.h | 6 +- trunk/drivers/net/wireless/wl12xx/event.c | 2 +- trunk/drivers/net/wireless/wl12xx/init.c | 17 +- trunk/drivers/net/wireless/wl12xx/main.c | 207 +-- trunk/drivers/net/wireless/wl12xx/scan.c | 42 +- trunk/drivers/net/wireless/wl12xx/sdio_test.c | 15 +- trunk/drivers/net/wireless/wl12xx/tx.c | 38 +- trunk/drivers/net/wireless/wl12xx/tx.h | 5 +- trunk/drivers/net/wireless/wl12xx/wl12xx.h | 5 +- trunk/drivers/net/wireless/wl3501_cs.c | 2 +- trunk/drivers/net/wireless/zd1211rw/zd_mac.c | 2 +- trunk/drivers/nfc/Kconfig | 2 +- .../staging/brcm80211/brcmsmac/mac80211_if.c | 19 +- trunk/drivers/staging/winbond/wbusb.c | 2 +- trunk/include/linux/ieee80211.h | 85 -- trunk/include/linux/if_ether.h | 1 - trunk/include/linux/nl80211.h | 57 - trunk/include/linux/rfkill-gpio.h | 4 - trunk/include/net/cfg80211.h | 36 +- trunk/include/net/ieee80211_radiotap.h | 1 - trunk/include/net/mac80211.h | 240 +--- trunk/include/net/nfc/nci_core.h | 1 - trunk/net/mac80211/Kconfig | 12 - trunk/net/mac80211/agg-rx.c | 2 +- trunk/net/mac80211/agg-tx.c | 2 +- trunk/net/mac80211/cfg.c | 392 +----- trunk/net/mac80211/debugfs.c | 52 + trunk/net/mac80211/debugfs_netdev.c | 48 +- trunk/net/mac80211/debugfs_sta.c | 37 +- trunk/net/mac80211/driver-ops.h | 60 +- trunk/net/mac80211/driver-trace.h | 117 +- trunk/net/mac80211/ht.c | 2 +- trunk/net/mac80211/ibss.c | 8 +- trunk/net/mac80211/ieee80211_i.h | 21 +- trunk/net/mac80211/iface.c | 14 +- trunk/net/mac80211/key.c | 4 +- trunk/net/mac80211/main.c | 18 - trunk/net/mac80211/mesh.c | 58 + trunk/net/mac80211/mesh.h | 4 + trunk/net/mac80211/mesh_plink.c | 20 +- trunk/net/mac80211/mlme.c | 40 +- trunk/net/mac80211/pm.c | 2 +- trunk/net/mac80211/rate.c | 37 +- trunk/net/mac80211/rc80211_minstrel_ht.c | 2 - trunk/net/mac80211/rx.c | 118 +- trunk/net/mac80211/scan.c | 3 +- trunk/net/mac80211/sta_info.c | 636 ++-------- trunk/net/mac80211/sta_info.h | 136 +- trunk/net/mac80211/status.c | 54 +- trunk/net/mac80211/tx.c | 187 +-- trunk/net/mac80211/util.c | 99 +- trunk/net/mac80211/wme.c | 4 +- trunk/net/mac80211/work.c | 2 +- trunk/net/nfc/nci/core.c | 63 +- trunk/net/nfc/nci/data.c | 2 - trunk/net/nfc/nci/ntf.c | 2 +- trunk/net/rfkill/rfkill-gpio.c | 11 - trunk/net/wireless/core.h | 4 +- trunk/net/wireless/mlme.c | 5 +- trunk/net/wireless/nl80211.c | 157 +-- trunk/net/wireless/util.c | 21 +- 179 files changed, 3654 insertions(+), 8090 deletions(-) create mode 100644 trunk/drivers/net/wireless/ath/ath6kl/node.c delete mode 100644 trunk/drivers/net/wireless/ath/ath6kl/testmode.c delete mode 100644 trunk/drivers/net/wireless/ath/ath6kl/testmode.h diff --git a/[refs] b/[refs] index 778c0234425f..5463ad5089f2 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 76ed94be65c8bd80b565865c186dd9f24bb2f23b +refs/heads/master: 9fd481e03c1e9c76c814b88b9ea1cbda9afb0812 diff --git a/trunk/Documentation/DocBook/80211.tmpl b/trunk/Documentation/DocBook/80211.tmpl index 2014155c899d..445289cd0e65 100644 --- a/trunk/Documentation/DocBook/80211.tmpl +++ b/trunk/Documentation/DocBook/80211.tmpl @@ -433,18 +433,8 @@ Insert notes about VLAN interfaces with hw crypto here or in the hw crypto chapter. -
- support for powersaving clients -!Pinclude/net/mac80211.h AP support for powersaving clients -
!Finclude/net/mac80211.h ieee80211_get_buffered_bc !Finclude/net/mac80211.h ieee80211_beacon_get -!Finclude/net/mac80211.h ieee80211_sta_eosp_irqsafe -!Finclude/net/mac80211.h ieee80211_frame_release_type -!Finclude/net/mac80211.h ieee80211_sta_ps_transition -!Finclude/net/mac80211.h ieee80211_sta_ps_transition_ni -!Finclude/net/mac80211.h ieee80211_sta_set_buffered -!Finclude/net/mac80211.h ieee80211_sta_block_awake @@ -470,6 +460,7 @@ !Finclude/net/mac80211.h sta_notify_cmd !Finclude/net/mac80211.h ieee80211_find_sta !Finclude/net/mac80211.h ieee80211_find_sta_by_ifaddr +!Finclude/net/mac80211.h ieee80211_sta_block_awake diff --git a/trunk/Documentation/feature-removal-schedule.txt b/trunk/Documentation/feature-removal-schedule.txt index 1cf3dbdb1538..dfd6a9f4a583 100644 --- a/trunk/Documentation/feature-removal-schedule.txt +++ b/trunk/Documentation/feature-removal-schedule.txt @@ -555,8 +555,3 @@ Why: This driver has been superseded by g_mass_storage. Who: Alan Stern ---------------------------- -What: iwlagn alias support -When: 3.5 -Why: The iwlagn module has been renamed iwlwifi. The alias will be around - for backward compatibility for several cycles and then dropped. -Who: Don Fry \ No newline at end of file diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index a31c6140a961..1789ce22ea8c 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -3413,7 +3413,7 @@ M: Wey-Yi Guy M: Intel Linux Wireless L: linux-wireless@vger.kernel.org W: http://intellinuxwireless.org -T: git git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-2.6.git S: Supported F: drivers/net/wireless/iwlwifi/ diff --git a/trunk/drivers/bluetooth/btusb.c b/trunk/drivers/bluetooth/btusb.c index 9cbac6b445e1..2755c1a9c38e 100644 --- a/trunk/drivers/bluetooth/btusb.c +++ b/trunk/drivers/bluetooth/btusb.c @@ -708,8 +708,7 @@ static int btusb_send_frame(struct sk_buff *skb) break; case HCI_ACLDATA_PKT: - if (!data->bulk_tx_ep || (hdev->conn_hash.acl_num < 1 && - hdev->conn_hash.le_num < 1)) + if (!data->bulk_tx_ep) return -ENODEV; urb = usb_alloc_urb(0, GFP_ATOMIC); diff --git a/trunk/drivers/net/wireless/Makefile b/trunk/drivers/net/wireless/Makefile index 4cf0ad312da1..7bba6a82b875 100644 --- a/trunk/drivers/net/wireless/Makefile +++ b/trunk/drivers/net/wireless/Makefile @@ -41,7 +41,7 @@ obj-$(CONFIG_ADM8211) += adm8211.o obj-$(CONFIG_MWL8K) += mwl8k.o -obj-$(CONFIG_IWLWIFI) += iwlwifi/ +obj-$(CONFIG_IWLAGN) += iwlwifi/ obj-$(CONFIG_IWLWIFI_LEGACY) += iwlegacy/ obj-$(CONFIG_RT2X00) += rt2x00/ diff --git a/trunk/drivers/net/wireless/adm8211.c b/trunk/drivers/net/wireless/adm8211.c index 3b752d9fb3cd..43ebc44fc82c 100644 --- a/trunk/drivers/net/wireless/adm8211.c +++ b/trunk/drivers/net/wireless/adm8211.c @@ -1249,8 +1249,7 @@ static int adm8211_hw_reset(struct ieee80211_hw *dev) return 0; } -static u64 adm8211_get_tsft(struct ieee80211_hw *dev, - struct ieee80211_vif *vif) +static u64 adm8211_get_tsft(struct ieee80211_hw *dev) { struct adm8211_priv *priv = dev->priv; u32 tsftl; diff --git a/trunk/drivers/net/wireless/at76c50x-usb.c b/trunk/drivers/net/wireless/at76c50x-usb.c index 39322d4121b7..298601436ee2 100644 --- a/trunk/drivers/net/wireless/at76c50x-usb.c +++ b/trunk/drivers/net/wireless/at76c50x-usb.c @@ -500,9 +500,10 @@ static int at76_usbdfu_download(struct usb_device *udev, u8 *buf, u32 size, #define HEX2STR_BUFFERS 4 #define HEX2STR_MAX_LEN 64 +#define BIN2HEX(x) ((x) < 10 ? '0' + (x) : (x) + 'A' - 10) /* Convert binary data into hex string */ -static char *hex2str(void *buf, size_t len) +static char *hex2str(void *buf, int len) { static atomic_t a = ATOMIC_INIT(0); static char bufs[HEX2STR_BUFFERS][3 * HEX2STR_MAX_LEN + 1]; @@ -513,17 +514,18 @@ static char *hex2str(void *buf, size_t len) if (len > HEX2STR_MAX_LEN) len = HEX2STR_MAX_LEN; - if (len == 0) - goto exit; + if (len <= 0) { + ret[0] = '\0'; + return ret; + } while (len--) { - obuf = pack_hex_byte(obuf, *ibuf++); + *obuf++ = BIN2HEX(*ibuf >> 4); + *obuf++ = BIN2HEX(*ibuf & 0xf); *obuf++ = '-'; + ibuf++; } - obuf--; - -exit: - *obuf = '\0'; + *(--obuf) = '\0'; return ret; } diff --git a/trunk/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/trunk/drivers/net/wireless/ath/ath5k/mac80211-ops.c index 6ed4c0717e3e..0560234ec3f6 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/mac80211-ops.c +++ b/trunk/drivers/net/wireless/ath/ath5k/mac80211-ops.c @@ -563,7 +563,7 @@ ath5k_get_stats(struct ieee80211_hw *hw, static int -ath5k_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue, +ath5k_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params) { struct ath5k_hw *ah = hw->priv; @@ -602,7 +602,7 @@ ath5k_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue, static u64 -ath5k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +ath5k_get_tsf(struct ieee80211_hw *hw) { struct ath5k_hw *ah = hw->priv; @@ -611,7 +611,7 @@ ath5k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) static void -ath5k_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u64 tsf) +ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf) { struct ath5k_hw *ah = hw->priv; @@ -620,7 +620,7 @@ ath5k_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u64 tsf) static void -ath5k_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +ath5k_reset_tsf(struct ieee80211_hw *hw) { struct ath5k_hw *ah = hw->priv; diff --git a/trunk/drivers/net/wireless/ath/ath6kl/Makefile b/trunk/drivers/net/wireless/ath/ath6kl/Makefile index 8f7a0d1c290c..e1bb07ea8e80 100644 --- a/trunk/drivers/net/wireless/ath/ath6kl/Makefile +++ b/trunk/drivers/net/wireless/ath/ath6kl/Makefile @@ -31,7 +31,5 @@ ath6kl-y += init.o ath6kl-y += main.o ath6kl-y += txrx.o ath6kl-y += wmi.o +ath6kl-y += node.o ath6kl-y += sdio.o -ath6kl-$(CONFIG_NL80211_TESTMODE) += testmode.o - -ccflags-y += -D__CHECK_ENDIAN__ diff --git a/trunk/drivers/net/wireless/ath/ath6kl/bmi.c b/trunk/drivers/net/wireless/ath/ath6kl/bmi.c index c5d11cc536e0..84676697d7eb 100644 --- a/trunk/drivers/net/wireless/ath/ath6kl/bmi.c +++ b/trunk/drivers/net/wireless/ath/ath6kl/bmi.c @@ -62,14 +62,14 @@ static int ath6kl_get_bmi_cmd_credits(struct ath6kl *ar) return 0; } -static int ath6kl_bmi_get_rx_lkahd(struct ath6kl *ar) +static int ath6kl_bmi_get_rx_lkahd(struct ath6kl *ar, bool need_timeout) { unsigned long timeout; u32 rx_word = 0; int ret = 0; timeout = jiffies + msecs_to_jiffies(BMI_COMMUNICATION_TIMEOUT); - while (time_before(jiffies, timeout) && !rx_word) { + while ((!need_timeout || time_before(jiffies, timeout)) && !rx_word) { ret = hif_read_write_sync(ar, RX_LOOKAHEAD_VALID_ADDRESS, (u8 *)&rx_word, sizeof(rx_word), HIF_RD_SYNC_BYTE_INC); @@ -109,7 +109,8 @@ static int ath6kl_bmi_send_buf(struct ath6kl *ar, u8 *buf, u32 len) return ret; } -static int ath6kl_bmi_recv_buf(struct ath6kl *ar, u8 *buf, u32 len) +static int ath6kl_bmi_recv_buf(struct ath6kl *ar, + u8 *buf, u32 len, bool want_timeout) { int ret; u32 addr; @@ -161,7 +162,7 @@ static int ath6kl_bmi_recv_buf(struct ath6kl *ar, u8 *buf, u32 len) * a function of Host processor speed. */ if (len >= 4) { /* NB: Currently, always true */ - ret = ath6kl_bmi_get_rx_lkahd(ar); + ret = ath6kl_bmi_get_rx_lkahd(ar, want_timeout); if (ret) return ret; } @@ -219,7 +220,7 @@ int ath6kl_bmi_get_target_info(struct ath6kl *ar, } ret = ath6kl_bmi_recv_buf(ar, (u8 *)&targ_info->version, - sizeof(targ_info->version)); + sizeof(targ_info->version), true); if (ret) { ath6kl_err("Unable to recv target info: %d\n", ret); return ret; @@ -229,7 +230,8 @@ int ath6kl_bmi_get_target_info(struct ath6kl *ar, /* Determine how many bytes are in the Target's targ_info */ ret = ath6kl_bmi_recv_buf(ar, (u8 *)&targ_info->byte_count, - sizeof(targ_info->byte_count)); + sizeof(targ_info->byte_count), + true); if (ret) { ath6kl_err("unable to read target info byte count: %d\n", ret); @@ -250,7 +252,8 @@ int ath6kl_bmi_get_target_info(struct ath6kl *ar, ((u8 *)targ_info) + sizeof(targ_info->byte_count), sizeof(*targ_info) - - sizeof(targ_info->byte_count)); + sizeof(targ_info->byte_count), + true); if (ret) { ath6kl_err("Unable to read target info (%d bytes): %d\n", @@ -308,7 +311,7 @@ int ath6kl_bmi_read(struct ath6kl *ar, u32 addr, u8 *buf, u32 len) ret); return ret; } - ret = ath6kl_bmi_recv_buf(ar, ar->bmi.cmd_buf, rx_len); + ret = ath6kl_bmi_recv_buf(ar, ar->bmi.cmd_buf, rx_len, true); if (ret) { ath6kl_err("Unable to read from the device: %d\n", ret); @@ -421,7 +424,7 @@ int ath6kl_bmi_execute(struct ath6kl *ar, u32 addr, u32 *param) return ret; } - ret = ath6kl_bmi_recv_buf(ar, ar->bmi.cmd_buf, sizeof(*param)); + ret = ath6kl_bmi_recv_buf(ar, ar->bmi.cmd_buf, sizeof(*param), false); if (ret) { ath6kl_err("Unable to read from the device: %d\n", ret); return ret; @@ -501,7 +504,7 @@ int ath6kl_bmi_reg_read(struct ath6kl *ar, u32 addr, u32 *param) return ret; } - ret = ath6kl_bmi_recv_buf(ar, ar->bmi.cmd_buf, sizeof(*param)); + ret = ath6kl_bmi_recv_buf(ar, ar->bmi.cmd_buf, sizeof(*param), true); if (ret) { ath6kl_err("Unable to read from the device: %d\n", ret); return ret; diff --git a/trunk/drivers/net/wireless/ath/ath6kl/bmi.h b/trunk/drivers/net/wireless/ath/ath6kl/bmi.h index 96851d5df24b..83546d76d979 100644 --- a/trunk/drivers/net/wireless/ath/ath6kl/bmi.h +++ b/trunk/drivers/net/wireless/ath/ath6kl/bmi.h @@ -139,8 +139,8 @@ */ #define TARGET_VERSION_SENTINAL 0xffffffff -#define TARGET_TYPE_AR6003 3 -#define TARGET_TYPE_AR6004 5 +#define TARGET_TYPE_AR6003 3 + #define BMI_ROMPATCH_INSTALL 9 /* * Semantics: Install a ROM Patch. diff --git a/trunk/drivers/net/wireless/ath/ath6kl/cfg80211.c b/trunk/drivers/net/wireless/ath/ath6kl/cfg80211.c index 8d9fbd4a62b7..14559ffb1453 100644 --- a/trunk/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/trunk/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -17,12 +17,6 @@ #include "core.h" #include "cfg80211.h" #include "debug.h" -#include "hif-ops.h" -#include "testmode.h" - -static unsigned int ath6kl_p2p; - -module_param(ath6kl_p2p, uint, 0644); #define RATETAB_ENT(_rate, _rateid, _flags) { \ .bitrate = (_rate), \ @@ -158,7 +152,8 @@ static int ath6kl_set_auth_type(struct ath6kl *ar, break; case NL80211_AUTHTYPE_AUTOMATIC: - ar->dot11_auth_mode = OPEN_AUTH | SHARED_AUTH; + ar->dot11_auth_mode = OPEN_AUTH; + ar->auto_auth_stage = AUTH_OPEN_IN_PROGRESS; break; default: @@ -172,8 +167,7 @@ static int ath6kl_set_auth_type(struct ath6kl *ar, static int ath6kl_set_cipher(struct ath6kl *ar, u32 cipher, bool ucast) { u8 *ar_cipher = ucast ? &ar->prwise_crypto : &ar->grp_crypto; - u8 *ar_cipher_len = ucast ? &ar->prwise_crypto_len : - &ar->grp_crypto_len; + u8 *ar_cipher_len = ucast ? &ar->prwise_crypto_len : &ar->grp_crpto_len; ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: cipher 0x%x, ucast %u\n", __func__, cipher, ucast); @@ -360,7 +354,6 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, } if (!ar->usr_bss_filter) { - clear_bit(CLEAR_BSSFILTER_ON_BEACON, &ar->flag); if (ath6kl_wmi_bssfilter_cmd(ar->wmi, ALL_BSS_FILTER, 0) != 0) { ath6kl_err("couldn't set bss filtering\n"); up(&ar->sem); @@ -377,14 +370,14 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, __func__, ar->auth_mode, ar->dot11_auth_mode, ar->prwise_crypto, ar->prwise_crypto_len, ar->grp_crypto, - ar->grp_crypto_len, ar->ch_hint); + ar->grp_crpto_len, ar->ch_hint); ar->reconnect_flag = 0; status = ath6kl_wmi_connect_cmd(ar->wmi, ar->nw_type, ar->dot11_auth_mode, ar->auth_mode, ar->prwise_crypto, ar->prwise_crypto_len, - ar->grp_crypto, ar->grp_crypto_len, + ar->grp_crypto, ar->grp_crpto_len, ar->ssid_len, ar->ssid, ar->req_bssid, ar->ch_hint, ar->connect_ctrl_flags); @@ -414,53 +407,6 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, return 0; } -static int ath6kl_add_bss_if_needed(struct ath6kl *ar, const u8 *bssid, - struct ieee80211_channel *chan, - const u8 *beacon_ie, size_t beacon_ie_len) -{ - struct cfg80211_bss *bss; - u8 *ie; - - bss = cfg80211_get_bss(ar->wdev->wiphy, chan, bssid, - ar->ssid, ar->ssid_len, WLAN_CAPABILITY_ESS, - WLAN_CAPABILITY_ESS); - if (bss == NULL) { - /* - * Since cfg80211 may not yet know about the BSS, - * generate a partial entry until the first BSS info - * event becomes available. - * - * Prepend SSID element since it is not included in the Beacon - * IEs from the target. - */ - ie = kmalloc(2 + ar->ssid_len + beacon_ie_len, GFP_KERNEL); - if (ie == NULL) - return -ENOMEM; - ie[0] = WLAN_EID_SSID; - ie[1] = ar->ssid_len; - memcpy(ie + 2, ar->ssid, ar->ssid_len); - memcpy(ie + 2 + ar->ssid_len, beacon_ie, beacon_ie_len); - bss = cfg80211_inform_bss(ar->wdev->wiphy, chan, - bssid, 0, WLAN_CAPABILITY_ESS, 100, - ie, 2 + ar->ssid_len + beacon_ie_len, - 0, GFP_KERNEL); - if (bss) - ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "added dummy bss for " - "%pM prior to indicating connect/roamed " - "event\n", bssid); - kfree(ie); - } else - ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "cfg80211 already has a bss " - "entry\n"); - - if (bss == NULL) - return -ENOMEM; - - cfg80211_put_bss(bss); - - return 0; -} - void ath6kl_cfg80211_connect_event(struct ath6kl *ar, u16 channel, u8 *bssid, u16 listen_intvl, u16 beacon_intvl, @@ -468,7 +414,19 @@ void ath6kl_cfg80211_connect_event(struct ath6kl *ar, u16 channel, u8 beacon_ie_len, u8 assoc_req_len, u8 assoc_resp_len, u8 *assoc_info) { - struct ieee80211_channel *chan; + u16 size = 0; + u16 capability = 0; + struct cfg80211_bss *bss = NULL; + struct ieee80211_mgmt *mgmt = NULL; + struct ieee80211_channel *ibss_ch = NULL; + s32 signal = 50 * 100; + u8 ie_buf_len = 0; + unsigned char ie_buf[256]; + unsigned char *ptr_ie_buf = ie_buf; + unsigned char *ieeemgmtbuf = NULL; + u8 source_mac[ETH_ALEN]; + u16 capa_mask; + u16 capa_val; /* capinfo + listen interval */ u8 assoc_req_ie_offset = sizeof(u16) + sizeof(u16); @@ -483,12 +441,7 @@ void ath6kl_cfg80211_connect_event(struct ath6kl *ar, u16 channel, assoc_req_len -= assoc_req_ie_offset; assoc_resp_len -= assoc_resp_ie_offset; - /* - * Store Beacon interval here; DTIM period will be available only once - * a Beacon frame from the AP is seen. - */ - ar->assoc_bss_beacon_int = beacon_intvl; - clear_bit(DTIM_PERIOD_AVAIL, &ar->flag); + ar->auto_auth_stage = AUTH_IDLE; if (nw_type & ADHOC_NETWORK) { if (ar->wdev->iftype != NL80211_IFTYPE_ADHOC) { @@ -499,26 +452,110 @@ void ath6kl_cfg80211_connect_event(struct ath6kl *ar, u16 channel, } if (nw_type & INFRA_NETWORK) { - if (ar->wdev->iftype != NL80211_IFTYPE_STATION && - ar->wdev->iftype != NL80211_IFTYPE_P2P_CLIENT) { + if (ar->wdev->iftype != NL80211_IFTYPE_STATION) { ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: ath6k not in station mode\n", __func__); return; } } - chan = ieee80211_get_channel(ar->wdev->wiphy, (int) channel); + if (nw_type & ADHOC_NETWORK) { + capa_mask = WLAN_CAPABILITY_IBSS; + capa_val = WLAN_CAPABILITY_IBSS; + } else { + capa_mask = WLAN_CAPABILITY_ESS; + capa_val = WLAN_CAPABILITY_ESS; + } + /* Before informing the join/connect event, make sure that + * bss entry is present in scan list, if it not present + * construct and insert into scan list, otherwise that + * event will be dropped on the way by cfg80211, due to + * this keys will not be plumbed in case of WEP and + * application will not be aware of join/connect status. */ + bss = cfg80211_get_bss(ar->wdev->wiphy, NULL, bssid, + ar->wdev->ssid, ar->wdev->ssid_len, + capa_mask, capa_val); + + /* + * Earlier we were updating the cfg about bss by making a beacon frame + * only if the entry for bss is not there. This can have some issue if + * ROAM event is generated and a heavy traffic is ongoing. The ROAM + * event is handled through a work queue and by the time it really gets + * handled, BSS would have been aged out. So it is better to update the + * cfg about BSS irrespective of its entry being present right now or + * not. + */ if (nw_type & ADHOC_NETWORK) { - cfg80211_ibss_joined(ar->net_dev, bssid, GFP_KERNEL); + /* construct 802.11 mgmt beacon */ + if (ptr_ie_buf) { + *ptr_ie_buf++ = WLAN_EID_SSID; + *ptr_ie_buf++ = ar->ssid_len; + memcpy(ptr_ie_buf, ar->ssid, ar->ssid_len); + ptr_ie_buf += ar->ssid_len; + + *ptr_ie_buf++ = WLAN_EID_IBSS_PARAMS; + *ptr_ie_buf++ = 2; /* length */ + *ptr_ie_buf++ = 0; /* ATIM window */ + *ptr_ie_buf++ = 0; /* ATIM window */ + + /* TODO: update ibss params and include supported rates, + * DS param set, extened support rates, wmm. */ + + ie_buf_len = ptr_ie_buf - ie_buf; + } + + capability |= WLAN_CAPABILITY_IBSS; + + if (ar->prwise_crypto == WEP_CRYPT) + capability |= WLAN_CAPABILITY_PRIVACY; + + memcpy(source_mac, ar->net_dev->dev_addr, ETH_ALEN); + ptr_ie_buf = ie_buf; + } else { + capability = *(u16 *) (&assoc_info[beacon_ie_len]); + memcpy(source_mac, bssid, ETH_ALEN); + ptr_ie_buf = assoc_req_ie; + ie_buf_len = assoc_req_len; + } + + size = offsetof(struct ieee80211_mgmt, u) + + sizeof(mgmt->u.beacon) + + ie_buf_len; + + ieeemgmtbuf = kzalloc(size, GFP_ATOMIC); + if (!ieeemgmtbuf) { + ath6kl_err("ieee mgmt buf alloc error\n"); + cfg80211_put_bss(bss); return; } - if (ath6kl_add_bss_if_needed(ar, bssid, chan, assoc_info, - beacon_ie_len) < 0) { - ath6kl_err("could not add cfg80211 bss entry for " - "connect/roamed notification\n"); + mgmt = (struct ieee80211_mgmt *)ieeemgmtbuf; + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_BEACON); + memset(mgmt->da, 0xff, ETH_ALEN); /* broadcast addr */ + memcpy(mgmt->sa, source_mac, ETH_ALEN); + memcpy(mgmt->bssid, bssid, ETH_ALEN); + mgmt->u.beacon.beacon_int = cpu_to_le16(beacon_intvl); + mgmt->u.beacon.capab_info = cpu_to_le16(capability); + memcpy(mgmt->u.beacon.variable, ptr_ie_buf, ie_buf_len); + + ibss_ch = ieee80211_get_channel(ar->wdev->wiphy, (int)channel); + + ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, + "%s: inform bss with bssid %pM channel %d beacon_intvl %d capability 0x%x\n", + __func__, mgmt->bssid, ibss_ch->hw_value, + beacon_intvl, capability); + + bss = cfg80211_inform_bss_frame(ar->wdev->wiphy, + ibss_ch, mgmt, + size, signal, GFP_KERNEL); + kfree(ieeemgmtbuf); + cfg80211_put_bss(bss); + + if (nw_type & ADHOC_NETWORK) { + cfg80211_ibss_joined(ar->net_dev, bssid, GFP_KERNEL); return; } @@ -531,7 +568,7 @@ void ath6kl_cfg80211_connect_event(struct ath6kl *ar, u16 channel, WLAN_STATUS_SUCCESS, GFP_KERNEL); } else if (ar->sme_state == SME_CONNECTED) { /* inform roam event to cfg80211 */ - cfg80211_roamed(ar->net_dev, chan, bssid, + cfg80211_roamed(ar->net_dev, ibss_ch, bssid, assoc_req_ie, assoc_req_len, assoc_resp_ie, assoc_resp_len, GFP_KERNEL); } @@ -568,8 +605,6 @@ static int ath6kl_cfg80211_disconnect(struct wiphy *wiphy, up(&ar->sem); - ar->sme_state = SME_DISCONNECTED; - return 0; } @@ -577,6 +612,9 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl *ar, u8 reason, u8 *bssid, u8 assoc_resp_len, u8 *assoc_info, u16 proto_reason) { + struct ath6kl_key *key = NULL; + u16 status; + if (ar->scan_req) { cfg80211_scan_done(ar->scan_req, true); ar->scan_req = NULL; @@ -594,64 +632,164 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl *ar, u8 reason, } if (ar->nw_type & INFRA_NETWORK) { - if (ar->wdev->iftype != NL80211_IFTYPE_STATION && - ar->wdev->iftype != NL80211_IFTYPE_P2P_CLIENT) { + if (ar->wdev->iftype != NL80211_IFTYPE_STATION) { ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: ath6k not in station mode\n", __func__); return; } } - /* - * Send a disconnect command to target when a disconnect event is - * received with reason code other than 3 (DISCONNECT_CMD - disconnect - * request from host) to make the firmware stop trying to connect even - * after giving disconnect event. There will be one more disconnect - * event for this disconnect command with reason code DISCONNECT_CMD - * which will be notified to cfg80211. - */ + if (!test_bit(CONNECT_PEND, &ar->flag)) { + if (reason != DISCONNECT_CMD) + ath6kl_wmi_disconnect_cmd(ar->wmi); - if (reason != DISCONNECT_CMD) { + return; + } + + if (reason == NO_NETWORK_AVAIL) { + /* connect cmd failed */ ath6kl_wmi_disconnect_cmd(ar->wmi); return; } - clear_bit(CONNECT_PEND, &ar->flag); + if (reason != DISCONNECT_CMD) + return; - if (ar->sme_state == SME_CONNECTING) { - cfg80211_connect_result(ar->net_dev, - bssid, NULL, 0, - NULL, 0, - WLAN_STATUS_UNSPECIFIED_FAILURE, - GFP_KERNEL); - } else if (ar->sme_state == SME_CONNECTED) { - cfg80211_disconnected(ar->net_dev, reason, - NULL, 0, GFP_KERNEL); + if (!ar->auto_auth_stage) { + clear_bit(CONNECT_PEND, &ar->flag); + + if (ar->sme_state == SME_CONNECTING) { + cfg80211_connect_result(ar->net_dev, + bssid, NULL, 0, + NULL, 0, + WLAN_STATUS_UNSPECIFIED_FAILURE, + GFP_KERNEL); + } else { + cfg80211_disconnected(ar->net_dev, reason, + NULL, 0, GFP_KERNEL); + } + + ar->sme_state = SME_DISCONNECTED; + return; } - ar->sme_state = SME_DISCONNECTED; + if (ar->dot11_auth_mode != OPEN_AUTH) + return; + + /* + * If the current auth algorithm is open, try shared and + * make autoAuthStage idle. We do not make it leap for now + * being. + */ + key = &ar->keys[ar->def_txkey_index]; + if (down_interruptible(&ar->sem)) { + ath6kl_err("busy, couldn't get access\n"); + return; + } + + ar->dot11_auth_mode = SHARED_AUTH; + ar->auto_auth_stage = AUTH_IDLE; + + ath6kl_wmi_addkey_cmd(ar->wmi, + ar->def_txkey_index, + ar->prwise_crypto, + GROUP_USAGE | TX_USAGE, + key->key_len, NULL, + key->key, + KEY_OP_INIT_VAL, NULL, + NO_SYNC_WMIFLAG); + + status = ath6kl_wmi_connect_cmd(ar->wmi, + ar->nw_type, + ar->dot11_auth_mode, + ar->auth_mode, + ar->prwise_crypto, + ar->prwise_crypto_len, + ar->grp_crypto, + ar->grp_crpto_len, + ar->ssid_len, + ar->ssid, + ar->req_bssid, + ar->ch_hint, + ar->connect_ctrl_flags); + up(&ar->sem); +} + +static inline bool is_ch_11a(u16 ch) +{ + return (!((ch >= 2412) && (ch <= 2484))); +} + +/* struct ath6kl_node_table::nt_nodelock is locked when calling this */ +void ath6kl_cfg80211_scan_node(struct wiphy *wiphy, struct bss *ni) +{ + u16 size; + unsigned char *ieeemgmtbuf = NULL; + struct ieee80211_mgmt *mgmt; + struct ieee80211_channel *channel; + struct ieee80211_supported_band *band; + struct ath6kl_common_ie *cie; + s32 signal; + int freq; + + cie = &ni->ni_cie; + + if (is_ch_11a(cie->ie_chan)) + band = wiphy->bands[IEEE80211_BAND_5GHZ]; /* 11a */ + else if ((cie->ie_erp) || (cie->ie_xrates)) + band = wiphy->bands[IEEE80211_BAND_2GHZ]; /* 11g */ + else + band = wiphy->bands[IEEE80211_BAND_2GHZ]; /* 11b */ + + size = ni->ni_framelen + offsetof(struct ieee80211_mgmt, u); + ieeemgmtbuf = kmalloc(size, GFP_ATOMIC); + if (!ieeemgmtbuf) { + ath6kl_err("ieee mgmt buf alloc error\n"); + return; + } + + /* + * TODO: Update target to include 802.11 mac header while sending + * bss info. Target removes 802.11 mac header while sending the bss + * info to host, cfg80211 needs it, for time being just filling the + * da, sa and bssid fields alone. + */ + mgmt = (struct ieee80211_mgmt *)ieeemgmtbuf; + memset(mgmt->da, 0xff, ETH_ALEN); /*broadcast addr */ + memcpy(mgmt->sa, ni->ni_macaddr, ETH_ALEN); + memcpy(mgmt->bssid, ni->ni_macaddr, ETH_ALEN); + memcpy(ieeemgmtbuf + offsetof(struct ieee80211_mgmt, u), + ni->ni_buf, ni->ni_framelen); + + freq = cie->ie_chan; + channel = ieee80211_get_channel(wiphy, freq); + signal = ni->ni_snr * 100; + + ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, + "%s: bssid %pM ch %d freq %d size %d\n", __func__, + mgmt->bssid, channel->hw_value, freq, size); + cfg80211_inform_bss_frame(wiphy, channel, mgmt, + size, signal, GFP_ATOMIC); + + kfree(ieeemgmtbuf); } static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_scan_request *request) { struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev); - s8 n_channels = 0; - u16 *channels = NULL; int ret = 0; if (!ath6kl_cfg80211_ready(ar)) return -EIO; if (!ar->usr_bss_filter) { - clear_bit(CLEAR_BSSFILTER_ON_BEACON, &ar->flag); - ret = ath6kl_wmi_bssfilter_cmd( - ar->wmi, - (test_bit(CONNECTED, &ar->flag) ? - ALL_BUT_BSS_FILTER : ALL_BSS_FILTER), 0); - if (ret) { + if (ath6kl_wmi_bssfilter_cmd(ar->wmi, + (test_bit(CONNECTED, &ar->flag) ? + ALL_BUT_BSS_FILTER : + ALL_BSS_FILTER), 0) != 0) { ath6kl_err("couldn't set bss filtering\n"); - return ret; + return -EIO; } } @@ -668,46 +806,13 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, request->ssids[i].ssid); } - if (request->ie) { - ret = ath6kl_wmi_set_appie_cmd(ar->wmi, WMI_FRAME_PROBE_REQ, - request->ie, request->ie_len); - if (ret) { - ath6kl_err("failed to set Probe Request appie for " - "scan"); - return ret; - } - } - - /* - * Scan only the requested channels if the request specifies a set of - * channels. If the list is longer than the target supports, do not - * configure the list and instead, scan all available channels. - */ - if (request->n_channels > 0 && - request->n_channels <= WMI_MAX_CHANNELS) { - u8 i; - - n_channels = request->n_channels; - - channels = kzalloc(n_channels * sizeof(u16), GFP_KERNEL); - if (channels == NULL) { - ath6kl_warn("failed to set scan channels, " - "scan all channels"); - n_channels = 0; - } - - for (i = 0; i < n_channels; i++) - channels[i] = request->channels[i]->center_freq; - } - - ret = ath6kl_wmi_startscan_cmd(ar->wmi, WMI_LONG_SCAN, 0, - false, 0, 0, n_channels, channels); - if (ret) + if (ath6kl_wmi_startscan_cmd(ar->wmi, WMI_LONG_SCAN, 0, + false, 0, 0, 0, NULL) != 0) { ath6kl_err("wmi_startscan_cmd failed\n"); - else - ar->scan_req = request; + ret = -EIO; + } - kfree(channels); + ar->scan_req = request; return ret; } @@ -726,6 +831,9 @@ void ath6kl_cfg80211_scan_complete_event(struct ath6kl *ar, int status) goto out; } + /* Translate data to cfg80211 mgmt format */ + wlan_iterate_nodes(&ar->scan_table, ar->wdev->wiphy); + cfg80211_scan_done(ar->scan_req, false); if (ar->scan_req->n_ssids && ar->scan_req->ssids[0].ssid_len) { @@ -810,40 +918,6 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, key_usage, key->seq_len); ar->def_txkey_index = key_index; - - if (ar->nw_type == AP_NETWORK && !pairwise && - (key_type == TKIP_CRYPT || key_type == AES_CRYPT) && params) { - ar->ap_mode_bkey.valid = true; - ar->ap_mode_bkey.key_index = key_index; - ar->ap_mode_bkey.key_type = key_type; - ar->ap_mode_bkey.key_len = key->key_len; - memcpy(ar->ap_mode_bkey.key, key->key, key->key_len); - if (!test_bit(CONNECTED, &ar->flag)) { - ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delay initial group " - "key configuration until AP mode has been " - "started\n"); - /* - * The key will be set in ath6kl_connect_ap_mode() once - * the connected event is received from the target. - */ - return 0; - } - } - - if (ar->next_mode == AP_NETWORK && key_type == WEP_CRYPT && - !test_bit(CONNECTED, &ar->flag)) { - /* - * Store the key locally so that it can be re-configured after - * the AP mode has properly started - * (ath6kl_install_statioc_wep_keys). - */ - ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delay WEP key configuration " - "until AP mode has been started\n"); - ar->wep_key_list[key_index].key_len = key->key_len; - memcpy(ar->wep_key_list[key_index].key, key->key, key->key_len); - return 0; - } - status = ath6kl_wmi_addkey_cmd(ar->wmi, ar->def_txkey_index, key_type, key_usage, key->key_len, key->seq, key->key, KEY_OP_INIT_VAL, @@ -928,7 +1002,6 @@ static int ath6kl_cfg80211_set_default_key(struct wiphy *wiphy, struct ath6kl_key *key = NULL; int status = 0; u8 key_usage; - enum crypto_type key_type = NONE_CRYPT; ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index); @@ -953,16 +1026,9 @@ static int ath6kl_cfg80211_set_default_key(struct wiphy *wiphy, key_usage = GROUP_USAGE; if (ar->prwise_crypto == WEP_CRYPT) key_usage |= TX_USAGE; - if (unicast) - key_type = ar->prwise_crypto; - if (multicast) - key_type = ar->grp_crypto; - - if (ar->next_mode == AP_NETWORK && !test_bit(CONNECTED, &ar->flag)) - return 0; /* Delay until AP mode has been started */ status = ath6kl_wmi_addkey_cmd(ar->wmi, ar->def_txkey_index, - key_type, key_usage, + ar->prwise_crypto, key_usage, key->key_len, key->seq, key->key, KEY_OP_INIT_VAL, NULL, SYNC_BOTH_WMIFLAG); @@ -1117,15 +1183,6 @@ static int ath6kl_cfg80211_change_iface(struct wiphy *wiphy, case NL80211_IFTYPE_ADHOC: ar->next_mode = ADHOC_NETWORK; break; - case NL80211_IFTYPE_AP: - ar->next_mode = AP_NETWORK; - break; - case NL80211_IFTYPE_P2P_CLIENT: - ar->next_mode = INFRA_NETWORK; - break; - case NL80211_IFTYPE_P2P_GO: - ar->next_mode = AP_NETWORK; - break; default: ath6kl_err("invalid interface type %u\n", type); return -EOPNOTSUPP; @@ -1189,13 +1246,13 @@ static int ath6kl_cfg80211_join_ibss(struct wiphy *wiphy, __func__, ar->auth_mode, ar->dot11_auth_mode, ar->prwise_crypto, ar->prwise_crypto_len, ar->grp_crypto, - ar->grp_crypto_len, ar->ch_hint); + ar->grp_crpto_len, ar->ch_hint); status = ath6kl_wmi_connect_cmd(ar->wmi, ar->nw_type, ar->dot11_auth_mode, ar->auth_mode, ar->prwise_crypto, ar->prwise_crypto_len, - ar->grp_crypto, ar->grp_crypto_len, + ar->grp_crypto, ar->grp_crpto_len, ar->ssid_len, ar->ssid, ar->req_bssid, ar->ch_hint, ar->connect_ctrl_flags); @@ -1365,23 +1422,12 @@ static int ath6kl_get_station(struct wiphy *wiphy, struct net_device *dev, sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; } else { - ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, - "invalid rate from stats: %d\n", rate); - ath6kl_debug_war(ar, ATH6KL_WAR_INVALID_RATE); + ath6kl_warn("invalid rate: %d\n", rate); return 0; } sinfo->filled |= STATION_INFO_TX_BITRATE; - if (test_bit(CONNECTED, &ar->flag) && - test_bit(DTIM_PERIOD_AVAIL, &ar->flag) && - ar->nw_type == INFRA_NETWORK) { - sinfo->filled |= STATION_INFO_BSS_PARAM; - sinfo->bss_param.flags = 0; - sinfo->bss_param.dtim_period = ar->assoc_bss_dtim_period; - sinfo->bss_param.beacon_interval = ar->assoc_bss_beacon_int; - } - return 0; } @@ -1409,402 +1455,6 @@ static int ath6kl_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev) return 0; } -#ifdef CONFIG_PM -static int ar6k_cfg80211_suspend(struct wiphy *wiphy, - struct cfg80211_wowlan *wow) -{ - struct ath6kl *ar = wiphy_priv(wiphy); - - return ath6kl_hif_suspend(ar); -} -#endif - -static int ath6kl_set_channel(struct wiphy *wiphy, struct net_device *dev, - struct ieee80211_channel *chan, - enum nl80211_channel_type channel_type) -{ - struct ath6kl *ar = ath6kl_priv(dev); - - if (!ath6kl_cfg80211_ready(ar)) - return -EIO; - - ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: center_freq=%u hw_value=%u\n", - __func__, chan->center_freq, chan->hw_value); - ar->next_chan = chan->center_freq; - - return 0; -} - -static bool ath6kl_is_p2p_ie(const u8 *pos) -{ - return pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && - pos[2] == 0x50 && pos[3] == 0x6f && - pos[4] == 0x9a && pos[5] == 0x09; -} - -static int ath6kl_set_ap_probe_resp_ies(struct ath6kl *ar, const u8 *ies, - size_t ies_len) -{ - const u8 *pos; - u8 *buf = NULL; - size_t len = 0; - int ret; - - /* - * Filter out P2P IE(s) since they will be included depending on - * the Probe Request frame in ath6kl_send_go_probe_resp(). - */ - - if (ies && ies_len) { - buf = kmalloc(ies_len, GFP_KERNEL); - if (buf == NULL) - return -ENOMEM; - pos = ies; - while (pos + 1 < ies + ies_len) { - if (pos + 2 + pos[1] > ies + ies_len) - break; - if (!ath6kl_is_p2p_ie(pos)) { - memcpy(buf + len, pos, 2 + pos[1]); - len += 2 + pos[1]; - } - pos += 2 + pos[1]; - } - } - - ret = ath6kl_wmi_set_appie_cmd(ar->wmi, WMI_FRAME_PROBE_RESP, - buf, len); - kfree(buf); - return ret; -} - -static int ath6kl_ap_beacon(struct wiphy *wiphy, struct net_device *dev, - struct beacon_parameters *info, bool add) -{ - struct ath6kl *ar = ath6kl_priv(dev); - struct ieee80211_mgmt *mgmt; - u8 *ies; - int ies_len; - struct wmi_connect_cmd p; - int res; - int i; - - ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: add=%d\n", __func__, add); - - if (!ath6kl_cfg80211_ready(ar)) - return -EIO; - - if (ar->next_mode != AP_NETWORK) - return -EOPNOTSUPP; - - if (info->beacon_ies) { - res = ath6kl_wmi_set_appie_cmd(ar->wmi, WMI_FRAME_BEACON, - info->beacon_ies, - info->beacon_ies_len); - if (res) - return res; - } - if (info->proberesp_ies) { - res = ath6kl_set_ap_probe_resp_ies(ar, info->proberesp_ies, - info->proberesp_ies_len); - if (res) - return res; - } - if (info->assocresp_ies) { - res = ath6kl_wmi_set_appie_cmd(ar->wmi, WMI_FRAME_ASSOC_RESP, - info->assocresp_ies, - info->assocresp_ies_len); - if (res) - return res; - } - - if (!add) - return 0; - - ar->ap_mode_bkey.valid = false; - - /* TODO: - * info->interval - * info->dtim_period - */ - - if (info->head == NULL) - return -EINVAL; - mgmt = (struct ieee80211_mgmt *) info->head; - ies = mgmt->u.beacon.variable; - if (ies > info->head + info->head_len) - return -EINVAL; - ies_len = info->head + info->head_len - ies; - - if (info->ssid == NULL) - return -EINVAL; - memcpy(ar->ssid, info->ssid, info->ssid_len); - ar->ssid_len = info->ssid_len; - if (info->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE) - return -EOPNOTSUPP; /* TODO */ - - ar->dot11_auth_mode = OPEN_AUTH; - - memset(&p, 0, sizeof(p)); - - for (i = 0; i < info->crypto.n_akm_suites; i++) { - switch (info->crypto.akm_suites[i]) { - case WLAN_AKM_SUITE_8021X: - if (info->crypto.wpa_versions & NL80211_WPA_VERSION_1) - p.auth_mode |= WPA_AUTH; - if (info->crypto.wpa_versions & NL80211_WPA_VERSION_2) - p.auth_mode |= WPA2_AUTH; - break; - case WLAN_AKM_SUITE_PSK: - if (info->crypto.wpa_versions & NL80211_WPA_VERSION_1) - p.auth_mode |= WPA_PSK_AUTH; - if (info->crypto.wpa_versions & NL80211_WPA_VERSION_2) - p.auth_mode |= WPA2_PSK_AUTH; - break; - } - } - if (p.auth_mode == 0) - p.auth_mode = NONE_AUTH; - ar->auth_mode = p.auth_mode; - - for (i = 0; i < info->crypto.n_ciphers_pairwise; i++) { - switch (info->crypto.ciphers_pairwise[i]) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - p.prwise_crypto_type |= WEP_CRYPT; - break; - case WLAN_CIPHER_SUITE_TKIP: - p.prwise_crypto_type |= TKIP_CRYPT; - break; - case WLAN_CIPHER_SUITE_CCMP: - p.prwise_crypto_type |= AES_CRYPT; - break; - } - } - if (p.prwise_crypto_type == 0) { - p.prwise_crypto_type = NONE_CRYPT; - ath6kl_set_cipher(ar, 0, true); - } else if (info->crypto.n_ciphers_pairwise == 1) - ath6kl_set_cipher(ar, info->crypto.ciphers_pairwise[0], true); - - switch (info->crypto.cipher_group) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - p.grp_crypto_type = WEP_CRYPT; - break; - case WLAN_CIPHER_SUITE_TKIP: - p.grp_crypto_type = TKIP_CRYPT; - break; - case WLAN_CIPHER_SUITE_CCMP: - p.grp_crypto_type = AES_CRYPT; - break; - default: - p.grp_crypto_type = NONE_CRYPT; - break; - } - ath6kl_set_cipher(ar, info->crypto.cipher_group, false); - - p.nw_type = AP_NETWORK; - ar->nw_type = ar->next_mode; - - p.ssid_len = ar->ssid_len; - memcpy(p.ssid, ar->ssid, ar->ssid_len); - p.dot11_auth_mode = ar->dot11_auth_mode; - p.ch = cpu_to_le16(ar->next_chan); - - res = ath6kl_wmi_ap_profile_commit(ar->wmi, &p); - if (res < 0) - return res; - - return 0; -} - -static int ath6kl_add_beacon(struct wiphy *wiphy, struct net_device *dev, - struct beacon_parameters *info) -{ - return ath6kl_ap_beacon(wiphy, dev, info, true); -} - -static int ath6kl_set_beacon(struct wiphy *wiphy, struct net_device *dev, - struct beacon_parameters *info) -{ - return ath6kl_ap_beacon(wiphy, dev, info, false); -} - -static int ath6kl_del_beacon(struct wiphy *wiphy, struct net_device *dev) -{ - struct ath6kl *ar = ath6kl_priv(dev); - - if (ar->nw_type != AP_NETWORK) - return -EOPNOTSUPP; - if (!test_bit(CONNECTED, &ar->flag)) - return -ENOTCONN; - - ath6kl_wmi_disconnect_cmd(ar->wmi); - clear_bit(CONNECTED, &ar->flag); - - return 0; -} - -static int ath6kl_change_station(struct wiphy *wiphy, struct net_device *dev, - u8 *mac, struct station_parameters *params) -{ - struct ath6kl *ar = ath6kl_priv(dev); - - if (ar->nw_type != AP_NETWORK) - return -EOPNOTSUPP; - - /* Use this only for authorizing/unauthorizing a station */ - if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED))) - return -EOPNOTSUPP; - - if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) - return ath6kl_wmi_ap_set_mlme(ar->wmi, WMI_AP_MLME_AUTHORIZE, - mac, 0); - return ath6kl_wmi_ap_set_mlme(ar->wmi, WMI_AP_MLME_UNAUTHORIZE, mac, - 0); -} - -static int ath6kl_remain_on_channel(struct wiphy *wiphy, - struct net_device *dev, - struct ieee80211_channel *chan, - enum nl80211_channel_type channel_type, - unsigned int duration, - u64 *cookie) -{ - struct ath6kl *ar = ath6kl_priv(dev); - - /* TODO: if already pending or ongoing remain-on-channel, - * return -EBUSY */ - *cookie = 1; /* only a single pending request is supported */ - - return ath6kl_wmi_remain_on_chnl_cmd(ar->wmi, chan->center_freq, - duration); -} - -static int ath6kl_cancel_remain_on_channel(struct wiphy *wiphy, - struct net_device *dev, - u64 cookie) -{ - struct ath6kl *ar = ath6kl_priv(dev); - - if (cookie != 1) - return -ENOENT; - - return ath6kl_wmi_cancel_remain_on_chnl_cmd(ar->wmi); -} - -static int ath6kl_send_go_probe_resp(struct ath6kl *ar, const u8 *buf, - size_t len, unsigned int freq) -{ - const u8 *pos; - u8 *p2p; - int p2p_len; - int ret; - const struct ieee80211_mgmt *mgmt; - - mgmt = (const struct ieee80211_mgmt *) buf; - - /* Include P2P IE(s) from the frame generated in user space. */ - - p2p = kmalloc(len, GFP_KERNEL); - if (p2p == NULL) - return -ENOMEM; - p2p_len = 0; - - pos = mgmt->u.probe_resp.variable; - while (pos + 1 < buf + len) { - if (pos + 2 + pos[1] > buf + len) - break; - if (ath6kl_is_p2p_ie(pos)) { - memcpy(p2p + p2p_len, pos, 2 + pos[1]); - p2p_len += 2 + pos[1]; - } - pos += 2 + pos[1]; - } - - ret = ath6kl_wmi_send_probe_response_cmd(ar->wmi, freq, mgmt->da, - p2p, p2p_len); - kfree(p2p); - return ret; -} - -static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, - struct ieee80211_channel *chan, bool offchan, - enum nl80211_channel_type channel_type, - bool channel_type_valid, unsigned int wait, - const u8 *buf, size_t len, u64 *cookie) -{ - struct ath6kl *ar = ath6kl_priv(dev); - u32 id; - const struct ieee80211_mgmt *mgmt; - - mgmt = (const struct ieee80211_mgmt *) buf; - if (buf + len >= mgmt->u.probe_resp.variable && - ar->nw_type == AP_NETWORK && test_bit(CONNECTED, &ar->flag) && - ieee80211_is_probe_resp(mgmt->frame_control)) { - /* - * Send Probe Response frame in AP mode using a separate WMI - * command to allow the target to fill in the generic IEs. - */ - *cookie = 0; /* TX status not supported */ - return ath6kl_send_go_probe_resp(ar, buf, len, - chan->center_freq); - } - - id = ar->send_action_id++; - if (id == 0) { - /* - * 0 is a reserved value in the WMI command and shall not be - * used for the command. - */ - id = ar->send_action_id++; - } - - *cookie = id; - return ath6kl_wmi_send_action_cmd(ar->wmi, id, chan->center_freq, wait, - buf, len); -} - -static void ath6kl_mgmt_frame_register(struct wiphy *wiphy, - struct net_device *dev, - u16 frame_type, bool reg) -{ - struct ath6kl *ar = ath6kl_priv(dev); - - ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: frame_type=0x%x reg=%d\n", - __func__, frame_type, reg); - if (frame_type == IEEE80211_STYPE_PROBE_REQ) { - /* - * Note: This notification callback is not allowed to sleep, so - * we cannot send WMI_PROBE_REQ_REPORT_CMD here. Instead, we - * hardcode target to report Probe Request frames all the time. - */ - ar->probe_req_report = reg; - } -} - -static const struct ieee80211_txrx_stypes -ath6kl_mgmt_stypes[NUM_NL80211_IFTYPES] = { - [NL80211_IFTYPE_STATION] = { - .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_RESP >> 4), - .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_REQ >> 4) - }, - [NL80211_IFTYPE_P2P_CLIENT] = { - .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_RESP >> 4), - .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_REQ >> 4) - }, - [NL80211_IFTYPE_P2P_GO] = { - .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_RESP >> 4), - .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_REQ >> 4) - }, -}; - static struct cfg80211_ops ath6kl_cfg80211_ops = { .change_virtual_intf = ath6kl_cfg80211_change_iface, .scan = ath6kl_cfg80211_scan, @@ -1824,26 +1474,12 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = { .set_pmksa = ath6kl_set_pmksa, .del_pmksa = ath6kl_del_pmksa, .flush_pmksa = ath6kl_flush_pmksa, - CFG80211_TESTMODE_CMD(ath6kl_tm_cmd) -#ifdef CONFIG_PM - .suspend = ar6k_cfg80211_suspend, -#endif - .set_channel = ath6kl_set_channel, - .add_beacon = ath6kl_add_beacon, - .set_beacon = ath6kl_set_beacon, - .del_beacon = ath6kl_del_beacon, - .change_station = ath6kl_change_station, - .remain_on_channel = ath6kl_remain_on_channel, - .cancel_remain_on_channel = ath6kl_cancel_remain_on_channel, - .mgmt_tx = ath6kl_mgmt_tx, - .mgmt_frame_register = ath6kl_mgmt_frame_register, }; struct wireless_dev *ath6kl_cfg80211_init(struct device *dev) { int ret = 0; struct wireless_dev *wdev; - struct ath6kl *ar; wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); if (!wdev) { @@ -1859,25 +1495,13 @@ struct wireless_dev *ath6kl_cfg80211_init(struct device *dev) return NULL; } - ar = wiphy_priv(wdev->wiphy); - ar->p2p = !!ath6kl_p2p; - - wdev->wiphy->mgmt_stypes = ath6kl_mgmt_stypes; - - wdev->wiphy->max_remain_on_channel_duration = 5000; - /* set device pointer for wiphy */ set_wiphy_dev(wdev->wiphy, dev); wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP); - if (ar->p2p) { - wdev->wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_GO) | - BIT(NL80211_IFTYPE_P2P_CLIENT); - } + BIT(NL80211_IFTYPE_ADHOC); /* max num of ssids that can be probed during scanning */ wdev->wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX; - wdev->wiphy->max_scan_ie_len = 1000; /* FIX: what is correct limit? */ wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz; wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &ath6kl_band_5ghz; wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; diff --git a/trunk/drivers/net/wireless/ath/ath6kl/common.h b/trunk/drivers/net/wireless/ath/ath6kl/common.h index b92f0e5d2336..6b0d45642fe3 100644 --- a/trunk/drivers/net/wireless/ath/ath6kl/common.h +++ b/trunk/drivers/net/wireless/ath/ath6kl/common.h @@ -75,11 +75,94 @@ enum crypto_type { AES_CRYPT = 0x08, }; +#define ATH6KL_NODE_HASHSIZE 32 +/* simple hash is enough for variation of macaddr */ +#define ATH6KL_NODE_HASH(addr) \ + (((const u8 *)(addr))[ETH_ALEN - 1] % \ + ATH6KL_NODE_HASHSIZE) + +/* + * Table of ath6kl_node instances. Each ieee80211com + * has at least one for holding the scan candidates. + * When operating as an access point or in ibss mode there + * is a second table for associated stations or neighbors. + */ +struct ath6kl_node_table { + spinlock_t nt_nodelock; /* on node table */ + struct bss *nt_node_first; /* information of all nodes */ + struct bss *nt_node_last; /* information of all nodes */ + struct bss *nt_hash[ATH6KL_NODE_HASHSIZE]; + const char *nt_name; /* for debugging */ + u32 nt_node_age; /* node aging time */ +}; + +#define WLAN_NODE_INACT_TIMEOUT_MSEC 120000 +#define WLAN_NODE_INACT_CNT 4 + +struct ath6kl_common_ie { + u16 ie_chan; + u8 *ie_tstamp; + u8 *ie_ssid; + u8 *ie_rates; + u8 *ie_xrates; + u8 *ie_country; + u8 *ie_wpa; + u8 *ie_rsn; + u8 *ie_wmm; + u8 *ie_ath; + u16 ie_capInfo; + u16 ie_beaconInt; + u8 *ie_tim; + u8 *ie_chswitch; + u8 ie_erp; + u8 *ie_wsc; + u8 *ie_htcap; + u8 *ie_htop; +}; + +struct bss { + u8 ni_macaddr[ETH_ALEN]; + u8 ni_snr; + s16 ni_rssi; + struct bss *ni_list_next; + struct bss *ni_list_prev; + struct bss *ni_hash_next; + struct bss *ni_hash_prev; + struct ath6kl_common_ie ni_cie; + u8 *ni_buf; + u16 ni_framelen; + struct ath6kl_node_table *ni_table; + u32 ni_refcnt; + + u32 ni_tstamp; + u32 ni_actcnt; +}; + struct htc_endpoint_credit_dist; struct ath6kl; enum htc_credit_dist_reason; struct htc_credit_state_info; +struct bss *wlan_node_alloc(int wh_size); +void wlan_node_free(struct bss *ni); +void wlan_setup_node(struct ath6kl_node_table *nt, struct bss *ni, + const u8 *mac_addr); +struct bss *wlan_find_node(struct ath6kl_node_table *nt, + const u8 *mac_addr); +void wlan_node_reclaim(struct ath6kl_node_table *nt, struct bss *ni); +void wlan_free_allnodes(struct ath6kl_node_table *nt); +void wlan_iterate_nodes(struct ath6kl_node_table *nt, void *arg); + +void wlan_node_table_init(struct ath6kl_node_table *nt); +void wlan_node_table_cleanup(struct ath6kl_node_table *nt); + +void wlan_refresh_inactive_nodes(struct ath6kl *ar); + +struct bss *wlan_find_ssid_node(struct ath6kl_node_table *nt, u8 *ssid, + u32 ssid_len, bool is_wpa2, bool match_ssid); + +void wlan_node_return(struct ath6kl_node_table *nt, struct bss *ni); + int ath6k_setup_credit_dist(void *htc_handle, struct htc_credit_state_info *cred_info); void ath6k_credit_distribute(struct htc_credit_state_info *cred_inf, diff --git a/trunk/drivers/net/wireless/ath/ath6kl/core.h b/trunk/drivers/net/wireless/ath/ath6kl/core.h index 6d8a4845baaf..74170229523f 100644 --- a/trunk/drivers/net/wireless/ath/ath6kl/core.h +++ b/trunk/drivers/net/wireless/ath/ath6kl/core.h @@ -21,12 +21,10 @@ #include #include #include -#include #include #include "htc.h" #include "wmi.h" #include "bmi.h" -#include "target.h" #define MAX_ATH6KL 1 #define ATH6KL_MAX_RX_BUFFERS 16 @@ -44,9 +42,6 @@ #define ATH6KL_MAX_ENDPOINTS 4 #define MAX_NODE_NUM 15 -/* Extra bytes for htc header alignment */ -#define ATH6KL_HTC_ALIGN_BYTES 3 - /* MAX_HI_COOKIE_NUM are reserved for high priority traffic */ #define MAX_DEF_COOKIE_NUM 180 #define MAX_HI_COOKIE_NUM 18 /* 10% of MAX_COOKIE_NUM */ @@ -58,35 +53,6 @@ #define A_DEFAULT_LISTEN_INTERVAL 100 #define A_MAX_WOW_LISTEN_INTERVAL 1000 -/* includes also the null byte */ -#define ATH6KL_FIRMWARE_MAGIC "QCA-ATH6KL" - -enum ath6kl_fw_ie_type { - ATH6KL_FW_IE_FW_VERSION = 0, - ATH6KL_FW_IE_TIMESTAMP = 1, - ATH6KL_FW_IE_OTP_IMAGE = 2, - ATH6KL_FW_IE_FW_IMAGE = 3, - ATH6KL_FW_IE_PATCH_IMAGE = 4, - ATH6KL_FW_IE_RESERVED_RAM_SIZE = 5, - ATH6KL_FW_IE_CAPABILITIES = 6, - ATH6KL_FW_IE_PATCH_ADDR = 7, -}; - -enum ath6kl_fw_capability { - ATH6KL_FW_CAPABILITY_HOST_P2P = 0, - - /* this needs to be last */ - ATH6KL_FW_CAPABILITY_MAX, -}; - -#define ATH6KL_CAPABILITY_LEN (ALIGN(ATH6KL_FW_CAPABILITY_MAX, 32) / 32) - -struct ath6kl_fw_ie { - __le32 id; - __le32 len; - u8 data[0]; -}; - /* AR6003 1.0 definitions */ #define AR6003_REV1_VERSION 0x300002ba @@ -95,9 +61,7 @@ struct ath6kl_fw_ie { #define AR6003_REV2_PATCH_DOWNLOAD_ADDRESS 0x57e910 #define AR6003_REV2_OTP_FILE "ath6k/AR6003/hw2.0/otp.bin.z77" #define AR6003_REV2_FIRMWARE_FILE "ath6k/AR6003/hw2.0/athwlan.bin.z77" -#define AR6003_REV2_TCMD_FIRMWARE_FILE "ath6k/AR6003/hw2.0/athtcmd_ram.bin" #define AR6003_REV2_PATCH_FILE "ath6k/AR6003/hw2.0/data.patch.bin" -#define AR6003_REV2_FIRMWARE_2_FILE "ath6k/AR6003/hw2.0/fw-2.bin" #define AR6003_REV2_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.bin" #define AR6003_REV2_DEFAULT_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.SD31.bin" @@ -105,21 +69,11 @@ struct ath6kl_fw_ie { #define AR6003_REV3_VERSION 0x30000582 #define AR6003_REV3_OTP_FILE "ath6k/AR6003/hw2.1.1/otp.bin" #define AR6003_REV3_FIRMWARE_FILE "ath6k/AR6003/hw2.1.1/athwlan.bin" -#define AR6003_REV3_TCMD_FIRMWARE_FILE "ath6k/AR6003/hw2.1.1/athtcmd_ram.bin" #define AR6003_REV3_PATCH_FILE "ath6k/AR6003/hw2.1.1/data.patch.bin" -#define AR6003_REV3_FIRMWARE_2_FILE "ath6k/AR6003/hw2.1.1/fw-2.bin" #define AR6003_REV3_BOARD_DATA_FILE "ath6k/AR6003/hw2.1.1/bdata.bin" #define AR6003_REV3_DEFAULT_BOARD_DATA_FILE \ "ath6k/AR6003/hw2.1.1/bdata.SD31.bin" -/* AR6004 1.0 definitions */ -#define AR6004_REV1_VERSION 0x30000623 -#define AR6004_REV1_FIRMWARE_FILE "ath6k/AR6004/hw6.1/fw.ram.bin" -#define AR6004_REV1_FIRMWARE_2_FILE "ath6k/AR6004/hw6.1/fw-2.bin" -#define AR6004_REV1_BOARD_DATA_FILE "ath6k/AR6004/hw6.1/bdata.bin" -#define AR6004_REV1_DEFAULT_BOARD_DATA_FILE "ath6k/AR6004/hw6.1/bdata.DB132.bin" -#define AR6004_REV1_EPPING_FIRMWARE_FILE "ath6k/AR6004/hw6.1/endpointping.bin" - /* Per STA data, used in AP mode */ #define STA_PS_AWAKE BIT(0) #define STA_PS_SLEEP BIT(1) @@ -371,13 +325,26 @@ struct ath6kl_mbox_info { #define ATH6KL_KEY_RECV 0x02 #define ATH6KL_KEY_DEFAULT 0x80 /* default xmit key */ -/* Initial group key for AP mode */ +/* + * WPA/RSN get/set key request. Specify the key/cipher + * type and whether the key is to be used for sending and/or + * receiving. The key index should be set only when working + * with global keys (use IEEE80211_KEYIX_NONE for ``no index''). + * Otherwise a unicast/pairwise key is specified by the bssid + * (on a station) or mac address (on an ap). They key length + * must include any MIC key data; otherwise it should be no + * more than ATH6KL_KEYBUF_SIZE. + */ struct ath6kl_req_key { - bool valid; - u8 key_index; - int key_type; - u8 key[WLAN_MAX_KEY_LEN]; - u8 key_len; + u8 ik_type; /* key/cipher type */ + u8 ik_pad; + u16 ik_keyix; /* key index */ + u8 ik_keylen; /* key length in bytes */ + u8 ik_flags; + u8 ik_macaddr[ETH_ALEN]; + u64 ik_keyrsc; /* key receive sequence counter */ + u64 ik_keytsc; /* key transmit sequence counter */ + u8 ik_keydata[ATH6KL_KEYBUF_SIZE + ATH6KL_MICBUF_SIZE]; }; /* Flag info */ @@ -394,9 +361,6 @@ struct ath6kl_req_key { #define NETDEV_REGISTERED 10 #define SKIP_SCAN 11 #define WLAN_ENABLED 12 -#define TESTMODE 13 -#define CLEAR_BSSFILTER_ON_BEACON 14 -#define DTIM_PERIOD_AVAIL 15 struct ath6kl { struct device *dev; @@ -419,7 +383,7 @@ struct ath6kl { u8 prwise_crypto; u8 prwise_crypto_len; u8 grp_crypto; - u8 grp_crypto_len; + u8 grp_crpto_len; u8 def_txkey_index; struct ath6kl_wep_key wep_key_list[WMI_MAX_KEY_INDEX + 1]; u8 bssid[ETH_ALEN]; @@ -428,7 +392,6 @@ struct ath6kl { u16 bss_ch; u16 listen_intvl_b; u16 listen_intvl_t; - u8 lrssi_roam_threshold; struct ath6kl_version version; u32 target_type; u8 tx_pwr; @@ -469,18 +432,7 @@ struct ath6kl { enum wlan_low_pwr_state wlan_pwr_state; struct wmi_scan_params_cmd sc_params; #define AR_MCAST_FILTER_MAC_ADDR_SIZE 4 - struct { - void *rx_report; - size_t rx_report_len; - } tm; - - struct { - u32 dataset_patch_addr; - u32 app_load_addr; - u32 app_start_override_addr; - u32 board_ext_data_addr; - u32 reserved_ram_size; - } hw; + u8 auto_auth_stage; u16 conf_flags; wait_queue_head_t event_wq; @@ -502,35 +454,9 @@ struct ath6kl { u8 *fw_patch; size_t fw_patch_len; - unsigned long fw_capabilities[ATH6KL_CAPABILITY_LEN]; - struct workqueue_struct *ath6kl_wq; - struct dentry *debugfs_phy; - - u32 send_action_id; - bool probe_req_report; - u16 next_chan; - - bool p2p; - u16 assoc_bss_beacon_int; - u8 assoc_bss_dtim_period; - -#ifdef CONFIG_ATH6KL_DEBUG - struct { - struct circ_buf fwlog_buf; - spinlock_t fwlog_lock; - void *fwlog_tmp; - u32 fwlog_mask; - unsigned int dbgfs_diag_reg; - u32 diag_reg_addr_wr; - u32 diag_reg_val_wr; - - struct { - unsigned int invalid_rate; - } war_stats; - } debug; -#endif /* CONFIG_ATH6KL_DEBUG */ + struct ath6kl_node_table scan_table; }; static inline void *ath6kl_priv(struct net_device *dev) @@ -548,19 +474,6 @@ static inline void ath6kl_deposit_credit_to_ep(struct htc_credit_state_info cred_info->cur_free_credits -= credits; } -static inline u32 ath6kl_get_hi_item_addr(struct ath6kl *ar, - u32 item_offset) -{ - u32 addr = 0; - - if (ar->target_type == TARGET_TYPE_AR6003) - addr = ATH6KL_AR6003_HI_START_ADDR + item_offset; - else if (ar->target_type == TARGET_TYPE_AR6004) - addr = ATH6KL_AR6004_HI_START_ADDR + item_offset; - - return addr; -} - void ath6kl_destroy(struct net_device *dev, unsigned int unregister); int ath6kl_configure_target(struct ath6kl *ar); void ath6kl_detect_error(unsigned long ptr); @@ -574,11 +487,9 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target, struct htc_packet *packet); void ath6kl_stop_txrx(struct ath6kl *ar); void ath6kl_cleanup_amsdu_rxbufs(struct ath6kl *ar); -int ath6kl_diag_write32(struct ath6kl *ar, u32 address, __le32 value); -int ath6kl_diag_write(struct ath6kl *ar, u32 address, void *data, u32 length); -int ath6kl_diag_read32(struct ath6kl *ar, u32 address, u32 *value); -int ath6kl_diag_read(struct ath6kl *ar, u32 address, void *data, u32 length); -int ath6kl_read_fwlogs(struct ath6kl *ar); +int ath6kl_access_datadiag(struct ath6kl *ar, u32 address, + u8 *data, u32 length, bool read); +int ath6kl_read_reg_diag(struct ath6kl *ar, u32 *address, u32 *data); void ath6kl_init_profile_info(struct ath6kl *ar); void ath6kl_tx_data_cleanup(struct ath6kl *ar); void ath6kl_stop_endpoint(struct net_device *dev, bool keep_profile, @@ -609,10 +520,6 @@ void ath6kl_connect_event(struct ath6kl *ar, u16 channel, u16 beacon_int, enum network_type net_type, u8 beacon_ie_len, u8 assoc_req_len, u8 assoc_resp_len, u8 *assoc_info); -void ath6kl_connect_ap_mode_bss(struct ath6kl *ar, u16 channel); -void ath6kl_connect_ap_mode_sta(struct ath6kl *ar, u16 aid, u8 *mac_addr, - u8 keymgmt, u8 ucipher, u8 auth, - u8 assoc_req_len, u8 *assoc_info); void ath6kl_disconnect_event(struct ath6kl *ar, u8 reason, u8 *bssid, u8 assoc_resp_len, u8 *assoc_info, u16 prot_reason_status); @@ -627,11 +534,11 @@ void ath6kl_pspoll_event(struct ath6kl *ar, u8 aid); void ath6kl_dtimexpiry_event(struct ath6kl *ar); void ath6kl_disconnect(struct ath6kl *ar); -void ath6kl_deep_sleep_enable(struct ath6kl *ar); void aggr_recv_delba_req_evt(struct ath6kl *ar, u8 tid); void aggr_recv_addba_req_evt(struct ath6kl *ar, u8 tid, u16 seq_no, u8 win_sz); void ath6kl_wakeup_event(void *dev); void ath6kl_target_failure(struct ath6kl *ar); +void ath6kl_cfg80211_scan_node(struct wiphy *wiphy, struct bss *ni); #endif /* CORE_H */ diff --git a/trunk/drivers/net/wireless/ath/ath6kl/debug.c b/trunk/drivers/net/wireless/ath/ath6kl/debug.c index ba3f23d71150..316136c8b903 100644 --- a/trunk/drivers/net/wireless/ath/ath6kl/debug.c +++ b/trunk/drivers/net/wireless/ath/ath6kl/debug.c @@ -15,26 +15,7 @@ */ #include "core.h" - -#include -#include -#include - #include "debug.h" -#include "target.h" - -struct ath6kl_fwlog_slot { - __le32 timestamp; - __le32 length; - - /* max ATH6KL_FWLOG_PAYLOAD_SIZE bytes */ - u8 payload[0]; -}; - -#define ATH6KL_FWLOG_SIZE 32768 -#define ATH6KL_FWLOG_SLOT_SIZE (sizeof(struct ath6kl_fwlog_slot) + \ - ATH6KL_FWLOG_PAYLOAD_SIZE) -#define ATH6KL_FWLOG_VALID_MASK 0x1ffff int ath6kl_printk(const char *level, const char *fmt, ...) { @@ -55,27 +36,6 @@ int ath6kl_printk(const char *level, const char *fmt, ...) } #ifdef CONFIG_ATH6KL_DEBUG - -#define REG_OUTPUT_LEN_PER_LINE 25 -#define REGTYPE_STR_LEN 100 - -struct ath6kl_diag_reg_info { - u32 reg_start; - u32 reg_end; - const char *reg_info; -}; - -static const struct ath6kl_diag_reg_info diag_reg[] = { - { 0x20000, 0x200fc, "General DMA and Rx registers" }, - { 0x28000, 0x28900, "MAC PCU register & keycache" }, - { 0x20800, 0x20a40, "QCU" }, - { 0x21000, 0x212f0, "DCU" }, - { 0x4000, 0x42e4, "RTC" }, - { 0x540000, 0x540000 + (256 * 1024), "RAM" }, - { 0x29800, 0x2B210, "Base Band" }, - { 0x1C000, 0x1C748, "Analog" }, -}; - void ath6kl_dump_registers(struct ath6kl_device *dev, struct ath6kl_irq_proc_registers *irq_proc_reg, struct ath6kl_irq_enable_reg *irq_enable_reg) @@ -187,748 +147,4 @@ void dump_cred_dist_stats(struct htc_target *target) target->cred_dist_cntxt->cur_free_credits); } -static int ath6kl_debugfs_open(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - -void ath6kl_debug_war(struct ath6kl *ar, enum ath6kl_war war) -{ - switch (war) { - case ATH6KL_WAR_INVALID_RATE: - ar->debug.war_stats.invalid_rate++; - break; - } -} - -static ssize_t read_file_war_stats(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath6kl *ar = file->private_data; - char *buf; - unsigned int len = 0, buf_len = 1500; - ssize_t ret_cnt; - - buf = kzalloc(buf_len, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - len += scnprintf(buf + len, buf_len - len, "\n"); - len += scnprintf(buf + len, buf_len - len, "%25s\n", - "Workaround stats"); - len += scnprintf(buf + len, buf_len - len, "%25s\n\n", - "================="); - len += scnprintf(buf + len, buf_len - len, "%20s %10u\n", - "Invalid rates", ar->debug.war_stats.invalid_rate); - - if (WARN_ON(len > buf_len)) - len = buf_len; - - ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); - - kfree(buf); - return ret_cnt; -} - -static const struct file_operations fops_war_stats = { - .read = read_file_war_stats, - .open = ath6kl_debugfs_open, - .owner = THIS_MODULE, - .llseek = default_llseek, -}; - -static void ath6kl_debug_fwlog_add(struct ath6kl *ar, const void *buf, - size_t buf_len) -{ - struct circ_buf *fwlog = &ar->debug.fwlog_buf; - size_t space; - int i; - - /* entries must all be equal size */ - if (WARN_ON(buf_len != ATH6KL_FWLOG_SLOT_SIZE)) - return; - - space = CIRC_SPACE(fwlog->head, fwlog->tail, ATH6KL_FWLOG_SIZE); - if (space < buf_len) - /* discard oldest slot */ - fwlog->tail = (fwlog->tail + ATH6KL_FWLOG_SLOT_SIZE) & - (ATH6KL_FWLOG_SIZE - 1); - - for (i = 0; i < buf_len; i += space) { - space = CIRC_SPACE_TO_END(fwlog->head, fwlog->tail, - ATH6KL_FWLOG_SIZE); - - if ((size_t) space > buf_len - i) - space = buf_len - i; - - memcpy(&fwlog->buf[fwlog->head], buf, space); - fwlog->head = (fwlog->head + space) & (ATH6KL_FWLOG_SIZE - 1); - } - -} - -void ath6kl_debug_fwlog_event(struct ath6kl *ar, const void *buf, size_t len) -{ - struct ath6kl_fwlog_slot *slot = ar->debug.fwlog_tmp; - size_t slot_len; - - if (WARN_ON(len > ATH6KL_FWLOG_PAYLOAD_SIZE)) - return; - - spin_lock_bh(&ar->debug.fwlog_lock); - - slot->timestamp = cpu_to_le32(jiffies); - slot->length = cpu_to_le32(len); - memcpy(slot->payload, buf, len); - - slot_len = sizeof(*slot) + len; - - if (slot_len < ATH6KL_FWLOG_SLOT_SIZE) - memset(slot->payload + len, 0, - ATH6KL_FWLOG_SLOT_SIZE - slot_len); - - ath6kl_debug_fwlog_add(ar, slot, ATH6KL_FWLOG_SLOT_SIZE); - - spin_unlock_bh(&ar->debug.fwlog_lock); -} - -static bool ath6kl_debug_fwlog_empty(struct ath6kl *ar) -{ - return CIRC_CNT(ar->debug.fwlog_buf.head, - ar->debug.fwlog_buf.tail, - ATH6KL_FWLOG_SLOT_SIZE) == 0; -} - -static ssize_t ath6kl_fwlog_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath6kl *ar = file->private_data; - struct circ_buf *fwlog = &ar->debug.fwlog_buf; - size_t len = 0, buf_len = count; - ssize_t ret_cnt; - char *buf; - int ccnt; - - buf = vmalloc(buf_len); - if (!buf) - return -ENOMEM; - - /* read undelivered logs from firmware */ - ath6kl_read_fwlogs(ar); - - spin_lock_bh(&ar->debug.fwlog_lock); - - while (len < buf_len && !ath6kl_debug_fwlog_empty(ar)) { - ccnt = CIRC_CNT_TO_END(fwlog->head, fwlog->tail, - ATH6KL_FWLOG_SIZE); - - if ((size_t) ccnt > buf_len - len) - ccnt = buf_len - len; - - memcpy(buf + len, &fwlog->buf[fwlog->tail], ccnt); - len += ccnt; - - fwlog->tail = (fwlog->tail + ccnt) & - (ATH6KL_FWLOG_SIZE - 1); - } - - spin_unlock_bh(&ar->debug.fwlog_lock); - - if (WARN_ON(len > buf_len)) - len = buf_len; - - ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); - - vfree(buf); - - return ret_cnt; -} - -static const struct file_operations fops_fwlog = { - .open = ath6kl_debugfs_open, - .read = ath6kl_fwlog_read, - .owner = THIS_MODULE, - .llseek = default_llseek, -}; - -static ssize_t ath6kl_fwlog_mask_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath6kl *ar = file->private_data; - char buf[16]; - int len; - - len = snprintf(buf, sizeof(buf), "0x%x\n", ar->debug.fwlog_mask); - - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static ssize_t ath6kl_fwlog_mask_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath6kl *ar = file->private_data; - int ret; - - ret = kstrtou32_from_user(user_buf, count, 0, &ar->debug.fwlog_mask); - if (ret) - return ret; - - ret = ath6kl_wmi_config_debug_module_cmd(ar->wmi, - ATH6KL_FWLOG_VALID_MASK, - ar->debug.fwlog_mask); - if (ret) - return ret; - - return count; -} - -static const struct file_operations fops_fwlog_mask = { - .open = ath6kl_debugfs_open, - .read = ath6kl_fwlog_mask_read, - .write = ath6kl_fwlog_mask_write, - .owner = THIS_MODULE, - .llseek = default_llseek, -}; - -static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath6kl *ar = file->private_data; - struct target_stats *tgt_stats = &ar->target_stats; - char *buf; - unsigned int len = 0, buf_len = 1500; - int i; - long left; - ssize_t ret_cnt; - - buf = kzalloc(buf_len, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - if (down_interruptible(&ar->sem)) { - kfree(buf); - return -EBUSY; - } - - set_bit(STATS_UPDATE_PEND, &ar->flag); - - if (ath6kl_wmi_get_stats_cmd(ar->wmi)) { - up(&ar->sem); - kfree(buf); - return -EIO; - } - - left = wait_event_interruptible_timeout(ar->event_wq, - !test_bit(STATS_UPDATE_PEND, - &ar->flag), WMI_TIMEOUT); - - up(&ar->sem); - - if (left <= 0) { - kfree(buf); - return -ETIMEDOUT; - } - - len += scnprintf(buf + len, buf_len - len, "\n"); - len += scnprintf(buf + len, buf_len - len, "%25s\n", - "Target Tx stats"); - len += scnprintf(buf + len, buf_len - len, "%25s\n\n", - "================="); - len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", - "Ucast packets", tgt_stats->tx_ucast_pkt); - len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", - "Bcast packets", tgt_stats->tx_bcast_pkt); - len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", - "Ucast byte", tgt_stats->tx_ucast_byte); - len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", - "Bcast byte", tgt_stats->tx_bcast_byte); - len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", - "Rts success cnt", tgt_stats->tx_rts_success_cnt); - for (i = 0; i < 4; i++) - len += scnprintf(buf + len, buf_len - len, - "%18s %d %10llu\n", "PER on ac", - i, tgt_stats->tx_pkt_per_ac[i]); - len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", - "Error", tgt_stats->tx_err); - len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", - "Fail count", tgt_stats->tx_fail_cnt); - len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", - "Retry count", tgt_stats->tx_retry_cnt); - len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", - "Multi retry cnt", tgt_stats->tx_mult_retry_cnt); - len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", - "Rts fail cnt", tgt_stats->tx_rts_fail_cnt); - len += scnprintf(buf + len, buf_len - len, "%25s %10llu\n\n", - "TKIP counter measure used", - tgt_stats->tkip_cnter_measures_invoked); - - len += scnprintf(buf + len, buf_len - len, "%25s\n", - "Target Rx stats"); - len += scnprintf(buf + len, buf_len - len, "%25s\n", - "================="); - - len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", - "Ucast packets", tgt_stats->rx_ucast_pkt); - len += scnprintf(buf + len, buf_len - len, "%20s %10d\n", - "Ucast Rate", tgt_stats->rx_ucast_rate); - len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", - "Bcast packets", tgt_stats->rx_bcast_pkt); - len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", - "Ucast byte", tgt_stats->rx_ucast_byte); - len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", - "Bcast byte", tgt_stats->rx_bcast_byte); - len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", - "Fragmented pkt", tgt_stats->rx_frgment_pkt); - len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", - "Error", tgt_stats->rx_err); - len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", - "CRC Err", tgt_stats->rx_crc_err); - len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", - "Key chache miss", tgt_stats->rx_key_cache_miss); - len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", - "Decrypt Err", tgt_stats->rx_decrypt_err); - len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", - "Duplicate frame", tgt_stats->rx_dupl_frame); - len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", - "Tkip Mic failure", tgt_stats->tkip_local_mic_fail); - len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", - "TKIP format err", tgt_stats->tkip_fmt_err); - len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", - "CCMP format Err", tgt_stats->ccmp_fmt_err); - len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n\n", - "CCMP Replay Err", tgt_stats->ccmp_replays); - - len += scnprintf(buf + len, buf_len - len, "%25s\n", - "Misc Target stats"); - len += scnprintf(buf + len, buf_len - len, "%25s\n", - "================="); - len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", - "Beacon Miss count", tgt_stats->cs_bmiss_cnt); - len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", - "Num Connects", tgt_stats->cs_connect_cnt); - len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", - "Num disconnects", tgt_stats->cs_discon_cnt); - len += scnprintf(buf + len, buf_len - len, "%20s %10d\n", - "Beacon avg rssi", tgt_stats->cs_ave_beacon_rssi); - - if (len > buf_len) - len = buf_len; - - ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); - - kfree(buf); - return ret_cnt; -} - -static const struct file_operations fops_tgt_stats = { - .read = read_file_tgt_stats, - .open = ath6kl_debugfs_open, - .owner = THIS_MODULE, - .llseek = default_llseek, -}; - -#define print_credit_info(fmt_str, ep_list_field) \ - (len += scnprintf(buf + len, buf_len - len, fmt_str, \ - ep_list->ep_list_field)) -#define CREDIT_INFO_DISPLAY_STRING_LEN 200 -#define CREDIT_INFO_LEN 128 - -static ssize_t read_file_credit_dist_stats(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath6kl *ar = file->private_data; - struct htc_target *target = ar->htc_target; - struct htc_endpoint_credit_dist *ep_list; - char *buf; - unsigned int buf_len, len = 0; - ssize_t ret_cnt; - - buf_len = CREDIT_INFO_DISPLAY_STRING_LEN + - get_queue_depth(&target->cred_dist_list) * CREDIT_INFO_LEN; - buf = kzalloc(buf_len, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - len += scnprintf(buf + len, buf_len - len, "%25s%5d\n", - "Total Avail Credits: ", - target->cred_dist_cntxt->total_avail_credits); - len += scnprintf(buf + len, buf_len - len, "%25s%5d\n", - "Free credits :", - target->cred_dist_cntxt->cur_free_credits); - - len += scnprintf(buf + len, buf_len - len, - " Epid Flags Cred_norm Cred_min Credits Cred_assngd" - " Seek_cred Cred_sz Cred_per_msg Cred_to_dist" - " qdepth\n"); - - list_for_each_entry(ep_list, &target->cred_dist_list, list) { - print_credit_info(" %2d", endpoint); - print_credit_info("%10x", dist_flags); - print_credit_info("%8d", cred_norm); - print_credit_info("%9d", cred_min); - print_credit_info("%9d", credits); - print_credit_info("%10d", cred_assngd); - print_credit_info("%13d", seek_cred); - print_credit_info("%12d", cred_sz); - print_credit_info("%9d", cred_per_msg); - print_credit_info("%14d", cred_to_dist); - len += scnprintf(buf + len, buf_len - len, "%12d\n", - get_queue_depth(&((struct htc_endpoint *) - ep_list->htc_rsvd)->txq)); - } - - if (len > buf_len) - len = buf_len; - - ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); - kfree(buf); - return ret_cnt; -} - -static const struct file_operations fops_credit_dist_stats = { - .read = read_file_credit_dist_stats, - .open = ath6kl_debugfs_open, - .owner = THIS_MODULE, - .llseek = default_llseek, -}; - -static unsigned long ath6kl_get_num_reg(void) -{ - int i; - unsigned long n_reg = 0; - - for (i = 0; i < ARRAY_SIZE(diag_reg); i++) - n_reg = n_reg + - (diag_reg[i].reg_end - diag_reg[i].reg_start) / 4 + 1; - - return n_reg; -} - -static bool ath6kl_dbg_is_diag_reg_valid(u32 reg_addr) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(diag_reg); i++) { - if (reg_addr >= diag_reg[i].reg_start && - reg_addr <= diag_reg[i].reg_end) - return true; - } - - return false; -} - -static ssize_t ath6kl_regread_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath6kl *ar = file->private_data; - u8 buf[50]; - unsigned int len = 0; - - if (ar->debug.dbgfs_diag_reg) - len += scnprintf(buf + len, sizeof(buf) - len, "0x%x\n", - ar->debug.dbgfs_diag_reg); - else - len += scnprintf(buf + len, sizeof(buf) - len, - "All diag registers\n"); - - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static ssize_t ath6kl_regread_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath6kl *ar = file->private_data; - u8 buf[50]; - unsigned int len; - unsigned long reg_addr; - - len = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, len)) - return -EFAULT; - - buf[len] = '\0'; - - if (strict_strtoul(buf, 0, ®_addr)) - return -EINVAL; - - if ((reg_addr % 4) != 0) - return -EINVAL; - - if (reg_addr && !ath6kl_dbg_is_diag_reg_valid(reg_addr)) - return -EINVAL; - - ar->debug.dbgfs_diag_reg = reg_addr; - - return count; -} - -static const struct file_operations fops_diag_reg_read = { - .read = ath6kl_regread_read, - .write = ath6kl_regread_write, - .open = ath6kl_debugfs_open, - .owner = THIS_MODULE, - .llseek = default_llseek, -}; - -static int ath6kl_regdump_open(struct inode *inode, struct file *file) -{ - struct ath6kl *ar = inode->i_private; - u8 *buf; - unsigned long int reg_len; - unsigned int len = 0, n_reg; - u32 addr; - __le32 reg_val; - int i, status; - - /* Dump all the registers if no register is specified */ - if (!ar->debug.dbgfs_diag_reg) - n_reg = ath6kl_get_num_reg(); - else - n_reg = 1; - - reg_len = n_reg * REG_OUTPUT_LEN_PER_LINE; - if (n_reg > 1) - reg_len += REGTYPE_STR_LEN; - - buf = vmalloc(reg_len); - if (!buf) - return -ENOMEM; - - if (n_reg == 1) { - addr = ar->debug.dbgfs_diag_reg; - - status = ath6kl_diag_read32(ar, - TARG_VTOP(ar->target_type, addr), - (u32 *)®_val); - if (status) - goto fail_reg_read; - - len += scnprintf(buf + len, reg_len - len, - "0x%06x 0x%08x\n", addr, le32_to_cpu(reg_val)); - goto done; - } - - for (i = 0; i < ARRAY_SIZE(diag_reg); i++) { - len += scnprintf(buf + len, reg_len - len, - "%s\n", diag_reg[i].reg_info); - for (addr = diag_reg[i].reg_start; - addr <= diag_reg[i].reg_end; addr += 4) { - status = ath6kl_diag_read32(ar, - TARG_VTOP(ar->target_type, addr), - (u32 *)®_val); - if (status) - goto fail_reg_read; - - len += scnprintf(buf + len, reg_len - len, - "0x%06x 0x%08x\n", - addr, le32_to_cpu(reg_val)); - } - } - -done: - file->private_data = buf; - return 0; - -fail_reg_read: - ath6kl_warn("Unable to read memory:%u\n", addr); - vfree(buf); - return -EIO; -} - -static ssize_t ath6kl_regdump_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - u8 *buf = file->private_data; - return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); -} - -static int ath6kl_regdump_release(struct inode *inode, struct file *file) -{ - vfree(file->private_data); - return 0; -} - -static const struct file_operations fops_reg_dump = { - .open = ath6kl_regdump_open, - .read = ath6kl_regdump_read, - .release = ath6kl_regdump_release, - .owner = THIS_MODULE, - .llseek = default_llseek, -}; - -static ssize_t ath6kl_lrssi_roam_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath6kl *ar = file->private_data; - unsigned long lrssi_roam_threshold; - char buf[32]; - ssize_t len; - - len = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, len)) - return -EFAULT; - - buf[len] = '\0'; - if (strict_strtoul(buf, 0, &lrssi_roam_threshold)) - return -EINVAL; - - ar->lrssi_roam_threshold = lrssi_roam_threshold; - - ath6kl_wmi_set_roam_lrssi_cmd(ar->wmi, ar->lrssi_roam_threshold); - - return count; -} - -static ssize_t ath6kl_lrssi_roam_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath6kl *ar = file->private_data; - char buf[32]; - unsigned int len; - - len = snprintf(buf, sizeof(buf), "%u\n", ar->lrssi_roam_threshold); - - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static const struct file_operations fops_lrssi_roam_threshold = { - .read = ath6kl_lrssi_roam_read, - .write = ath6kl_lrssi_roam_write, - .open = ath6kl_debugfs_open, - .owner = THIS_MODULE, - .llseek = default_llseek, -}; - -static ssize_t ath6kl_regwrite_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath6kl *ar = file->private_data; - u8 buf[32]; - unsigned int len = 0; - - len = scnprintf(buf, sizeof(buf), "Addr: 0x%x Val: 0x%x\n", - ar->debug.diag_reg_addr_wr, ar->debug.diag_reg_val_wr); - - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static ssize_t ath6kl_regwrite_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath6kl *ar = file->private_data; - char buf[32]; - char *sptr, *token; - unsigned int len = 0; - u32 reg_addr, reg_val; - - len = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, len)) - return -EFAULT; - - buf[len] = '\0'; - sptr = buf; - - token = strsep(&sptr, "="); - if (!token) - return -EINVAL; - - if (kstrtou32(token, 0, ®_addr)) - return -EINVAL; - - if (!ath6kl_dbg_is_diag_reg_valid(reg_addr)) - return -EINVAL; - - if (kstrtou32(sptr, 0, ®_val)) - return -EINVAL; - - ar->debug.diag_reg_addr_wr = reg_addr; - ar->debug.diag_reg_val_wr = reg_val; - - if (ath6kl_diag_write32(ar, ar->debug.diag_reg_addr_wr, - cpu_to_le32(ar->debug.diag_reg_val_wr))) - return -EIO; - - return count; -} - -static const struct file_operations fops_diag_reg_write = { - .read = ath6kl_regwrite_read, - .write = ath6kl_regwrite_write, - .open = ath6kl_debugfs_open, - .owner = THIS_MODULE, - .llseek = default_llseek, -}; - -int ath6kl_debug_init(struct ath6kl *ar) -{ - ar->debug.fwlog_buf.buf = vmalloc(ATH6KL_FWLOG_SIZE); - if (ar->debug.fwlog_buf.buf == NULL) - return -ENOMEM; - - ar->debug.fwlog_tmp = kmalloc(ATH6KL_FWLOG_SLOT_SIZE, GFP_KERNEL); - if (ar->debug.fwlog_tmp == NULL) { - vfree(ar->debug.fwlog_buf.buf); - return -ENOMEM; - } - - spin_lock_init(&ar->debug.fwlog_lock); - - /* - * Actually we are lying here but don't know how to read the mask - * value from the firmware. - */ - ar->debug.fwlog_mask = 0; - - ar->debugfs_phy = debugfs_create_dir("ath6kl", - ar->wdev->wiphy->debugfsdir); - if (!ar->debugfs_phy) { - vfree(ar->debug.fwlog_buf.buf); - kfree(ar->debug.fwlog_tmp); - return -ENOMEM; - } - - debugfs_create_file("tgt_stats", S_IRUSR, ar->debugfs_phy, ar, - &fops_tgt_stats); - - debugfs_create_file("credit_dist_stats", S_IRUSR, ar->debugfs_phy, ar, - &fops_credit_dist_stats); - - debugfs_create_file("fwlog", S_IRUSR, ar->debugfs_phy, ar, - &fops_fwlog); - - debugfs_create_file("fwlog_mask", S_IRUSR | S_IWUSR, ar->debugfs_phy, - ar, &fops_fwlog_mask); - - debugfs_create_file("reg_addr", S_IRUSR | S_IWUSR, ar->debugfs_phy, ar, - &fops_diag_reg_read); - - debugfs_create_file("reg_dump", S_IRUSR, ar->debugfs_phy, ar, - &fops_reg_dump); - - debugfs_create_file("lrssi_roam_threshold", S_IRUSR | S_IWUSR, - ar->debugfs_phy, ar, &fops_lrssi_roam_threshold); - - debugfs_create_file("reg_write", S_IRUSR | S_IWUSR, - ar->debugfs_phy, ar, &fops_diag_reg_write); - - debugfs_create_file("war_stats", S_IRUSR, ar->debugfs_phy, ar, - &fops_war_stats); - - return 0; -} - -void ath6kl_debug_cleanup(struct ath6kl *ar) -{ - vfree(ar->debug.fwlog_buf.buf); - kfree(ar->debug.fwlog_tmp); -} - #endif diff --git a/trunk/drivers/net/wireless/ath/ath6kl/debug.h b/trunk/drivers/net/wireless/ath/ath6kl/debug.h index 9288a3ce1e39..66b399962f01 100644 --- a/trunk/drivers/net/wireless/ath/ath6kl/debug.h +++ b/trunk/drivers/net/wireless/ath/ath6kl/debug.h @@ -34,12 +34,8 @@ enum ATH6K_DEBUG_MASK { ATH6KL_DBG_TRC = BIT(11), /* generic func tracing */ ATH6KL_DBG_SCATTER = BIT(12), /* hif scatter tracing */ ATH6KL_DBG_WLAN_CFG = BIT(13), /* cfg80211 i/f file tracing */ - ATH6KL_DBG_RAW_BYTES = BIT(14), /* dump tx/rx frames */ + ATH6KL_DBG_RAW_BYTES = BIT(14), /* dump tx/rx and wmi frames */ ATH6KL_DBG_AGGR = BIT(15), /* aggregation */ - ATH6KL_DBG_SDIO = BIT(16), - ATH6KL_DBG_SDIO_DUMP = BIT(17), - ATH6KL_DBG_BOOT = BIT(18), /* driver init and fw boot */ - ATH6KL_DBG_WMI_DUMP = BIT(19), ATH6KL_DBG_ANY = 0xffffffff /* enable all logs */ }; @@ -56,10 +52,6 @@ extern int ath6kl_printk(const char *level, const char *fmt, ...) #define AR_DBG_LVL_CHECK(mask) (debug_mask & mask) -enum ath6kl_war { - ATH6KL_WAR_INVALID_RATE, -}; - #ifdef CONFIG_ATH6KL_DEBUG #define ath6kl_dbg(mask, fmt, ...) \ ({ \ @@ -73,14 +65,12 @@ enum ath6kl_war { }) static inline void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask, - const char *msg, const char *prefix, - const void *buf, size_t len) + const char *msg, const void *buf, + size_t len) { if (debug_mask & mask) { - if (msg) - ath6kl_dbg(mask, "%s\n", msg); - - print_hex_dump_bytes(prefix, DUMP_PREFIX_OFFSET, buf, len); + ath6kl_dbg(mask, "%s\n", msg); + print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, buf, len); } } @@ -88,11 +78,6 @@ void ath6kl_dump_registers(struct ath6kl_device *dev, struct ath6kl_irq_proc_registers *irq_proc_reg, struct ath6kl_irq_enable_reg *irq_en_reg); void dump_cred_dist_stats(struct htc_target *target); -void ath6kl_debug_fwlog_event(struct ath6kl *ar, const void *buf, size_t len); -void ath6kl_debug_war(struct ath6kl *ar, enum ath6kl_war war); -int ath6kl_debug_init(struct ath6kl *ar); -void ath6kl_debug_cleanup(struct ath6kl *ar); - #else static inline int ath6kl_dbg(enum ATH6K_DEBUG_MASK dbg_mask, const char *fmt, ...) @@ -101,8 +86,8 @@ static inline int ath6kl_dbg(enum ATH6K_DEBUG_MASK dbg_mask, } static inline void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask, - const char *msg, const char *prefix, - const void *buf, size_t len) + const char *msg, const void *buf, + size_t len) { } @@ -115,24 +100,6 @@ static inline void ath6kl_dump_registers(struct ath6kl_device *dev, static inline void dump_cred_dist_stats(struct htc_target *target) { } - -static inline void ath6kl_debug_fwlog_event(struct ath6kl *ar, - const void *buf, size_t len) -{ -} - -static inline void ath6kl_debug_war(struct ath6kl *ar, enum ath6kl_war war) -{ -} - -static inline int ath6kl_debug_init(struct ath6kl *ar) -{ - return 0; -} - -static inline void ath6kl_debug_cleanup(struct ath6kl *ar) -{ -} - #endif + #endif diff --git a/trunk/drivers/net/wireless/ath/ath6kl/hif-ops.h b/trunk/drivers/net/wireless/ath/ath6kl/hif-ops.h index d6c898f3d0b3..c923979776a0 100644 --- a/trunk/drivers/net/wireless/ath/ath6kl/hif-ops.h +++ b/trunk/drivers/net/wireless/ath/ath6kl/hif-ops.h @@ -69,9 +69,4 @@ static inline void ath6kl_hif_cleanup_scatter(struct ath6kl *ar) return ar->hif_ops->cleanup_scatter(ar); } -static inline int ath6kl_hif_suspend(struct ath6kl *ar) -{ - return ar->hif_ops->suspend(ar); -} - #endif diff --git a/trunk/drivers/net/wireless/ath/ath6kl/hif.h b/trunk/drivers/net/wireless/ath/ath6kl/hif.h index 797e2d1d9bf9..5ceff54775a1 100644 --- a/trunk/drivers/net/wireless/ath/ath6kl/hif.h +++ b/trunk/drivers/net/wireless/ath/ath6kl/hif.h @@ -202,7 +202,6 @@ struct ath6kl_hif_ops { int (*scat_req_rw) (struct ath6kl *ar, struct hif_scatter_req *scat_req); void (*cleanup_scatter)(struct ath6kl *ar); - int (*suspend)(struct ath6kl *ar); }; #endif diff --git a/trunk/drivers/net/wireless/ath/ath6kl/htc.c b/trunk/drivers/net/wireless/ath/ath6kl/htc.c index f88a7c9e4148..a8dc5c3ea567 100644 --- a/trunk/drivers/net/wireless/ath/ath6kl/htc.c +++ b/trunk/drivers/net/wireless/ath/ath6kl/htc.c @@ -22,19 +22,8 @@ #define CALC_TXRX_PADDED_LEN(dev, len) (__ALIGN_MASK((len), (dev)->block_mask)) -static void ath6kl_htc_tx_buf_align(u8 **buf, unsigned long len) -{ - u8 *align_addr; - - if (!IS_ALIGNED((unsigned long) *buf, 4)) { - align_addr = PTR_ALIGN(*buf - 4, 4); - memmove(align_addr, *buf, len); - *buf = align_addr; - } -} - -static void ath6kl_htc_tx_prep_pkt(struct htc_packet *packet, u8 flags, - int ctrl0, int ctrl1) +static void htc_prep_send_pkt(struct htc_packet *packet, u8 flags, int ctrl0, + int ctrl1) { struct htc_frame_hdr *hdr; @@ -178,8 +167,7 @@ static void htc_async_tx_scat_complete(struct htc_target *target, htc_tx_complete(endpoint, &tx_compq); } -static int ath6kl_htc_tx_issue(struct htc_target *target, - struct htc_packet *packet) +static int htc_issue_send(struct htc_target *target, struct htc_packet *packet) { int status; bool sync = false; @@ -208,7 +196,7 @@ static int ath6kl_htc_tx_issue(struct htc_target *target, HIF_WR_SYNC_BLOCK_INC); packet->status = status; - packet->buf += HTC_HDR_LENGTH; + packet->buf += HTC_HDR_LENGTH; } else status = hif_write_async(target->dev->ar, target->dev->ar->mbox_info.htc_addr, @@ -277,9 +265,9 @@ static int htc_check_credits(struct htc_target *target, return 0; } -static void ath6kl_htc_tx_pkts_get(struct htc_target *target, - struct htc_endpoint *endpoint, - struct list_head *queue) +static void htc_tx_pkts_get(struct htc_target *target, + struct htc_endpoint *endpoint, + struct list_head *queue) { int req_cred; u8 flags; @@ -358,11 +346,11 @@ static int htc_get_credit_padding(unsigned int cred_sz, int *len, return cred_pad; } -static int ath6kl_htc_tx_setup_scat_list(struct htc_target *target, - struct htc_endpoint *endpoint, - struct hif_scatter_req *scat_req, - int n_scat, - struct list_head *queue) +static int htc_setup_send_scat_list(struct htc_target *target, + struct htc_endpoint *endpoint, + struct hif_scatter_req *scat_req, + int n_scat, + struct list_head *queue) { struct htc_packet *packet; int i, len, rem_scat, cred_pad; @@ -382,23 +370,27 @@ static int ath6kl_htc_tx_setup_scat_list(struct htc_target *target, cred_pad = htc_get_credit_padding(target->tgt_cred_sz, &len, endpoint); - if (cred_pad < 0 || rem_scat < len) { + if (cred_pad < 0) { + status = -EINVAL; + break; + } + + if (rem_scat < len) { + /* exceeds what we can transfer */ status = -ENOSPC; break; } rem_scat -= len; /* now remove it from the queue */ + packet = list_first_entry(queue, struct htc_packet, list); list_del(&packet->list); scat_req->scat_list[i].packet = packet; /* prepare packet and flag message as part of a send bundle */ - ath6kl_htc_tx_prep_pkt(packet, + htc_prep_send_pkt(packet, packet->info.tx.flags | HTC_FLAGS_SEND_BUNDLE, cred_pad, packet->info.tx.seqno); - /* Make sure the buffer is 4-byte aligned */ - ath6kl_htc_tx_buf_align(&packet->buf, - packet->act_len + HTC_HDR_LENGTH); scat_req->scat_list[i].buf = packet->buf; scat_req->scat_list[i].len = len; @@ -410,7 +402,7 @@ static int ath6kl_htc_tx_setup_scat_list(struct htc_target *target, } /* Roll back scatter setup in case of any failure */ - if (scat_req->scat_entries < HTC_MIN_HTC_MSGS_TO_BUNDLE) { + if (status || (scat_req->scat_entries < HTC_MIN_HTC_MSGS_TO_BUNDLE)) { for (i = scat_req->scat_entries - 1; i >= 0; i--) { packet = scat_req->scat_list[i].packet; if (packet) { @@ -418,32 +410,31 @@ static int ath6kl_htc_tx_setup_scat_list(struct htc_target *target, list_add(&packet->list, queue); } } - return -EAGAIN; + return -EINVAL; } - return status; + return 0; } /* - * Drain a queue and send as bundles this function may return without fully - * draining the queue when + * htc_issue_send_bundle: drain a queue and send as bundles + * this function may return without fully draining the queue + * when * * 1. scatter resources are exhausted * 2. a message that will consume a partial credit will stop the * bundling process early * 3. we drop below the minimum number of messages for a bundle */ -static void ath6kl_htc_tx_bundle(struct htc_endpoint *endpoint, - struct list_head *queue, - int *sent_bundle, int *n_bundle_pkts) +static void htc_issue_send_bundle(struct htc_endpoint *endpoint, + struct list_head *queue, + int *sent_bundle, int *n_bundle_pkts) { struct htc_target *target = endpoint->target; struct hif_scatter_req *scat_req = NULL; int n_scat, n_sent_bundle = 0, tot_pkts_bundle = 0; - int status; while (true) { - status = 0; n_scat = get_queue_depth(queue); n_scat = min(n_scat, target->msg_per_bndl_max); @@ -466,10 +457,8 @@ static void ath6kl_htc_tx_bundle(struct htc_endpoint *endpoint, scat_req->len = 0; scat_req->scat_entries = 0; - status = ath6kl_htc_tx_setup_scat_list(target, endpoint, - scat_req, n_scat, - queue); - if (status == -EAGAIN) { + if (htc_setup_send_scat_list(target, endpoint, scat_req, + n_scat, queue)) { hif_scatter_req_add(target->dev->ar, scat_req); break; } @@ -483,21 +472,18 @@ static void ath6kl_htc_tx_bundle(struct htc_endpoint *endpoint, "send scatter total bytes: %d , entries: %d\n", scat_req->len, scat_req->scat_entries); ath6kldev_submit_scat_req(target->dev, scat_req, false); - - if (status) - break; } *sent_bundle = n_sent_bundle; *n_bundle_pkts = tot_pkts_bundle; - ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "%s (sent:%d)\n", - __func__, n_sent_bundle); + ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "htc_issue_send_bundle (sent:%d)\n", + n_sent_bundle); return; } -static void ath6kl_htc_tx_from_queue(struct htc_target *target, - struct htc_endpoint *endpoint) +static void htc_tx_from_ep_txq(struct htc_target *target, + struct htc_endpoint *endpoint) { struct list_head txq; struct htc_packet *packet; @@ -525,7 +511,7 @@ static void ath6kl_htc_tx_from_queue(struct htc_target *target, if (list_empty(&endpoint->txq)) break; - ath6kl_htc_tx_pkts_get(target, endpoint, &txq); + htc_tx_pkts_get(target, endpoint, &txq); if (list_empty(&txq)) break; @@ -542,8 +528,8 @@ static void ath6kl_htc_tx_from_queue(struct htc_target *target, HTC_MIN_HTC_MSGS_TO_BUNDLE)) { int temp1 = 0, temp2 = 0; - ath6kl_htc_tx_bundle(endpoint, &txq, - &temp1, &temp2); + htc_issue_send_bundle(endpoint, &txq, + &temp1, &temp2); bundle_sent += temp1; n_pkts_bundle += temp2; } @@ -555,9 +541,9 @@ static void ath6kl_htc_tx_from_queue(struct htc_target *target, list); list_del(&packet->list); - ath6kl_htc_tx_prep_pkt(packet, packet->info.tx.flags, - 0, packet->info.tx.seqno); - ath6kl_htc_tx_issue(target, packet); + htc_prep_send_pkt(packet, packet->info.tx.flags, + 0, packet->info.tx.seqno); + htc_issue_send(target, packet); } spin_lock_bh(&target->tx_lock); @@ -570,9 +556,9 @@ static void ath6kl_htc_tx_from_queue(struct htc_target *target, spin_unlock_bh(&target->tx_lock); } -static bool ath6kl_htc_tx_try(struct htc_target *target, - struct htc_endpoint *endpoint, - struct htc_packet *tx_pkt) +static bool htc_try_send(struct htc_target *target, + struct htc_endpoint *endpoint, + struct htc_packet *tx_pkt) { struct htc_ep_callbacks ep_cb; int txq_depth; @@ -608,7 +594,7 @@ static bool ath6kl_htc_tx_try(struct htc_target *target, list_add_tail(&tx_pkt->list, &endpoint->txq); spin_unlock_bh(&target->tx_lock); - ath6kl_htc_tx_from_queue(target, endpoint); + htc_tx_from_ep_txq(target, endpoint); return true; } @@ -642,7 +628,7 @@ static void htc_chk_ep_txq(struct htc_target *target) * chance to reclaim credits from lower priority * ones. */ - ath6kl_htc_tx_from_queue(target, endpoint); + htc_tx_from_ep_txq(target, endpoint); spin_lock_bh(&target->tx_lock); } spin_unlock_bh(&target->tx_lock); @@ -694,8 +680,8 @@ static int htc_setup_tx_complete(struct htc_target *target) /* we want synchronous operation */ send_pkt->completion = NULL; - ath6kl_htc_tx_prep_pkt(send_pkt, 0, 0, 0); - status = ath6kl_htc_tx_issue(target, send_pkt); + htc_prep_send_pkt(send_pkt, 0, 0, 0); + status = htc_issue_send(target, send_pkt); if (send_pkt != NULL) htc_reclaim_txctrl_buf(target, send_pkt); @@ -747,7 +733,7 @@ int ath6kl_htc_tx(struct htc_target *target, struct htc_packet *packet) endpoint = &target->endpoint[packet->endpoint]; - if (!ath6kl_htc_tx_try(target, endpoint, packet)) { + if (!htc_try_send(target, endpoint, packet)) { packet->status = (target->htc_flags & HTC_OP_STATE_STOPPING) ? -ECANCELED : -ENOSPC; INIT_LIST_HEAD(&queue); @@ -860,8 +846,8 @@ void ath6kl_htc_indicate_activity_change(struct htc_target *target, /* HTC Rx */ -static inline void ath6kl_htc_rx_update_stats(struct htc_endpoint *endpoint, - int n_look_ahds) +static inline void htc_update_rx_stats(struct htc_endpoint *endpoint, + int n_look_ahds) { endpoint->ep_st.rx_pkts++; if (n_look_ahds == 1) @@ -908,9 +894,8 @@ static void reclaim_rx_ctrl_buf(struct htc_target *target, spin_unlock_bh(&target->htc_lock); } -static int ath6kl_htc_rx_packet(struct htc_target *target, - struct htc_packet *packet, - u32 rx_len) +static int dev_rx_pkt(struct htc_target *target, struct htc_packet *packet, + u32 rx_len) { struct ath6kl_device *dev = target->dev; u32 padded_len; @@ -944,9 +929,9 @@ static int ath6kl_htc_rx_packet(struct htc_target *target, * "hint" that there are more single-packets to fetch * on this endpoint. */ -static void ath6kl_htc_rx_set_indicate(u32 lk_ahd, - struct htc_endpoint *endpoint, - struct htc_packet *packet) +static void set_rxpkt_indication_flag(u32 lk_ahd, + struct htc_endpoint *endpoint, + struct htc_packet *packet) { struct htc_frame_hdr *htc_hdr = (struct htc_frame_hdr *)&lk_ahd; @@ -957,7 +942,7 @@ static void ath6kl_htc_rx_set_indicate(u32 lk_ahd, } } -static void ath6kl_htc_rx_chk_water_mark(struct htc_endpoint *endpoint) +static void chk_rx_water_mark(struct htc_endpoint *endpoint) { struct htc_ep_callbacks ep_cb = endpoint->ep_cb; @@ -974,9 +959,8 @@ static void ath6kl_htc_rx_chk_water_mark(struct htc_endpoint *endpoint) } /* This function is called with rx_lock held */ -static int ath6kl_htc_rx_setup(struct htc_target *target, - struct htc_endpoint *ep, - u32 *lk_ahds, struct list_head *queue, int n_msg) +static int htc_setup_rxpkts(struct htc_target *target, struct htc_endpoint *ep, + u32 *lk_ahds, struct list_head *queue, int n_msg) { struct htc_packet *packet; /* FIXME: type of lk_ahds can't be right */ @@ -1076,10 +1060,10 @@ static int ath6kl_htc_rx_setup(struct htc_target *target, return status; } -static int ath6kl_htc_rx_alloc(struct htc_target *target, - u32 lk_ahds[], int msg, - struct htc_endpoint *endpoint, - struct list_head *queue) +static int alloc_and_prep_rxpkts(struct htc_target *target, + u32 lk_ahds[], int msg, + struct htc_endpoint *endpoint, + struct list_head *queue) { int status = 0; struct htc_packet *packet, *tmp_pkt; @@ -1145,8 +1129,8 @@ static int ath6kl_htc_rx_alloc(struct htc_target *target, n_msg = 1; /* Setup packet buffers for each message */ - status = ath6kl_htc_rx_setup(target, endpoint, &lk_ahds[i], - queue, n_msg); + status = htc_setup_rxpkts(target, endpoint, &lk_ahds[i], queue, + n_msg); /* * This is due to unavailabilty of buffers to rx entire data. @@ -1192,9 +1176,9 @@ static void htc_ctrl_rx(struct htc_target *context, struct htc_packet *packets) packets->act_len + HTC_HDR_LENGTH); ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, - "Unexpected ENDPOINT 0 Message", "", - packets->buf - HTC_HDR_LENGTH, - packets->act_len + HTC_HDR_LENGTH); + "Unexpected ENDPOINT 0 Message", + packets->buf - HTC_HDR_LENGTH, + packets->act_len + HTC_HDR_LENGTH); } htc_reclaim_rxbuf(context, packets, &context->endpoint[0]); @@ -1328,7 +1312,7 @@ static int htc_parse_trailer(struct htc_target *target, memcpy((u8 *)&next_lk_ahds[0], lk_ahd->lk_ahd, 4); ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "Next Look Ahead", - "", next_lk_ahds, 4); + next_lk_ahds, 4); *n_lk_ahds = 1; } @@ -1347,7 +1331,7 @@ static int htc_parse_trailer(struct htc_target *target, (struct htc_bundle_lkahd_rpt *) record_buf; ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "Bundle lk_ahd", - "", record_buf, record->len); + record_buf, record->len); for (i = 0; i < len; i++) { memcpy((u8 *)&next_lk_ahds[i], @@ -1380,8 +1364,7 @@ static int htc_proc_trailer(struct htc_target *target, ath6kl_dbg(ATH6KL_DBG_HTC_RECV, "+htc_proc_trailer (len:%d)\n", len); - ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "Recv Trailer", "", - buf, len); + ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "Recv Trailer", buf, len); orig_buf = buf; orig_len = len; @@ -1419,14 +1402,14 @@ static int htc_proc_trailer(struct htc_target *target, if (status) ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "BAD Recv Trailer", - "", orig_buf, orig_len); + orig_buf, orig_len); return status; } -static int ath6kl_htc_rx_process_hdr(struct htc_target *target, - struct htc_packet *packet, - u32 *next_lkahds, int *n_lkahds) +static int htc_proc_rxhdr(struct htc_target *target, + struct htc_packet *packet, + u32 *next_lkahds, int *n_lkahds) { int status = 0; u16 payload_len; @@ -1436,8 +1419,8 @@ static int ath6kl_htc_rx_process_hdr(struct htc_target *target, if (n_lkahds != NULL) *n_lkahds = 0; - ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "HTC Recv PKT", "htc ", - packet->buf, packet->act_len); + ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "HTC Recv PKT", packet->buf, + packet->act_len); /* * NOTE: we cannot assume the alignment of buf, so we use the safe @@ -1478,12 +1461,12 @@ static int ath6kl_htc_rx_process_hdr(struct htc_target *target, } if (lk_ahd != packet->info.rx.exp_hdr) { - ath6kl_err("%s(): lk_ahd mismatch! (pPkt:0x%p flags:0x%X)\n", - __func__, packet, packet->info.rx.rx_flags); + ath6kl_err("htc_proc_rxhdr, lk_ahd mismatch! (pPkt:0x%p flags:0x%X)\n", + packet, packet->info.rx.rx_flags); ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "Expected Message lk_ahd", - "", &packet->info.rx.exp_hdr, 4); + &packet->info.rx.exp_hdr, 4); ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "Current Frame Header", - "", (u8 *)&lk_ahd, sizeof(lk_ahd)); + (u8 *)&lk_ahd, sizeof(lk_ahd)); status = -ENOMEM; goto fail_rx; } @@ -1491,8 +1474,8 @@ static int ath6kl_htc_rx_process_hdr(struct htc_target *target, if (htc_hdr->flags & HTC_FLG_RX_TRAILER) { if (htc_hdr->ctrl[0] < sizeof(struct htc_record_hdr) || htc_hdr->ctrl[0] > payload_len) { - ath6kl_err("%s(): invalid hdr (payload len should be :%d, CB[0] is:%d)\n", - __func__, payload_len, htc_hdr->ctrl[0]); + ath6kl_err("htc_proc_rxhdr, invalid hdr (payload len should be :%d, CB[0] is:%d)\n", + payload_len, htc_hdr->ctrl[0]); status = -ENOMEM; goto fail_rx; } @@ -1519,20 +1502,20 @@ static int ath6kl_htc_rx_process_hdr(struct htc_target *target, fail_rx: if (status) ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "BAD HTC Recv PKT", - "", packet->buf, + packet->buf, packet->act_len < 256 ? packet->act_len : 256); else { if (packet->act_len > 0) ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, - "HTC - Application Msg", "", + "HTC - Application Msg", packet->buf, packet->act_len); } return status; } -static void ath6kl_htc_rx_complete(struct htc_endpoint *endpoint, - struct htc_packet *packet) +static void do_rx_completion(struct htc_endpoint *endpoint, + struct htc_packet *packet) { ath6kl_dbg(ATH6KL_DBG_HTC_RECV, "htc calling ep %d recv callback on packet 0x%p\n", @@ -1540,10 +1523,10 @@ static void ath6kl_htc_rx_complete(struct htc_endpoint *endpoint, endpoint->ep_cb.rx(endpoint->target, packet); } -static int ath6kl_htc_rx_bundle(struct htc_target *target, - struct list_head *rxq, - struct list_head *sync_compq, - int *n_pkt_fetched, bool part_bundle) +static int htc_issue_rxpkt_bundle(struct htc_target *target, + struct list_head *rxq, + struct list_head *sync_compq, + int *n_pkt_fetched, bool part_bundle) { struct hif_scatter_req *scat_req; struct htc_packet *packet; @@ -1565,15 +1548,15 @@ static int ath6kl_htc_rx_bundle(struct htc_target *target, * This would only happen if the target ignored our max * bundle limit. */ - ath6kl_warn("%s(): partial bundle detected num:%d , %d\n", - __func__, get_queue_depth(rxq), n_scat_pkt); + ath6kl_warn("htc_issue_rxpkt_bundle : partial bundle detected num:%d , %d\n", + get_queue_depth(rxq), n_scat_pkt); } len = 0; ath6kl_dbg(ATH6KL_DBG_HTC_RECV, - "%s(): (numpackets: %d , actual : %d)\n", - __func__, get_queue_depth(rxq), n_scat_pkt); + "htc_issue_rxpkt_bundle (numpackets: %d , actual : %d)\n", + get_queue_depth(rxq), n_scat_pkt); scat_req = hif_scatter_req_get(target->dev->ar); @@ -1633,10 +1616,9 @@ static int ath6kl_htc_rx_bundle(struct htc_target *target, return status; } -static int ath6kl_htc_rx_process_packets(struct htc_target *target, - struct list_head *comp_pktq, - u32 lk_ahds[], - int *n_lk_ahd) +static int htc_proc_fetched_rxpkts(struct htc_target *target, + struct list_head *comp_pktq, u32 lk_ahds[], + int *n_lk_ahd) { struct htc_packet *packet, *tmp_pkt; struct htc_endpoint *ep; @@ -1647,8 +1629,7 @@ static int ath6kl_htc_rx_process_packets(struct htc_target *target, ep = &target->endpoint[packet->endpoint]; /* process header for each of the recv packet */ - status = ath6kl_htc_rx_process_hdr(target, packet, lk_ahds, - n_lk_ahd); + status = htc_proc_rxhdr(target, packet, lk_ahds, n_lk_ahd); if (status) return status; @@ -1658,8 +1639,8 @@ static int ath6kl_htc_rx_process_packets(struct htc_target *target, * based on the lookahead. */ if (*n_lk_ahd > 0) - ath6kl_htc_rx_set_indicate(lk_ahds[0], - ep, packet); + set_rxpkt_indication_flag(lk_ahds[0], + ep, packet); } else /* * Packets in a bundle automatically have @@ -1668,20 +1649,20 @@ static int ath6kl_htc_rx_process_packets(struct htc_target *target, packet->info.rx.indicat_flags |= HTC_RX_FLAGS_INDICATE_MORE_PKTS; - ath6kl_htc_rx_update_stats(ep, *n_lk_ahd); + htc_update_rx_stats(ep, *n_lk_ahd); if (packet->info.rx.rx_flags & HTC_RX_PKT_PART_OF_BUNDLE) ep->ep_st.rx_bundl += 1; - ath6kl_htc_rx_complete(ep, packet); + do_rx_completion(ep, packet); } return status; } -static int ath6kl_htc_rx_fetch(struct htc_target *target, - struct list_head *rx_pktq, - struct list_head *comp_pktq) +static int htc_fetch_rxpkts(struct htc_target *target, + struct list_head *rx_pktq, + struct list_head *comp_pktq) { int fetched_pkts; bool part_bundle = false; @@ -1697,10 +1678,10 @@ static int ath6kl_htc_rx_fetch(struct htc_target *target, * bundle transfer and recv bundling is * allowed. */ - status = ath6kl_htc_rx_bundle(target, rx_pktq, - comp_pktq, - &fetched_pkts, - part_bundle); + status = htc_issue_rxpkt_bundle(target, rx_pktq, + comp_pktq, + &fetched_pkts, + part_bundle); if (status) return status; @@ -1729,8 +1710,7 @@ static int ath6kl_htc_rx_fetch(struct htc_target *target, HTC_RX_PKT_IGNORE_LOOKAHEAD; /* go fetch the packet */ - status = ath6kl_htc_rx_packet(target, packet, - packet->act_len); + status = dev_rx_pkt(target, packet, packet->act_len); if (status) return status; @@ -1784,9 +1764,9 @@ int ath6kl_htc_rxmsg_pending_handler(struct htc_target *target, * Try to allocate as many HTC RX packets indicated by the * look_aheads. */ - status = ath6kl_htc_rx_alloc(target, look_aheads, - num_look_ahead, endpoint, - &rx_pktq); + status = alloc_and_prep_rxpkts(target, look_aheads, + num_look_ahead, endpoint, + &rx_pktq); if (status) break; @@ -1801,15 +1781,14 @@ int ath6kl_htc_rxmsg_pending_handler(struct htc_target *target, num_look_ahead = 0; - status = ath6kl_htc_rx_fetch(target, &rx_pktq, &comp_pktq); + status = htc_fetch_rxpkts(target, &rx_pktq, &comp_pktq); if (!status) - ath6kl_htc_rx_chk_water_mark(endpoint); + chk_rx_water_mark(endpoint); /* Process fetched packets */ - status = ath6kl_htc_rx_process_packets(target, &comp_pktq, - look_aheads, - &num_look_ahead); + status = htc_proc_fetched_rxpkts(target, &comp_pktq, + look_aheads, &num_look_ahead); if (!num_look_ahead || status) break; @@ -1902,14 +1881,14 @@ static struct htc_packet *htc_wait_for_ctrl_msg(struct htc_target *target) packet->completion = NULL; /* get the message from the device, this will block */ - if (ath6kl_htc_rx_packet(target, packet, packet->act_len)) + if (dev_rx_pkt(target, packet, packet->act_len)) goto fail_ctrl_rx; /* process receive header */ - packet->status = ath6kl_htc_rx_process_hdr(target, packet, NULL, NULL); + packet->status = htc_proc_rxhdr(target, packet, NULL, NULL); if (packet->status) { - ath6kl_err("htc_wait_for_ctrl_msg, ath6kl_htc_rx_process_hdr failed (status = %d)\n", + ath6kl_err("htc_wait_for_ctrl_msg, htc_proc_rxhdr failed (status = %d)\n", packet->status); goto fail_ctrl_rx; } @@ -1956,7 +1935,7 @@ int ath6kl_htc_add_rxbuf_multiple(struct htc_target *target, list_for_each_entry_safe(packet, tmp_pkt, pkt_queue, list) { packet->status = -ECANCELED; list_del(&packet->list); - ath6kl_htc_rx_complete(endpoint, packet); + do_rx_completion(endpoint, packet); } return status; @@ -2055,8 +2034,8 @@ int ath6kl_htc_conn_service(struct htc_target *target, /* we want synchronous operation */ tx_pkt->completion = NULL; - ath6kl_htc_tx_prep_pkt(tx_pkt, 0, 0, 0); - status = ath6kl_htc_tx_issue(target, tx_pkt); + htc_prep_send_pkt(tx_pkt, 0, 0, 0); + status = htc_issue_send(target, tx_pkt); if (status) goto fail_tx; diff --git a/trunk/drivers/net/wireless/ath/ath6kl/init.c b/trunk/drivers/net/wireless/ath/ath6kl/init.c index c1d2366704b5..9d10322eac41 100644 --- a/trunk/drivers/net/wireless/ath/ath6kl/init.c +++ b/trunk/drivers/net/wireless/ath/ath6kl/init.c @@ -15,8 +15,6 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include -#include #include #include "core.h" #include "cfg80211.h" @@ -25,10 +23,8 @@ #include "hif-ops.h" unsigned int debug_mask; -static unsigned int testmode; module_param(debug_mask, uint, 0644); -module_param(testmode, uint, 0644); /* * Include definitions here that can be used to tune the WLAN module @@ -57,6 +53,12 @@ module_param(testmode, uint, 0644); #define CONFIG_AR600x_DEBUG_UART_TX_PIN 8 +enum addr_type { + DATASET_PATCH_ADDR, + APP_LOAD_ADDR, + APP_START_OVERRIDE_ADDR, +}; + #define ATH6KL_DATA_OFFSET 64 struct sk_buff *ath6kl_buf_alloc(int size) { @@ -65,7 +67,7 @@ struct sk_buff *ath6kl_buf_alloc(int size) /* Add chacheline space at front and back of buffer */ reserved = (2 * L1_CACHE_BYTES) + ATH6KL_DATA_OFFSET + - sizeof(struct htc_packet) + ATH6KL_HTC_ALIGN_BYTES; + sizeof(struct htc_packet); skb = dev_alloc_skb(size + reserved); if (skb) @@ -83,7 +85,7 @@ void ath6kl_init_profile_info(struct ath6kl *ar) ar->prwise_crypto = NONE_CRYPT; ar->prwise_crypto_len = 0; ar->grp_crypto = NONE_CRYPT; - ar->grp_crypto_len = 0; + ar->grp_crpto_len = 0; memset(ar->wep_key_list, 0, sizeof(ar->wep_key_list)); memset(ar->req_bssid, 0, sizeof(ar->req_bssid)); memset(ar->bssid, 0, sizeof(ar->bssid)); @@ -106,6 +108,17 @@ static u8 ath6kl_get_fw_iftype(struct ath6kl *ar) } } +static inline u32 ath6kl_get_hi_item_addr(struct ath6kl *ar, + u32 item_offset) +{ + u32 addr = 0; + + if (ar->target_type == TARGET_TYPE_AR6003) + addr = ATH6KL_HI_START_ADDR + item_offset; + + return addr; +} + static int ath6kl_set_host_app_area(struct ath6kl *ar) { u32 address, data; @@ -114,15 +127,16 @@ static int ath6kl_set_host_app_area(struct ath6kl *ar) /* Fetch the address of the host_app_area_s * instance in the host interest area */ address = ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_app_host_interest)); - address = TARG_VTOP(ar->target_type, address); + address = TARG_VTOP(address); - if (ath6kl_diag_read32(ar, address, &data)) + if (ath6kl_read_reg_diag(ar, &address, &data)) return -EIO; - address = TARG_VTOP(ar->target_type, data); + address = TARG_VTOP(data); host_app_area.wmi_protocol_ver = WMI_PROTOCOL_VERSION; - if (ath6kl_diag_write(ar, address, (u8 *) &host_app_area, - sizeof(struct host_app_area))) + if (ath6kl_access_datadiag(ar, address, + (u8 *)&host_app_area, + sizeof(struct host_app_area), false)) return -EIO; return 0; @@ -276,7 +290,6 @@ static void ath6kl_init_control_info(struct ath6kl *ar) memset(&ar->sc_params, 0, sizeof(ar->sc_params)); ar->sc_params.short_scan_ratio = WMI_SHORTSCANRATIO_DEFAULT; ar->sc_params.scan_ctrl_flags = DEFAULT_SCAN_CTRL_FLAGS; - ar->lrssi_roam_threshold = DEF_LRSSI_ROAM_THRESHOLD; memset((u8 *)ar->sta_list, 0, AP_MAX_NUM_STA * sizeof(struct ath6kl_sta)); @@ -357,10 +370,10 @@ static void ath6kl_dump_target_assert_info(struct ath6kl *ar) /* the reg dump pointer is copied to the host interest area */ address = ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_failure_state)); - address = TARG_VTOP(ar->target_type, address); + address = TARG_VTOP(address); /* read RAM location through diagnostic window */ - status = ath6kl_diag_read32(ar, address, ®dump_loc); + status = ath6kl_read_reg_diag(ar, &address, ®dump_loc); if (status || !regdump_loc) { ath6kl_err("failed to get ptr to register dump area\n"); @@ -369,11 +382,15 @@ static void ath6kl_dump_target_assert_info(struct ath6kl *ar) ath6kl_dbg(ATH6KL_DBG_TRC, "location of register dump data: 0x%X\n", regdump_loc); - regdump_loc = TARG_VTOP(ar->target_type, regdump_loc); + + regdump_loc = TARG_VTOP(regdump_loc); /* fetch register dump data */ - status = ath6kl_diag_read(ar, regdump_loc, (u8 *)®dump_val[0], - REG_DUMP_COUNT_AR6003 * (sizeof(u32))); + status = ath6kl_access_datadiag(ar, + regdump_loc, + (u8 *)®dump_val[0], + REG_DUMP_COUNT_AR6003 * (sizeof(u32)), + true); if (status) { ath6kl_err("failed to get register dump\n"); @@ -399,7 +416,6 @@ void ath6kl_target_failure(struct ath6kl *ar) static int ath6kl_target_config_wlan_params(struct ath6kl *ar) { int status = 0; - int ret; /* * Configure the device for rx dot11 header rules. "0,0" are the @@ -444,28 +460,6 @@ static int ath6kl_target_config_wlan_params(struct ath6kl *ar) status = -EIO; } - if (ar->p2p) { - ret = ath6kl_wmi_info_req_cmd(ar->wmi, - P2P_FLAG_CAPABILITIES_REQ | - P2P_FLAG_MACADDR_REQ | - P2P_FLAG_HMODEL_REQ); - if (ret) { - ath6kl_dbg(ATH6KL_DBG_TRC, "failed to request P2P " - "capabilities (%d) - assuming P2P not " - "supported\n", ret); - ar->p2p = 0; - } - } - - if (ar->p2p) { - /* Enable Probe Request reporting for P2P */ - ret = ath6kl_wmi_probe_report_req_cmd(ar->wmi, true); - if (ret) { - ath6kl_dbg(ATH6KL_DBG_TRC, "failed to enable Probe " - "Request reporting (%d)\n", ret); - } - } - return status; } @@ -501,10 +495,6 @@ int ath6kl_configure_target(struct ath6kl *ar) param |= (1 << HI_OPTION_NUM_DEV_SHIFT); param |= (fw_iftype << HI_OPTION_FW_MODE_SHIFT); - if (ar->p2p && fw_iftype == HI_OPTION_FW_MODE_BSS_STA) { - param |= HI_OPTION_FW_SUBMODE_P2PDEV << - HI_OPTION_FW_SUBMODE_SHIFT; - } param |= (0 << HI_OPTION_MAC_ADDR_METHOD_SHIFT); param |= (0 << HI_OPTION_FW_BRIDGE_SHIFT); @@ -528,21 +518,29 @@ int ath6kl_configure_target(struct ath6kl *ar) * but possible in theory. */ - param = ar->hw.board_ext_data_addr; - ram_reserved_size = ar->hw.reserved_ram_size; - - if (ath6kl_bmi_write(ar, ath6kl_get_hi_item_addr(ar, - HI_ITEM(hi_board_ext_data)), - (u8 *)¶m, 4) != 0) { - ath6kl_err("bmi_write_memory for hi_board_ext_data failed\n"); - return -EIO; - } + if (ar->target_type == TARGET_TYPE_AR6003) { + if (ar->version.target_ver == AR6003_REV2_VERSION) { + param = AR6003_REV2_BOARD_EXT_DATA_ADDRESS; + ram_reserved_size = AR6003_REV2_RAM_RESERVE_SIZE; + } else { + param = AR6003_REV3_BOARD_EXT_DATA_ADDRESS; + ram_reserved_size = AR6003_REV3_RAM_RESERVE_SIZE; + } - if (ath6kl_bmi_write(ar, ath6kl_get_hi_item_addr(ar, - HI_ITEM(hi_end_ram_reserve_sz)), - (u8 *)&ram_reserved_size, 4) != 0) { - ath6kl_err("bmi_write_memory for hi_end_ram_reserve_sz failed\n"); - return -EIO; + if (ath6kl_bmi_write(ar, + ath6kl_get_hi_item_addr(ar, + HI_ITEM(hi_board_ext_data)), + (u8 *)¶m, 4) != 0) { + ath6kl_err("bmi_write_memory for hi_board_ext_data failed\n"); + return -EIO; + } + if (ath6kl_bmi_write(ar, + ath6kl_get_hi_item_addr(ar, + HI_ITEM(hi_end_ram_reserve_sz)), + (u8 *)&ram_reserved_size, 4) != 0) { + ath6kl_err("bmi_write_memory for hi_end_ram_reserve_sz failed\n"); + return -EIO; + } } /* set the block size for the target */ @@ -570,12 +568,6 @@ struct ath6kl *ath6kl_core_alloc(struct device *sdev) ar->wdev = wdev; wdev->iftype = NL80211_IFTYPE_STATION; - if (ath6kl_debug_init(ar)) { - ath6kl_err("Failed to initialize debugfs\n"); - ath6kl_cfg80211_deinit(ar); - return NULL; - } - dev = alloc_netdev(0, "wlan%d", ether_setup); if (!dev) { ath6kl_err("no memory for network device instance\n"); @@ -587,6 +579,7 @@ struct ath6kl *ath6kl_core_alloc(struct device *sdev) SET_NETDEV_DEV(dev, wiphy_dev(wdev->wiphy)); wdev->netdev = dev; ar->sme_state = SME_DISCONNECTED; + ar->auto_auth_stage = AUTH_IDLE; init_netdev(dev); @@ -618,6 +611,29 @@ int ath6kl_unavail_ev(struct ath6kl *ar) } /* firmware upload */ +static u32 ath6kl_get_load_address(u32 target_ver, enum addr_type type) +{ + WARN_ON(target_ver != AR6003_REV2_VERSION && + target_ver != AR6003_REV3_VERSION); + + switch (type) { + case DATASET_PATCH_ADDR: + return (target_ver == AR6003_REV2_VERSION) ? + AR6003_REV2_DATASET_PATCH_ADDRESS : + AR6003_REV3_DATASET_PATCH_ADDRESS; + case APP_LOAD_ADDR: + return (target_ver == AR6003_REV2_VERSION) ? + AR6003_REV2_APP_LOAD_ADDRESS : + 0x1234; + case APP_START_OVERRIDE_ADDR: + return (target_ver == AR6003_REV2_VERSION) ? + AR6003_REV2_APP_START_OVERRIDE : + AR6003_REV3_APP_START_OVERRIDE; + default: + return 0; + } +} + static int ath6kl_get_fw(struct ath6kl *ar, const char *filename, u8 **fw, size_t *fw_len) { @@ -639,79 +655,15 @@ static int ath6kl_get_fw(struct ath6kl *ar, const char *filename, return ret; } -#ifdef CONFIG_OF -static const char *get_target_ver_dir(const struct ath6kl *ar) -{ - switch (ar->version.target_ver) { - case AR6003_REV1_VERSION: - return "ath6k/AR6003/hw1.0"; - case AR6003_REV2_VERSION: - return "ath6k/AR6003/hw2.0"; - case AR6003_REV3_VERSION: - return "ath6k/AR6003/hw2.1.1"; - } - ath6kl_warn("%s: unsupported target version 0x%x.\n", __func__, - ar->version.target_ver); - return NULL; -} - -/* - * Check the device tree for a board-id and use it to construct - * the pathname to the firmware file. Used (for now) to find a - * fallback to the "bdata.bin" file--typically a symlink to the - * appropriate board-specific file. - */ -static bool check_device_tree(struct ath6kl *ar) -{ - static const char *board_id_prop = "atheros,board-id"; - struct device_node *node; - char board_filename[64]; - const char *board_id; - int ret; - - for_each_compatible_node(node, NULL, "atheros,ath6kl") { - board_id = of_get_property(node, board_id_prop, NULL); - if (board_id == NULL) { - ath6kl_warn("No \"%s\" property on %s node.\n", - board_id_prop, node->name); - continue; - } - snprintf(board_filename, sizeof(board_filename), - "%s/bdata.%s.bin", get_target_ver_dir(ar), board_id); - - ret = ath6kl_get_fw(ar, board_filename, &ar->fw_board, - &ar->fw_board_len); - if (ret) { - ath6kl_err("Failed to get DT board file %s: %d\n", - board_filename, ret); - continue; - } - return true; - } - return false; -} -#else -static bool check_device_tree(struct ath6kl *ar) -{ - return false; -} -#endif /* CONFIG_OF */ - static int ath6kl_fetch_board_file(struct ath6kl *ar) { const char *filename; int ret; - if (ar->fw_board != NULL) - return 0; - switch (ar->version.target_ver) { case AR6003_REV2_VERSION: filename = AR6003_REV2_BOARD_DATA_FILE; break; - case AR6004_REV1_VERSION: - filename = AR6004_REV1_BOARD_DATA_FILE; - break; default: filename = AR6003_REV3_BOARD_DATA_FILE; break; @@ -724,11 +676,6 @@ static int ath6kl_fetch_board_file(struct ath6kl *ar) return 0; } - if (check_device_tree(ar)) { - /* got board file from device tree */ - return 0; - } - /* there was no proper board file, try to use default instead */ ath6kl_warn("Failed to get board file %s (%d), trying to find default board file.\n", filename, ret); @@ -737,9 +684,6 @@ static int ath6kl_fetch_board_file(struct ath6kl *ar) case AR6003_REV2_VERSION: filename = AR6003_REV2_DEFAULT_BOARD_DATA_FILE; break; - case AR6004_REV1_VERSION: - filename = AR6004_REV1_DEFAULT_BOARD_DATA_FILE; - break; default: filename = AR6003_REV3_DEFAULT_BOARD_DATA_FILE; break; @@ -759,384 +703,47 @@ static int ath6kl_fetch_board_file(struct ath6kl *ar) return 0; } -static int ath6kl_fetch_otp_file(struct ath6kl *ar) -{ - const char *filename; - int ret; - - if (ar->fw_otp != NULL) - return 0; - - switch (ar->version.target_ver) { - case AR6003_REV2_VERSION: - filename = AR6003_REV2_OTP_FILE; - break; - case AR6004_REV1_VERSION: - ath6kl_dbg(ATH6KL_DBG_TRC, "AR6004 doesn't need OTP file\n"); - return 0; - break; - default: - filename = AR6003_REV3_OTP_FILE; - break; - } - - ret = ath6kl_get_fw(ar, filename, &ar->fw_otp, - &ar->fw_otp_len); - if (ret) { - ath6kl_err("Failed to get OTP file %s: %d\n", - filename, ret); - return ret; - } - - return 0; -} - -static int ath6kl_fetch_fw_file(struct ath6kl *ar) -{ - const char *filename; - int ret; - - if (ar->fw != NULL) - return 0; - - if (testmode) { - switch (ar->version.target_ver) { - case AR6003_REV2_VERSION: - filename = AR6003_REV2_TCMD_FIRMWARE_FILE; - break; - case AR6003_REV3_VERSION: - filename = AR6003_REV3_TCMD_FIRMWARE_FILE; - break; - case AR6004_REV1_VERSION: - ath6kl_warn("testmode not supported with ar6004\n"); - return -EOPNOTSUPP; - default: - ath6kl_warn("unknown target version: 0x%x\n", - ar->version.target_ver); - return -EINVAL; - } - - set_bit(TESTMODE, &ar->flag); - - goto get_fw; - } - - switch (ar->version.target_ver) { - case AR6003_REV2_VERSION: - filename = AR6003_REV2_FIRMWARE_FILE; - break; - case AR6004_REV1_VERSION: - filename = AR6004_REV1_FIRMWARE_FILE; - break; - default: - filename = AR6003_REV3_FIRMWARE_FILE; - break; - } - -get_fw: - ret = ath6kl_get_fw(ar, filename, &ar->fw, &ar->fw_len); - if (ret) { - ath6kl_err("Failed to get firmware file %s: %d\n", - filename, ret); - return ret; - } - - return 0; -} - -static int ath6kl_fetch_patch_file(struct ath6kl *ar) -{ - const char *filename; - int ret; - - switch (ar->version.target_ver) { - case AR6003_REV2_VERSION: - filename = AR6003_REV2_PATCH_FILE; - break; - case AR6004_REV1_VERSION: - /* FIXME: implement for AR6004 */ - return 0; - break; - default: - filename = AR6003_REV3_PATCH_FILE; - break; - } - - if (ar->fw_patch == NULL) { - ret = ath6kl_get_fw(ar, filename, &ar->fw_patch, - &ar->fw_patch_len); - if (ret) { - ath6kl_err("Failed to get patch file %s: %d\n", - filename, ret); - return ret; - } - } - - return 0; -} - -static int ath6kl_fetch_fw_api1(struct ath6kl *ar) -{ - int ret; - - ret = ath6kl_fetch_otp_file(ar); - if (ret) - return ret; - - ret = ath6kl_fetch_fw_file(ar); - if (ret) - return ret; - - ret = ath6kl_fetch_patch_file(ar); - if (ret) - return ret; - - return 0; -} - -static int ath6kl_fetch_fw_api2(struct ath6kl *ar) -{ - size_t magic_len, len, ie_len; - const struct firmware *fw; - struct ath6kl_fw_ie *hdr; - const char *filename; - const u8 *data; - int ret, ie_id, i, index, bit; - __le32 *val; - - switch (ar->version.target_ver) { - case AR6003_REV2_VERSION: - filename = AR6003_REV2_FIRMWARE_2_FILE; - break; - case AR6003_REV3_VERSION: - filename = AR6003_REV3_FIRMWARE_2_FILE; - break; - case AR6004_REV1_VERSION: - filename = AR6004_REV1_FIRMWARE_2_FILE; - break; - default: - return -EOPNOTSUPP; - } - - ret = request_firmware(&fw, filename, ar->dev); - if (ret) - return ret; - - data = fw->data; - len = fw->size; - - /* magic also includes the null byte, check that as well */ - magic_len = strlen(ATH6KL_FIRMWARE_MAGIC) + 1; - - if (len < magic_len) { - ret = -EINVAL; - goto out; - } - - if (memcmp(data, ATH6KL_FIRMWARE_MAGIC, magic_len) != 0) { - ret = -EINVAL; - goto out; - } - - len -= magic_len; - data += magic_len; - - /* loop elements */ - while (len > sizeof(struct ath6kl_fw_ie)) { - /* hdr is unaligned! */ - hdr = (struct ath6kl_fw_ie *) data; - - ie_id = le32_to_cpup(&hdr->id); - ie_len = le32_to_cpup(&hdr->len); - - len -= sizeof(*hdr); - data += sizeof(*hdr); - - if (len < ie_len) { - ret = -EINVAL; - goto out; - } - - switch (ie_id) { - case ATH6KL_FW_IE_OTP_IMAGE: - ath6kl_dbg(ATH6KL_DBG_BOOT, "found otp image ie (%zd B)\n", - ie_len); - - ar->fw_otp = kmemdup(data, ie_len, GFP_KERNEL); - - if (ar->fw_otp == NULL) { - ret = -ENOMEM; - goto out; - } - - ar->fw_otp_len = ie_len; - break; - case ATH6KL_FW_IE_FW_IMAGE: - ath6kl_dbg(ATH6KL_DBG_BOOT, "found fw image ie (%zd B)\n", - ie_len); - - ar->fw = kmemdup(data, ie_len, GFP_KERNEL); - - if (ar->fw == NULL) { - ret = -ENOMEM; - goto out; - } - - ar->fw_len = ie_len; - break; - case ATH6KL_FW_IE_PATCH_IMAGE: - ath6kl_dbg(ATH6KL_DBG_BOOT, "found patch image ie (%zd B)\n", - ie_len); - - ar->fw_patch = kmemdup(data, ie_len, GFP_KERNEL); - - if (ar->fw_patch == NULL) { - ret = -ENOMEM; - goto out; - } - - ar->fw_patch_len = ie_len; - break; - case ATH6KL_FW_IE_RESERVED_RAM_SIZE: - val = (__le32 *) data; - ar->hw.reserved_ram_size = le32_to_cpup(val); - - ath6kl_dbg(ATH6KL_DBG_BOOT, - "found reserved ram size ie 0x%d\n", - ar->hw.reserved_ram_size); - break; - case ATH6KL_FW_IE_CAPABILITIES: - ath6kl_dbg(ATH6KL_DBG_BOOT, - "found firmware capabilities ie (%zd B)\n", - ie_len); - - for (i = 0; i < ATH6KL_FW_CAPABILITY_MAX; i++) { - index = ALIGN(i, 8) / 8; - bit = i % 8; - - if (data[index] & (1 << bit)) - __set_bit(i, ar->fw_capabilities); - } - - ath6kl_dbg_dump(ATH6KL_DBG_BOOT, "capabilities", "", - ar->fw_capabilities, - sizeof(ar->fw_capabilities)); - break; - case ATH6KL_FW_IE_PATCH_ADDR: - if (ie_len != sizeof(*val)) - break; - - val = (__le32 *) data; - ar->hw.dataset_patch_addr = le32_to_cpup(val); - - ath6kl_dbg(ATH6KL_DBG_BOOT, - "found patch address ie 0x%d\n", - ar->hw.dataset_patch_addr); - break; - default: - ath6kl_dbg(ATH6KL_DBG_BOOT, "Unknown fw ie: %u\n", - le32_to_cpup(&hdr->id)); - break; - } - - len -= ie_len; - data += ie_len; - }; - - ret = 0; -out: - release_firmware(fw); - - return ret; -} - -static int ath6kl_fetch_firmwares(struct ath6kl *ar) -{ - int ret; - - ret = ath6kl_fetch_board_file(ar); - if (ret) - return ret; - - ret = ath6kl_fetch_fw_api2(ar); - if (ret == 0) { - ath6kl_dbg(ATH6KL_DBG_BOOT, "using fw api 2\n"); - return 0; - } - - ret = ath6kl_fetch_fw_api1(ar); - if (ret) - return ret; - - ath6kl_dbg(ATH6KL_DBG_BOOT, "using fw api 1\n"); - - return 0; -} static int ath6kl_upload_board_file(struct ath6kl *ar) { u32 board_address, board_ext_address, param; - u32 board_data_size, board_ext_data_size; int ret; - if (WARN_ON(ar->fw_board == NULL)) - return -ENOENT; - - /* - * Determine where in Target RAM to write Board Data. - * For AR6004, host determine Target RAM address for - * writing board data. - */ - if (ar->target_type == TARGET_TYPE_AR6004) { - board_address = AR6004_REV1_BOARD_DATA_ADDRESS; - ath6kl_bmi_write(ar, - ath6kl_get_hi_item_addr(ar, - HI_ITEM(hi_board_data)), - (u8 *) &board_address, 4); - } else { - ath6kl_bmi_read(ar, - ath6kl_get_hi_item_addr(ar, - HI_ITEM(hi_board_data)), - (u8 *) &board_address, 4); + if (ar->fw_board == NULL) { + ret = ath6kl_fetch_board_file(ar); + if (ret) + return ret; } + /* Determine where in Target RAM to write Board Data */ + ath6kl_bmi_read(ar, + ath6kl_get_hi_item_addr(ar, + HI_ITEM(hi_board_data)), + (u8 *) &board_address, 4); + ath6kl_dbg(ATH6KL_DBG_TRC, "board data download addr: 0x%x\n", + board_address); + /* determine where in target ram to write extended board data */ ath6kl_bmi_read(ar, ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_board_ext_data)), (u8 *) &board_ext_address, 4); + ath6kl_dbg(ATH6KL_DBG_TRC, "board file download addr: 0x%x\n", + board_ext_address); + if (board_ext_address == 0) { ath6kl_err("Failed to get board file target address.\n"); return -EINVAL; } - switch (ar->target_type) { - case TARGET_TYPE_AR6003: - board_data_size = AR6003_BOARD_DATA_SZ; - board_ext_data_size = AR6003_BOARD_EXT_DATA_SZ; - break; - case TARGET_TYPE_AR6004: - board_data_size = AR6004_BOARD_DATA_SZ; - board_ext_data_size = AR6004_BOARD_EXT_DATA_SZ; - break; - default: - WARN_ON(1); - return -EINVAL; - break; - } - - if (ar->fw_board_len == (board_data_size + - board_ext_data_size)) { - + if (ar->fw_board_len == (AR6003_BOARD_DATA_SZ + + AR6003_BOARD_EXT_DATA_SZ)) { /* write extended board data */ - ath6kl_dbg(ATH6KL_DBG_BOOT, - "writing extended board data to 0x%x (%d B)\n", - board_ext_address, board_ext_data_size); - ret = ath6kl_bmi_write(ar, board_ext_address, - ar->fw_board + board_data_size, - board_ext_data_size); + ar->fw_board + AR6003_BOARD_DATA_SZ, + AR6003_BOARD_EXT_DATA_SZ); + if (ret) { ath6kl_err("Failed to write extended board data: %d\n", ret); @@ -1144,25 +751,21 @@ static int ath6kl_upload_board_file(struct ath6kl *ar) } /* record that extended board data is initialized */ - param = (board_ext_data_size << 16) | 1; - + param = (AR6003_BOARD_EXT_DATA_SZ << 16) | 1; ath6kl_bmi_write(ar, ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_board_ext_data_config)), (unsigned char *) ¶m, 4); } - if (ar->fw_board_len < board_data_size) { + if (ar->fw_board_len < AR6003_BOARD_DATA_SZ) { ath6kl_err("Too small board file: %zu\n", ar->fw_board_len); ret = -EINVAL; return ret; } - ath6kl_dbg(ATH6KL_DBG_BOOT, "writing board file to 0x%x (%d B)\n", - board_address, board_data_size); - ret = ath6kl_bmi_write(ar, board_address, ar->fw_board, - board_data_size); + AR6003_BOARD_DATA_SZ); if (ret) { ath6kl_err("Board file bmi write failed: %d\n", ret); @@ -1181,16 +784,31 @@ static int ath6kl_upload_board_file(struct ath6kl *ar) static int ath6kl_upload_otp(struct ath6kl *ar) { + const char *filename; u32 address, param; int ret; - if (WARN_ON(ar->fw_otp == NULL)) - return -ENOENT; + switch (ar->version.target_ver) { + case AR6003_REV2_VERSION: + filename = AR6003_REV2_OTP_FILE; + break; + default: + filename = AR6003_REV3_OTP_FILE; + break; + } - address = ar->hw.app_load_addr; + if (ar->fw_otp == NULL) { + ret = ath6kl_get_fw(ar, filename, &ar->fw_otp, + &ar->fw_otp_len); + if (ret) { + ath6kl_err("Failed to get OTP file %s: %d\n", + filename, ret); + return ret; + } + } - ath6kl_dbg(ATH6KL_DBG_BOOT, "writing otp to 0x%x (%zd B)\n", address, - ar->fw_otp_len); + address = ath6kl_get_load_address(ar->version.target_ver, + APP_LOAD_ADDR); ret = ath6kl_bmi_fast_download(ar, address, ar->fw_otp, ar->fw_otp_len); @@ -1199,25 +817,10 @@ static int ath6kl_upload_otp(struct ath6kl *ar) return ret; } - /* read firmware start address */ - ret = ath6kl_bmi_read(ar, - ath6kl_get_hi_item_addr(ar, - HI_ITEM(hi_app_start)), - (u8 *) &address, sizeof(address)); - - if (ret) { - ath6kl_err("Failed to read hi_app_start: %d\n", ret); - return ret; - } - - ar->hw.app_start_override_addr = address; - - ath6kl_dbg(ATH6KL_DBG_BOOT, "app_start_override_addr 0x%x\n", - ar->hw.app_start_override_addr); - /* execute the OTP code */ - ath6kl_dbg(ATH6KL_DBG_BOOT, "executing OTP at 0x%x\n", address); param = 0; + address = ath6kl_get_load_address(ar->version.target_ver, + APP_START_OVERRIDE_ADDR); ath6kl_bmi_execute(ar, address, ¶m); return ret; @@ -1225,16 +828,30 @@ static int ath6kl_upload_otp(struct ath6kl *ar) static int ath6kl_upload_firmware(struct ath6kl *ar) { + const char *filename; u32 address; int ret; - if (WARN_ON(ar->fw == NULL)) - return -ENOENT; + switch (ar->version.target_ver) { + case AR6003_REV2_VERSION: + filename = AR6003_REV2_FIRMWARE_FILE; + break; + default: + filename = AR6003_REV3_FIRMWARE_FILE; + break; + } - address = ar->hw.app_load_addr; + if (ar->fw == NULL) { + ret = ath6kl_get_fw(ar, filename, &ar->fw, &ar->fw_len); + if (ret) { + ath6kl_err("Failed to get firmware file %s: %d\n", + filename, ret); + return ret; + } + } - ath6kl_dbg(ATH6KL_DBG_BOOT, "writing firmware to 0x%x (%zd B)\n", - address, ar->fw_len); + address = ath6kl_get_load_address(ar->version.target_ver, + APP_LOAD_ADDR); ret = ath6kl_bmi_fast_download(ar, address, ar->fw, ar->fw_len); @@ -1243,29 +860,41 @@ static int ath6kl_upload_firmware(struct ath6kl *ar) return ret; } - /* - * Set starting address for firmware - * Don't need to setup app_start override addr on AR6004 - */ - if (ar->target_type != TARGET_TYPE_AR6004) { - address = ar->hw.app_start_override_addr; - ath6kl_bmi_set_app_start(ar, address); - } + /* Set starting address for firmware */ + address = ath6kl_get_load_address(ar->version.target_ver, + APP_START_OVERRIDE_ADDR); + ath6kl_bmi_set_app_start(ar, address); + return ret; } static int ath6kl_upload_patch(struct ath6kl *ar) { + const char *filename; u32 address, param; int ret; - if (WARN_ON(ar->fw_patch == NULL)) - return -ENOENT; + switch (ar->version.target_ver) { + case AR6003_REV2_VERSION: + filename = AR6003_REV2_PATCH_FILE; + break; + default: + filename = AR6003_REV3_PATCH_FILE; + break; + } - address = ar->hw.dataset_patch_addr; + if (ar->fw_patch == NULL) { + ret = ath6kl_get_fw(ar, filename, &ar->fw_patch, + &ar->fw_patch_len); + if (ret) { + ath6kl_err("Failed to get patch file %s: %d\n", + filename, ret); + return ret; + } + } - ath6kl_dbg(ATH6KL_DBG_BOOT, "writing patch to 0x%x (%zd B)\n", - address, ar->fw_patch_len); + address = ath6kl_get_load_address(ar->version.target_ver, + DATASET_PATCH_ADDR); ret = ath6kl_bmi_write(ar, address, ar->fw_patch, ar->fw_patch_len); if (ret) { @@ -1287,8 +916,7 @@ static int ath6kl_init_upload(struct ath6kl *ar) u32 param, options, sleep, address; int status = 0; - if (ar->target_type != TARGET_TYPE_AR6003 && - ar->target_type != TARGET_TYPE_AR6004) + if (ar->target_type != TARGET_TYPE_AR6003) return -EINVAL; /* temporarily disable system sleep */ @@ -1320,22 +948,18 @@ static int ath6kl_init_upload(struct ath6kl *ar) options, sleep); /* program analog PLL register */ - /* no need to control 40/44MHz clock on AR6004 */ - if (ar->target_type != TARGET_TYPE_AR6004) { - status = ath6kl_bmi_reg_write(ar, ATH6KL_ANALOG_PLL_REGISTER, - 0xF9104001); - - if (status) - return status; + status = ath6kl_bmi_reg_write(ar, ATH6KL_ANALOG_PLL_REGISTER, + 0xF9104001); + if (status) + return status; - /* Run at 80/88MHz by default */ - param = SM(CPU_CLOCK_STANDARD, 1); + /* Run at 80/88MHz by default */ + param = SM(CPU_CLOCK_STANDARD, 1); - address = RTC_BASE_ADDRESS + CPU_CLOCK_ADDRESS; - status = ath6kl_bmi_reg_write(ar, address, param); - if (status) - return status; - } + address = RTC_BASE_ADDRESS + CPU_CLOCK_ADDRESS; + status = ath6kl_bmi_reg_write(ar, address, param); + if (status) + return status; param = 0; address = RTC_BASE_ADDRESS + LPO_CAL_ADDRESS; @@ -1412,45 +1036,6 @@ static int ath6kl_init_upload(struct ath6kl *ar) return status; } -static int ath6kl_init_hw_params(struct ath6kl *ar) -{ - switch (ar->version.target_ver) { - case AR6003_REV2_VERSION: - ar->hw.dataset_patch_addr = AR6003_REV2_DATASET_PATCH_ADDRESS; - ar->hw.app_load_addr = AR6003_REV2_APP_LOAD_ADDRESS; - ar->hw.board_ext_data_addr = AR6003_REV2_BOARD_EXT_DATA_ADDRESS; - ar->hw.reserved_ram_size = AR6003_REV2_RAM_RESERVE_SIZE; - break; - case AR6003_REV3_VERSION: - ar->hw.dataset_patch_addr = AR6003_REV3_DATASET_PATCH_ADDRESS; - ar->hw.app_load_addr = 0x1234; - ar->hw.board_ext_data_addr = AR6003_REV3_BOARD_EXT_DATA_ADDRESS; - ar->hw.reserved_ram_size = AR6003_REV3_RAM_RESERVE_SIZE; - break; - case AR6004_REV1_VERSION: - ar->hw.dataset_patch_addr = AR6003_REV2_DATASET_PATCH_ADDRESS; - ar->hw.app_load_addr = AR6003_REV3_APP_LOAD_ADDRESS; - ar->hw.board_ext_data_addr = AR6004_REV1_BOARD_EXT_DATA_ADDRESS; - ar->hw.reserved_ram_size = AR6004_REV1_RAM_RESERVE_SIZE; - break; - default: - ath6kl_err("Unsupported hardware version: 0x%x\n", - ar->version.target_ver); - return -EINVAL; - } - - ath6kl_dbg(ATH6KL_DBG_BOOT, - "target_ver 0x%x target_type 0x%x dataset_patch 0x%x app_load_addr 0x%x\n", - ar->version.target_ver, ar->target_type, - ar->hw.dataset_patch_addr, ar->hw.app_load_addr); - ath6kl_dbg(ATH6KL_DBG_BOOT, - "app_start_override_addr 0x%x board_ext_data_addr 0x%x reserved_ram_size 0x%x", - ar->hw.app_start_override_addr, ar->hw.board_ext_data_addr, - ar->hw.reserved_ram_size); - - return 0; -} - static int ath6kl_init(struct net_device *dev) { struct ath6kl *ar = ath6kl_priv(dev); @@ -1477,6 +1062,8 @@ static int ath6kl_init(struct net_device *dev) ath6kl_dbg(ATH6KL_DBG_TRC, "%s: got wmi @ 0x%p.\n", __func__, ar->wmi); + wlan_node_table_init(&ar->scan_table); + /* * The reason we have to wait for the target here is that the * driver layer has to init BMI in order to set the host block @@ -1524,8 +1111,6 @@ static int ath6kl_init(struct net_device *dev) &ar->flag), WMI_TIMEOUT); - ath6kl_dbg(ATH6KL_DBG_BOOT, "firmware booted\n"); - if (ar->version.abi_ver != ATH6KL_ABI_VERSION) { ath6kl_err("abi version mismatch: host(0x%x), target(0x%x)\n", ATH6KL_ABI_VERSION, ar->version.abi_ver); @@ -1548,8 +1133,6 @@ static int ath6kl_init(struct net_device *dev) ar->conf_flags = ATH6KL_CONF_IGNORE_ERP_BARKER | ATH6KL_CONF_ENABLE_11N | ATH6KL_CONF_ENABLE_TX_BURST; - ar->wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM; - status = ath6kl_target_config_wlan_params(ar); if (!status) goto ath6kl_init_done; @@ -1562,6 +1145,7 @@ static int ath6kl_init(struct net_device *dev) err_cleanup_scatter: ath6kl_hif_cleanup_scatter(ar); err_node_cleanup: + wlan_node_table_cleanup(&ar->scan_table); ath6kl_wmi_shutdown(ar->wmi); clear_bit(WMI_ENABLED, &ar->flag); ar->wmi = NULL; @@ -1591,10 +1175,6 @@ int ath6kl_core_init(struct ath6kl *ar) ar->target_type = le32_to_cpu(targ_info.type); ar->wdev->wiphy->hw_version = le32_to_cpu(targ_info.version); - ret = ath6kl_init_hw_params(ar); - if (ret) - goto err_bmi_cleanup; - ret = ath6kl_configure_target(ar); if (ret) goto err_bmi_cleanup; @@ -1613,10 +1193,6 @@ int ath6kl_core_init(struct ath6kl *ar) goto err_htc_cleanup; } - ret = ath6kl_fetch_firmwares(ar); - if (ret) - goto err_htc_cleanup; - ret = ath6kl_init_upload(ar); if (ret) goto err_htc_cleanup; @@ -1709,8 +1285,6 @@ void ath6kl_destroy(struct net_device *dev, unsigned int unregister) ath6kl_bmi_cleanup(ar); - ath6kl_debug_cleanup(ar); - if (unregister && test_bit(NETDEV_REGISTERED, &ar->flag)) { unregister_netdev(dev); clear_bit(NETDEV_REGISTERED, &ar->flag); @@ -1718,6 +1292,8 @@ void ath6kl_destroy(struct net_device *dev, unsigned int unregister) free_netdev(dev); + wlan_node_table_cleanup(&ar->scan_table); + kfree(ar->fw_board); kfree(ar->fw_otp); kfree(ar->fw); diff --git a/trunk/drivers/net/wireless/ath/ath6kl/main.c b/trunk/drivers/net/wireless/ath/ath6kl/main.c index 30b5a53db9ed..c336eae0cf48 100644 --- a/trunk/drivers/net/wireless/ath/ath6kl/main.c +++ b/trunk/drivers/net/wireless/ath/ath6kl/main.c @@ -61,8 +61,7 @@ static void ath6kl_add_new_sta(struct ath6kl *ar, u8 *mac, u16 aid, u8 *wpaie, sta = &ar->sta_list[free_slot]; memcpy(sta->mac, mac, ETH_ALEN); - if (ielen <= ATH6KL_MAX_IE) - memcpy(sta->wpa_ie, wpaie, ielen); + memcpy(sta->wpa_ie, wpaie, ielen); sta->aid = aid; sta->keymgmt = keymgmt; sta->ucipher = ucipher; @@ -178,8 +177,8 @@ void ath6kl_free_cookie(struct ath6kl *ar, struct ath6kl_cookie *cookie) static int ath6kl_set_addrwin_reg(struct ath6kl *ar, u32 reg_addr, u32 addr) { int status; + u8 addr_val[4]; s32 i; - __le32 addr_val; /* * Write bytes 1,2,3 of the register to set the upper address bytes, @@ -189,18 +188,16 @@ static int ath6kl_set_addrwin_reg(struct ath6kl *ar, u32 reg_addr, u32 addr) for (i = 1; i <= 3; i++) { /* * Fill the buffer with the address byte value we want to - * hit 4 times. No need to worry about endianness as the - * same byte is copied to all four bytes of addr_val at - * any time. + * hit 4 times. */ - memset((u8 *)&addr_val, ((u8 *)&addr)[i], 4); + memset(addr_val, ((u8 *)&addr)[i], 4); /* * Hit each byte of the register address with a 4-byte * write operation to the same address, this is a harmless * operation. */ - status = hif_read_write_sync(ar, reg_addr + i, (u8 *)&addr_val, + status = hif_read_write_sync(ar, reg_addr + i, addr_val, 4, HIF_WR_SYNC_BYTE_FIX); if (status) break; @@ -218,9 +215,7 @@ static int ath6kl_set_addrwin_reg(struct ath6kl *ar, u32 reg_addr, u32 addr) * cycle to start, the extra 3 byte write to bytes 1,2,3 has no * effect since we are writing the same values again */ - addr_val = cpu_to_le32(addr); - status = hif_read_write_sync(ar, reg_addr, - (u8 *)&(addr_val), + status = hif_read_write_sync(ar, reg_addr, (u8 *)(&addr), 4, HIF_WR_SYNC_BYTE_INC); if (status) { @@ -233,193 +228,90 @@ static int ath6kl_set_addrwin_reg(struct ath6kl *ar, u32 reg_addr, u32 addr) } /* - * Read from the hardware through its diagnostic window. No cooperation - * from the firmware is required for this. + * Read from the ATH6KL through its diagnostic window. No cooperation from + * the Target is required for this. */ -int ath6kl_diag_read32(struct ath6kl *ar, u32 address, u32 *value) +int ath6kl_read_reg_diag(struct ath6kl *ar, u32 *address, u32 *data) { - int ret; + int status; /* set window register to start read cycle */ - ret = ath6kl_set_addrwin_reg(ar, WINDOW_READ_ADDR_ADDRESS, address); - if (ret) - return ret; + status = ath6kl_set_addrwin_reg(ar, WINDOW_READ_ADDR_ADDRESS, + *address); + + if (status) + return status; /* read the data */ - ret = hif_read_write_sync(ar, WINDOW_DATA_ADDRESS, (u8 *) value, - sizeof(*value), HIF_RD_SYNC_BYTE_INC); - if (ret) { - ath6kl_warn("failed to read32 through diagnose window: %d\n", - ret); - return ret; + status = hif_read_write_sync(ar, WINDOW_DATA_ADDRESS, (u8 *)data, + sizeof(u32), HIF_RD_SYNC_BYTE_INC); + if (status) { + ath6kl_err("failed to read from window data addr\n"); + return status; } - return 0; + return status; } + /* * Write to the ATH6KL through its diagnostic window. No cooperation from * the Target is required for this. */ -int ath6kl_diag_write32(struct ath6kl *ar, u32 address, __le32 value) +static int ath6kl_write_reg_diag(struct ath6kl *ar, u32 *address, u32 *data) { - int ret; + int status; /* set write data */ - ret = hif_read_write_sync(ar, WINDOW_DATA_ADDRESS, (u8 *) &value, - sizeof(value), HIF_WR_SYNC_BYTE_INC); - if (ret) { - ath6kl_err("failed to write 0x%x during diagnose window to 0x%d\n", - address, value); - return ret; + status = hif_read_write_sync(ar, WINDOW_DATA_ADDRESS, (u8 *)data, + sizeof(u32), HIF_WR_SYNC_BYTE_INC); + if (status) { + ath6kl_err("failed to write 0x%x to window data addr\n", *data); + return status; } /* set window register, which starts the write cycle */ return ath6kl_set_addrwin_reg(ar, WINDOW_WRITE_ADDR_ADDRESS, - address); + *address); } -int ath6kl_diag_read(struct ath6kl *ar, u32 address, void *data, u32 length) -{ - u32 count, *buf = data; - int ret; - - if (WARN_ON(length % 4)) - return -EINVAL; - - for (count = 0; count < length / 4; count++, address += 4) { - ret = ath6kl_diag_read32(ar, address, &buf[count]); - if (ret) - return ret; - } - - return 0; -} - -int ath6kl_diag_write(struct ath6kl *ar, u32 address, void *data, u32 length) +int ath6kl_access_datadiag(struct ath6kl *ar, u32 address, + u8 *data, u32 length, bool read) { u32 count; - __le32 *buf = data; - int ret; - - if (WARN_ON(length % 4)) - return -EINVAL; - - for (count = 0; count < length / 4; count++, address += 4) { - ret = ath6kl_diag_write32(ar, address, buf[count]); - if (ret) - return ret; - } - - return 0; -} - -int ath6kl_read_fwlogs(struct ath6kl *ar) -{ - struct ath6kl_dbglog_hdr debug_hdr; - struct ath6kl_dbglog_buf debug_buf; - u32 address, length, dropped, firstbuf, debug_hdr_addr; - int ret = 0, loop; - u8 *buf; - - buf = kmalloc(ATH6KL_FWLOG_PAYLOAD_SIZE, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - address = TARG_VTOP(ar->target_type, - ath6kl_get_hi_item_addr(ar, - HI_ITEM(hi_dbglog_hdr))); - - ret = ath6kl_diag_read32(ar, address, &debug_hdr_addr); - if (ret) - goto out; - - /* Get the contents of the ring buffer */ - if (debug_hdr_addr == 0) { - ath6kl_warn("Invalid address for debug_hdr_addr\n"); - ret = -EINVAL; - goto out; - } - - address = TARG_VTOP(ar->target_type, debug_hdr_addr); - ath6kl_diag_read(ar, address, &debug_hdr, sizeof(debug_hdr)); - - address = TARG_VTOP(ar->target_type, - le32_to_cpu(debug_hdr.dbuf_addr)); - firstbuf = address; - dropped = le32_to_cpu(debug_hdr.dropped); - ath6kl_diag_read(ar, address, &debug_buf, sizeof(debug_buf)); - - loop = 100; - - do { - address = TARG_VTOP(ar->target_type, - le32_to_cpu(debug_buf.buffer_addr)); - length = le32_to_cpu(debug_buf.length); - - if (length != 0 && (le32_to_cpu(debug_buf.length) <= - le32_to_cpu(debug_buf.bufsize))) { - length = ALIGN(length, 4); - - ret = ath6kl_diag_read(ar, address, - buf, length); - if (ret) - goto out; - - ath6kl_debug_fwlog_event(ar, buf, length); - } - - address = TARG_VTOP(ar->target_type, - le32_to_cpu(debug_buf.next)); - ath6kl_diag_read(ar, address, &debug_buf, sizeof(debug_buf)); - if (ret) - goto out; - - loop--; + int status = 0; - if (WARN_ON(loop == 0)) { - ret = -ETIMEDOUT; - goto out; + for (count = 0; count < length; count += 4, address += 4) { + if (read) { + status = ath6kl_read_reg_diag(ar, &address, + (u32 *) &data[count]); + if (status) + break; + } else { + status = ath6kl_write_reg_diag(ar, &address, + (u32 *) &data[count]); + if (status) + break; } - } while (address != firstbuf); - -out: - kfree(buf); + } - return ret; + return status; } -/* FIXME: move to a better place, target.h? */ -#define AR6003_RESET_CONTROL_ADDRESS 0x00004000 -#define AR6004_RESET_CONTROL_ADDRESS 0x00004000 - static void ath6kl_reset_device(struct ath6kl *ar, u32 target_type, bool wait_fot_compltn, bool cold_reset) { int status = 0; u32 address; - __le32 data; + u32 data; - if (target_type != TARGET_TYPE_AR6003 && - target_type != TARGET_TYPE_AR6004) + if (target_type != TARGET_TYPE_AR6003) return; - data = cold_reset ? cpu_to_le32(RESET_CONTROL_COLD_RST) : - cpu_to_le32(RESET_CONTROL_MBOX_RST); + data = cold_reset ? RESET_CONTROL_COLD_RST : RESET_CONTROL_MBOX_RST; - switch (target_type) { - case TARGET_TYPE_AR6003: - address = AR6003_RESET_CONTROL_ADDRESS; - break; - case TARGET_TYPE_AR6004: - address = AR6004_RESET_CONTROL_ADDRESS; - break; - default: - address = AR6003_RESET_CONTROL_ADDRESS; - break; - } - - status = ath6kl_diag_write32(ar, address, data); + address = RTC_BASE_ADDRESS; + status = ath6kl_write_reg_diag(ar, &address, &data); if (status) ath6kl_err("failed to reset target\n"); @@ -519,107 +411,68 @@ static void ath6kl_install_static_wep_keys(struct ath6kl *ar) } } -void ath6kl_connect_ap_mode_bss(struct ath6kl *ar, u16 channel) -{ - struct ath6kl_req_key *ik; - int res; - u8 key_rsc[ATH6KL_KEY_SEQ_LEN]; - - ik = &ar->ap_mode_bkey; - - ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "AP mode started on %u MHz\n", channel); - - switch (ar->auth_mode) { - case NONE_AUTH: - if (ar->prwise_crypto == WEP_CRYPT) - ath6kl_install_static_wep_keys(ar); - break; - case WPA_PSK_AUTH: - case WPA2_PSK_AUTH: - case (WPA_PSK_AUTH | WPA2_PSK_AUTH): - if (!ik->valid) - break; - - ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delayed addkey for " - "the initial group key for AP mode\n"); - memset(key_rsc, 0, sizeof(key_rsc)); - res = ath6kl_wmi_addkey_cmd( - ar->wmi, ik->key_index, ik->key_type, - GROUP_USAGE, ik->key_len, key_rsc, ik->key, - KEY_OP_INIT_VAL, NULL, SYNC_BOTH_WMIFLAG); - if (res) { - ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delayed " - "addkey failed: %d\n", res); - } - break; - } - - ath6kl_wmi_bssfilter_cmd(ar->wmi, NONE_BSS_FILTER, 0); - set_bit(CONNECTED, &ar->flag); - netif_carrier_on(ar->net_dev); -} - -void ath6kl_connect_ap_mode_sta(struct ath6kl *ar, u16 aid, u8 *mac_addr, - u8 keymgmt, u8 ucipher, u8 auth, - u8 assoc_req_len, u8 *assoc_info) +static void ath6kl_connect_ap_mode(struct ath6kl *ar, u16 channel, u8 *bssid, + u16 listen_int, u16 beacon_int, + u8 assoc_resp_len, u8 *assoc_info) { - u8 *ies = NULL, *wpa_ie = NULL, *pos; - size_t ies_len = 0; + struct net_device *dev = ar->net_dev; struct station_info sinfo; + struct ath6kl_req_key *ik; + enum crypto_type keyType = NONE_CRYPT; - ath6kl_dbg(ATH6KL_DBG_TRC, "new station %pM aid=%d\n", mac_addr, aid); - - if (assoc_req_len > sizeof(struct ieee80211_hdr_3addr)) { - struct ieee80211_mgmt *mgmt = - (struct ieee80211_mgmt *) assoc_info; - if (ieee80211_is_assoc_req(mgmt->frame_control) && - assoc_req_len >= sizeof(struct ieee80211_hdr_3addr) + - sizeof(mgmt->u.assoc_req)) { - ies = mgmt->u.assoc_req.variable; - ies_len = assoc_info + assoc_req_len - ies; - } else if (ieee80211_is_reassoc_req(mgmt->frame_control) && - assoc_req_len >= sizeof(struct ieee80211_hdr_3addr) - + sizeof(mgmt->u.reassoc_req)) { - ies = mgmt->u.reassoc_req.variable; - ies_len = assoc_info + assoc_req_len - ies; - } - } + if (memcmp(dev->dev_addr, bssid, ETH_ALEN) == 0) { + ik = &ar->ap_mode_bkey; - pos = ies; - while (pos && pos + 1 < ies + ies_len) { - if (pos + 2 + pos[1] > ies + ies_len) + switch (ar->auth_mode) { + case NONE_AUTH: + if (ar->prwise_crypto == WEP_CRYPT) + ath6kl_install_static_wep_keys(ar); break; - if (pos[0] == WLAN_EID_RSN) - wpa_ie = pos; /* RSN IE */ - else if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && - pos[1] >= 4 && - pos[2] == 0x00 && pos[3] == 0x50 && pos[4] == 0xf2) { - if (pos[5] == 0x01) - wpa_ie = pos; /* WPA IE */ - else if (pos[5] == 0x04) { - wpa_ie = pos; /* WPS IE */ - break; /* overrides WPA/RSN IE */ + case WPA_PSK_AUTH: + case WPA2_PSK_AUTH: + case (WPA_PSK_AUTH|WPA2_PSK_AUTH): + switch (ik->ik_type) { + case ATH6KL_CIPHER_TKIP: + keyType = TKIP_CRYPT; + break; + case ATH6KL_CIPHER_AES_CCM: + keyType = AES_CRYPT; + break; + default: + goto skip_key; } + ath6kl_wmi_addkey_cmd(ar->wmi, ik->ik_keyix, keyType, + GROUP_USAGE, ik->ik_keylen, + (u8 *)&ik->ik_keyrsc, + ik->ik_keydata, + KEY_OP_INIT_VAL, ik->ik_macaddr, + SYNC_BOTH_WMIFLAG); + break; } - pos += 2 + pos[1]; +skip_key: + set_bit(CONNECTED, &ar->flag); + return; } - ath6kl_add_new_sta(ar, mac_addr, aid, wpa_ie, - wpa_ie ? 2 + wpa_ie[1] : 0, - keymgmt, ucipher, auth); + ath6kl_dbg(ATH6KL_DBG_TRC, "new station %pM aid=%d\n", + bssid, channel); + + ath6kl_add_new_sta(ar, bssid, channel, assoc_info, assoc_resp_len, + listen_int & 0xFF, beacon_int, + (listen_int >> 8) & 0xFF); /* send event to application */ memset(&sinfo, 0, sizeof(sinfo)); /* TODO: sinfo.generation */ - - sinfo.assoc_req_ies = ies; - sinfo.assoc_req_ies_len = ies_len; - sinfo.filled |= STATION_INFO_ASSOC_REQ_IES; - - cfg80211_new_sta(ar->net_dev, mac_addr, &sinfo, GFP_KERNEL); + /* TODO: need to deliver (Re)AssocReq IEs somehow.. change in + * cfg80211 needed, e.g., by adding those into sinfo + */ + cfg80211_new_sta(ar->net_dev, bssid, &sinfo, GFP_KERNEL); netif_wake_queue(ar->net_dev); + + return; } /* Functions for Tx credit handling */ @@ -926,41 +779,6 @@ void ath6kl_disconnect(struct ath6kl *ar) } } -void ath6kl_deep_sleep_enable(struct ath6kl *ar) -{ - switch (ar->sme_state) { - case SME_CONNECTING: - cfg80211_connect_result(ar->net_dev, ar->bssid, NULL, 0, - NULL, 0, - WLAN_STATUS_UNSPECIFIED_FAILURE, - GFP_KERNEL); - break; - case SME_CONNECTED: - default: - /* - * FIXME: oddly enough smeState is in DISCONNECTED during - * suspend, why? Need to send disconnected event in that - * state. - */ - cfg80211_disconnected(ar->net_dev, 0, NULL, 0, GFP_KERNEL); - break; - } - - if (test_bit(CONNECTED, &ar->flag) || - test_bit(CONNECT_PEND, &ar->flag)) - ath6kl_wmi_disconnect_cmd(ar->wmi); - - ar->sme_state = SME_DISCONNECTED; - - /* disable scanning */ - if (ath6kl_wmi_scanparams_cmd(ar->wmi, 0xFFFF, 0, 0, 0, 0, 0, 0, 0, - 0, 0) != 0) - printk(KERN_WARNING "ath6kl: failed to disable scan " - "during suspend\n"); - - ath6kl_cfg80211_scan_complete_event(ar, -ECANCELED); -} - /* WMI Event handlers */ static const char *get_hw_id_string(u32 id) @@ -1001,20 +819,17 @@ void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver) set_bit(WMI_READY, &ar->flag); wake_up(&ar->event_wq); - ath6kl_info("hw %s fw %s%s\n", + ath6kl_info("hw %s fw %s\n", get_hw_id_string(ar->wdev->wiphy->hw_version), - ar->wdev->wiphy->fw_version, - test_bit(TESTMODE, &ar->flag) ? " testmode" : ""); + ar->wdev->wiphy->fw_version); } void ath6kl_scan_complete_evt(struct ath6kl *ar, int status) { ath6kl_cfg80211_scan_complete_event(ar, status); - if (!ar->usr_bss_filter) { - clear_bit(CLEAR_BSSFILTER_ON_BEACON, &ar->flag); + if (!ar->usr_bss_filter) ath6kl_wmi_bssfilter_cmd(ar->wmi, NONE_BSS_FILTER, 0); - } ath6kl_dbg(ATH6KL_DBG_WLAN_SCAN, "scan complete: %d\n", status); } @@ -1027,6 +842,13 @@ void ath6kl_connect_event(struct ath6kl *ar, u16 channel, u8 *bssid, { unsigned long flags; + if (ar->nw_type == AP_NETWORK) { + ath6kl_connect_ap_mode(ar, channel, bssid, listen_int, + beacon_int, assoc_resp_len, + assoc_info); + return; + } + ath6kl_cfg80211_connect_event(ar, channel, bssid, listen_int, beacon_int, net_type, beacon_ie_len, @@ -1058,10 +880,8 @@ void ath6kl_connect_event(struct ath6kl *ar, u16 channel, u8 *bssid, ar->next_ep_id = ENDPOINT_2; } - if (!ar->usr_bss_filter) { - set_bit(CLEAR_BSSFILTER_ON_BEACON, &ar->flag); - ath6kl_wmi_bssfilter_cmd(ar->wmi, CURRENT_BSS_FILTER, 0); - } + if (!ar->usr_bss_filter) + ath6kl_wmi_bssfilter_cmd(ar->wmi, NONE_BSS_FILTER, 0); } void ath6kl_tkip_micerr_event(struct ath6kl *ar, u8 keyid, bool ismcast) @@ -1095,11 +915,26 @@ static void ath6kl_update_target_stats(struct ath6kl *ar, u8 *ptr, u32 len) (struct wmi_target_stats *) ptr; struct target_stats *stats = &ar->target_stats; struct tkip_ccmp_stats *ccmp_stats; + struct bss *conn_bss = NULL; + struct cserv_stats *c_stats; u8 ac; if (len < sizeof(*tgt_stats)) return; + /* update the RSSI of the connected bss */ + if (test_bit(CONNECTED, &ar->flag)) { + conn_bss = ath6kl_wmi_find_node(ar->wmi, ar->bssid); + if (conn_bss) { + c_stats = &tgt_stats->cserv_stats; + conn_bss->ni_rssi = + a_sle16_to_cpu(c_stats->cs_ave_beacon_rssi); + conn_bss->ni_snr = + tgt_stats->cserv_stats.cs_ave_beacon_snr; + ath6kl_wmi_node_return(ar->wmi, conn_bss); + } + } + ath6kl_dbg(ATH6KL_DBG_TRC, "updating target stats\n"); stats->tx_pkt += le32_to_cpu(tgt_stats->stats.tx.pkt); @@ -1330,6 +1165,7 @@ void ath6kl_disconnect_event(struct ath6kl *ar, u8 reason, u8 *bssid, u8 assoc_resp_len, u8 *assoc_info, u16 prot_reason_status) { + struct bss *wmi_ssid_node = NULL; unsigned long flags; if (ar->nw_type == AP_NETWORK) { @@ -1352,10 +1188,7 @@ void ath6kl_disconnect_event(struct ath6kl *ar, u8 reason, u8 *bssid, cfg80211_del_sta(ar->net_dev, bssid, GFP_KERNEL); } - if (memcmp(ar->net_dev->dev_addr, bssid, ETH_ALEN) == 0) { - memset(ar->wep_key_list, 0, sizeof(ar->wep_key_list)); - clear_bit(CONNECTED, &ar->flag); - } + clear_bit(CONNECTED, &ar->flag); return; } @@ -1389,6 +1222,33 @@ void ath6kl_disconnect_event(struct ath6kl *ar, u8 reason, u8 *bssid, } } + if ((reason == NO_NETWORK_AVAIL) && test_bit(WMI_READY, &ar->flag)) { + ath6kl_wmi_node_free(ar->wmi, bssid); + + /* + * In case any other same SSID nodes are present remove it, + * since those nodes also not available now. + */ + do { + /* + * Find the nodes based on SSID and remove it + * + * Note: This case will not work out for + * Hidden-SSID + */ + wmi_ssid_node = ath6kl_wmi_find_ssid_node(ar->wmi, + ar->ssid, + ar->ssid_len, + false, + true); + + if (wmi_ssid_node) + ath6kl_wmi_node_free(ar->wmi, + wmi_ssid_node->ni_macaddr); + + } while (wmi_ssid_node); + } + /* update connect & link status atomically */ spin_lock_irqsave(&ar->lock, flags); clear_bit(CONNECTED, &ar->flag); @@ -1471,7 +1331,7 @@ void init_netdev(struct net_device *dev) dev->needed_headroom = ETH_HLEN; dev->needed_headroom += sizeof(struct ath6kl_llc_snap_hdr) + sizeof(struct wmi_data_hdr) + HTC_HDR_LENGTH - + WMI_MAX_TX_META_SZ + ATH6KL_HTC_ALIGN_BYTES; + + WMI_MAX_TX_META_SZ; return; } diff --git a/trunk/drivers/net/wireless/ath/ath6kl/node.c b/trunk/drivers/net/wireless/ath/ath6kl/node.c new file mode 100644 index 000000000000..131205c610b9 --- /dev/null +++ b/trunk/drivers/net/wireless/ath/ath6kl/node.c @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2004-2011 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "htc.h" +#include "wmi.h" +#include "debug.h" + +struct bss *wlan_node_alloc(int wh_size) +{ + struct bss *ni; + + ni = kzalloc(sizeof(struct bss), GFP_ATOMIC); + + if ((ni != NULL) && wh_size) { + ni->ni_buf = kmalloc(wh_size, GFP_ATOMIC); + if (ni->ni_buf == NULL) { + kfree(ni); + return NULL; + } + } + + return ni; +} + +void wlan_node_free(struct bss *ni) +{ + kfree(ni->ni_buf); + kfree(ni); +} + +void wlan_setup_node(struct ath6kl_node_table *nt, struct bss *ni, + const u8 *mac_addr) +{ + int hash; + + memcpy(ni->ni_macaddr, mac_addr, ETH_ALEN); + hash = ATH6KL_NODE_HASH(mac_addr); + ni->ni_refcnt = 1; + + ni->ni_tstamp = jiffies_to_msecs(jiffies); + ni->ni_actcnt = WLAN_NODE_INACT_CNT; + + spin_lock_bh(&nt->nt_nodelock); + + /* insert at the end of the node list */ + ni->ni_list_next = NULL; + ni->ni_list_prev = nt->nt_node_last; + if (nt->nt_node_last != NULL) + nt->nt_node_last->ni_list_next = ni; + + nt->nt_node_last = ni; + if (nt->nt_node_first == NULL) + nt->nt_node_first = ni; + + /* insert into the hash list */ + ni->ni_hash_next = nt->nt_hash[hash]; + if (ni->ni_hash_next != NULL) + nt->nt_hash[hash]->ni_hash_prev = ni; + + ni->ni_hash_prev = NULL; + nt->nt_hash[hash] = ni; + + spin_unlock_bh(&nt->nt_nodelock); +} + +struct bss *wlan_find_node(struct ath6kl_node_table *nt, + const u8 *mac_addr) +{ + struct bss *ni, *found_ni = NULL; + int hash; + + spin_lock_bh(&nt->nt_nodelock); + + hash = ATH6KL_NODE_HASH(mac_addr); + for (ni = nt->nt_hash[hash]; ni; ni = ni->ni_hash_next) { + if (memcmp(ni->ni_macaddr, mac_addr, ETH_ALEN) == 0) { + ni->ni_refcnt++; + found_ni = ni; + break; + } + } + + spin_unlock_bh(&nt->nt_nodelock); + + return found_ni; +} + +void wlan_node_reclaim(struct ath6kl_node_table *nt, struct bss *ni) +{ + int hash; + + spin_lock_bh(&nt->nt_nodelock); + + if (ni->ni_list_prev == NULL) + /* fix list head */ + nt->nt_node_first = ni->ni_list_next; + else + ni->ni_list_prev->ni_list_next = ni->ni_list_next; + + if (ni->ni_list_next == NULL) + /* fix list tail */ + nt->nt_node_last = ni->ni_list_prev; + else + ni->ni_list_next->ni_list_prev = ni->ni_list_prev; + + if (ni->ni_hash_prev == NULL) { + /* first in list so fix the list head */ + hash = ATH6KL_NODE_HASH(ni->ni_macaddr); + nt->nt_hash[hash] = ni->ni_hash_next; + } else { + ni->ni_hash_prev->ni_hash_next = ni->ni_hash_next; + } + + if (ni->ni_hash_next != NULL) + ni->ni_hash_next->ni_hash_prev = ni->ni_hash_prev; + + wlan_node_free(ni); + + spin_unlock_bh(&nt->nt_nodelock); +} + +static void wlan_node_dec_free(struct bss *ni) +{ + if ((ni->ni_refcnt--) == 1) + wlan_node_free(ni); +} + +void wlan_free_allnodes(struct ath6kl_node_table *nt) +{ + struct bss *ni; + + while ((ni = nt->nt_node_first) != NULL) + wlan_node_reclaim(nt, ni); +} + +void wlan_iterate_nodes(struct ath6kl_node_table *nt, void *arg) +{ + struct bss *ni; + + spin_lock_bh(&nt->nt_nodelock); + for (ni = nt->nt_node_first; ni; ni = ni->ni_list_next) { + ni->ni_refcnt++; + ath6kl_cfg80211_scan_node(arg, ni); + wlan_node_dec_free(ni); + } + spin_unlock_bh(&nt->nt_nodelock); +} + +void wlan_node_table_init(struct ath6kl_node_table *nt) +{ + ath6kl_dbg(ATH6KL_DBG_WLAN_NODE, "node table = 0x%lx\n", + (unsigned long)nt); + + memset(nt, 0, sizeof(struct ath6kl_node_table)); + + spin_lock_init(&nt->nt_nodelock); + + nt->nt_node_age = WLAN_NODE_INACT_TIMEOUT_MSEC; +} + +void wlan_refresh_inactive_nodes(struct ath6kl *ar) +{ + struct ath6kl_node_table *nt = &ar->scan_table; + struct bss *bss; + u32 now; + + now = jiffies_to_msecs(jiffies); + bss = nt->nt_node_first; + while (bss != NULL) { + /* refresh all nodes except the current bss */ + if (memcmp(ar->bssid, bss->ni_macaddr, ETH_ALEN) != 0) { + if (((now - bss->ni_tstamp) > nt->nt_node_age) + || --bss->ni_actcnt == 0) { + wlan_node_reclaim(nt, bss); + } + } + bss = bss->ni_list_next; + } +} + +void wlan_node_table_cleanup(struct ath6kl_node_table *nt) +{ + wlan_free_allnodes(nt); +} + +struct bss *wlan_find_ssid_node(struct ath6kl_node_table *nt, u8 * ssid, + u32 ssid_len, bool is_wpa2, bool match_ssid) +{ + struct bss *ni, *found_ni = NULL; + u8 *ie_ssid; + + spin_lock_bh(&nt->nt_nodelock); + + for (ni = nt->nt_node_first; ni; ni = ni->ni_list_next) { + + ie_ssid = ni->ni_cie.ie_ssid; + + if ((ie_ssid[1] <= IEEE80211_MAX_SSID_LEN) && + (memcmp(ssid, &ie_ssid[2], ssid_len) == 0)) { + + if (match_ssid || + (is_wpa2 && ni->ni_cie.ie_rsn != NULL) || + (!is_wpa2 && ni->ni_cie.ie_wpa != NULL)) { + ni->ni_refcnt++; + found_ni = ni; + break; + } + } + } + + spin_unlock_bh(&nt->nt_nodelock); + + return found_ni; +} + +void wlan_node_return(struct ath6kl_node_table *nt, struct bss *ni) +{ + spin_lock_bh(&nt->nt_nodelock); + wlan_node_dec_free(ni); + spin_unlock_bh(&nt->nt_nodelock); +} diff --git a/trunk/drivers/net/wireless/ath/ath6kl/sdio.c b/trunk/drivers/net/wireless/ath/ath6kl/sdio.c index f1dc311ee0c7..34171604cbe4 100644 --- a/trunk/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/trunk/drivers/net/wireless/ath/ath6kl/sdio.c @@ -25,7 +25,6 @@ #include "hif-ops.h" #include "target.h" #include "debug.h" -#include "cfg80211.h" struct ath6kl_sdio { struct sdio_func *func; @@ -135,12 +134,10 @@ static int ath6kl_sdio_io(struct sdio_func *func, u32 request, u32 addr, int ret = 0; if (request & HIF_WRITE) { - /* FIXME: looks like ugly workaround for something */ if (addr >= HIF_MBOX_BASE_ADDR && addr <= HIF_MBOX_END_ADDR) addr += (HIF_MBOX_WIDTH - len); - /* FIXME: this also looks like ugly workaround */ if (addr == HIF_MBOX0_EXT_BASE_ADDR) addr += HIF_MBOX0_EXT_WIDTH - len; @@ -155,11 +152,6 @@ static int ath6kl_sdio_io(struct sdio_func *func, u32 request, u32 addr, ret = sdio_memcpy_fromio(func, buf, addr, len); } - ath6kl_dbg(ATH6KL_DBG_SDIO, "%s addr 0x%x%s buf 0x%p len %d\n", - request & HIF_WRITE ? "wr" : "rd", addr, - request & HIF_FIXED_ADDRESS ? " (fixed)" : "", buf, len); - ath6kl_dbg_dump(ATH6KL_DBG_SDIO_DUMP, NULL, "sdio ", buf, len); - return ret; } @@ -180,8 +172,7 @@ static struct bus_request *ath6kl_sdio_alloc_busreq(struct ath6kl_sdio *ar_sdio) list_del(&bus_req->list); spin_unlock_irqrestore(&ar_sdio->lock, flag); - ath6kl_dbg(ATH6KL_DBG_SCATTER, "%s: bus request 0x%p\n", - __func__, bus_req); + ath6kl_dbg(ATH6KL_DBG_TRC, "%s: bus request 0x%p\n", __func__, bus_req); return bus_req; } @@ -191,8 +182,7 @@ static void ath6kl_sdio_free_bus_req(struct ath6kl_sdio *ar_sdio, { unsigned long flag; - ath6kl_dbg(ATH6KL_DBG_SCATTER, "%s: bus request 0x%p\n", - __func__, bus_req); + ath6kl_dbg(ATH6KL_DBG_TRC, "%s: bus request 0x%p\n", __func__, bus_req); spin_lock_irqsave(&ar_sdio->lock, flag); list_add_tail(&bus_req->list, &ar_sdio->bus_req_freeq); @@ -223,6 +213,16 @@ static void ath6kl_sdio_setup_scat_data(struct hif_scatter_req *scat_req, /* assemble SG list */ for (i = 0; i < scat_req->scat_entries; i++, sg++) { + if ((unsigned long)scat_req->scat_list[i].buf & 0x3) + /* + * Some scatter engines can handle unaligned + * buffers, print this as informational only. + */ + ath6kl_dbg(ATH6KL_DBG_SCATTER, + "(%s) scatter buffer is unaligned 0x%p\n", + scat_req->req & HIF_WRITE ? "WR" : "RD", + scat_req->scat_list[i].buf); + ath6kl_dbg(ATH6KL_DBG_SCATTER, "%d: addr:0x%p, len:%d\n", i, scat_req->scat_list[i].buf, scat_req->scat_list[i].len); @@ -447,8 +447,6 @@ static void ath6kl_sdio_irq_handler(struct sdio_func *func) int status; struct ath6kl_sdio *ar_sdio; - ath6kl_dbg(ATH6KL_DBG_SDIO, "irq\n"); - ar_sdio = sdio_get_drvdata(func); atomic_set(&ar_sdio->irq_handling, 1); @@ -686,7 +684,7 @@ static int ath6kl_sdio_enable_scatter(struct ath6kl *ar) MAX_SCATTER_REQUESTS, virt_scat); if (!ret) { - ath6kl_dbg(ATH6KL_DBG_SCATTER, + ath6kl_dbg(ATH6KL_DBG_ANY, "hif-scatter enabled: max scatter req : %d entries: %d\n", MAX_SCATTER_REQUESTS, MAX_SCATTER_ENTRIES_PER_REQ); @@ -711,7 +709,7 @@ static int ath6kl_sdio_enable_scatter(struct ath6kl *ar) return ret; } - ath6kl_dbg(ATH6KL_DBG_SCATTER, + ath6kl_dbg(ATH6KL_DBG_ANY, "Vitual scatter enabled, max_scat_req:%d, entries:%d\n", ATH6KL_SCATTER_REQS, ATH6KL_SCATTER_ENTRIES_PER_REQ); @@ -723,34 +721,6 @@ static int ath6kl_sdio_enable_scatter(struct ath6kl *ar) return 0; } -static int ath6kl_sdio_suspend(struct ath6kl *ar) -{ - struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar); - struct sdio_func *func = ar_sdio->func; - mmc_pm_flag_t flags; - int ret; - - flags = sdio_get_host_pm_caps(func); - - if (!(flags & MMC_PM_KEEP_POWER)) - /* as host doesn't support keep power we need to bail out */ - ath6kl_dbg(ATH6KL_DBG_SDIO, - "func %d doesn't support MMC_PM_KEEP_POWER\n", - func->num); - return -EINVAL; - - ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); - if (ret) { - printk(KERN_ERR "ath6kl: set sdio pm flags failed: %d\n", - ret); - return ret; - } - - ath6kl_deep_sleep_enable(ar); - - return 0; -} - static const struct ath6kl_hif_ops ath6kl_sdio_ops = { .read_write_sync = ath6kl_sdio_read_write_sync, .write_async = ath6kl_sdio_write_async, @@ -761,7 +731,6 @@ static const struct ath6kl_hif_ops ath6kl_sdio_ops = { .enable_scatter = ath6kl_sdio_enable_scatter, .scat_req_rw = ath6kl_sdio_async_rw_scatter, .cleanup_scatter = ath6kl_sdio_cleanup_scatter, - .suspend = ath6kl_sdio_suspend, }; static int ath6kl_sdio_probe(struct sdio_func *func, @@ -772,10 +741,10 @@ static int ath6kl_sdio_probe(struct sdio_func *func, struct ath6kl *ar; int count; - ath6kl_dbg(ATH6KL_DBG_SDIO, - "new func %d vendor 0x%x device 0x%x block 0x%x/0x%x\n", - func->num, func->vendor, func->device, - func->max_blksize, func->cur_blksize); + ath6kl_dbg(ATH6KL_DBG_TRC, + "%s: func: 0x%X, vendor id: 0x%X, dev id: 0x%X, block size: 0x%X/0x%X\n", + __func__, func->num, func->vendor, + func->device, func->max_blksize, func->cur_blksize); ar_sdio = kzalloc(sizeof(struct ath6kl_sdio), GFP_KERNEL); if (!ar_sdio) @@ -831,10 +800,10 @@ static int ath6kl_sdio_probe(struct sdio_func *func, ath6kl_err("Failed to enable 4-bit async irq mode %d\n", ret); sdio_release_host(func); - goto err_cfg80211; + goto err_dma; } - ath6kl_dbg(ATH6KL_DBG_SDIO, "4-bit async irq mode enabled\n"); + ath6kl_dbg(ATH6KL_DBG_TRC, "4-bit async irq mode enabled\n"); } /* give us some time to enable, in ms */ @@ -844,7 +813,7 @@ static int ath6kl_sdio_probe(struct sdio_func *func, ret = ath6kl_sdio_power_on(ar_sdio); if (ret) - goto err_cfg80211; + goto err_dma; sdio_claim_host(func); @@ -868,8 +837,6 @@ static int ath6kl_sdio_probe(struct sdio_func *func, err_off: ath6kl_sdio_power_off(ar_sdio); -err_cfg80211: - ath6kl_cfg80211_deinit(ar_sdio->ar); err_dma: kfree(ar_sdio->dma_buffer); err_hif: @@ -882,10 +849,6 @@ static void ath6kl_sdio_remove(struct sdio_func *func) { struct ath6kl_sdio *ar_sdio; - ath6kl_dbg(ATH6KL_DBG_SDIO, - "removed func %d vendor 0x%x device 0x%x\n", - func->num, func->vendor, func->device); - ar_sdio = sdio_get_drvdata(func); ath6kl_stop_txrx(ar_sdio->ar); diff --git a/trunk/drivers/net/wireless/ath/ath6kl/target.h b/trunk/drivers/net/wireless/ath/ath6kl/target.h index c9a76051f042..519a013c9991 100644 --- a/trunk/drivers/net/wireless/ath/ath6kl/target.h +++ b/trunk/drivers/net/wireless/ath/ath6kl/target.h @@ -20,9 +20,6 @@ #define AR6003_BOARD_DATA_SZ 1024 #define AR6003_BOARD_EXT_DATA_SZ 768 -#define AR6004_BOARD_DATA_SZ 7168 -#define AR6004_BOARD_EXT_DATA_SZ 0 - #define RESET_CONTROL_ADDRESS 0x00000000 #define RESET_CONTROL_COLD_RST 0x00000100 #define RESET_CONTROL_MBOX_RST 0x00000004 @@ -138,8 +135,7 @@ * between the two, and is intended to remain constant (with additions only * at the end). */ -#define ATH6KL_AR6003_HI_START_ADDR 0x00540600 -#define ATH6KL_AR6004_HI_START_ADDR 0x00400800 +#define ATH6KL_HI_START_ADDR 0x00540600 /* * These are items that the Host may need to access @@ -304,11 +300,6 @@ struct host_interest { #define HI_OPTION_FW_MODE_BSS_STA 0x1 #define HI_OPTION_FW_MODE_AP 0x2 -#define HI_OPTION_FW_SUBMODE_NONE 0x0 -#define HI_OPTION_FW_SUBMODE_P2PDEV 0x1 -#define HI_OPTION_FW_SUBMODE_P2PCLIENT 0x2 -#define HI_OPTION_FW_SUBMODE_P2PGO 0x3 - #define HI_OPTION_NUM_DEV_SHIFT 0x9 #define HI_OPTION_FW_BRIDGE_SHIFT 0x04 @@ -321,44 +312,20 @@ struct host_interest { |------------------------------------------------------------------------------| */ #define HI_OPTION_FW_MODE_SHIFT 0xC -#define HI_OPTION_FW_SUBMODE_SHIFT 0x14 /* Convert a Target virtual address into a Target physical address */ -#define AR6003_VTOP(vaddr) ((vaddr) & 0x001fffff) -#define AR6004_VTOP(vaddr) (vaddr) - -#define TARG_VTOP(target_type, vaddr) \ - (((target_type) == TARGET_TYPE_AR6003) ? AR6003_VTOP(vaddr) : \ - (((target_type) == TARGET_TYPE_AR6004) ? AR6004_VTOP(vaddr) : 0)) +#define TARG_VTOP(vaddr) (vaddr & 0x001fffff) +#define AR6003_REV2_APP_START_OVERRIDE 0x944C00 #define AR6003_REV2_APP_LOAD_ADDRESS 0x543180 #define AR6003_REV2_BOARD_EXT_DATA_ADDRESS 0x57E500 #define AR6003_REV2_DATASET_PATCH_ADDRESS 0x57e884 #define AR6003_REV2_RAM_RESERVE_SIZE 6912 +#define AR6003_REV3_APP_START_OVERRIDE 0x945d00 #define AR6003_REV3_APP_LOAD_ADDRESS 0x545000 #define AR6003_REV3_BOARD_EXT_DATA_ADDRESS 0x542330 #define AR6003_REV3_DATASET_PATCH_ADDRESS 0x57FF74 #define AR6003_REV3_RAM_RESERVE_SIZE 512 -#define AR6004_REV1_BOARD_DATA_ADDRESS 0x435400 -#define AR6004_REV1_BOARD_EXT_DATA_ADDRESS 0x437000 -#define AR6004_REV1_RAM_RESERVE_SIZE 11264 - -#define ATH6KL_FWLOG_PAYLOAD_SIZE 1500 - -struct ath6kl_dbglog_buf { - __le32 next; - __le32 buffer_addr; - __le32 bufsize; - __le32 length; - __le32 count; - __le32 free; -} __packed; - -struct ath6kl_dbglog_hdr { - __le32 dbuf_addr; - __le32 dropped; -} __packed; - #endif diff --git a/trunk/drivers/net/wireless/ath/ath6kl/testmode.c b/trunk/drivers/net/wireless/ath/ath6kl/testmode.c deleted file mode 100644 index 381eb66a605f..000000000000 --- a/trunk/drivers/net/wireless/ath/ath6kl/testmode.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (c) 2010-2011 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "testmode.h" - -#include - -enum ath6kl_tm_attr { - __ATH6KL_TM_ATTR_INVALID = 0, - ATH6KL_TM_ATTR_CMD = 1, - ATH6KL_TM_ATTR_DATA = 2, - - /* keep last */ - __ATH6KL_TM_ATTR_AFTER_LAST, - ATH6KL_TM_ATTR_MAX = __ATH6KL_TM_ATTR_AFTER_LAST - 1, -}; - -enum ath6kl_tm_cmd { - ATH6KL_TM_CMD_TCMD = 0, - ATH6KL_TM_CMD_RX_REPORT = 1, -}; - -#define ATH6KL_TM_DATA_MAX_LEN 5000 - -static const struct nla_policy ath6kl_tm_policy[ATH6KL_TM_ATTR_MAX + 1] = { - [ATH6KL_TM_ATTR_CMD] = { .type = NLA_U32 }, - [ATH6KL_TM_ATTR_DATA] = { .type = NLA_BINARY, - .len = ATH6KL_TM_DATA_MAX_LEN }, -}; - -void ath6kl_tm_rx_report_event(struct ath6kl *ar, void *buf, size_t buf_len) -{ - if (down_interruptible(&ar->sem)) - return; - - kfree(ar->tm.rx_report); - - ar->tm.rx_report = kmemdup(buf, buf_len, GFP_KERNEL); - ar->tm.rx_report_len = buf_len; - - up(&ar->sem); - - wake_up(&ar->event_wq); -} - -static int ath6kl_tm_rx_report(struct ath6kl *ar, void *buf, size_t buf_len, - struct sk_buff *skb) -{ - int ret = 0; - long left; - - if (down_interruptible(&ar->sem)) - return -ERESTARTSYS; - - if (!test_bit(WMI_READY, &ar->flag)) { - ret = -EIO; - goto out; - } - - if (test_bit(DESTROY_IN_PROGRESS, &ar->flag)) { - ret = -EBUSY; - goto out; - } - - if (ath6kl_wmi_test_cmd(ar->wmi, buf, buf_len) < 0) { - up(&ar->sem); - return -EIO; - } - - left = wait_event_interruptible_timeout(ar->event_wq, - ar->tm.rx_report != NULL, - WMI_TIMEOUT); - - if (left == 0) { - ret = -ETIMEDOUT; - goto out; - } else if (left < 0) { - ret = left; - goto out; - } - - if (ar->tm.rx_report == NULL || ar->tm.rx_report_len == 0) { - ret = -EINVAL; - goto out; - } - - NLA_PUT(skb, ATH6KL_TM_ATTR_DATA, ar->tm.rx_report_len, - ar->tm.rx_report); - - kfree(ar->tm.rx_report); - ar->tm.rx_report = NULL; - -out: - up(&ar->sem); - - return ret; - -nla_put_failure: - ret = -ENOBUFS; - goto out; -} - -int ath6kl_tm_cmd(struct wiphy *wiphy, void *data, int len) -{ - struct ath6kl *ar = wiphy_priv(wiphy); - struct nlattr *tb[ATH6KL_TM_ATTR_MAX + 1]; - int err, buf_len, reply_len; - struct sk_buff *skb; - void *buf; - - err = nla_parse(tb, ATH6KL_TM_ATTR_MAX, data, len, - ath6kl_tm_policy); - if (err) - return err; - - if (!tb[ATH6KL_TM_ATTR_CMD]) - return -EINVAL; - - switch (nla_get_u32(tb[ATH6KL_TM_ATTR_CMD])) { - case ATH6KL_TM_CMD_TCMD: - if (!tb[ATH6KL_TM_ATTR_DATA]) - return -EINVAL; - - buf = nla_data(tb[ATH6KL_TM_ATTR_DATA]); - buf_len = nla_len(tb[ATH6KL_TM_ATTR_DATA]); - - ath6kl_wmi_test_cmd(ar->wmi, buf, buf_len); - - return 0; - - break; - case ATH6KL_TM_CMD_RX_REPORT: - if (!tb[ATH6KL_TM_ATTR_DATA]) - return -EINVAL; - - buf = nla_data(tb[ATH6KL_TM_ATTR_DATA]); - buf_len = nla_len(tb[ATH6KL_TM_ATTR_DATA]); - - reply_len = nla_total_size(ATH6KL_TM_DATA_MAX_LEN); - skb = cfg80211_testmode_alloc_reply_skb(wiphy, reply_len); - if (!skb) - return -ENOMEM; - - err = ath6kl_tm_rx_report(ar, buf, buf_len, skb); - if (err < 0) { - kfree_skb(skb); - return err; - } - - return cfg80211_testmode_reply(skb); - default: - return -EOPNOTSUPP; - } -} diff --git a/trunk/drivers/net/wireless/ath/ath6kl/testmode.h b/trunk/drivers/net/wireless/ath/ath6kl/testmode.h deleted file mode 100644 index 43dffcc11fb1..000000000000 --- a/trunk/drivers/net/wireless/ath/ath6kl/testmode.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2010-2011 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "core.h" - -#ifdef CONFIG_NL80211_TESTMODE - -void ath6kl_tm_rx_report_event(struct ath6kl *ar, void *buf, size_t buf_len); -int ath6kl_tm_cmd(struct wiphy *wiphy, void *data, int len); - -#else - -static inline void ath6kl_tm_rx_report_event(struct ath6kl *ar, void *buf, - size_t buf_len) -{ -} - -static inline int ath6kl_tm_cmd(struct wiphy *wiphy, void *data, int len) -{ - return 0; -} - -#endif diff --git a/trunk/drivers/net/wireless/ath/ath6kl/txrx.c b/trunk/drivers/net/wireless/ath/ath6kl/txrx.c index a7117074f81c..167bdb9cf68d 100644 --- a/trunk/drivers/net/wireless/ath/ath6kl/txrx.c +++ b/trunk/drivers/net/wireless/ath/ath6kl/txrx.c @@ -239,6 +239,7 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev) u16 htc_tag = ATH6KL_DATA_PKT_TAG; u8 ac = 99 ; /* initialize to unmapped ac */ bool chk_adhoc_ps_mapping = false, more_data = false; + struct wmi_tx_meta_v2 meta_v2; int ret; ath6kl_dbg(ATH6KL_DBG_WLAN_TX, @@ -261,6 +262,8 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev) } if (test_bit(WMI_ENABLED, &ar->flag)) { + memset(&meta_v2, 0, sizeof(meta_v2)); + if (skb_headroom(skb) < dev->needed_headroom) { WARN_ON(1); goto fail_tx; @@ -317,31 +320,12 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev) spin_unlock_bh(&ar->lock); - if (!IS_ALIGNED((unsigned long) skb->data - HTC_HDR_LENGTH, 4) && - skb_cloned(skb)) { - /* - * We will touch (move the buffer data to align it. Since the - * skb buffer is cloned and not only the header is changed, we - * have to copy it to allow the changes. Since we are copying - * the data here, we may as well align it by reserving suitable - * headroom to avoid the memmove in ath6kl_htc_tx_buf_align(). - */ - struct sk_buff *nskb; - - nskb = skb_copy_expand(skb, HTC_HDR_LENGTH, 0, GFP_ATOMIC); - if (nskb == NULL) - goto fail_tx; - kfree_skb(skb); - skb = nskb; - } - cookie->skb = skb; cookie->map_no = map_no; set_htc_pkt_info(&cookie->htc_pkt, cookie, skb->data, skb->len, eid, htc_tag); - ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, __func__, "tx ", - skb->data, skb->len); + ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, __func__, skb->data, skb->len); /* * HTC interface is asynchronous, if this fails, cleanup will @@ -705,8 +689,6 @@ void ath6kl_rx_refill(struct htc_target *target, enum htc_endpoint_id endpoint) break; packet = (struct htc_packet *) skb->head; - if (!IS_ALIGNED((unsigned long) skb->data, 4)) - skb->data = PTR_ALIGN(skb->data - 4, 4); set_htc_rxpkt_info(packet, skb, skb->data, ATH6KL_BUFFER_SIZE, endpoint); list_add_tail(&packet->list, &queue); @@ -727,8 +709,6 @@ void ath6kl_refill_amsdu_rxbufs(struct ath6kl *ar, int count) return; packet = (struct htc_packet *) skb->head; - if (!IS_ALIGNED((unsigned long) skb->data, 4)) - skb->data = PTR_ALIGN(skb->data - 4, 4); set_htc_rxpkt_info(packet, skb, skb->data, ATH6KL_AMSDU_BUFFER_SIZE, 0); spin_lock_bh(&ar->lock); @@ -832,7 +812,7 @@ static void aggr_slice_amsdu(struct aggr_info *p_aggr, /* Add the length of A-MSDU subframe padding bytes - * Round to nearest word. */ - frame_8023_len = ALIGN(frame_8023_len, 4); + frame_8023_len = ALIGN(frame_8023_len + 3, 3); framep += frame_8023_len; amsdu_len -= frame_8023_len; @@ -1064,13 +1044,12 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) ar->net_stats.rx_packets++; ar->net_stats.rx_bytes += packet->act_len; - spin_unlock_bh(&ar->lock); - skb_put(skb, packet->act_len + HTC_HDR_LENGTH); skb_pull(skb, HTC_HDR_LENGTH); - ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, __func__, "rx ", - skb->data, skb->len); + ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, __func__, skb->data, skb->len); + + spin_unlock_bh(&ar->lock); skb->dev = ar->net_dev; @@ -1086,8 +1065,9 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) return; } - min_hdr_len = sizeof(struct ethhdr) + sizeof(struct wmi_data_hdr) + - sizeof(struct ath6kl_llc_snap_hdr); + min_hdr_len = sizeof(struct ethhdr); + min_hdr_len += sizeof(struct wmi_data_hdr) + + sizeof(struct ath6kl_llc_snap_hdr); dhdr = (struct wmi_data_hdr *) skb->data; @@ -1183,7 +1163,8 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) seq_no = wmi_data_hdr_get_seqno(dhdr); meta_type = wmi_data_hdr_get_meta(dhdr); dot11_hdr = wmi_data_hdr_get_dot11(dhdr); - skb_pull(skb, sizeof(struct wmi_data_hdr)); + + ath6kl_wmi_data_hdr_remove(ar->wmi, skb); switch (meta_type) { case WMI_META_VERSION_1: @@ -1250,15 +1231,9 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) ath6kl_data_tx(skb1, ar->net_dev); } - datap = (struct ethhdr *) skb->data; - - if (is_unicast_ether_addr(datap->h_dest) && - aggr_process_recv_frm(ar->aggr_cntxt, tid, seq_no, - is_amsdu, skb)) - /* aggregation code will handle the skb */ - return; - - ath6kl_deliver_frames_to_nw_stack(ar->net_dev, skb); + if (!aggr_process_recv_frm(ar->aggr_cntxt, tid, seq_no, + is_amsdu, skb)) + ath6kl_deliver_frames_to_nw_stack(ar->net_dev, skb); } static void aggr_timeout(unsigned long arg) @@ -1275,6 +1250,10 @@ static void aggr_timeout(unsigned long arg) if (!rxtid->aggr || !rxtid->timer_mon || rxtid->progress) continue; + /* + * FIXME: these timeouts happen quite fruently, something + * line once within 60 seconds. Investigate why. + */ stats->num_timeouts++; ath6kl_dbg(ATH6KL_DBG_AGGR, "aggr timeout (st %d end %d)\n", diff --git a/trunk/drivers/net/wireless/ath/ath6kl/wmi.c b/trunk/drivers/net/wireless/ath/ath6kl/wmi.c index a7de23cbd2c7..f5aa33dd4c42 100644 --- a/trunk/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/trunk/drivers/net/wireless/ath/ath6kl/wmi.c @@ -17,9 +17,6 @@ #include #include "core.h" #include "debug.h" -#include "testmode.h" -#include "../regd.h" -#include "../regd_common.h" static int ath6kl_wmi_sync_point(struct wmi *wmi); @@ -170,11 +167,9 @@ int ath6kl_wmi_data_hdr_add(struct wmi *wmi, struct sk_buff *skb, if (WARN_ON(skb == NULL)) return -EINVAL; - if (tx_meta_info) { - ret = ath6kl_wmi_meta_add(wmi, skb, &meta_ver, tx_meta_info); - if (ret) - return ret; - } + ret = ath6kl_wmi_meta_add(wmi, skb, &meta_ver, tx_meta_info); + if (ret) + return ret; skb_push(skb, sizeof(struct wmi_data_hdr)); @@ -381,6 +376,35 @@ int ath6kl_wmi_dot3_2_dix(struct sk_buff *skb) return 0; } +int ath6kl_wmi_data_hdr_remove(struct wmi *wmi, struct sk_buff *skb) +{ + if (WARN_ON(skb == NULL)) + return -EINVAL; + + skb_pull(skb, sizeof(struct wmi_data_hdr)); + + return 0; +} + +static void ath6kl_wmi_convert_bssinfo_hdr2_to_hdr(struct sk_buff *skb, + u8 *datap) +{ + struct wmi_bss_info_hdr2 bih2; + struct wmi_bss_info_hdr *bih; + + memcpy(&bih2, datap, sizeof(struct wmi_bss_info_hdr2)); + + skb_push(skb, 4); + bih = (struct wmi_bss_info_hdr *) skb->data; + + bih->ch = bih2.ch; + bih->frame_type = bih2.frame_type; + bih->snr = bih2.snr; + bih->rssi = a_cpu_to_sle16(bih2.snr - 95); + bih->ie_mask = cpu_to_le32(le16_to_cpu(bih2.ie_mask)); + memcpy(bih->bssid, bih2.bssid, ETH_ALEN); +} + static int ath6kl_wmi_tx_complete_event_rx(u8 *datap, int len) { struct tx_complete_msg_v1 *msg_v1; @@ -409,201 +433,6 @@ static int ath6kl_wmi_tx_complete_event_rx(u8 *datap, int len) return 0; } -static int ath6kl_wmi_remain_on_chnl_event_rx(struct wmi *wmi, u8 *datap, - int len) -{ - struct wmi_remain_on_chnl_event *ev; - u32 freq; - u32 dur; - struct ieee80211_channel *chan; - struct ath6kl *ar = wmi->parent_dev; - - if (len < sizeof(*ev)) - return -EINVAL; - - ev = (struct wmi_remain_on_chnl_event *) datap; - freq = le32_to_cpu(ev->freq); - dur = le32_to_cpu(ev->duration); - ath6kl_dbg(ATH6KL_DBG_WMI, "remain_on_chnl: freq=%u dur=%u\n", - freq, dur); - chan = ieee80211_get_channel(ar->wdev->wiphy, freq); - if (!chan) { - ath6kl_dbg(ATH6KL_DBG_WMI, "remain_on_chnl: Unknown channel " - "(freq=%u)\n", freq); - return -EINVAL; - } - cfg80211_ready_on_channel(ar->net_dev, 1, chan, NL80211_CHAN_NO_HT, - dur, GFP_ATOMIC); - - return 0; -} - -static int ath6kl_wmi_cancel_remain_on_chnl_event_rx(struct wmi *wmi, - u8 *datap, int len) -{ - struct wmi_cancel_remain_on_chnl_event *ev; - u32 freq; - u32 dur; - struct ieee80211_channel *chan; - struct ath6kl *ar = wmi->parent_dev; - - if (len < sizeof(*ev)) - return -EINVAL; - - ev = (struct wmi_cancel_remain_on_chnl_event *) datap; - freq = le32_to_cpu(ev->freq); - dur = le32_to_cpu(ev->duration); - ath6kl_dbg(ATH6KL_DBG_WMI, "cancel_remain_on_chnl: freq=%u dur=%u " - "status=%u\n", freq, dur, ev->status); - chan = ieee80211_get_channel(ar->wdev->wiphy, freq); - if (!chan) { - ath6kl_dbg(ATH6KL_DBG_WMI, "cancel_remain_on_chnl: Unknown " - "channel (freq=%u)\n", freq); - return -EINVAL; - } - cfg80211_remain_on_channel_expired(ar->net_dev, 1, chan, - NL80211_CHAN_NO_HT, GFP_ATOMIC); - - return 0; -} - -static int ath6kl_wmi_tx_status_event_rx(struct wmi *wmi, u8 *datap, int len) -{ - struct wmi_tx_status_event *ev; - u32 id; - struct ath6kl *ar = wmi->parent_dev; - - if (len < sizeof(*ev)) - return -EINVAL; - - ev = (struct wmi_tx_status_event *) datap; - id = le32_to_cpu(ev->id); - ath6kl_dbg(ATH6KL_DBG_WMI, "tx_status: id=%x ack_status=%u\n", - id, ev->ack_status); - if (wmi->last_mgmt_tx_frame) { - cfg80211_mgmt_tx_status(ar->net_dev, id, - wmi->last_mgmt_tx_frame, - wmi->last_mgmt_tx_frame_len, - !!ev->ack_status, GFP_ATOMIC); - kfree(wmi->last_mgmt_tx_frame); - wmi->last_mgmt_tx_frame = NULL; - wmi->last_mgmt_tx_frame_len = 0; - } - - return 0; -} - -static int ath6kl_wmi_rx_probe_req_event_rx(struct wmi *wmi, u8 *datap, int len) -{ - struct wmi_p2p_rx_probe_req_event *ev; - u32 freq; - u16 dlen; - struct ath6kl *ar = wmi->parent_dev; - - if (len < sizeof(*ev)) - return -EINVAL; - - ev = (struct wmi_p2p_rx_probe_req_event *) datap; - freq = le32_to_cpu(ev->freq); - dlen = le16_to_cpu(ev->len); - if (datap + len < ev->data + dlen) { - ath6kl_err("invalid wmi_p2p_rx_probe_req_event: " - "len=%d dlen=%u\n", len, dlen); - return -EINVAL; - } - ath6kl_dbg(ATH6KL_DBG_WMI, "rx_probe_req: len=%u freq=%u " - "probe_req_report=%d\n", - dlen, freq, ar->probe_req_report); - - if (ar->probe_req_report || ar->nw_type == AP_NETWORK) - cfg80211_rx_mgmt(ar->net_dev, freq, ev->data, dlen, GFP_ATOMIC); - - return 0; -} - -static int ath6kl_wmi_p2p_capabilities_event_rx(u8 *datap, int len) -{ - struct wmi_p2p_capabilities_event *ev; - u16 dlen; - - if (len < sizeof(*ev)) - return -EINVAL; - - ev = (struct wmi_p2p_capabilities_event *) datap; - dlen = le16_to_cpu(ev->len); - ath6kl_dbg(ATH6KL_DBG_WMI, "p2p_capab: len=%u\n", dlen); - - return 0; -} - -static int ath6kl_wmi_rx_action_event_rx(struct wmi *wmi, u8 *datap, int len) -{ - struct wmi_rx_action_event *ev; - u32 freq; - u16 dlen; - struct ath6kl *ar = wmi->parent_dev; - - if (len < sizeof(*ev)) - return -EINVAL; - - ev = (struct wmi_rx_action_event *) datap; - freq = le32_to_cpu(ev->freq); - dlen = le16_to_cpu(ev->len); - if (datap + len < ev->data + dlen) { - ath6kl_err("invalid wmi_rx_action_event: " - "len=%d dlen=%u\n", len, dlen); - return -EINVAL; - } - ath6kl_dbg(ATH6KL_DBG_WMI, "rx_action: len=%u freq=%u\n", dlen, freq); - cfg80211_rx_mgmt(ar->net_dev, freq, ev->data, dlen, GFP_ATOMIC); - - return 0; -} - -static int ath6kl_wmi_p2p_info_event_rx(u8 *datap, int len) -{ - struct wmi_p2p_info_event *ev; - u32 flags; - u16 dlen; - - if (len < sizeof(*ev)) - return -EINVAL; - - ev = (struct wmi_p2p_info_event *) datap; - flags = le32_to_cpu(ev->info_req_flags); - dlen = le16_to_cpu(ev->len); - ath6kl_dbg(ATH6KL_DBG_WMI, "p2p_info: flags=%x len=%d\n", flags, dlen); - - if (flags & P2P_FLAG_CAPABILITIES_REQ) { - struct wmi_p2p_capabilities *cap; - if (dlen < sizeof(*cap)) - return -EINVAL; - cap = (struct wmi_p2p_capabilities *) ev->data; - ath6kl_dbg(ATH6KL_DBG_WMI, "p2p_info: GO Power Save = %d\n", - cap->go_power_save); - } - - if (flags & P2P_FLAG_MACADDR_REQ) { - struct wmi_p2p_macaddr *mac; - if (dlen < sizeof(*mac)) - return -EINVAL; - mac = (struct wmi_p2p_macaddr *) ev->data; - ath6kl_dbg(ATH6KL_DBG_WMI, "p2p_info: MAC Address = %pM\n", - mac->mac_addr); - } - - if (flags & P2P_FLAG_HMODEL_REQ) { - struct wmi_p2p_hmodel *mod; - if (dlen < sizeof(*mod)) - return -EINVAL; - mod = (struct wmi_p2p_hmodel *) ev->data; - ath6kl_dbg(ATH6KL_DBG_WMI, "p2p_info: P2P Model = %d (%s)\n", - mod->p2p_model, - mod->p2p_model ? "host" : "firmware"); - } - return 0; -} - static inline struct sk_buff *ath6kl_wmi_get_new_buf(u32 size) { struct sk_buff *skb; @@ -649,84 +478,18 @@ static int ath6kl_wmi_ready_event_rx(struct wmi *wmi, u8 *datap, int len) return 0; } -/* - * Mechanism to modify the roaming behavior in the firmware. The lower rssi - * at which the station has to roam can be passed with - * WMI_SET_LRSSI_SCAN_PARAMS. Subtract 96 from RSSI to get the signal level - * in dBm. - */ -int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi) -{ - struct sk_buff *skb; - struct roam_ctrl_cmd *cmd; - - skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); - if (!skb) - return -ENOMEM; - - cmd = (struct roam_ctrl_cmd *) skb->data; - - cmd->info.params.lrssi_scan_period = cpu_to_le16(DEF_LRSSI_SCAN_PERIOD); - cmd->info.params.lrssi_scan_threshold = a_cpu_to_sle16(lrssi + - DEF_SCAN_FOR_ROAM_INTVL); - cmd->info.params.lrssi_roam_threshold = a_cpu_to_sle16(lrssi); - cmd->info.params.roam_rssi_floor = DEF_LRSSI_ROAM_FLOOR; - cmd->roam_ctrl = WMI_SET_LRSSI_SCAN_PARAMS; - - ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_ROAM_CTRL_CMDID, NO_SYNC_WMIFLAG); - - return 0; -} - static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len) { struct wmi_connect_event *ev; u8 *pie, *peie; - struct ath6kl *ar = wmi->parent_dev; if (len < sizeof(struct wmi_connect_event)) return -EINVAL; ev = (struct wmi_connect_event *) datap; - if (ar->nw_type == AP_NETWORK) { - /* AP mode start/STA connected event */ - struct net_device *dev = ar->net_dev; - if (memcmp(dev->dev_addr, ev->u.ap_bss.bssid, ETH_ALEN) == 0) { - ath6kl_dbg(ATH6KL_DBG_WMI, "%s: freq %d bssid %pM " - "(AP started)\n", - __func__, le16_to_cpu(ev->u.ap_bss.ch), - ev->u.ap_bss.bssid); - ath6kl_connect_ap_mode_bss( - ar, le16_to_cpu(ev->u.ap_bss.ch)); - } else { - ath6kl_dbg(ATH6KL_DBG_WMI, "%s: aid %u mac_addr %pM " - "auth=%u keymgmt=%u cipher=%u apsd_info=%u " - "(STA connected)\n", - __func__, ev->u.ap_sta.aid, - ev->u.ap_sta.mac_addr, - ev->u.ap_sta.auth, - ev->u.ap_sta.keymgmt, - le16_to_cpu(ev->u.ap_sta.cipher), - ev->u.ap_sta.apsd_info); - ath6kl_connect_ap_mode_sta( - ar, ev->u.ap_sta.aid, ev->u.ap_sta.mac_addr, - ev->u.ap_sta.keymgmt, - le16_to_cpu(ev->u.ap_sta.cipher), - ev->u.ap_sta.auth, ev->assoc_req_len, - ev->assoc_info + ev->beacon_ie_len); - } - return 0; - } - - /* STA/IBSS mode connection event */ - - ath6kl_dbg(ATH6KL_DBG_WMI, - "wmi event connect freq %d bssid %pM listen_intvl %d beacon_intvl %d type %d\n", - le16_to_cpu(ev->u.sta.ch), ev->u.sta.bssid, - le16_to_cpu(ev->u.sta.listen_intvl), - le16_to_cpu(ev->u.sta.beacon_intvl), - le32_to_cpu(ev->u.sta.nw_type)); + ath6kl_dbg(ATH6KL_DBG_WMI, "%s: freq %d bssid %pM\n", + __func__, ev->ch, ev->bssid); /* Start of assoc rsp IEs */ pie = ev->assoc_info + ev->beacon_ie_len + @@ -755,92 +518,16 @@ static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len) pie += pie[1] + 2; } - ath6kl_connect_event(wmi->parent_dev, le16_to_cpu(ev->u.sta.ch), - ev->u.sta.bssid, - le16_to_cpu(ev->u.sta.listen_intvl), - le16_to_cpu(ev->u.sta.beacon_intvl), - le32_to_cpu(ev->u.sta.nw_type), + ath6kl_connect_event(wmi->parent_dev, le16_to_cpu(ev->ch), ev->bssid, + le16_to_cpu(ev->listen_intvl), + le16_to_cpu(ev->beacon_intvl), + le32_to_cpu(ev->nw_type), ev->beacon_ie_len, ev->assoc_req_len, ev->assoc_resp_len, ev->assoc_info); return 0; } -static struct country_code_to_enum_rd * -ath6kl_regd_find_country(u16 countryCode) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(allCountries); i++) { - if (allCountries[i].countryCode == countryCode) - return &allCountries[i]; - } - - return NULL; -} - -static struct reg_dmn_pair_mapping * -ath6kl_get_regpair(u16 regdmn) -{ - int i; - - if (regdmn == NO_ENUMRD) - return NULL; - - for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) { - if (regDomainPairs[i].regDmnEnum == regdmn) - return ®DomainPairs[i]; - } - - return NULL; -} - -static struct country_code_to_enum_rd * -ath6kl_regd_find_country_by_rd(u16 regdmn) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(allCountries); i++) { - if (allCountries[i].regDmnEnum == regdmn) - return &allCountries[i]; - } - - return NULL; -} - -static void ath6kl_wmi_regdomain_event(struct wmi *wmi, u8 *datap, int len) -{ - - struct ath6kl_wmi_regdomain *ev; - struct country_code_to_enum_rd *country = NULL; - struct reg_dmn_pair_mapping *regpair = NULL; - char alpha2[2]; - u32 reg_code; - - ev = (struct ath6kl_wmi_regdomain *) datap; - reg_code = le32_to_cpu(ev->reg_code); - - if ((reg_code >> ATH6KL_COUNTRY_RD_SHIFT) & COUNTRY_ERD_FLAG) - country = ath6kl_regd_find_country((u16) reg_code); - else if (!(((u16) reg_code & WORLD_SKU_MASK) == WORLD_SKU_PREFIX)) { - - regpair = ath6kl_get_regpair((u16) reg_code); - country = ath6kl_regd_find_country_by_rd((u16) reg_code); - ath6kl_dbg(ATH6KL_DBG_WMI, "Regpair used: 0x%0x\n", - regpair->regDmnEnum); - } - - if (country) { - alpha2[0] = country->isoName[0]; - alpha2[1] = country->isoName[1]; - - regulatory_hint(wmi->parent_dev->wdev->wiphy, alpha2); - - ath6kl_dbg(ATH6KL_DBG_WMI, "Country alpha2 being used: %c%c\n", - alpha2[0], alpha2[1]); - } -} - static int ath6kl_wmi_disconnect_event_rx(struct wmi *wmi, u8 *datap, int len) { struct wmi_disconnect_event *ev; @@ -851,11 +538,6 @@ static int ath6kl_wmi_disconnect_event_rx(struct wmi *wmi, u8 *datap, int len) ev = (struct wmi_disconnect_event *) datap; - ath6kl_dbg(ATH6KL_DBG_WMI, - "wmi event disconnect proto_reason %d bssid %pM wmi_reason %d assoc_resp_len %d\n", - le16_to_cpu(ev->proto_reason_status), ev->bssid, - ev->disconn_reason, ev->assoc_resp_len); - wmi->is_wmm_enabled = false; wmi->pair_crypto_type = NONE_CRYPT; wmi->grp_crypto_type = NONE_CRYPT; @@ -900,92 +582,315 @@ static int ath6kl_wmi_tkip_micerr_event_rx(struct wmi *wmi, u8 *datap, int len) return 0; } -static int ath6kl_wmi_bssinfo_event_rx(struct wmi *wmi, u8 *datap, int len) +static int ath6kl_wlan_parse_beacon(u8 *buf, int frame_len, + struct ath6kl_common_ie *cie) { - struct wmi_bss_info_hdr2 *bih; - u8 *buf; - struct ieee80211_channel *channel; - struct ath6kl *ar = wmi->parent_dev; - struct ieee80211_mgmt *mgmt; - struct cfg80211_bss *bss; + u8 *frm, *efrm; + u8 elemid_ssid = false; + + frm = buf; + efrm = (u8 *) (frm + frame_len); - if (len <= sizeof(struct wmi_bss_info_hdr2)) + /* + * beacon/probe response frame format + * [8] time stamp + * [2] beacon interval + * [2] capability information + * [tlv] ssid + * [tlv] supported rates + * [tlv] country information + * [tlv] parameter set (FH/DS) + * [tlv] erp information + * [tlv] extended supported rates + * [tlv] WMM + * [tlv] WPA or RSN + * [tlv] Atheros Advanced Capabilities + */ + if ((efrm - frm) < 12) return -EINVAL; - bih = (struct wmi_bss_info_hdr2 *) datap; - buf = datap + sizeof(struct wmi_bss_info_hdr2); - len -= sizeof(struct wmi_bss_info_hdr2); + memset(cie, 0, sizeof(*cie)); - ath6kl_dbg(ATH6KL_DBG_WMI, - "bss info evt - ch %u, snr %d, rssi %d, bssid \"%pM\" " - "frame_type=%d\n", - bih->ch, bih->snr, bih->snr - 95, bih->bssid, - bih->frame_type); - - if (bih->frame_type != BEACON_FTYPE && - bih->frame_type != PROBERESP_FTYPE) - return 0; /* Only update BSS table for now */ - - if (bih->frame_type == BEACON_FTYPE && - test_bit(CLEAR_BSSFILTER_ON_BEACON, &ar->flag)) { - clear_bit(CLEAR_BSSFILTER_ON_BEACON, &ar->flag); - ath6kl_wmi_bssfilter_cmd(ar->wmi, NONE_BSS_FILTER, 0); + cie->ie_tstamp = frm; + frm += 8; + cie->ie_beaconInt = *(u16 *) frm; + frm += 2; + cie->ie_capInfo = *(u16 *) frm; + frm += 2; + cie->ie_chan = 0; + + while (frm < efrm) { + switch (*frm) { + case WLAN_EID_SSID: + if (!elemid_ssid) { + cie->ie_ssid = frm; + elemid_ssid = true; + } + break; + case WLAN_EID_SUPP_RATES: + cie->ie_rates = frm; + break; + case WLAN_EID_COUNTRY: + cie->ie_country = frm; + break; + case WLAN_EID_FH_PARAMS: + break; + case WLAN_EID_DS_PARAMS: + cie->ie_chan = frm[2]; + break; + case WLAN_EID_TIM: + cie->ie_tim = frm; + break; + case WLAN_EID_IBSS_PARAMS: + break; + case WLAN_EID_EXT_SUPP_RATES: + cie->ie_xrates = frm; + break; + case WLAN_EID_ERP_INFO: + if (frm[1] != 1) + return -EINVAL; + + cie->ie_erp = frm[2]; + break; + case WLAN_EID_RSN: + cie->ie_rsn = frm; + break; + case WLAN_EID_HT_CAPABILITY: + cie->ie_htcap = frm; + break; + case WLAN_EID_HT_INFORMATION: + cie->ie_htop = frm; + break; + case WLAN_EID_VENDOR_SPECIFIC: + if (frm[1] > 3 && frm[2] == 0x00 && frm[3] == 0x50 && + frm[4] == 0xf2) { + /* OUT Type (00:50:F2) */ + + if (frm[5] == WPA_OUI_TYPE) { + /* WPA OUT */ + cie->ie_wpa = frm; + } else if (frm[5] == WMM_OUI_TYPE) { + /* WMM OUT */ + cie->ie_wmm = frm; + } else if (frm[5] == WSC_OUT_TYPE) { + /* WSC OUT */ + cie->ie_wsc = frm; + } + + } else if (frm[1] > 3 && frm[2] == 0x00 + && frm[3] == 0x03 && frm[4] == 0x7f + && frm[5] == ATH_OUI_TYPE) { + /* Atheros OUI (00:03:7f) */ + cie->ie_ath = frm; + } + break; + default: + break; + } + frm += frm[1] + 2; } - channel = ieee80211_get_channel(ar->wdev->wiphy, le16_to_cpu(bih->ch)); - if (channel == NULL) + if ((cie->ie_rates == NULL) + || (cie->ie_rates[1] > ATH6KL_RATE_MAXSIZE)) return -EINVAL; - if (len < 8 + 2 + 2) + if ((cie->ie_ssid == NULL) + || (cie->ie_ssid[1] > IEEE80211_MAX_SSID_LEN)) + return -EINVAL; + + return 0; +} + +static int ath6kl_wmi_bssinfo_event_rx(struct wmi *wmi, u8 *datap, int len) +{ + struct bss *bss = NULL; + struct wmi_bss_info_hdr *bih; + u8 cached_ssid_len = 0; + u8 cached_ssid[IEEE80211_MAX_SSID_LEN] = { 0 }; + u8 beacon_ssid_len = 0; + u8 *buf, *ie_ssid; + u8 *ni_buf; + int buf_len; + + int ret; + + if (len <= sizeof(struct wmi_bss_info_hdr)) return -EINVAL; - if (bih->frame_type == BEACON_FTYPE && test_bit(CONNECTED, &ar->flag) && - memcmp(bih->bssid, ar->bssid, ETH_ALEN) == 0) { - const u8 *tim; - tim = cfg80211_find_ie(WLAN_EID_TIM, buf + 8 + 2 + 2, - len - 8 - 2 - 2); - if (tim && tim[1] >= 2) { - ar->assoc_bss_dtim_period = tim[3]; - set_bit(DTIM_PERIOD_AVAIL, &ar->flag); + bih = (struct wmi_bss_info_hdr *) datap; + bss = wlan_find_node(&wmi->parent_dev->scan_table, bih->bssid); + + if (a_sle16_to_cpu(bih->rssi) > 0) { + if (bss == NULL) + return 0; + else + bih->rssi = a_cpu_to_sle16(bss->ni_rssi); + } + + buf = datap + sizeof(struct wmi_bss_info_hdr); + len -= sizeof(struct wmi_bss_info_hdr); + + ath6kl_dbg(ATH6KL_DBG_WMI, + "bss info evt - ch %u, rssi %02x, bssid \"%pM\"\n", + bih->ch, a_sle16_to_cpu(bih->rssi), bih->bssid); + + if (bss != NULL) { + /* + * Free up the node. We are about to allocate a new node. + * In case of hidden AP, beacon will not have ssid, + * but a directed probe response will have it, + * so cache the probe-resp-ssid if already present. + */ + if (wmi->is_probe_ssid && (bih->frame_type == BEACON_FTYPE)) { + ie_ssid = bss->ni_cie.ie_ssid; + if (ie_ssid && (ie_ssid[1] <= IEEE80211_MAX_SSID_LEN) && + (ie_ssid[2] != 0)) { + cached_ssid_len = ie_ssid[1]; + memcpy(cached_ssid, ie_ssid + 2, + cached_ssid_len); + } } + + /* + * Use the current average rssi of associated AP base on + * assumption + * 1. Most os with GUI will update RSSI by + * ath6kl_wmi_get_stats_cmd() periodically. + * 2. ath6kl_wmi_get_stats_cmd(..) will be called when calling + * ath6kl_wmi_startscan_cmd(...) + * The average value of RSSI give end-user better feeling for + * instance value of scan result. It also sync up RSSI info + * in GUI between scan result and RSSI signal icon. + */ + if (memcmp(wmi->parent_dev->bssid, bih->bssid, ETH_ALEN) == 0) { + bih->rssi = a_cpu_to_sle16(bss->ni_rssi); + bih->snr = bss->ni_snr; + } + + wlan_node_reclaim(&wmi->parent_dev->scan_table, bss); } /* - * In theory, use of cfg80211_inform_bss() would be more natural here - * since we do not have the full frame. However, at least for now, - * cfg80211 can only distinguish Beacon and Probe Response frames from - * each other when using cfg80211_inform_bss_frame(), so let's build a - * fake IEEE 802.11 header to be able to take benefit of this. + * beacon/probe response frame format + * [8] time stamp + * [2] beacon interval + * [2] capability information + * [tlv] ssid + */ + beacon_ssid_len = buf[SSID_IE_LEN_INDEX]; + + /* + * If ssid is cached for this hidden AP, then change + * buffer len accordingly. */ - mgmt = kmalloc(24 + len, GFP_ATOMIC); - if (mgmt == NULL) + if (wmi->is_probe_ssid && (bih->frame_type == BEACON_FTYPE) && + (cached_ssid_len != 0) && + (beacon_ssid_len == 0 || (cached_ssid_len > beacon_ssid_len && + buf[SSID_IE_LEN_INDEX + 1] == 0))) { + + len += (cached_ssid_len - beacon_ssid_len); + } + + bss = wlan_node_alloc(len); + if (!bss) + return -ENOMEM; + + bss->ni_snr = bih->snr; + bss->ni_rssi = a_sle16_to_cpu(bih->rssi); + + if (WARN_ON(!bss->ni_buf)) return -EINVAL; - if (bih->frame_type == BEACON_FTYPE) { - mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | - IEEE80211_STYPE_BEACON); - memset(mgmt->da, 0xff, ETH_ALEN); - } else { - struct net_device *dev = ar->net_dev; + /* + * In case of hidden AP, beacon will not have ssid, + * but a directed probe response will have it, + * so place the cached-ssid(probe-resp) in the bss info. + */ + if (wmi->is_probe_ssid && (bih->frame_type == BEACON_FTYPE) && + (cached_ssid_len != 0) && + (beacon_ssid_len == 0 || (beacon_ssid_len && + buf[SSID_IE_LEN_INDEX + 1] == 0))) { + ni_buf = bss->ni_buf; + buf_len = len; + + /* + * Copy the first 14 bytes: + * time-stamp(8), beacon-interval(2), + * cap-info(2), ssid-id(1), ssid-len(1). + */ + memcpy(ni_buf, buf, SSID_IE_LEN_INDEX + 1); + + ni_buf[SSID_IE_LEN_INDEX] = cached_ssid_len; + ni_buf += (SSID_IE_LEN_INDEX + 1); + + buf += (SSID_IE_LEN_INDEX + 1); + buf_len -= (SSID_IE_LEN_INDEX + 1); + + memcpy(ni_buf, cached_ssid, cached_ssid_len); + ni_buf += cached_ssid_len; + + buf += beacon_ssid_len; + buf_len -= beacon_ssid_len; + + if (cached_ssid_len > beacon_ssid_len) + buf_len -= (cached_ssid_len - beacon_ssid_len); + + memcpy(ni_buf, buf, buf_len); + } else + memcpy(bss->ni_buf, buf, len); + + bss->ni_framelen = len; + + ret = ath6kl_wlan_parse_beacon(bss->ni_buf, len, &bss->ni_cie); + if (ret) { + wlan_node_free(bss); + return -EINVAL; + } + + /* + * Update the frequency in ie_chan, overwriting of channel number + * which is done in ath6kl_wlan_parse_beacon + */ + bss->ni_cie.ie_chan = le16_to_cpu(bih->ch); + wlan_setup_node(&wmi->parent_dev->scan_table, bss, bih->bssid); + + return 0; +} - mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | - IEEE80211_STYPE_PROBE_RESP); - memcpy(mgmt->da, dev->dev_addr, ETH_ALEN); +static int ath6kl_wmi_opt_frame_event_rx(struct wmi *wmi, u8 *datap, int len) +{ + struct bss *bss; + struct wmi_opt_rx_info_hdr *bih; + u8 *buf; + + if (len <= sizeof(struct wmi_opt_rx_info_hdr)) + return -EINVAL; + + bih = (struct wmi_opt_rx_info_hdr *) datap; + buf = datap + sizeof(struct wmi_opt_rx_info_hdr); + len -= sizeof(struct wmi_opt_rx_info_hdr); + + ath6kl_dbg(ATH6KL_DBG_WMI, "opt frame event %2.2x:%2.2x\n", + bih->bssid[4], bih->bssid[5]); + + bss = wlan_find_node(&wmi->parent_dev->scan_table, bih->bssid); + if (bss != NULL) { + /* Free up the node. We are about to allocate a new node. */ + wlan_node_reclaim(&wmi->parent_dev->scan_table, bss); } - mgmt->duration = cpu_to_le16(0); - memcpy(mgmt->sa, bih->bssid, ETH_ALEN); - memcpy(mgmt->bssid, bih->bssid, ETH_ALEN); - mgmt->seq_ctrl = cpu_to_le16(0); - - memcpy(&mgmt->u.beacon, buf, len); - - bss = cfg80211_inform_bss_frame(ar->wdev->wiphy, channel, mgmt, - 24 + len, (bih->snr - 95) * 100, - GFP_ATOMIC); - kfree(mgmt); - if (bss == NULL) + + bss = wlan_node_alloc(len); + if (!bss) return -ENOMEM; - cfg80211_put_bss(bss); + + bss->ni_snr = bih->snr; + bss->ni_cie.ie_chan = le16_to_cpu(bih->ch); + + if (WARN_ON(!bss->ni_buf)) + return -EINVAL; + + memcpy(bss->ni_buf, buf, len); + wlan_setup_node(&wmi->parent_dev->scan_table, bss, bih->bssid); return 0; } @@ -1044,13 +949,6 @@ static int ath6kl_wmi_bitrate_reply_rx(struct wmi *wmi, u8 *datap, int len) return 0; } -static int ath6kl_wmi_tcmd_test_report_rx(struct wmi *wmi, u8 *datap, int len) -{ - ath6kl_tm_rx_report_event(wmi->parent_dev, datap, len); - - return 0; -} - static int ath6kl_wmi_ratemask_reply_rx(struct wmi *wmi, u8 *datap, int len) { if (len < sizeof(struct wmi_fix_rates_reply)) @@ -1100,41 +998,15 @@ static int ath6kl_wmi_scan_complete_rx(struct wmi *wmi, u8 *datap, int len) ev = (struct wmi_scan_complete_event *) datap; + if (a_sle32_to_cpu(ev->status) == 0) + wlan_refresh_inactive_nodes(wmi->parent_dev); + ath6kl_scan_complete_evt(wmi->parent_dev, a_sle32_to_cpu(ev->status)); wmi->is_probe_ssid = false; return 0; } -static int ath6kl_wmi_neighbor_report_event_rx(struct wmi *wmi, u8 *datap, - int len) -{ - struct wmi_neighbor_report_event *ev; - u8 i; - - if (len < sizeof(*ev)) - return -EINVAL; - ev = (struct wmi_neighbor_report_event *) datap; - if (sizeof(*ev) + ev->num_neighbors * sizeof(struct wmi_neighbor_info) - > len) { - ath6kl_dbg(ATH6KL_DBG_WMI, "truncated neighbor event " - "(num=%d len=%d)\n", ev->num_neighbors, len); - return -EINVAL; - } - for (i = 0; i < ev->num_neighbors; i++) { - ath6kl_dbg(ATH6KL_DBG_WMI, "neighbor %d/%d - %pM 0x%x\n", - i + 1, ev->num_neighbors, ev->neighbor[i].bssid, - ev->neighbor[i].bss_flags); - cfg80211_pmksa_candidate_notify(wmi->parent_dev->net_dev, i, - ev->neighbor[i].bssid, - !!(ev->neighbor[i].bss_flags & - WMI_PREAUTH_CAPABLE_BSS), - GFP_ATOMIC); - } - - return 0; -} - /* * Target is reporting a programming error. This is for * developer aid only. Target only checks a few common violations @@ -1538,11 +1410,6 @@ int ath6kl_wmi_cmd_send(struct wmi *wmi, struct sk_buff *skb, if (WARN_ON(skb == NULL)) return -EINVAL; - ath6kl_dbg(ATH6KL_DBG_WMI, "wmi tx id %d len %d flag %d\n", - cmd_id, skb->len, sync_flag); - ath6kl_dbg_dump(ATH6KL_DBG_WMI_DUMP, NULL, "wmi tx ", - skb->data, skb->len); - if (sync_flag >= END_WMIFLAG) { dev_kfree_skb(skb); return -EINVAL; @@ -1601,13 +1468,6 @@ int ath6kl_wmi_connect_cmd(struct wmi *wmi, enum network_type nw_type, struct wmi_connect_cmd *cc; int ret; - ath6kl_dbg(ATH6KL_DBG_WMI, - "wmi connect bssid %pM freq %d flags 0x%x ssid_len %d " - "type %d dot11_auth %d auth %d pairwise %d group %d\n", - bssid, channel, ctrl_flags, ssid_len, nw_type, - dot11_auth_mode, auth_mode, pairwise_crypto, group_crypto); - ath6kl_dbg_dump(ATH6KL_DBG_WMI, NULL, "ssid ", ssid, ssid_len); - wmi->traffic_class = 100; if ((pairwise_crypto == NONE_CRYPT) && (group_crypto != NONE_CRYPT)) @@ -1653,9 +1513,6 @@ int ath6kl_wmi_reconnect_cmd(struct wmi *wmi, u8 *bssid, u16 channel) struct wmi_reconnect_cmd *cc; int ret; - ath6kl_dbg(ATH6KL_DBG_WMI, "wmi reconnect bssid %pM freq %d\n", - bssid, channel); - wmi->traffic_class = 100; skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_reconnect_cmd)); @@ -1678,8 +1535,6 @@ int ath6kl_wmi_disconnect_cmd(struct wmi *wmi) { int ret; - ath6kl_dbg(ATH6KL_DBG_WMI, "wmi disconnect\n"); - wmi->traffic_class = 100; /* Disconnect command does not need to do a SYNC before. */ @@ -1696,7 +1551,7 @@ int ath6kl_wmi_startscan_cmd(struct wmi *wmi, enum wmi_scan_type scan_type, struct sk_buff *skb; struct wmi_start_scan_cmd *sc; s8 size; - int i, ret; + int ret; size = sizeof(struct wmi_start_scan_cmd); @@ -1721,8 +1576,8 @@ int ath6kl_wmi_startscan_cmd(struct wmi *wmi, enum wmi_scan_type scan_type, sc->force_scan_intvl = cpu_to_le32(force_scan_interval); sc->num_ch = num_chan; - for (i = 0; i < num_chan; i++) - sc->ch_list[i] = cpu_to_le16(ch_list[i]); + if (num_chan) + memcpy(sc->ch_list, ch_list, num_chan * sizeof(u16)); ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_START_SCAN_CMDID, NO_SYNC_WMIFLAG); @@ -1915,10 +1770,6 @@ int ath6kl_wmi_addkey_cmd(struct wmi *wmi, u8 key_index, struct wmi_add_cipher_key_cmd *cmd; int ret; - ath6kl_dbg(ATH6KL_DBG_WMI, "addkey cmd: key_index=%u key_type=%d " - "key_usage=%d key_len=%d key_op_ctrl=%d\n", - key_index, key_type, key_usage, key_len, key_op_ctrl); - if ((key_index > WMI_MAX_KEY_INDEX) || (key_len > WMI_MAX_KEY_LEN) || (key_material == NULL)) return -EINVAL; @@ -2360,25 +2211,6 @@ int ath6kl_wmi_get_challenge_resp_cmd(struct wmi *wmi, u32 cookie, u32 source) return ret; } -int ath6kl_wmi_config_debug_module_cmd(struct wmi *wmi, u32 valid, u32 config) -{ - struct ath6kl_wmix_dbglog_cfg_module_cmd *cmd; - struct sk_buff *skb; - int ret; - - skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); - if (!skb) - return -ENOMEM; - - cmd = (struct ath6kl_wmix_dbglog_cfg_module_cmd *) skb->data; - cmd->valid = cpu_to_le32(valid); - cmd->config = cpu_to_le32(config); - - ret = ath6kl_wmi_cmd_send_xtnd(wmi, skb, WMIX_DBGLOG_CFG_MODULE_CMDID, - NO_SYNC_WMIFLAG); - return ret; -} - int ath6kl_wmi_get_stats_cmd(struct wmi *wmi) { return ath6kl_wmi_simple_cmd(wmi, WMI_GET_STATISTICS_CMDID); @@ -2484,29 +2316,49 @@ int ath6kl_wmi_set_keepalive_cmd(struct wmi *wmi, u8 keep_alive_intvl) return ret; } -int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len) +s32 ath6kl_wmi_get_rate(s8 rate_index) { - struct sk_buff *skb; - int ret; + if (rate_index == RATE_AUTO) + return 0; - skb = ath6kl_wmi_get_new_buf(len); - if (!skb) - return -ENOMEM; + return wmi_rate_tbl[(u32) rate_index][0]; +} - memcpy(skb->data, buf, len); +void ath6kl_wmi_node_return(struct wmi *wmi, struct bss *bss) +{ + if (bss) + wlan_node_return(&wmi->parent_dev->scan_table, bss); +} - ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_TEST_CMDID, NO_SYNC_WMIFLAG); +struct bss *ath6kl_wmi_find_ssid_node(struct wmi *wmi, u8 * ssid, + u32 ssid_len, bool is_wpa2, + bool match_ssid) +{ + struct bss *node = NULL; - return ret; + node = wlan_find_ssid_node(&wmi->parent_dev->scan_table, ssid, + ssid_len, is_wpa2, match_ssid); + return node; } +struct bss *ath6kl_wmi_find_node(struct wmi *wmi, const u8 * mac_addr) +{ + struct bss *ni = NULL; -s32 ath6kl_wmi_get_rate(s8 rate_index) + ni = wlan_find_node(&wmi->parent_dev->scan_table, mac_addr); + + return ni; +} + +void ath6kl_wmi_node_free(struct wmi *wmi, const u8 * mac_addr) { - if (rate_index == RATE_AUTO) - return 0; + struct bss *ni = NULL; - return wmi_rate_tbl[(u32) rate_index][0]; + ni = wlan_find_node(&wmi->parent_dev->scan_table, mac_addr); + if (ni != NULL) + wlan_node_reclaim(&wmi->parent_dev->scan_table, ni); + + return; } static int ath6kl_wmi_get_pmkid_list_event_rx(struct wmi *wmi, u8 *datap, @@ -2548,47 +2400,6 @@ static int ath6kl_wmi_delba_req_event_rx(struct wmi *wmi, u8 *datap, int len) } /* AP mode functions */ - -int ath6kl_wmi_ap_profile_commit(struct wmi *wmip, struct wmi_connect_cmd *p) -{ - struct sk_buff *skb; - struct wmi_connect_cmd *cm; - int res; - - skb = ath6kl_wmi_get_new_buf(sizeof(*cm)); - if (!skb) - return -ENOMEM; - - cm = (struct wmi_connect_cmd *) skb->data; - memcpy(cm, p, sizeof(*cm)); - - res = ath6kl_wmi_cmd_send(wmip, skb, WMI_AP_CONFIG_COMMIT_CMDID, - NO_SYNC_WMIFLAG); - ath6kl_dbg(ATH6KL_DBG_WMI, "%s: nw_type=%u auth_mode=%u ch=%u " - "ctrl_flags=0x%x-> res=%d\n", - __func__, p->nw_type, p->auth_mode, le16_to_cpu(p->ch), - le32_to_cpu(p->ctrl_flags), res); - return res; -} - -int ath6kl_wmi_ap_set_mlme(struct wmi *wmip, u8 cmd, const u8 *mac, u16 reason) -{ - struct sk_buff *skb; - struct wmi_ap_set_mlme_cmd *cm; - - skb = ath6kl_wmi_get_new_buf(sizeof(*cm)); - if (!skb) - return -ENOMEM; - - cm = (struct wmi_ap_set_mlme_cmd *) skb->data; - memcpy(cm->mac, mac, ETH_ALEN); - cm->reason = cpu_to_le16(reason); - cm->cmd = cmd; - - return ath6kl_wmi_cmd_send(wmip, skb, WMI_AP_SET_MLME_CMDID, - NO_SYNC_WMIFLAG); -} - static int ath6kl_wmi_pspoll_event_rx(struct wmi *wmi, u8 *datap, int len) { struct wmi_pspoll_event *ev; @@ -2622,7 +2433,6 @@ int ath6kl_wmi_set_pvb_cmd(struct wmi *wmi, u16 aid, bool flag) cmd = (struct wmi_ap_set_pvb_cmd *) skb->data; cmd->aid = cpu_to_le16(aid); - cmd->rsvd = cpu_to_le16(0); cmd->flag = cpu_to_le32(flag); ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_AP_SET_PVB_CMDID, @@ -2654,160 +2464,6 @@ int ath6kl_wmi_set_rx_frame_format_cmd(struct wmi *wmi, u8 rx_meta_ver, return ret; } -int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 mgmt_frm_type, const u8 *ie, - u8 ie_len) -{ - struct sk_buff *skb; - struct wmi_set_appie_cmd *p; - - skb = ath6kl_wmi_get_new_buf(sizeof(*p) + ie_len); - if (!skb) - return -ENOMEM; - - ath6kl_dbg(ATH6KL_DBG_WMI, "set_appie_cmd: mgmt_frm_type=%u " - "ie_len=%u\n", mgmt_frm_type, ie_len); - p = (struct wmi_set_appie_cmd *) skb->data; - p->mgmt_frm_type = mgmt_frm_type; - p->ie_len = ie_len; - memcpy(p->ie_info, ie, ie_len); - return ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_APPIE_CMDID, - NO_SYNC_WMIFLAG); -} - -int ath6kl_wmi_disable_11b_rates_cmd(struct wmi *wmi, bool disable) -{ - struct sk_buff *skb; - struct wmi_disable_11b_rates_cmd *cmd; - - skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); - if (!skb) - return -ENOMEM; - - ath6kl_dbg(ATH6KL_DBG_WMI, "disable_11b_rates_cmd: disable=%u\n", - disable); - cmd = (struct wmi_disable_11b_rates_cmd *) skb->data; - cmd->disable = disable ? 1 : 0; - - return ath6kl_wmi_cmd_send(wmi, skb, WMI_DISABLE_11B_RATES_CMDID, - NO_SYNC_WMIFLAG); -} - -int ath6kl_wmi_remain_on_chnl_cmd(struct wmi *wmi, u32 freq, u32 dur) -{ - struct sk_buff *skb; - struct wmi_remain_on_chnl_cmd *p; - - skb = ath6kl_wmi_get_new_buf(sizeof(*p)); - if (!skb) - return -ENOMEM; - - ath6kl_dbg(ATH6KL_DBG_WMI, "remain_on_chnl_cmd: freq=%u dur=%u\n", - freq, dur); - p = (struct wmi_remain_on_chnl_cmd *) skb->data; - p->freq = cpu_to_le32(freq); - p->duration = cpu_to_le32(dur); - return ath6kl_wmi_cmd_send(wmi, skb, WMI_REMAIN_ON_CHNL_CMDID, - NO_SYNC_WMIFLAG); -} - -int ath6kl_wmi_send_action_cmd(struct wmi *wmi, u32 id, u32 freq, u32 wait, - const u8 *data, u16 data_len) -{ - struct sk_buff *skb; - struct wmi_send_action_cmd *p; - u8 *buf; - - if (wait) - return -EINVAL; /* Offload for wait not supported */ - - buf = kmalloc(data_len, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - skb = ath6kl_wmi_get_new_buf(sizeof(*p) + data_len); - if (!skb) { - kfree(buf); - return -ENOMEM; - } - - kfree(wmi->last_mgmt_tx_frame); - wmi->last_mgmt_tx_frame = buf; - wmi->last_mgmt_tx_frame_len = data_len; - - ath6kl_dbg(ATH6KL_DBG_WMI, "send_action_cmd: id=%u freq=%u wait=%u " - "len=%u\n", id, freq, wait, data_len); - p = (struct wmi_send_action_cmd *) skb->data; - p->id = cpu_to_le32(id); - p->freq = cpu_to_le32(freq); - p->wait = cpu_to_le32(wait); - p->len = cpu_to_le16(data_len); - memcpy(p->data, data, data_len); - return ath6kl_wmi_cmd_send(wmi, skb, WMI_SEND_ACTION_CMDID, - NO_SYNC_WMIFLAG); -} - -int ath6kl_wmi_send_probe_response_cmd(struct wmi *wmi, u32 freq, - const u8 *dst, - const u8 *data, u16 data_len) -{ - struct sk_buff *skb; - struct wmi_p2p_probe_response_cmd *p; - - skb = ath6kl_wmi_get_new_buf(sizeof(*p) + data_len); - if (!skb) - return -ENOMEM; - - ath6kl_dbg(ATH6KL_DBG_WMI, "send_probe_response_cmd: freq=%u dst=%pM " - "len=%u\n", freq, dst, data_len); - p = (struct wmi_p2p_probe_response_cmd *) skb->data; - p->freq = cpu_to_le32(freq); - memcpy(p->destination_addr, dst, ETH_ALEN); - p->len = cpu_to_le16(data_len); - memcpy(p->data, data, data_len); - return ath6kl_wmi_cmd_send(wmi, skb, WMI_SEND_PROBE_RESPONSE_CMDID, - NO_SYNC_WMIFLAG); -} - -int ath6kl_wmi_probe_report_req_cmd(struct wmi *wmi, bool enable) -{ - struct sk_buff *skb; - struct wmi_probe_req_report_cmd *p; - - skb = ath6kl_wmi_get_new_buf(sizeof(*p)); - if (!skb) - return -ENOMEM; - - ath6kl_dbg(ATH6KL_DBG_WMI, "probe_report_req_cmd: enable=%u\n", - enable); - p = (struct wmi_probe_req_report_cmd *) skb->data; - p->enable = enable ? 1 : 0; - return ath6kl_wmi_cmd_send(wmi, skb, WMI_PROBE_REQ_REPORT_CMDID, - NO_SYNC_WMIFLAG); -} - -int ath6kl_wmi_info_req_cmd(struct wmi *wmi, u32 info_req_flags) -{ - struct sk_buff *skb; - struct wmi_get_p2p_info *p; - - skb = ath6kl_wmi_get_new_buf(sizeof(*p)); - if (!skb) - return -ENOMEM; - - ath6kl_dbg(ATH6KL_DBG_WMI, "info_req_cmd: flags=%x\n", - info_req_flags); - p = (struct wmi_get_p2p_info *) skb->data; - p->info_req_flags = cpu_to_le32(info_req_flags); - return ath6kl_wmi_cmd_send(wmi, skb, WMI_GET_P2P_INFO_CMDID, - NO_SYNC_WMIFLAG); -} - -int ath6kl_wmi_cancel_remain_on_chnl_cmd(struct wmi *wmi) -{ - ath6kl_dbg(ATH6KL_DBG_WMI, "cancel_remain_on_chnl_cmd\n"); - return ath6kl_wmi_simple_cmd(wmi, WMI_CANCEL_REMAIN_ON_CHNL_CMDID); -} - static int ath6kl_wmi_control_rx_xtnd(struct wmi *wmi, struct sk_buff *skb) { struct wmix_cmd_hdr *cmd; @@ -2832,14 +2488,11 @@ static int ath6kl_wmi_control_rx_xtnd(struct wmi *wmi, struct sk_buff *skb) switch (id) { case WMIX_HB_CHALLENGE_RESP_EVENTID: - ath6kl_dbg(ATH6KL_DBG_WMI, "wmi event hb challenge resp\n"); break; case WMIX_DBGLOG_EVENTID: - ath6kl_dbg(ATH6KL_DBG_WMI, "wmi event dbglog len %d\n", len); - ath6kl_debug_fwlog_event(wmi->parent_dev, datap, len); break; default: - ath6kl_warn("unknown cmd id 0x%x\n", id); + ath6kl_err("unknown cmd id 0x%x\n", id); wmi->stat.cmd_id_err++; ret = -EINVAL; break; @@ -2875,9 +2528,8 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb) datap = skb->data; len = skb->len; - ath6kl_dbg(ATH6KL_DBG_WMI, "wmi rx id %d len %d\n", id, len); - ath6kl_dbg_dump(ATH6KL_DBG_WMI_DUMP, NULL, "wmi rx ", - datap, len); + ath6kl_dbg(ATH6KL_DBG_WMI, "%s: wmi id: %d\n", __func__, id); + ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "msg payload ", datap, len); switch (id) { case WMI_GET_BITRATE_CMDID: @@ -2914,11 +2566,11 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb) break; case WMI_BSSINFO_EVENTID: ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_BSSINFO_EVENTID\n"); - ret = ath6kl_wmi_bssinfo_event_rx(wmi, datap, len); + ath6kl_wmi_convert_bssinfo_hdr2_to_hdr(skb, datap); + ret = ath6kl_wmi_bssinfo_event_rx(wmi, skb->data, skb->len); break; case WMI_REGDOMAIN_EVENTID: ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REGDOMAIN_EVENTID\n"); - ath6kl_wmi_regdomain_event(wmi, datap, len); break; case WMI_PSTREAM_TIMEOUT_EVENTID: ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_PSTREAM_TIMEOUT_EVENTID\n"); @@ -2926,7 +2578,6 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb) break; case WMI_NEIGHBOR_REPORT_EVENTID: ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_NEIGHBOR_REPORT_EVENTID\n"); - ret = ath6kl_wmi_neighbor_report_event_rx(wmi, datap, len); break; case WMI_SCAN_COMPLETE_EVENTID: ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_SCAN_COMPLETE_EVENTID\n"); @@ -2949,7 +2600,7 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb) break; case WMI_OPT_RX_FRAME_EVENTID: ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_OPT_RX_FRAME_EVENTID\n"); - /* this event has been deprecated */ + ret = ath6kl_wmi_opt_frame_event_rx(wmi, datap, len); break; case WMI_REPORT_ROAM_TBL_EVENTID: ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REPORT_ROAM_TBL_EVENTID\n"); @@ -2968,10 +2619,6 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb) case WMI_REPORT_ROAM_DATA_EVENTID: ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REPORT_ROAM_DATA_EVENTID\n"); break; - case WMI_TEST_EVENTID: - ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TEST_EVENTID\n"); - ret = ath6kl_wmi_tcmd_test_report_rx(wmi, datap, len); - break; case WMI_GET_FIXRATES_CMDID: ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_FIXRATES_CMDID\n"); ret = ath6kl_wmi_ratemask_reply_rx(wmi, datap, len); @@ -3036,36 +2683,6 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb) ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TX_COMPLETE_EVENTID\n"); ret = ath6kl_wmi_tx_complete_event_rx(datap, len); break; - case WMI_REMAIN_ON_CHNL_EVENTID: - ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REMAIN_ON_CHNL_EVENTID\n"); - ret = ath6kl_wmi_remain_on_chnl_event_rx(wmi, datap, len); - break; - case WMI_CANCEL_REMAIN_ON_CHNL_EVENTID: - ath6kl_dbg(ATH6KL_DBG_WMI, - "WMI_CANCEL_REMAIN_ON_CHNL_EVENTID\n"); - ret = ath6kl_wmi_cancel_remain_on_chnl_event_rx(wmi, datap, - len); - break; - case WMI_TX_STATUS_EVENTID: - ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TX_STATUS_EVENTID\n"); - ret = ath6kl_wmi_tx_status_event_rx(wmi, datap, len); - break; - case WMI_RX_PROBE_REQ_EVENTID: - ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_RX_PROBE_REQ_EVENTID\n"); - ret = ath6kl_wmi_rx_probe_req_event_rx(wmi, datap, len); - break; - case WMI_P2P_CAPABILITIES_EVENTID: - ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_P2P_CAPABILITIES_EVENTID\n"); - ret = ath6kl_wmi_p2p_capabilities_event_rx(datap, len); - break; - case WMI_RX_ACTION_EVENTID: - ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_RX_ACTION_EVENTID\n"); - ret = ath6kl_wmi_rx_action_event_rx(wmi, datap, len); - break; - case WMI_P2P_INFO_EVENTID: - ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_P2P_INFO_EVENTID\n"); - ret = ath6kl_wmi_p2p_info_event_rx(datap, len); - break; default: ath6kl_dbg(ATH6KL_DBG_WMI, "unknown cmd id 0x%x\n", id); wmi->stat.cmd_id_err++; @@ -3122,6 +2739,5 @@ void ath6kl_wmi_shutdown(struct wmi *wmi) if (!wmi) return; - kfree(wmi->last_mgmt_tx_frame); kfree(wmi); } diff --git a/trunk/drivers/net/wireless/ath/ath6kl/wmi.h b/trunk/drivers/net/wireless/ath/ath6kl/wmi.h index f8e644d54aa7..fe3ddce64087 100644 --- a/trunk/drivers/net/wireless/ath/ath6kl/wmi.h +++ b/trunk/drivers/net/wireless/ath/ath6kl/wmi.h @@ -129,9 +129,6 @@ struct wmi { u8 ht_allowed[A_NUM_BANDS]; u8 traffic_class; bool is_probe_ssid; - - u8 *last_mgmt_tx_frame; - size_t last_mgmt_tx_frame_len; }; struct host_app_area { @@ -493,61 +490,17 @@ enum wmi_cmd_id { WMI_SET_PASSPHRASE_CMDID, WMI_SEND_ASSOC_RES_CMDID, WMI_SET_ASSOC_REQ_RELAY_CMDID, + WMI_GET_RFKILL_MODE_CMDID, /* ACS command, consists of sub-commands */ WMI_ACS_CTRL_CMDID, - WMI_SET_EXCESS_TX_RETRY_THRES_CMDID, - WMI_SET_TBD_TIME_CMDID, /*added for wmiconfig command for TBD */ - - /* Pktlog cmds */ - WMI_PKTLOG_ENABLE_CMDID, - WMI_PKTLOG_DISABLE_CMDID, - - /* More P2P Cmds */ - WMI_P2P_GO_NEG_REQ_RSP_CMDID, - WMI_P2P_GRP_INIT_CMDID, - WMI_P2P_GRP_FORMATION_DONE_CMDID, - WMI_P2P_INVITE_CMDID, - WMI_P2P_INVITE_REQ_RSP_CMDID, - WMI_P2P_PROV_DISC_REQ_CMDID, - WMI_P2P_SET_CMDID, - - WMI_GET_RFKILL_MODE_CMDID, - WMI_SET_RFKILL_MODE_CMDID, - WMI_AP_SET_APSD_CMDID, - WMI_AP_APSD_BUFFERED_TRAFFIC_CMDID, - WMI_P2P_SDPD_TX_CMDID, /* F05C */ - WMI_P2P_STOP_SDPD_CMDID, - WMI_P2P_CANCEL_CMDID, /* Ultra low power store / recall commands */ WMI_STORERECALL_CONFIGURE_CMDID, WMI_STORERECALL_RECALL_CMDID, WMI_STORERECALL_HOST_READY_CMDID, WMI_FORCE_TARGET_ASSERT_CMDID, - - WMI_SET_PROBED_SSID_EX_CMDID, - WMI_SET_NETWORK_LIST_OFFLOAD_CMDID, - WMI_SET_ARP_NS_OFFLOAD_CMDID, - WMI_ADD_WOW_EXT_PATTERN_CMDID, - WMI_GTK_OFFLOAD_OP_CMDID, - WMI_REMAIN_ON_CHNL_CMDID, - WMI_CANCEL_REMAIN_ON_CHNL_CMDID, - WMI_SEND_ACTION_CMDID, - WMI_PROBE_REQ_REPORT_CMDID, - WMI_DISABLE_11B_RATES_CMDID, - WMI_SEND_PROBE_RESPONSE_CMDID, - WMI_GET_P2P_INFO_CMDID, - WMI_AP_JOIN_BSS_CMDID, -}; - -enum wmi_mgmt_frame_type { - WMI_FRAME_BEACON = 0, - WMI_FRAME_PROBE_REQ, - WMI_FRAME_PROBE_RESP, - WMI_FRAME_ASSOC_REQ, - WMI_FRAME_ASSOC_RESP, - WMI_NUM_MGMT_FRAME + WMI_SET_EXCESS_TX_RETRY_THRES_CMDID, }; /* WMI_CONNECT_CMDID */ @@ -566,6 +519,11 @@ enum dot11_auth_mode { LEAP_AUTH = 0x04, }; +enum { + AUTH_IDLE, + AUTH_OPEN_IN_PROGRESS, +}; + enum auth_mode { NONE_AUTH = 0x01, WPA_AUTH = 0x02, @@ -1221,26 +1179,15 @@ enum wmi_event_id { WMI_WAC_START_WPS_EVENTID, WMI_WAC_CTRL_REQ_REPLY_EVENTID, - WMI_REPORT_WMM_PARAMS_EVENTID, - WMI_WAC_REJECT_WPS_EVENTID, - - /* More P2P Events */ - WMI_P2P_GO_NEG_REQ_EVENTID, - WMI_P2P_INVITE_REQ_EVENTID, - WMI_P2P_INVITE_RCVD_RESULT_EVENTID, - WMI_P2P_INVITE_SENT_RESULT_EVENTID, - WMI_P2P_PROV_DISC_RESP_EVENTID, - WMI_P2P_PROV_DISC_REQ_EVENTID, - /* RFKILL Events */ WMI_RFKILL_STATE_CHANGE_EVENTID, WMI_RFKILL_GET_MODE_CMD_EVENTID, - - WMI_P2P_START_SDPD_EVENTID, - WMI_P2P_SDPD_RX_EVENTID, - WMI_THIN_RESERVED_START_EVENTID = 0x8000, - /* Events in this range are reserved for thinmode */ + + /* + * Events in this range are reserved for thinmode + * See wmi_thin.h for actual definitions + */ WMI_THIN_RESERVED_END_EVENTID = 0x8fff, WMI_SET_CHANNEL_EVENTID, @@ -1248,17 +1195,7 @@ enum wmi_event_id { /* Generic ACS event */ WMI_ACS_EVENTID, - WMI_STORERECALL_STORE_EVENTID, - WMI_WOW_EXT_WAKE_EVENTID, - WMI_GTK_OFFLOAD_STATUS_EVENTID, - WMI_NETWORK_LIST_OFFLOAD_EVENTID, - WMI_REMAIN_ON_CHNL_EVENTID, - WMI_CANCEL_REMAIN_ON_CHNL_EVENTID, - WMI_TX_STATUS_EVENTID, - WMI_RX_PROBE_REQ_EVENTID, - WMI_P2P_CAPABILITIES_EVENTID, - WMI_RX_ACTION_EVENTID, - WMI_P2P_INFO_EVENTID, + WMI_REPORT_WMM_PARAMS_EVENTID }; struct wmi_ready_event_2 { @@ -1270,30 +1207,11 @@ struct wmi_ready_event_2 { /* Connect Event */ struct wmi_connect_event { - union { - struct { - __le16 ch; - u8 bssid[ETH_ALEN]; - __le16 listen_intvl; - __le16 beacon_intvl; - __le32 nw_type; - } sta; - struct { - u8 phymode; - u8 aid; - u8 mac_addr[ETH_ALEN]; - u8 auth; - u8 keymgmt; - __le16 cipher; - u8 apsd_info; - u8 unused[3]; - } ap_sta; - struct { - __le16 ch; - u8 bssid[ETH_ALEN]; - u8 unused[8]; - } ap_bss; - } u; + __le16 ch; + u8 bssid[ETH_ALEN]; + __le16 listen_intvl; + __le16 beacon_intvl; + __le32 nw_type; u8 beacon_ie_len; u8 assoc_req_len; u8 assoc_resp_len; @@ -1320,12 +1238,6 @@ enum wmi_disconnect_reason { IBSS_MERGE = 0xe, }; -#define ATH6KL_COUNTRY_RD_SHIFT 16 - -struct ath6kl_wmi_regdomain { - __le32 reg_code; -}; - struct wmi_disconnect_event { /* reason code, see 802.11 spec. */ __le16 proto_reason_status; @@ -1353,54 +1265,33 @@ enum wmi_bi_ftype { PROBEREQ_FTYPE, }; -#define DEF_LRSSI_SCAN_PERIOD 5 -#define DEF_LRSSI_ROAM_THRESHOLD 20 -#define DEF_LRSSI_ROAM_FLOOR 60 -#define DEF_SCAN_FOR_ROAM_INTVL 2 +struct wmi_bss_info_hdr { + __le16 ch; -enum wmi_roam_ctrl { - WMI_FORCE_ROAM = 1, - WMI_SET_ROAM_MODE, - WMI_SET_HOST_BIAS, - WMI_SET_LRSSI_SCAN_PARAMS, -}; + /* see, enum wmi_bi_ftype */ + u8 frame_type; -struct bss_bias { + u8 snr; + a_sle16 rssi; u8 bssid[ETH_ALEN]; - u8 bias; -} __packed; - -struct bss_bias_info { - u8 num_bss; - struct bss_bias bss_bias[1]; -} __packed; - -struct low_rssi_scan_params { - __le16 lrssi_scan_period; - a_sle16 lrssi_scan_threshold; - a_sle16 lrssi_roam_threshold; - u8 roam_rssi_floor; - u8 reserved[1]; -} __packed; - -struct roam_ctrl_cmd { - union { - u8 bssid[ETH_ALEN]; - u8 roam_mode; - struct bss_bias_info bss; - struct low_rssi_scan_params params; - } __packed info; - u8 roam_ctrl; + __le32 ie_mask; } __packed; -/* BSS INFO HDR version 2.0 */ +/* + * BSS INFO HDR version 2.0 + * With 6 bytes HTC header and 6 bytes of WMI header + * WMI_BSS_INFO_HDR cannot be accommodated in the removed 802.11 management + * header space. + * - Reduce the ie_mask to 2 bytes as only two bit flags are used + * - Remove rssi and compute it on the host. rssi = snr - 95 + */ struct wmi_bss_info_hdr2 { - __le16 ch; /* frequency in MHz */ + __le16 ch; /* see, enum wmi_bi_ftype */ u8 frame_type; - u8 snr; /* note: rssi = snr - 95 dBm */ + u8 snr; u8 bssid[ETH_ALEN]; __le16 ie_mask; } __packed; @@ -1439,16 +1330,6 @@ enum wmi_bss_flags { WMI_PMKID_VALID_BSS = 0x02, }; -struct wmi_neighbor_info { - u8 bssid[ETH_ALEN]; - u8 bss_flags; /* enum wmi_bss_flags */ -} __packed; - -struct wmi_neighbor_report_event { - u8 num_neighbors; - struct wmi_neighbor_info neighbor[0]; -} __packed; - /* TKIP MIC Error Event */ struct wmi_tkip_micerr_event { u8 key_id; @@ -1761,12 +1642,6 @@ struct wmi_get_keepalive_cmd { u8 keep_alive_intvl; } __packed; -struct wmi_set_appie_cmd { - u8 mgmt_frm_type; /* enum wmi_mgmt_frame_type */ - u8 ie_len; - u8 ie_info[0]; -} __packed; - /* Notify the WSC registration status to the target */ #define WSC_REG_ACTIVE 1 #define WSC_REG_INACTIVE 0 @@ -1914,26 +1789,8 @@ struct wmi_tx_complete_event { /* Used with WMI_AP_SET_NUM_STA_CMDID */ -/* - * Used with WMI_AP_SET_MLME_CMDID - */ - -/* MLME Commands */ -#define WMI_AP_MLME_ASSOC 1 /* associate station */ -#define WMI_AP_DISASSOC 2 /* disassociate station */ -#define WMI_AP_DEAUTH 3 /* deauthenticate station */ -#define WMI_AP_MLME_AUTHORIZE 4 /* authorize station */ -#define WMI_AP_MLME_UNAUTHORIZE 5 /* unauthorize station */ - -struct wmi_ap_set_mlme_cmd { - u8 mac[ETH_ALEN]; - __le16 reason; /* 802.11 reason code */ - u8 cmd; /* operation to perform (WMI_AP_*) */ -} __packed; - struct wmi_ap_set_pvb_cmd { __le32 flag; - __le16 rsvd; __le16 aid; } __packed; @@ -1983,100 +1840,6 @@ struct wmi_ap_mode_stat { /* End of AP mode definitions */ -struct wmi_remain_on_chnl_cmd { - __le32 freq; - __le32 duration; -} __packed; - -struct wmi_send_action_cmd { - __le32 id; - __le32 freq; - __le32 wait; - __le16 len; - u8 data[0]; -} __packed; - -struct wmi_tx_status_event { - __le32 id; - u8 ack_status; -} __packed; - -struct wmi_probe_req_report_cmd { - u8 enable; -} __packed; - -struct wmi_disable_11b_rates_cmd { - u8 disable; -} __packed; - -struct wmi_set_appie_extended_cmd { - u8 role_id; - u8 mgmt_frm_type; - u8 ie_len; - u8 ie_info[0]; -} __packed; - -struct wmi_remain_on_chnl_event { - __le32 freq; - __le32 duration; -} __packed; - -struct wmi_cancel_remain_on_chnl_event { - __le32 freq; - __le32 duration; - u8 status; -} __packed; - -struct wmi_rx_action_event { - __le32 freq; - __le16 len; - u8 data[0]; -} __packed; - -struct wmi_p2p_capabilities_event { - __le16 len; - u8 data[0]; -} __packed; - -struct wmi_p2p_rx_probe_req_event { - __le32 freq; - __le16 len; - u8 data[0]; -} __packed; - -#define P2P_FLAG_CAPABILITIES_REQ (0x00000001) -#define P2P_FLAG_MACADDR_REQ (0x00000002) -#define P2P_FLAG_HMODEL_REQ (0x00000002) - -struct wmi_get_p2p_info { - __le32 info_req_flags; -} __packed; - -struct wmi_p2p_info_event { - __le32 info_req_flags; - __le16 len; - u8 data[0]; -} __packed; - -struct wmi_p2p_capabilities { - u8 go_power_save; -} __packed; - -struct wmi_p2p_macaddr { - u8 mac_addr[ETH_ALEN]; -} __packed; - -struct wmi_p2p_hmodel { - u8 p2p_model; -} __packed; - -struct wmi_p2p_probe_response_cmd { - __le32 freq; - u8 destination_addr[ETH_ALEN]; - __le16 len; - u8 data[0]; -} __packed; - /* Extended WMI (WMIX) * * Extended WMIX commands are encapsulated in a WMI message with @@ -2135,11 +1898,6 @@ struct wmix_hb_challenge_resp_cmd { __le32 source; } __packed; -struct ath6kl_wmix_dbglog_cfg_module_cmd { - __le32 valid; - __le32 config; -} __packed; - /* End of Extended WMI (WMIX) */ enum wmi_sync_flag { @@ -2167,11 +1925,14 @@ int ath6kl_wmi_data_hdr_add(struct wmi *wmi, struct sk_buff *skb, int ath6kl_wmi_dot11_hdr_remove(struct wmi *wmi, struct sk_buff *skb); int ath6kl_wmi_dot3_2_dix(struct sk_buff *skb); +int ath6kl_wmi_data_hdr_remove(struct wmi *wmi, struct sk_buff *skb); int ath6kl_wmi_implicit_create_pstream(struct wmi *wmi, struct sk_buff *skb, u32 layer2_priority, bool wmm_enabled, u8 *ac); int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb); +struct bss *ath6kl_wmi_find_node(struct wmi *wmi, const u8 *mac_addr); +void ath6kl_wmi_node_free(struct wmi *wmi, const u8 *mac_addr); int ath6kl_wmi_cmd_send(struct wmi *wmi, struct sk_buff *skb, enum wmi_cmd_id cmd_id, enum wmi_sync_flag sync_flag); @@ -2217,7 +1978,6 @@ int ath6kl_wmi_set_lpreamble_cmd(struct wmi *wmi, u8 status, u8 preamble_policy); int ath6kl_wmi_get_challenge_resp_cmd(struct wmi *wmi, u32 cookie, u32 source); -int ath6kl_wmi_config_debug_module_cmd(struct wmi *wmi, u32 valid, u32 config); int ath6kl_wmi_get_stats_cmd(struct wmi *wmi); int ath6kl_wmi_addkey_cmd(struct wmi *wmi, u8 key_index, @@ -2235,47 +1995,23 @@ int ath6kl_wmi_get_tx_pwr_cmd(struct wmi *wmi); int ath6kl_wmi_set_wmm_txop(struct wmi *wmi, enum wmi_txop_cfg cfg); int ath6kl_wmi_set_keepalive_cmd(struct wmi *wmi, u8 keep_alive_intvl); -int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len); s32 ath6kl_wmi_get_rate(s8 rate_index); int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, struct wmi_set_ip_cmd *ip_cmd); -int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi); -/* AP mode */ -int ath6kl_wmi_ap_profile_commit(struct wmi *wmip, struct wmi_connect_cmd *p); +struct bss *ath6kl_wmi_find_ssid_node(struct wmi *wmi, u8 *ssid, + u32 ssid_len, bool is_wpa2, + bool match_ssid); -int ath6kl_wmi_ap_set_mlme(struct wmi *wmip, u8 cmd, const u8 *mac, u16 reason); +void ath6kl_wmi_node_return(struct wmi *wmi, struct bss *bss); +/* AP mode */ int ath6kl_wmi_set_pvb_cmd(struct wmi *wmi, u16 aid, bool flag); int ath6kl_wmi_set_rx_frame_format_cmd(struct wmi *wmi, u8 rx_meta_version, bool rx_dot11_hdr, bool defrag_on_host); -int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 mgmt_frm_type, const u8 *ie, - u8 ie_len); - -/* P2P */ -int ath6kl_wmi_disable_11b_rates_cmd(struct wmi *wmi, bool disable); - -int ath6kl_wmi_remain_on_chnl_cmd(struct wmi *wmi, u32 freq, u32 dur); - -int ath6kl_wmi_send_action_cmd(struct wmi *wmi, u32 id, u32 freq, u32 wait, - const u8 *data, u16 data_len); - -int ath6kl_wmi_send_probe_response_cmd(struct wmi *wmi, u32 freq, - const u8 *dst, - const u8 *data, u16 data_len); - -int ath6kl_wmi_probe_report_req_cmd(struct wmi *wmi, bool enable); - -int ath6kl_wmi_info_req_cmd(struct wmi *wmi, u32 info_req_flags); - -int ath6kl_wmi_cancel_remain_on_chnl_cmd(struct wmi *wmi); - -int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 mgmt_frm_type, const u8 *ie, - u8 ie_len); - void *ath6kl_wmi_init(struct ath6kl *devt); void ath6kl_wmi_shutdown(struct wmi *wmi); diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/trunk/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h index 08e9341f6368..f2c6f2316a3b 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h @@ -1514,7 +1514,7 @@ static const u32 ar9300_2p2_mac_core[][2] = { {0x00008258, 0x00000000}, {0x0000825c, 0x40000000}, {0x00008260, 0x00080922}, - {0x00008264, 0x9d400010}, + {0x00008264, 0x9bc00010}, {0x00008268, 0xffffffff}, {0x0000826c, 0x0000ffff}, {0x00008270, 0x00000000}, diff --git a/trunk/drivers/net/wireless/ath/ath9k/ath9k.h b/trunk/drivers/net/wireless/ath/ath9k/ath9k.h index 1e8614783181..94d887b65e69 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/trunk/drivers/net/wireless/ath/ath9k/ath9k.h @@ -340,8 +340,7 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an); -void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc, - struct ath_node *an); +bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an); /********/ /* VIFs */ diff --git a/trunk/drivers/net/wireless/ath/ath9k/debug.c b/trunk/drivers/net/wireless/ath/ath9k/debug.c index a5329c98f9ea..179da2099270 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/debug.c +++ b/trunk/drivers/net/wireless/ath/ath9k/debug.c @@ -876,15 +876,6 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, TX_SAMP_DBG(rssi) = ts->ts_rssi; TX_SAMP_DBG(tid) = ts->tid; TX_SAMP_DBG(qid) = ts->qid; - - if (ts->ts_flags & ATH9K_TX_BA) { - TX_SAMP_DBG(ba_low) = ts->ba_low; - TX_SAMP_DBG(ba_high) = ts->ba_high; - } else { - TX_SAMP_DBG(ba_low) = 0; - TX_SAMP_DBG(ba_high) = 0; - } - sc->debug.tsidx = (sc->debug.tsidx + 1) % ATH_DBG_MAX_SAMPLES; spin_unlock(&sc->debug.samp_lock); @@ -1525,15 +1516,14 @@ static int open_file_bb_mac_samps(struct inode *inode, struct file *file) len += snprintf(buf + len, size - len, "Tx status Dump :\n"); len += snprintf(buf + len, size - len, "Sample rssi:- ctl0 ctl1 ctl2 ext0 ext1 ext2 comb " - "isok rts_fail data_fail rate tid qid " - "ba_low ba_high tx_before(ms)\n"); + "isok rts_fail data_fail rate tid qid tx_before(ms)\n"); for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) { for (i = 0; i < ATH_DBG_MAX_SAMPLES; i++) { if (!ATH_SAMP_DBG(ts[i].jiffies)) continue; - len += snprintf(buf + len, size - len, "%-14d" - "%-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d %-8d " - "%-9d %-4d %-3d %-3d %08x %08x %-11d\n", + len += snprintf(buf + len, size - len, "%4d \t" + "%8d %4d %4d %4d %4d %4d %4d %4d %4d " + "%4d %4d %2d %2d %d\n", sampidx, ATH_SAMP_DBG(ts[i].rssi_ctl0), ATH_SAMP_DBG(ts[i].rssi_ctl1), @@ -1548,8 +1538,6 @@ static int open_file_bb_mac_samps(struct inode *inode, struct file *file) ATH_SAMP_DBG(ts[i].rateindex), ATH_SAMP_DBG(ts[i].tid), ATH_SAMP_DBG(ts[i].qid), - ATH_SAMP_DBG(ts[i].ba_low), - ATH_SAMP_DBG(ts[i].ba_high), jiffies_to_msecs(jiffies - ATH_SAMP_DBG(ts[i].jiffies))); } @@ -1562,8 +1550,8 @@ static int open_file_bb_mac_samps(struct inode *inode, struct file *file) for (i = 0; i < ATH_DBG_MAX_SAMPLES; i++) { if (!ATH_SAMP_DBG(rs[i].jiffies)) continue; - len += snprintf(buf + len, size - len, "%-14d" - "%-4d %-4d %-4d %-4d %-4d %-4d %-4d %-9s %-2d %02x %-13d\n", + len += snprintf(buf + len, size - len, "%4d \t" + "%8d %4d %4d %4d %4d %4d %4d %s %4d %02x %d\n", sampidx, ATH_SAMP_DBG(rs[i].rssi_ctl0), ATH_SAMP_DBG(rs[i].rssi_ctl1), diff --git a/trunk/drivers/net/wireless/ath/ath9k/debug.h b/trunk/drivers/net/wireless/ath/ath9k/debug.h index b93e88bd8c58..39f89bc9abcd 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/debug.h +++ b/trunk/drivers/net/wireless/ath/ath9k/debug.h @@ -196,8 +196,6 @@ struct ath_dbg_bb_mac_samp { u8 rateindex; u8 qid; u8 tid; - u32 ba_low; - u32 ba_high; } ts[ATH_DBG_MAX_SAMPLES]; struct { u64 jiffies; diff --git a/trunk/drivers/net/wireless/ath/ath9k/eeprom.h b/trunk/drivers/net/wireless/ath/ath9k/eeprom.h index 5d92f96980e6..a3c7d0c247a3 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/trunk/drivers/net/wireless/ath/ath9k/eeprom.h @@ -104,11 +104,16 @@ #define OLC_FOR_AR9287_10_LATER (AR_SREV_9287_11_OR_LATER(ah) && \ ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) +#define AR_EEPROM_RFSILENT_GPIO_SEL 0x001c +#define AR_EEPROM_RFSILENT_GPIO_SEL_S 2 +#define AR_EEPROM_RFSILENT_POLARITY 0x0002 +#define AR_EEPROM_RFSILENT_POLARITY_S 1 + #define EEP_RFSILENT_ENABLED 0x0001 #define EEP_RFSILENT_ENABLED_S 0 #define EEP_RFSILENT_POLARITY 0x0002 #define EEP_RFSILENT_POLARITY_S 1 -#define EEP_RFSILENT_GPIO_SEL (AR_SREV_9480(ah) ? 0x00fc : 0x001c) +#define EEP_RFSILENT_GPIO_SEL 0x001c #define EEP_RFSILENT_GPIO_SEL_S 2 #define AR5416_OPFLAGS_11A 0x01 diff --git a/trunk/drivers/net/wireless/ath/ath9k/gpio.c b/trunk/drivers/net/wireless/ath/ath9k/gpio.c index fd0f84ebdb51..afbf5400a52a 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/gpio.c +++ b/trunk/drivers/net/wireless/ath/ath9k/gpio.c @@ -84,14 +84,9 @@ void ath_init_leds(struct ath_softc *sc) static bool ath_is_rfkill_set(struct ath_softc *sc) { struct ath_hw *ah = sc->sc_ah; - bool is_blocked; - ath9k_ps_wakeup(sc); - is_blocked = ath9k_hw_gpio_get(ah, ah->rfkill_gpio) == + return ath9k_hw_gpio_get(ah, ah->rfkill_gpio) == ah->rfkill_polarity; - ath9k_ps_restore(sc); - - return is_blocked; } void ath9k_rfkill_poll_state(struct ieee80211_hw *hw) diff --git a/trunk/drivers/net/wireless/ath/ath9k/hif_usb.c b/trunk/drivers/net/wireless/ath/ath9k/hif_usb.c index 77c8ded8de57..d3f4a59cd456 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/trunk/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -38,7 +38,6 @@ static struct usb_device_id ath9k_hif_usb_ids[] = { { USB_DEVICE(0x04CA, 0x4605) }, /* Liteon */ { USB_DEVICE(0x040D, 0x3801) }, /* VIA */ { USB_DEVICE(0x0cf3, 0xb003) }, /* Ubiquiti WifiStation Ext */ - { USB_DEVICE(0x057c, 0x8403) }, /* AVM FRITZ!WLAN 11N v2 USB */ { USB_DEVICE(0x0cf3, 0x7015), .driver_info = AR9287_USB }, /* Atheros */ diff --git a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c index e3a02eb8e0cc..db2352e5cc0d 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c +++ b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c @@ -228,14 +228,8 @@ void ath9k_init_leds(struct ath9k_htc_priv *priv) static bool ath_is_rfkill_set(struct ath9k_htc_priv *priv) { - bool is_blocked; - - ath9k_htc_ps_wakeup(priv); - is_blocked = ath9k_hw_gpio_get(priv->ah, priv->ah->rfkill_gpio) == - priv->ah->rfkill_polarity; - ath9k_htc_ps_restore(priv); - - return is_blocked; + return ath9k_hw_gpio_get(priv->ah, priv->ah->rfkill_gpio) == + priv->ah->rfkill_polarity; } void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw) diff --git a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 0b9a0e8a4958..495fdf680a6c 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1352,8 +1352,7 @@ static int ath9k_htc_sta_remove(struct ieee80211_hw *hw, return ret; } -static int ath9k_htc_conf_tx(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, u16 queue, +static int ath9k_htc_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params) { struct ath9k_htc_priv *priv = hw->priv; @@ -1564,8 +1563,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, mutex_unlock(&priv->mutex); } -static u64 ath9k_htc_get_tsf(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) +static u64 ath9k_htc_get_tsf(struct ieee80211_hw *hw) { struct ath9k_htc_priv *priv = hw->priv; u64 tsf; @@ -1579,8 +1577,7 @@ static u64 ath9k_htc_get_tsf(struct ieee80211_hw *hw, return tsf; } -static void ath9k_htc_set_tsf(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, u64 tsf) +static void ath9k_htc_set_tsf(struct ieee80211_hw *hw, u64 tsf) { struct ath9k_htc_priv *priv = hw->priv; @@ -1591,8 +1588,7 @@ static void ath9k_htc_set_tsf(struct ieee80211_hw *hw, mutex_unlock(&priv->mutex); } -static void ath9k_htc_reset_tsf(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) +static void ath9k_htc_reset_tsf(struct ieee80211_hw *hw) { struct ath9k_htc_priv *priv = hw->priv; diff --git a/trunk/drivers/net/wireless/ath/ath9k/hw.c b/trunk/drivers/net/wireless/ath/ath9k/hw.c index 42ebe8fb053a..f2de7ee047ce 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/hw.c +++ b/trunk/drivers/net/wireless/ath/ath9k/hw.c @@ -284,12 +284,7 @@ static void ath9k_hw_read_revisions(struct ath_hw *ah) ah->hw_version.macVersion = (val & AR_SREV_VERSION2) >> AR_SREV_TYPE2_S; ah->hw_version.macRev = MS(val, AR_SREV_REVISION2); - - if (AR_SREV_9480(ah)) - ah->is_pciexpress = true; - else - ah->is_pciexpress = (val & - AR_SREV_TYPE2_HOST_MODE) ? 0 : 1; + ah->is_pciexpress = (val & AR_SREV_TYPE2_HOST_MODE) ? 0 : 1; } else { if (!AR_SREV_9100(ah)) ah->hw_version.macVersion = MS(val, AR_SREV_VERSION); @@ -2158,10 +2153,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) pCap->num_gpio_pins = AR9271_NUM_GPIO; else if (AR_DEVID_7010(ah)) pCap->num_gpio_pins = AR7010_NUM_GPIO; - else if (AR_SREV_9300_20_OR_LATER(ah)) - pCap->num_gpio_pins = AR9300_NUM_GPIO; - else if (AR_SREV_9287_11_OR_LATER(ah)) - pCap->num_gpio_pins = AR9287_NUM_GPIO; else if (AR_SREV_9285_12_OR_LATER(ah)) pCap->num_gpio_pins = AR9285_NUM_GPIO; else if (AR_SREV_9280_20_OR_LATER(ah)) diff --git a/trunk/drivers/net/wireless/ath/ath9k/main.c b/trunk/drivers/net/wireless/ath/ath9k/main.c index 988318665758..ee39702da5d8 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/main.c +++ b/trunk/drivers/net/wireless/ath/ath9k/main.c @@ -133,7 +133,7 @@ void ath9k_ps_restore(struct ath_softc *sc) ath_hw_cycle_counters_update(common); spin_unlock(&common->cc_lock); - ath9k_hw_setpower(sc->sc_ah, mode); + ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP); unlock: spin_unlock_irqrestore(&sc->sc_pm_lock, flags); @@ -1833,7 +1833,8 @@ static void ath9k_sta_notify(struct ieee80211_hw *hw, switch (cmd) { case STA_NOTIFY_SLEEP: an->sleeping = true; - ath_tx_aggr_sleep(sta, sc, an); + if (ath_tx_aggr_sleep(sc, an)) + ieee80211_sta_set_tim(sta); break; case STA_NOTIFY_AWAKE: an->sleeping = false; @@ -1842,8 +1843,7 @@ static void ath9k_sta_notify(struct ieee80211_hw *hw, } } -static int ath9k_conf_tx(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, u16 queue, +static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params) { struct ath_softc *sc = hw->priv; @@ -2143,7 +2143,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, ath9k_ps_restore(sc); } -static u64 ath9k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +static u64 ath9k_get_tsf(struct ieee80211_hw *hw) { struct ath_softc *sc = hw->priv; u64 tsf; @@ -2157,9 +2157,7 @@ static u64 ath9k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) return tsf; } -static void ath9k_set_tsf(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - u64 tsf) +static void ath9k_set_tsf(struct ieee80211_hw *hw, u64 tsf) { struct ath_softc *sc = hw->priv; @@ -2170,7 +2168,7 @@ static void ath9k_set_tsf(struct ieee80211_hw *hw, mutex_unlock(&sc->mutex); } -static void ath9k_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +static void ath9k_reset_tsf(struct ieee80211_hw *hw) { struct ath_softc *sc = hw->priv; diff --git a/trunk/drivers/net/wireless/ath/ath9k/rc.c b/trunk/drivers/net/wireless/ath/ath9k/rc.c index 8448281dd069..4f1301881137 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/rc.c +++ b/trunk/drivers/net/wireless/ath/ath9k/rc.c @@ -1362,6 +1362,12 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, if (tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) return; + if (!(tx_info->flags & IEEE80211_TX_STAT_AMPDU)) { + tx_info->status.ampdu_ack_len = + (tx_info->flags & IEEE80211_TX_STAT_ACK ? 1 : 0); + tx_info->status.ampdu_len = 1; + } + if (!(tx_info->flags & IEEE80211_TX_STAT_ACK)) tx_status = 1; diff --git a/trunk/drivers/net/wireless/ath/ath9k/recv.c b/trunk/drivers/net/wireless/ath/ath9k/recv.c index f658ec60b510..bcc0b222ec18 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/recv.c +++ b/trunk/drivers/net/wireless/ath/ath9k/recv.c @@ -205,22 +205,14 @@ static void ath_rx_remove_buffer(struct ath_softc *sc, static void ath_rx_edma_cleanup(struct ath_softc *sc) { - struct ath_hw *ah = sc->sc_ah; - struct ath_common *common = ath9k_hw_common(ah); struct ath_buf *bf; ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_LP); ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_HP); list_for_each_entry(bf, &sc->rx.rxbuf, list) { - if (bf->bf_mpdu) { - dma_unmap_single(sc->dev, bf->bf_buf_addr, - common->rx_bufsize, - DMA_BIDIRECTIONAL); + if (bf->bf_mpdu) dev_kfree_skb_any(bf->bf_mpdu); - bf->bf_buf_addr = 0; - bf->bf_mpdu = NULL; - } } INIT_LIST_HEAD(&sc->rx.rxbuf); @@ -586,11 +578,22 @@ static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb) static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb) { + struct ieee80211_mgmt *mgmt; struct ath_common *common = ath9k_hw_common(sc->sc_ah); if (skb->len < 24 + 8 + 2 + 2) return; + mgmt = (struct ieee80211_mgmt *)skb->data; + if (memcmp(common->curbssid, mgmt->bssid, ETH_ALEN) != 0) { + /* TODO: This doesn't work well if you have stations + * associated to two different APs because curbssid + * is just the last AP that any of the stations associated + * with. + */ + return; /* not from our current AP */ + } + sc->ps_flags &= ~PS_WAIT_FOR_BEACON; if (sc->ps_flags & PS_BEACON_SYNC) { @@ -626,7 +629,7 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb) } } -static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb, bool mybeacon) +static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb) { struct ieee80211_hdr *hdr; struct ath_common *common = ath9k_hw_common(sc->sc_ah); @@ -635,7 +638,7 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb, bool mybeacon) /* Process Beacon and CAB receive in PS state */ if (((sc->ps_flags & PS_WAIT_FOR_BEACON) || ath9k_check_auto_sleep(sc)) - && mybeacon) + && ieee80211_is_beacon(hdr->frame_control)) ath_rx_ps_beacon(sc, skb); else if ((sc->ps_flags & PS_WAIT_FOR_CAB) && (ieee80211_is_data(hdr->frame_control) || @@ -1941,10 +1944,10 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) spin_lock_irqsave(&sc->sc_pm_lock, flags); if ((sc->ps_flags & (PS_WAIT_FOR_BEACON | - PS_WAIT_FOR_CAB | - PS_WAIT_FOR_PSPOLL_DATA)) || - ath9k_check_auto_sleep(sc)) - ath_rx_ps(sc, skb, rs.is_mybeacon); + PS_WAIT_FOR_CAB | + PS_WAIT_FOR_PSPOLL_DATA)) || + ath9k_check_auto_sleep(sc)) + ath_rx_ps(sc, skb); spin_unlock_irqrestore(&sc->sc_pm_lock, flags); if ((ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) && sc->ant_rx == 3) diff --git a/trunk/drivers/net/wireless/ath/ath9k/xmit.c b/trunk/drivers/net/wireless/ath/ath9k/xmit.c index c2bfc57958d8..fa3dcfdf7174 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/xmit.c +++ b/trunk/drivers/net/wireless/ath/ath9k/xmit.c @@ -542,7 +542,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, /* prepend un-acked frames to the beginning of the pending frame queue */ if (!skb_queue_empty(&bf_pending)) { if (an->sleeping) - ieee80211_sta_set_buffered(sta, tid->tidno, true); + ieee80211_sta_set_tim(sta); spin_lock_bh(&txq->axq_lock); if (clear_filter) @@ -1153,13 +1153,12 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) ath_tx_flush_tid(sc, txtid); } -void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc, - struct ath_node *an) +bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an) { struct ath_atx_tid *tid; struct ath_atx_ac *ac; struct ath_txq *txq; - bool buffered; + bool buffered = false; int tidno; for (tidno = 0, tid = &an->tid[tidno]; @@ -1173,7 +1172,8 @@ void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc, spin_lock_bh(&txq->axq_lock); - buffered = !skb_queue_empty(&tid->buf_q); + if (!skb_queue_empty(&tid->buf_q)) + buffered = true; tid->sched = false; list_del(&tid->list); @@ -1184,9 +1184,9 @@ void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc, } spin_unlock_bh(&txq->axq_lock); - - ieee80211_sta_set_buffered(sta, tidno, buffered); } + + return buffered; } void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an) @@ -2043,9 +2043,10 @@ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf, tx_info->flags |= IEEE80211_TX_STAT_AMPDU; BUG_ON(nbad > nframes); + + tx_info->status.ampdu_len = nframes; + tx_info->status.ampdu_ack_len = nframes - nbad; } - tx_info->status.ampdu_len = nframes; - tx_info->status.ampdu_ack_len = nframes - nbad; if ((ts->ts_status & ATH9K_TXERR_FILT) == 0 && (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) == 0) { diff --git a/trunk/drivers/net/wireless/ath/carl9170/main.c b/trunk/drivers/net/wireless/ath/carl9170/main.c index beca71073e9b..af351ecd87c4 100644 --- a/trunk/drivers/net/wireless/ath/carl9170/main.c +++ b/trunk/drivers/net/wireless/ath/carl9170/main.c @@ -1078,8 +1078,7 @@ static void carl9170_op_bss_info_changed(struct ieee80211_hw *hw, mutex_unlock(&ar->mutex); } -static u64 carl9170_op_get_tsf(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) +static u64 carl9170_op_get_tsf(struct ieee80211_hw *hw) { struct ar9170 *ar = hw->priv; struct carl9170_tsf_rsp tsf; @@ -1305,8 +1304,7 @@ static int carl9170_op_sta_remove(struct ieee80211_hw *hw, return 0; } -static int carl9170_op_conf_tx(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, u16 queue, +static int carl9170_op_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *param) { struct ar9170 *ar = hw->priv; diff --git a/trunk/drivers/net/wireless/b43/b43.h b/trunk/drivers/net/wireless/b43/b43.h index 447a2307c9d9..f8615cdf1075 100644 --- a/trunk/drivers/net/wireless/b43/b43.h +++ b/trunk/drivers/net/wireless/b43/b43.h @@ -107,40 +107,6 @@ #define B43_MMIO_RADIO_HWENABLED_LO 0x49A #define B43_MMIO_GPIO_CONTROL 0x49C #define B43_MMIO_GPIO_MASK 0x49E -#define B43_MMIO_TXE0_CTL 0x500 -#define B43_MMIO_TXE0_AUX 0x502 -#define B43_MMIO_TXE0_TS_LOC 0x504 -#define B43_MMIO_TXE0_TIME_OUT 0x506 -#define B43_MMIO_TXE0_WM_0 0x508 -#define B43_MMIO_TXE0_WM_1 0x50A -#define B43_MMIO_TXE0_PHYCTL 0x50C -#define B43_MMIO_TXE0_STATUS 0x50E -#define B43_MMIO_TXE0_MMPLCP0 0x510 -#define B43_MMIO_TXE0_MMPLCP1 0x512 -#define B43_MMIO_TXE0_PHYCTL1 0x514 -#define B43_MMIO_XMTFIFODEF 0x520 -#define B43_MMIO_XMTFIFO_FRAME_CNT 0x522 /* core rev>= 16 only */ -#define B43_MMIO_XMTFIFO_BYTE_CNT 0x524 /* core rev>= 16 only */ -#define B43_MMIO_XMTFIFO_HEAD 0x526 /* core rev>= 16 only */ -#define B43_MMIO_XMTFIFO_RD_PTR 0x528 /* core rev>= 16 only */ -#define B43_MMIO_XMTFIFO_WR_PTR 0x52A /* core rev>= 16 only */ -#define B43_MMIO_XMTFIFODEF1 0x52C /* core rev>= 16 only */ -#define B43_MMIO_XMTFIFOCMD 0x540 -#define B43_MMIO_XMTFIFOFLUSH 0x542 -#define B43_MMIO_XMTFIFOTHRESH 0x544 -#define B43_MMIO_XMTFIFORDY 0x546 -#define B43_MMIO_XMTFIFOPRIRDY 0x548 -#define B43_MMIO_XMTFIFORQPRI 0x54A -#define B43_MMIO_XMTTPLATETXPTR 0x54C -#define B43_MMIO_XMTTPLATEPTR 0x550 -#define B43_MMIO_SMPL_CLCT_STRPTR 0x552 /* core rev>= 22 only */ -#define B43_MMIO_SMPL_CLCT_STPPTR 0x554 /* core rev>= 22 only */ -#define B43_MMIO_SMPL_CLCT_CURPTR 0x556 /* core rev>= 22 only */ -#define B43_MMIO_XMTTPLATEDATALO 0x560 -#define B43_MMIO_XMTTPLATEDATAHI 0x562 -#define B43_MMIO_XMTSEL 0x568 -#define B43_MMIO_XMTTXCNT 0x56A -#define B43_MMIO_XMTTXSHMADDR 0x56C #define B43_MMIO_TSF_CFP_START_LOW 0x604 #define B43_MMIO_TSF_CFP_START_HIGH 0x606 #define B43_MMIO_TSF_CFP_PRETBTT 0x612 @@ -152,16 +118,12 @@ #define B43_MMIO_TSF_3 0x638 /* core rev < 3 only */ #define B43_MMIO_RNG 0x65A #define B43_MMIO_IFSSLOT 0x684 /* Interframe slot time */ -#define B43_MMIO_IFSCTL 0x688 /* Interframe space control */ -#define B43_MMIO_IFSSTAT 0x690 -#define B43_MMIO_IFSMEDBUSYCTL 0x692 -#define B43_MMIO_IFTXDUR 0x694 +#define B43_MMIO_IFSCTL 0x688 /* Interframe space control */ #define B43_MMIO_IFSCTL_USE_EDCF 0x0004 #define B43_MMIO_POWERUP_DELAY 0x6A8 #define B43_MMIO_BTCOEX_CTL 0x6B4 /* Bluetooth Coexistence Control */ #define B43_MMIO_BTCOEX_STAT 0x6B6 /* Bluetooth Coexistence Status */ #define B43_MMIO_BTCOEX_TXCTL 0x6B8 /* Bluetooth Coexistence Transmit Control */ -#define B43_MMIO_WEPCTL 0x7C0 /* SPROM boardflags_lo values */ #define B43_BFL_BTCOEXIST 0x0001 /* implements Bluetooth coexistance */ diff --git a/trunk/drivers/net/wireless/b43/main.c b/trunk/drivers/net/wireless/b43/main.c index 7cf4125a1624..56fa3a3648c4 100644 --- a/trunk/drivers/net/wireless/b43/main.c +++ b/trunk/drivers/net/wireless/b43/main.c @@ -729,59 +729,52 @@ void b43_dummy_transmission(struct b43_wldev *dev, bool ofdm, bool pa_on) for (i = 0; i < 5; i++) b43_ram_write(dev, i * 4, buffer[i]); - b43_write16(dev, B43_MMIO_XMTSEL, 0x0000); - + b43_write16(dev, 0x0568, 0x0000); if (dev->dev->core_rev < 11) - b43_write16(dev, B43_MMIO_WEPCTL, 0x0000); + b43_write16(dev, 0x07C0, 0x0000); else - b43_write16(dev, B43_MMIO_WEPCTL, 0x0100); - + b43_write16(dev, 0x07C0, 0x0100); value = (ofdm ? 0x41 : 0x40); - b43_write16(dev, B43_MMIO_TXE0_PHYCTL, value); - if (phy->type == B43_PHYTYPE_N || phy->type == B43_PHYTYPE_LP || - phy->type == B43_PHYTYPE_LCN) - b43_write16(dev, B43_MMIO_TXE0_PHYCTL1, 0x1A02); - - b43_write16(dev, B43_MMIO_TXE0_WM_0, 0x0000); - b43_write16(dev, B43_MMIO_TXE0_WM_1, 0x0000); - - b43_write16(dev, B43_MMIO_XMTTPLATETXPTR, 0x0000); - b43_write16(dev, B43_MMIO_XMTTXCNT, 0x0014); - b43_write16(dev, B43_MMIO_XMTSEL, 0x0826); - b43_write16(dev, B43_MMIO_TXE0_CTL, 0x0000); - - if (!pa_on && phy->type == B43_PHYTYPE_N) - ; /*b43_nphy_pa_override(dev, false) */ + b43_write16(dev, 0x050C, value); + if ((phy->type == B43_PHYTYPE_N) || (phy->type == B43_PHYTYPE_LP)) + b43_write16(dev, 0x0514, 0x1A02); + b43_write16(dev, 0x0508, 0x0000); + b43_write16(dev, 0x050A, 0x0000); + b43_write16(dev, 0x054C, 0x0000); + b43_write16(dev, 0x056A, 0x0014); + b43_write16(dev, 0x0568, 0x0826); + b43_write16(dev, 0x0500, 0x0000); + if (!pa_on && (phy->type == B43_PHYTYPE_N)) { + //SPEC TODO + } switch (phy->type) { case B43_PHYTYPE_N: - case B43_PHYTYPE_LCN: - b43_write16(dev, B43_MMIO_TXE0_AUX, 0x00D0); + b43_write16(dev, 0x0502, 0x00D0); break; case B43_PHYTYPE_LP: - b43_write16(dev, B43_MMIO_TXE0_AUX, 0x0050); + b43_write16(dev, 0x0502, 0x0050); break; default: - b43_write16(dev, B43_MMIO_TXE0_AUX, 0x0030); + b43_write16(dev, 0x0502, 0x0030); } - b43_read16(dev, B43_MMIO_TXE0_AUX); if (phy->radio_ver == 0x2050 && phy->radio_rev <= 0x5) b43_radio_write16(dev, 0x0051, 0x0017); for (i = 0x00; i < max_loop; i++) { - value = b43_read16(dev, B43_MMIO_TXE0_STATUS); + value = b43_read16(dev, 0x050E); if (value & 0x0080) break; udelay(10); } for (i = 0x00; i < 0x0A; i++) { - value = b43_read16(dev, B43_MMIO_TXE0_STATUS); + value = b43_read16(dev, 0x050E); if (value & 0x0400) break; udelay(10); } for (i = 0x00; i < 0x19; i++) { - value = b43_read16(dev, B43_MMIO_IFSSTAT); + value = b43_read16(dev, 0x0690); if (!(value & 0x0100)) break; udelay(10); @@ -3559,8 +3552,7 @@ static void b43_qos_init(struct b43_wldev *dev) b43dbg(dev->wl, "QoS enabled\n"); } -static int b43_op_conf_tx(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, u16 _queue, +static int b43_op_conf_tx(struct ieee80211_hw *hw, u16 _queue, const struct ieee80211_tx_queue_params *params) { struct b43_wl *wl = hw_to_b43_wl(hw); @@ -3607,7 +3599,7 @@ static int b43_op_get_stats(struct ieee80211_hw *hw, return 0; } -static u64 b43_op_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +static u64 b43_op_get_tsf(struct ieee80211_hw *hw) { struct b43_wl *wl = hw_to_b43_wl(hw); struct b43_wldev *dev; @@ -3626,8 +3618,7 @@ static u64 b43_op_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) return tsf; } -static void b43_op_set_tsf(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, u64 tsf) +static void b43_op_set_tsf(struct ieee80211_hw *hw, u64 tsf) { struct b43_wl *wl = hw_to_b43_wl(hw); struct b43_wldev *dev; diff --git a/trunk/drivers/net/wireless/b43/phy_lcn.c b/trunk/drivers/net/wireless/b43/phy_lcn.c index a13e28ef6246..bffeb44b4a40 100644 --- a/trunk/drivers/net/wireless/b43/phy_lcn.c +++ b/trunk/drivers/net/wireless/b43/phy_lcn.c @@ -433,7 +433,7 @@ static void b43_phy_lcn_sense_setup(struct b43_wldev *dev, b43_phy_set(dev, 0x4d0, 0x20); b43_radio_write(dev, 0x112, 0x6); - b43_dummy_transmission(dev, true, false); + /* TODO: dummy transmission? */ /* Wait if not done */ if (!(b43_phy_read(dev, 0x476) & 0x8000)) udelay(10); diff --git a/trunk/drivers/net/wireless/b43/tables_phy_lcn.c b/trunk/drivers/net/wireless/b43/tables_phy_lcn.c index 5176363cadf2..9d484e2f79bf 100644 --- a/trunk/drivers/net/wireless/b43/tables_phy_lcn.c +++ b/trunk/drivers/net/wireless/b43/tables_phy_lcn.c @@ -657,25 +657,8 @@ void b43_phy_lcn_load_tx_gain_tab(struct b43_wldev *dev, } } -/* wlc_lcnphy_load_rfpower */ -static void b43_phy_lcn_load_rfpower(struct b43_wldev *dev) -{ - u32 bbmult, rfgain; - u8 i; - - for (i = 0; i < 128; i++) { - bbmult = b43_lcntab_read(dev, B43_LCNTAB32(0x7, 0x140 + i)); - bbmult >>= 20; - rfgain = b43_lcntab_read(dev, B43_LCNTAB32(0x7, 0xc0 + i)); - - /* TODO: calculate value for 0x240 + i table offset - * b43_lcntab_write(dev, B43_LCNTAB32(0x7, 0x240 + i), val); - */ - } -} - /* Not implemented in brcmsmac, noticed in wl in MMIO dump */ -static void b43_phy_lcn_rewrite_rfpower_table(struct b43_wldev *dev) +static void b43_phy_lcn_rewrite_tables(struct b43_wldev *dev) { int i; u32 tmp; @@ -702,7 +685,7 @@ void b43_phy_lcn_tables_init(struct b43_wldev *dev) b43_phy_lcn_upload_static_tables(dev); if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { - if (sprom->boardflags_lo & B43_BFL_FEM) + if (sprom->boardflags_lo & B43_BFL_EXTLNA) b43_phy_lcn_load_tx_gain_tab(dev, b43_lcntab_tx_gain_tbl_2ghz_ext_pa_rev0); else @@ -718,7 +701,7 @@ void b43_phy_lcn_tables_init(struct b43_wldev *dev) else b43err(dev->wl, "SW ctl table is unknown for this card\n"); - b43_phy_lcn_load_rfpower(dev); - b43_phy_lcn_rewrite_rfpower_table(dev); + /* TODO: various tables ops here */ + b43_phy_lcn_rewrite_tables(dev); b43_phy_lcn_clean_papd_comp_table(dev); } diff --git a/trunk/drivers/net/wireless/b43legacy/main.c b/trunk/drivers/net/wireless/b43legacy/main.c index a3b72cd72c66..468d1836548e 100644 --- a/trunk/drivers/net/wireless/b43legacy/main.c +++ b/trunk/drivers/net/wireless/b43legacy/main.c @@ -2466,8 +2466,7 @@ static void b43legacy_op_tx(struct ieee80211_hw *hw, } } -static int b43legacy_op_conf_tx(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, u16 queue, +static int b43legacy_op_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params) { return 0; diff --git a/trunk/drivers/net/wireless/iwlegacy/iwl-4965-tx.c b/trunk/drivers/net/wireless/iwlegacy/iwl-4965-tx.c index 7f12e3638bae..ac4f64de1363 100644 --- a/trunk/drivers/net/wireless/iwlegacy/iwl-4965-tx.c +++ b/trunk/drivers/net/wireless/iwlegacy/iwl-4965-tx.c @@ -335,7 +335,7 @@ int iwl4965_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) sta_priv = (void *)sta->drv_priv; if (sta_priv && sta_priv->asleep && - (info->flags & IEEE80211_TX_CTL_POLL_RESPONSE)) { + (info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE)) { /* * This sends an asynchronous command to the device, * but we can rely on it being processed before the diff --git a/trunk/drivers/net/wireless/iwlegacy/iwl-core.c b/trunk/drivers/net/wireless/iwlegacy/iwl-core.c index 2bd5659310d7..35cd2537e7fd 100644 --- a/trunk/drivers/net/wireless/iwlegacy/iwl-core.c +++ b/trunk/drivers/net/wireless/iwlegacy/iwl-core.c @@ -937,7 +937,7 @@ void iwl_legacy_irq_handle_error(struct iwl_priv *priv) &priv->contexts[IWL_RXON_CTX_BSS]); #endif - wake_up(&priv->wait_command_queue); + wake_up_interruptible(&priv->wait_command_queue); /* Keep the restart process from trying to send host * commands by clearing the INIT status bit */ @@ -1250,8 +1250,7 @@ void iwl_legacy_clear_isr_stats(struct iwl_priv *priv) memset(&priv->isr_stats, 0, sizeof(priv->isr_stats)); } -int iwl_legacy_mac_conf_tx(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, u16 queue, +int iwl_legacy_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params) { struct iwl_priv *priv = hw->priv; @@ -1747,7 +1746,7 @@ int iwl_legacy_force_reset(struct iwl_priv *priv, bool external) /* Set the FW error flag -- cleared on iwl_down */ set_bit(STATUS_FW_ERROR, &priv->status); - wake_up(&priv->wait_command_queue); + wake_up_interruptible(&priv->wait_command_queue); /* * Keep the restart process from trying to send host * commands by clearing the INIT status bit @@ -2221,8 +2220,7 @@ int iwl_legacy_mac_config(struct ieee80211_hw *hw, u32 changed) } EXPORT_SYMBOL(iwl_legacy_mac_config); -void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) +void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw) { struct iwl_priv *priv = hw->priv; unsigned long flags; diff --git a/trunk/drivers/net/wireless/iwlegacy/iwl-core.h b/trunk/drivers/net/wireless/iwlegacy/iwl-core.h index d1271fe07d4b..84da79376ef8 100644 --- a/trunk/drivers/net/wireless/iwlegacy/iwl-core.h +++ b/trunk/drivers/net/wireless/iwlegacy/iwl-core.h @@ -286,8 +286,7 @@ struct iwl_cfg { ***************************/ struct ieee80211_hw *iwl_legacy_alloc_all(struct iwl_cfg *cfg); -int iwl_legacy_mac_conf_tx(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, u16 queue, +int iwl_legacy_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params); int iwl_legacy_mac_tx_last_beacon(struct ieee80211_hw *hw); void iwl_legacy_set_rxon_hwcrypto(struct iwl_priv *priv, @@ -621,8 +620,7 @@ static inline const struct ieee80211_supported_band *iwl_get_hw_mode( /* mac80211 handlers */ int iwl_legacy_mac_config(struct ieee80211_hw *hw, u32 changed); -void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw, - struct ieee80211_vif *vif); +void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw); void iwl_legacy_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, diff --git a/trunk/drivers/net/wireless/iwlegacy/iwl-hcmd.c b/trunk/drivers/net/wireless/iwlegacy/iwl-hcmd.c index ce1fc9feb61f..62b4b09122cb 100644 --- a/trunk/drivers/net/wireless/iwlegacy/iwl-hcmd.c +++ b/trunk/drivers/net/wireless/iwlegacy/iwl-hcmd.c @@ -167,7 +167,7 @@ int iwl_legacy_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) goto out; } - ret = wait_event_timeout(priv->wait_command_queue, + ret = wait_event_interruptible_timeout(priv->wait_command_queue, !test_bit(STATUS_HCMD_ACTIVE, &priv->status), HOST_COMPLETE_TIMEOUT); if (!ret) { diff --git a/trunk/drivers/net/wireless/iwlegacy/iwl-tx.c b/trunk/drivers/net/wireless/iwlegacy/iwl-tx.c index ef9e268bf8a0..4fff995c6f3e 100644 --- a/trunk/drivers/net/wireless/iwlegacy/iwl-tx.c +++ b/trunk/drivers/net/wireless/iwlegacy/iwl-tx.c @@ -625,8 +625,6 @@ iwl_legacy_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) cmd = txq->cmd[cmd_index]; meta = &txq->meta[cmd_index]; - txq->time_stamp = jiffies; - pci_unmap_single(priv->pci_dev, dma_unmap_addr(meta, mapping), dma_unmap_len(meta, len), @@ -647,7 +645,7 @@ iwl_legacy_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) clear_bit(STATUS_HCMD_ACTIVE, &priv->status); IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s\n", iwl_legacy_get_cmd_string(cmd->hdr.cmd)); - wake_up(&priv->wait_command_queue); + wake_up_interruptible(&priv->wait_command_queue); } /* Mark as unmapped */ diff --git a/trunk/drivers/net/wireless/iwlegacy/iwl3945-base.c b/trunk/drivers/net/wireless/iwlegacy/iwl3945-base.c index b282d869a546..015739d204f2 100644 --- a/trunk/drivers/net/wireless/iwlegacy/iwl3945-base.c +++ b/trunk/drivers/net/wireless/iwlegacy/iwl3945-base.c @@ -840,7 +840,7 @@ static void iwl3945_rx_card_state_notif(struct iwl_priv *priv, wiphy_rfkill_set_hw_state(priv->hw->wiphy, test_bit(STATUS_RF_KILL_HW, &priv->status)); else - wake_up(&priv->wait_command_queue); + wake_up_interruptible(&priv->wait_command_queue); } /** @@ -2268,7 +2268,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv) iwl3945_reg_txpower_periodic(priv); IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n"); - wake_up(&priv->wait_command_queue); + wake_up_interruptible(&priv->wait_command_queue); return; @@ -2299,7 +2299,7 @@ static void __iwl3945_down(struct iwl_priv *priv) iwl_legacy_clear_driver_stations(priv); /* Unblock any waiting calls */ - wake_up_all(&priv->wait_command_queue); + wake_up_interruptible_all(&priv->wait_command_queue); /* Wipe out the EXIT_PENDING status bit if we are not actually * exiting the module */ @@ -2852,7 +2852,7 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw) /* Wait for START_ALIVE from ucode. Otherwise callbacks from * mac80211 will not be run successfully. */ - ret = wait_event_timeout(priv->wait_command_queue, + ret = wait_event_interruptible_timeout(priv->wait_command_queue, test_bit(STATUS_READY, &priv->status), UCODE_READY_TIMEOUT); if (!ret) { diff --git a/trunk/drivers/net/wireless/iwlegacy/iwl4965-base.c b/trunk/drivers/net/wireless/iwlegacy/iwl4965-base.c index d2fba9eae153..6bc5575c8dff 100644 --- a/trunk/drivers/net/wireless/iwlegacy/iwl4965-base.c +++ b/trunk/drivers/net/wireless/iwlegacy/iwl4965-base.c @@ -575,7 +575,7 @@ static void iwl4965_rx_card_state_notif(struct iwl_priv *priv, wiphy_rfkill_set_hw_state(priv->hw->wiphy, test_bit(STATUS_RF_KILL_HW, &priv->status)); else - wake_up(&priv->wait_command_queue); + wake_up_interruptible(&priv->wait_command_queue); } /** @@ -925,7 +925,7 @@ static void iwl4965_irq_tasklet(struct iwl_priv *priv) handled |= CSR_INT_BIT_FH_TX; /* Wake up uCode load routine, now that load is complete */ priv->ucode_write_complete = 1; - wake_up(&priv->wait_command_queue); + wake_up_interruptible(&priv->wait_command_queue); } if (inta & ~handled) { @@ -1794,7 +1794,7 @@ static void iwl4965_alive_start(struct iwl_priv *priv) iwl4965_rf_kill_ct_config(priv); IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n"); - wake_up(&priv->wait_command_queue); + wake_up_interruptible(&priv->wait_command_queue); iwl_legacy_power_update_mode(priv, true); IWL_DEBUG_INFO(priv, "Updated power mode\n"); @@ -1827,7 +1827,7 @@ static void __iwl4965_down(struct iwl_priv *priv) iwl_legacy_clear_driver_stations(priv); /* Unblock any waiting calls */ - wake_up_all(&priv->wait_command_queue); + wake_up_interruptible_all(&priv->wait_command_queue); /* Wipe out the EXIT_PENDING status bit if we are not actually * exiting the module */ @@ -2265,7 +2265,7 @@ int iwl4965_mac_start(struct ieee80211_hw *hw) /* Wait for START_ALIVE from Run Time ucode. Otherwise callbacks from * mac80211 will not be run successfully. */ - ret = wait_event_timeout(priv->wait_command_queue, + ret = wait_event_interruptible_timeout(priv->wait_command_queue, test_bit(STATUS_READY, &priv->status), UCODE_READY_TIMEOUT); if (!ret) { diff --git a/trunk/drivers/net/wireless/iwlwifi/Kconfig b/trunk/drivers/net/wireless/iwlwifi/Kconfig index e0441033788c..1d7572f9887f 100644 --- a/trunk/drivers/net/wireless/iwlwifi/Kconfig +++ b/trunk/drivers/net/wireless/iwlwifi/Kconfig @@ -1,5 +1,5 @@ -config IWLWIFI - tristate "Intel Wireless WiFi Next Gen AGN - Wireless-N/Advanced-N/Ultimate-N (iwlwifi) " +config IWLAGN + tristate "Intel Wireless WiFi Next Gen AGN - Wireless-N/Advanced-N/Ultimate-N (iwlagn) " depends on PCI && MAC80211 select FW_LOADER select NEW_LEDS @@ -39,14 +39,14 @@ config IWLWIFI If you want to compile the driver as a module ( = code which can be inserted in and removed from the running kernel whenever you want), say M here and read . The - module will be called iwlwifi. + module will be called iwlagn. menu "Debugging Options" - depends on IWLWIFI + depends on IWLAGN config IWLWIFI_DEBUG - bool "Enable full debugging output in the iwlwifi driver" - depends on IWLWIFI + bool "Enable full debugging output in the iwlagn driver" + depends on IWLAGN ---help--- This option will enable debug tracing output for the iwlwifi drivers @@ -70,8 +70,8 @@ config IWLWIFI_DEBUG any problems you may encounter. config IWLWIFI_DEBUGFS - bool "iwlwifi debugfs support" - depends on IWLWIFI && MAC80211_DEBUGFS + bool "iwlagn debugfs support" + depends on IWLAGN && MAC80211_DEBUGFS ---help--- Enable creation of debugfs files for the iwlwifi drivers. This is a low-impact option that allows getting insight into the @@ -79,13 +79,13 @@ config IWLWIFI_DEBUGFS config IWLWIFI_DEBUG_EXPERIMENTAL_UCODE bool "Experimental uCode support" - depends on IWLWIFI && IWLWIFI_DEBUG + depends on IWLAGN && IWLWIFI_DEBUG ---help--- Enable use of experimental ucode for testing and debugging. config IWLWIFI_DEVICE_TRACING bool "iwlwifi device access tracing" - depends on IWLWIFI + depends on IWLAGN depends on EVENT_TRACING help Say Y here to trace all commands, including TX frames and IO @@ -104,7 +104,7 @@ endmenu config IWLWIFI_DEVICE_SVTOOL bool "iwlwifi device svtool support" - depends on IWLWIFI + depends on IWLAGN select NL80211_TESTMODE help This option enables the svtool support for iwlwifi device through diff --git a/trunk/drivers/net/wireless/iwlwifi/Makefile b/trunk/drivers/net/wireless/iwlwifi/Makefile index bacafa4a5f48..8fa59cdb3b49 100644 --- a/trunk/drivers/net/wireless/iwlwifi/Makefile +++ b/trunk/drivers/net/wireless/iwlwifi/Makefile @@ -1,25 +1,25 @@ -# WIFI -obj-$(CONFIG_IWLWIFI) += iwlwifi.o -iwlwifi-objs := iwl-agn.o iwl-agn-rs.o -iwlwifi-objs += iwl-agn-ucode.o iwl-agn-tx.o -iwlwifi-objs += iwl-agn-lib.o iwl-agn-calib.o iwl-io.o -iwlwifi-objs += iwl-agn-tt.o iwl-agn-sta.o +# AGN +obj-$(CONFIG_IWLAGN) += iwlagn.o +iwlagn-objs := iwl-agn.o iwl-agn-rs.o +iwlagn-objs += iwl-agn-ucode.o iwl-agn-tx.o +iwlagn-objs += iwl-agn-lib.o iwl-agn-calib.o iwl-io.o +iwlagn-objs += iwl-agn-tt.o iwl-agn-sta.o -iwlwifi-objs += iwl-core.o iwl-eeprom.o iwl-power.o -iwlwifi-objs += iwl-rx.o iwl-sta.o -iwlwifi-objs += iwl-scan.o iwl-led.o -iwlwifi-objs += iwl-agn-rxon.o -iwlwifi-objs += iwl-5000.o -iwlwifi-objs += iwl-6000.o -iwlwifi-objs += iwl-1000.o -iwlwifi-objs += iwl-2000.o -iwlwifi-objs += iwl-pci.o -iwlwifi-objs += iwl-trans.o -iwlwifi-objs += iwl-trans-pcie.o iwl-trans-pcie-rx.o iwl-trans-pcie-tx.o +iwlagn-objs += iwl-core.o iwl-eeprom.o iwl-power.o +iwlagn-objs += iwl-rx.o iwl-sta.o +iwlagn-objs += iwl-scan.o iwl-led.o +iwlagn-objs += iwl-agn-rxon.o +iwlagn-objs += iwl-5000.o +iwlagn-objs += iwl-6000.o +iwlagn-objs += iwl-1000.o +iwlagn-objs += iwl-2000.o +iwlagn-objs += iwl-pci.o +iwlagn-objs += iwl-trans.o +iwlagn-objs += iwl-trans-pcie.o iwl-trans-pcie-rx.o iwl-trans-pcie-tx.o -iwlwifi-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o -iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o -iwlwifi-$(CONFIG_IWLWIFI_DEVICE_SVTOOL) += iwl-sv-open.o +iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o +iwlagn-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o +iwlagn-$(CONFIG_IWLWIFI_DEVICE_SVTOOL) += iwl-sv-open.o CFLAGS_iwl-devtrace.o := -I$(src) diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index d30714be515b..e8b324c84da8 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -190,6 +190,433 @@ int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band) return -1; } +static int iwl_get_single_channel_for_scan(struct iwl_priv *priv, + struct ieee80211_vif *vif, + enum ieee80211_band band, + struct iwl_scan_channel *scan_ch) +{ + const struct ieee80211_supported_band *sband; + u16 passive_dwell = 0; + u16 active_dwell = 0; + int added = 0; + u16 channel = 0; + + sband = iwl_get_hw_mode(priv, band); + if (!sband) { + IWL_ERR(priv, "invalid band\n"); + return added; + } + + active_dwell = iwl_get_active_dwell_time(priv, band, 0); + passive_dwell = iwl_get_passive_dwell_time(priv, band, vif); + + if (passive_dwell <= active_dwell) + passive_dwell = active_dwell + 1; + + channel = iwl_get_single_channel_number(priv, band); + if (channel) { + scan_ch->channel = cpu_to_le16(channel); + scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; + scan_ch->active_dwell = cpu_to_le16(active_dwell); + scan_ch->passive_dwell = cpu_to_le16(passive_dwell); + /* Set txpower levels to defaults */ + scan_ch->dsp_atten = 110; + if (band == IEEE80211_BAND_5GHZ) + scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; + else + scan_ch->tx_gain = ((1 << 5) | (5 << 3)); + added++; + } else + IWL_ERR(priv, "no valid channel found\n"); + return added; +} + +static int iwl_get_channels_for_scan(struct iwl_priv *priv, + struct ieee80211_vif *vif, + enum ieee80211_band band, + u8 is_active, u8 n_probes, + struct iwl_scan_channel *scan_ch) +{ + struct ieee80211_channel *chan; + const struct ieee80211_supported_band *sband; + const struct iwl_channel_info *ch_info; + u16 passive_dwell = 0; + u16 active_dwell = 0; + int added, i; + u16 channel; + + sband = iwl_get_hw_mode(priv, band); + if (!sband) + return 0; + + active_dwell = iwl_get_active_dwell_time(priv, band, n_probes); + passive_dwell = iwl_get_passive_dwell_time(priv, band, vif); + + if (passive_dwell <= active_dwell) + passive_dwell = active_dwell + 1; + + for (i = 0, added = 0; i < priv->scan_request->n_channels; i++) { + chan = priv->scan_request->channels[i]; + + if (chan->band != band) + continue; + + channel = chan->hw_value; + scan_ch->channel = cpu_to_le16(channel); + + ch_info = iwl_get_channel_info(priv, band, channel); + if (!is_channel_valid(ch_info)) { + IWL_DEBUG_SCAN(priv, "Channel %d is INVALID for this band.\n", + channel); + continue; + } + + if (!is_active || is_channel_passive(ch_info) || + (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)) + scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; + else + scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE; + + if (n_probes) + scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes); + + scan_ch->active_dwell = cpu_to_le16(active_dwell); + scan_ch->passive_dwell = cpu_to_le16(passive_dwell); + + /* Set txpower levels to defaults */ + scan_ch->dsp_atten = 110; + + /* NOTE: if we were doing 6Mb OFDM for scans we'd use + * power level: + * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3; + */ + if (band == IEEE80211_BAND_5GHZ) + scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; + else + scan_ch->tx_gain = ((1 << 5) | (5 << 3)); + + IWL_DEBUG_SCAN(priv, "Scanning ch=%d prob=0x%X [%s %d]\n", + channel, le32_to_cpu(scan_ch->type), + (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ? + "ACTIVE" : "PASSIVE", + (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ? + active_dwell : passive_dwell); + + scan_ch++; + added++; + } + + IWL_DEBUG_SCAN(priv, "total channels to scan %d\n", added); + return added; +} + +int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) +{ + struct iwl_host_cmd cmd = { + .id = REPLY_SCAN_CMD, + .len = { sizeof(struct iwl_scan_cmd), }, + .flags = CMD_SYNC, + }; + struct iwl_scan_cmd *scan; + struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; + u32 rate_flags = 0; + u16 cmd_len; + u16 rx_chain = 0; + enum ieee80211_band band; + u8 n_probes = 0; + u8 rx_ant = hw_params(priv).valid_rx_ant; + u8 rate; + bool is_active = false; + int chan_mod; + u8 active_chains; + u8 scan_tx_antennas = hw_params(priv).valid_tx_ant; + int ret; + + lockdep_assert_held(&priv->shrd->mutex); + + if (vif) + ctx = iwl_rxon_ctx_from_vif(vif); + + if (!priv->scan_cmd) { + priv->scan_cmd = kmalloc(sizeof(struct iwl_scan_cmd) + + IWL_MAX_SCAN_SIZE, GFP_KERNEL); + if (!priv->scan_cmd) { + IWL_DEBUG_SCAN(priv, + "fail to allocate memory for scan\n"); + return -ENOMEM; + } + } + scan = priv->scan_cmd; + memset(scan, 0, sizeof(struct iwl_scan_cmd) + IWL_MAX_SCAN_SIZE); + + scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH; + scan->quiet_time = IWL_ACTIVE_QUIET_TIME; + + if (priv->scan_type != IWL_SCAN_ROC && + iwl_is_any_associated(priv)) { + u16 interval = 0; + u32 extra; + u32 suspend_time = 100; + u32 scan_suspend_time = 100; + + IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); + switch (priv->scan_type) { + case IWL_SCAN_ROC: + WARN_ON(1); + break; + case IWL_SCAN_RADIO_RESET: + interval = 0; + break; + case IWL_SCAN_NORMAL: + interval = vif->bss_conf.beacon_int; + break; + } + + scan->suspend_time = 0; + scan->max_out_time = cpu_to_le32(200 * 1024); + if (!interval) + interval = suspend_time; + + extra = (suspend_time / interval) << 22; + scan_suspend_time = (extra | + ((suspend_time % interval) * 1024)); + scan->suspend_time = cpu_to_le32(scan_suspend_time); + IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n", + scan_suspend_time, interval); + } else if (priv->scan_type == IWL_SCAN_ROC) { + scan->suspend_time = 0; + scan->max_out_time = 0; + scan->quiet_time = 0; + scan->quiet_plcp_th = 0; + } + + switch (priv->scan_type) { + case IWL_SCAN_RADIO_RESET: + IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n"); + break; + case IWL_SCAN_NORMAL: + if (priv->scan_request->n_ssids) { + int i, p = 0; + IWL_DEBUG_SCAN(priv, "Kicking off active scan\n"); + for (i = 0; i < priv->scan_request->n_ssids; i++) { + /* always does wildcard anyway */ + if (!priv->scan_request->ssids[i].ssid_len) + continue; + scan->direct_scan[p].id = WLAN_EID_SSID; + scan->direct_scan[p].len = + priv->scan_request->ssids[i].ssid_len; + memcpy(scan->direct_scan[p].ssid, + priv->scan_request->ssids[i].ssid, + priv->scan_request->ssids[i].ssid_len); + n_probes++; + p++; + } + is_active = true; + } else + IWL_DEBUG_SCAN(priv, "Start passive scan.\n"); + break; + case IWL_SCAN_ROC: + IWL_DEBUG_SCAN(priv, "Start ROC scan.\n"); + break; + } + + scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; + scan->tx_cmd.sta_id = ctx->bcast_sta_id; + scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; + + switch (priv->scan_band) { + case IEEE80211_BAND_2GHZ: + scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK; + chan_mod = le32_to_cpu( + priv->contexts[IWL_RXON_CTX_BSS].active.flags & + RXON_FLG_CHANNEL_MODE_MSK) + >> RXON_FLG_CHANNEL_MODE_POS; + if (chan_mod == CHANNEL_MODE_PURE_40) { + rate = IWL_RATE_6M_PLCP; + } else { + rate = IWL_RATE_1M_PLCP; + rate_flags = RATE_MCS_CCK_MSK; + } + /* + * Internal scans are passive, so we can indiscriminately set + * the BT ignore flag on 2.4 GHz since it applies to TX only. + */ + if (priv->cfg->bt_params && + priv->cfg->bt_params->advanced_bt_coexist) + scan->tx_cmd.tx_flags |= TX_CMD_FLG_IGNORE_BT; + break; + case IEEE80211_BAND_5GHZ: + rate = IWL_RATE_6M_PLCP; + break; + default: + IWL_WARN(priv, "Invalid scan band\n"); + return -EIO; + } + + /* + * If active scanning is requested but a certain channel is + * marked passive, we can do active scanning if we detect + * transmissions. + * + * There is an issue with some firmware versions that triggers + * a sysassert on a "good CRC threshold" of zero (== disabled), + * on a radar channel even though this means that we should NOT + * send probes. + * + * The "good CRC threshold" is the number of frames that we + * need to receive during our dwell time on a channel before + * sending out probes -- setting this to a huge value will + * mean we never reach it, but at the same time work around + * the aforementioned issue. Thus use IWL_GOOD_CRC_TH_NEVER + * here instead of IWL_GOOD_CRC_TH_DISABLED. + * + * This was fixed in later versions along with some other + * scan changes, and the threshold behaves as a flag in those + * versions. + */ + if (priv->new_scan_threshold_behaviour) + scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT : + IWL_GOOD_CRC_TH_DISABLED; + else + scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT : + IWL_GOOD_CRC_TH_NEVER; + + band = priv->scan_band; + + if (priv->cfg->scan_rx_antennas[band]) + rx_ant = priv->cfg->scan_rx_antennas[band]; + + if (band == IEEE80211_BAND_2GHZ && + priv->cfg->bt_params && + priv->cfg->bt_params->advanced_bt_coexist) { + /* transmit 2.4 GHz probes only on first antenna */ + scan_tx_antennas = first_antenna(scan_tx_antennas); + } + + priv->scan_tx_ant[band] = iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band], + scan_tx_antennas); + rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]); + scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags); + + /* In power save mode use one chain, otherwise use all chains */ + if (test_bit(STATUS_POWER_PMI, &priv->shrd->status)) { + /* rx_ant has been set to all valid chains previously */ + active_chains = rx_ant & + ((u8)(priv->chain_noise_data.active_chains)); + if (!active_chains) + active_chains = rx_ant; + + IWL_DEBUG_SCAN(priv, "chain_noise_data.active_chains: %u\n", + priv->chain_noise_data.active_chains); + + rx_ant = first_antenna(active_chains); + } + if (priv->cfg->bt_params && + priv->cfg->bt_params->advanced_bt_coexist && + priv->bt_full_concurrent) { + /* operated as 1x1 in full concurrency mode */ + rx_ant = first_antenna(rx_ant); + } + + /* MIMO is not used here, but value is required */ + rx_chain |= + hw_params(priv).valid_rx_ant << RXON_RX_CHAIN_VALID_POS; + rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; + rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS; + rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; + scan->rx_chain = cpu_to_le16(rx_chain); + switch (priv->scan_type) { + case IWL_SCAN_NORMAL: + cmd_len = iwl_fill_probe_req(priv, + (struct ieee80211_mgmt *)scan->data, + vif->addr, + priv->scan_request->ie, + priv->scan_request->ie_len, + IWL_MAX_SCAN_SIZE - sizeof(*scan)); + break; + case IWL_SCAN_RADIO_RESET: + case IWL_SCAN_ROC: + /* use bcast addr, will not be transmitted but must be valid */ + cmd_len = iwl_fill_probe_req(priv, + (struct ieee80211_mgmt *)scan->data, + iwl_bcast_addr, NULL, 0, + IWL_MAX_SCAN_SIZE - sizeof(*scan)); + break; + default: + BUG(); + } + scan->tx_cmd.len = cpu_to_le16(cmd_len); + + scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK | + RXON_FILTER_BCON_AWARE_MSK); + + switch (priv->scan_type) { + case IWL_SCAN_RADIO_RESET: + scan->channel_count = + iwl_get_single_channel_for_scan(priv, vif, band, + (void *)&scan->data[cmd_len]); + break; + case IWL_SCAN_NORMAL: + scan->channel_count = + iwl_get_channels_for_scan(priv, vif, band, + is_active, n_probes, + (void *)&scan->data[cmd_len]); + break; + case IWL_SCAN_ROC: { + struct iwl_scan_channel *scan_ch; + + scan->channel_count = 1; + + scan_ch = (void *)&scan->data[cmd_len]; + scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; + scan_ch->channel = + cpu_to_le16(priv->hw_roc_channel->hw_value); + scan_ch->active_dwell = + scan_ch->passive_dwell = + cpu_to_le16(priv->hw_roc_duration); + + /* Set txpower levels to defaults */ + scan_ch->dsp_atten = 110; + + /* NOTE: if we were doing 6Mb OFDM for scans we'd use + * power level: + * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3; + */ + if (priv->hw_roc_channel->band == IEEE80211_BAND_5GHZ) + scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; + else + scan_ch->tx_gain = ((1 << 5) | (5 << 3)); + } + break; + } + + if (scan->channel_count == 0) { + IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count); + return -EIO; + } + + cmd.len[0] += le16_to_cpu(scan->tx_cmd.len) + + scan->channel_count * sizeof(struct iwl_scan_channel); + cmd.data[0] = scan; + cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY; + scan->len = cpu_to_le16(cmd.len[0]); + + /* set scan bit here for PAN params */ + set_bit(STATUS_SCAN_HW, &priv->shrd->status); + + ret = iwlagn_set_pan_params(priv); + if (ret) + return ret; + + ret = iwl_trans_send_cmd(trans(priv), &cmd); + if (ret) { + clear_bit(STATUS_SCAN_HW, &priv->shrd->status); + iwlagn_set_pan_params(priv); + } + + return ret; +} + int iwlagn_manage_ibss_station(struct iwl_priv *priv, struct ieee80211_vif *vif, bool add) { @@ -705,9 +1132,8 @@ static void iwlagn_set_kill_msk(struct iwl_priv *priv, } } -int iwlagn_bt_coex_profile_notif(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, - struct iwl_device_cmd *cmd) +void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb) { unsigned long flags; struct iwl_rx_packet *pkt = rxb_addr(rxb); @@ -716,7 +1142,7 @@ int iwlagn_bt_coex_profile_notif(struct iwl_priv *priv, if (priv->bt_enable_flag == IWLAGN_BT_FLAG_COEX_MODE_DISABLED) { /* bt coex disabled */ - return 0; + return; } IWL_DEBUG_COEX(priv, "BT Coex notification:\n"); @@ -758,7 +1184,6 @@ int iwlagn_bt_coex_profile_notif(struct iwl_priv *priv, spin_lock_irqsave(&priv->shrd->lock, flags); priv->bt_ci_compliance = coex->bt_ci_compliance; spin_unlock_irqrestore(&priv->shrd->lock, flags); - return 0; } void iwlagn_bt_rx_handler_setup(struct iwl_priv *priv) diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 7d6a3bf64950..ffee15ba06a8 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -346,7 +346,7 @@ static void rs_program_fix_rate(struct iwl_priv *priv, { struct iwl_station_priv *sta_priv = container_of(lq_sta, struct iwl_station_priv, lq_sta); - struct iwl_rxon_context *ctx = sta_priv->ctx; + struct iwl_rxon_context *ctx = sta_priv->common.ctx; lq_sta->active_legacy_rate = 0x0FFF; /* 1 - 54 MBits, includes CCK */ lq_sta->active_siso_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ @@ -710,7 +710,7 @@ static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags, static bool rs_use_green(struct ieee80211_sta *sta) { struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; - struct iwl_rxon_context *ctx = sta_priv->ctx; + struct iwl_rxon_context *ctx = sta_priv->common.ctx; return (sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) && !(ctx->ht.non_gf_sta_present); @@ -917,7 +917,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, struct iwl_scale_tbl_info tbl_type; struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl; struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; - struct iwl_rxon_context *ctx = sta_priv->ctx; + struct iwl_rxon_context *ctx = sta_priv->common.ctx; IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n"); @@ -1283,7 +1283,7 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv, s32 rate; s8 is_green = lq_sta->is_green; struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; - struct iwl_rxon_context *ctx = sta_priv->ctx; + struct iwl_rxon_context *ctx = sta_priv->common.ctx; if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported) return -1; @@ -1339,7 +1339,7 @@ static int rs_switch_to_mimo3(struct iwl_priv *priv, s32 rate; s8 is_green = lq_sta->is_green; struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; - struct iwl_rxon_context *ctx = sta_priv->ctx; + struct iwl_rxon_context *ctx = sta_priv->common.ctx; if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported) return -1; @@ -1396,7 +1396,7 @@ static int rs_switch_to_siso(struct iwl_priv *priv, u8 is_green = lq_sta->is_green; s32 rate; struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; - struct iwl_rxon_context *ctx = sta_priv->ctx; + struct iwl_rxon_context *ctx = sta_priv->common.ctx; if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported) return -1; @@ -2263,7 +2263,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, u8 tid = IWL_MAX_TID_COUNT; struct iwl_tid_data *tid_data; struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; - struct iwl_rxon_context *ctx = sta_priv->ctx; + struct iwl_rxon_context *ctx = sta_priv->common.ctx; IWL_DEBUG_RATE(priv, "rate scale calculate new rate for skb\n"); @@ -2273,6 +2273,9 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, info->flags & IEEE80211_TX_CTL_NO_ACK) return; + if (!sta || !lq_sta) + return; + lq_sta->supp_rates = sta->supp_rates[lq_sta->band]; tid = rs_tl_add_packet(lq_sta, hdr); @@ -2703,7 +2706,7 @@ static void rs_initialize_lq(struct iwl_priv *priv, return; sta_priv = (void *)sta->drv_priv; - ctx = sta_priv->ctx; + ctx = sta_priv->common.ctx; i = lq_sta->last_txrate_idx; diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index ca632f9b1cc8..00e6fc59e459 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -370,7 +370,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv) slot1 = IWL_MIN_SLOT_TIME; } else if (!ctx_pan->vif->bss_conf.idle && !ctx_pan->vif->bss_conf.assoc) { - slot1 = dtim * bcnint * 3 - IWL_MIN_SLOT_TIME; + slot1 = bcnint * 3 - IWL_MIN_SLOT_TIME; slot0 = IWL_MIN_SLOT_TIME; } } else if (ctx_pan->vif) { diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-tt.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-tt.c index c27180a73351..495f93664741 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-tt.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-tt.c @@ -114,6 +114,9 @@ static bool iwl_within_ct_kill_margin(struct iwl_priv *priv) s32 temp = priv->temperature; /* degrees CELSIUS except specified */ bool within_margin = false; + if (priv->cfg->base_params->temperature_kelvin) + temp = KELVIN_TO_CELSIUS(priv->temperature); + if (!priv->thermal_throttle.advanced_tt) within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >= CT_KILL_THRESHOLD_LEGACY) ? true : false; @@ -588,6 +591,9 @@ static void iwl_bg_tt_work(struct work_struct *work) if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) return; + if (priv->cfg->base_params->temperature_kelvin) + temp = KELVIN_TO_CELSIUS(priv->temperature); + if (!priv->thermal_throttle.advanced_tt) iwl_legacy_tt_handler(priv, temp, false); else @@ -635,13 +641,11 @@ void iwl_tt_initialize(struct iwl_priv *priv) if (priv->cfg->base_params->adv_thermal_throttle) { IWL_DEBUG_TEMP(priv, "Advanced Thermal Throttling\n"); - tt->restriction = kcalloc(IWL_TI_STATE_MAX, - sizeof(struct iwl_tt_restriction), - GFP_KERNEL); - tt->transaction = kcalloc(IWL_TI_STATE_MAX * - (IWL_TI_STATE_MAX - 1), - sizeof(struct iwl_tt_trans), - GFP_KERNEL); + tt->restriction = kzalloc(sizeof(struct iwl_tt_restriction) * + IWL_TI_STATE_MAX, GFP_KERNEL); + tt->transaction = kzalloc(sizeof(struct iwl_tt_trans) * + IWL_TI_STATE_MAX * (IWL_TI_STATE_MAX - 1), + GFP_KERNEL); if (!tt->restriction || !tt->transaction) { IWL_ERR(priv, "Fallback to Legacy Throttling\n"); priv->thermal_throttle.advanced_tt = false; diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index dcb3bd67d4f9..459b82b8a2a7 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -300,7 +300,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) sta_priv = (void *)info->control.sta->drv_priv; if (sta_priv && sta_priv->asleep && - (info->flags & IEEE80211_TX_CTL_POLL_RESPONSE)) { + (info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE)) { /* * This sends an asynchronous command to the device, * but we can rely on it being processed before the @@ -313,9 +313,6 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) iwl_sta_modify_sleep_tx_count(priv, sta_id, 1); } - if (info->flags & IEEE80211_TX_CTL_AMPDU) - is_agg = true; - /* irqs already disabled/saved above when locking priv->shrd->lock */ spin_lock(&priv->shrd->sta_lock); @@ -325,7 +322,10 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) goto drop_unlock_sta; memset(dev_cmd, 0, sizeof(*dev_cmd)); - tx_cmd = (struct iwl_tx_cmd *) dev_cmd->payload; + tx_cmd = &dev_cmd->cmd.tx; + + /* Copy MAC header from skb into command buffer */ + memcpy(tx_cmd->hdr, hdr, hdr_len); /* Total # bytes to be transmitted */ len = (u16)skb->len; @@ -342,8 +342,6 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) iwl_update_stats(priv, true, fc, len); - memset(&info->status, 0, sizeof(info->status)); - info->driver_data[0] = ctx; info->driver_data[1] = dev_cmd; @@ -582,9 +580,6 @@ static void iwl_rx_reply_tx_agg(struct iwl_priv *priv, IWL_DEBUG_COEX(priv, "receive reply tx w/ bt_kill\n"); } - if (tx_resp->frame_count == 1) - return; - /* Construct bit-map of pending frames within Tx window */ for (i = 0; i < tx_resp->frame_count; i++) { u16 fstatus = le16_to_cpu(frame_status[i].status); @@ -741,8 +736,7 @@ static void iwl_check_abort_status(struct iwl_priv *priv, } } -int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, - struct iwl_device_cmd *cmd) +void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = rxb_addr(rxb); u16 sequence = le16_to_cpu(pkt->hdr.sequence); @@ -830,7 +824,6 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, iwl_check_abort_status(priv, tx_resp->frame_count, status); spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); - return 0; } /** @@ -839,9 +832,8 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, * Handles block-acknowledge notification from device, which reports success * of frames sent via aggregation. */ -int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, - struct iwl_device_cmd *cmd) +void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba; @@ -865,7 +857,7 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, if (scd_flow >= hw_params(priv).max_txq_num) { IWL_ERR(priv, "BUG_ON scd_flow is bigger than number of queues\n"); - return 0; + return; } sta_id = ba_resp->sta_id; @@ -885,14 +877,14 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, "BA scd_flow %d does not match txq_id %d\n", scd_flow, agg->txq_id); spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); - return 0; + return; } if (unlikely(!agg->wait_for_ba)) { if (unlikely(ba_resp->bitmap)) IWL_ERR(priv, "Received BA when not expected\n"); spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); - return 0; + return; } IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, " @@ -943,10 +935,7 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, else WARN_ON_ONCE(1); - info = IEEE80211_SKB_CB(skb); - kmem_cache_free(priv->tx_cmd_pool, (info->driver_data[1])); - - if (freed == 1) { + if (freed == 0) { /* this is the first skb we deliver in this batch */ /* put the rate scaling data there */ info = IEEE80211_SKB_CB(skb); @@ -959,9 +948,11 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, info); } + info = IEEE80211_SKB_CB(skb); + kmem_cache_free(priv->tx_cmd_pool, (info->driver_data[1])); + ieee80211_tx_status_irqsafe(priv->hw, skb); } spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); - return 0; } diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index b4e1e7c4c314..634f18f6125a 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -228,9 +228,8 @@ static int iwlagn_send_calib_cfg(struct iwl_priv *priv) return iwl_trans_send_cmd(trans(priv), &cmd); } -int iwlagn_rx_calib_result(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, - struct iwl_device_cmd *cmd) +void iwlagn_rx_calib_result(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->u.raw; @@ -263,10 +262,9 @@ int iwlagn_rx_calib_result(struct iwl_priv *priv, default: IWL_ERR(priv, "Unknown calibration notification %d\n", hdr->op_code); - return -1; + return; } iwl_calib_set(&priv->calib_results[index], pkt->u.raw, len); - return 0; } int iwlagn_init_alive_start(struct iwl_priv *priv) diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn.c index d0fd6f063bf8..6def1c272775 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -79,7 +79,6 @@ MODULE_DESCRIPTION(DRV_DESCRIPTION); MODULE_VERSION(DRV_VERSION); MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); MODULE_LICENSE("GPL"); -MODULE_ALIAS("iwlagn"); void iwl_update_chain_flags(struct iwl_priv *priv) { @@ -2514,7 +2513,7 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, mutex_lock(&priv->shrd->mutex); IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n", sta->addr); - sta_priv->sta_id = IWL_INVALID_STATION; + sta_priv->common.sta_id = IWL_INVALID_STATION; atomic_set(&sta_priv->pending_frames, 0); if (vif->type == NL80211_IFTYPE_AP) @@ -2530,7 +2529,7 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, return ret; } - sta_priv->sta_id = sta_id; + sta_priv->common.sta_id = sta_id; /* Initialize rate scaling */ IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n", @@ -2771,6 +2770,15 @@ static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw, mutex_lock(&priv->shrd->mutex); + /* + * TODO: Remove this hack! Firmware needs to be updated + * to allow longer off-channel periods in scanning for + * this use case, based on a flag (and we'll need an API + * flag in the firmware when it has that). + */ + if (iwl_is_associated(priv, IWL_RXON_CTX_BSS) && duration > 80) + duration = 80; + if (test_bit(STATUS_SCAN_HW, &priv->shrd->status)) { err = -EBUSY; goto out; @@ -2779,7 +2787,6 @@ static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw, priv->hw_roc_channel = channel; priv->hw_roc_chantype = channel_type; priv->hw_roc_duration = duration; - priv->hw_roc_start_notified = false; cancel_delayed_work(&priv->hw_roc_disable_work); if (!ctx->is_active) { diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn.h b/trunk/drivers/net/wireless/iwlwifi/iwl-agn.h index 2a297d1e6bc7..4bc1f4669e5a 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -88,9 +88,8 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw, u32 changes); /* uCode */ -int iwlagn_rx_calib_result(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, - struct iwl_device_cmd *cmd); +void iwlagn_rx_calib_result(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb); int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type); void iwlagn_send_prio_tbl(struct iwl_priv *priv); int iwlagn_run_init_ucode(struct iwl_priv *priv); @@ -117,11 +116,9 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u16 tid, u16 *ssn); int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u16 tid); -int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, - struct iwl_device_cmd *cmd); -int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, - struct iwl_device_cmd *cmd); +void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb); +void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); static inline u32 iwl_tx_status_to_mac80211(u32 status) { @@ -149,6 +146,7 @@ static inline bool iwl_is_tx_success(u32 status) u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx, u8 valid); /* scan */ +int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif); void iwlagn_post_scan(struct iwl_priv *priv); void iwlagn_disable_roc(struct iwl_priv *priv); @@ -158,9 +156,8 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv, /* bt coex */ void iwlagn_send_advance_bt_config(struct iwl_priv *priv); -int iwlagn_bt_coex_profile_notif(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, - struct iwl_device_cmd *cmd); +void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb); void iwlagn_bt_rx_handler_setup(struct iwl_priv *priv); void iwlagn_bt_setup_deferred_work(struct iwl_priv *priv); void iwlagn_bt_cancel_deferred_work(struct iwl_priv *priv); diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-core.c b/trunk/drivers/net/wireless/iwlwifi/iwl-core.c index 0725603dbf1d..cea6520fafdb 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-core.c @@ -125,12 +125,12 @@ int iwl_init_geos(struct iwl_priv *priv) return 0; } - channels = kcalloc(priv->channel_count, - sizeof(struct ieee80211_channel), GFP_KERNEL); + channels = kzalloc(sizeof(struct ieee80211_channel) * + priv->channel_count, GFP_KERNEL); if (!channels) return -ENOMEM; - rates = kcalloc(IWL_RATE_COUNT_LEGACY, sizeof(struct ieee80211_rate), + rates = kzalloc((sizeof(struct ieee80211_rate) * IWL_RATE_COUNT_LEGACY), GFP_KERNEL); if (!rates) { kfree(channels); @@ -1123,9 +1123,8 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear) &statistics_cmd); } -int iwl_mac_conf_tx(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, u16 queue, - const struct ieee80211_tx_queue_params *params) +int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, + const struct ieee80211_tx_queue_params *params) { struct iwl_priv *priv = hw->priv; struct iwl_rxon_context *ctx; diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-core.h b/trunk/drivers/net/wireless/iwlwifi/iwl-core.h index db50b650756c..6d7ad45c6d6f 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-core.h @@ -108,6 +108,7 @@ struct iwl_lib_ops { * radio tuning when there is a high receiving plcp error rate * @chain_noise_scale: default chain noise scale used for gain computation * @wd_timeout: TX queues watchdog timeout + * @temperature_kelvin: temperature report by uCode in kelvin * @max_event_log_size: size of event log buffer size for ucode event logging * @shadow_reg_enable: HW shadhow register bit * @no_idle_support: do not support idle mode @@ -129,6 +130,7 @@ struct iwl_base_params { u8 plcp_delta_threshold; s32 chain_noise_scale; unsigned int wd_timeout; + bool temperature_kelvin; u32 max_event_log_size; const bool shadow_reg_enable; const bool no_idle_support; @@ -236,8 +238,7 @@ struct iwl_cfg { * L i b * ***************************/ -int iwl_mac_conf_tx(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, u16 queue, +int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params); int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw); void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx, @@ -319,7 +320,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force); ******************************************************************************/ void iwl_init_scan_params(struct iwl_priv *priv); int iwl_scan_cancel(struct iwl_priv *priv); -void iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms); +int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms); void iwl_force_scan_end(struct iwl_priv *priv); int iwl_mac_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, @@ -329,6 +330,12 @@ int iwl_force_reset(struct iwl_priv *priv, int mode, bool external); u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, const u8 *ta, const u8 *ie, int ie_len, int left); void iwl_setup_rx_scan_handlers(struct iwl_priv *priv); +u16 iwl_get_active_dwell_time(struct iwl_priv *priv, + enum ieee80211_band band, + u8 n_probes); +u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, + enum ieee80211_band band, + struct ieee80211_vif *vif); void iwl_setup_scan_deferred_work(struct iwl_priv *priv); void iwl_cancel_scan_deferred_work(struct iwl_priv *priv); int __must_check iwl_scan_initiate(struct iwl_priv *priv, diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/trunk/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 6d49dfbee964..bf2a678970a9 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -715,20 +715,6 @@ static ssize_t iwl_dbgfs_disable_ht40_read(struct file *file, return simple_read_from_buffer(user_buf, count, ppos, buf, pos); } -static ssize_t iwl_dbgfs_temperature_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_priv *priv = file->private_data; - char buf[8]; - int pos = 0; - const size_t bufsz = sizeof(buf); - - pos += scnprintf(buf + pos, bufsz - pos, "%d\n", priv->temperature); - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - - static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) @@ -823,7 +809,6 @@ DEBUGFS_READ_WRITE_FILE_OPS(rx_handlers); DEBUGFS_READ_FILE_OPS(qos); DEBUGFS_READ_FILE_OPS(thermal_throttling); DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40); -DEBUGFS_READ_FILE_OPS(temperature); DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override); DEBUGFS_READ_FILE_OPS(current_sleep_command); @@ -2551,7 +2536,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR); DEBUGFS_ADD_FILE(thermal_throttling, dir_data, S_IRUSR); DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR); - DEBUGFS_ADD_FILE(temperature, dir_data, S_IRUSR); + DEBUGFS_ADD_U32(temperature, dir_data, &priv->temperature, S_IRUSR); DEBUGFS_ADD_FILE(rx_statistics, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(tx_statistics, dir_debug, S_IRUSR); diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-dev.h b/trunk/drivers/net/wireless/iwlwifi/iwl-dev.h index 257aa9a407ca..f69e556bd3c2 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -202,6 +202,11 @@ struct iwl_station_entry { struct iwl_link_quality_cmd *lq; }; +struct iwl_station_priv_common { + struct iwl_rxon_context *ctx; + u8 sta_id; +}; + /* * iwl_station_priv: Driver's private station information * @@ -210,13 +215,12 @@ struct iwl_station_entry { * space. */ struct iwl_station_priv { - struct iwl_rxon_context *ctx; + struct iwl_station_priv_common common; struct iwl_lq_sta lq_sta; atomic_t pending_frames; bool client; bool asleep; u8 max_agg_bufsize; - u8 sta_id; }; /** @@ -841,9 +845,8 @@ struct iwl_priv { void (*pre_rx_handler)(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); - int (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, - struct iwl_device_cmd *cmd); + void (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb); struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; @@ -877,7 +880,7 @@ struct iwl_priv { u8 channel_count; /* # of channels */ /* thermal calibration */ - s32 temperature; /* Celsius */ + s32 temperature; /* degrees Kelvin */ s32 last_temperature; /* init calibration results */ @@ -1030,7 +1033,7 @@ struct iwl_priv { struct delayed_work hw_roc_disable_work; enum nl80211_channel_type hw_roc_chantype; int hw_roc_duration; - bool hw_roc_setup, hw_roc_start_notified; + bool hw_roc_setup; /* bt coex */ u8 bt_enable_flag; diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.c index a4e43bd4a547..0b669417b0a6 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -899,9 +899,8 @@ int iwl_init_channel_map(struct iwl_priv *priv) IWL_DEBUG_EEPROM(priv, "Parsing data for %d channels.\n", priv->channel_count); - priv->channel_info = kcalloc(priv->channel_count, - sizeof(struct iwl_channel_info), - GFP_KERNEL); + priv->channel_info = kzalloc(sizeof(struct iwl_channel_info) * + priv->channel_count, GFP_KERNEL); if (!priv->channel_info) { IWL_ERR(priv, "Could not allocate channel_info\n"); priv->channel_count = 0; diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-led.c b/trunk/drivers/net/wireless/iwlwifi/iwl-led.c index f149165e8010..7dffed186f0a 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-led.c @@ -104,6 +104,7 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd) .len = { sizeof(struct iwl_led_cmd), }, .data = { led_cmd, }, .flags = CMD_ASYNC, + .callback = NULL, }; u32 reg; diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-rx.c b/trunk/drivers/net/wireless/iwlwifi/iwl-rx.c index bcd7f64683aa..2ee61031e207 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -130,9 +130,8 @@ const char *get_cmd_string(u8 cmd) * ******************************************************************************/ -static int iwl_rx_reply_error(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, - struct iwl_device_cmd *cmd) +static void iwl_rx_reply_error(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = rxb_addr(rxb); @@ -143,11 +142,9 @@ static int iwl_rx_reply_error(struct iwl_priv *priv, pkt->u.err_resp.cmd_id, le16_to_cpu(pkt->u.err_resp.bad_cmd_seq_num), le32_to_cpu(pkt->u.err_resp.error_info)); - return 0; } -static int iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, - struct iwl_device_cmd *cmd) +static void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_csa_notification *csa = &(pkt->u.csa_notif); @@ -159,7 +156,7 @@ static int iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, struct iwl_rxon_cmd *rxon = (void *)&ctx->active; if (!test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status)) - return 0; + return; if (!le32_to_cpu(csa->status) && csa->channel == priv->switch_channel) { rxon->channel = csa->channel; @@ -172,13 +169,11 @@ static int iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, le16_to_cpu(csa->channel)); iwl_chswitch_done(priv, false); } - return 0; } -static int iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, - struct iwl_device_cmd *cmd) +static void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif); @@ -186,17 +181,15 @@ static int iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, if (!report->state) { IWL_DEBUG_11H(priv, "Spectrum Measure Notification: Start\n"); - return 0; + return; } memcpy(&priv->measure_report, report, sizeof(*report)); priv->measurement_status |= MEASUREMENT_READY; - return 0; } -static int iwl_rx_pm_sleep_notif(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, - struct iwl_device_cmd *cmd) +static void iwl_rx_pm_sleep_notif(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb) { #ifdef CONFIG_IWLWIFI_DEBUG struct iwl_rx_packet *pkt = rxb_addr(rxb); @@ -204,12 +197,10 @@ static int iwl_rx_pm_sleep_notif(struct iwl_priv *priv, IWL_DEBUG_RX(priv, "sleep mode: %d, src: %d\n", sleep->pm_sleep_mode, sleep->pm_wakeup_src); #endif - return 0; } -static int iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, - struct iwl_device_cmd *cmd) +static void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = rxb_addr(rxb); u32 __maybe_unused len = @@ -218,12 +209,10 @@ static int iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv, "notification for %s:\n", len, get_cmd_string(pkt->hdr.cmd)); iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, len); - return 0; } -static int iwl_rx_beacon_notif(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, - struct iwl_device_cmd *cmd) +static void iwl_rx_beacon_notif(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwlagn_beacon_notif *beacon = (void *)pkt->u.raw; @@ -244,7 +233,6 @@ static int iwl_rx_beacon_notif(struct iwl_priv *priv, if (!test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) queue_work(priv->shrd->workqueue, &priv->beacon_update); - return 0; } /* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */ @@ -487,9 +475,8 @@ iwl_accumulative_statistics(struct iwl_priv *priv, } #endif -static int iwl_rx_statistics(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, - struct iwl_device_cmd *cmd) +static void iwl_rx_statistics(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb) { unsigned long stamp = jiffies; const int reg_recalib_period = 60; @@ -543,7 +530,7 @@ static int iwl_rx_statistics(struct iwl_priv *priv, WARN_ONCE(1, "len %d doesn't match BT (%zu) or normal (%zu)\n", len, sizeof(struct iwl_bt_notif_statistics), sizeof(struct iwl_notif_statistics)); - return 0; + return; } change = common->temperature != priv->statistics.common.temperature || @@ -586,12 +573,10 @@ static int iwl_rx_statistics(struct iwl_priv *priv, } if (priv->cfg->lib->temperature && change) priv->cfg->lib->temperature(priv); - return 0; } -static int iwl_rx_reply_statistics(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, - struct iwl_device_cmd *cmd) +static void iwl_rx_reply_statistics(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = rxb_addr(rxb); @@ -606,15 +591,13 @@ static int iwl_rx_reply_statistics(struct iwl_priv *priv, #endif IWL_DEBUG_RX(priv, "Statistics have been cleared\n"); } - iwl_rx_statistics(priv, rxb, cmd); - return 0; + iwl_rx_statistics(priv, rxb); } /* Handle notification from uCode that card's power state is changing * due to software, hardware, or critical temperature RFKILL */ -static int iwl_rx_card_state_notif(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, - struct iwl_device_cmd *cmd) +static void iwl_rx_card_state_notif(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = rxb_addr(rxb); u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags); @@ -662,12 +645,10 @@ static int iwl_rx_card_state_notif(struct iwl_priv *priv, test_bit(STATUS_RF_KILL_HW, &priv->shrd->status)); else wake_up(&priv->shrd->wait_command_queue); - return 0; } -static int iwl_rx_missed_beacon_notif(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, - struct iwl_device_cmd *cmd) +static void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = rxb_addr(rxb); @@ -685,21 +666,18 @@ static int iwl_rx_missed_beacon_notif(struct iwl_priv *priv, if (!test_bit(STATUS_SCANNING, &priv->shrd->status)) iwl_init_sensitivity(priv); } - return 0; } /* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD). * This will be used later in iwl_rx_reply_rx() for REPLY_RX_MPDU_CMD. */ -static int iwl_rx_reply_rx_phy(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, - struct iwl_device_cmd *cmd) +static void iwl_rx_reply_rx_phy(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = rxb_addr(rxb); priv->last_phy_res_valid = true; memcpy(&priv->last_phy_res, pkt->u.raw, sizeof(struct iwl_rx_phy_res)); - return 0; } /* @@ -914,9 +892,8 @@ static int iwlagn_calc_rssi(struct iwl_priv *priv, /* Called for REPLY_RX (legacy ABG frames), or * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */ -static int iwl_rx_reply_rx(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, - struct iwl_device_cmd *cmd) +static void iwl_rx_reply_rx(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb) { struct ieee80211_hdr *header; struct ieee80211_rx_status rx_status; @@ -949,7 +926,7 @@ static int iwl_rx_reply_rx(struct iwl_priv *priv, } else { if (!priv->last_phy_res_valid) { IWL_ERR(priv, "MPDU frame without cached PHY data\n"); - return 0; + return; } phy_res = &priv->last_phy_res; amsdu = (struct iwl_rx_mpdu_res_start *)pkt->u.raw; @@ -963,14 +940,14 @@ static int iwl_rx_reply_rx(struct iwl_priv *priv, if ((unlikely(phy_res->cfg_phy_cnt > 20))) { IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n", phy_res->cfg_phy_cnt); - return 0; + return; } if (!(rx_pkt_status & RX_RES_STATUS_NO_CRC32_ERROR) || !(rx_pkt_status & RX_RES_STATUS_NO_RXE_OVERFLOW)) { IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n", le32_to_cpu(rx_pkt_status)); - return 0; + return; } /* This will be used in several places later */ @@ -1031,7 +1008,6 @@ static int iwl_rx_reply_rx(struct iwl_priv *priv, iwl_pass_packet_to_mac80211(priv, header, len, ampdu_status, rxb, &rx_status); - return 0; } /** @@ -1042,8 +1018,7 @@ static int iwl_rx_reply_rx(struct iwl_priv *priv, */ void iwl_setup_rx_handlers(struct iwl_priv *priv) { - int (**handlers)(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, - struct iwl_device_cmd *cmd); + void (**handlers)(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); handlers = priv->rx_handlers; @@ -1053,7 +1028,6 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv) handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif; handlers[PM_DEBUG_STATISTIC_NOTIFIC] = iwl_rx_pm_debug_statistics_notif; handlers[BEACON_NOTIFICATION] = iwl_rx_beacon_notif; - handlers[REPLY_ADD_STA] = iwl_add_sta_callback; /* * The same handler is used for both the REPLY to a discrete @@ -1091,11 +1065,9 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv) } -int iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, - struct iwl_device_cmd *cmd) +void iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = rxb_addr(rxb); - int err = 0; /* * Do the notification wait before RX handlers so @@ -1130,12 +1102,11 @@ int iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, * rx_handlers table. See iwl_setup_rx_handlers() */ if (priv->rx_handlers[pkt->hdr.cmd]) { priv->rx_handlers_stats[pkt->hdr.cmd]++; - err = priv->rx_handlers[pkt->hdr.cmd] (priv, rxb, cmd); + priv->rx_handlers[pkt->hdr.cmd] (priv, rxb); } else { /* No handling needed */ IWL_DEBUG_RX(priv, "No handler needed for %s, 0x%02x\n", get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); } - return err; } diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-scan.c b/trunk/drivers/net/wireless/iwlwifi/iwl-scan.c index c5c95d5319b1..fc5af3475392 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -114,65 +114,6 @@ static void iwl_complete_scan(struct iwl_priv *priv, bool aborted) priv->scan_request = NULL; } -static void iwl_process_scan_complete(struct iwl_priv *priv) -{ - bool aborted; - - lockdep_assert_held(&priv->shrd->mutex); - - if (!test_and_clear_bit(STATUS_SCAN_COMPLETE, &priv->shrd->status)) - return; - - IWL_DEBUG_SCAN(priv, "Completed scan.\n"); - - cancel_delayed_work(&priv->scan_check); - - aborted = test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->shrd->status); - if (aborted) - IWL_DEBUG_SCAN(priv, "Aborted scan completed.\n"); - - if (!test_and_clear_bit(STATUS_SCANNING, &priv->shrd->status)) { - IWL_DEBUG_SCAN(priv, "Scan already completed.\n"); - goto out_settings; - } - - if (priv->scan_type == IWL_SCAN_ROC) { - ieee80211_remain_on_channel_expired(priv->hw); - priv->hw_roc_channel = NULL; - schedule_delayed_work(&priv->hw_roc_disable_work, 10 * HZ); - } - - if (priv->scan_type != IWL_SCAN_NORMAL && !aborted) { - int err; - - /* Check if mac80211 requested scan during our internal scan */ - if (priv->scan_request == NULL) - goto out_complete; - - /* If so request a new scan */ - err = iwl_scan_initiate(priv, priv->scan_vif, IWL_SCAN_NORMAL, - priv->scan_request->channels[0]->band); - if (err) { - IWL_DEBUG_SCAN(priv, - "failed to initiate pending scan: %d\n", err); - aborted = true; - goto out_complete; - } - - return; - } - -out_complete: - iwl_complete_scan(priv, aborted); - -out_settings: - /* Can we still talk to firmware ? */ - if (!iwl_is_ready_rf(priv->shrd)) - return; - - iwlagn_post_scan(priv); -} - void iwl_force_scan_end(struct iwl_priv *priv) { lockdep_assert_held(&priv->shrd->mutex); @@ -186,7 +127,6 @@ void iwl_force_scan_end(struct iwl_priv *priv) clear_bit(STATUS_SCANNING, &priv->shrd->status); clear_bit(STATUS_SCAN_HW, &priv->shrd->status); clear_bit(STATUS_SCAN_ABORTING, &priv->shrd->status); - clear_bit(STATUS_SCAN_COMPLETE, &priv->shrd->status); iwl_complete_scan(priv, true); } @@ -229,7 +169,7 @@ int iwl_scan_cancel(struct iwl_priv *priv) * @ms: amount of time to wait (in milliseconds) for scan to abort * */ -void iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms) +int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms) { unsigned long timeout = jiffies + msecs_to_jiffies(ms); @@ -241,30 +181,16 @@ void iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms) while (time_before_eq(jiffies, timeout)) { if (!test_bit(STATUS_SCAN_HW, &priv->shrd->status)) - goto finished; + break; msleep(20); } - return; - - finished: - /* - * Now STATUS_SCAN_HW is clear. This means that the - * device finished, but the background work is going - * to execute at best as soon as we release the mutex. - * Since we need to be able to issue a new scan right - * after this function returns, run the complete here. - * The STATUS_SCAN_COMPLETE bit will then be cleared - * and prevent the background work from "completing" - * a possible new scan. - */ - iwl_process_scan_complete(priv); + return test_bit(STATUS_SCAN_HW, &priv->shrd->status); } /* Service response to REPLY_SCAN_CMD (0x80) */ -static int iwl_rx_reply_scan(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, - struct iwl_device_cmd *cmd) +static void iwl_rx_reply_scan(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb) { #ifdef CONFIG_IWLWIFI_DEBUG struct iwl_rx_packet *pkt = rxb_addr(rxb); @@ -273,13 +199,11 @@ static int iwl_rx_reply_scan(struct iwl_priv *priv, IWL_DEBUG_SCAN(priv, "Scan request status = 0x%x\n", notif->status); #endif - return 0; } /* Service SCAN_START_NOTIFICATION (0x82) */ -static int iwl_rx_scan_start_notif(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, - struct iwl_device_cmd *cmd) +static void iwl_rx_scan_start_notif(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_scanstart_notification *notif = @@ -294,19 +218,13 @@ static int iwl_rx_scan_start_notif(struct iwl_priv *priv, le32_to_cpu(notif->tsf_low), notif->status, notif->beacon_timer); - if (priv->scan_type == IWL_SCAN_ROC && - !priv->hw_roc_start_notified) { + if (priv->scan_type == IWL_SCAN_ROC) ieee80211_ready_on_channel(priv->hw); - priv->hw_roc_start_notified = true; - } - - return 0; } /* Service SCAN_RESULTS_NOTIFICATION (0x83) */ -static int iwl_rx_scan_results_notif(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, - struct iwl_device_cmd *cmd) +static void iwl_rx_scan_results_notif(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb) { #ifdef CONFIG_IWLWIFI_DEBUG struct iwl_rx_packet *pkt = rxb_addr(rxb); @@ -315,24 +233,20 @@ static int iwl_rx_scan_results_notif(struct iwl_priv *priv, IWL_DEBUG_SCAN(priv, "Scan ch.res: " "%d [802.11%s] " - "probe status: %u:%u " "(TSF: 0x%08X:%08X) - %d " "elapsed=%lu usec\n", notif->channel, notif->band ? "bg" : "a", - notif->probe_status, notif->num_probe_not_sent, le32_to_cpu(notif->tsf_high), le32_to_cpu(notif->tsf_low), le32_to_cpu(notif->statistics[0]), le32_to_cpu(notif->tsf_low) - priv->scan_start_tsf); #endif - return 0; } /* Service SCAN_COMPLETE_NOTIFICATION (0x84) */ -static int iwl_rx_scan_complete_notif(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, - struct iwl_device_cmd *cmd) +static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw; @@ -342,20 +256,13 @@ static int iwl_rx_scan_complete_notif(struct iwl_priv *priv, scan_notif->tsf_low, scan_notif->tsf_high, scan_notif->status); + /* The HW is no longer scanning */ + clear_bit(STATUS_SCAN_HW, &priv->shrd->status); + IWL_DEBUG_SCAN(priv, "Scan on %sGHz took %dms\n", (priv->scan_band == IEEE80211_BAND_2GHZ) ? "2.4" : "5.2", jiffies_to_msecs(jiffies - priv->scan_start)); - /* - * When aborting, we run the scan completed background work inline - * and the background work must then do nothing. The SCAN_COMPLETE - * bit helps implement that logic and thus needs to be set before - * queueing the work. Also, since the scan abort waits for SCAN_HW - * to clear, we need to set SCAN_COMPLETE before clearing SCAN_HW - * to avoid a race there. - */ - set_bit(STATUS_SCAN_COMPLETE, &priv->shrd->status); - clear_bit(STATUS_SCAN_HW, &priv->shrd->status); queue_work(priv->shrd->workqueue, &priv->scan_completed); if (priv->iw_mode != NL80211_IFTYPE_ADHOC && @@ -379,7 +286,6 @@ static int iwl_rx_scan_complete_notif(struct iwl_priv *priv, queue_work(priv->shrd->workqueue, &priv->bt_traffic_change_work); } - return 0; } void iwl_setup_rx_scan_handlers(struct iwl_priv *priv) @@ -393,8 +299,9 @@ void iwl_setup_rx_scan_handlers(struct iwl_priv *priv) iwl_rx_scan_complete_notif; } -static u16 iwl_get_active_dwell_time(struct iwl_priv *priv, - enum ieee80211_band band, u8 n_probes) +inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv, + enum ieee80211_band band, + u8 n_probes) { if (band == IEEE80211_BAND_5GHZ) return IWL_ACTIVE_DWELL_TIME_52 + @@ -404,481 +311,35 @@ static u16 iwl_get_active_dwell_time(struct iwl_priv *priv, IWL_ACTIVE_DWELL_FACTOR_24GHZ * (n_probes + 1); } -static u16 iwl_limit_dwell(struct iwl_priv *priv, u16 dwell_time) +u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, + enum ieee80211_band band, + struct ieee80211_vif *vif) { struct iwl_rxon_context *ctx; - - /* - * If we're associated, we clamp the dwell time 98% - * of the smallest beacon interval (minus 2 * channel - * tune time) - */ - for_each_context(priv, ctx) { - u16 value; - - if (!iwl_is_associated_ctx(ctx)) - continue; - value = ctx->beacon_int; - if (!value) - value = IWL_PASSIVE_DWELL_BASE; - value = (value * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2; - dwell_time = min(value, dwell_time); - } - - return dwell_time; -} - -static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, - enum ieee80211_band band) -{ u16 passive = (band == IEEE80211_BAND_2GHZ) ? IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 : IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52; - return iwl_limit_dwell(priv, passive); -} - -static int iwl_get_single_channel_for_scan(struct iwl_priv *priv, - struct ieee80211_vif *vif, - enum ieee80211_band band, - struct iwl_scan_channel *scan_ch) -{ - const struct ieee80211_supported_band *sband; - u16 passive_dwell = 0; - u16 active_dwell = 0; - int added = 0; - u16 channel = 0; - - sband = iwl_get_hw_mode(priv, band); - if (!sband) { - IWL_ERR(priv, "invalid band\n"); - return added; - } - - active_dwell = iwl_get_active_dwell_time(priv, band, 0); - passive_dwell = iwl_get_passive_dwell_time(priv, band); - - if (passive_dwell <= active_dwell) - passive_dwell = active_dwell + 1; - - channel = iwl_get_single_channel_number(priv, band); - if (channel) { - scan_ch->channel = cpu_to_le16(channel); - scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; - scan_ch->active_dwell = cpu_to_le16(active_dwell); - scan_ch->passive_dwell = cpu_to_le16(passive_dwell); - /* Set txpower levels to defaults */ - scan_ch->dsp_atten = 110; - if (band == IEEE80211_BAND_5GHZ) - scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; - else - scan_ch->tx_gain = ((1 << 5) | (5 << 3)); - added++; - } else - IWL_ERR(priv, "no valid channel found\n"); - return added; -} - -static int iwl_get_channels_for_scan(struct iwl_priv *priv, - struct ieee80211_vif *vif, - enum ieee80211_band band, - u8 is_active, u8 n_probes, - struct iwl_scan_channel *scan_ch) -{ - struct ieee80211_channel *chan; - const struct ieee80211_supported_band *sband; - const struct iwl_channel_info *ch_info; - u16 passive_dwell = 0; - u16 active_dwell = 0; - int added, i; - u16 channel; - - sband = iwl_get_hw_mode(priv, band); - if (!sband) - return 0; - - active_dwell = iwl_get_active_dwell_time(priv, band, n_probes); - passive_dwell = iwl_get_passive_dwell_time(priv, band); - - if (passive_dwell <= active_dwell) - passive_dwell = active_dwell + 1; - - for (i = 0, added = 0; i < priv->scan_request->n_channels; i++) { - chan = priv->scan_request->channels[i]; - - if (chan->band != band) - continue; - - channel = chan->hw_value; - scan_ch->channel = cpu_to_le16(channel); - - ch_info = iwl_get_channel_info(priv, band, channel); - if (!is_channel_valid(ch_info)) { - IWL_DEBUG_SCAN(priv, - "Channel %d is INVALID for this band.\n", - channel); - continue; - } - - if (!is_active || is_channel_passive(ch_info) || - (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)) - scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; - else - scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE; - - if (n_probes) - scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes); - - scan_ch->active_dwell = cpu_to_le16(active_dwell); - scan_ch->passive_dwell = cpu_to_le16(passive_dwell); - - /* Set txpower levels to defaults */ - scan_ch->dsp_atten = 110; - - /* NOTE: if we were doing 6Mb OFDM for scans we'd use - * power level: - * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3; - */ - if (band == IEEE80211_BAND_5GHZ) - scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; - else - scan_ch->tx_gain = ((1 << 5) | (5 << 3)); - - IWL_DEBUG_SCAN(priv, "Scanning ch=%d prob=0x%X [%s %d]\n", - channel, le32_to_cpu(scan_ch->type), - (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ? - "ACTIVE" : "PASSIVE", - (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ? - active_dwell : passive_dwell); - - scan_ch++; - added++; - } - - IWL_DEBUG_SCAN(priv, "total channels to scan %d\n", added); - return added; -} - -static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) -{ - struct iwl_host_cmd cmd = { - .id = REPLY_SCAN_CMD, - .len = { sizeof(struct iwl_scan_cmd), }, - .flags = CMD_SYNC, - }; - struct iwl_scan_cmd *scan; - struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; - u32 rate_flags = 0; - u16 cmd_len; - u16 rx_chain = 0; - enum ieee80211_band band; - u8 n_probes = 0; - u8 rx_ant = hw_params(priv).valid_rx_ant; - u8 rate; - bool is_active = false; - int chan_mod; - u8 active_chains; - u8 scan_tx_antennas = hw_params(priv).valid_tx_ant; - int ret; - - lockdep_assert_held(&priv->shrd->mutex); - - if (vif) - ctx = iwl_rxon_ctx_from_vif(vif); - - if (!priv->scan_cmd) { - priv->scan_cmd = kmalloc(sizeof(struct iwl_scan_cmd) + - IWL_MAX_SCAN_SIZE, GFP_KERNEL); - if (!priv->scan_cmd) { - IWL_DEBUG_SCAN(priv, - "fail to allocate memory for scan\n"); - return -ENOMEM; - } - } - scan = priv->scan_cmd; - memset(scan, 0, sizeof(struct iwl_scan_cmd) + IWL_MAX_SCAN_SIZE); - - scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH; - scan->quiet_time = IWL_ACTIVE_QUIET_TIME; - - if (priv->scan_type != IWL_SCAN_ROC && - iwl_is_any_associated(priv)) { - u16 interval = 0; - u32 extra; - u32 suspend_time = 100; - u32 scan_suspend_time = 100; - - IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); - switch (priv->scan_type) { - case IWL_SCAN_ROC: - WARN_ON(1); - break; - case IWL_SCAN_RADIO_RESET: - interval = 0; - break; - case IWL_SCAN_NORMAL: - interval = vif->bss_conf.beacon_int; - break; - } - - scan->suspend_time = 0; - scan->max_out_time = cpu_to_le32(200 * 1024); - if (!interval) - interval = suspend_time; - - extra = (suspend_time / interval) << 22; - scan_suspend_time = (extra | - ((suspend_time % interval) * 1024)); - scan->suspend_time = cpu_to_le32(scan_suspend_time); - IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n", - scan_suspend_time, interval); - } else if (priv->scan_type == IWL_SCAN_ROC) { - scan->suspend_time = 0; - scan->max_out_time = 0; - scan->quiet_time = 0; - scan->quiet_plcp_th = 0; - } - - switch (priv->scan_type) { - case IWL_SCAN_RADIO_RESET: - IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n"); - break; - case IWL_SCAN_NORMAL: - if (priv->scan_request->n_ssids) { - int i, p = 0; - IWL_DEBUG_SCAN(priv, "Kicking off active scan\n"); - for (i = 0; i < priv->scan_request->n_ssids; i++) { - /* always does wildcard anyway */ - if (!priv->scan_request->ssids[i].ssid_len) - continue; - scan->direct_scan[p].id = WLAN_EID_SSID; - scan->direct_scan[p].len = - priv->scan_request->ssids[i].ssid_len; - memcpy(scan->direct_scan[p].ssid, - priv->scan_request->ssids[i].ssid, - priv->scan_request->ssids[i].ssid_len); - n_probes++; - p++; - } - is_active = true; - } else - IWL_DEBUG_SCAN(priv, "Start passive scan.\n"); - break; - case IWL_SCAN_ROC: - IWL_DEBUG_SCAN(priv, "Start ROC scan.\n"); - break; - } - - scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; - scan->tx_cmd.sta_id = ctx->bcast_sta_id; - scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; - - switch (priv->scan_band) { - case IEEE80211_BAND_2GHZ: - scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK; - chan_mod = le32_to_cpu( - priv->contexts[IWL_RXON_CTX_BSS].active.flags & - RXON_FLG_CHANNEL_MODE_MSK) - >> RXON_FLG_CHANNEL_MODE_POS; - if (chan_mod == CHANNEL_MODE_PURE_40) { - rate = IWL_RATE_6M_PLCP; - } else { - rate = IWL_RATE_1M_PLCP; - rate_flags = RATE_MCS_CCK_MSK; - } + if (iwl_is_any_associated(priv)) { /* - * Internal scans are passive, so we can indiscriminately set - * the BT ignore flag on 2.4 GHz since it applies to TX only. + * If we're associated, we clamp the maximum passive + * dwell time to be 98% of the smallest beacon interval + * (minus 2 * channel tune time) */ - if (priv->cfg->bt_params && - priv->cfg->bt_params->advanced_bt_coexist) - scan->tx_cmd.tx_flags |= TX_CMD_FLG_IGNORE_BT; - break; - case IEEE80211_BAND_5GHZ: - rate = IWL_RATE_6M_PLCP; - break; - default: - IWL_WARN(priv, "Invalid scan band\n"); - return -EIO; - } - - /* - * If active scanning is requested but a certain channel is - * marked passive, we can do active scanning if we detect - * transmissions. - * - * There is an issue with some firmware versions that triggers - * a sysassert on a "good CRC threshold" of zero (== disabled), - * on a radar channel even though this means that we should NOT - * send probes. - * - * The "good CRC threshold" is the number of frames that we - * need to receive during our dwell time on a channel before - * sending out probes -- setting this to a huge value will - * mean we never reach it, but at the same time work around - * the aforementioned issue. Thus use IWL_GOOD_CRC_TH_NEVER - * here instead of IWL_GOOD_CRC_TH_DISABLED. - * - * This was fixed in later versions along with some other - * scan changes, and the threshold behaves as a flag in those - * versions. - */ - if (priv->new_scan_threshold_behaviour) - scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT : - IWL_GOOD_CRC_TH_DISABLED; - else - scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT : - IWL_GOOD_CRC_TH_NEVER; - - band = priv->scan_band; - - if (priv->cfg->scan_rx_antennas[band]) - rx_ant = priv->cfg->scan_rx_antennas[band]; - - if (band == IEEE80211_BAND_2GHZ && - priv->cfg->bt_params && - priv->cfg->bt_params->advanced_bt_coexist) { - /* transmit 2.4 GHz probes only on first antenna */ - scan_tx_antennas = first_antenna(scan_tx_antennas); - } - - priv->scan_tx_ant[band] = iwl_toggle_tx_ant(priv, - priv->scan_tx_ant[band], - scan_tx_antennas); - rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]); - scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags); - - /* In power save mode use one chain, otherwise use all chains */ - if (test_bit(STATUS_POWER_PMI, &priv->shrd->status)) { - /* rx_ant has been set to all valid chains previously */ - active_chains = rx_ant & - ((u8)(priv->chain_noise_data.active_chains)); - if (!active_chains) - active_chains = rx_ant; - - IWL_DEBUG_SCAN(priv, "chain_noise_data.active_chains: %u\n", - priv->chain_noise_data.active_chains); - - rx_ant = first_antenna(active_chains); - } - if (priv->cfg->bt_params && - priv->cfg->bt_params->advanced_bt_coexist && - priv->bt_full_concurrent) { - /* operated as 1x1 in full concurrency mode */ - rx_ant = first_antenna(rx_ant); - } - - /* MIMO is not used here, but value is required */ - rx_chain |= - hw_params(priv).valid_rx_ant << RXON_RX_CHAIN_VALID_POS; - rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; - rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS; - rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; - scan->rx_chain = cpu_to_le16(rx_chain); - switch (priv->scan_type) { - case IWL_SCAN_NORMAL: - cmd_len = iwl_fill_probe_req(priv, - (struct ieee80211_mgmt *)scan->data, - vif->addr, - priv->scan_request->ie, - priv->scan_request->ie_len, - IWL_MAX_SCAN_SIZE - sizeof(*scan)); - break; - case IWL_SCAN_RADIO_RESET: - case IWL_SCAN_ROC: - /* use bcast addr, will not be transmitted but must be valid */ - cmd_len = iwl_fill_probe_req(priv, - (struct ieee80211_mgmt *)scan->data, - iwl_bcast_addr, NULL, 0, - IWL_MAX_SCAN_SIZE - sizeof(*scan)); - break; - default: - BUG(); - } - scan->tx_cmd.len = cpu_to_le16(cmd_len); - - scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK | - RXON_FILTER_BCON_AWARE_MSK); - - switch (priv->scan_type) { - case IWL_SCAN_RADIO_RESET: - scan->channel_count = - iwl_get_single_channel_for_scan(priv, vif, band, - (void *)&scan->data[cmd_len]); - break; - case IWL_SCAN_NORMAL: - scan->channel_count = - iwl_get_channels_for_scan(priv, vif, band, - is_active, n_probes, - (void *)&scan->data[cmd_len]); - break; - case IWL_SCAN_ROC: { - struct iwl_scan_channel *scan_ch; - int n_chan, i; - u16 dwell; - - dwell = iwl_limit_dwell(priv, priv->hw_roc_duration); - n_chan = DIV_ROUND_UP(priv->hw_roc_duration, dwell); - - scan->channel_count = n_chan; - - scan_ch = (void *)&scan->data[cmd_len]; - - for (i = 0; i < n_chan; i++) { - scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; - scan_ch->channel = - cpu_to_le16(priv->hw_roc_channel->hw_value); - - if (i == n_chan - 1) - dwell = priv->hw_roc_duration - i * dwell; - - scan_ch->active_dwell = - scan_ch->passive_dwell = cpu_to_le16(dwell); - - /* Set txpower levels to defaults */ - scan_ch->dsp_atten = 110; - - /* NOTE: if we were doing 6Mb OFDM for scans we'd use - * power level: - * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3; - */ - if (priv->hw_roc_channel->band == IEEE80211_BAND_5GHZ) - scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; - else - scan_ch->tx_gain = ((1 << 5) | (5 << 3)); - - scan_ch++; - } + for_each_context(priv, ctx) { + u16 value; + + if (!iwl_is_associated_ctx(ctx)) + continue; + value = ctx->vif ? ctx->vif->bss_conf.beacon_int : 0; + if ((value > IWL_PASSIVE_DWELL_BASE) || !value) + value = IWL_PASSIVE_DWELL_BASE; + value = (value * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2; + passive = min(value, passive); } - - break; - } - - if (scan->channel_count == 0) { - IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count); - return -EIO; - } - - cmd.len[0] += le16_to_cpu(scan->tx_cmd.len) + - scan->channel_count * sizeof(struct iwl_scan_channel); - cmd.data[0] = scan; - cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY; - scan->len = cpu_to_le16(cmd.len[0]); - - /* set scan bit here for PAN params */ - set_bit(STATUS_SCAN_HW, &priv->shrd->status); - - ret = iwlagn_set_pan_params(priv); - if (ret) - return ret; - - ret = iwl_trans_send_cmd(trans(priv), &cmd); - if (ret) { - clear_bit(STATUS_SCAN_HW, &priv->shrd->status); - iwlagn_set_pan_params(priv); } - return ret; + return passive; } void iwl_init_scan_params(struct iwl_priv *priv) @@ -954,33 +415,31 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, mutex_lock(&priv->shrd->mutex); + if (test_bit(STATUS_SCANNING, &priv->shrd->status) && + priv->scan_type != IWL_SCAN_NORMAL) { + IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); + ret = -EAGAIN; + goto out_unlock; + } + + /* mac80211 will only ask for one band at a time */ + priv->scan_request = req; + priv->scan_vif = vif; + /* * If an internal scan is in progress, just set * up the scan_request as per above. */ if (priv->scan_type != IWL_SCAN_NORMAL) { - IWL_DEBUG_SCAN(priv, - "SCAN request during internal scan - defer\n"); - priv->scan_request = req; - priv->scan_vif = vif; + IWL_DEBUG_SCAN(priv, "SCAN request during internal scan\n"); ret = 0; - } else { - priv->scan_request = req; - priv->scan_vif = vif; - /* - * mac80211 will only ask for one band at a time - * so using channels[0] here is ok - */ + } else ret = iwl_scan_initiate(priv, vif, IWL_SCAN_NORMAL, req->channels[0]->band); - if (ret) { - priv->scan_request = NULL; - priv->scan_vif = NULL; - } - } IWL_DEBUG_MAC80211(priv, "leave\n"); +out_unlock: mutex_unlock(&priv->shrd->mutex); return ret; @@ -1098,10 +557,61 @@ static void iwl_bg_abort_scan(struct work_struct *work) static void iwl_bg_scan_completed(struct work_struct *work) { struct iwl_priv *priv = - container_of(work, struct iwl_priv, scan_completed); + container_of(work, struct iwl_priv, scan_completed); + bool aborted; + + IWL_DEBUG_SCAN(priv, "Completed scan.\n"); + + cancel_delayed_work(&priv->scan_check); mutex_lock(&priv->shrd->mutex); - iwl_process_scan_complete(priv); + + aborted = test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->shrd->status); + if (aborted) + IWL_DEBUG_SCAN(priv, "Aborted scan completed.\n"); + + if (!test_and_clear_bit(STATUS_SCANNING, &priv->shrd->status)) { + IWL_DEBUG_SCAN(priv, "Scan already completed.\n"); + goto out_settings; + } + + if (priv->scan_type == IWL_SCAN_ROC) { + ieee80211_remain_on_channel_expired(priv->hw); + priv->hw_roc_channel = NULL; + schedule_delayed_work(&priv->hw_roc_disable_work, 10 * HZ); + } + + if (priv->scan_type != IWL_SCAN_NORMAL && !aborted) { + int err; + + /* Check if mac80211 requested scan during our internal scan */ + if (priv->scan_request == NULL) + goto out_complete; + + /* If so request a new scan */ + err = iwl_scan_initiate(priv, priv->scan_vif, IWL_SCAN_NORMAL, + priv->scan_request->channels[0]->band); + if (err) { + IWL_DEBUG_SCAN(priv, + "failed to initiate pending scan: %d\n", err); + aborted = true; + goto out_complete; + } + + goto out; + } + +out_complete: + iwl_complete_scan(priv, aborted); + +out_settings: + /* Can we still talk to firmware ? */ + if (!iwl_is_ready_rf(priv->shrd)) + goto out; + + iwlagn_post_scan(priv); + +out: mutex_unlock(&priv->shrd->mutex); } diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-shared.h b/trunk/drivers/net/wireless/iwlwifi/iwl-shared.h index 3a24b477b8fb..40186a61f20a 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -100,7 +100,7 @@ struct iwl_priv; struct iwl_sensitivity_ranges; struct iwl_trans_ops; -#define DRV_NAME "iwlwifi" +#define DRV_NAME "iwlagn" #define IWLWIFI_VERSION "in-tree:" #define DRV_COPYRIGHT "Copyright(c) 2003-2011 Intel Corporation" #define DRV_AUTHOR "" @@ -423,11 +423,8 @@ enum iwl_rxon_context_id { int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, struct iwl_cfg *cfg); void __devexit iwl_remove(struct iwl_priv * priv); -struct iwl_device_cmd; -int __must_check iwl_rx_dispatch(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, - struct iwl_device_cmd *cmd); +void iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); int iwlagn_hw_valid_rtc_data_addr(u32 addr); void iwl_start_tx_ba_trans_ready(struct iwl_priv *priv, enum iwl_rxon_context_id ctx, @@ -489,7 +486,6 @@ static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv, #define STATUS_FW_ERROR 17 #define STATUS_DEVICE_ENABLED 18 #define STATUS_CHANNEL_SWITCH_PENDING 19 -#define STATUS_SCAN_COMPLETE 20 static inline int iwl_is_ready(struct iwl_shared *shrd) { diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-sta.c b/trunk/drivers/net/wireless/iwlwifi/iwl-sta.c index 580a4d702ff3..e24135e7d37d 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -59,7 +59,8 @@ static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) static int iwl_process_add_sta_resp(struct iwl_priv *priv, struct iwl_addsta_cmd *addsta, - struct iwl_rx_packet *pkt) + struct iwl_rx_packet *pkt, + bool sync) { u8 sta_id = addsta->sta.sta_id; unsigned long flags; @@ -122,14 +123,15 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv, return ret; } -int iwl_add_sta_callback(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, - struct iwl_device_cmd *cmd) +static void iwl_add_sta_callback(struct iwl_shared *shrd, + struct iwl_device_cmd *cmd, + struct iwl_rx_packet *pkt) { - struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_addsta_cmd *addsta = - (struct iwl_addsta_cmd *) cmd->payload; + (struct iwl_addsta_cmd *)cmd->cmd.payload; + + iwl_process_add_sta_resp(shrd->priv, addsta, pkt, false); - return iwl_process_add_sta_resp(priv, addsta, pkt); } static u16 iwlagn_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) @@ -145,6 +147,7 @@ static u16 iwlagn_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) int iwl_send_add_sta(struct iwl_priv *priv, struct iwl_addsta_cmd *sta, u8 flags) { + struct iwl_rx_packet *pkt = NULL; int ret = 0; u8 data[sizeof(*sta)]; struct iwl_host_cmd cmd = { @@ -157,7 +160,9 @@ int iwl_send_add_sta(struct iwl_priv *priv, IWL_DEBUG_INFO(priv, "Adding sta %u (%pM) %ssynchronously\n", sta_id, sta->sta.addr, flags & CMD_ASYNC ? "a" : ""); - if (!(flags & CMD_ASYNC)) { + if (flags & CMD_ASYNC) + cmd.callback = iwl_add_sta_callback; + else { cmd.flags |= CMD_WANT_SKB; might_sleep(); } @@ -167,16 +172,14 @@ int iwl_send_add_sta(struct iwl_priv *priv, if (ret || (flags & CMD_ASYNC)) return ret; - /*else the command was successfully sent in SYNC mode, need to free - * the reply page */ + if (ret == 0) { + pkt = (struct iwl_rx_packet *)cmd.reply_page; + ret = iwl_process_add_sta_resp(priv, sta, pkt, true); + } iwl_free_pages(priv->shrd, cmd.reply_page); - if (cmd.handler_status) - IWL_ERR(priv, "%s - error in the CMD response %d", __func__, - cmd.handler_status); - - return cmd.handler_status; + return ret; } static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, @@ -302,7 +305,7 @@ u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, station->ctxid = ctx->ctxid; if (sta) { - struct iwl_station_priv *sta_priv; + struct iwl_station_priv_common *sta_priv; sta_priv = (void *)sta->drv_priv; sta_priv->ctx = ctx; @@ -818,7 +821,7 @@ int iwl_mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_sta *sta) { struct iwl_priv *priv = hw->priv; - struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; + struct iwl_station_priv_common *sta_common = (void *)sta->drv_priv; int ret; IWL_DEBUG_INFO(priv, "received request to remove station %pM\n", @@ -826,7 +829,7 @@ int iwl_mac_sta_remove(struct ieee80211_hw *hw, mutex_lock(&priv->shrd->mutex); IWL_DEBUG_INFO(priv, "proceeding to remove station %pM\n", sta->addr); - ret = iwl_remove_station(priv, sta_priv->sta_id, sta->addr); + ret = iwl_remove_station(priv, sta_common->sta_id, sta->addr); if (ret) IWL_ERR(priv, "Error removing station %pM\n", sta->addr); diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-sta.h b/trunk/drivers/net/wireless/iwlwifi/iwl-sta.h index 1bca0dabde8d..9641eb6b1d0a 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -61,9 +61,6 @@ u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx, struct iwl_link_quality_cmd *lq, u8 flags, bool init); void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx); -int iwl_add_sta_callback(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, - struct iwl_device_cmd *cmd); - /** * iwl_clear_driver_stations - clear knowledge of all stations from driver @@ -105,7 +102,7 @@ static inline int iwl_sta_id(struct ieee80211_sta *sta) if (WARN_ON(!sta)) return IWL_INVALID_STATION; - return ((struct iwl_station_priv *)sta->drv_priv)->sta_id; + return ((struct iwl_station_priv_common *)sta->drv_priv)->sta_id; } /** diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h b/trunk/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h index 2b6756e8b8f9..49cd5a768280 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h @@ -118,6 +118,16 @@ struct iwl_dma_ptr { struct iwl_cmd_meta { /* only for SYNC commands, iff the reply skb is wanted */ struct iwl_host_cmd *source; + /* + * only for ASYNC commands + * (which is somewhat stupid -- look at iwl-sta.c for instance + * which duplicates a bunch of code because the callback isn't + * invoked for SYNC commands, if it were and its result passed + * through it would be simpler...) + */ + void (*callback)(struct iwl_shared *shrd, + struct iwl_device_cmd *cmd, + struct iwl_rx_packet *pkt); u32 flags; @@ -275,8 +285,10 @@ int iwlagn_txq_attach_buf_to_tfd(struct iwl_trans *trans, dma_addr_t addr, u16 len, u8 reset); int iwl_queue_init(struct iwl_queue *q, int count, int slots_num, u32 id); int iwl_trans_pcie_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd); +int __must_check iwl_trans_pcie_send_cmd_pdu(struct iwl_trans *trans, u8 id, + u32 flags, u16 len, const void *data); void iwl_tx_cmd_complete(struct iwl_trans *trans, - struct iwl_rx_mem_buffer *rxb, int handler_status); + struct iwl_rx_mem_buffer *rxb); void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans, struct iwl_tx_queue *txq, u16 byte_cnt); diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/trunk/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c index b4eff556cd0a..6f3f07dd817d 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c @@ -372,15 +372,12 @@ static void iwl_rx_handle(struct iwl_trans *trans) struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_rx_queue *rxq = &trans_pcie->rxq; - struct iwl_tx_queue *txq = &trans_pcie->txq[trans->shrd->cmd_queue]; - struct iwl_device_cmd *cmd; u32 r, i; int reclaim; unsigned long flags; u8 fill_rx = 0; u32 count = 8; int total_empty; - int index, cmd_index; /* uCode's read index (stored in shared DRAM) indicates the last Rx * buffer that the driver may process (last buffer filled by ucode). */ @@ -400,8 +397,8 @@ static void iwl_rx_handle(struct iwl_trans *trans) fill_rx = 1; while (i != r) { - int len, err; - u16 sequence; + int len; + u16 txq_id, sequence; rxb = rxq->queue[i]; @@ -442,26 +439,17 @@ static void iwl_rx_handle(struct iwl_trans *trans) (pkt->hdr.cmd != REPLY_TX); sequence = le16_to_cpu(pkt->hdr.sequence); - index = SEQ_TO_INDEX(sequence); - cmd_index = get_cmd_index(&txq->q, index); - - if (reclaim) - cmd = txq->cmd[cmd_index]; - else - cmd = NULL; + txq_id = SEQ_TO_QUEUE(le16_to_cpu(pkt->hdr.sequence)); /* warn if this is cmd response / notification and the uCode * didn't set the SEQ_RX_FRAME for a frame that is - * uCode-originated - * If you saw this code after the second half of 2012, then - * please remove it - */ - WARN(pkt->hdr.cmd != REPLY_TX && reclaim == false && + * uCode-originated*/ + WARN(txq_id == trans->shrd->cmd_queue && reclaim == false && (!(pkt->hdr.sequence & SEQ_RX_FRAME)), "reclaim is false, SEQ_RX_FRAME unset: %s\n", get_cmd_string(pkt->hdr.cmd)); - err = iwl_rx_dispatch(priv(trans), rxb, cmd); + iwl_rx_dispatch(priv(trans), rxb); /* * XXX: After here, we should always check rxb->page @@ -476,7 +464,7 @@ static void iwl_rx_handle(struct iwl_trans *trans) * iwl_trans_send_cmd() * as we reclaim the driver command queue */ if (rxb->page) - iwl_tx_cmd_complete(trans, rxb, err); + iwl_tx_cmd_complete(trans, rxb); else IWL_WARN(trans, "Claim null rxb?\n"); } diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c b/trunk/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c index ee7059dcbbcb..031a291a13dc 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c @@ -59,15 +59,13 @@ void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans, u8 sta_id = 0; u16 len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE; __le16 bc_ent; - struct iwl_tx_cmd *tx_cmd = - (struct iwl_tx_cmd *) txq->cmd[txq->q.write_ptr]->payload; scd_bc_tbl = trans_pcie->scd_bc_tbls.addr; WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX); - sta_id = tx_cmd->sta_id; - sec_ctl = tx_cmd->sec_ctl; + sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id; + sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl; switch (sec_ctl & TX_CMD_SEC_MSK) { case TX_CMD_SEC_CCM: @@ -355,13 +353,11 @@ static void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_trans *trans, int read_ptr = txq->q.read_ptr; u8 sta_id = 0; __le16 bc_ent; - struct iwl_tx_cmd *tx_cmd = - (struct iwl_tx_cmd *) txq->cmd[txq->q.read_ptr]->payload; WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX); if (txq_id != trans->shrd->cmd_queue) - sta_id = tx_cmd->sta_id; + sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id; bc_ent = cpu_to_le16(1 | (sta_id << 12)); scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent; @@ -766,6 +762,8 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) memset(out_meta, 0, sizeof(*out_meta)); /* re-initialize to NULL */ if (cmd->flags & CMD_WANT_SKB) out_meta->source = cmd; + if (cmd->flags & CMD_ASYNC) + out_meta->callback = cmd->callback; /* set up the header */ @@ -777,7 +775,7 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) /* and copy the data that needs to be copied */ - cmd_dest = out_cmd->payload; + cmd_dest = &out_cmd->cmd.payload[0]; for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { if (!cmd->len[i]) continue; @@ -896,15 +894,12 @@ static void iwl_hcmd_queue_reclaim(struct iwl_trans *trans, int txq_id, /** * iwl_tx_cmd_complete - Pull unused buffers off the queue and reclaim them * @rxb: Rx buffer to reclaim - * @handler_status: return value of the handler of the command - * (put in setup_rx_handlers) * * If an Rx buffer has an async callback associated with it the callback * will be executed. The attached skb (if present) will only be freed * if the callback returns 1 */ -void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_mem_buffer *rxb, - int handler_status) +void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = rxb_addr(rxb); u16 sequence = le16_to_cpu(pkt->hdr.sequence); @@ -941,9 +936,9 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_mem_buffer *rxb, /* Input error checking is done when commands are added to queue. */ if (meta->flags & CMD_WANT_SKB) { meta->source->reply_page = (unsigned long)rxb_addr(rxb); - meta->source->handler_status = handler_status; rxb->page = NULL; - } + } else if (meta->callback) + meta->callback(trans->shrd, cmd, pkt); spin_lock_irqsave(&trans->hcmd_lock, flags); @@ -963,6 +958,30 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_mem_buffer *rxb, #define HOST_COMPLETE_TIMEOUT (2 * HZ) +static void iwl_generic_cmd_callback(struct iwl_shared *shrd, + struct iwl_device_cmd *cmd, + struct iwl_rx_packet *pkt) +{ + if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { + IWL_ERR(shrd->trans, "Bad return from %s (0x%08X)\n", + get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags); + return; + } + +#ifdef CONFIG_IWLWIFI_DEBUG + switch (cmd->hdr.cmd) { + case REPLY_TX_LINK_QUALITY_CMD: + case SENSITIVITY_CMD: + IWL_DEBUG_HC_DUMP(shrd->trans, "back from %s (0x%08X)\n", + get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags); + break; + default: + IWL_DEBUG_HC(shrd->trans, "back from %s (0x%08X)\n", + get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags); + } +#endif +} + static int iwl_send_cmd_async(struct iwl_trans *trans, struct iwl_host_cmd *cmd) { int ret; @@ -971,6 +990,9 @@ static int iwl_send_cmd_async(struct iwl_trans *trans, struct iwl_host_cmd *cmd) if (WARN_ON(cmd->flags & CMD_WANT_SKB)) return -EINVAL; + /* Assign a generic callback if one is not provided */ + if (!cmd->callback) + cmd->callback = iwl_generic_cmd_callback; if (test_bit(STATUS_EXIT_PENDING, &trans->shrd->status)) return -EBUSY; @@ -992,6 +1014,10 @@ static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd) lockdep_assert_held(&trans->shrd->mutex); + /* A synchronous command can not have a callback set. */ + if (WARN_ON(cmd->callback)) + return -EINVAL; + IWL_DEBUG_INFO(trans, "Attempting to send sync command %s\n", get_cmd_string(cmd->id)); diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/trunk/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index 416e9920e4d9..ca13eebbdb4f 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -83,6 +83,8 @@ static int iwl_trans_rx_alloc(struct iwl_trans *trans) memset(&trans_pcie->rxq, 0, sizeof(trans_pcie->rxq)); spin_lock_init(&rxq->lock); + INIT_LIST_HEAD(&rxq->rx_free); + INIT_LIST_HEAD(&rxq->rx_used); if (WARN_ON(rxq->bd || rxq->rb_stts)) return -EINVAL; @@ -304,8 +306,8 @@ static int iwl_trans_txq_alloc(struct iwl_trans *trans, txq->q.n_window = slots_num; - txq->meta = kcalloc(slots_num, sizeof(txq->meta[0]), GFP_KERNEL); - txq->cmd = kcalloc(slots_num, sizeof(txq->cmd[0]), GFP_KERNEL); + txq->meta = kzalloc(sizeof(txq->meta[0]) * slots_num, GFP_KERNEL); + txq->cmd = kzalloc(sizeof(txq->cmd[0]) * slots_num, GFP_KERNEL); if (!txq->meta || !txq->cmd) goto error; @@ -322,8 +324,8 @@ static int iwl_trans_txq_alloc(struct iwl_trans *trans, /* Driver private data, only for Tx (not command) queues, * not shared with device. */ if (txq_id != trans->shrd->cmd_queue) { - txq->skbs = kcalloc(TFD_QUEUE_SIZE_MAX, sizeof(txq->skbs[0]), - GFP_KERNEL); + txq->skbs = kzalloc(sizeof(txq->skbs[0]) * + TFD_QUEUE_SIZE_MAX, GFP_KERNEL); if (!txq->skbs) { IWL_ERR(trans, "kmalloc for auxiliary BD " "structures failed\n"); @@ -534,8 +536,8 @@ static int iwl_trans_tx_alloc(struct iwl_trans *trans) goto error; } - trans_pcie->txq = kcalloc(hw_params(trans).max_txq_num, - sizeof(struct iwl_tx_queue), GFP_KERNEL); + trans_pcie->txq = kzalloc(sizeof(struct iwl_tx_queue) * + hw_params(trans).max_txq_num, GFP_KERNEL); if (!trans_pcie->txq) { IWL_ERR(trans, "Not enough memory for txq\n"); ret = ENOMEM; @@ -1041,7 +1043,7 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct iwl_tx_cmd *tx_cmd = (struct iwl_tx_cmd *) dev_cmd->payload; + struct iwl_tx_cmd *tx_cmd = &dev_cmd->cmd.tx; struct iwl_cmd_meta *out_meta; struct iwl_tx_queue *txq; struct iwl_queue *q; @@ -1094,16 +1096,13 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, hdr->seq_ctrl |= cpu_to_le16(seq_number); seq_number += 0x10; /* aggregation is on for this */ - if (info->flags & IEEE80211_TX_CTL_AMPDU) { - WARN_ON(tid_data->agg.state != IWL_AGG_ON); + if (info->flags & IEEE80211_TX_CTL_AMPDU && + tid_data->agg.state == IWL_AGG_ON) { txq_id = tid_data->agg.txq_id; is_agg = true; } } - /* Copy MAC header from skb into command buffer */ - memcpy(tx_cmd->hdr, hdr, hdr_len); - txq = &trans_pcie->txq[txq_id]; q = &txq->q; diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-trans.h b/trunk/drivers/net/wireless/iwlwifi/iwl-trans.h index c5923125c3f9..5b6e6842d5fc 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -97,7 +97,15 @@ enum { */ struct iwl_device_cmd { struct iwl_cmd_header hdr; /* uCode API */ - u8 payload[DEF_CMD_PAYLOAD_SIZE]; + union { + u32 flags; + u8 val8; + u16 val16; + u32 val32; + struct iwl_tx_cmd tx; + struct iwl6000_channel_switch_cmd chswitch; + u8 payload[DEF_CMD_PAYLOAD_SIZE]; + } __packed cmd; } __packed; #define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_device_cmd)) @@ -112,8 +120,6 @@ enum iwl_hcmd_dataflag { * struct iwl_host_cmd - Host command to the uCode * @data: array of chunks that composes the data of the host command * @reply_page: pointer to the page that holds the response to the host command - * @handler_status: return value of the handler of the command - * (put in setup_rx_handlers) - valid for SYNC mode only * @callback: * @flags: can be CMD_* note CMD_WANT_SKB is incompatible withe CMD_ASYNC * @len: array of the lenths of the chunks in data @@ -123,8 +129,9 @@ enum iwl_hcmd_dataflag { struct iwl_host_cmd { const void *data[IWL_MAX_CMD_TFDS]; unsigned long reply_page; - int handler_status; - + void (*callback)(struct iwl_shared *shrd, + struct iwl_device_cmd *cmd, + struct iwl_rx_packet *pkt); u32 flags; u16 len[IWL_MAX_CMD_TFDS]; u8 dataflags[IWL_MAX_CMD_TFDS]; diff --git a/trunk/drivers/net/wireless/libertas/cfg.c b/trunk/drivers/net/wireless/libertas/cfg.c index 610bfcee3cf6..85b3169c40d7 100644 --- a/trunk/drivers/net/wireless/libertas/cfg.c +++ b/trunk/drivers/net/wireless/libertas/cfg.c @@ -695,7 +695,7 @@ static void lbs_scan_worker(struct work_struct *work) tlv = scan_cmd->tlvbuffer; /* add SSID TLV */ - if (priv->scan_req->n_ssids && priv->scan_req->ssids[0].ssid_len > 0) + if (priv->scan_req->n_ssids) tlv += lbs_add_ssid_tlv(tlv, priv->scan_req->ssids[0].ssid, priv->scan_req->ssids[0].ssid_len); @@ -736,6 +736,7 @@ static void lbs_scan_worker(struct work_struct *work) cfg80211_scan_done(priv->scan_req, false); priv->scan_req = NULL; + priv->last_scan = jiffies; } /* Restart network */ @@ -1301,26 +1302,24 @@ static int lbs_cfg_connect(struct wiphy *wiphy, struct net_device *dev, lbs_deb_enter(LBS_DEB_CFG80211); if (!sme->bssid) { - struct cfg80211_scan_request *creq; - - /* - * Scan for the requested network after waiting for existing - * scans to finish. + /* Run a scan if one isn't in-progress already and if the last + * scan was done more than 2 seconds ago. */ - lbs_deb_assoc("assoc: waiting for existing scans\n"); - wait_event_interruptible_timeout(priv->scan_q, - (priv->scan_req == NULL), - (15 * HZ)); + if (priv->scan_req == NULL && + time_after(jiffies, priv->last_scan + (2 * HZ))) { + struct cfg80211_scan_request *creq; - creq = _new_connect_scan_req(wiphy, sme); - if (!creq) { - ret = -EINVAL; - goto done; - } + creq = _new_connect_scan_req(wiphy, sme); + if (!creq) { + ret = -EINVAL; + goto done; + } - lbs_deb_assoc("assoc: scanning for compatible AP\n"); - _internal_start_scan(priv, true, creq); + lbs_deb_assoc("assoc: scanning for compatible AP\n"); + _internal_start_scan(priv, true, creq); + } + /* Wait for any in-progress scan to complete */ lbs_deb_assoc("assoc: waiting for scan to complete\n"); wait_event_interruptible_timeout(priv->scan_q, (priv->scan_req == NULL), diff --git a/trunk/drivers/net/wireless/libertas/dev.h b/trunk/drivers/net/wireless/libertas/dev.h index f3fd447131c2..b9ff0dc53e8d 100644 --- a/trunk/drivers/net/wireless/libertas/dev.h +++ b/trunk/drivers/net/wireless/libertas/dev.h @@ -158,7 +158,6 @@ struct lbs_private { /* protected by hard_start_xmit serialization */ u8 txretrycount; struct sk_buff *currenttxskb; - struct timer_list tx_lockup_timer; /* Locks */ struct mutex lock; @@ -180,6 +179,7 @@ struct lbs_private { wait_queue_head_t scan_q; /* Whether the scan was initiated internally and not by cfg80211 */ bool internal_scan; + unsigned long last_scan; }; extern struct cmd_confirm_sleep confirm_sleep; diff --git a/trunk/drivers/net/wireless/libertas/main.c b/trunk/drivers/net/wireless/libertas/main.c index 6a326233391f..d62d1fb4177f 100644 --- a/trunk/drivers/net/wireless/libertas/main.c +++ b/trunk/drivers/net/wireless/libertas/main.c @@ -188,7 +188,6 @@ int lbs_stop_iface(struct lbs_private *priv) spin_unlock_irqrestore(&priv->driver_lock, flags); cancel_work_sync(&priv->mcast_work); - del_timer_sync(&priv->tx_lockup_timer); /* Disable command processing, and wait for all commands to complete */ lbs_deb_main("waiting for commands to complete\n"); @@ -244,7 +243,6 @@ void lbs_host_to_card_done(struct lbs_private *priv) lbs_deb_enter(LBS_DEB_THREAD); spin_lock_irqsave(&priv->driver_lock, flags); - del_timer(&priv->tx_lockup_timer); priv->dnld_sent = DNLD_RES_RECEIVED; @@ -587,9 +585,6 @@ static int lbs_thread(void *data) if (ret) { lbs_deb_tx("host_to_card failed %d\n", ret); priv->dnld_sent = DNLD_RES_RECEIVED; - } else { - mod_timer(&priv->tx_lockup_timer, - jiffies + (HZ * 5)); } priv->tx_pending_len = 0; if (!priv->currenttxskb) { @@ -606,7 +601,6 @@ static int lbs_thread(void *data) } del_timer(&priv->command_timer); - del_timer(&priv->tx_lockup_timer); del_timer(&priv->auto_deepsleep_timer); lbs_deb_leave(LBS_DEB_THREAD); @@ -740,32 +734,6 @@ static void lbs_cmd_timeout_handler(unsigned long data) lbs_deb_leave(LBS_DEB_CMD); } -/** - * lbs_tx_lockup_handler - handles the timeout of the passing of TX frames - * to the hardware. This is known to frequently happen with SD8686 when - * waking up after a Wake-on-WLAN-triggered resume. - * - * @data: &struct lbs_private pointer - */ -static void lbs_tx_lockup_handler(unsigned long data) -{ - struct lbs_private *priv = (struct lbs_private *)data; - unsigned long flags; - - lbs_deb_enter(LBS_DEB_TX); - spin_lock_irqsave(&priv->driver_lock, flags); - - netdev_info(priv->dev, "TX lockup detected\n"); - if (priv->reset_card) - priv->reset_card(priv); - - priv->dnld_sent = DNLD_RES_RECEIVED; - wake_up_interruptible(&priv->waitq); - - spin_unlock_irqrestore(&priv->driver_lock, flags); - lbs_deb_leave(LBS_DEB_TX); -} - /** * auto_deepsleep_timer_fn - put the device back to deep sleep mode when * timer expires and no activity (command, event, data etc.) is detected. @@ -852,8 +820,6 @@ static int lbs_init_adapter(struct lbs_private *priv) setup_timer(&priv->command_timer, lbs_cmd_timeout_handler, (unsigned long)priv); - setup_timer(&priv->tx_lockup_timer, lbs_tx_lockup_handler, - (unsigned long)priv); setup_timer(&priv->auto_deepsleep_timer, auto_deepsleep_timer_fn, (unsigned long)priv); @@ -891,7 +857,6 @@ static void lbs_free_adapter(struct lbs_private *priv) lbs_free_cmd_buffer(priv); kfifo_free(&priv->event_fifo); del_timer(&priv->command_timer); - del_timer(&priv->tx_lockup_timer); del_timer(&priv->auto_deepsleep_timer); lbs_deb_leave(LBS_DEB_MAIN); diff --git a/trunk/drivers/net/wireless/mac80211_hwsim.c b/trunk/drivers/net/wireless/mac80211_hwsim.c index 68455a2307cb..34b79fc91e39 100644 --- a/trunk/drivers/net/wireless/mac80211_hwsim.c +++ b/trunk/drivers/net/wireless/mac80211_hwsim.c @@ -970,8 +970,7 @@ static int mac80211_hwsim_set_tim(struct ieee80211_hw *hw, } static int mac80211_hwsim_conf_tx( - struct ieee80211_hw *hw, - struct ieee80211_vif *vif, u16 queue, + struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params) { wiphy_debug(hw->wiphy, diff --git a/trunk/drivers/net/wireless/mwifiex/11n_aggr.c b/trunk/drivers/net/wireless/mwifiex/11n_aggr.c index 9e63d16365e3..1a453a605b3f 100644 --- a/trunk/drivers/net/wireless/mwifiex/11n_aggr.c +++ b/trunk/drivers/net/wireless/mwifiex/11n_aggr.c @@ -193,6 +193,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, skb_src = skb_dequeue(&pra_list->skb_head); pra_list->total_pkts_size -= skb_src->len; + pra_list->total_pkts--; atomic_dec(&priv->wmm.tx_pkts_queued); @@ -268,6 +269,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, skb_queue_tail(&pra_list->skb_head, skb_aggr); pra_list->total_pkts_size += skb_aggr->len; + pra_list->total_pkts++; atomic_inc(&priv->wmm.tx_pkts_queued); diff --git a/trunk/drivers/net/wireless/mwifiex/11n_aggr.h b/trunk/drivers/net/wireless/mwifiex/11n_aggr.h index 900e1c62a0cc..9c6dca7ab02c 100644 --- a/trunk/drivers/net/wireless/mwifiex/11n_aggr.h +++ b/trunk/drivers/net/wireless/mwifiex/11n_aggr.h @@ -21,7 +21,6 @@ #define _MWIFIEX_11N_AGGR_H_ #define PKT_TYPE_AMSDU 0xE6 -#define MIN_NUM_AMSDU 2 int mwifiex_11n_deaggregate_pkt(struct mwifiex_private *priv, struct sk_buff *skb); diff --git a/trunk/drivers/net/wireless/mwifiex/cfg80211.c b/trunk/drivers/net/wireless/mwifiex/cfg80211.c index 462c71067bfb..6fd53e4e3fe6 100644 --- a/trunk/drivers/net/wireless/mwifiex/cfg80211.c +++ b/trunk/drivers/net/wireless/mwifiex/cfg80211.c @@ -543,28 +543,12 @@ mwifiex_dump_station_info(struct mwifiex_private *priv, ret = -EFAULT; } - /* - * Bit 0 in tx_htinfo indicates that current Tx rate is 11n rate. Valid - * MCS index values for us are 0 to 7. - */ - if ((priv->tx_htinfo & BIT(0)) && (priv->tx_rate < 8)) { - sinfo->txrate.mcs = priv->tx_rate; - sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; - /* 40MHz rate */ - if (priv->tx_htinfo & BIT(1)) - sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; - /* SGI enabled */ - if (priv->tx_htinfo & BIT(2)) - sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; - } - sinfo->rx_bytes = priv->stats.rx_bytes; sinfo->tx_bytes = priv->stats.tx_bytes; sinfo->rx_packets = priv->stats.rx_packets; sinfo->tx_packets = priv->stats.tx_packets; sinfo->signal = priv->qual_level; - /* bit rate is in 500 kb/s units. Convert it to 100kb/s units */ - sinfo->txrate.legacy = rate.rate * 5; + sinfo->txrate.legacy = rate.rate; return ret; } @@ -581,6 +565,8 @@ mwifiex_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, { struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); + mwifiex_dump_station_info(priv, sinfo); + if (!priv->media_connected) return -ENOENT; if (memcmp(mac, priv->cfg_bssid, ETH_ALEN)) @@ -782,7 +768,6 @@ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv) struct mwifiex_bss_info bss_info; int ie_len; u8 ie_buf[IEEE80211_MAX_SSID_LEN + sizeof(struct ieee_types_header)]; - enum ieee80211_band band; if (mwifiex_get_bss_info(priv, &bss_info)) return -1; @@ -795,10 +780,9 @@ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv) bss_info.ssid.ssid_len); ie_len = ie_buf[1] + sizeof(struct ieee_types_header); - band = mwifiex_band_to_radio_type(priv->curr_bss_params.band); chan = __ieee80211_get_channel(priv->wdev->wiphy, ieee80211_channel_to_frequency(bss_info.bss_chan, - band)); + priv->curr_bss_params.band)); cfg80211_inform_bss(priv->wdev->wiphy, chan, bss_info.bssid, 0, WLAN_CAPABILITY_IBSS, @@ -1162,150 +1146,8 @@ mwifiex_setup_ht_caps(struct ieee80211_sta_ht_cap *ht_info, ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; } -/* - * create a new virtual interface with the given name - */ -struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy, - char *name, - enum nl80211_iftype type, - u32 *flags, - struct vif_params *params) -{ - struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); - struct mwifiex_adapter *adapter; - struct net_device *dev; - void *mdev_priv; - - if (!priv) - return NULL; - - adapter = priv->adapter; - if (!adapter) - return NULL; - - switch (type) { - case NL80211_IFTYPE_UNSPECIFIED: - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_ADHOC: - if (priv->bss_mode) { - wiphy_err(wiphy, "cannot create multiple" - " station/adhoc interfaces\n"); - return NULL; - } - - if (type == NL80211_IFTYPE_UNSPECIFIED) - priv->bss_mode = NL80211_IFTYPE_STATION; - else - priv->bss_mode = type; - - priv->bss_type = MWIFIEX_BSS_TYPE_STA; - priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II; - priv->bss_priority = 0; - priv->bss_role = MWIFIEX_BSS_ROLE_STA; - priv->bss_index = 0; - priv->bss_num = 0; - - break; - default: - wiphy_err(wiphy, "type not supported\n"); - return NULL; - } - - dev = alloc_netdev_mq(sizeof(struct mwifiex_private *), name, - ether_setup, 1); - if (!dev) { - wiphy_err(wiphy, "no memory available for netdevice\n"); - goto error; - } - - dev_net_set(dev, wiphy_net(wiphy)); - dev->ieee80211_ptr = priv->wdev; - dev->ieee80211_ptr->iftype = priv->bss_mode; - memcpy(dev->dev_addr, wiphy->perm_addr, ETH_ALEN); - memcpy(dev->perm_addr, wiphy->perm_addr, ETH_ALEN); - SET_NETDEV_DEV(dev, wiphy_dev(wiphy)); - - dev->flags |= IFF_BROADCAST | IFF_MULTICAST; - dev->watchdog_timeo = MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT; - dev->hard_header_len += MWIFIEX_MIN_DATA_HEADER_LEN; - - mdev_priv = netdev_priv(dev); - *((unsigned long *) mdev_priv) = (unsigned long) priv; - - priv->netdev = dev; - mwifiex_init_priv_params(priv, dev); - - SET_NETDEV_DEV(dev, adapter->dev); - - /* Register network device */ - if (register_netdevice(dev)) { - wiphy_err(wiphy, "cannot register virtual network device\n"); - goto error; - } - - sema_init(&priv->async_sem, 1); - priv->scan_pending_on_block = false; - - dev_dbg(adapter->dev, "info: %s: Marvell 802.11 Adapter\n", dev->name); - -#ifdef CONFIG_DEBUG_FS - mwifiex_dev_debugfs_init(priv); -#endif - return dev; -error: - if (dev && (dev->reg_state == NETREG_UNREGISTERED)) - free_netdev(dev); - priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; - - return NULL; -} -EXPORT_SYMBOL_GPL(mwifiex_add_virtual_intf); - -/* - * del_virtual_intf: remove the virtual interface determined by dev - */ -int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev) -{ - struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); - - if (!priv || !dev) - return 0; - -#ifdef CONFIG_DEBUG_FS - mwifiex_dev_debugfs_remove(priv); -#endif - - if (!netif_queue_stopped(priv->netdev)) - netif_stop_queue(priv->netdev); - - if (netif_carrier_ok(priv->netdev)) - netif_carrier_off(priv->netdev); - - if (dev->reg_state == NETREG_REGISTERED) - unregister_netdevice(dev); - - if (dev->reg_state == NETREG_UNREGISTERED) - free_netdev(dev); - - /* Clear the priv in adapter */ - priv->netdev = NULL; - - priv->media_connected = false; - - cancel_work_sync(&priv->cfg_workqueue); - flush_workqueue(priv->workqueue); - destroy_workqueue(priv->workqueue); - - priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; - - return 0; -} -EXPORT_SYMBOL_GPL(mwifiex_del_virtual_intf); - /* station cfg80211 operations */ static struct cfg80211_ops mwifiex_cfg80211_ops = { - .add_virtual_intf = mwifiex_add_virtual_intf, - .del_virtual_intf = mwifiex_del_virtual_intf, .change_virtual_intf = mwifiex_cfg80211_change_virtual_intf, .scan = mwifiex_cfg80211_scan, .connect = mwifiex_cfg80211_connect, @@ -1330,7 +1172,8 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { * default parameters and handler function pointers, and finally * registers the device. */ -int mwifiex_register_cfg80211(struct mwifiex_private *priv) +int mwifiex_register_cfg80211(struct net_device *dev, u8 *mac, + struct mwifiex_private *priv) { int ret; void *wdev_priv; @@ -1370,15 +1213,12 @@ int mwifiex_register_cfg80211(struct mwifiex_private *priv) wdev->wiphy->cipher_suites = mwifiex_cipher_suites; wdev->wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites); - memcpy(wdev->wiphy->perm_addr, priv->curr_addr, ETH_ALEN); + memcpy(wdev->wiphy->perm_addr, mac, 6); wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; /* We are using custom domains */ wdev->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; - /* Reserve space for bss band information */ - wdev->wiphy->bss_priv_size = sizeof(u8); - wdev->wiphy->reg_notifier = mwifiex_reg_notifier; /* Set struct mwifiex_private pointer in wiphy_priv */ @@ -1400,8 +1240,17 @@ int mwifiex_register_cfg80211(struct mwifiex_private *priv) "info: successfully registered wiphy device\n"); } + dev_net_set(dev, wiphy_net(wdev->wiphy)); + dev->ieee80211_ptr = wdev; + memcpy(dev->dev_addr, wdev->wiphy->perm_addr, 6); + memcpy(dev->perm_addr, wdev->wiphy->perm_addr, 6); + SET_NETDEV_DEV(dev, wiphy_dev(wdev->wiphy)); priv->wdev = wdev; + dev->flags |= IFF_BROADCAST | IFF_MULTICAST; + dev->watchdog_timeo = MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT; + dev->hard_header_len += MWIFIEX_MIN_DATA_HEADER_LEN; + return ret; } diff --git a/trunk/drivers/net/wireless/mwifiex/cfg80211.h b/trunk/drivers/net/wireless/mwifiex/cfg80211.h index 8d010f2500c5..c4db8f36aa16 100644 --- a/trunk/drivers/net/wireless/mwifiex/cfg80211.h +++ b/trunk/drivers/net/wireless/mwifiex/cfg80211.h @@ -24,7 +24,8 @@ #include "main.h" -int mwifiex_register_cfg80211(struct mwifiex_private *); +int mwifiex_register_cfg80211(struct net_device *, u8 *, + struct mwifiex_private *); void mwifiex_cfg80211_results(struct work_struct *work); #endif diff --git a/trunk/drivers/net/wireless/mwifiex/cmdevt.c b/trunk/drivers/net/wireless/mwifiex/cmdevt.c index d12e25d0c880..b5352afb8714 100644 --- a/trunk/drivers/net/wireless/mwifiex/cmdevt.c +++ b/trunk/drivers/net/wireless/mwifiex/cmdevt.c @@ -90,9 +90,6 @@ mwifiex_clean_cmd_node(struct mwifiex_adapter *adapter, cmd_node->data_buf = NULL; cmd_node->wait_q_enabled = false; - if (cmd_node->cmd_skb) - skb_trim(cmd_node->cmd_skb, 0); - if (cmd_node->resp_skb) { dev_kfree_skb_any(cmd_node->resp_skb); cmd_node->resp_skb = NULL; diff --git a/trunk/drivers/net/wireless/mwifiex/decl.h b/trunk/drivers/net/wireless/mwifiex/decl.h index 6ca62c809cb9..94ddc9038cb3 100644 --- a/trunk/drivers/net/wireless/mwifiex/decl.h +++ b/trunk/drivers/net/wireless/mwifiex/decl.h @@ -114,6 +114,14 @@ struct mwifiex_txinfo { u8 bss_index; }; +struct mwifiex_bss_attr { + u8 bss_type; + u8 frame_type; + u8 active; + u8 bss_priority; + u8 bss_num; +}; + enum mwifiex_wmm_ac_e { WMM_AC_BK, WMM_AC_BE, diff --git a/trunk/drivers/net/wireless/mwifiex/init.c b/trunk/drivers/net/wireless/mwifiex/init.c index e1076b46401e..26e685a31bc0 100644 --- a/trunk/drivers/net/wireless/mwifiex/init.c +++ b/trunk/drivers/net/wireless/mwifiex/init.c @@ -76,7 +76,7 @@ static int mwifiex_init_priv(struct mwifiex_private *priv) memset(priv->curr_addr, 0xff, ETH_ALEN); priv->pkt_tx_ctrl = 0; - priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; + priv->bss_mode = NL80211_IFTYPE_STATION; priv->data_rate = 0; /* Initially indicate the rate as auto */ priv->is_data_rate_auto = true; priv->bcn_avg_factor = DEFAULT_BCN_AVG_FACTOR; diff --git a/trunk/drivers/net/wireless/mwifiex/main.c b/trunk/drivers/net/wireless/mwifiex/main.c index 848645118ad4..53579ad83e5c 100644 --- a/trunk/drivers/net/wireless/mwifiex/main.c +++ b/trunk/drivers/net/wireless/mwifiex/main.c @@ -26,6 +26,21 @@ const char driver_version[] = "mwifiex " VERSION " (%s) "; +static struct mwifiex_bss_attr mwifiex_bss_sta[] = { + {MWIFIEX_BSS_TYPE_STA, MWIFIEX_DATA_FRAME_TYPE_ETH_II, true, 0, 0}, +}; + +static int drv_mode = DRV_MODE_STA; + +/* Supported drv_mode table */ +static struct mwifiex_drv_mode mwifiex_drv_mode_tbl[] = { + { + .drv_mode = DRV_MODE_STA, + .intf_num = ARRAY_SIZE(mwifiex_bss_sta), + .bss_attr = mwifiex_bss_sta, + }, +}; + /* * This function registers the device and performs all the necessary * initializations. @@ -42,6 +57,7 @@ const char driver_version[] = "mwifiex " VERSION " (%s) "; * proper cleanup before exiting. */ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops, + struct mwifiex_drv_mode *drv_mode_ptr, void **padapter) { struct mwifiex_adapter *adapter; @@ -62,20 +78,44 @@ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops, goto error; adapter->priv_num = 0; + for (i = 0; i < drv_mode_ptr->intf_num; i++) { + adapter->priv[i] = NULL; - /* Allocate memory for private structure */ - adapter->priv[0] = kzalloc(sizeof(struct mwifiex_private), - GFP_KERNEL); - if (!adapter->priv[0]) { - dev_err(adapter->dev, "%s: failed to alloc priv[0]\n", - __func__); - goto error; - } + if (!drv_mode_ptr->bss_attr[i].active) + continue; + + /* Allocate memory for private structure */ + adapter->priv[i] = kzalloc(sizeof(struct mwifiex_private), + GFP_KERNEL); + if (!adapter->priv[i]) { + dev_err(adapter->dev, "%s: failed to alloc priv[%d]\n", + __func__, i); + goto error; + } - adapter->priv_num++; + adapter->priv_num++; + adapter->priv[i]->adapter = adapter; + /* Save bss_type, frame_type & bss_priority */ + adapter->priv[i]->bss_type = drv_mode_ptr->bss_attr[i].bss_type; + adapter->priv[i]->frame_type = + drv_mode_ptr->bss_attr[i].frame_type; + adapter->priv[i]->bss_priority = + drv_mode_ptr->bss_attr[i].bss_priority; + + if (drv_mode_ptr->bss_attr[i].bss_type == MWIFIEX_BSS_TYPE_STA) + adapter->priv[i]->bss_role = MWIFIEX_BSS_ROLE_STA; + else if (drv_mode_ptr->bss_attr[i].bss_type == + MWIFIEX_BSS_TYPE_UAP) + adapter->priv[i]->bss_role = MWIFIEX_BSS_ROLE_UAP; + + /* Save bss_index & bss_num */ + adapter->priv[i]->bss_index = i; + adapter->priv[i]->bss_num = drv_mode_ptr->bss_attr[i].bss_num; + } + adapter->drv_mode = drv_mode_ptr; - adapter->priv[0]->adapter = adapter; - mwifiex_init_lock_list(adapter); + if (mwifiex_init_lock_list(adapter)) + goto error; init_timer(&adapter->cmd_timer); adapter->cmd_timer.function = mwifiex_cmd_timeout_func; @@ -86,9 +126,9 @@ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops, error: dev_dbg(adapter->dev, "info: leave mwifiex_register with error\n"); - for (i = 0; i < adapter->priv_num; i++) + mwifiex_free_lock_list(adapter); + for (i = 0; i < drv_mode_ptr->intf_num; i++) kfree(adapter->priv[i]); - kfree(adapter); return -1; @@ -275,6 +315,38 @@ int mwifiex_main_process(struct mwifiex_adapter *adapter) return ret; } +/* + * This function initializes the software. + * + * The main work includes allocating and initializing the adapter structure + * and initializing the private structures. + */ +static int +mwifiex_init_sw(void *card, struct mwifiex_if_ops *if_ops, void **padapter) +{ + int i; + struct mwifiex_drv_mode *drv_mode_ptr; + + /* find mwifiex_drv_mode entry from mwifiex_drv_mode_tbl */ + drv_mode_ptr = NULL; + for (i = 0; i < ARRAY_SIZE(mwifiex_drv_mode_tbl); i++) { + if (mwifiex_drv_mode_tbl[i].drv_mode == drv_mode) { + drv_mode_ptr = &mwifiex_drv_mode_tbl[i]; + break; + } + } + + if (!drv_mode_ptr) { + pr_err("invalid drv_mode=%d\n", drv_mode); + return -1; + } + + if (mwifiex_register(card, if_ops, drv_mode_ptr, padapter)) + return -1; + + return 0; +} + /* * This function frees the adapter structure. * @@ -577,8 +649,8 @@ static const struct net_device_ops mwifiex_netdev_ops = { * * In addition, the CFG80211 work queue is also created. */ -void mwifiex_init_priv_params(struct mwifiex_private *priv, - struct net_device *dev) +static void +mwifiex_init_priv_params(struct mwifiex_private *priv, struct net_device *dev) { dev->netdev_ops = &mwifiex_netdev_ops; /* Initialize private structure */ @@ -591,6 +663,118 @@ void mwifiex_init_priv_params(struct mwifiex_private *priv, memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN); } +/* + * This function adds a new logical interface. + * + * It allocates, initializes and registers the interface by performing + * the following opearations - + * - Allocate a new net device structure + * - Assign device name + * - Register the new device with CFG80211 subsystem + * - Initialize semaphore and private structure + * - Register the new device with kernel + * - Create the complete debug FS structure if configured + */ +static struct mwifiex_private *mwifiex_add_interface( + struct mwifiex_adapter *adapter, + u8 bss_index, u8 bss_type) +{ + struct net_device *dev; + struct mwifiex_private *priv; + void *mdev_priv; + + dev = alloc_netdev_mq(sizeof(struct mwifiex_private *), "mlan%d", + ether_setup, 1); + if (!dev) { + dev_err(adapter->dev, "no memory available for netdevice\n"); + goto error; + } + + if (mwifiex_register_cfg80211(dev, adapter->priv[bss_index]->curr_addr, + adapter->priv[bss_index]) != 0) { + dev_err(adapter->dev, "cannot register netdevice with cfg80211\n"); + goto error; + } + /* Save the priv pointer in netdev */ + priv = adapter->priv[bss_index]; + mdev_priv = netdev_priv(dev); + *((unsigned long *) mdev_priv) = (unsigned long) priv; + + priv->netdev = dev; + + sema_init(&priv->async_sem, 1); + priv->scan_pending_on_block = false; + + mwifiex_init_priv_params(priv, dev); + + SET_NETDEV_DEV(dev, adapter->dev); + + /* Register network device */ + if (register_netdev(dev)) { + dev_err(adapter->dev, "cannot register virtual network device\n"); + goto error; + } + + dev_dbg(adapter->dev, "info: %s: Marvell 802.11 Adapter\n", dev->name); +#ifdef CONFIG_DEBUG_FS + mwifiex_dev_debugfs_init(priv); +#endif + return priv; +error: + if (dev) + free_netdev(dev); + return NULL; +} + +/* + * This function removes a logical interface. + * + * It deregisters, resets and frees the interface by performing + * the following operations - + * - Disconnect the device if connected, send wireless event to + * notify applications. + * - Remove the debug FS structure if configured + * - Unregister the device from kernel + * - Free the net device structure + * - Cancel all works and destroy work queue + * - Unregister and free the wireless device from CFG80211 subsystem + */ +static void +mwifiex_remove_interface(struct mwifiex_adapter *adapter, u8 bss_index) +{ + struct net_device *dev; + struct mwifiex_private *priv = adapter->priv[bss_index]; + + if (!priv) + return; + dev = priv->netdev; + + if (priv->media_connected) + priv->media_connected = false; + +#ifdef CONFIG_DEBUG_FS + mwifiex_dev_debugfs_remove(priv); +#endif + /* Last reference is our one */ + dev_dbg(adapter->dev, "info: %s: refcnt = %d\n", + dev->name, netdev_refcnt_read(dev)); + + if (dev->reg_state == NETREG_REGISTERED) + unregister_netdev(dev); + + /* Clear the priv in adapter */ + priv->netdev = NULL; + if (dev) + free_netdev(dev); + + cancel_work_sync(&priv->cfg_workqueue); + flush_workqueue(priv->workqueue); + destroy_workqueue(priv->workqueue); + wiphy_unregister(priv->wdev->wiphy); + wiphy_free(priv->wdev->wiphy); + kfree(priv->wdev); +} + /* * This function check if command is pending. */ @@ -663,14 +847,14 @@ int mwifiex_add_card(void *card, struct semaphore *sem, struct mwifiex_if_ops *if_ops) { + int i; struct mwifiex_adapter *adapter; char fmt[64]; - struct mwifiex_private *priv; if (down_interruptible(sem)) goto exit_sem_err; - if (mwifiex_register(card, if_ops, (void **)&adapter)) { + if (mwifiex_init_sw(card, if_ops, (void **)&adapter)) { pr_err("%s: software init failed\n", __func__); goto err_init_sw; } @@ -704,26 +888,14 @@ mwifiex_add_card(void *card, struct semaphore *sem, goto err_init_fw; } - priv = adapter->priv[0]; - - if (mwifiex_register_cfg80211(priv) != 0) { - dev_err(adapter->dev, "cannot register netdevice" - " with cfg80211\n"); - goto err_init_fw; - } - - rtnl_lock(); - /* Create station interface by default */ - if (!mwifiex_add_virtual_intf(priv->wdev->wiphy, "mlan%d", - NL80211_IFTYPE_STATION, NULL, NULL)) { - rtnl_unlock(); - dev_err(adapter->dev, "cannot create default station" - " interface\n"); - goto err_add_intf; + /* Add interfaces */ + for (i = 0; i < adapter->drv_mode->intf_num; i++) { + if (!mwifiex_add_interface(adapter, i, + adapter->drv_mode->bss_attr[i].bss_type)) { + goto err_add_intf; + } } - rtnl_unlock(); - up(sem); mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1); @@ -732,9 +904,8 @@ mwifiex_add_card(void *card, struct semaphore *sem, return 0; err_add_intf: - rtnl_lock(); - mwifiex_del_virtual_intf(priv->wdev->wiphy, priv->netdev); - rtnl_unlock(); + for (i = 0; i < adapter->priv_num; i++) + mwifiex_remove_interface(adapter, i); err_init_fw: pr_debug("info: %s: unregister device\n", __func__); adapter->if_ops.unregister_dev(adapter); @@ -789,7 +960,7 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem) /* Stop data */ for (i = 0; i < adapter->priv_num; i++) { priv = adapter->priv[i]; - if (priv && priv->netdev) { + if (priv) { if (!netif_queue_stopped(priv->netdev)) netif_stop_queue(priv->netdev); if (netif_carrier_ok(priv->netdev)) @@ -814,20 +985,9 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem) atomic_read(&adapter->cmd_pending)); } - for (i = 0; i < adapter->priv_num; i++) { - priv = adapter->priv[i]; - - if (!priv) - continue; - - rtnl_lock(); - mwifiex_del_virtual_intf(priv->wdev->wiphy, priv->netdev); - rtnl_unlock(); - } - - wiphy_unregister(priv->wdev->wiphy); - wiphy_free(priv->wdev->wiphy); - kfree(priv->wdev); + /* Remove interface */ + for (i = 0; i < adapter->priv_num; i++) + mwifiex_remove_interface(adapter, i); mwifiex_terminate_workqueue(adapter); diff --git a/trunk/drivers/net/wireless/mwifiex/main.h b/trunk/drivers/net/wireless/mwifiex/main.h index 907ab746dc4b..e6b6c0cfb63e 100644 --- a/trunk/drivers/net/wireless/mwifiex/main.h +++ b/trunk/drivers/net/wireless/mwifiex/main.h @@ -45,6 +45,15 @@ enum { MWIFIEX_SYNC_CMD }; +#define DRV_MODE_STA 0x1 + +struct mwifiex_drv_mode { + u16 drv_mode; + u16 intf_num; + struct mwifiex_bss_attr *bss_attr; +}; + + #define MWIFIEX_MAX_AP 64 #define MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT (5 * HZ) @@ -173,6 +182,7 @@ struct mwifiex_ra_list_tbl { struct sk_buff_head skb_head; u8 ra[ETH_ALEN]; u32 total_pkts_size; + u32 total_pkts; u32 is_11n_enabled; }; @@ -536,6 +546,7 @@ struct mwifiex_if_ops { struct mwifiex_adapter { struct mwifiex_private *priv[MWIFIEX_MAX_BSS_NUM]; u8 priv_num; + struct mwifiex_drv_mode *drv_mode; const struct firmware *firmware; char fw_name[32]; struct device *dev; @@ -781,8 +792,6 @@ int mwifiex_cmd_get_hw_spec(struct mwifiex_private *priv, int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv, struct host_cmd_ds_command *resp); int is_command_pending(struct mwifiex_adapter *adapter); -void mwifiex_init_priv_params(struct mwifiex_private *priv, - struct net_device *dev); /* * This function checks if the queuing is RA based or not. @@ -949,7 +958,7 @@ int mwifiex_get_bss_info(struct mwifiex_private *, int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv, u8 *bssid, s32 rssi, u8 *ie_buf, size_t ie_len, u16 beacon_period, - u16 cap_info_bitmap, u8 band, + u16 cap_info_bitmap, struct mwifiex_bssdescriptor *bss_desc); int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter, struct mwifiex_bssdescriptor *bss_entry, @@ -957,12 +966,6 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter, int mwifiex_check_network_compatibility(struct mwifiex_private *priv, struct mwifiex_bssdescriptor *bss_desc); -struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy, - char *name, enum nl80211_iftype type, - u32 *flags, struct vif_params *params); -int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev); - - #ifdef CONFIG_DEBUG_FS void mwifiex_debugfs_init(void); void mwifiex_debugfs_remove(void); diff --git a/trunk/drivers/net/wireless/mwifiex/scan.c b/trunk/drivers/net/wireless/mwifiex/scan.c index ca3761965e85..8d8588db1cd9 100644 --- a/trunk/drivers/net/wireless/mwifiex/scan.c +++ b/trunk/drivers/net/wireless/mwifiex/scan.c @@ -532,7 +532,7 @@ mwifiex_scan_create_channel_list(struct mwifiex_private *priv, sband = priv->wdev->wiphy->bands[band]; - for (i = 0; (i < sband->n_channels) ; i++) { + for (i = 0; (i < sband->n_channels) ; i++, chan_idx++) { ch = &sband->channels[i]; if (ch->flags & IEEE80211_CHAN_DISABLED) continue; @@ -563,7 +563,6 @@ mwifiex_scan_create_channel_list(struct mwifiex_private *priv, scan_chan_list[chan_idx].chan_scan_mode_bitmap |= MWIFIEX_DISABLE_CHAN_FILT; } - chan_idx++; } } @@ -1464,9 +1463,9 @@ int mwifiex_check_network_compatibility(struct mwifiex_private *priv, } static int -mwifiex_update_curr_bss_params(struct mwifiex_private *priv, u8 *bssid, - s32 rssi, const u8 *ie_buf, size_t ie_len, - u16 beacon_period, u16 cap_info_bitmap, u8 band) +mwifiex_update_curr_bss_params(struct mwifiex_private *priv, + u8 *bssid, s32 rssi, const u8 *ie_buf, + size_t ie_len, u16 beacon_period, u16 cap_info_bitmap) { struct mwifiex_bssdescriptor *bss_desc = NULL; int ret; @@ -1489,7 +1488,7 @@ mwifiex_update_curr_bss_params(struct mwifiex_private *priv, u8 *bssid, ret = mwifiex_fill_new_bss_desc(priv, bssid, rssi, beacon_ie, ie_len, beacon_period, - cap_info_bitmap, band, bss_desc); + cap_info_bitmap, bss_desc); if (ret) goto done; @@ -1533,11 +1532,6 @@ mwifiex_update_curr_bss_params(struct mwifiex_private *priv, u8 *bssid, return 0; } -static void mwifiex_free_bss_priv(struct cfg80211_bss *bss) -{ - kfree(bss->priv); -} - /* * This function handles the command response of scan. * @@ -1576,7 +1570,6 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, struct chan_band_param_set *chan_band; u8 is_bgscan_resp; unsigned long flags; - struct cfg80211_bss *bss; is_bgscan_resp = (le16_to_cpu(resp->command) == HostCmd_CMD_802_11_BG_SCAN_QUERY); @@ -1758,12 +1751,10 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, chan = ieee80211_get_channel(priv->wdev->wiphy, freq); if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) { - bss = cfg80211_inform_bss(priv->wdev->wiphy, - chan, bssid, network_tsf, - cap_info_bitmap, beacon_period, - ie_buf, ie_len, rssi, GFP_KERNEL); - *(u8 *)bss->priv = band; - bss->free_priv = mwifiex_free_bss_priv; + cfg80211_inform_bss(priv->wdev->wiphy, chan, + bssid, network_tsf, cap_info_bitmap, + beacon_period, ie_buf, ie_len, rssi, + GFP_KERNEL); if (priv->media_connected && !memcmp(bssid, priv->curr_bss_params.bss_descriptor @@ -1771,7 +1762,7 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, mwifiex_update_curr_bss_params(priv, bssid, rssi, ie_buf, ie_len, beacon_period, - cap_info_bitmap, band); + cap_info_bitmap); } } else { dev_dbg(adapter->dev, "missing BSS channel IE\n"); diff --git a/trunk/drivers/net/wireless/mwifiex/sta_ioctl.c b/trunk/drivers/net/wireless/mwifiex/sta_ioctl.c index 520800b618e7..eb569fa9adba 100644 --- a/trunk/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/trunk/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -148,7 +148,7 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv, int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv, u8 *bssid, s32 rssi, u8 *ie_buf, size_t ie_len, u16 beacon_period, - u16 cap_info_bitmap, u8 band, + u16 cap_info_bitmap, struct mwifiex_bssdescriptor *bss_desc) { int ret; @@ -159,7 +159,6 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv, bss_desc->beacon_buf_size = ie_len; bss_desc->beacon_period = beacon_period; bss_desc->cap_info_bitmap = cap_info_bitmap; - bss_desc->bss_band = band; if (bss_desc->cap_info_bitmap & WLAN_CAPABILITY_PRIVACY) { dev_dbg(priv->adapter->dev, "info: InterpretIE: AP WEP enabled\n"); bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_8021X_WEP; @@ -204,7 +203,6 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, beacon_ie = kmemdup(bss->information_elements, bss->len_beacon_ies, GFP_KERNEL); if (!beacon_ie) { - kfree(bss_desc); dev_err(priv->adapter->dev, " failed to alloc beacon_ie\n"); return -ENOMEM; } @@ -212,8 +210,7 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, ret = mwifiex_fill_new_bss_desc(priv, bss->bssid, bss->signal, beacon_ie, bss->len_beacon_ies, bss->beacon_interval, - bss->capability, - *(u8 *)bss->priv, bss_desc); + bss->capability, bss_desc); if (ret) goto done; } @@ -655,7 +652,6 @@ mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel) u16 curr_chan = 0; struct cfg80211_bss *bss = NULL; struct ieee80211_channel *chan; - enum ieee80211_band band; memset(&bss_info, 0, sizeof(bss_info)); @@ -692,9 +688,9 @@ mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel) goto done; } - band = mwifiex_band_to_radio_type(priv->curr_bss_params.band); chan = __ieee80211_get_channel(priv->wdev->wiphy, - ieee80211_channel_to_frequency(channel, band)); + ieee80211_channel_to_frequency(channel, + priv->curr_bss_params.band)); /* Find the BSS we want using available scan results */ bss = cfg80211_get_bss(priv->wdev->wiphy, chan, bss_info.bssid, @@ -720,9 +716,51 @@ mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel) static int mwifiex_rate_ioctl_get_rate_value(struct mwifiex_private *priv, struct mwifiex_rate_cfg *rate_cfg) { + struct mwifiex_adapter *adapter = priv->adapter; + rate_cfg->is_rate_auto = priv->is_data_rate_auto; - return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_TX_RATE_QUERY, - HostCmd_ACT_GEN_GET, 0, NULL); + if (!priv->media_connected) { + switch (adapter->config_bands) { + case BAND_B: + /* Return the lowest supported rate for B band */ + rate_cfg->rate = supported_rates_b[0] & 0x7f; + break; + case BAND_G: + case BAND_G | BAND_GN: + /* Return the lowest supported rate for G band */ + rate_cfg->rate = supported_rates_g[0] & 0x7f; + break; + case BAND_B | BAND_G: + case BAND_A | BAND_B | BAND_G: + case BAND_A | BAND_B: + case BAND_A | BAND_B | BAND_G | BAND_AN | BAND_GN: + case BAND_B | BAND_G | BAND_GN: + /* Return the lowest supported rate for BG band */ + rate_cfg->rate = supported_rates_bg[0] & 0x7f; + break; + case BAND_A: + case BAND_A | BAND_G: + case BAND_A | BAND_G | BAND_AN | BAND_GN: + case BAND_A | BAND_AN: + /* Return the lowest supported rate for A band */ + rate_cfg->rate = supported_rates_a[0] & 0x7f; + break; + case BAND_GN: + /* Return the lowest supported rate for N band */ + rate_cfg->rate = supported_rates_n[0] & 0x7f; + break; + default: + dev_warn(adapter->dev, "invalid band %#x\n", + adapter->config_bands); + break; + } + } else { + return mwifiex_send_cmd_sync(priv, + HostCmd_CMD_802_11_TX_RATE_QUERY, + HostCmd_ACT_GEN_GET, 0, NULL); + } + + return 0; } /* @@ -829,10 +867,10 @@ int mwifiex_drv_get_data_rate(struct mwifiex_private *priv, ret = mwifiex_rate_ioctl_cfg(priv, rate); if (!ret) { - if (rate->is_rate_auto) + if (rate && rate->is_rate_auto) rate->rate = mwifiex_index_to_data_rate(priv->tx_rate, priv->tx_htinfo); - else + else if (rate) rate->rate = priv->data_rate; } else { ret = -1; diff --git a/trunk/drivers/net/wireless/mwifiex/wmm.c b/trunk/drivers/net/wireless/mwifiex/wmm.c index eda24474c1fc..69e260b41711 100644 --- a/trunk/drivers/net/wireless/mwifiex/wmm.c +++ b/trunk/drivers/net/wireless/mwifiex/wmm.c @@ -121,6 +121,7 @@ mwifiex_wmm_allocate_ralist_node(struct mwifiex_adapter *adapter, u8 *ra) memcpy(ra_list->ra, ra, ETH_ALEN); ra_list->total_pkts_size = 0; + ra_list->total_pkts = 0; dev_dbg(adapter->dev, "info: allocated ra_list %p\n", ra_list); @@ -647,6 +648,7 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_adapter *adapter, skb_queue_tail(&ra_list->skb_head, skb); ra_list->total_pkts_size += skb->len; + ra_list->total_pkts++; atomic_inc(&priv->wmm.tx_pkts_queued); @@ -972,28 +974,6 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, return NULL; } -/* - * This function checks if 11n aggregation is possible. - */ -static int -mwifiex_is_11n_aggragation_possible(struct mwifiex_private *priv, - struct mwifiex_ra_list_tbl *ptr, - int max_buf_size) -{ - int count = 0, total_size = 0; - struct sk_buff *skb, *tmp; - - skb_queue_walk_safe(&ptr->skb_head, skb, tmp) { - total_size += skb->len; - if (total_size >= max_buf_size) - break; - if (++count >= MIN_NUM_AMSDU) - return true; - } - - return false; -} - /* * This function sends a single packet to firmware for transmission. */ @@ -1021,6 +1001,7 @@ mwifiex_send_single_packet(struct mwifiex_private *priv, dev_dbg(adapter->dev, "data: dequeuing the packet %p %p\n", ptr, skb); ptr->total_pkts_size -= skb->len; + ptr->total_pkts--; if (!skb_queue_empty(&ptr->skb_head)) skb_next = skb_peek(&ptr->skb_head); @@ -1046,6 +1027,7 @@ mwifiex_send_single_packet(struct mwifiex_private *priv, skb_queue_tail(&ptr->skb_head, skb); ptr->total_pkts_size += skb->len; + ptr->total_pkts++; tx_info->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT; spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags); @@ -1231,9 +1213,11 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter) mwifiex_send_delba(priv, tid_del, ra, 1); } } +/* Minimum number of AMSDU */ +#define MIN_NUM_AMSDU 2 + if (mwifiex_is_amsdu_allowed(priv, tid) && - mwifiex_is_11n_aggragation_possible(priv, ptr, - adapter->tx_buf_size)) + (ptr->total_pkts >= MIN_NUM_AMSDU)) mwifiex_11n_aggregate_pkt(priv, ptr, INTF_HEADER_LEN, ptr_index, flags); /* ra_list_spinlock has been freed in diff --git a/trunk/drivers/net/wireless/mwl8k.c b/trunk/drivers/net/wireless/mwl8k.c index 995695c28d5c..ea1395aafa39 100644 --- a/trunk/drivers/net/wireless/mwl8k.c +++ b/trunk/drivers/net/wireless/mwl8k.c @@ -4915,8 +4915,7 @@ static int mwl8k_sta_add(struct ieee80211_hw *hw, return ret; } -static int mwl8k_conf_tx(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, u16 queue, +static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params) { struct mwl8k_priv *priv = hw->priv; @@ -5463,7 +5462,7 @@ static int mwl8k_reload_firmware(struct ieee80211_hw *hw, char *fw_image) goto fail; for (i = 0; i < MWL8K_TX_WMM_QUEUES; i++) { - rc = mwl8k_conf_tx(hw, NULL, i, &priv->wmm_params[i]); + rc = mwl8k_conf_tx(hw, i, &priv->wmm_params[i]); if (rc) goto fail; } diff --git a/trunk/drivers/net/wireless/p54/main.c b/trunk/drivers/net/wireless/p54/main.c index ad9ae04d07aa..726a9343f514 100644 --- a/trunk/drivers/net/wireless/p54/main.c +++ b/trunk/drivers/net/wireless/p54/main.c @@ -404,8 +404,7 @@ static void p54_configure_filter(struct ieee80211_hw *dev, p54_set_groupfilter(priv); } -static int p54_conf_tx(struct ieee80211_hw *dev, - struct ieee80211_vif *vif, u16 queue, +static int p54_conf_tx(struct ieee80211_hw *dev, u16 queue, const struct ieee80211_tx_queue_params *params) { struct p54_common *priv = dev->priv; diff --git a/trunk/drivers/net/wireless/p54/txrx.c b/trunk/drivers/net/wireless/p54/txrx.c index f485784a60ae..2b97a89e7ff8 100644 --- a/trunk/drivers/net/wireless/p54/txrx.c +++ b/trunk/drivers/net/wireless/p54/txrx.c @@ -689,7 +689,7 @@ static void p54_tx_80211_header(struct p54_common *priv, struct sk_buff *skb, if (!(info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)) *flags |= P54_HDR_FLAG_DATA_OUT_SEQNR; - if (info->flags & IEEE80211_TX_CTL_POLL_RESPONSE) + if (info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE) *flags |= P54_HDR_FLAG_DATA_OUT_NOCANCEL; if (info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT) diff --git a/trunk/drivers/net/wireless/rt2x00/rt2400pci.c b/trunk/drivers/net/wireless/rt2x00/rt2400pci.c index 3a6b40239bc1..daa32fc9398b 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1239,7 +1239,7 @@ static void rt2400pci_fill_rxdone(struct queue_entry *entry, * call, we must decrease the higher 32bits with 1 to get * to correct value. */ - tsf = rt2x00dev->ops->hw->get_tsf(rt2x00dev->hw, NULL); + tsf = rt2x00dev->ops->hw->get_tsf(rt2x00dev->hw); rx_low = rt2x00_get_field32(word4, RXD_W4_RX_END_TIME); rx_high = upper_32_bits(tsf); @@ -1648,8 +1648,7 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev) /* * IEEE80211 stack callback functions. */ -static int rt2400pci_conf_tx(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, u16 queue, +static int rt2400pci_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params) { struct rt2x00_dev *rt2x00dev = hw->priv; @@ -1662,7 +1661,7 @@ static int rt2400pci_conf_tx(struct ieee80211_hw *hw, if (queue != 0) return -EINVAL; - if (rt2x00mac_conf_tx(hw, vif, queue, params)) + if (rt2x00mac_conf_tx(hw, queue, params)) return -EINVAL; /* @@ -1674,8 +1673,7 @@ static int rt2400pci_conf_tx(struct ieee80211_hw *hw, return 0; } -static u64 rt2400pci_get_tsf(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) +static u64 rt2400pci_get_tsf(struct ieee80211_hw *hw) { struct rt2x00_dev *rt2x00dev = hw->priv; u64 tsf; diff --git a/trunk/drivers/net/wireless/rt2x00/rt2500pci.c b/trunk/drivers/net/wireless/rt2x00/rt2500pci.c index dcc0e1fcca77..b46c3b8866fa 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1966,8 +1966,7 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev) /* * IEEE80211 stack callback functions. */ -static u64 rt2500pci_get_tsf(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) +static u64 rt2500pci_get_tsf(struct ieee80211_hw *hw) { struct rt2x00_dev *rt2x00dev = hw->priv; u64 tsf; diff --git a/trunk/drivers/net/wireless/rt2x00/rt2800lib.c b/trunk/drivers/net/wireless/rt2x00/rt2800lib.c index 3f183a15186e..31c98509f7e6 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2800lib.c @@ -4398,8 +4398,7 @@ int rt2800_set_rts_threshold(struct ieee80211_hw *hw, u32 value) } EXPORT_SYMBOL_GPL(rt2800_set_rts_threshold); -int rt2800_conf_tx(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, u16 queue_idx, +int rt2800_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, const struct ieee80211_tx_queue_params *params) { struct rt2x00_dev *rt2x00dev = hw->priv; @@ -4415,7 +4414,7 @@ int rt2800_conf_tx(struct ieee80211_hw *hw, * we are free to update the registers based on the value * in the queue parameter. */ - retval = rt2x00mac_conf_tx(hw, vif, queue_idx, params); + retval = rt2x00mac_conf_tx(hw, queue_idx, params); if (retval) return retval; @@ -4467,7 +4466,7 @@ int rt2800_conf_tx(struct ieee80211_hw *hw, } EXPORT_SYMBOL_GPL(rt2800_conf_tx); -u64 rt2800_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +u64 rt2800_get_tsf(struct ieee80211_hw *hw) { struct rt2x00_dev *rt2x00dev = hw->priv; u64 tsf; diff --git a/trunk/drivers/net/wireless/rt2x00/rt2800lib.h b/trunk/drivers/net/wireless/rt2x00/rt2800lib.h index 8c3c281904fe..7a2511f6785c 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/trunk/drivers/net/wireless/rt2x00/rt2800lib.h @@ -197,10 +197,9 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev); void rt2800_get_tkip_seq(struct ieee80211_hw *hw, u8 hw_key_idx, u32 *iv32, u16 *iv16); int rt2800_set_rts_threshold(struct ieee80211_hw *hw, u32 value); -int rt2800_conf_tx(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, u16 queue_idx, +int rt2800_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, const struct ieee80211_tx_queue_params *params); -u64 rt2800_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif); +u64 rt2800_get_tsf(struct ieee80211_hw *hw); int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00.h b/trunk/drivers/net/wireless/rt2x00/rt2x00.h index 2ec5c00235e6..cbf8eb334e96 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00.h +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00.h @@ -1299,8 +1299,7 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, u32 changes); -int rt2x00mac_conf_tx(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, u16 queue, +int rt2x00mac_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params); void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw); void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop); diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00mac.c b/trunk/drivers/net/wireless/rt2x00/rt2x00mac.c index bf0acff07807..cef1c878c37e 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -713,8 +713,7 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, } EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed); -int rt2x00mac_conf_tx(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, u16 queue_idx, +int rt2x00mac_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, const struct ieee80211_tx_queue_params *params) { struct rt2x00_dev *rt2x00dev = hw->priv; diff --git a/trunk/drivers/net/wireless/rt2x00/rt61pci.c b/trunk/drivers/net/wireless/rt2x00/rt61pci.c index bf55b4a311e3..058ef4b19d1d 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt61pci.c +++ b/trunk/drivers/net/wireless/rt2x00/rt61pci.c @@ -2883,8 +2883,7 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev) /* * IEEE80211 stack callback functions. */ -static int rt61pci_conf_tx(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, u16 queue_idx, +static int rt61pci_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, const struct ieee80211_tx_queue_params *params) { struct rt2x00_dev *rt2x00dev = hw->priv; @@ -2900,7 +2899,7 @@ static int rt61pci_conf_tx(struct ieee80211_hw *hw, * we are free to update the registers based on the value * in the queue parameter. */ - retval = rt2x00mac_conf_tx(hw, vif, queue_idx, params); + retval = rt2x00mac_conf_tx(hw, queue_idx, params); if (retval) return retval; @@ -2941,7 +2940,7 @@ static int rt61pci_conf_tx(struct ieee80211_hw *hw, return 0; } -static u64 rt61pci_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +static u64 rt61pci_get_tsf(struct ieee80211_hw *hw) { struct rt2x00_dev *rt2x00dev = hw->priv; u64 tsf; diff --git a/trunk/drivers/net/wireless/rt2x00/rt73usb.c b/trunk/drivers/net/wireless/rt2x00/rt73usb.c index cfb19dbb0a67..0baeb894f093 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt73usb.c +++ b/trunk/drivers/net/wireless/rt2x00/rt73usb.c @@ -2222,8 +2222,7 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev) /* * IEEE80211 stack callback functions. */ -static int rt73usb_conf_tx(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, u16 queue_idx, +static int rt73usb_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, const struct ieee80211_tx_queue_params *params) { struct rt2x00_dev *rt2x00dev = hw->priv; @@ -2239,7 +2238,7 @@ static int rt73usb_conf_tx(struct ieee80211_hw *hw, * we are free to update the registers based on the value * in the queue parameter. */ - retval = rt2x00mac_conf_tx(hw, vif, queue_idx, params); + retval = rt2x00mac_conf_tx(hw, queue_idx, params); if (retval) return retval; @@ -2280,7 +2279,7 @@ static int rt73usb_conf_tx(struct ieee80211_hw *hw, return 0; } -static u64 rt73usb_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +static u64 rt73usb_get_tsf(struct ieee80211_hw *hw) { struct rt2x00_dev *rt2x00dev = hw->priv; u64 tsf; diff --git a/trunk/drivers/net/wireless/rtl818x/rtl8180/dev.c b/trunk/drivers/net/wireless/rtl818x/rtl8180/dev.c index 0082015ff664..66b29dc07cc3 100644 --- a/trunk/drivers/net/wireless/rtl818x/rtl8180/dev.c +++ b/trunk/drivers/net/wireless/rtl818x/rtl8180/dev.c @@ -669,8 +669,7 @@ static void rtl8180_stop(struct ieee80211_hw *dev) rtl8180_free_tx_ring(dev, i); } -static u64 rtl8180_get_tsf(struct ieee80211_hw *dev, - struct ieee80211_vif *vif) +static u64 rtl8180_get_tsf(struct ieee80211_hw *dev) { struct rtl8180_priv *priv = dev->priv; @@ -702,7 +701,7 @@ static void rtl8180_beacon_work(struct work_struct *work) * TODO: make hardware update beacon timestamp */ mgmt = (struct ieee80211_mgmt *)skb->data; - mgmt->u.beacon.timestamp = cpu_to_le64(rtl8180_get_tsf(dev, vif)); + mgmt->u.beacon.timestamp = cpu_to_le64(rtl8180_get_tsf(dev)); /* TODO: use actual beacon queue */ skb_set_queue_mapping(skb, 0); diff --git a/trunk/drivers/net/wireless/rtl818x/rtl8187/dev.c b/trunk/drivers/net/wireless/rtl818x/rtl8187/dev.c index 24873b55b55c..1e0be14d10d4 100644 --- a/trunk/drivers/net/wireless/rtl818x/rtl8187/dev.c +++ b/trunk/drivers/net/wireless/rtl818x/rtl8187/dev.c @@ -1241,8 +1241,7 @@ static void rtl8187_configure_filter(struct ieee80211_hw *dev, rtl818x_iowrite32_async(priv, &priv->map->RX_CONF, priv->rx_conf); } -static int rtl8187_conf_tx(struct ieee80211_hw *dev, - struct ieee80211_vif *vif, u16 queue, +static int rtl8187_conf_tx(struct ieee80211_hw *dev, u16 queue, const struct ieee80211_tx_queue_params *params) { struct rtl8187_priv *priv = dev->priv; @@ -1278,7 +1277,7 @@ static int rtl8187_conf_tx(struct ieee80211_hw *dev, return 0; } -static u64 rtl8187_get_tsf(struct ieee80211_hw *dev, struct ieee80211_vif *vif) +static u64 rtl8187_get_tsf(struct ieee80211_hw *dev) { struct rtl8187_priv *priv = dev->priv; diff --git a/trunk/drivers/net/wireless/rtlwifi/core.c b/trunk/drivers/net/wireless/rtlwifi/core.c index 3f0f056fae9c..04c4e9eb6ee6 100644 --- a/trunk/drivers/net/wireless/rtlwifi/core.c +++ b/trunk/drivers/net/wireless/rtlwifi/core.c @@ -504,8 +504,7 @@ static int _rtl_get_hal_qnum(u16 queue) *for mac80211 VO=0, VI=1, BE=2, BK=3 *for rtl819x BE=0, BK=1, VI=2, VO=3 */ -static int rtl_op_conf_tx(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, u16 queue, +static int rtl_op_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *param) { struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -776,7 +775,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, mutex_unlock(&rtlpriv->locks.conf_mutex); } -static u64 rtl_op_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +static u64 rtl_op_get_tsf(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); u64 tsf; @@ -785,8 +784,7 @@ static u64 rtl_op_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) return tsf; } -static void rtl_op_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - u64 tsf) +static void rtl_op_set_tsf(struct ieee80211_hw *hw, u64 tsf) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); @@ -796,8 +794,7 @@ static void rtl_op_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_CORRECT_TSF, (u8 *) (&bibss)); } -static void rtl_op_reset_tsf(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) +static void rtl_op_reset_tsf(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); u8 tmp = 0; diff --git a/trunk/drivers/net/wireless/rtlwifi/usb.c b/trunk/drivers/net/wireless/rtlwifi/usb.c index b42c2e2b2055..8b1cef0ffde6 100644 --- a/trunk/drivers/net/wireless/rtlwifi/usb.c +++ b/trunk/drivers/net/wireless/rtlwifi/usb.c @@ -191,6 +191,44 @@ static void _usb_write32_async(struct rtl_priv *rtlpriv, u32 addr, u32 val) _usb_write_async(to_usb_device(dev), addr, val, 4); } +static int _usb_nbytes_read_write(struct usb_device *udev, bool read, u32 addr, + u16 len, u8 *pdata) +{ + int status; + u8 request; + u16 wvalue; + u16 index; + + request = REALTEK_USB_VENQT_CMD_REQ; + index = REALTEK_USB_VENQT_CMD_IDX; /* n/a */ + wvalue = (u16)addr; + if (read) + status = _usbctrl_vendorreq_sync_read(udev, request, wvalue, + index, pdata, len); + else + status = _usbctrl_vendorreq_async_write(udev, request, wvalue, + index, pdata, len); + return status; +} + +static int _usb_readN_sync(struct rtl_priv *rtlpriv, u32 addr, u16 len, + u8 *pdata) +{ + struct device *dev = rtlpriv->io.dev; + + return _usb_nbytes_read_write(to_usb_device(dev), true, addr, len, + pdata); +} + +static int _usb_writeN_async(struct rtl_priv *rtlpriv, u32 addr, u16 len, + u8 *pdata) +{ + struct device *dev = rtlpriv->io.dev; + + return _usb_nbytes_read_write(to_usb_device(dev), false, addr, len, + pdata); +} + static void _rtl_usb_io_handler_init(struct device *dev, struct ieee80211_hw *hw) { @@ -201,9 +239,11 @@ static void _rtl_usb_io_handler_init(struct device *dev, rtlpriv->io.write8_async = _usb_write8_async; rtlpriv->io.write16_async = _usb_write16_async; rtlpriv->io.write32_async = _usb_write32_async; + rtlpriv->io.writeN_async = _usb_writeN_async; rtlpriv->io.read8_sync = _usb_read8_sync; rtlpriv->io.read16_sync = _usb_read16_sync; rtlpriv->io.read32_sync = _usb_read32_sync; + rtlpriv->io.readN_sync = _usb_readN_sync; } static void _rtl_usb_io_handler_release(struct ieee80211_hw *hw) @@ -823,7 +863,6 @@ static void _rtl_usb_tx_preprocess(struct ieee80211_hw *hw, struct sk_buff *skb, u8 tid = 0; u16 seq_number = 0; - memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); if (ieee80211_is_auth(fc)) { RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, ("MAC80211_LINKING\n")); rtl_ips_nic_on(hw); diff --git a/trunk/drivers/net/wireless/rtlwifi/wifi.h b/trunk/drivers/net/wireless/rtlwifi/wifi.h index 3126485393d9..615f6b4463e6 100644 --- a/trunk/drivers/net/wireless/rtlwifi/wifi.h +++ b/trunk/drivers/net/wireless/rtlwifi/wifi.h @@ -942,12 +942,16 @@ struct rtl_io { unsigned long pci_base_addr; /*device I/O address */ void (*write8_async) (struct rtl_priv *rtlpriv, u32 addr, u8 val); - void (*write16_async) (struct rtl_priv *rtlpriv, u32 addr, __le16 val); - void (*write32_async) (struct rtl_priv *rtlpriv, u32 addr, __le32 val); + void (*write16_async) (struct rtl_priv *rtlpriv, u32 addr, u16 val); + void (*write32_async) (struct rtl_priv *rtlpriv, u32 addr, u32 val); + int (*writeN_async) (struct rtl_priv *rtlpriv, u32 addr, u16 len, + u8 *pdata); u8(*read8_sync) (struct rtl_priv *rtlpriv, u32 addr); u16(*read16_sync) (struct rtl_priv *rtlpriv, u32 addr); u32(*read32_sync) (struct rtl_priv *rtlpriv, u32 addr); + int (*readN_sync) (struct rtl_priv *rtlpriv, u32 addr, u16 len, + u8 *pdata); }; diff --git a/trunk/drivers/net/wireless/wl1251/main.c b/trunk/drivers/net/wireless/wl1251/main.c index ba3268ea81fe..a14a48c99cdc 100644 --- a/trunk/drivers/net/wireless/wl1251/main.c +++ b/trunk/drivers/net/wireless/wl1251/main.c @@ -1158,8 +1158,7 @@ static struct ieee80211_channel wl1251_channels[] = { { .hw_value = 13, .center_freq = 2472}, }; -static int wl1251_op_conf_tx(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, u16 queue, +static int wl1251_op_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params) { enum wl1251_acx_ps_scheme ps_scheme; diff --git a/trunk/drivers/net/wireless/wl12xx/Makefile b/trunk/drivers/net/wireless/wl12xx/Makefile index 621b3483ca2c..521c0414e52e 100644 --- a/trunk/drivers/net/wireless/wl12xx/Makefile +++ b/trunk/drivers/net/wireless/wl12xx/Makefile @@ -1,16 +1,16 @@ wl12xx-objs = main.o cmd.o io.o event.o tx.o rx.o ps.o acx.o \ boot.o init.o debugfs.o scan.o -wl12xx_spi-objs = spi.o +wl12xx_spi-objs = spi.o wl12xx_sdio-objs = sdio.o -wl12xx_sdio_test-objs = sdio_test.o +wl12xx_sdio_test-objs = sdio_test.o wl12xx-$(CONFIG_NL80211_TESTMODE) += testmode.o obj-$(CONFIG_WL12XX) += wl12xx.o obj-$(CONFIG_WL12XX_SPI) += wl12xx_spi.o obj-$(CONFIG_WL12XX_SDIO) += wl12xx_sdio.o -obj-$(CONFIG_WL12XX_SDIO_TEST) += wl12xx_sdio_test.o +obj-$(CONFIG_WL12XX_SDIO_TEST) += wl12xx_sdio_test.o # small builtin driver bit obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx_platform_data.o diff --git a/trunk/drivers/net/wireless/wl12xx/cmd.c b/trunk/drivers/net/wireless/wl12xx/cmd.c index 287fe95ecb40..084262f169b2 100644 --- a/trunk/drivers/net/wireless/wl12xx/cmd.c +++ b/trunk/drivers/net/wireless/wl12xx/cmd.c @@ -661,9 +661,12 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl) wl1271_debug(DEBUG_CMD, "cmd role start ap %d", wl->role_id); - /* trying to use hidden SSID with an old hostapd version */ - if (wl->ssid_len == 0 && !bss_conf->hidden_ssid) { - wl1271_error("got a null SSID from beacon/bss"); + /* + * We currently do not support hidden SSID. The real SSID + * should be fetched from mac80211 first. + */ + if (wl->ssid_len == 0) { + wl1271_warning("Hidden SSID currently not supported for AP"); ret = -EINVAL; goto out; } @@ -692,18 +695,9 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl) cmd->ap.dtim_interval = bss_conf->dtim_period; cmd->ap.beacon_expiry = WL1271_AP_DEF_BEACON_EXP; cmd->channel = wl->channel; - - if (!bss_conf->hidden_ssid) { - /* take the SSID from the beacon for backward compatibility */ - cmd->ap.ssid_type = WL12XX_SSID_TYPE_PUBLIC; - cmd->ap.ssid_len = wl->ssid_len; - memcpy(cmd->ap.ssid, wl->ssid, wl->ssid_len); - } else { - cmd->ap.ssid_type = WL12XX_SSID_TYPE_HIDDEN; - cmd->ap.ssid_len = bss_conf->ssid_len; - memcpy(cmd->ap.ssid, bss_conf->ssid, bss_conf->ssid_len); - } - + cmd->ap.ssid_len = wl->ssid_len; + cmd->ap.ssid_type = WL12XX_SSID_TYPE_PUBLIC; + memcpy(cmd->ap.ssid, wl->ssid, wl->ssid_len); cmd->ap.local_rates = cpu_to_le32(0xffffffff); switch (wl->band) { @@ -1112,7 +1106,6 @@ int wl1271_cmd_build_probe_req(struct wl1271 *wl, { struct sk_buff *skb; int ret; - u32 rate; skb = ieee80211_probereq_get(wl->hw, wl->vif, ssid, ssid_len, ie, ie_len); @@ -1123,13 +1116,14 @@ int wl1271_cmd_build_probe_req(struct wl1271 *wl, wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", skb->data, skb->len); - rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]); if (band == IEEE80211_BAND_2GHZ) ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, - skb->data, skb->len, 0, rate); + skb->data, skb->len, 0, + wl->conf.tx.basic_rate); else ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, - skb->data, skb->len, 0, rate); + skb->data, skb->len, 0, + wl->conf.tx.basic_rate_5); out: dev_kfree_skb(skb); @@ -1140,7 +1134,6 @@ struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, struct sk_buff *skb) { int ret; - u32 rate; if (!skb) skb = ieee80211_ap_probereq_get(wl->hw, wl->vif); @@ -1149,13 +1142,14 @@ struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, wl1271_dump(DEBUG_SCAN, "AP PROBE REQ: ", skb->data, skb->len); - rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[wl->band]); if (wl->band == IEEE80211_BAND_2GHZ) ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, - skb->data, skb->len, 0, rate); + skb->data, skb->len, 0, + wl->conf.tx.basic_rate); else ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, - skb->data, skb->len, 0, rate); + skb->data, skb->len, 0, + wl->conf.tx.basic_rate_5); if (ret < 0) wl1271_error("Unable to set ap probe request template."); @@ -1448,8 +1442,7 @@ int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid) sta_rates |= sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET; cmd->supported_rates = - cpu_to_le32(wl1271_tx_enabled_rates_get(wl, sta_rates, - wl->band)); + cpu_to_le32(wl1271_tx_enabled_rates_get(wl, sta_rates)); wl1271_debug(DEBUG_CMD, "new peer rates=0x%x queues=0x%x", cmd->supported_rates, sta->uapsd_queues); diff --git a/trunk/drivers/net/wireless/wl12xx/conf.h b/trunk/drivers/net/wireless/wl12xx/conf.h index 6a6805c3cc74..45428a21f9e2 100644 --- a/trunk/drivers/net/wireless/wl12xx/conf.h +++ b/trunk/drivers/net/wireless/wl12xx/conf.h @@ -454,10 +454,12 @@ struct conf_rx_settings { #define CONF_TX_AP_DEFAULT_MGMT_RATES (CONF_HW_BIT_RATE_1MBPS | \ CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS) -/* default rates for working as IBSS (11b and OFDM) */ +/* + * Default rates for working as IBSS. use 11b rates + */ #define CONF_TX_IBSS_DEFAULT_RATES (CONF_HW_BIT_RATE_1MBPS | \ CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS | \ - CONF_HW_BIT_RATE_11MBPS | CONF_TX_OFDM_RATES); + CONF_HW_BIT_RATE_11MBPS); struct conf_tx_rate_class { diff --git a/trunk/drivers/net/wireless/wl12xx/event.c b/trunk/drivers/net/wireless/wl12xx/event.c index e66db69f8d17..c73fe4c6b616 100644 --- a/trunk/drivers/net/wireless/wl12xx/event.c +++ b/trunk/drivers/net/wireless/wl12xx/event.c @@ -181,7 +181,7 @@ static void wl1271_stop_ba_event(struct wl1271 *wl) } else { int i; struct wl1271_link *lnk; - for (i = WL1271_AP_STA_HLID_START; i < AP_MAX_LINKS; i++) { + for (i = WL1271_AP_STA_HLID_START; i < WL12XX_MAX_LINKS; i++) { lnk = &wl->links[i]; if (!wl1271_is_active_sta(wl, i) || !lnk->ba_bitmap) continue; diff --git a/trunk/drivers/net/wireless/wl12xx/init.c b/trunk/drivers/net/wireless/wl12xx/init.c index 04db64c94e9a..09515f5e5e1d 100644 --- a/trunk/drivers/net/wireless/wl12xx/init.c +++ b/trunk/drivers/net/wireless/wl12xx/init.c @@ -103,7 +103,6 @@ static int wl1271_ap_init_deauth_template(struct wl1271 *wl) { struct wl12xx_disconn_template *tmpl; int ret; - u32 rate; tmpl = kzalloc(sizeof(*tmpl), GFP_KERNEL); if (!tmpl) { @@ -114,9 +113,9 @@ static int wl1271_ap_init_deauth_template(struct wl1271 *wl) tmpl->header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH); - rate = wl1271_tx_min_rate_get(wl, wl->basic_rate_set); ret = wl1271_cmd_template_set(wl, CMD_TEMPL_DEAUTH_AP, - tmpl, sizeof(*tmpl), 0, rate); + tmpl, sizeof(*tmpl), 0, + wl1271_tx_min_rate_get(wl)); out: kfree(tmpl); @@ -127,7 +126,6 @@ static int wl1271_ap_init_null_template(struct wl1271 *wl) { struct ieee80211_hdr_3addr *nullfunc; int ret; - u32 rate; nullfunc = kzalloc(sizeof(*nullfunc), GFP_KERNEL); if (!nullfunc) { @@ -144,9 +142,9 @@ static int wl1271_ap_init_null_template(struct wl1271 *wl) memcpy(nullfunc->addr2, wl->mac_addr, ETH_ALEN); memcpy(nullfunc->addr3, wl->mac_addr, ETH_ALEN); - rate = wl1271_tx_min_rate_get(wl, wl->basic_rate_set); ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, nullfunc, - sizeof(*nullfunc), 0, rate); + sizeof(*nullfunc), 0, + wl1271_tx_min_rate_get(wl)); out: kfree(nullfunc); @@ -157,7 +155,6 @@ static int wl1271_ap_init_qos_null_template(struct wl1271 *wl) { struct ieee80211_qos_hdr *qosnull; int ret; - u32 rate; qosnull = kzalloc(sizeof(*qosnull), GFP_KERNEL); if (!qosnull) { @@ -174,9 +171,9 @@ static int wl1271_ap_init_qos_null_template(struct wl1271 *wl) memcpy(qosnull->addr2, wl->mac_addr, ETH_ALEN); memcpy(qosnull->addr3, wl->mac_addr, ETH_ALEN); - rate = wl1271_tx_min_rate_get(wl, wl->basic_rate_set); ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, qosnull, - sizeof(*qosnull), 0, rate); + sizeof(*qosnull), 0, + wl1271_tx_min_rate_get(wl)); out: kfree(qosnull); @@ -501,7 +498,7 @@ int wl1271_init_ap_rates(struct wl1271 *wl) return ret; /* use the min basic rate for AP broadcast/multicast */ - rc.enabled_rates = wl1271_tx_min_rate_get(wl, wl->basic_rate_set); + rc.enabled_rates = wl1271_tx_min_rate_get(wl); rc.short_retry_limit = 10; rc.long_retry_limit = 10; rc.aflags = 0; diff --git a/trunk/drivers/net/wireless/wl12xx/main.c b/trunk/drivers/net/wireless/wl12xx/main.c index e2d6edd2fcd2..680f5582618e 100644 --- a/trunk/drivers/net/wireless/wl12xx/main.c +++ b/trunk/drivers/net/wireless/wl12xx/main.c @@ -2099,8 +2099,6 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, wl->time_offset = 0; wl->session_counter = 0; wl->rate_set = CONF_TX_RATE_MASK_BASIC; - wl->bitrate_masks[IEEE80211_BAND_2GHZ] = wl->conf.tx.basic_rate; - wl->bitrate_masks[IEEE80211_BAND_5GHZ] = wl->conf.tx.basic_rate_5; wl->vif = NULL; wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT; wl1271_free_ap_keys(wl); @@ -2239,8 +2237,14 @@ static int wl1271_unjoin(struct wl1271 *wl) static void wl1271_set_band_rate(struct wl1271 *wl) { - wl->basic_rate_set = wl->bitrate_masks[wl->band]; - wl->rate_set = wl->basic_rate_set; + if (wl->band == IEEE80211_BAND_2GHZ) { + wl->basic_rate_set = wl->conf.tx.basic_rate; + wl->rate_set = wl->conf.tx.basic_rate; + } else { + wl->basic_rate_set = wl->conf.tx.basic_rate_5; + wl->rate_set = wl->conf.tx.basic_rate_5; + } + } static bool wl12xx_is_roc(struct wl1271 *wl) @@ -2269,7 +2273,7 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, bool idle) if (ret < 0) goto out; } - wl->rate_set = wl1271_tx_min_rate_get(wl, wl->basic_rate_set); + wl->rate_set = wl1271_tx_min_rate_get(wl); ret = wl1271_acx_sta_rate_policies(wl); if (ret < 0) goto out; @@ -2351,8 +2355,6 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) if (changed & IEEE80211_CONF_CHANGE_CHANNEL && ((wl->band != conf->channel->band) || (wl->channel != channel))) { - /* send all pending packets */ - wl1271_tx_work_locked(wl); wl->band = conf->channel->band; wl->channel = channel; @@ -2366,8 +2368,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) wl1271_set_band_rate(wl); - wl->basic_rate = - wl1271_tx_min_rate_get(wl, wl->basic_rate_set); + wl->basic_rate = wl1271_tx_min_rate_get(wl); ret = wl1271_acx_sta_rate_policies(wl); if (ret < 0) wl1271_warning("rate policy for channel " @@ -3068,93 +3069,6 @@ static int wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *skb, return 0; } -static void wl12xx_remove_ie(struct sk_buff *skb, u8 eid, int ieoffset) -{ - int len; - const u8 *next, *end = skb->data + skb->len; - u8 *ie = (u8 *)cfg80211_find_ie(eid, skb->data + ieoffset, - skb->len - ieoffset); - if (!ie) - return; - len = ie[1] + 2; - next = ie + len; - memmove(ie, next, end - next); - skb_trim(skb, skb->len - len); -} - -static void wl12xx_remove_vendor_ie(struct sk_buff *skb, - unsigned int oui, u8 oui_type, - int ieoffset) -{ - int len; - const u8 *next, *end = skb->data + skb->len; - u8 *ie = (u8 *)cfg80211_find_vendor_ie(oui, oui_type, - skb->data + ieoffset, - skb->len - ieoffset); - if (!ie) - return; - len = ie[1] + 2; - next = ie + len; - memmove(ie, next, end - next); - skb_trim(skb, skb->len - len); -} - -static int wl1271_ap_set_probe_resp_tmpl(struct wl1271 *wl, - u8 *probe_rsp_data, - size_t probe_rsp_len, - u32 rates) -{ - struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf; - u8 probe_rsp_templ[WL1271_CMD_TEMPL_MAX_SIZE]; - int ssid_ie_offset, ie_offset, templ_len; - const u8 *ptr; - - /* no need to change probe response if the SSID is set correctly */ - if (wl->ssid_len > 0) - return wl1271_cmd_template_set(wl, - CMD_TEMPL_AP_PROBE_RESPONSE, - probe_rsp_data, - probe_rsp_len, 0, - rates); - - if (probe_rsp_len + bss_conf->ssid_len > WL1271_CMD_TEMPL_MAX_SIZE) { - wl1271_error("probe_rsp template too big"); - return -EINVAL; - } - - /* start searching from IE offset */ - ie_offset = offsetof(struct ieee80211_mgmt, u.probe_resp.variable); - - ptr = cfg80211_find_ie(WLAN_EID_SSID, probe_rsp_data + ie_offset, - probe_rsp_len - ie_offset); - if (!ptr) { - wl1271_error("No SSID in beacon!"); - return -EINVAL; - } - - ssid_ie_offset = ptr - probe_rsp_data; - ptr += (ptr[1] + 2); - - memcpy(probe_rsp_templ, probe_rsp_data, ssid_ie_offset); - - /* insert SSID from bss_conf */ - probe_rsp_templ[ssid_ie_offset] = WLAN_EID_SSID; - probe_rsp_templ[ssid_ie_offset + 1] = bss_conf->ssid_len; - memcpy(probe_rsp_templ + ssid_ie_offset + 2, - bss_conf->ssid, bss_conf->ssid_len); - templ_len = ssid_ie_offset + 2 + bss_conf->ssid_len; - - memcpy(probe_rsp_templ + ssid_ie_offset + 2 + bss_conf->ssid_len, - ptr, probe_rsp_len - (ptr - probe_rsp_data)); - templ_len += probe_rsp_len - (ptr - probe_rsp_data); - - return wl1271_cmd_template_set(wl, - CMD_TEMPL_AP_PROBE_RESPONSE, - probe_rsp_templ, - templ_len, 0, - rates); -} - static int wl1271_bss_erp_info_changed(struct wl1271 *wl, struct ieee80211_bss_conf *bss_conf, u32 changed) @@ -3211,7 +3125,6 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, if ((changed & BSS_CHANGED_BEACON)) { struct ieee80211_hdr *hdr; - u32 min_rate; int ieoffset = offsetof(struct ieee80211_mgmt, u.beacon.variable); struct sk_buff *beacon = ieee80211_beacon_get(wl->hw, vif); @@ -3227,46 +3140,28 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, dev_kfree_skb(beacon); goto out; } - min_rate = wl1271_tx_min_rate_get(wl, wl->basic_rate_set); tmpl_id = is_ap ? CMD_TEMPL_AP_BEACON : CMD_TEMPL_BEACON; ret = wl1271_cmd_template_set(wl, tmpl_id, beacon->data, beacon->len, 0, - min_rate); + wl1271_tx_min_rate_get(wl)); if (ret < 0) { dev_kfree_skb(beacon); goto out; } - /* remove TIM ie from probe response */ - wl12xx_remove_ie(beacon, WLAN_EID_TIM, ieoffset); - - /* - * remove p2p ie from probe response. - * the fw reponds to probe requests that don't include - * the p2p ie. probe requests with p2p ie will be passed, - * and will be responded by the supplicant (the spec - * forbids including the p2p ie when responding to probe - * requests that didn't include it). - */ - wl12xx_remove_vendor_ie(beacon, WLAN_OUI_WFA, - WLAN_OUI_TYPE_WFA_P2P, ieoffset); - hdr = (struct ieee80211_hdr *) beacon->data; hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP); - if (is_ap) - ret = wl1271_ap_set_probe_resp_tmpl(wl, - beacon->data, - beacon->len, - min_rate); - else - ret = wl1271_cmd_template_set(wl, - CMD_TEMPL_PROBE_RESPONSE, - beacon->data, - beacon->len, 0, - min_rate); + + tmpl_id = is_ap ? CMD_TEMPL_AP_PROBE_RESPONSE : + CMD_TEMPL_PROBE_RESPONSE; + ret = wl1271_cmd_template_set(wl, + tmpl_id, + beacon->data, + beacon->len, 0, + wl1271_tx_min_rate_get(wl)); dev_kfree_skb(beacon); if (ret < 0) goto out; @@ -3287,10 +3182,8 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl, if ((changed & BSS_CHANGED_BASIC_RATES)) { u32 rates = bss_conf->basic_rates; - wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates, - wl->band); - wl->basic_rate = wl1271_tx_min_rate_get(wl, - wl->basic_rate_set); + wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates); + wl->basic_rate = wl1271_tx_min_rate_get(wl); ret = wl1271_init_ap_rates(wl); if (ret < 0) { @@ -3472,15 +3365,12 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, * to use with control frames. */ rates = bss_conf->basic_rates; - wl->basic_rate_set = - wl1271_tx_enabled_rates_get(wl, rates, - wl->band); - wl->basic_rate = - wl1271_tx_min_rate_get(wl, wl->basic_rate_set); + wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, + rates); + wl->basic_rate = wl1271_tx_min_rate_get(wl); if (sta_rate_set) wl->rate_set = wl1271_tx_enabled_rates_get(wl, - sta_rate_set, - wl->band); + sta_rate_set); ret = wl1271_acx_sta_rate_policies(wl); if (ret < 0) goto out; @@ -3527,8 +3417,7 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, /* revert back to minimum rates for the current band */ wl1271_set_band_rate(wl); - wl->basic_rate = - wl1271_tx_min_rate_get(wl, wl->basic_rate_set); + wl->basic_rate = wl1271_tx_min_rate_get(wl); ret = wl1271_acx_sta_rate_policies(wl); if (ret < 0) goto out; @@ -3579,13 +3468,11 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, if (bss_conf->ibss_joined) { u32 rates = bss_conf->basic_rates; - wl->basic_rate_set = - wl1271_tx_enabled_rates_get(wl, rates, - wl->band); - wl->basic_rate = - wl1271_tx_min_rate_get(wl, wl->basic_rate_set); + wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, + rates); + wl->basic_rate = wl1271_tx_min_rate_get(wl); - /* by default, use 11b + OFDM rates */ + /* by default, use 11b rates */ wl->rate_set = CONF_TX_IBSS_DEFAULT_RATES; ret = wl1271_acx_sta_rate_policies(wl); if (ret < 0) @@ -3744,8 +3631,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, mutex_unlock(&wl->mutex); } -static int wl1271_op_conf_tx(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, u16 queue, +static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params) { struct wl1271 *wl = hw->priv; @@ -3816,8 +3702,7 @@ static int wl1271_op_conf_tx(struct ieee80211_hw *hw, return ret; } -static u64 wl1271_op_get_tsf(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) +static u64 wl1271_op_get_tsf(struct ieee80211_hw *hw) { struct wl1271 *wl = hw->priv; @@ -4107,29 +3992,6 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, return ret; } -static int wl12xx_set_bitrate_mask(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - const struct cfg80211_bitrate_mask *mask) -{ - struct wl1271 *wl = hw->priv; - int i; - - wl1271_debug(DEBUG_MAC80211, "mac80211 set_bitrate_mask 0x%x 0x%x", - mask->control[NL80211_BAND_2GHZ].legacy, - mask->control[NL80211_BAND_5GHZ].legacy); - - mutex_lock(&wl->mutex); - - for (i = 0; i < IEEE80211_NUM_BANDS; i++) - wl->bitrate_masks[i] = - wl1271_tx_enabled_rates_get(wl, - mask->control[i].legacy, - i); - mutex_unlock(&wl->mutex); - - return 0; -} - static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw) { struct wl1271 *wl = hw->priv; @@ -4405,7 +4267,6 @@ static const struct ieee80211_ops wl1271_ops = { .sta_remove = wl1271_op_sta_remove, .ampdu_action = wl1271_op_ampdu_action, .tx_frames_pending = wl1271_tx_frames_pending, - .set_bitrate_mask = wl12xx_set_bitrate_mask, CFG80211_TESTMODE_CMD(wl1271_tm_cmd) }; @@ -4724,8 +4585,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void) int i, j, ret; unsigned int order; - BUILD_BUG_ON(AP_MAX_LINKS > WL12XX_MAX_LINKS); - hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); if (!hw) { wl1271_error("could not alloc ieee80211_hw"); @@ -4828,8 +4687,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void) /* Apply default driver configuration. */ wl1271_conf_init(wl); - wl->bitrate_masks[IEEE80211_BAND_2GHZ] = wl->conf.tx.basic_rate; - wl->bitrate_masks[IEEE80211_BAND_5GHZ] = wl->conf.tx.basic_rate_5; order = get_order(WL1271_AGGR_BUFFER_SIZE); wl->aggr_buf = (u8 *)__get_free_pages(GFP_KERNEL, order); diff --git a/trunk/drivers/net/wireless/wl12xx/scan.c b/trunk/drivers/net/wireless/wl12xx/scan.c index 128ccb79318c..eeccc9f095bb 100644 --- a/trunk/drivers/net/wireless/wl12xx/scan.c +++ b/trunk/drivers/net/wireless/wl12xx/scan.c @@ -28,7 +28,6 @@ #include "scan.h" #include "acx.h" #include "ps.h" -#include "tx.h" void wl1271_scan_complete_work(struct work_struct *work) { @@ -100,18 +99,14 @@ static int wl1271_get_scan_channels(struct wl1271 *wl, for (i = 0, j = 0; i < req->n_channels && j < WL1271_SCAN_MAX_CHANNELS; i++) { + flags = req->channels[i]->flags; if (!test_bit(i, wl->scan.scanned_ch) && !(flags & IEEE80211_CHAN_DISABLED) && - (req->channels[i]->band == band) && - /* - * In passive scans, we scan all remaining - * channels, even if not marked as such. - * In active scans, we only scan channels not - * marked as passive. - */ - (passive || !(flags & IEEE80211_CHAN_PASSIVE_SCAN))) { + ((!!(flags & IEEE80211_CHAN_PASSIVE_SCAN)) == passive) && + (req->channels[i]->band == band)) { + wl1271_debug(DEBUG_SCAN, "band %d, center_freq %d ", req->channels[i]->band, req->channels[i]->center_freq); @@ -163,10 +158,6 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band, int ret; u16 scan_options = 0; - /* skip active scans if we don't have SSIDs */ - if (!passive && wl->scan.req->n_ssids == 0) - return WL1271_NOTHING_TO_SCAN; - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); trigger = kzalloc(sizeof(*trigger), GFP_KERNEL); if (!cmd || !trigger) { @@ -174,7 +165,8 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band, goto out; } - if (passive) + /* No SSIDs means that we have a forced passive scan */ + if (passive || wl->scan.req->n_ssids == 0) scan_options |= WL1271_SCAN_OPT_PASSIVE; if (WARN_ON(wl->role_id == WL12XX_INVALID_ROLE_ID)) { @@ -244,17 +236,14 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band, void wl1271_scan_stm(struct wl1271 *wl) { int ret = 0; - enum ieee80211_band band; - u32 rate; switch (wl->scan.state) { case WL1271_SCAN_STATE_IDLE: break; case WL1271_SCAN_STATE_2GHZ_ACTIVE: - band = IEEE80211_BAND_2GHZ; - rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]); - ret = wl1271_scan_send(wl, band, false, rate); + ret = wl1271_scan_send(wl, IEEE80211_BAND_2GHZ, false, + wl->conf.tx.basic_rate); if (ret == WL1271_NOTHING_TO_SCAN) { wl->scan.state = WL1271_SCAN_STATE_2GHZ_PASSIVE; wl1271_scan_stm(wl); @@ -263,9 +252,8 @@ void wl1271_scan_stm(struct wl1271 *wl) break; case WL1271_SCAN_STATE_2GHZ_PASSIVE: - band = IEEE80211_BAND_2GHZ; - rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]); - ret = wl1271_scan_send(wl, band, true, rate); + ret = wl1271_scan_send(wl, IEEE80211_BAND_2GHZ, true, + wl->conf.tx.basic_rate); if (ret == WL1271_NOTHING_TO_SCAN) { if (wl->enable_11a) wl->scan.state = WL1271_SCAN_STATE_5GHZ_ACTIVE; @@ -277,9 +265,8 @@ void wl1271_scan_stm(struct wl1271 *wl) break; case WL1271_SCAN_STATE_5GHZ_ACTIVE: - band = IEEE80211_BAND_5GHZ; - rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]); - ret = wl1271_scan_send(wl, band, false, rate); + ret = wl1271_scan_send(wl, IEEE80211_BAND_5GHZ, false, + wl->conf.tx.basic_rate_5); if (ret == WL1271_NOTHING_TO_SCAN) { wl->scan.state = WL1271_SCAN_STATE_5GHZ_PASSIVE; wl1271_scan_stm(wl); @@ -288,9 +275,8 @@ void wl1271_scan_stm(struct wl1271 *wl) break; case WL1271_SCAN_STATE_5GHZ_PASSIVE: - band = IEEE80211_BAND_5GHZ; - rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]); - ret = wl1271_scan_send(wl, band, true, rate); + ret = wl1271_scan_send(wl, IEEE80211_BAND_5GHZ, true, + wl->conf.tx.basic_rate_5); if (ret == WL1271_NOTHING_TO_SCAN) { wl->scan.state = WL1271_SCAN_STATE_DONE; wl1271_scan_stm(wl); diff --git a/trunk/drivers/net/wireless/wl12xx/sdio_test.c b/trunk/drivers/net/wireless/wl12xx/sdio_test.c index f25d5d9212e7..c3610492852e 100644 --- a/trunk/drivers/net/wireless/wl12xx/sdio_test.c +++ b/trunk/drivers/net/wireless/wl12xx/sdio_test.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -143,23 +142,14 @@ static int wl1271_sdio_set_power(struct wl1271 *wl, bool enable) ret = pm_runtime_get_sync(&func->dev); if (ret < 0) goto out; - - /* Runtime PM might be disabled, power up the card manually */ - ret = mmc_power_restore_host(func->card->host); - if (ret < 0) - goto out; - sdio_claim_host(func); sdio_enable_func(func); + sdio_release_host(func); } else { + sdio_claim_host(func); sdio_disable_func(func); sdio_release_host(func); - /* Runtime PM might be disabled, power off the card manually */ - ret = mmc_power_save_host(func->card->host); - if (ret < 0) - goto out; - /* Power down the card */ ret = pm_runtime_put_sync(&func->dev); } @@ -443,6 +433,7 @@ static int __devinit wl1271_probe(struct sdio_func *func, sdio_set_drvdata(func, wl_test); + /* power up the device */ ret = wl1271_chip_wakeup(wl); if (ret) { diff --git a/trunk/drivers/net/wireless/wl12xx/tx.c b/trunk/drivers/net/wireless/wl12xx/tx.c index bad9e29d49b0..9d4157ce0950 100644 --- a/trunk/drivers/net/wireless/wl12xx/tx.c +++ b/trunk/drivers/net/wireless/wl12xx/tx.c @@ -81,7 +81,8 @@ static int wl1271_tx_update_filters(struct wl1271 *wl, struct ieee80211_hdr *hdr; int ret; - hdr = (struct ieee80211_hdr *)skb->data; + hdr = (struct ieee80211_hdr *)(skb->data + + sizeof(struct wl1271_tx_hw_descr)); /* * stop bssid-based filtering before transmitting authentication @@ -180,20 +181,14 @@ u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct sk_buff *skb) static u8 wl1271_tx_get_hlid(struct wl1271 *wl, struct sk_buff *skb) { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - if (wl12xx_is_dummy_packet(wl, skb)) return wl->system_hlid; if (wl->bss_type == BSS_TYPE_AP_BSS) return wl12xx_tx_get_hlid_ap(wl, skb); - wl1271_tx_update_filters(wl, skb); - - if ((test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) || - test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags)) && - !ieee80211_is_auth(hdr->frame_control) && - !ieee80211_is_assoc_req(hdr->frame_control)) + if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) || + test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags)) return wl->sta_hlid; else return wl->dev_hlid; @@ -428,6 +423,8 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb, if (wl->bss_type == BSS_TYPE_AP_BSS) { wl1271_tx_ap_update_inconnection_sta(wl, skb); wl1271_tx_regulate_link(wl, hlid); + } else { + wl1271_tx_update_filters(wl, skb); } /* @@ -450,14 +447,13 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb, return total_len; } -u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set, - enum ieee80211_band rate_band) +u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set) { struct ieee80211_supported_band *band; u32 enabled_rates = 0; int bit; - band = wl->hw->wiphy->bands[rate_band]; + band = wl->hw->wiphy->bands[wl->band]; for (bit = 0; bit < band->n_bitrates; bit++) { if (rate_set & 0x1) enabled_rates |= band->bitrates[bit].hw_value; @@ -990,10 +986,20 @@ void wl1271_tx_flush(struct wl1271 *wl) wl1271_warning("Unable to flush all TX buffers, timed out."); } -u32 wl1271_tx_min_rate_get(struct wl1271 *wl, u32 rate_set) +u32 wl1271_tx_min_rate_get(struct wl1271 *wl) { - if (WARN_ON(!rate_set)) - return 0; + int i; + u32 rate = 0; + + if (!wl->basic_rate_set) { + WARN_ON(1); + wl->basic_rate_set = wl->conf.tx.basic_rate; + } + + for (i = 0; !rate; i++) { + if ((wl->basic_rate_set >> i) & 0x1) + rate = 1 << i; + } - return BIT(__ffs(rate_set)); + return rate; } diff --git a/trunk/drivers/net/wireless/wl12xx/tx.h b/trunk/drivers/net/wireless/wl12xx/tx.h index dc4f09adf088..d6fdbf904a09 100644 --- a/trunk/drivers/net/wireless/wl12xx/tx.h +++ b/trunk/drivers/net/wireless/wl12xx/tx.h @@ -209,9 +209,8 @@ void wl1271_tx_complete(struct wl1271 *wl); void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues); void wl1271_tx_flush(struct wl1271 *wl); u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); -u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set, - enum ieee80211_band rate_band); -u32 wl1271_tx_min_rate_get(struct wl1271 *wl, u32 rate_set); +u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set); +u32 wl1271_tx_min_rate_get(struct wl1271 *wl); u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct sk_buff *skb); void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid); void wl1271_handle_tx_low_watermark(struct wl1271 *wl); diff --git a/trunk/drivers/net/wireless/wl12xx/wl12xx.h b/trunk/drivers/net/wireless/wl12xx/wl12xx.h index 997f53245011..3ceb20c170bc 100644 --- a/trunk/drivers/net/wireless/wl12xx/wl12xx.h +++ b/trunk/drivers/net/wireless/wl12xx/wl12xx.h @@ -138,7 +138,7 @@ extern u32 wl12xx_debug_level; #define WL1271_DEFAULT_DTIM_PERIOD 1 #define WL12XX_MAX_ROLES 4 -#define WL12XX_MAX_LINKS 12 +#define WL12XX_MAX_LINKS 8 #define WL12XX_INVALID_ROLE_ID 0xff #define WL12XX_INVALID_LINK_ID 0xff @@ -279,7 +279,7 @@ struct wl12xx_fw_status { /* Cumulative counter of released Voice memory blocks */ u8 tx_voice_released_blks; - u8 padding_1[3]; + u8 padding_1[7]; __le32 log_start_addr; } __packed; @@ -526,7 +526,6 @@ struct wl1271 { u32 basic_rate_set; u32 basic_rate; u32 rate_set; - u32 bitrate_masks[IEEE80211_NUM_BANDS]; /* The current band */ enum ieee80211_band band; diff --git a/trunk/drivers/net/wireless/wl3501_cs.c b/trunk/drivers/net/wireless/wl3501_cs.c index 98fbf54f6004..6bc7c92fbff7 100644 --- a/trunk/drivers/net/wireless/wl3501_cs.c +++ b/trunk/drivers/net/wireless/wl3501_cs.c @@ -1781,7 +1781,7 @@ static int wl3501_get_encode(struct net_device *dev, keys, len_keys); if (rc) goto out; - tocopy = min_t(u16, len_keys, wrqu->encoding.length); + tocopy = min_t(u8, len_keys, wrqu->encoding.length); tocopy = min_t(u8, tocopy, 100); wrqu->encoding.length = tocopy; memcpy(extra, keys, tocopy); diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_mac.c b/trunk/drivers/net/wireless/zd1211rw/zd_mac.c index 0a70149df3fc..cabfae1e70b1 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/trunk/drivers/net/wireless/zd1211rw/zd_mac.c @@ -1332,7 +1332,7 @@ static void zd_op_bss_info_changed(struct ieee80211_hw *hw, } } -static u64 zd_op_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +static u64 zd_op_get_tsf(struct ieee80211_hw *hw) { struct zd_mac *mac = zd_hw_mac(hw); return zd_chip_get_tsf(&mac->chip); diff --git a/trunk/drivers/nfc/Kconfig b/trunk/drivers/nfc/Kconfig index 5af959274d4e..8a56fd3da989 100644 --- a/trunk/drivers/nfc/Kconfig +++ b/trunk/drivers/nfc/Kconfig @@ -29,7 +29,7 @@ config NFC_PN533 config NFC_WILINK tristate "Texas Instruments NFC WiLink driver" - depends on TI_ST && NFC_NCI + depends on TI_ST help This enables the NFC driver for Texas Instrument's BT/FM/GPS/NFC combo devices. This makes use of shared transport line discipline diff --git a/trunk/drivers/staging/brcm80211/brcmsmac/mac80211_if.c b/trunk/drivers/staging/brcm80211/brcmsmac/mac80211_if.c index 6d71cba3a0a5..d6de44e430d3 100644 --- a/trunk/drivers/staging/brcm80211/brcmsmac/mac80211_if.c +++ b/trunk/drivers/staging/brcm80211/brcmsmac/mac80211_if.c @@ -133,19 +133,16 @@ static int brcms_ops_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set); static void brcms_ops_sw_scan_start(struct ieee80211_hw *hw); static void brcms_ops_sw_scan_complete(struct ieee80211_hw *hw); -static void brcms_ops_set_tsf(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, u64 tsf); +static void brcms_ops_set_tsf(struct ieee80211_hw *hw, u64 tsf); static int brcms_ops_get_stats(struct ieee80211_hw *hw, struct ieee80211_low_level_stats *stats); static void brcms_ops_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum sta_notify_cmd cmd, struct ieee80211_sta *sta); -static int brcms_ops_conf_tx(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, u16 queue, - const struct ieee80211_tx_queue_params *params); -static u64 brcms_ops_get_tsf(struct ieee80211_hw *hw, - struct ieee80211_vif *vif); +static int brcms_ops_conf_tx(struct ieee80211_hw *hw, u16 queue, + const struct ieee80211_tx_queue_params *params); +static u64 brcms_ops_get_tsf(struct ieee80211_hw *hw); static int brcms_ops_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta); static int brcms_ops_sta_remove(struct ieee80211_hw *hw, @@ -519,8 +516,7 @@ static void brcms_ops_sw_scan_complete(struct ieee80211_hw *hw) return; } -static void brcms_ops_set_tsf(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, u64 tsf) +static void brcms_ops_set_tsf(struct ieee80211_hw *hw, u64 tsf) { wiphy_err(hw->wiphy, "%s: Enter\n", __func__); return; @@ -557,7 +553,7 @@ brcms_ops_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif, } static int -brcms_ops_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue, +brcms_ops_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params) { struct brcms_info *wl = hw->priv; @@ -569,8 +565,7 @@ brcms_ops_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue, return 0; } -static u64 brcms_ops_get_tsf(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) +static u64 brcms_ops_get_tsf(struct ieee80211_hw *hw) { wiphy_err(hw->wiphy, "%s: Enter\n", __func__); return 0; diff --git a/trunk/drivers/staging/winbond/wbusb.c b/trunk/drivers/staging/winbond/wbusb.c index a2e8bd452ed9..3724e1e67ec2 100644 --- a/trunk/drivers/staging/winbond/wbusb.c +++ b/trunk/drivers/staging/winbond/wbusb.c @@ -277,7 +277,7 @@ static int wbsoft_config(struct ieee80211_hw *dev, u32 changed) return 0; } -static u64 wbsoft_get_tsf(struct ieee80211_hw *dev, struct ieee80211_vif *vif) +static u64 wbsoft_get_tsf(struct ieee80211_hw *dev) { printk("wbsoft_get_tsf called\n"); return 0; diff --git a/trunk/include/linux/ieee80211.h b/trunk/include/linux/ieee80211.h index 48363c3c40f8..b5e0a5c344fd 100644 --- a/trunk/include/linux/ieee80211.h +++ b/trunk/include/linux/ieee80211.h @@ -759,12 +759,6 @@ struct ieee80211_mgmt { u8 action; u8 smps_control; } __attribute__ ((packed)) ht_smps; - struct { - u8 action_code; - u8 dialog_token; - __le16 capability; - u8 variable[0]; - } __packed tdls_discover_resp; } u; } __attribute__ ((packed)) action; } u; @@ -811,52 +805,6 @@ struct ieee80211_pspoll { u8 ta[6]; } __attribute__ ((packed)); -/* TDLS */ - -/* Link-id information element */ -struct ieee80211_tdls_lnkie { - u8 ie_type; /* Link Identifier IE */ - u8 ie_len; - u8 bssid[6]; - u8 init_sta[6]; - u8 resp_sta[6]; -} __packed; - -struct ieee80211_tdls_data { - u8 da[6]; - u8 sa[6]; - __be16 ether_type; - u8 payload_type; - u8 category; - u8 action_code; - union { - struct { - u8 dialog_token; - __le16 capability; - u8 variable[0]; - } __packed setup_req; - struct { - __le16 status_code; - u8 dialog_token; - __le16 capability; - u8 variable[0]; - } __packed setup_resp; - struct { - __le16 status_code; - u8 dialog_token; - u8 variable[0]; - } __packed setup_cfm; - struct { - __le16 reason_code; - u8 variable[0]; - } __packed teardown; - struct { - u8 dialog_token; - u8 variable[0]; - } __packed discover_req; - } u; -} __packed; - /** * struct ieee80211_bar - HT Block Ack Request * @@ -1248,8 +1196,6 @@ enum ieee80211_eid { WLAN_EID_TS_DELAY = 43, WLAN_EID_TCLAS_PROCESSING = 44, WLAN_EID_QOS_CAPA = 46, - /* 802.11z */ - WLAN_EID_LINK_ID = 101, /* 802.11s */ WLAN_EID_MESH_CONFIG = 113, WLAN_EID_MESH_ID = 114, @@ -1333,7 +1279,6 @@ enum ieee80211_category { WLAN_CATEGORY_HT = 7, WLAN_CATEGORY_SA_QUERY = 8, WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION = 9, - WLAN_CATEGORY_TDLS = 12, WLAN_CATEGORY_MESH_ACTION = 13, WLAN_CATEGORY_MULTIHOP_ACTION = 14, WLAN_CATEGORY_SELF_PROTECTED = 15, @@ -1397,36 +1342,6 @@ enum ieee80211_key_len { WLAN_KEY_LEN_AES_CMAC = 16, }; -/* Public action codes */ -enum ieee80211_pub_actioncode { - WLAN_PUB_ACTION_TDLS_DISCOVER_RES = 14, -}; - -/* TDLS action codes */ -enum ieee80211_tdls_actioncode { - WLAN_TDLS_SETUP_REQUEST = 0, - WLAN_TDLS_SETUP_RESPONSE = 1, - WLAN_TDLS_SETUP_CONFIRM = 2, - WLAN_TDLS_TEARDOWN = 3, - WLAN_TDLS_PEER_TRAFFIC_INDICATION = 4, - WLAN_TDLS_CHANNEL_SWITCH_REQUEST = 5, - WLAN_TDLS_CHANNEL_SWITCH_RESPONSE = 6, - WLAN_TDLS_PEER_PSM_REQUEST = 7, - WLAN_TDLS_PEER_PSM_RESPONSE = 8, - WLAN_TDLS_PEER_TRAFFIC_RESPONSE = 9, - WLAN_TDLS_DISCOVERY_REQUEST = 10, -}; - -/* - * TDLS capabililites to be enabled in the 5th byte of the - * @WLAN_EID_EXT_CAPABILITY information element - */ -#define WLAN_EXT_CAPA5_TDLS_ENABLED BIT(5) -#define WLAN_EXT_CAPA5_TDLS_PROHIBITED BIT(6) - -/* TDLS specific payload type in the LLC/SNAP header */ -#define WLAN_TDLS_SNAP_RFTYPE 0x2 - /** * enum - mesh path selection protocol identifier * diff --git a/trunk/include/linux/if_ether.h b/trunk/include/linux/if_ether.h index 49c38fc8dbc3..a3d99ff6e3b5 100644 --- a/trunk/include/linux/if_ether.h +++ b/trunk/include/linux/if_ether.h @@ -83,7 +83,6 @@ #define ETH_P_8021AH 0x88E7 /* 802.1ah Backbone Service Tag */ #define ETH_P_1588 0x88F7 /* IEEE 1588 Timesync */ #define ETH_P_FCOE 0x8906 /* Fibre Channel over Ethernet */ -#define ETH_P_TDLS 0x890D /* TDLS */ #define ETH_P_FIP 0x8914 /* FCoE Initialization Protocol */ #define ETH_P_QINQ1 0x9100 /* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */ #define ETH_P_QINQ2 0x9200 /* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */ diff --git a/trunk/include/linux/nl80211.h b/trunk/include/linux/nl80211.h index 9d797f253d8e..460b12a8ef66 100644 --- a/trunk/include/linux/nl80211.h +++ b/trunk/include/linux/nl80211.h @@ -238,8 +238,6 @@ * * @NL80211_CMD_GET_SCAN: get scan results * @NL80211_CMD_TRIGGER_SCAN: trigger a new scan with the given parameters - * %NL80211_ATTR_TX_NO_CCK_RATE is used to decide whether to send the - * probe requests at CCK rate or not. * @NL80211_CMD_NEW_SCAN_RESULTS: scan notification (as a reply to * NL80211_CMD_GET_SCAN and on the "scan" multicast group) * @NL80211_CMD_SCAN_ABORTED: scan was aborted, for unspecified reasons, @@ -434,8 +432,6 @@ * specified using %NL80211_ATTR_DURATION. When called, this operation * returns a cookie (%NL80211_ATTR_COOKIE) that will be included with the * TX status event pertaining to the TX request. - * %NL80211_ATTR_TX_NO_CCK_RATE is used to decide whether to send the - * management frames at CCK rate or not in 2GHz band. * @NL80211_CMD_FRAME_WAIT_CANCEL: When an off-channel TX was requested, this * command may be used with the corresponding cookie to cancel the wait * time if it is known that it is no longer necessary. @@ -506,9 +502,6 @@ * @NL80211_CMD_PMKSA_CANDIDATE: This is used as an event to inform userspace * of PMKSA caching dandidates. * - * @NL80211_CMD_TDLS_OPER: Perform a high-level TDLS command (e.g. link setup). - * @NL80211_CMD_TDLS_MGMT: Send a TDLS management frame. - * * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use */ @@ -635,9 +628,6 @@ enum nl80211_commands { NL80211_CMD_PMKSA_CANDIDATE, - NL80211_CMD_TDLS_OPER, - NL80211_CMD_TDLS_MGMT, - /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ @@ -1088,27 +1078,6 @@ enum nl80211_commands { * @NL80211_ATTR_PMKSA_CANDIDATE: Nested attribute containing the PMKSA caching * candidate information, see &enum nl80211_pmksa_candidate_attr. * - * @NL80211_ATTR_TX_NO_CCK_RATE: Indicates whether to use CCK rate or not - * for management frames transmission. In order to avoid p2p probe/action - * frames are being transmitted at CCK rate in 2GHz band, the user space - * applications use this attribute. - * This attribute is used with %NL80211_CMD_TRIGGER_SCAN and - * %NL80211_CMD_FRAME commands. - * - * @NL80211_ATTR_TDLS_ACTION: Low level TDLS action code (e.g. link setup - * request, link setup confirm, link teardown, etc.). Values are - * described in the TDLS (802.11z) specification. - * @NL80211_ATTR_TDLS_DIALOG_TOKEN: Non-zero token for uniquely identifying a - * TDLS conversation between two devices. - * @NL80211_ATTR_TDLS_OPERATION: High level TDLS operation; see - * &enum nl80211_tdls_operation, represented as a u8. - * @NL80211_ATTR_TDLS_SUPPORT: A flag indicating the device can operate - * as a TDLS peer sta. - * @NL80211_ATTR_TDLS_EXTERNAL_SETUP: The TDLS discovery/setup and teardown - * procedures should be performed by sending TDLS packets via - * %NL80211_CMD_TDLS_MGMT. Otherwise %NL80211_CMD_TDLS_OPER should be - * used for asking the driver to perform a TDLS operation. - * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */ @@ -1329,14 +1298,6 @@ enum nl80211_attrs { NL80211_ATTR_PMKSA_CANDIDATE, - NL80211_ATTR_TX_NO_CCK_RATE, - - NL80211_ATTR_TDLS_ACTION, - NL80211_ATTR_TDLS_DIALOG_TOKEN, - NL80211_ATTR_TDLS_OPERATION, - NL80211_ATTR_TDLS_SUPPORT, - NL80211_ATTR_TDLS_EXTERNAL_SETUP, - /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -1434,7 +1395,6 @@ enum nl80211_iftype { * @NL80211_STA_FLAG_WME: station is WME/QoS capable * @NL80211_STA_FLAG_MFP: station uses management frame protection * @NL80211_STA_FLAG_AUTHENTICATED: station is authenticated - * @NL80211_STA_FLAG_TDLS_PEER: station is a TDLS peer * @NL80211_STA_FLAG_MAX: highest station flag number currently defined * @__NL80211_STA_FLAG_AFTER_LAST: internal use */ @@ -1445,7 +1405,6 @@ enum nl80211_sta_flags { NL80211_STA_FLAG_WME, NL80211_STA_FLAG_MFP, NL80211_STA_FLAG_AUTHENTICATED, - NL80211_STA_FLAG_TDLS_PEER, /* keep last */ __NL80211_STA_FLAG_AFTER_LAST, @@ -2632,20 +2591,4 @@ enum nl80211_pmksa_candidate_attr { MAX_NL80211_PMKSA_CANDIDATE = NUM_NL80211_PMKSA_CANDIDATE - 1 }; -/** - * enum nl80211_tdls_operation - values for %NL80211_ATTR_TDLS_OPERATION - * @NL80211_TDLS_DISCOVERY_REQ: Send a TDLS discovery request - * @NL80211_TDLS_SETUP: Setup TDLS link - * @NL80211_TDLS_TEARDOWN: Teardown a TDLS link which is already established - * @NL80211_TDLS_ENABLE_LINK: Enable TDLS link - * @NL80211_TDLS_DISABLE_LINK: Disable TDLS link - */ -enum nl80211_tdls_operation { - NL80211_TDLS_DISCOVERY_REQ, - NL80211_TDLS_SETUP, - NL80211_TDLS_TEARDOWN, - NL80211_TDLS_ENABLE_LINK, - NL80211_TDLS_DISABLE_LINK, -}; - #endif /* __LINUX_NL80211_H */ diff --git a/trunk/include/linux/rfkill-gpio.h b/trunk/include/linux/rfkill-gpio.h index 4d09f6eab359..a175d0598033 100644 --- a/trunk/include/linux/rfkill-gpio.h +++ b/trunk/include/linux/rfkill-gpio.h @@ -30,8 +30,6 @@ * @reset_gpio: GPIO which is used for reseting rfkill switch * @shutdown_gpio: GPIO which is used for shutdown of rfkill switch * @power_clk_name: [optional] name of clk to turn off while blocked - * @gpio_runtime_close: clean up platform specific gpio configuration - * @gpio_runtime_setup: set up platform specific gpio configuration */ struct rfkill_gpio_platform_data { @@ -40,8 +38,6 @@ struct rfkill_gpio_platform_data { int shutdown_gpio; const char *power_clk_name; enum rfkill_type type; - void (*gpio_runtime_close)(struct platform_device *); - int (*gpio_runtime_setup)(struct platform_device *); }; #endif /* __RFKILL_GPIO_H */ diff --git a/trunk/include/net/cfg80211.h b/trunk/include/net/cfg80211.h index 74f4f85be32f..ccfdf3f63ce5 100644 --- a/trunk/include/net/cfg80211.h +++ b/trunk/include/net/cfg80211.h @@ -423,17 +423,6 @@ enum plink_actions { PLINK_ACTION_BLOCK, }; -/** - * enum station_parameters_apply_mask - station parameter values to apply - * @STATION_PARAM_APPLY_UAPSD: apply new uAPSD parameters (uapsd_queues, max_sp) - * - * Not all station parameters have in-band "no change" signalling, - * for those that don't these flags will are used. - */ -enum station_parameters_apply_mask { - STATION_PARAM_APPLY_UAPSD = BIT(0), -}; - /** * struct station_parameters - station parameters * @@ -461,7 +450,6 @@ struct station_parameters { u8 *supported_rates; struct net_device *vlan; u32 sta_flags_mask, sta_flags_set; - u32 sta_modify_mask; int listen_interval; u16 aid; u8 supported_rates_len; @@ -872,7 +860,6 @@ struct cfg80211_ssid { * @wiphy: the wiphy this was for * @dev: the interface * @aborted: (internal) scan request was notified as aborted - * @no_cck: used to send probe requests at non CCK rate in 2GHz band */ struct cfg80211_scan_request { struct cfg80211_ssid *ssids; @@ -887,7 +874,6 @@ struct cfg80211_scan_request { struct wiphy *wiphy; struct net_device *dev; bool aborted; - bool no_cck; /* keep last */ struct ieee80211_channel *channels[0]; @@ -1422,9 +1408,6 @@ struct cfg80211_gtk_rekey_data { * @set_ringparam: Set tx and rx ring sizes. * * @get_ringparam: Get tx and rx ring current and maximum sizes. - * - * @tdls_mgmt: Transmit a TDLS management frame. - * @tdls_oper: Perform a high-level TDLS operation (e.g. TDLS link setup). */ struct cfg80211_ops { int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow); @@ -1501,7 +1484,7 @@ struct cfg80211_ops { int (*change_bss)(struct wiphy *wiphy, struct net_device *dev, struct bss_parameters *params); - int (*set_txq_params)(struct wiphy *wiphy, struct net_device *dev, + int (*set_txq_params)(struct wiphy *wiphy, struct ieee80211_txq_params *params); int (*set_channel)(struct wiphy *wiphy, struct net_device *dev, @@ -1577,8 +1560,7 @@ struct cfg80211_ops { struct ieee80211_channel *chan, bool offchan, enum nl80211_channel_type channel_type, bool channel_type_valid, unsigned int wait, - const u8 *buf, size_t len, bool no_cck, - u64 *cookie); + const u8 *buf, size_t len, u64 *cookie); int (*mgmt_tx_cancel_wait)(struct wiphy *wiphy, struct net_device *dev, u64 cookie); @@ -1608,12 +1590,6 @@ struct cfg80211_ops { int (*set_rekey_data)(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_gtk_rekey_data *data); - - int (*tdls_mgmt)(struct wiphy *wiphy, struct net_device *dev, - u8 *peer, u8 action_code, u8 dialog_token, - u16 status_code, const u8 *buf, size_t len); - int (*tdls_oper)(struct wiphy *wiphy, struct net_device *dev, - u8 *peer, enum nl80211_tdls_operation oper); }; /* @@ -1666,12 +1642,6 @@ struct cfg80211_ops { * @WIPHY_FLAG_SUPPORTS_FW_ROAM: The device supports roaming feature in the * firmware. * @WIPHY_FLAG_AP_UAPSD: The device supports uapsd on AP. - * @WIPHY_FLAG_SUPPORTS_TDLS: The device supports TDLS (802.11z) operation. - * @WIPHY_FLAG_TDLS_EXTERNAL_SETUP: The device does not handle TDLS (802.11z) - * link setup/discovery operations internally. Setup, discovery and - * teardown packets should be sent through the @NL80211_CMD_TDLS_MGMT - * command. When this flag is not set, @NL80211_CMD_TDLS_OPER should be - * used for asking the driver/firmware to perform a TDLS operation. */ enum wiphy_flags { WIPHY_FLAG_CUSTOM_REGULATORY = BIT(0), @@ -1688,8 +1658,6 @@ enum wiphy_flags { WIPHY_FLAG_ENFORCE_COMBINATIONS = BIT(12), WIPHY_FLAG_SUPPORTS_FW_ROAM = BIT(13), WIPHY_FLAG_AP_UAPSD = BIT(14), - WIPHY_FLAG_SUPPORTS_TDLS = BIT(15), - WIPHY_FLAG_TDLS_EXTERNAL_SETUP = BIT(16), }; /** diff --git a/trunk/include/net/ieee80211_radiotap.h b/trunk/include/net/ieee80211_radiotap.h index 7e2c4d483ad0..b0be5fb9de19 100644 --- a/trunk/include/net/ieee80211_radiotap.h +++ b/trunk/include/net/ieee80211_radiotap.h @@ -251,7 +251,6 @@ enum ieee80211_radiotap_type { * retries */ #define IEEE80211_RADIOTAP_F_TX_CTS 0x0002 /* used cts 'protection' */ #define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 /* used rts/cts handshake */ -#define IEEE80211_RADIOTAP_F_TX_NOACK 0x0008 /* don't expect an ack */ /* For IEEE80211_RADIOTAP_MCS */ diff --git a/trunk/include/net/mac80211.h b/trunk/include/net/mac80211.h index cd108dfa1952..c0f63fd0c52b 100644 --- a/trunk/include/net/mac80211.h +++ b/trunk/include/net/mac80211.h @@ -109,7 +109,6 @@ enum ieee80211_ac_numbers { IEEE80211_AC_BE = 2, IEEE80211_AC_BK = 3, }; -#define IEEE80211_NUM_ACS 4 /** * struct ieee80211_tx_queue_params - transmit queue configuration @@ -339,9 +338,9 @@ struct ieee80211_bss_conf { * used to indicate that a frame was already retried due to PS * @IEEE80211_TX_INTFL_DONT_ENCRYPT: completely internal to mac80211, * used to indicate frame should not be encrypted - * @IEEE80211_TX_CTL_POLL_RESPONSE: This frame is a response to a poll - * frame (PS-Poll or uAPSD) and should be sent although the station - * is in powersave mode. + * @IEEE80211_TX_CTL_PSPOLL_RESPONSE: (internal?) + * This frame is a response to a PS-poll frame and should be sent + * although the station is in powersave mode. * @IEEE80211_TX_CTL_MORE_FRAMES: More frames will be passed to the * transmit function after the current frame, this can be used * by drivers to kick the DMA queue only if unset or when the @@ -364,17 +363,6 @@ struct ieee80211_bss_conf { * @IEEE80211_TX_INTFL_TKIP_MIC_FAILURE: Marks this packet to be used for TKIP * testing. It will be sent out with incorrect Michael MIC key to allow * TKIP countermeasures to be tested. - * @IEEE80211_TX_CTL_NO_CCK_RATE: This frame will be sent at non CCK rate. - * This flag is actually used for management frame especially for P2P - * frames not being sent at CCK rate in 2GHz band. - * @IEEE80211_TX_STATUS_EOSP: This packet marks the end of service period, - * when its status is reported the service period ends. For frames in - * an SP that mac80211 transmits, it is already set; for driver frames - * the driver may set this flag. It is also used to do the same for - * PS-Poll responses. - * @IEEE80211_TX_CTL_USE_MINRATE: This frame will be sent at lowest rate. - * This flag is used to send nullfunc frame at minimum rate when - * the nullfunc is used for connection monitoring purpose. * * Note: If you have to add new flags to the enumeration, then don't * forget to update %IEEE80211_TX_TEMPORARY_FLAGS when necessary. @@ -396,7 +384,7 @@ enum mac80211_tx_control_flags { IEEE80211_TX_INTFL_NEED_TXPROCESSING = BIT(14), IEEE80211_TX_INTFL_RETRIED = BIT(15), IEEE80211_TX_INTFL_DONT_ENCRYPT = BIT(16), - IEEE80211_TX_CTL_POLL_RESPONSE = BIT(17), + IEEE80211_TX_CTL_PSPOLL_RESPONSE = BIT(17), IEEE80211_TX_CTL_MORE_FRAMES = BIT(18), IEEE80211_TX_INTFL_RETRANSMISSION = BIT(19), IEEE80211_TX_INTFL_HAS_RADIOTAP = BIT(20), @@ -405,9 +393,6 @@ enum mac80211_tx_control_flags { IEEE80211_TX_CTL_STBC = BIT(23) | BIT(24), IEEE80211_TX_CTL_TX_OFFCHAN = BIT(25), IEEE80211_TX_INTFL_TKIP_MIC_FAILURE = BIT(26), - IEEE80211_TX_CTL_NO_CCK_RATE = BIT(27), - IEEE80211_TX_STATUS_EOSP = BIT(28), - IEEE80211_TX_CTL_USE_MINRATE = BIT(29), }; #define IEEE80211_TX_CTL_STBC_SHIFT 23 @@ -421,9 +406,9 @@ enum mac80211_tx_control_flags { IEEE80211_TX_CTL_SEND_AFTER_DTIM | IEEE80211_TX_CTL_AMPDU | \ IEEE80211_TX_STAT_TX_FILTERED | IEEE80211_TX_STAT_ACK | \ IEEE80211_TX_STAT_AMPDU | IEEE80211_TX_STAT_AMPDU_NO_BACK | \ - IEEE80211_TX_CTL_RATE_CTRL_PROBE | IEEE80211_TX_CTL_POLL_RESPONSE | \ + IEEE80211_TX_CTL_RATE_CTRL_PROBE | IEEE80211_TX_CTL_PSPOLL_RESPONSE | \ IEEE80211_TX_CTL_MORE_FRAMES | IEEE80211_TX_CTL_LDPC | \ - IEEE80211_TX_CTL_STBC | IEEE80211_TX_STATUS_EOSP) + IEEE80211_TX_CTL_STBC) /** * enum mac80211_rate_control_flags - per-rate flags set by the @@ -1542,95 +1527,6 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw, * This rule applies to all other FIF flags as well. */ -/** - * DOC: AP support for powersaving clients - * - * In order to implement AP and P2P GO modes, mac80211 has support for - * client powersaving, both "legacy" PS (PS-Poll/null data) and uAPSD. - * There currently is no support for sAPSD. - * - * There is one assumption that mac80211 makes, namely that a client - * will not poll with PS-Poll and trigger with uAPSD at the same time. - * Both are supported, and both can be used by the same client, but - * they can't be used concurrently by the same client. This simplifies - * the driver code. - * - * The first thing to keep in mind is that there is a flag for complete - * driver implementation: %IEEE80211_HW_AP_LINK_PS. If this flag is set, - * mac80211 expects the driver to handle most of the state machine for - * powersaving clients and will ignore the PM bit in incoming frames. - * Drivers then use ieee80211_sta_ps_transition() to inform mac80211 of - * stations' powersave transitions. In this mode, mac80211 also doesn't - * handle PS-Poll/uAPSD. - * - * In the mode without %IEEE80211_HW_AP_LINK_PS, mac80211 will check the - * PM bit in incoming frames for client powersave transitions. When a - * station goes to sleep, we will stop transmitting to it. There is, - * however, a race condition: a station might go to sleep while there is - * data buffered on hardware queues. If the device has support for this - * it will reject frames, and the driver should give the frames back to - * mac80211 with the %IEEE80211_TX_STAT_TX_FILTERED flag set which will - * cause mac80211 to retry the frame when the station wakes up. The - * driver is also notified of powersave transitions by calling its - * @sta_notify callback. - * - * When the station is asleep, it has three choices: it can wake up, - * it can PS-Poll, or it can possibly start a uAPSD service period. - * Waking up is implemented by simply transmitting all buffered (and - * filtered) frames to the station. This is the easiest case. When - * the station sends a PS-Poll or a uAPSD trigger frame, mac80211 - * will inform the driver of this with the @allow_buffered_frames - * callback; this callback is optional. mac80211 will then transmit - * the frames as usual and set the %IEEE80211_TX_CTL_POLL_RESPONSE - * on each frame. The last frame in the service period (or the only - * response to a PS-Poll) also has %IEEE80211_TX_STATUS_EOSP set to - * indicate that it ends the service period; as this frame must have - * TX status report it also sets %IEEE80211_TX_CTL_REQ_TX_STATUS. - * When TX status is reported for this frame, the service period is - * marked has having ended and a new one can be started by the peer. - * - * Another race condition can happen on some devices like iwlwifi - * when there are frames queued for the station and it wakes up - * or polls; the frames that are already queued could end up being - * transmitted first instead, causing reordering and/or wrong - * processing of the EOSP. The cause is that allowing frames to be - * transmitted to a certain station is out-of-band communication to - * the device. To allow this problem to be solved, the driver can - * call ieee80211_sta_block_awake() if frames are buffered when it - * is notified that the station went to sleep. When all these frames - * have been filtered (see above), it must call the function again - * to indicate that the station is no longer blocked. - * - * If the driver buffers frames in the driver for aggregation in any - * way, it must use the ieee80211_sta_set_buffered() call when it is - * notified of the station going to sleep to inform mac80211 of any - * TIDs that have frames buffered. Note that when a station wakes up - * this information is reset (hence the requirement to call it when - * informed of the station going to sleep). Then, when a service - * period starts for any reason, @release_buffered_frames is called - * with the number of frames to be released and which TIDs they are - * to come from. In this case, the driver is responsible for setting - * the EOSP (for uAPSD) and MORE_DATA bits in the released frames, - * to help the @more_data paramter is passed to tell the driver if - * there is more data on other TIDs -- the TIDs to release frames - * from are ignored since mac80211 doesn't know how many frames the - * buffers for those TIDs contain. - * - * If the driver also implement GO mode, where absence periods may - * shorten service periods (or abort PS-Poll responses), it must - * filter those response frames except in the case of frames that - * are buffered in the driver -- those must remain buffered to avoid - * reordering. Because it is possible that no frames are released - * in this case, the driver must call ieee80211_sta_eosp_irqsafe() - * to indicate to mac80211 that the service period ended anyway. - * - * Finally, if frames from multiple TIDs are released from mac80211 - * but the driver might reorder them, it must clear & set the flags - * appropriately (only the last frame may have %IEEE80211_TX_STATUS_EOSP) - * and also take care of the EOSP and MORE_DATA bits in the frame. - * The driver may also use ieee80211_sta_eosp_irqsafe() in this case. - */ - /** * enum ieee80211_filter_flags - hardware filter flags * @@ -1720,17 +1616,6 @@ enum ieee80211_tx_sync_type { IEEE80211_TX_SYNC_ACTION, }; -/** - * enum ieee80211_frame_release_type - frame release reason - * @IEEE80211_FRAME_RELEASE_PSPOLL: frame released for PS-Poll - * @IEEE80211_FRAME_RELEASE_UAPSD: frame(s) released due to - * frame received on trigger-enabled AC - */ -enum ieee80211_frame_release_type { - IEEE80211_FRAME_RELEASE_PSPOLL, - IEEE80211_FRAME_RELEASE_UAPSD, -}; - /** * struct ieee80211_ops - callbacks from mac80211 to the driver * @@ -2041,45 +1926,6 @@ enum ieee80211_frame_release_type { * The callback can sleep. * @rssi_callback: Notify driver when the average RSSI goes above/below * thresholds that were registered previously. The callback can sleep. - * - * @release_buffered_frames: Release buffered frames according to the given - * parameters. In the case where the driver buffers some frames for - * sleeping stations mac80211 will use this callback to tell the driver - * to release some frames, either for PS-poll or uAPSD. - * Note that if the @more_data paramter is %false the driver must check - * if there are more frames on the given TIDs, and if there are more than - * the frames being released then it must still set the more-data bit in - * the frame. If the @more_data parameter is %true, then of course the - * more-data bit must always be set. - * The @tids parameter tells the driver which TIDs to release frames - * from, for PS-poll it will always have only a single bit set. - * In the case this is used for a PS-poll initiated release, the - * @num_frames parameter will always be 1 so code can be shared. In - * this case the driver must also set %IEEE80211_TX_STATUS_EOSP flag - * on the TX status (and must report TX status) so that the PS-poll - * period is properly ended. This is used to avoid sending multiple - * responses for a retried PS-poll frame. - * In the case this is used for uAPSD, the @num_frames parameter may be - * bigger than one, but the driver may send fewer frames (it must send - * at least one, however). In this case it is also responsible for - * setting the EOSP flag in the QoS header of the frames. Also, when the - * service period ends, the driver must set %IEEE80211_TX_STATUS_EOSP - * on the last frame in the SP. Alternatively, it may call the function - * ieee80211_sta_eosp_irqsafe() to inform mac80211 of the end of the SP. - * This callback must be atomic. - * @allow_buffered_frames: Prepare device to allow the given number of frames - * to go out to the given station. The frames will be sent by mac80211 - * via the usual TX path after this call. The TX information for frames - * released will also have the %IEEE80211_TX_CTL_POLL_RESPONSE flag set - * and the last one will also have %IEEE80211_TX_STATUS_EOSP set. In case - * frames from multiple TIDs are released and the driver might reorder - * them between the TIDs, it must set the %IEEE80211_TX_STATUS_EOSP flag - * on the last frame and clear it on all others and also handle the EOSP - * bit in the QoS header correctly. Alternatively, it can also call the - * ieee80211_sta_eosp_irqsafe() function. - * The @tids parameter is a bitmap and tells the driver which TIDs the - * frames will be on; it will at most have two bits set. - * This callback must be atomic. */ struct ieee80211_ops { void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb); @@ -2152,13 +1998,11 @@ struct ieee80211_ops { struct ieee80211_sta *sta); void (*sta_notify)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum sta_notify_cmd, struct ieee80211_sta *sta); - int (*conf_tx)(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, u16 queue, + int (*conf_tx)(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params); - u64 (*get_tsf)(struct ieee80211_hw *hw, struct ieee80211_vif *vif); - void (*set_tsf)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - u64 tsf); - void (*reset_tsf)(struct ieee80211_hw *hw, struct ieee80211_vif *vif); + u64 (*get_tsf)(struct ieee80211_hw *hw); + void (*set_tsf)(struct ieee80211_hw *hw, u64 tsf); + void (*reset_tsf)(struct ieee80211_hw *hw); int (*tx_last_beacon)(struct ieee80211_hw *hw); int (*ampdu_action)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, @@ -2195,17 +2039,6 @@ struct ieee80211_ops { const struct cfg80211_bitrate_mask *mask); void (*rssi_callback)(struct ieee80211_hw *hw, enum ieee80211_rssi_event rssi_event); - - void (*allow_buffered_frames)(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, - u16 tids, int num_frames, - enum ieee80211_frame_release_type reason, - bool more_data); - void (*release_buffered_frames)(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, - u16 tids, int num_frames, - enum ieee80211_frame_release_type reason, - bool more_data); }; /** @@ -2523,35 +2356,17 @@ static inline int ieee80211_sta_ps_transition_ni(struct ieee80211_sta *sta, #define IEEE80211_TX_STATUS_HEADROOM 13 /** - * ieee80211_sta_set_buffered - inform mac80211 about driver-buffered frames + * ieee80211_sta_set_tim - set the TIM bit for a sleeping station * @sta: &struct ieee80211_sta pointer for the sleeping station - * @tid: the TID that has buffered frames - * @buffered: indicates whether or not frames are buffered for this TID * * If a driver buffers frames for a powersave station instead of passing - * them back to mac80211 for retransmission, the station may still need - * to be told that there are buffered frames via the TIM bit. + * them back to mac80211 for retransmission, the station needs to be told + * to wake up using the TIM bitmap in the beacon. * - * This function informs mac80211 whether or not there are frames that are - * buffered in the driver for a given TID; mac80211 can then use this data - * to set the TIM bit (NOTE: This may call back into the driver's set_tim - * call! Beware of the locking!) - * - * If all frames are released to the station (due to PS-poll or uAPSD) - * then the driver needs to inform mac80211 that there no longer are - * frames buffered. However, when the station wakes up mac80211 assumes - * that all buffered frames will be transmitted and clears this data, - * drivers need to make sure they inform mac80211 about all buffered - * frames on the sleep transition (sta_notify() with %STA_NOTIFY_SLEEP). - * - * Note that technically mac80211 only needs to know this per AC, not per - * TID, but since driver buffering will inevitably happen per TID (since - * it is related to aggregation) it is easier to make mac80211 map the - * TID to the AC as required instead of keeping track in all drivers that - * use this API. + * This function sets the station's TIM bit - it will be cleared when the + * station wakes up. */ -void ieee80211_sta_set_buffered(struct ieee80211_sta *sta, - u8 tid, bool buffered); +void ieee80211_sta_set_tim(struct ieee80211_sta *sta); /** * ieee80211_tx_status - transmit status callback @@ -3208,24 +3023,6 @@ struct ieee80211_sta *ieee80211_find_sta_by_ifaddr(struct ieee80211_hw *hw, void ieee80211_sta_block_awake(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta, bool block); -/** - * ieee80211_sta_eosp - notify mac80211 about end of SP - * @pubsta: the station - * - * When a device transmits frames in a way that it can't tell - * mac80211 in the TX status about the EOSP, it must clear the - * %IEEE80211_TX_STATUS_EOSP bit and call this function instead. - * This applies for PS-Poll as well as uAPSD. - * - * Note that there is no non-_irqsafe version right now as - * it wasn't needed, but just like _tx_status() and _rx() - * must not be mixed in irqsafe/non-irqsafe versions, this - * function must not be mixed with those either. Use the - * all irqsafe, or all non-irqsafe, don't mix! If you need - * the non-irqsafe version of this, you need to add it. - */ -void ieee80211_sta_eosp_irqsafe(struct ieee80211_sta *pubsta); - /** * ieee80211_iter_keys - iterate keys programmed into the device * @hw: pointer obtained from ieee80211_alloc_hw() @@ -3642,9 +3439,4 @@ void ieee80211_enable_rssi_reports(struct ieee80211_vif *vif, int rssi_max_thold); void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif); - -int ieee80211_add_srates_ie(struct ieee80211_vif *vif, struct sk_buff *skb); - -int ieee80211_add_ext_srates_ie(struct ieee80211_vif *vif, - struct sk_buff *skb); #endif /* MAC80211_H */ diff --git a/trunk/include/net/nfc/nci_core.h b/trunk/include/net/nfc/nci_core.h index b8b4bbd7e0fc..2563f3a95e67 100644 --- a/trunk/include/net/nfc/nci_core.h +++ b/trunk/include/net/nfc/nci_core.h @@ -40,7 +40,6 @@ enum { NCI_UP, NCI_DISCOVERY, NCI_POLL_ACTIVE, - NCI_DATA_EXCHANGE, }; /* NCI timeouts */ diff --git a/trunk/net/mac80211/Kconfig b/trunk/net/mac80211/Kconfig index 7d3b438755f0..d1886b59bec4 100644 --- a/trunk/net/mac80211/Kconfig +++ b/trunk/net/mac80211/Kconfig @@ -225,18 +225,6 @@ config MAC80211_VERBOSE_MHWMP_DEBUG Do not select this option. -config MAC80211_VERBOSE_TDLS_DEBUG - bool "Verbose TDLS debugging" - depends on MAC80211_DEBUG_MENU - ---help--- - Selecting this option causes mac80211 to print out very - verbose TDLS selection debugging messages (when mac80211 - is a TDLS STA). - It should not be selected on production systems as those - messages are remotely triggerable. - - Do not select this option. - config MAC80211_DEBUG_COUNTERS bool "Extra statistics for TX/RX debugging" depends on MAC80211_DEBUG_MENU diff --git a/trunk/net/mac80211/agg-rx.c b/trunk/net/mac80211/agg-rx.c index 0cde8df6828d..e6cab51dceb0 100644 --- a/trunk/net/mac80211/agg-rx.c +++ b/trunk/net/mac80211/agg-rx.c @@ -223,7 +223,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, status = WLAN_STATUS_REQUEST_DECLINED; - if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) { + if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) { #ifdef CONFIG_MAC80211_HT_DEBUG printk(KERN_DEBUG "Suspend in progress. " "Denying ADDBA request\n"); diff --git a/trunk/net/mac80211/agg-tx.c b/trunk/net/mac80211/agg-tx.c index 2ac033989e01..3cef5a7281cb 100644 --- a/trunk/net/mac80211/agg-tx.c +++ b/trunk/net/mac80211/agg-tx.c @@ -382,7 +382,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, sdata->vif.type != NL80211_IFTYPE_AP) return -EINVAL; - if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) { + if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) { #ifdef CONFIG_MAC80211_HT_DEBUG printk(KERN_DEBUG "BA sessions blocked. " "Denying BA session request\n"); diff --git a/trunk/net/mac80211/cfg.c b/trunk/net/mac80211/cfg.c index 1309bb9c97be..b57ddf941e59 100644 --- a/trunk/net/mac80211/cfg.c +++ b/trunk/net/mac80211/cfg.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include "ieee80211_i.h" #include "driver-ops.h" @@ -668,6 +667,7 @@ static void sta_apply_parameters(struct ieee80211_local *local, struct sta_info *sta, struct station_parameters *params) { + unsigned long flags; u32 rates; int i, j; struct ieee80211_supported_band *sband; @@ -676,58 +676,46 @@ static void sta_apply_parameters(struct ieee80211_local *local, sband = local->hw.wiphy->bands[local->oper_channel->band]; + spin_lock_irqsave(&sta->flaglock, flags); mask = params->sta_flags_mask; set = params->sta_flags_set; if (mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) { + sta->flags &= ~WLAN_STA_AUTHORIZED; if (set & BIT(NL80211_STA_FLAG_AUTHORIZED)) - set_sta_flag(sta, WLAN_STA_AUTHORIZED); - else - clear_sta_flag(sta, WLAN_STA_AUTHORIZED); + sta->flags |= WLAN_STA_AUTHORIZED; } if (mask & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) { + sta->flags &= ~WLAN_STA_SHORT_PREAMBLE; if (set & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) - set_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE); - else - clear_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE); + sta->flags |= WLAN_STA_SHORT_PREAMBLE; } if (mask & BIT(NL80211_STA_FLAG_WME)) { + sta->flags &= ~WLAN_STA_WME; + sta->sta.wme = false; if (set & BIT(NL80211_STA_FLAG_WME)) { - set_sta_flag(sta, WLAN_STA_WME); + sta->flags |= WLAN_STA_WME; sta->sta.wme = true; - } else { - clear_sta_flag(sta, WLAN_STA_WME); - sta->sta.wme = false; } } if (mask & BIT(NL80211_STA_FLAG_MFP)) { + sta->flags &= ~WLAN_STA_MFP; if (set & BIT(NL80211_STA_FLAG_MFP)) - set_sta_flag(sta, WLAN_STA_MFP); - else - clear_sta_flag(sta, WLAN_STA_MFP); + sta->flags |= WLAN_STA_MFP; } if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) { + sta->flags &= ~WLAN_STA_AUTH; if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) - set_sta_flag(sta, WLAN_STA_AUTH); - else - clear_sta_flag(sta, WLAN_STA_AUTH); + sta->flags |= WLAN_STA_AUTH; } + spin_unlock_irqrestore(&sta->flaglock, flags); - if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) { - if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) - set_sta_flag(sta, WLAN_STA_TDLS_PEER); - else - clear_sta_flag(sta, WLAN_STA_TDLS_PEER); - } - - if (params->sta_modify_mask & STATION_PARAM_APPLY_UAPSD) { - sta->sta.uapsd_queues = params->uapsd_queues; - sta->sta.max_sp = params->max_sp; - } + sta->sta.uapsd_queues = params->uapsd_queues; + sta->sta.max_sp = params->max_sp; /* * cfg80211 validates this (1-2007) and allows setting the AID @@ -818,17 +806,10 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, if (!sta) return -ENOMEM; - set_sta_flag(sta, WLAN_STA_AUTH); - set_sta_flag(sta, WLAN_STA_ASSOC); + sta->flags = WLAN_STA_AUTH | WLAN_STA_ASSOC; sta_apply_parameters(local, sta, params); - /* Only TDLS-supporting stations can add TDLS peers */ - if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) && - !((wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) && - sdata->vif.type == NL80211_IFTYPE_STATION)) - return -ENOTSUPP; - rate_control_rate_init(sta); layer2_update = sdata->vif.type == NL80211_IFTYPE_AP_VLAN || @@ -881,14 +862,6 @@ static int ieee80211_change_station(struct wiphy *wiphy, return -ENOENT; } - /* The TDLS bit cannot be toggled after the STA was added */ - if ((params->sta_flags_mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) && - !!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) != - !!test_sta_flag(sta, WLAN_STA_TDLS_PEER)) { - rcu_read_unlock(); - return -EINVAL; - } - if (params->vlan && params->vlan != sta->sdata->dev) { vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); @@ -1298,11 +1271,9 @@ static int ieee80211_change_bss(struct wiphy *wiphy, } static int ieee80211_set_txq_params(struct wiphy *wiphy, - struct net_device *dev, struct ieee80211_txq_params *params) { struct ieee80211_local *local = wiphy_priv(wiphy); - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_tx_queue_params p; if (!local->ops->conf_tx) @@ -1323,8 +1294,8 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy, if (params->queue >= local->hw.queues) return -EINVAL; - sdata->tx_conf[params->queue] = p; - if (drv_conf_tx(local, sdata, params->queue, &p)) { + local->tx_conf[params->queue] = p; + if (drv_conf_tx(local, params->queue, &p)) { wiphy_debug(local->hw.wiphy, "failed to set TX queue parameters for queue %d\n", params->queue); @@ -1898,8 +1869,7 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, struct ieee80211_channel *chan, bool offchan, enum nl80211_channel_type channel_type, bool channel_type_valid, unsigned int wait, - const u8 *buf, size_t len, bool no_cck, - u64 *cookie) + const u8 *buf, size_t len, u64 *cookie) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = sdata->local; @@ -1926,9 +1896,6 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, flags |= IEEE80211_TX_CTL_TX_OFFCHAN; } - if (no_cck) - flags |= IEEE80211_TX_CTL_NO_CCK_RATE; - if (is_offchan && !offchan) return -EBUSY; @@ -2153,323 +2120,6 @@ static int ieee80211_set_rekey_data(struct wiphy *wiphy, return 0; } -static void ieee80211_tdls_add_ext_capab(struct sk_buff *skb) -{ - u8 *pos = (void *)skb_put(skb, 7); - - *pos++ = WLAN_EID_EXT_CAPABILITY; - *pos++ = 5; /* len */ - *pos++ = 0x0; - *pos++ = 0x0; - *pos++ = 0x0; - *pos++ = 0x0; - *pos++ = WLAN_EXT_CAPA5_TDLS_ENABLED; -} - -static u16 ieee80211_get_tdls_sta_capab(struct ieee80211_sub_if_data *sdata) -{ - struct ieee80211_local *local = sdata->local; - u16 capab; - - capab = 0; - if (local->oper_channel->band != IEEE80211_BAND_2GHZ) - return capab; - - if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE)) - capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME; - if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE)) - capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; - - return capab; -} - -static void ieee80211_tdls_add_link_ie(struct sk_buff *skb, u8 *src_addr, - u8 *peer, u8 *bssid) -{ - struct ieee80211_tdls_lnkie *lnkid; - - lnkid = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_lnkie)); - - lnkid->ie_type = WLAN_EID_LINK_ID; - lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) - 2; - - memcpy(lnkid->bssid, bssid, ETH_ALEN); - memcpy(lnkid->init_sta, src_addr, ETH_ALEN); - memcpy(lnkid->resp_sta, peer, ETH_ALEN); -} - -static int -ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, - u8 *peer, u8 action_code, u8 dialog_token, - u16 status_code, struct sk_buff *skb) -{ - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - struct ieee80211_tdls_data *tf; - - tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u)); - - memcpy(tf->da, peer, ETH_ALEN); - memcpy(tf->sa, sdata->vif.addr, ETH_ALEN); - tf->ether_type = cpu_to_be16(ETH_P_TDLS); - tf->payload_type = WLAN_TDLS_SNAP_RFTYPE; - - switch (action_code) { - case WLAN_TDLS_SETUP_REQUEST: - tf->category = WLAN_CATEGORY_TDLS; - tf->action_code = WLAN_TDLS_SETUP_REQUEST; - - skb_put(skb, sizeof(tf->u.setup_req)); - tf->u.setup_req.dialog_token = dialog_token; - tf->u.setup_req.capability = - cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); - - ieee80211_add_srates_ie(&sdata->vif, skb); - ieee80211_add_ext_srates_ie(&sdata->vif, skb); - ieee80211_tdls_add_ext_capab(skb); - break; - case WLAN_TDLS_SETUP_RESPONSE: - tf->category = WLAN_CATEGORY_TDLS; - tf->action_code = WLAN_TDLS_SETUP_RESPONSE; - - skb_put(skb, sizeof(tf->u.setup_resp)); - tf->u.setup_resp.status_code = cpu_to_le16(status_code); - tf->u.setup_resp.dialog_token = dialog_token; - tf->u.setup_resp.capability = - cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); - - ieee80211_add_srates_ie(&sdata->vif, skb); - ieee80211_add_ext_srates_ie(&sdata->vif, skb); - ieee80211_tdls_add_ext_capab(skb); - break; - case WLAN_TDLS_SETUP_CONFIRM: - tf->category = WLAN_CATEGORY_TDLS; - tf->action_code = WLAN_TDLS_SETUP_CONFIRM; - - skb_put(skb, sizeof(tf->u.setup_cfm)); - tf->u.setup_cfm.status_code = cpu_to_le16(status_code); - tf->u.setup_cfm.dialog_token = dialog_token; - break; - case WLAN_TDLS_TEARDOWN: - tf->category = WLAN_CATEGORY_TDLS; - tf->action_code = WLAN_TDLS_TEARDOWN; - - skb_put(skb, sizeof(tf->u.teardown)); - tf->u.teardown.reason_code = cpu_to_le16(status_code); - break; - case WLAN_TDLS_DISCOVERY_REQUEST: - tf->category = WLAN_CATEGORY_TDLS; - tf->action_code = WLAN_TDLS_DISCOVERY_REQUEST; - - skb_put(skb, sizeof(tf->u.discover_req)); - tf->u.discover_req.dialog_token = dialog_token; - break; - default: - return -EINVAL; - } - - return 0; -} - -static int -ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev, - u8 *peer, u8 action_code, u8 dialog_token, - u16 status_code, struct sk_buff *skb) -{ - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - struct ieee80211_mgmt *mgmt; - - mgmt = (void *)skb_put(skb, 24); - memset(mgmt, 0, 24); - memcpy(mgmt->da, peer, ETH_ALEN); - memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); - memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); - - mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | - IEEE80211_STYPE_ACTION); - - switch (action_code) { - case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: - skb_put(skb, 1 + sizeof(mgmt->u.action.u.tdls_discover_resp)); - mgmt->u.action.category = WLAN_CATEGORY_PUBLIC; - mgmt->u.action.u.tdls_discover_resp.action_code = - WLAN_PUB_ACTION_TDLS_DISCOVER_RES; - mgmt->u.action.u.tdls_discover_resp.dialog_token = - dialog_token; - mgmt->u.action.u.tdls_discover_resp.capability = - cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); - - ieee80211_add_srates_ie(&sdata->vif, skb); - ieee80211_add_ext_srates_ie(&sdata->vif, skb); - ieee80211_tdls_add_ext_capab(skb); - break; - default: - return -EINVAL; - } - - return 0; -} - -static int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, - u8 *peer, u8 action_code, u8 dialog_token, - u16 status_code, const u8 *extra_ies, - size_t extra_ies_len) -{ - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - struct ieee80211_local *local = sdata->local; - struct ieee80211_tx_info *info; - struct sk_buff *skb = NULL; - bool send_direct; - int ret; - - if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) - return -ENOTSUPP; - - /* make sure we are in managed mode, and associated */ - if (sdata->vif.type != NL80211_IFTYPE_STATION || - !sdata->u.mgd.associated) - return -EINVAL; - -#ifdef CONFIG_MAC80211_VERBOSE_TDLS_DEBUG - printk(KERN_DEBUG "TDLS mgmt action %d peer %pM\n", action_code, peer); -#endif - - skb = dev_alloc_skb(local->hw.extra_tx_headroom + - max(sizeof(struct ieee80211_mgmt), - sizeof(struct ieee80211_tdls_data)) + - 50 + /* supported rates */ - 7 + /* ext capab */ - extra_ies_len + - sizeof(struct ieee80211_tdls_lnkie)); - if (!skb) - return -ENOMEM; - - info = IEEE80211_SKB_CB(skb); - skb_reserve(skb, local->hw.extra_tx_headroom); - - switch (action_code) { - case WLAN_TDLS_SETUP_REQUEST: - case WLAN_TDLS_SETUP_RESPONSE: - case WLAN_TDLS_SETUP_CONFIRM: - case WLAN_TDLS_TEARDOWN: - case WLAN_TDLS_DISCOVERY_REQUEST: - ret = ieee80211_prep_tdls_encap_data(wiphy, dev, peer, - action_code, dialog_token, - status_code, skb); - send_direct = false; - break; - case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: - ret = ieee80211_prep_tdls_direct(wiphy, dev, peer, action_code, - dialog_token, status_code, - skb); - send_direct = true; - break; - default: - ret = -ENOTSUPP; - break; - } - - if (ret < 0) - goto fail; - - if (extra_ies_len) - memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len); - - /* the TDLS link IE is always added last */ - switch (action_code) { - case WLAN_TDLS_SETUP_REQUEST: - case WLAN_TDLS_SETUP_CONFIRM: - case WLAN_TDLS_TEARDOWN: - case WLAN_TDLS_DISCOVERY_REQUEST: - /* we are the initiator */ - ieee80211_tdls_add_link_ie(skb, sdata->vif.addr, peer, - sdata->u.mgd.bssid); - break; - case WLAN_TDLS_SETUP_RESPONSE: - case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: - /* we are the responder */ - ieee80211_tdls_add_link_ie(skb, peer, sdata->vif.addr, - sdata->u.mgd.bssid); - break; - default: - ret = -ENOTSUPP; - goto fail; - } - - if (send_direct) { - ieee80211_tx_skb(sdata, skb); - return 0; - } - - /* - * According to 802.11z: Setup req/resp are sent in AC_BK, otherwise - * we should default to AC_VI. - */ - switch (action_code) { - case WLAN_TDLS_SETUP_REQUEST: - case WLAN_TDLS_SETUP_RESPONSE: - skb_set_queue_mapping(skb, IEEE80211_AC_BK); - skb->priority = 2; - break; - default: - skb_set_queue_mapping(skb, IEEE80211_AC_VI); - skb->priority = 5; - break; - } - - /* disable bottom halves when entering the Tx path */ - local_bh_disable(); - ret = ieee80211_subif_start_xmit(skb, dev); - local_bh_enable(); - - return ret; - -fail: - dev_kfree_skb(skb); - return ret; -} - -static int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, - u8 *peer, enum nl80211_tdls_operation oper) -{ - struct sta_info *sta; - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - - if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) - return -ENOTSUPP; - - if (sdata->vif.type != NL80211_IFTYPE_STATION) - return -EINVAL; - -#ifdef CONFIG_MAC80211_VERBOSE_TDLS_DEBUG - printk(KERN_DEBUG "TDLS oper %d peer %pM\n", oper, peer); -#endif - - switch (oper) { - case NL80211_TDLS_ENABLE_LINK: - rcu_read_lock(); - sta = sta_info_get(sdata, peer); - if (!sta) { - rcu_read_unlock(); - return -ENOLINK; - } - - set_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH); - rcu_read_unlock(); - break; - case NL80211_TDLS_DISABLE_LINK: - return sta_info_destroy_addr(sdata, peer); - case NL80211_TDLS_TEARDOWN: - case NL80211_TDLS_SETUP: - case NL80211_TDLS_DISCOVERY_REQ: - /* We don't support in-driver setup/teardown/discovery */ - return -ENOTSUPP; - default: - return -ENOTSUPP; - } - - return 0; -} - struct cfg80211_ops mac80211_config_ops = { .add_virtual_intf = ieee80211_add_iface, .del_virtual_intf = ieee80211_del_iface, @@ -2533,6 +2183,4 @@ struct cfg80211_ops mac80211_config_ops = { .set_ringparam = ieee80211_set_ringparam, .get_ringparam = ieee80211_get_ringparam, .set_rekey_data = ieee80211_set_rekey_data, - .tdls_oper = ieee80211_tdls_oper, - .tdls_mgmt = ieee80211_tdls_mgmt, }; diff --git a/trunk/net/mac80211/debugfs.c b/trunk/net/mac80211/debugfs.c index 883996b2f99f..c9141168fd43 100644 --- a/trunk/net/mac80211/debugfs.c +++ b/trunk/net/mac80211/debugfs.c @@ -78,6 +78,57 @@ DEBUGFS_READONLY_FILE(wep_iv, "%#08x", DEBUGFS_READONLY_FILE(rate_ctrl_alg, "%s", local->rate_ctrl ? local->rate_ctrl->ops->name : "hw/driver"); +static ssize_t tsf_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ieee80211_local *local = file->private_data; + u64 tsf; + + tsf = drv_get_tsf(local); + + return mac80211_format_buffer(user_buf, count, ppos, "0x%016llx\n", + (unsigned long long) tsf); +} + +static ssize_t tsf_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ieee80211_local *local = file->private_data; + unsigned long long tsf; + char buf[100]; + size_t len; + + len = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, len)) + return -EFAULT; + buf[len] = '\0'; + + if (strncmp(buf, "reset", 5) == 0) { + if (local->ops->reset_tsf) { + drv_reset_tsf(local); + wiphy_info(local->hw.wiphy, "debugfs reset TSF\n"); + } + } else { + tsf = simple_strtoul(buf, NULL, 0); + if (local->ops->set_tsf) { + drv_set_tsf(local, tsf); + wiphy_info(local->hw.wiphy, + "debugfs set TSF to %#018llx\n", tsf); + + } + } + + return count; +} + +static const struct file_operations tsf_ops = { + .read = tsf_read, + .write = tsf_write, + .open = mac80211_open_file_generic, + .llseek = default_llseek, +}; + static ssize_t reset_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { @@ -396,6 +447,7 @@ void debugfs_hw_add(struct ieee80211_local *local) DEBUGFS_ADD(frequency); DEBUGFS_ADD(total_ps_buffered); DEBUGFS_ADD(wep_iv); + DEBUGFS_ADD(tsf); DEBUGFS_ADD(queues); DEBUGFS_ADD_MODE(reset, 0200); DEBUGFS_ADD(noack); diff --git a/trunk/net/mac80211/debugfs_netdev.c b/trunk/net/mac80211/debugfs_netdev.c index 9352819a986b..dd0462917518 100644 --- a/trunk/net/mac80211/debugfs_netdev.c +++ b/trunk/net/mac80211/debugfs_netdev.c @@ -21,7 +21,6 @@ #include "rate.h" #include "debugfs.h" #include "debugfs_netdev.h" -#include "driver-ops.h" static ssize_t ieee80211_if_read( struct ieee80211_sub_if_data *sdata, @@ -332,46 +331,6 @@ static ssize_t ieee80211_if_fmt_num_buffered_multicast( } __IEEE80211_IF_FILE(num_buffered_multicast, NULL); -/* IBSS attributes */ -static ssize_t ieee80211_if_fmt_tsf( - const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) -{ - struct ieee80211_local *local = sdata->local; - u64 tsf; - - tsf = drv_get_tsf(local, (struct ieee80211_sub_if_data *)sdata); - - return scnprintf(buf, buflen, "0x%016llx\n", (unsigned long long) tsf); -} - -static ssize_t ieee80211_if_parse_tsf( - struct ieee80211_sub_if_data *sdata, const char *buf, int buflen) -{ - struct ieee80211_local *local = sdata->local; - unsigned long long tsf; - int ret; - - if (strncmp(buf, "reset", 5) == 0) { - if (local->ops->reset_tsf) { - drv_reset_tsf(local, sdata); - wiphy_info(local->hw.wiphy, "debugfs reset TSF\n"); - } - } else { - ret = kstrtoull(buf, 10, &tsf); - if (ret < 0) - return -EINVAL; - if (local->ops->set_tsf) { - drv_set_tsf(local, sdata, tsf); - wiphy_info(local->hw.wiphy, - "debugfs set TSF to %#018llx\n", tsf); - } - } - - return buflen; -} -__IEEE80211_IF_FILE_W(tsf); - - /* WDS attributes */ IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC); @@ -462,11 +421,6 @@ static void add_ap_files(struct ieee80211_sub_if_data *sdata) DEBUGFS_ADD_MODE(tkip_mic_test, 0200); } -static void add_ibss_files(struct ieee80211_sub_if_data *sdata) -{ - DEBUGFS_ADD_MODE(tsf, 0600); -} - static void add_wds_files(struct ieee80211_sub_if_data *sdata) { DEBUGFS_ADD(drop_unencrypted); @@ -561,7 +515,7 @@ static void add_files(struct ieee80211_sub_if_data *sdata) add_sta_files(sdata); break; case NL80211_IFTYPE_ADHOC: - add_ibss_files(sdata); + /* XXX */ break; case NL80211_IFTYPE_AP: add_ap_files(sdata); diff --git a/trunk/net/mac80211/debugfs_sta.c b/trunk/net/mac80211/debugfs_sta.c index c5f341798c16..a01d2137fddc 100644 --- a/trunk/net/mac80211/debugfs_sta.c +++ b/trunk/net/mac80211/debugfs_sta.c @@ -56,22 +56,19 @@ STA_FILE(last_signal, last_signal, D); static ssize_t sta_flags_read(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) { - char buf[121]; + char buf[100]; struct sta_info *sta = file->private_data; - -#define TEST(flg) \ - test_sta_flag(sta, WLAN_STA_##flg) ? #flg "\n" : "" - - int res = scnprintf(buf, sizeof(buf), - "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", - TEST(AUTH), TEST(ASSOC), TEST(PS_STA), - TEST(PS_DRIVER), TEST(AUTHORIZED), - TEST(SHORT_PREAMBLE), TEST(ASSOC_AP), - TEST(WME), TEST(WDS), TEST(CLEAR_PS_FILT), - TEST(MFP), TEST(BLOCK_BA), TEST(PSPOLL), - TEST(UAPSD), TEST(SP), TEST(TDLS_PEER), - TEST(TDLS_PEER_AUTH)); -#undef TEST + u32 staflags = get_sta_flags(sta); + int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s", + staflags & WLAN_STA_AUTH ? "AUTH\n" : "", + staflags & WLAN_STA_ASSOC ? "ASSOC\n" : "", + staflags & WLAN_STA_PS_STA ? "PS (sta)\n" : "", + staflags & WLAN_STA_PS_DRIVER ? "PS (driver)\n" : "", + staflags & WLAN_STA_AUTHORIZED ? "AUTHORIZED\n" : "", + staflags & WLAN_STA_SHORT_PREAMBLE ? "SHORT PREAMBLE\n" : "", + staflags & WLAN_STA_WME ? "WME\n" : "", + staflags & WLAN_STA_WDS ? "WDS\n" : "", + staflags & WLAN_STA_MFP ? "MFP\n" : ""); return simple_read_from_buffer(userbuf, count, ppos, buf, res); } STA_OPS(flags); @@ -81,14 +78,8 @@ static ssize_t sta_num_ps_buf_frames_read(struct file *file, size_t count, loff_t *ppos) { struct sta_info *sta = file->private_data; - char buf[17*IEEE80211_NUM_ACS], *p = buf; - int ac; - - for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) - p += scnprintf(p, sizeof(buf)+buf-p, "AC%d: %d\n", ac, - skb_queue_len(&sta->ps_tx_buf[ac]) + - skb_queue_len(&sta->tx_filtered[ac])); - return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf); + return mac80211_format_buffer(userbuf, count, ppos, "%u\n", + skb_queue_len(&sta->ps_tx_buf)); } STA_OPS(num_ps_buf_frames); diff --git a/trunk/net/mac80211/driver-ops.h b/trunk/net/mac80211/driver-ops.h index 5f165d7eb2db..9001ff331f0a 100644 --- a/trunk/net/mac80211/driver-ops.h +++ b/trunk/net/mac80211/driver-ops.h @@ -413,56 +413,50 @@ static inline void drv_sta_remove(struct ieee80211_local *local, trace_drv_return_void(local); } -static inline int drv_conf_tx(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata, u16 queue, +static inline int drv_conf_tx(struct ieee80211_local *local, u16 queue, const struct ieee80211_tx_queue_params *params) { int ret = -EOPNOTSUPP; might_sleep(); - trace_drv_conf_tx(local, sdata, queue, params); + trace_drv_conf_tx(local, queue, params); if (local->ops->conf_tx) - ret = local->ops->conf_tx(&local->hw, &sdata->vif, - queue, params); + ret = local->ops->conf_tx(&local->hw, queue, params); trace_drv_return_int(local, ret); return ret; } -static inline u64 drv_get_tsf(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata) +static inline u64 drv_get_tsf(struct ieee80211_local *local) { u64 ret = -1ULL; might_sleep(); - trace_drv_get_tsf(local, sdata); + trace_drv_get_tsf(local); if (local->ops->get_tsf) - ret = local->ops->get_tsf(&local->hw, &sdata->vif); + ret = local->ops->get_tsf(&local->hw); trace_drv_return_u64(local, ret); return ret; } -static inline void drv_set_tsf(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata, - u64 tsf) +static inline void drv_set_tsf(struct ieee80211_local *local, u64 tsf) { might_sleep(); - trace_drv_set_tsf(local, sdata, tsf); + trace_drv_set_tsf(local, tsf); if (local->ops->set_tsf) - local->ops->set_tsf(&local->hw, &sdata->vif, tsf); + local->ops->set_tsf(&local->hw, tsf); trace_drv_return_void(local); } -static inline void drv_reset_tsf(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata) +static inline void drv_reset_tsf(struct ieee80211_local *local) { might_sleep(); - trace_drv_reset_tsf(local, sdata); + trace_drv_reset_tsf(local); if (local->ops->reset_tsf) - local->ops->reset_tsf(&local->hw, &sdata->vif); + local->ops->reset_tsf(&local->hw); trace_drv_return_void(local); } @@ -671,34 +665,4 @@ static inline void drv_rssi_callback(struct ieee80211_local *local, local->ops->rssi_callback(&local->hw, event); trace_drv_return_void(local); } - -static inline void -drv_release_buffered_frames(struct ieee80211_local *local, - struct sta_info *sta, u16 tids, int num_frames, - enum ieee80211_frame_release_type reason, - bool more_data) -{ - trace_drv_release_buffered_frames(local, &sta->sta, tids, num_frames, - reason, more_data); - if (local->ops->release_buffered_frames) - local->ops->release_buffered_frames(&local->hw, &sta->sta, tids, - num_frames, reason, - more_data); - trace_drv_return_void(local); -} - -static inline void -drv_allow_buffered_frames(struct ieee80211_local *local, - struct sta_info *sta, u16 tids, int num_frames, - enum ieee80211_frame_release_type reason, - bool more_data) -{ - trace_drv_allow_buffered_frames(local, &sta->sta, tids, num_frames, - reason, more_data); - if (local->ops->allow_buffered_frames) - local->ops->allow_buffered_frames(&local->hw, &sta->sta, - tids, num_frames, reason, - more_data); - trace_drv_return_void(local); -} #endif /* __MAC80211_DRIVER_OPS */ diff --git a/trunk/net/mac80211/driver-trace.h b/trunk/net/mac80211/driver-trace.h index 2af4fca55337..f47b00dc7afd 100644 --- a/trunk/net/mac80211/driver-trace.h +++ b/trunk/net/mac80211/driver-trace.h @@ -697,76 +697,64 @@ TRACE_EVENT(drv_sta_remove, ); TRACE_EVENT(drv_conf_tx, - TP_PROTO(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata, - u16 queue, + TP_PROTO(struct ieee80211_local *local, u16 queue, const struct ieee80211_tx_queue_params *params), - TP_ARGS(local, sdata, queue, params), + TP_ARGS(local, queue, params), TP_STRUCT__entry( LOCAL_ENTRY - VIF_ENTRY __field(u16, queue) __field(u16, txop) __field(u16, cw_min) __field(u16, cw_max) __field(u8, aifs) - __field(bool, uapsd) ), TP_fast_assign( LOCAL_ASSIGN; - VIF_ASSIGN; __entry->queue = queue; __entry->txop = params->txop; __entry->cw_max = params->cw_max; __entry->cw_min = params->cw_min; __entry->aifs = params->aifs; - __entry->uapsd = params->uapsd; ), TP_printk( - LOCAL_PR_FMT VIF_PR_FMT " queue:%d", - LOCAL_PR_ARG, VIF_PR_ARG, __entry->queue + LOCAL_PR_FMT " queue:%d", + LOCAL_PR_ARG, __entry->queue ) ); -DEFINE_EVENT(local_sdata_evt, drv_get_tsf, - TP_PROTO(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata), - TP_ARGS(local, sdata) +DEFINE_EVENT(local_only_evt, drv_get_tsf, + TP_PROTO(struct ieee80211_local *local), + TP_ARGS(local) ); TRACE_EVENT(drv_set_tsf, - TP_PROTO(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata, - u64 tsf), + TP_PROTO(struct ieee80211_local *local, u64 tsf), - TP_ARGS(local, sdata, tsf), + TP_ARGS(local, tsf), TP_STRUCT__entry( LOCAL_ENTRY - VIF_ENTRY __field(u64, tsf) ), TP_fast_assign( LOCAL_ASSIGN; - VIF_ASSIGN; __entry->tsf = tsf; ), TP_printk( - LOCAL_PR_FMT VIF_PR_FMT " tsf:%llu", - LOCAL_PR_ARG, VIF_PR_ARG, (unsigned long long)__entry->tsf + LOCAL_PR_FMT " tsf:%llu", + LOCAL_PR_ARG, (unsigned long long)__entry->tsf ) ); -DEFINE_EVENT(local_sdata_evt, drv_reset_tsf, - TP_PROTO(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata), - TP_ARGS(local, sdata) +DEFINE_EVENT(local_only_evt, drv_reset_tsf, + TP_PROTO(struct ieee80211_local *local), + TP_ARGS(local) ); DEFINE_EVENT(local_only_evt, drv_tx_last_beacon, @@ -1129,61 +1117,6 @@ TRACE_EVENT(drv_rssi_callback, ) ); -DECLARE_EVENT_CLASS(release_evt, - TP_PROTO(struct ieee80211_local *local, - struct ieee80211_sta *sta, - u16 tids, int num_frames, - enum ieee80211_frame_release_type reason, - bool more_data), - - TP_ARGS(local, sta, tids, num_frames, reason, more_data), - - TP_STRUCT__entry( - LOCAL_ENTRY - STA_ENTRY - __field(u16, tids) - __field(int, num_frames) - __field(int, reason) - __field(bool, more_data) - ), - - TP_fast_assign( - LOCAL_ASSIGN; - STA_ASSIGN; - __entry->tids = tids; - __entry->num_frames = num_frames; - __entry->reason = reason; - __entry->more_data = more_data; - ), - - TP_printk( - LOCAL_PR_FMT STA_PR_FMT - " TIDs:0x%.4x frames:%d reason:%d more:%d", - LOCAL_PR_ARG, STA_PR_ARG, __entry->tids, __entry->num_frames, - __entry->reason, __entry->more_data - ) -); - -DEFINE_EVENT(release_evt, drv_release_buffered_frames, - TP_PROTO(struct ieee80211_local *local, - struct ieee80211_sta *sta, - u16 tids, int num_frames, - enum ieee80211_frame_release_type reason, - bool more_data), - - TP_ARGS(local, sta, tids, num_frames, reason, more_data) -); - -DEFINE_EVENT(release_evt, drv_allow_buffered_frames, - TP_PROTO(struct ieee80211_local *local, - struct ieee80211_sta *sta, - u16 tids, int num_frames, - enum ieee80211_frame_release_type reason, - bool more_data), - - TP_ARGS(local, sta, tids, num_frames, reason, more_data) -); - /* * Tracing for API calls that drivers call. */ @@ -1498,28 +1431,6 @@ TRACE_EVENT(api_enable_rssi_reports, ) ); -TRACE_EVENT(api_eosp, - TP_PROTO(struct ieee80211_local *local, - struct ieee80211_sta *sta), - - TP_ARGS(local, sta), - - TP_STRUCT__entry( - LOCAL_ENTRY - STA_ENTRY - ), - - TP_fast_assign( - LOCAL_ASSIGN; - STA_ASSIGN; - ), - - TP_printk( - LOCAL_PR_FMT STA_PR_FMT, - LOCAL_PR_ARG, STA_PR_FMT - ) -); - /* * Tracing for internal functions * (which may also be called in response to driver calls) diff --git a/trunk/net/mac80211/ht.c b/trunk/net/mac80211/ht.c index f80a35c0d000..2b9b52c69569 100644 --- a/trunk/net/mac80211/ht.c +++ b/trunk/net/mac80211/ht.c @@ -130,7 +130,7 @@ void ieee80211_ba_session_work(struct work_struct *work) * down by the code that set the flag, so this * need not run. */ - if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) + if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) return; mutex_lock(&sta->ampdu_mlme.mtx); diff --git a/trunk/net/mac80211/ibss.c b/trunk/net/mac80211/ibss.c index 2da3040787a7..836b2752ecd6 100644 --- a/trunk/net/mac80211/ibss.c +++ b/trunk/net/mac80211/ibss.c @@ -81,7 +81,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, lockdep_assert_held(&ifibss->mtx); /* Reset own TSF to allow time synchronization work. */ - drv_reset_tsf(local, sdata); + drv_reset_tsf(local); skb = ifibss->skb; rcu_assign_pointer(ifibss->presp, NULL); @@ -314,7 +314,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, } if (sta && elems->wmm_info) - set_sta_flag(sta, WLAN_STA_WME); + set_sta_flags(sta, WLAN_STA_WME); rcu_read_unlock(); } @@ -382,7 +382,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, * second best option: get current TSF * (will return -1 if not supported) */ - rx_timestamp = drv_get_tsf(local, sdata); + rx_timestamp = drv_get_tsf(local); } #ifdef CONFIG_MAC80211_IBSS_DEBUG @@ -452,7 +452,7 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, return NULL; sta->last_rx = jiffies; - set_sta_flag(sta, WLAN_STA_AUTHORIZED); + set_sta_flags(sta, WLAN_STA_AUTHORIZED); /* make sure mandatory rates are always added */ sta->sta.supp_rates[band] = supp_rates | diff --git a/trunk/net/mac80211/ieee80211_i.h b/trunk/net/mac80211/ieee80211_i.h index 9fa5f8a674bc..21186e280ceb 100644 --- a/trunk/net/mac80211/ieee80211_i.h +++ b/trunk/net/mac80211/ieee80211_i.h @@ -609,8 +609,6 @@ struct ieee80211_sub_if_data { __be16 control_port_protocol; bool control_port_no_encrypt; - struct ieee80211_tx_queue_params tx_conf[IEEE80211_MAX_QUEUES]; - struct work_struct work; struct sk_buff_head skb_queue; @@ -664,11 +662,6 @@ enum sdata_queue_type { enum { IEEE80211_RX_MSG = 1, IEEE80211_TX_STATUS_MSG = 2, - IEEE80211_EOSP_MSG = 3, -}; - -struct skb_eosp_msg_data { - u8 sta[ETH_ALEN], iface[ETH_ALEN]; }; enum queue_stop_reason { @@ -758,6 +751,7 @@ struct ieee80211_local { struct workqueue_struct *workqueue; unsigned long queue_stop_reasons[IEEE80211_MAX_QUEUES]; + struct ieee80211_tx_queue_params tx_conf[IEEE80211_MAX_QUEUES]; /* also used to protect ampdu_ac_queue and amdpu_ac_stop_refcnt */ spinlock_t queue_stop_reason_lock; @@ -1277,7 +1271,6 @@ void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int ke struct ieee80211_hdr *hdr, const u8 *tsc, gfp_t gfp); void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata); -void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); void ieee802_11_parse_elems(u8 *start, size_t len, struct ieee802_11_elems *elems); @@ -1309,11 +1302,11 @@ void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue, enum queue_stop_reason reason); void ieee80211_add_pending_skb(struct ieee80211_local *local, struct sk_buff *skb); -void ieee80211_add_pending_skbs(struct ieee80211_local *local, - struct sk_buff_head *skbs); -void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, - struct sk_buff_head *skbs, - void (*fn)(void *data), void *data); +int ieee80211_add_pending_skbs(struct ieee80211_local *local, + struct sk_buff_head *skbs); +int ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, + struct sk_buff_head *skbs, + void (*fn)(void *data), void *data); void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, u16 transaction, u16 auth_alg, @@ -1331,7 +1324,7 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, const u8 *ssid, size_t ssid_len, const u8 *ie, size_t ie_len, - u32 ratemask, bool directed, bool no_cck); + u32 ratemask, bool directed); void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, const size_t supp_rates_len, diff --git a/trunk/net/mac80211/iface.c b/trunk/net/mac80211/iface.c index ef741e8dbedb..eaa80a3d412b 100644 --- a/trunk/net/mac80211/iface.c +++ b/trunk/net/mac80211/iface.c @@ -299,8 +299,8 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) goto err_del_interface; } - /* no atomic bitop required since STA is not live yet */ - set_sta_flag(sta, WLAN_STA_AUTHORIZED); + /* no locking required since STA is not live yet */ + sta->flags |= WLAN_STA_AUTHORIZED; res = sta_info_insert(sta); if (res) { @@ -460,15 +460,17 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, synchronize_rcu(); kfree(old_beacon); + /* free all potentially still buffered bcast frames */ + while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) { + local->total_ps_buffered--; + dev_kfree_skb(skb); + } + /* down all dependent devices, that is VLANs */ list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans, u.vlan.list) dev_close(vlan->dev); WARN_ON(!list_empty(&sdata->u.ap.vlans)); - - /* free all potentially still buffered bcast frames */ - local->total_ps_buffered -= skb_queue_len(&sdata->u.ap.ps_bc_buf); - skb_queue_purge(&sdata->u.ap.ps_bc_buf); } if (going_down) diff --git a/trunk/net/mac80211/key.c b/trunk/net/mac80211/key.c index 756b157c2edd..5150c6d11b57 100644 --- a/trunk/net/mac80211/key.c +++ b/trunk/net/mac80211/key.c @@ -464,7 +464,7 @@ int ieee80211_key_link(struct ieee80211_key *key, * some hardware cannot handle TKIP with QoS, so * we indicate whether QoS could be in use. */ - if (test_sta_flag(sta, WLAN_STA_WME)) + if (test_sta_flags(sta, WLAN_STA_WME)) key->conf.flags |= IEEE80211_KEY_FLAG_WMM_STA; } else { if (sdata->vif.type == NL80211_IFTYPE_STATION) { @@ -478,7 +478,7 @@ int ieee80211_key_link(struct ieee80211_key *key, /* same here, the AP could be using QoS */ ap = sta_info_get(key->sdata, key->sdata->u.mgd.bssid); if (ap) { - if (test_sta_flag(ap, WLAN_STA_WME)) + if (test_sta_flags(ap, WLAN_STA_WME)) key->conf.flags |= IEEE80211_KEY_FLAG_WMM_STA; } diff --git a/trunk/net/mac80211/main.c b/trunk/net/mac80211/main.c index 17b038aeac9b..a5809a1a6239 100644 --- a/trunk/net/mac80211/main.c +++ b/trunk/net/mac80211/main.c @@ -325,8 +325,6 @@ u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata) static void ieee80211_tasklet_handler(unsigned long data) { struct ieee80211_local *local = (struct ieee80211_local *) data; - struct sta_info *sta, *tmp; - struct skb_eosp_msg_data *eosp_data; struct sk_buff *skb; while ((skb = skb_dequeue(&local->skb_queue)) || @@ -342,18 +340,6 @@ static void ieee80211_tasklet_handler(unsigned long data) skb->pkt_type = 0; ieee80211_tx_status(local_to_hw(local), skb); break; - case IEEE80211_EOSP_MSG: - eosp_data = (void *)skb->cb; - for_each_sta_info(local, eosp_data->sta, sta, tmp) { - /* skip wrong virtual interface */ - if (memcmp(eosp_data->iface, - sta->sdata->vif.addr, ETH_ALEN)) - continue; - clear_sta_flag(sta, WLAN_STA_SP); - break; - } - dev_kfree_skb(skb); - break; default: WARN(1, "mac80211: Packet is of unknown type %d\n", skb->pkt_type); @@ -877,10 +863,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) if (local->ops->sched_scan_start) local->hw.wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; - /* mac80211 based drivers don't support internal TDLS setup */ - if (local->hw.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) - local->hw.wiphy->flags |= WIPHY_FLAG_TDLS_EXTERNAL_SETUP; - result = wiphy_register(local->hw.wiphy); if (result < 0) goto fail_wiphy_register; diff --git a/trunk/net/mac80211/mesh.c b/trunk/net/mac80211/mesh.c index a7078fdba8ca..a4225ae69681 100644 --- a/trunk/net/mac80211/mesh.c +++ b/trunk/net/mac80211/mesh.c @@ -320,6 +320,64 @@ mesh_add_rsn_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) return 0; } +int +mesh_add_srates_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_local *local = sdata->local; + struct ieee80211_supported_band *sband; + int rate; + u8 i, rates, *pos; + + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; + rates = sband->n_bitrates; + if (rates > 8) + rates = 8; + + if (skb_tailroom(skb) < rates + 2) + return -ENOMEM; + + pos = skb_put(skb, rates + 2); + *pos++ = WLAN_EID_SUPP_RATES; + *pos++ = rates; + for (i = 0; i < rates; i++) { + rate = sband->bitrates[i].bitrate; + *pos++ = (u8) (rate / 5); + } + + return 0; +} + +int +mesh_add_ext_srates_ie(struct sk_buff *skb, + struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_local *local = sdata->local; + struct ieee80211_supported_band *sband; + int rate; + u8 i, exrates, *pos; + + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; + exrates = sband->n_bitrates; + if (exrates > 8) + exrates -= 8; + else + exrates = 0; + + if (skb_tailroom(skb) < exrates + 2) + return -ENOMEM; + + if (exrates) { + pos = skb_put(skb, exrates + 2); + *pos++ = WLAN_EID_EXT_SUPP_RATES; + *pos++ = exrates; + for (i = 8; i < sband->n_bitrates; i++) { + rate = sband->bitrates[i].bitrate; + *pos++ = (u8) (rate / 5); + } + } + return 0; +} + int mesh_add_ds_params_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) { diff --git a/trunk/net/mac80211/mesh.h b/trunk/net/mac80211/mesh.h index 8c00e2d1d636..7118e8e8855c 100644 --- a/trunk/net/mac80211/mesh.h +++ b/trunk/net/mac80211/mesh.h @@ -210,6 +210,10 @@ int mesh_add_rsn_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata); int mesh_add_vendor_ies(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata); +int mesh_add_srates_ie(struct sk_buff *skb, + struct ieee80211_sub_if_data *sdata); +int mesh_add_ext_srates_ie(struct sk_buff *skb, + struct ieee80211_sub_if_data *sdata); int mesh_add_ds_params_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata); void mesh_rmc_free(struct ieee80211_sub_if_data *sdata); diff --git a/trunk/net/mac80211/mesh_plink.c b/trunk/net/mac80211/mesh_plink.c index 7e57f5d07f66..4396906175ae 100644 --- a/trunk/net/mac80211/mesh_plink.c +++ b/trunk/net/mac80211/mesh_plink.c @@ -43,10 +43,6 @@ enum plink_event { CLS_IGNR }; -static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, - enum ieee80211_self_protected_actioncode action, - u8 *da, __le16 llid, __le16 plid, __le16 reason); - static inline void mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata) { @@ -92,9 +88,7 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata, if (!sta) return NULL; - set_sta_flag(sta, WLAN_STA_AUTH); - set_sta_flag(sta, WLAN_STA_AUTHORIZED); - set_sta_flag(sta, WLAN_STA_WME); + sta->flags = WLAN_STA_AUTHORIZED | WLAN_STA_AUTH | WLAN_STA_WME; sta->sta.supp_rates[local->hw.conf.channel->band] = rates; rate_control_rate_init(sta); @@ -139,10 +133,6 @@ void mesh_plink_deactivate(struct sta_info *sta) spin_lock_bh(&sta->lock); deactivated = __mesh_plink_deactivate(sta); - sta->reason = cpu_to_le16(WLAN_REASON_MESH_PEER_CANCELED); - mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, - sta->sta.addr, sta->llid, sta->plid, - sta->reason); spin_unlock_bh(&sta->lock); if (deactivated) @@ -187,8 +177,8 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, pos = skb_put(skb, 2); memcpy(pos + 2, &plid, 2); } - if (ieee80211_add_srates_ie(&sdata->vif, skb) || - ieee80211_add_ext_srates_ie(&sdata->vif, skb) || + if (mesh_add_srates_ie(skb, sdata) || + mesh_add_ext_srates_ie(skb, sdata) || mesh_add_rsn_ie(skb, sdata) || mesh_add_meshid_ie(skb, sdata) || mesh_add_meshconf_ie(skb, sdata)) @@ -385,7 +375,7 @@ int mesh_plink_open(struct sta_info *sta) __le16 llid; struct ieee80211_sub_if_data *sdata = sta->sdata; - if (!test_sta_flag(sta, WLAN_STA_AUTH)) + if (!test_sta_flags(sta, WLAN_STA_AUTH)) return -EPERM; spin_lock_bh(&sta->lock); @@ -505,7 +495,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m return; } - if (sta && !test_sta_flag(sta, WLAN_STA_AUTH)) { + if (sta && !test_sta_flags(sta, WLAN_STA_AUTH)) { mpl_dbg("Mesh plink: Action frame from non-authed peer\n"); rcu_read_unlock(); return; diff --git a/trunk/net/mac80211/mlme.c b/trunk/net/mac80211/mlme.c index 0e5d8daba1ee..1a59fb6630d4 100644 --- a/trunk/net/mac80211/mlme.c +++ b/trunk/net/mac80211/mlme.c @@ -348,7 +348,6 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local, { struct sk_buff *skb; struct ieee80211_hdr_3addr *nullfunc; - struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; skb = ieee80211_nullfunc_get(&local->hw, &sdata->vif); if (!skb) @@ -359,10 +358,6 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local, nullfunc->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; - if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL | - IEEE80211_STA_CONNECTION_POLL)) - IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_USE_MINRATE; - ieee80211_tx_skb(sdata, skb); } @@ -632,7 +627,7 @@ static bool ieee80211_powersave_allowed(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_managed *mgd = &sdata->u.mgd; struct sta_info *sta = NULL; - bool authorized = false; + u32 sta_flags = 0; if (!mgd->powersave) return false; @@ -650,10 +645,13 @@ static bool ieee80211_powersave_allowed(struct ieee80211_sub_if_data *sdata) rcu_read_lock(); sta = sta_info_get(sdata, mgd->bssid); if (sta) - authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED); + sta_flags = get_sta_flags(sta); rcu_read_unlock(); - return authorized; + if (!(sta_flags & WLAN_STA_AUTHORIZED)) + return false; + + return true; } /* need to hold RTNL or interface lock */ @@ -938,8 +936,8 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, params.aifs, params.cw_min, params.cw_max, params.txop, params.uapsd); #endif - sdata->tx_conf[queue] = params; - if (drv_conf_tx(local, sdata, queue, ¶ms)) + local->tx_conf[queue] = params; + if (drv_conf_tx(local, queue, ¶ms)) wiphy_debug(local->hw.wiphy, "failed to set TX queue parameters for queue %d\n", queue); @@ -1097,7 +1095,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, mutex_lock(&local->sta_mtx); sta = sta_info_get(sdata, bssid); if (sta) { - set_sta_flag(sta, WLAN_STA_BLOCK_BA); + set_sta_flags(sta, WLAN_STA_BLOCK_BA); ieee80211_sta_tear_down_BA_sessions(sta, tx); } mutex_unlock(&local->sta_mtx); @@ -1139,9 +1137,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, changed |= BSS_CHANGED_BSSID | BSS_CHANGED_HT; ieee80211_bss_info_change_notify(sdata, changed); - /* remove AP and TDLS peers */ if (remove_sta) - sta_info_flush(local, sdata); + sta_info_destroy_addr(sdata, bssid); del_timer_sync(&sdata->u.mgd.conn_mon_timer); del_timer_sync(&sdata->u.mgd.bcn_mon_timer); @@ -1242,7 +1239,7 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) } else { ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0, - (u32) -1, true, false); + (u32) -1, true); } ifmgd->probe_send_count++; @@ -1515,11 +1512,10 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, return false; } - set_sta_flag(sta, WLAN_STA_AUTH); - set_sta_flag(sta, WLAN_STA_ASSOC); - set_sta_flag(sta, WLAN_STA_ASSOC_AP); + set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC | + WLAN_STA_ASSOC_AP); if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) - set_sta_flag(sta, WLAN_STA_AUTHORIZED); + set_sta_flags(sta, WLAN_STA_AUTHORIZED); rates = 0; basic_rates = 0; @@ -1578,10 +1574,10 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, rate_control_rate_init(sta); if (ifmgd->flags & IEEE80211_STA_MFP_ENABLED) - set_sta_flag(sta, WLAN_STA_MFP); + set_sta_flags(sta, WLAN_STA_MFP); if (elems.wmm_param) - set_sta_flag(sta, WLAN_STA_WME); + set_sta_flags(sta, WLAN_STA_WME); /* sta_info_reinsert will also unlock the mutex lock */ err = sta_info_reinsert(sta); @@ -2742,7 +2738,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, req->reason_code, cookie, !req->local_state_change); if (assoc_bss) - sta_info_flush(sdata->local, sdata); + sta_info_destroy_addr(sdata, bssid); mutex_lock(&sdata->local->mtx); ieee80211_recalc_idle(sdata->local); @@ -2782,7 +2778,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, ieee80211_send_deauth_disassoc(sdata, req->bss->bssid, IEEE80211_STYPE_DISASSOC, req->reason_code, cookie, !req->local_state_change); - sta_info_flush(sdata->local, sdata); + sta_info_destroy_addr(sdata, bssid); mutex_lock(&sdata->local->mtx); ieee80211_recalc_idle(sdata->local); diff --git a/trunk/net/mac80211/pm.c b/trunk/net/mac80211/pm.c index 9ee7164b207c..6326d3439861 100644 --- a/trunk/net/mac80211/pm.c +++ b/trunk/net/mac80211/pm.c @@ -42,7 +42,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { mutex_lock(&local->sta_mtx); list_for_each_entry(sta, &local->sta_list, list) { - set_sta_flag(sta, WLAN_STA_BLOCK_BA); + set_sta_flags(sta, WLAN_STA_BLOCK_BA); ieee80211_sta_tear_down_BA_sessions(sta, true); } mutex_unlock(&local->sta_mtx); diff --git a/trunk/net/mac80211/rate.c b/trunk/net/mac80211/rate.c index ff5c3aa48a15..3d5a2cb835c4 100644 --- a/trunk/net/mac80211/rate.c +++ b/trunk/net/mac80211/rate.c @@ -199,7 +199,7 @@ static void rate_control_release(struct kref *kref) kfree(ctrl_ref); } -static bool rc_no_data_or_no_ack_use_min(struct ieee80211_tx_rate_control *txrc) +static bool rc_no_data_or_no_ack(struct ieee80211_tx_rate_control *txrc) { struct sk_buff *skb = txrc->skb; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; @@ -208,9 +208,7 @@ static bool rc_no_data_or_no_ack_use_min(struct ieee80211_tx_rate_control *txrc) fc = hdr->frame_control; - return (info->flags & (IEEE80211_TX_CTL_NO_ACK | - IEEE80211_TX_CTL_USE_MINRATE)) || - !ieee80211_is_data(fc); + return (info->flags & IEEE80211_TX_CTL_NO_ACK) || !ieee80211_is_data(fc); } static void rc_send_low_broadcast(s8 *idx, u32 basic_rates, @@ -235,27 +233,6 @@ static void rc_send_low_broadcast(s8 *idx, u32 basic_rates, /* could not find a basic rate; use original selection */ } -static inline s8 -rate_lowest_non_cck_index(struct ieee80211_supported_band *sband, - struct ieee80211_sta *sta) -{ - int i; - - for (i = 0; i < sband->n_bitrates; i++) { - struct ieee80211_rate *srate = &sband->bitrates[i]; - if ((srate->bitrate == 10) || (srate->bitrate == 20) || - (srate->bitrate == 55) || (srate->bitrate == 110)) - continue; - - if (rate_supported(sta, sband->band, i)) - return i; - } - - /* No matching rate found */ - return 0; -} - - bool rate_control_send_low(struct ieee80211_sta *sta, void *priv_sta, struct ieee80211_tx_rate_control *txrc) @@ -264,14 +241,8 @@ bool rate_control_send_low(struct ieee80211_sta *sta, struct ieee80211_supported_band *sband = txrc->sband; int mcast_rate; - if (!sta || !priv_sta || rc_no_data_or_no_ack_use_min(txrc)) { - if ((sband->band != IEEE80211_BAND_2GHZ) || - !(info->flags & IEEE80211_TX_CTL_NO_CCK_RATE)) - info->control.rates[0].idx = - rate_lowest_index(txrc->sband, sta); - else - info->control.rates[0].idx = - rate_lowest_non_cck_index(txrc->sband, sta); + if (!sta || !priv_sta || rc_no_data_or_no_ack(txrc)) { + info->control.rates[0].idx = rate_lowest_index(txrc->sband, sta); info->control.rates[0].count = (info->flags & IEEE80211_TX_CTL_NO_ACK) ? 1 : txrc->hw->max_rate_tries; diff --git a/trunk/net/mac80211/rc80211_minstrel_ht.c b/trunk/net/mac80211/rc80211_minstrel_ht.c index cdb28535716b..e19249b0f971 100644 --- a/trunk/net/mac80211/rc80211_minstrel_ht.c +++ b/trunk/net/mac80211/rc80211_minstrel_ht.c @@ -281,8 +281,6 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) mr = minstrel_get_ratestats(mi, mg->max_tp_rate); if (cur_tp < mr->cur_tp) { - mi->max_tp_rate2 = mi->max_tp_rate; - cur_tp2 = cur_tp; mi->max_tp_rate = mg->max_tp_rate; cur_tp = mr->cur_tp; } diff --git a/trunk/net/mac80211/rx.c b/trunk/net/mac80211/rx.c index b867bd55de7a..db46601e50bf 100644 --- a/trunk/net/mac80211/rx.c +++ b/trunk/net/mac80211/rx.c @@ -841,7 +841,7 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) ieee80211_is_pspoll(hdr->frame_control)) && rx->sdata->vif.type != NL80211_IFTYPE_ADHOC && rx->sdata->vif.type != NL80211_IFTYPE_WDS && - (!rx->sta || !test_sta_flag(rx->sta, WLAN_STA_ASSOC)))) { + (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) { if (rx->sta && rx->sta->dummy && ieee80211_is_data_present(hdr->frame_control)) { u16 ethertype; @@ -1110,7 +1110,7 @@ static void ap_sta_ps_start(struct sta_info *sta) struct ieee80211_local *local = sdata->local; atomic_inc(&sdata->bss->num_sta_ps); - set_sta_flag(sta, WLAN_STA_PS_STA); + set_sta_flags(sta, WLAN_STA_PS_STA); if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS)) drv_sta_notify(local, sdata, STA_NOTIFY_SLEEP, &sta->sta); #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG @@ -1130,7 +1130,7 @@ static void ap_sta_ps_end(struct sta_info *sta) sdata->name, sta->sta.addr, sta->sta.aid); #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ - if (test_sta_flag(sta, WLAN_STA_PS_DRIVER)) { + if (test_sta_flags(sta, WLAN_STA_PS_DRIVER)) { #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG printk(KERN_DEBUG "%s: STA %pM aid %d driver-ps-blocked\n", sdata->name, sta->sta.addr, sta->sta.aid); @@ -1149,7 +1149,7 @@ int ieee80211_sta_ps_transition(struct ieee80211_sta *sta, bool start) WARN_ON(!(sta_inf->local->hw.flags & IEEE80211_HW_AP_LINK_PS)); /* Don't let the same PS state be set twice */ - in_ps = test_sta_flag(sta_inf, WLAN_STA_PS_STA); + in_ps = test_sta_flags(sta_inf, WLAN_STA_PS_STA); if ((start && in_ps) || (!start && !in_ps)) return -EINVAL; @@ -1162,81 +1162,6 @@ int ieee80211_sta_ps_transition(struct ieee80211_sta *sta, bool start) } EXPORT_SYMBOL(ieee80211_sta_ps_transition); -static ieee80211_rx_result debug_noinline -ieee80211_rx_h_uapsd_and_pspoll(struct ieee80211_rx_data *rx) -{ - struct ieee80211_sub_if_data *sdata = rx->sdata; - struct ieee80211_hdr *hdr = (void *)rx->skb->data; - struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); - int tid, ac; - - if (!rx->sta || !(status->rx_flags & IEEE80211_RX_RA_MATCH)) - return RX_CONTINUE; - - if (sdata->vif.type != NL80211_IFTYPE_AP && - sdata->vif.type != NL80211_IFTYPE_AP_VLAN) - return RX_CONTINUE; - - /* - * The device handles station powersave, so don't do anything about - * uAPSD and PS-Poll frames (the latter shouldn't even come up from - * it to mac80211 since they're handled.) - */ - if (sdata->local->hw.flags & IEEE80211_HW_AP_LINK_PS) - return RX_CONTINUE; - - /* - * Don't do anything if the station isn't already asleep. In - * the uAPSD case, the station will probably be marked asleep, - * in the PS-Poll case the station must be confused ... - */ - if (!test_sta_flag(rx->sta, WLAN_STA_PS_STA)) - return RX_CONTINUE; - - if (unlikely(ieee80211_is_pspoll(hdr->frame_control))) { - if (!test_sta_flag(rx->sta, WLAN_STA_SP)) { - if (!test_sta_flag(rx->sta, WLAN_STA_PS_DRIVER)) - ieee80211_sta_ps_deliver_poll_response(rx->sta); - else - set_sta_flag(rx->sta, WLAN_STA_PSPOLL); - } - - /* Free PS Poll skb here instead of returning RX_DROP that would - * count as an dropped frame. */ - dev_kfree_skb(rx->skb); - - return RX_QUEUED; - } else if (!ieee80211_has_morefrags(hdr->frame_control) && - !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) && - ieee80211_has_pm(hdr->frame_control) && - (ieee80211_is_data_qos(hdr->frame_control) || - ieee80211_is_qos_nullfunc(hdr->frame_control))) { - tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; - ac = ieee802_1d_to_ac[tid & 7]; - - /* - * If this AC is not trigger-enabled do nothing. - * - * NB: This could/should check a separate bitmap of trigger- - * enabled queues, but for now we only implement uAPSD w/o - * TSPEC changes to the ACs, so they're always the same. - */ - if (!(rx->sta->sta.uapsd_queues & BIT(ac))) - return RX_CONTINUE; - - /* if we are in a service period, do nothing */ - if (test_sta_flag(rx->sta, WLAN_STA_SP)) - return RX_CONTINUE; - - if (!test_sta_flag(rx->sta, WLAN_STA_PS_DRIVER)) - ieee80211_sta_ps_deliver_uapsd(rx->sta); - else - set_sta_flag(rx->sta, WLAN_STA_UAPSD); - } - - return RX_CONTINUE; -} - static ieee80211_rx_result debug_noinline ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) { @@ -1295,7 +1220,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) && (rx->sdata->vif.type == NL80211_IFTYPE_AP || rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) { - if (test_sta_flag(sta, WLAN_STA_PS_STA)) { + if (test_sta_flags(sta, WLAN_STA_PS_STA)) { /* * Ignore doze->wake transitions that are * indicated by non-data frames, the standard @@ -1547,6 +1472,33 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) return RX_CONTINUE; } +static ieee80211_rx_result debug_noinline +ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx) +{ + struct ieee80211_sub_if_data *sdata = rx->sdata; + __le16 fc = ((struct ieee80211_hdr *)rx->skb->data)->frame_control; + struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); + + if (likely(!rx->sta || !ieee80211_is_pspoll(fc) || + !(status->rx_flags & IEEE80211_RX_RA_MATCH))) + return RX_CONTINUE; + + if ((sdata->vif.type != NL80211_IFTYPE_AP) && + (sdata->vif.type != NL80211_IFTYPE_AP_VLAN)) + return RX_DROP_UNUSABLE; + + if (!test_sta_flags(rx->sta, WLAN_STA_PS_DRIVER)) + ieee80211_sta_ps_deliver_poll_response(rx->sta); + else + set_sta_flags(rx->sta, WLAN_STA_PSPOLL); + + /* Free PS Poll skb here instead of returning RX_DROP that would + * count as an dropped frame. */ + dev_kfree_skb(rx->skb); + + return RX_QUEUED; +} + static ieee80211_rx_result debug_noinline ieee80211_rx_h_remove_qos_control(struct ieee80211_rx_data *rx) { @@ -1570,7 +1522,7 @@ static int ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx) { if (unlikely(!rx->sta || - !test_sta_flag(rx->sta, WLAN_STA_AUTHORIZED))) + !test_sta_flags(rx->sta, WLAN_STA_AUTHORIZED))) return -EACCES; return 0; @@ -1613,7 +1565,7 @@ ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx) if (status->flag & RX_FLAG_DECRYPTED) return 0; - if (rx->sta && test_sta_flag(rx->sta, WLAN_STA_MFP)) { + if (rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP)) { if (unlikely(!ieee80211_has_protected(fc) && ieee80211_is_unicast_robust_mgmt_frame(rx->skb) && rx->key)) { @@ -2615,9 +2567,9 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx) CALL_RXH(ieee80211_rx_h_decrypt) CALL_RXH(ieee80211_rx_h_check_more_data) - CALL_RXH(ieee80211_rx_h_uapsd_and_pspoll) CALL_RXH(ieee80211_rx_h_sta_process) CALL_RXH(ieee80211_rx_h_defragment) + CALL_RXH(ieee80211_rx_h_ps_poll) CALL_RXH(ieee80211_rx_h_michael_mic_verify) /* must be after MMIC verify so header is counted in MPDU mic */ #ifdef CONFIG_MAC80211_MESH diff --git a/trunk/net/mac80211/scan.c b/trunk/net/mac80211/scan.c index 830e60f65779..6f09eca01112 100644 --- a/trunk/net/mac80211/scan.c +++ b/trunk/net/mac80211/scan.c @@ -660,8 +660,7 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local, local->scan_req->ssids[i].ssid, local->scan_req->ssids[i].ssid_len, local->scan_req->ie, local->scan_req->ie_len, - local->scan_req->rates[band], false, - local->scan_req->no_cck); + local->scan_req->rates[band], false); /* * After sending probe requests, wait for probe responses diff --git a/trunk/net/mac80211/sta_info.c b/trunk/net/mac80211/sta_info.c index 076593bffbcf..c52e58c0a979 100644 --- a/trunk/net/mac80211/sta_info.c +++ b/trunk/net/mac80211/sta_info.c @@ -24,7 +24,6 @@ #include "sta_info.h" #include "debugfs_sta.h" #include "mesh.h" -#include "wme.h" /** * DOC: STA information lifetime rules @@ -244,22 +243,13 @@ static void sta_unblock(struct work_struct *wk) if (sta->dead) return; - if (!test_sta_flag(sta, WLAN_STA_PS_STA)) + if (!test_sta_flags(sta, WLAN_STA_PS_STA)) ieee80211_sta_ps_deliver_wakeup(sta); - else if (test_and_clear_sta_flag(sta, WLAN_STA_PSPOLL)) { - clear_sta_flag(sta, WLAN_STA_PS_DRIVER); - - local_bh_disable(); + else if (test_and_clear_sta_flags(sta, WLAN_STA_PSPOLL)) { + clear_sta_flags(sta, WLAN_STA_PS_DRIVER); ieee80211_sta_ps_deliver_poll_response(sta); - local_bh_enable(); - } else if (test_and_clear_sta_flag(sta, WLAN_STA_UAPSD)) { - clear_sta_flag(sta, WLAN_STA_PS_DRIVER); - - local_bh_disable(); - ieee80211_sta_ps_deliver_uapsd(sta); - local_bh_enable(); } else - clear_sta_flag(sta, WLAN_STA_PS_DRIVER); + clear_sta_flags(sta, WLAN_STA_PS_DRIVER); } static int sta_prepare_rate_control(struct ieee80211_local *local, @@ -292,6 +282,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, return NULL; spin_lock_init(&sta->lock); + spin_lock_init(&sta->flaglock); INIT_WORK(&sta->drv_unblock_wk, sta_unblock); INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work); mutex_init(&sta->ampdu_mlme.mtx); @@ -318,10 +309,8 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, */ sta->timer_to_tid[i] = i; } - for (i = 0; i < IEEE80211_NUM_ACS; i++) { - skb_queue_head_init(&sta->ps_tx_buf[i]); - skb_queue_head_init(&sta->tx_filtered[i]); - } + skb_queue_head_init(&sta->ps_tx_buf); + skb_queue_head_init(&sta->tx_filtered); for (i = 0; i < NUM_RX_DATA_QUEUES; i++) sta->last_seq_ctrl[i] = cpu_to_le16(USHRT_MAX); @@ -652,84 +641,54 @@ static inline void __bss_tim_clear(struct ieee80211_if_ap *bss, u16 aid) bss->tim[aid / 8] &= ~(1 << (aid % 8)); } -static unsigned long ieee80211_tids_for_ac(int ac) +static void __sta_info_set_tim_bit(struct ieee80211_if_ap *bss, + struct sta_info *sta) { - /* If we ever support TIDs > 7, this obviously needs to be adjusted */ - switch (ac) { - case IEEE80211_AC_VO: - return BIT(6) | BIT(7); - case IEEE80211_AC_VI: - return BIT(4) | BIT(5); - case IEEE80211_AC_BE: - return BIT(0) | BIT(3); - case IEEE80211_AC_BK: - return BIT(1) | BIT(2); - default: - WARN_ON(1); - return 0; + BUG_ON(!bss); + + __bss_tim_set(bss, sta->sta.aid); + + if (sta->local->ops->set_tim) { + sta->local->tim_in_locked_section = true; + drv_set_tim(sta->local, &sta->sta, true); + sta->local->tim_in_locked_section = false; } } -void sta_info_recalc_tim(struct sta_info *sta) +void sta_info_set_tim_bit(struct sta_info *sta) { - struct ieee80211_local *local = sta->local; - struct ieee80211_if_ap *bss = sta->sdata->bss; unsigned long flags; - bool indicate_tim = false; - u8 ignore_for_tim = sta->sta.uapsd_queues; - int ac; - if (WARN_ON_ONCE(!sta->sdata->bss)) - return; + BUG_ON(!sta->sdata->bss); - /* No need to do anything if the driver does all */ - if (local->hw.flags & IEEE80211_HW_AP_LINK_PS) - return; - - if (sta->dead) - goto done; - - /* - * If all ACs are delivery-enabled then we should build - * the TIM bit for all ACs anyway; if only some are then - * we ignore those and build the TIM bit using only the - * non-enabled ones. - */ - if (ignore_for_tim == BIT(IEEE80211_NUM_ACS) - 1) - ignore_for_tim = 0; - - for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { - unsigned long tids; - - if (ignore_for_tim & BIT(ac)) - continue; + spin_lock_irqsave(&sta->local->sta_lock, flags); + __sta_info_set_tim_bit(sta->sdata->bss, sta); + spin_unlock_irqrestore(&sta->local->sta_lock, flags); +} - indicate_tim |= !skb_queue_empty(&sta->tx_filtered[ac]) || - !skb_queue_empty(&sta->ps_tx_buf[ac]); - if (indicate_tim) - break; +static void __sta_info_clear_tim_bit(struct ieee80211_if_ap *bss, + struct sta_info *sta) +{ + BUG_ON(!bss); - tids = ieee80211_tids_for_ac(ac); + __bss_tim_clear(bss, sta->sta.aid); - indicate_tim |= - sta->driver_buffered_tids & tids; + if (sta->local->ops->set_tim) { + sta->local->tim_in_locked_section = true; + drv_set_tim(sta->local, &sta->sta, false); + sta->local->tim_in_locked_section = false; } +} - done: - spin_lock_irqsave(&local->sta_lock, flags); - - if (indicate_tim) - __bss_tim_set(bss, sta->sta.aid); - else - __bss_tim_clear(bss, sta->sta.aid); +void sta_info_clear_tim_bit(struct sta_info *sta) +{ + unsigned long flags; - if (local->ops->set_tim) { - local->tim_in_locked_section = true; - drv_set_tim(local, &sta->sta, indicate_tim); - local->tim_in_locked_section = false; - } + BUG_ON(!sta->sdata->bss); - spin_unlock_irqrestore(&local->sta_lock, flags); + spin_lock_irqsave(&sta->local->sta_lock, flags); + __sta_info_clear_tim_bit(sta->sdata->bss, sta); + spin_unlock_irqrestore(&sta->local->sta_lock, flags); } static bool sta_info_buffer_expired(struct sta_info *sta, struct sk_buff *skb) @@ -752,59 +711,21 @@ static bool sta_info_buffer_expired(struct sta_info *sta, struct sk_buff *skb) } -static bool sta_info_cleanup_expire_buffered_ac(struct ieee80211_local *local, - struct sta_info *sta, int ac) +static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local, + struct sta_info *sta) { unsigned long flags; struct sk_buff *skb; - /* - * First check for frames that should expire on the filtered - * queue. Frames here were rejected by the driver and are on - * a separate queue to avoid reordering with normal PS-buffered - * frames. They also aren't accounted for right now in the - * total_ps_buffered counter. - */ - for (;;) { - spin_lock_irqsave(&sta->tx_filtered[ac].lock, flags); - skb = skb_peek(&sta->tx_filtered[ac]); - if (sta_info_buffer_expired(sta, skb)) - skb = __skb_dequeue(&sta->tx_filtered[ac]); - else - skb = NULL; - spin_unlock_irqrestore(&sta->tx_filtered[ac].lock, flags); - - /* - * Frames are queued in order, so if this one - * hasn't expired yet we can stop testing. If - * we actually reached the end of the queue we - * also need to stop, of course. - */ - if (!skb) - break; - dev_kfree_skb(skb); - } - - /* - * Now also check the normal PS-buffered queue, this will - * only find something if the filtered queue was emptied - * since the filtered frames are all before the normal PS - * buffered frames. - */ for (;;) { - spin_lock_irqsave(&sta->ps_tx_buf[ac].lock, flags); - skb = skb_peek(&sta->ps_tx_buf[ac]); + spin_lock_irqsave(&sta->ps_tx_buf.lock, flags); + skb = skb_peek(&sta->ps_tx_buf); if (sta_info_buffer_expired(sta, skb)) - skb = __skb_dequeue(&sta->ps_tx_buf[ac]); + skb = __skb_dequeue(&sta->ps_tx_buf); else skb = NULL; - spin_unlock_irqrestore(&sta->ps_tx_buf[ac].lock, flags); + spin_unlock_irqrestore(&sta->ps_tx_buf.lock, flags); - /* - * frames are queued in order, so if this one - * hasn't expired yet (or we reached the end of - * the queue) we can stop testing - */ if (!skb) break; @@ -814,47 +735,22 @@ static bool sta_info_cleanup_expire_buffered_ac(struct ieee80211_local *local, sta->sta.addr); #endif dev_kfree_skb(skb); - } - /* - * Finally, recalculate the TIM bit for this station -- it might - * now be clear because the station was too slow to retrieve its - * frames. - */ - sta_info_recalc_tim(sta); - - /* - * Return whether there are any frames still buffered, this is - * used to check whether the cleanup timer still needs to run, - * if there are no frames we don't need to rearm the timer. - */ - return !(skb_queue_empty(&sta->ps_tx_buf[ac]) && - skb_queue_empty(&sta->tx_filtered[ac])); -} - -static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local, - struct sta_info *sta) -{ - bool have_buffered = false; - int ac; - - /* This is only necessary for stations on BSS interfaces */ - if (!sta->sdata->bss) - return false; - - for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) - have_buffered |= - sta_info_cleanup_expire_buffered_ac(local, sta, ac); + if (skb_queue_empty(&sta->ps_tx_buf) && + !test_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF)) + sta_info_clear_tim_bit(sta); + } - return have_buffered; + return !skb_queue_empty(&sta->ps_tx_buf); } static int __must_check __sta_info_destroy(struct sta_info *sta) { struct ieee80211_local *local; struct ieee80211_sub_if_data *sdata; + struct sk_buff *skb; unsigned long flags; - int ret, i, ac; + int ret, i; might_sleep(); @@ -870,7 +766,7 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) * sessions -- block that to make sure the tear-down * will be sufficient. */ - set_sta_flag(sta, WLAN_STA_BLOCK_BA); + set_sta_flags(sta, WLAN_STA_BLOCK_BA); ieee80211_sta_tear_down_BA_sessions(sta, true); spin_lock_irqsave(&local->sta_lock, flags); @@ -891,15 +787,12 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) sta->dead = true; - if (test_sta_flag(sta, WLAN_STA_PS_STA) || - test_sta_flag(sta, WLAN_STA_PS_DRIVER)) { + if (test_and_clear_sta_flags(sta, + WLAN_STA_PS_STA | WLAN_STA_PS_DRIVER)) { BUG_ON(!sdata->bss); - clear_sta_flag(sta, WLAN_STA_PS_STA); - clear_sta_flag(sta, WLAN_STA_PS_DRIVER); - atomic_dec(&sdata->bss->num_sta_ps); - sta_info_recalc_tim(sta); + sta_info_clear_tim_bit(sta); } local->num_sta--; @@ -925,12 +818,6 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) */ synchronize_rcu(); - for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { - local->total_ps_buffered -= skb_queue_len(&sta->ps_tx_buf[ac]); - __skb_queue_purge(&sta->ps_tx_buf[ac]); - __skb_queue_purge(&sta->tx_filtered[ac]); - } - #ifdef CONFIG_MAC80211_MESH if (ieee80211_vif_is_mesh(&sdata->vif)) mesh_accept_plinks_update(sdata); @@ -953,6 +840,14 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) } #endif + while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) { + local->total_ps_buffered--; + dev_kfree_skb_any(skb); + } + + while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) + dev_kfree_skb_any(skb); + __sta_info_free(local, sta); return 0; @@ -1118,8 +1013,7 @@ static void clear_sta_ps_flags(void *_sta) { struct sta_info *sta = _sta; - clear_sta_flag(sta, WLAN_STA_PS_DRIVER); - clear_sta_flag(sta, WLAN_STA_PS_STA); + clear_sta_flags(sta, WLAN_STA_PS_DRIVER | WLAN_STA_PS_STA); } /* powersave support code */ @@ -1127,341 +1021,86 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) { struct ieee80211_sub_if_data *sdata = sta->sdata; struct ieee80211_local *local = sdata->local; - struct sk_buff_head pending; - int filtered = 0, buffered = 0, ac; - - clear_sta_flag(sta, WLAN_STA_SP); - - BUILD_BUG_ON(BITS_TO_LONGS(STA_TID_NUM) > 1); - sta->driver_buffered_tids = 0; + int sent, buffered; + clear_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF); if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS)) drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta); - skb_queue_head_init(&pending); + if (!skb_queue_empty(&sta->ps_tx_buf)) + sta_info_clear_tim_bit(sta); /* Send all buffered frames to the station */ - for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { - int count = skb_queue_len(&pending), tmp; - - skb_queue_splice_tail_init(&sta->tx_filtered[ac], &pending); - tmp = skb_queue_len(&pending); - filtered += tmp - count; - count = tmp; - - skb_queue_splice_tail_init(&sta->ps_tx_buf[ac], &pending); - tmp = skb_queue_len(&pending); - buffered += tmp - count; - } - - ieee80211_add_pending_skbs_fn(local, &pending, clear_sta_ps_flags, sta); - + sent = ieee80211_add_pending_skbs(local, &sta->tx_filtered); + buffered = ieee80211_add_pending_skbs_fn(local, &sta->ps_tx_buf, + clear_sta_ps_flags, sta); + sent += buffered; local->total_ps_buffered -= buffered; - sta_info_recalc_tim(sta); - #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG printk(KERN_DEBUG "%s: STA %pM aid %d sending %d filtered/%d PS frames " "since STA not sleeping anymore\n", sdata->name, - sta->sta.addr, sta->sta.aid, filtered, buffered); + sta->sta.addr, sta->sta.aid, sent - buffered, buffered); #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ } -static void ieee80211_send_null_response(struct ieee80211_sub_if_data *sdata, - struct sta_info *sta, int tid, - enum ieee80211_frame_release_type reason) -{ - struct ieee80211_local *local = sdata->local; - struct ieee80211_qos_hdr *nullfunc; - struct sk_buff *skb; - int size = sizeof(*nullfunc); - __le16 fc; - bool qos = test_sta_flag(sta, WLAN_STA_WME); - struct ieee80211_tx_info *info; - - if (qos) { - fc = cpu_to_le16(IEEE80211_FTYPE_DATA | - IEEE80211_STYPE_QOS_NULLFUNC | - IEEE80211_FCTL_FROMDS); - } else { - size -= 2; - fc = cpu_to_le16(IEEE80211_FTYPE_DATA | - IEEE80211_STYPE_NULLFUNC | - IEEE80211_FCTL_FROMDS); - } - - skb = dev_alloc_skb(local->hw.extra_tx_headroom + size); - if (!skb) - return; - - skb_reserve(skb, local->hw.extra_tx_headroom); - - nullfunc = (void *) skb_put(skb, size); - nullfunc->frame_control = fc; - nullfunc->duration_id = 0; - memcpy(nullfunc->addr1, sta->sta.addr, ETH_ALEN); - memcpy(nullfunc->addr2, sdata->vif.addr, ETH_ALEN); - memcpy(nullfunc->addr3, sdata->vif.addr, ETH_ALEN); - - if (qos) { - skb->priority = tid; - - skb_set_queue_mapping(skb, ieee802_1d_to_ac[tid]); - - nullfunc->qos_ctrl = cpu_to_le16(tid); - - if (reason == IEEE80211_FRAME_RELEASE_UAPSD) - nullfunc->qos_ctrl |= - cpu_to_le16(IEEE80211_QOS_CTL_EOSP); - } - - info = IEEE80211_SKB_CB(skb); - - /* - * Tell TX path to send this frame even though the - * STA may still remain is PS mode after this frame - * exchange. Also set EOSP to indicate this packet - * ends the poll/service period. - */ - info->flags |= IEEE80211_TX_CTL_POLL_RESPONSE | - IEEE80211_TX_STATUS_EOSP | - IEEE80211_TX_CTL_REQ_TX_STATUS; - - drv_allow_buffered_frames(local, sta, BIT(tid), 1, reason, false); - - ieee80211_xmit(sdata, skb); -} - -static void -ieee80211_sta_ps_deliver_response(struct sta_info *sta, - int n_frames, u8 ignored_acs, - enum ieee80211_frame_release_type reason) +void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta) { struct ieee80211_sub_if_data *sdata = sta->sdata; struct ieee80211_local *local = sdata->local; - bool found = false; - bool more_data = false; - int ac; - unsigned long driver_release_tids = 0; - struct sk_buff_head frames; - - /* Service or PS-Poll period starts */ - set_sta_flag(sta, WLAN_STA_SP); - - __skb_queue_head_init(&frames); - - /* - * Get response frame(s) and more data bit for it. - */ - for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { - unsigned long tids; - - if (ignored_acs & BIT(ac)) - continue; - - tids = ieee80211_tids_for_ac(ac); - - if (!found) { - driver_release_tids = sta->driver_buffered_tids & tids; - if (driver_release_tids) { - found = true; - } else { - struct sk_buff *skb; - - while (n_frames > 0) { - skb = skb_dequeue(&sta->tx_filtered[ac]); - if (!skb) { - skb = skb_dequeue( - &sta->ps_tx_buf[ac]); - if (skb) - local->total_ps_buffered--; - } - if (!skb) - break; - n_frames--; - found = true; - __skb_queue_tail(&frames, skb); - } - } - - /* - * If the driver has data on more than one TID then - * certainly there's more data if we release just a - * single frame now (from a single TID). - */ - if (reason == IEEE80211_FRAME_RELEASE_PSPOLL && - hweight16(driver_release_tids) > 1) { - more_data = true; - driver_release_tids = - BIT(ffs(driver_release_tids) - 1); - break; - } - } + struct sk_buff *skb; + int no_pending_pkts; - if (!skb_queue_empty(&sta->tx_filtered[ac]) || - !skb_queue_empty(&sta->ps_tx_buf[ac])) { - more_data = true; - break; - } + skb = skb_dequeue(&sta->tx_filtered); + if (!skb) { + skb = skb_dequeue(&sta->ps_tx_buf); + if (skb) + local->total_ps_buffered--; } + no_pending_pkts = skb_queue_empty(&sta->tx_filtered) && + skb_queue_empty(&sta->ps_tx_buf); - if (!found) { - int tid; + if (skb) { + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_hdr *hdr = + (struct ieee80211_hdr *) skb->data; /* - * For PS-Poll, this can only happen due to a race condition - * when we set the TIM bit and the station notices it, but - * before it can poll for the frame we expire it. - * - * For uAPSD, this is said in the standard (11.2.1.5 h): - * At each unscheduled SP for a non-AP STA, the AP shall - * attempt to transmit at least one MSDU or MMPDU, but no - * more than the value specified in the Max SP Length field - * in the QoS Capability element from delivery-enabled ACs, - * that are destined for the non-AP STA. - * - * Since we have no other MSDU/MMPDU, transmit a QoS null frame. + * Tell TX path to send this frame even though the STA may + * still remain is PS mode after this frame exchange. */ + info->flags |= IEEE80211_TX_CTL_PSPOLL_RESPONSE; - /* This will evaluate to 1, 3, 5 or 7. */ - tid = 7 - ((ffs(~ignored_acs) - 1) << 1); - - ieee80211_send_null_response(sdata, sta, tid, reason); - return; - } - - if (!driver_release_tids) { - struct sk_buff_head pending; - struct sk_buff *skb; - int num = 0; - u16 tids = 0; - - skb_queue_head_init(&pending); - - while ((skb = __skb_dequeue(&frames))) { - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_hdr *hdr = (void *) skb->data; - u8 *qoshdr = NULL; - - num++; - - /* - * Tell TX path to send this frame even though the - * STA may still remain is PS mode after this frame - * exchange. - */ - info->flags |= IEEE80211_TX_CTL_POLL_RESPONSE; - - /* - * Use MoreData flag to indicate whether there are - * more buffered frames for this STA - */ - if (!more_data) - hdr->frame_control &= - cpu_to_le16(~IEEE80211_FCTL_MOREDATA); - else - hdr->frame_control |= - cpu_to_le16(IEEE80211_FCTL_MOREDATA); - - if (ieee80211_is_data_qos(hdr->frame_control) || - ieee80211_is_qos_nullfunc(hdr->frame_control)) - qoshdr = ieee80211_get_qos_ctl(hdr); - - /* set EOSP for the frame */ - if (reason == IEEE80211_FRAME_RELEASE_UAPSD && - qoshdr && skb_queue_empty(&frames)) - *qoshdr |= IEEE80211_QOS_CTL_EOSP; - - info->flags |= IEEE80211_TX_STATUS_EOSP | - IEEE80211_TX_CTL_REQ_TX_STATUS; - - if (qoshdr) - tids |= BIT(*qoshdr & IEEE80211_QOS_CTL_TID_MASK); - else - tids |= BIT(0); - - __skb_queue_tail(&pending, skb); - } +#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG + printk(KERN_DEBUG "STA %pM aid %d: PS Poll (entries after %d)\n", + sta->sta.addr, sta->sta.aid, + skb_queue_len(&sta->ps_tx_buf)); +#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ - drv_allow_buffered_frames(local, sta, tids, num, - reason, more_data); + /* Use MoreData flag to indicate whether there are more + * buffered frames for this STA */ + if (no_pending_pkts) + hdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_MOREDATA); + else + hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); - ieee80211_add_pending_skbs(local, &pending); + ieee80211_add_pending_skb(local, skb); - sta_info_recalc_tim(sta); + if (no_pending_pkts) + sta_info_clear_tim_bit(sta); +#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG } else { /* - * We need to release a frame that is buffered somewhere in the - * driver ... it'll have to handle that. - * Note that, as per the comment above, it'll also have to see - * if there is more than just one frame on the specific TID that - * we're releasing from, and it needs to set the more-data bit - * accordingly if we tell it that there's no more data. If we do - * tell it there's more data, then of course the more-data bit - * needs to be set anyway. + * FIXME: This can be the result of a race condition between + * us expiring a frame and the station polling for it. + * Should we send it a null-func frame indicating we + * have nothing buffered for it? */ - drv_release_buffered_frames(local, sta, driver_release_tids, - n_frames, reason, more_data); - - /* - * Note that we don't recalculate the TIM bit here as it would - * most likely have no effect at all unless the driver told us - * that the TID became empty before returning here from the - * release function. - * Either way, however, when the driver tells us that the TID - * became empty we'll do the TIM recalculation. - */ - } -} - -void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta) -{ - u8 ignore_for_response = sta->sta.uapsd_queues; - - /* - * If all ACs are delivery-enabled then we should reply - * from any of them, if only some are enabled we reply - * only from the non-enabled ones. - */ - if (ignore_for_response == BIT(IEEE80211_NUM_ACS) - 1) - ignore_for_response = 0; - - ieee80211_sta_ps_deliver_response(sta, 1, ignore_for_response, - IEEE80211_FRAME_RELEASE_PSPOLL); -} - -void ieee80211_sta_ps_deliver_uapsd(struct sta_info *sta) -{ - int n_frames = sta->sta.max_sp; - u8 delivery_enabled = sta->sta.uapsd_queues; - - /* - * If we ever grow support for TSPEC this might happen if - * the TSPEC update from hostapd comes in between a trigger - * frame setting WLAN_STA_UAPSD in the RX path and this - * actually getting called. - */ - if (!delivery_enabled) - return; - - switch (sta->sta.max_sp) { - case 1: - n_frames = 2; - break; - case 2: - n_frames = 4; - break; - case 3: - n_frames = 6; - break; - case 0: - /* XXX: what is a good value? */ - n_frames = 8; - break; + printk(KERN_DEBUG "%s: STA %pM sent PS Poll even " + "though there are no buffered frames for it\n", + sdata->name, sta->sta.addr); +#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ } - - ieee80211_sta_ps_deliver_response(sta, n_frames, ~delivery_enabled, - IEEE80211_FRAME_RELEASE_UAPSD); } void ieee80211_sta_block_awake(struct ieee80211_hw *hw, @@ -1472,50 +1111,17 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw, trace_api_sta_block_awake(sta->local, pubsta, block); if (block) - set_sta_flag(sta, WLAN_STA_PS_DRIVER); - else if (test_sta_flag(sta, WLAN_STA_PS_DRIVER)) + set_sta_flags(sta, WLAN_STA_PS_DRIVER); + else if (test_sta_flags(sta, WLAN_STA_PS_DRIVER)) ieee80211_queue_work(hw, &sta->drv_unblock_wk); } EXPORT_SYMBOL(ieee80211_sta_block_awake); -void ieee80211_sta_eosp_irqsafe(struct ieee80211_sta *pubsta) -{ - struct sta_info *sta = container_of(pubsta, struct sta_info, sta); - struct ieee80211_local *local = sta->local; - struct sk_buff *skb; - struct skb_eosp_msg_data *data; - - trace_api_eosp(local, pubsta); - - skb = alloc_skb(0, GFP_ATOMIC); - if (!skb) { - /* too bad ... but race is better than loss */ - clear_sta_flag(sta, WLAN_STA_SP); - return; - } - - data = (void *)skb->cb; - memcpy(data->sta, pubsta->addr, ETH_ALEN); - memcpy(data->iface, sta->sdata->vif.addr, ETH_ALEN); - skb->pkt_type = IEEE80211_EOSP_MSG; - skb_queue_tail(&local->skb_queue, skb); - tasklet_schedule(&local->tasklet); -} -EXPORT_SYMBOL(ieee80211_sta_eosp_irqsafe); - -void ieee80211_sta_set_buffered(struct ieee80211_sta *pubsta, - u8 tid, bool buffered) +void ieee80211_sta_set_tim(struct ieee80211_sta *pubsta) { struct sta_info *sta = container_of(pubsta, struct sta_info, sta); - if (WARN_ON(tid >= STA_TID_NUM)) - return; - - if (buffered) - set_bit(tid, &sta->driver_buffered_tids); - else - clear_bit(tid, &sta->driver_buffered_tids); - - sta_info_recalc_tim(sta); + set_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF); + sta_info_set_tim_bit(sta); } -EXPORT_SYMBOL(ieee80211_sta_set_buffered); +EXPORT_SYMBOL(ieee80211_sta_set_tim); diff --git a/trunk/net/mac80211/sta_info.h b/trunk/net/mac80211/sta_info.h index 8c8ce05ad26f..56a3d38a2cd1 100644 --- a/trunk/net/mac80211/sta_info.h +++ b/trunk/net/mac80211/sta_info.h @@ -19,8 +19,7 @@ /** * enum ieee80211_sta_info_flags - Stations flags * - * These flags are used with &struct sta_info's @flags member, but - * only indirectly with set_sta_flag() and friends. + * These flags are used with &struct sta_info's @flags member. * * @WLAN_STA_AUTH: Station is authenticated. * @WLAN_STA_ASSOC: Station is associated. @@ -44,33 +43,24 @@ * be in the queues * @WLAN_STA_PSPOLL: Station sent PS-poll while driver was keeping * station in power-save mode, reply when the driver unblocks. - * @WLAN_STA_TDLS_PEER: Station is a TDLS peer. - * @WLAN_STA_TDLS_PEER_AUTH: This TDLS peer is authorized to send direct - * packets. This means the link is enabled. - * @WLAN_STA_UAPSD: Station requested unscheduled SP while driver was - * keeping station in power-save mode, reply when the driver - * unblocks the station. - * @WLAN_STA_SP: Station is in a service period, so don't try to - * reply to other uAPSD trigger frames or PS-Poll. + * @WLAN_STA_PS_DRIVER_BUF: Station has frames pending in driver internal + * buffers. Automatically cleared on station wake-up. */ enum ieee80211_sta_info_flags { - WLAN_STA_AUTH, - WLAN_STA_ASSOC, - WLAN_STA_PS_STA, - WLAN_STA_AUTHORIZED, - WLAN_STA_SHORT_PREAMBLE, - WLAN_STA_ASSOC_AP, - WLAN_STA_WME, - WLAN_STA_WDS, - WLAN_STA_CLEAR_PS_FILT, - WLAN_STA_MFP, - WLAN_STA_BLOCK_BA, - WLAN_STA_PS_DRIVER, - WLAN_STA_PSPOLL, - WLAN_STA_TDLS_PEER, - WLAN_STA_TDLS_PEER_AUTH, - WLAN_STA_UAPSD, - WLAN_STA_SP, + WLAN_STA_AUTH = 1<<0, + WLAN_STA_ASSOC = 1<<1, + WLAN_STA_PS_STA = 1<<2, + WLAN_STA_AUTHORIZED = 1<<3, + WLAN_STA_SHORT_PREAMBLE = 1<<4, + WLAN_STA_ASSOC_AP = 1<<5, + WLAN_STA_WME = 1<<6, + WLAN_STA_WDS = 1<<7, + WLAN_STA_CLEAR_PS_FILT = 1<<9, + WLAN_STA_MFP = 1<<10, + WLAN_STA_BLOCK_BA = 1<<11, + WLAN_STA_PS_DRIVER = 1<<12, + WLAN_STA_PSPOLL = 1<<13, + WLAN_STA_PS_DRIVER_BUF = 1<<14, }; #define STA_TID_NUM 16 @@ -213,16 +203,15 @@ struct sta_ampdu_mlme { * @last_rx_rate_flag: rx status flag of the last data packet * @lock: used for locking all fields that require locking, see comments * in the header file. + * @flaglock: spinlock for flags accesses * @drv_unblock_wk: used for driver PS unblocking * @listen_interval: listen interval of this station, when we're acting as AP - * @_flags: STA flags, see &enum ieee80211_sta_info_flags, do not use directly - * @ps_tx_buf: buffers (per AC) of frames to transmit to this station - * when it leaves power saving state or polls - * @tx_filtered: buffers (per AC) of frames we already tried to - * transmit but were filtered by hardware due to STA having - * entered power saving state, these are also delivered to - * the station when it leaves powersave or polls for frames - * @driver_buffered_tids: bitmap of TIDs the driver has data buffered on + * @flags: STA flags, see &enum ieee80211_sta_info_flags + * @ps_tx_buf: buffer of frames to transmit to this station + * when it leaves power saving state + * @tx_filtered: buffer of frames we already tried to transmit + * but were filtered by hardware due to STA having entered + * power saving state * @rx_packets: Number of MSDUs received from this STA * @rx_bytes: Number of bytes received from this STA * @wep_weak_iv_count: number of weak WEP IVs received from this station @@ -272,6 +261,7 @@ struct sta_info { struct rate_control_ref *rate_ctrl; void *rate_ctrl_priv; spinlock_t lock; + spinlock_t flaglock; struct work_struct drv_unblock_wk; @@ -281,16 +271,18 @@ struct sta_info { bool uploaded; - /* use the accessors defined below */ - unsigned long _flags; + /* + * frequently updated, locked with own spinlock (flaglock), + * use the accessors defined below + */ + u32 flags; /* * STA powersave frame queues, no more than the internal * locking required. */ - struct sk_buff_head ps_tx_buf[IEEE80211_NUM_ACS]; - struct sk_buff_head tx_filtered[IEEE80211_NUM_ACS]; - unsigned long driver_buffered_tids; + struct sk_buff_head ps_tx_buf; + struct sk_buff_head tx_filtered; /* Updated from RX path only, no locking requirements */ unsigned long rx_packets, rx_bytes; @@ -366,28 +358,60 @@ static inline enum nl80211_plink_state sta_plink_state(struct sta_info *sta) return NL80211_PLINK_LISTEN; } -static inline void set_sta_flag(struct sta_info *sta, - enum ieee80211_sta_info_flags flag) +static inline void set_sta_flags(struct sta_info *sta, const u32 flags) { - set_bit(flag, &sta->_flags); + unsigned long irqfl; + + spin_lock_irqsave(&sta->flaglock, irqfl); + sta->flags |= flags; + spin_unlock_irqrestore(&sta->flaglock, irqfl); } -static inline void clear_sta_flag(struct sta_info *sta, - enum ieee80211_sta_info_flags flag) +static inline void clear_sta_flags(struct sta_info *sta, const u32 flags) { - clear_bit(flag, &sta->_flags); + unsigned long irqfl; + + spin_lock_irqsave(&sta->flaglock, irqfl); + sta->flags &= ~flags; + spin_unlock_irqrestore(&sta->flaglock, irqfl); } -static inline int test_sta_flag(struct sta_info *sta, - enum ieee80211_sta_info_flags flag) +static inline u32 test_sta_flags(struct sta_info *sta, const u32 flags) { - return test_bit(flag, &sta->_flags); + u32 ret; + unsigned long irqfl; + + spin_lock_irqsave(&sta->flaglock, irqfl); + ret = sta->flags & flags; + spin_unlock_irqrestore(&sta->flaglock, irqfl); + + return ret; } -static inline int test_and_clear_sta_flag(struct sta_info *sta, - enum ieee80211_sta_info_flags flag) +static inline u32 test_and_clear_sta_flags(struct sta_info *sta, + const u32 flags) { - return test_and_clear_bit(flag, &sta->_flags); + u32 ret; + unsigned long irqfl; + + spin_lock_irqsave(&sta->flaglock, irqfl); + ret = sta->flags & flags; + sta->flags &= ~flags; + spin_unlock_irqrestore(&sta->flaglock, irqfl); + + return ret; +} + +static inline u32 get_sta_flags(struct sta_info *sta) +{ + u32 ret; + unsigned long irqfl; + + spin_lock_irqsave(&sta->flaglock, irqfl); + ret = sta->flags; + spin_unlock_irqrestore(&sta->flaglock, irqfl); + + return ret; } void ieee80211_assign_tid_tx(struct sta_info *sta, int tid, @@ -405,8 +429,8 @@ rcu_dereference_protected_tid_tx(struct sta_info *sta, int tid) #define STA_HASH(sta) (sta[5]) -/* Maximum number of frames to buffer per power saving station per AC */ -#define STA_MAX_TX_BUFFER 64 +/* Maximum number of frames to buffer per power saving station */ +#define STA_MAX_TX_BUFFER 128 /* Minimum buffered frame expiry time. If STA uses listen interval that is * smaller than this value, the minimum value here is used instead. */ @@ -499,7 +523,8 @@ int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, int sta_info_destroy_addr_bss(struct ieee80211_sub_if_data *sdata, const u8 *addr); -void sta_info_recalc_tim(struct sta_info *sta); +void sta_info_set_tim_bit(struct sta_info *sta); +void sta_info_clear_tim_bit(struct sta_info *sta); void sta_info_init(struct ieee80211_local *local); void sta_info_stop(struct ieee80211_local *local); @@ -510,6 +535,5 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta); void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta); -void ieee80211_sta_ps_deliver_uapsd(struct sta_info *sta); #endif /* STA_INFO_H */ diff --git a/trunk/net/mac80211/status.c b/trunk/net/mac80211/status.c index 864a9c3bcf46..d50358c45ab0 100644 --- a/trunk/net/mac80211/status.c +++ b/trunk/net/mac80211/status.c @@ -14,7 +14,6 @@ #include "rate.h" #include "mesh.h" #include "led.h" -#include "wme.h" void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, @@ -44,8 +43,6 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, struct sk_buff *skb) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_hdr *hdr = (void *)skb->data; - int ac; /* * This skb 'survived' a round-trip through the driver, and @@ -65,38 +62,12 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, sta->tx_filtered_count++; - /* - * Clear more-data bit on filtered frames, it might be set - * but later frames might time out so it might have to be - * clear again ... It's all rather unlikely (this frame - * should time out first, right?) but let's not confuse - * peers unnecessarily. - */ - if (hdr->frame_control & cpu_to_le16(IEEE80211_FCTL_MOREDATA)) - hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_MOREDATA); - - if (ieee80211_is_data_qos(hdr->frame_control)) { - u8 *p = ieee80211_get_qos_ctl(hdr); - int tid = *p & IEEE80211_QOS_CTL_TID_MASK; - - /* - * Clear EOSP if set, this could happen e.g. - * if an absence period (us being a P2P GO) - * shortens the SP. - */ - if (*p & IEEE80211_QOS_CTL_EOSP) - *p &= ~IEEE80211_QOS_CTL_EOSP; - ac = ieee802_1d_to_ac[tid & 7]; - } else { - ac = IEEE80211_AC_BE; - } - /* * Clear the TX filter mask for this STA when sending the next * packet. If the STA went to power save mode, this will happen * when it wakes up for the next time. */ - set_sta_flag(sta, WLAN_STA_CLEAR_PS_FILT); + set_sta_flags(sta, WLAN_STA_CLEAR_PS_FILT); /* * This code races in the following way: @@ -132,19 +103,13 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, * changes before calling TX status events if ordering can be * unknown. */ - if (test_sta_flag(sta, WLAN_STA_PS_STA) && - skb_queue_len(&sta->tx_filtered[ac]) < STA_MAX_TX_BUFFER) { - skb_queue_tail(&sta->tx_filtered[ac], skb); - sta_info_recalc_tim(sta); - - if (!timer_pending(&local->sta_cleanup)) - mod_timer(&local->sta_cleanup, - round_jiffies(jiffies + - STA_INFO_CLEANUP_INTERVAL)); + if (test_sta_flags(sta, WLAN_STA_PS_STA) && + skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) { + skb_queue_tail(&sta->tx_filtered, skb); return; } - if (!test_sta_flag(sta, WLAN_STA_PS_STA) && + if (!test_sta_flags(sta, WLAN_STA_PS_STA) && !(info->flags & IEEE80211_TX_INTFL_RETRIED)) { /* Software retry the packet once */ info->flags |= IEEE80211_TX_INTFL_RETRIED; @@ -156,8 +121,8 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, if (net_ratelimit()) wiphy_debug(local->hw.wiphy, "dropped TX filtered frame, queue_len=%d PS=%d @%lu\n", - skb_queue_len(&sta->tx_filtered[ac]), - !!test_sta_flag(sta, WLAN_STA_PS_STA), jiffies); + skb_queue_len(&sta->tx_filtered), + !!test_sta_flags(sta, WLAN_STA_PS_STA), jiffies); #endif dev_kfree_skb(skb); } @@ -284,11 +249,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) if (memcmp(hdr->addr2, sta->sdata->vif.addr, ETH_ALEN)) continue; - if (info->flags & IEEE80211_TX_STATUS_EOSP) - clear_sta_flag(sta, WLAN_STA_SP); - acked = !!(info->flags & IEEE80211_TX_STAT_ACK); - if (!acked && test_sta_flag(sta, WLAN_STA_PS_STA)) { + if (!acked && test_sta_flags(sta, WLAN_STA_PS_STA)) { /* * The STA is in power save mode, so assume * that this TX packet failed because of that. diff --git a/trunk/net/mac80211/tx.c b/trunk/net/mac80211/tx.c index ad2ee4a90ec4..7cd6c28968b2 100644 --- a/trunk/net/mac80211/tx.c +++ b/trunk/net/mac80211/tx.c @@ -253,7 +253,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); - bool assoc = false; + u32 sta_flags; if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) return TX_CONTINUE; @@ -284,11 +284,10 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) if (tx->flags & IEEE80211_TX_PS_BUFFERED) return TX_CONTINUE; - if (tx->sta) - assoc = test_sta_flag(tx->sta, WLAN_STA_ASSOC); + sta_flags = tx->sta ? get_sta_flags(tx->sta) : 0; if (likely(tx->flags & IEEE80211_TX_UNICAST)) { - if (unlikely(!assoc && + if (unlikely(!(sta_flags & WLAN_STA_ASSOC) && tx->sdata->vif.type != NL80211_IFTYPE_ADHOC && ieee80211_is_data(hdr->frame_control))) { #ifdef CONFIG_MAC80211_VERBOSE_DEBUG @@ -344,22 +343,13 @@ static void purge_old_ps_buffers(struct ieee80211_local *local) total += skb_queue_len(&ap->ps_bc_buf); } - /* - * Drop one frame from each station from the lowest-priority - * AC that has frames at all. - */ list_for_each_entry_rcu(sta, &local->sta_list, list) { - int ac; - - for (ac = IEEE80211_AC_BK; ac >= IEEE80211_AC_VO; ac--) { - skb = skb_dequeue(&sta->ps_tx_buf[ac]); - total += skb_queue_len(&sta->ps_tx_buf[ac]); - if (skb) { - purged++; - dev_kfree_skb(skb); - break; - } + skb = skb_dequeue(&sta->ps_tx_buf); + if (skb) { + purged++; + dev_kfree_skb(skb); } + total += skb_queue_len(&sta->ps_tx_buf); } rcu_read_unlock(); @@ -428,7 +418,7 @@ static int ieee80211_use_mfp(__le16 fc, struct sta_info *sta, if (!ieee80211_is_mgmt(fc)) return 0; - if (sta == NULL || !test_sta_flag(sta, WLAN_STA_MFP)) + if (sta == NULL || !test_sta_flags(sta, WLAN_STA_MFP)) return 0; if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *) @@ -445,6 +435,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; struct ieee80211_local *local = tx->local; + u32 staflags; if (unlikely(!sta || ieee80211_is_probe_resp(hdr->frame_control) || @@ -453,52 +444,57 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) ieee80211_is_reassoc_resp(hdr->frame_control))) return TX_CONTINUE; - if (unlikely((test_sta_flag(sta, WLAN_STA_PS_STA) || - test_sta_flag(sta, WLAN_STA_PS_DRIVER)) && - !(info->flags & IEEE80211_TX_CTL_POLL_RESPONSE))) { - int ac = skb_get_queue_mapping(tx->skb); + staflags = get_sta_flags(sta); + if (unlikely((staflags & (WLAN_STA_PS_STA | WLAN_STA_PS_DRIVER)) && + !(info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE))) { #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG - printk(KERN_DEBUG "STA %pM aid %d: PS buffer for AC %d\n", - sta->sta.addr, sta->sta.aid, ac); + printk(KERN_DEBUG "STA %pM aid %d: PS buffer (entries " + "before %d)\n", + sta->sta.addr, sta->sta.aid, + skb_queue_len(&sta->ps_tx_buf)); #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER) purge_old_ps_buffers(tx->local); - if (skb_queue_len(&sta->ps_tx_buf[ac]) >= STA_MAX_TX_BUFFER) { - struct sk_buff *old = skb_dequeue(&sta->ps_tx_buf[ac]); + if (skb_queue_len(&sta->ps_tx_buf) >= STA_MAX_TX_BUFFER) { + struct sk_buff *old = skb_dequeue(&sta->ps_tx_buf); #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG - if (net_ratelimit()) - printk(KERN_DEBUG "%s: STA %pM TX buffer for " - "AC %d full - dropping oldest frame\n", - tx->sdata->name, sta->sta.addr, ac); + if (net_ratelimit()) { + printk(KERN_DEBUG "%s: STA %pM TX " + "buffer full - dropping oldest frame\n", + tx->sdata->name, sta->sta.addr); + } #endif dev_kfree_skb(old); } else tx->local->total_ps_buffered++; + /* + * Queue frame to be sent after STA wakes up/polls, + * but don't set the TIM bit if the driver is blocking + * wakeup or poll response transmissions anyway. + */ + if (skb_queue_empty(&sta->ps_tx_buf) && + !(staflags & WLAN_STA_PS_DRIVER)) + sta_info_set_tim_bit(sta); + info->control.jiffies = jiffies; info->control.vif = &tx->sdata->vif; info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; - skb_queue_tail(&sta->ps_tx_buf[ac], tx->skb); + skb_queue_tail(&sta->ps_tx_buf, tx->skb); if (!timer_pending(&local->sta_cleanup)) mod_timer(&local->sta_cleanup, round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL)); - /* - * We queued up some frames, so the TIM bit might - * need to be set, recalculate it. - */ - sta_info_recalc_tim(sta); - return TX_QUEUED; } #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG - else if (unlikely(test_sta_flag(sta, WLAN_STA_PS_STA))) { - printk(KERN_DEBUG - "%s: STA %pM in PS mode, but polling/in SP -> send frame\n", - tx->sdata->name, sta->sta.addr); + else if (unlikely(staflags & WLAN_STA_PS_STA)) { + printk(KERN_DEBUG "%s: STA %pM in PS mode, but pspoll " + "set -> send frame\n", tx->sdata->name, + sta->sta.addr); } #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ @@ -556,7 +552,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) !(info->flags & IEEE80211_TX_CTL_INJECTED) && (!ieee80211_is_robust_mgmt_frame(hdr) || (ieee80211_is_action(hdr->frame_control) && - tx->sta && test_sta_flag(tx->sta, WLAN_STA_MFP)))) { + tx->sta && test_sta_flags(tx->sta, WLAN_STA_MFP)))) { I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted); return TX_DROP; } else @@ -615,7 +611,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) u32 len; bool inval = false, rts = false, short_preamble = false; struct ieee80211_tx_rate_control txrc; - bool assoc = false; + u32 sta_flags; memset(&txrc, 0, sizeof(txrc)); @@ -651,17 +647,17 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) */ if (tx->sdata->vif.bss_conf.use_short_preamble && (ieee80211_is_data(hdr->frame_control) || - (tx->sta && test_sta_flag(tx->sta, WLAN_STA_SHORT_PREAMBLE)))) + (tx->sta && test_sta_flags(tx->sta, WLAN_STA_SHORT_PREAMBLE)))) txrc.short_preamble = short_preamble = true; - if (tx->sta) - assoc = test_sta_flag(tx->sta, WLAN_STA_ASSOC); + sta_flags = tx->sta ? get_sta_flags(tx->sta) : 0; /* * Lets not bother rate control if we're associated and cannot * talk to the sta. This should not happen. */ - if (WARN(test_bit(SCAN_SW_SCANNING, &tx->local->scanning) && assoc && + if (WARN(test_bit(SCAN_SW_SCANNING, &tx->local->scanning) && + (sta_flags & WLAN_STA_ASSOC) && !rate_usable_index_exists(sband, &tx->sta->sta), "%s: Dropped data frame as no usable bitrate found while " "scanning and associated. Target station: " @@ -804,9 +800,6 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx) if (ieee80211_hdrlen(hdr->frame_control) < 24) return TX_CONTINUE; - if (ieee80211_is_qos_nullfunc(hdr->frame_control)) - return TX_CONTINUE; - /* * Anything but QoS data that has a sequence number field * (is long enough) gets a sequence number from the global @@ -1054,7 +1047,6 @@ static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len, NULL); - u16 txflags; info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; tx->flags &= ~IEEE80211_TX_FRAGMENTED; @@ -1103,13 +1095,6 @@ static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, tx->flags |= IEEE80211_TX_FRAGMENTED; break; - case IEEE80211_RADIOTAP_TX_FLAGS: - txflags = le16_to_cpu(get_unaligned((__le16*) - iterator.this_arg)); - if (txflags & IEEE80211_RADIOTAP_F_TX_NOACK) - info->flags |= IEEE80211_TX_CTL_NO_ACK; - break; - /* * Please update the file * Documentation/networking/mac80211-injection.txt @@ -1247,7 +1232,6 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, tx->sta = sta_info_get(sdata, hdr->addr1); if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) && - !ieee80211_is_qos_nullfunc(hdr->frame_control) && (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION) && !(local->hw.flags & IEEE80211_HW_TX_AMPDU_SETUP_IN_HW)) { struct tid_ampdu_tx *tid_tx; @@ -1274,11 +1258,8 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, tx->flags |= IEEE80211_TX_UNICAST; if (unlikely(local->wifi_wme_noack_test)) info->flags |= IEEE80211_TX_CTL_NO_ACK; - /* - * Flags are initialized to 0. Hence, no need to - * explicitly unset IEEE80211_TX_CTL_NO_ACK since - * it might already be set for injected frames. - */ + else + info->flags &= ~IEEE80211_TX_CTL_NO_ACK; } if (tx->flags & IEEE80211_TX_FRAGMENTED) { @@ -1292,7 +1273,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, if (!tx->sta) info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; - else if (test_and_clear_sta_flag(tx->sta, WLAN_STA_CLEAR_PS_FILT)) + else if (test_and_clear_sta_flags(tx->sta, WLAN_STA_CLEAR_PS_FILT)) info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; hdrlen = ieee80211_hdrlen(hdr->frame_control); @@ -1534,7 +1515,8 @@ static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata, return 0; } -void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) +static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, + struct sk_buff *skb) { struct ieee80211_local *local = sdata->local; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); @@ -1742,9 +1724,8 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, int encaps_len, skip_header_bytes; int nh_pos, h_pos; struct sta_info *sta = NULL; - bool wme_sta = false, authorized = false, tdls_auth = false; + u32 sta_flags = 0; struct sk_buff *tmp_skb; - bool tdls_direct = false; if (unlikely(skb->len < ETH_HLEN)) { ret = NETDEV_TX_OK; @@ -1768,8 +1749,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, memcpy(hdr.addr3, skb->data, ETH_ALEN); memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); hdrlen = 30; - authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED); - wme_sta = test_sta_flag(sta, WLAN_STA_WME); + sta_flags = get_sta_flags(sta); } rcu_read_unlock(); if (sta) @@ -1857,50 +1837,11 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, break; #endif case NL80211_IFTYPE_STATION: - if (sdata->wdev.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) { - bool tdls_peer = false; - - rcu_read_lock(); - sta = sta_info_get(sdata, skb->data); - if (sta) { - authorized = test_sta_flag(sta, - WLAN_STA_AUTHORIZED); - wme_sta = test_sta_flag(sta, WLAN_STA_WME); - tdls_peer = test_sta_flag(sta, - WLAN_STA_TDLS_PEER); - tdls_auth = test_sta_flag(sta, - WLAN_STA_TDLS_PEER_AUTH); - } - rcu_read_unlock(); - - /* - * If the TDLS link is enabled, send everything - * directly. Otherwise, allow TDLS setup frames - * to be transmitted indirectly. - */ - tdls_direct = tdls_peer && (tdls_auth || - !(ethertype == ETH_P_TDLS && skb->len > 14 && - skb->data[14] == WLAN_TDLS_SNAP_RFTYPE)); - } - - if (tdls_direct) { - /* link during setup - throw out frames to peer */ - if (!tdls_auth) { - ret = NETDEV_TX_OK; - goto fail; - } - - /* DA SA BSSID */ - memcpy(hdr.addr1, skb->data, ETH_ALEN); - memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); - memcpy(hdr.addr3, sdata->u.mgd.bssid, ETH_ALEN); - hdrlen = 24; - } else if (sdata->u.mgd.use_4addr && - cpu_to_be16(ethertype) != sdata->control_port_protocol) { - fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | - IEEE80211_FCTL_TODS); + memcpy(hdr.addr1, sdata->u.mgd.bssid, ETH_ALEN); + if (sdata->u.mgd.use_4addr && + cpu_to_be16(ethertype) != sdata->control_port_protocol) { + fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); /* RA TA DA SA */ - memcpy(hdr.addr1, sdata->u.mgd.bssid, ETH_ALEN); memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN); memcpy(hdr.addr3, skb->data, ETH_ALEN); memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); @@ -1908,7 +1849,6 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, } else { fc |= cpu_to_le16(IEEE80211_FCTL_TODS); /* BSSID SA DA */ - memcpy(hdr.addr1, sdata->u.mgd.bssid, ETH_ALEN); memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); memcpy(hdr.addr3, skb->data, ETH_ALEN); hdrlen = 24; @@ -1934,19 +1874,17 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, if (!is_multicast_ether_addr(hdr.addr1)) { rcu_read_lock(); sta = sta_info_get(sdata, hdr.addr1); - if (sta) { - authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED); - wme_sta = test_sta_flag(sta, WLAN_STA_WME); - } + if (sta) + sta_flags = get_sta_flags(sta); rcu_read_unlock(); } /* For mesh, the use of the QoS header is mandatory */ if (ieee80211_vif_is_mesh(&sdata->vif)) - wme_sta = true; + sta_flags |= WLAN_STA_WME; /* receiver and we are QoS enabled, use a QoS type frame */ - if (wme_sta && local->hw.queues >= 4) { + if ((sta_flags & WLAN_STA_WME) && local->hw.queues >= 4) { fc |= cpu_to_le16(IEEE80211_STYPE_QOS_DATA); hdrlen += 2; } @@ -1956,7 +1894,8 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, * EAPOL frames from the local station. */ if (!ieee80211_vif_is_mesh(&sdata->vif) && - unlikely(!is_multicast_ether_addr(hdr.addr1) && !authorized && + unlikely(!is_multicast_ether_addr(hdr.addr1) && + !(sta_flags & WLAN_STA_AUTHORIZED) && !(cpu_to_be16(ethertype) == sdata->control_port_protocol && compare_ether_addr(sdata->vif.addr, skb->data + ETH_ALEN) == 0))) { @@ -2368,9 +2307,9 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, *pos++ = WLAN_EID_SSID; *pos++ = 0x0; - if (ieee80211_add_srates_ie(&sdata->vif, skb) || + if (mesh_add_srates_ie(skb, sdata) || mesh_add_ds_params_ie(skb, sdata) || - ieee80211_add_ext_srates_ie(&sdata->vif, skb) || + mesh_add_ext_srates_ie(skb, sdata) || mesh_add_rsn_ie(skb, sdata) || mesh_add_meshid_ie(skb, sdata) || mesh_add_meshconf_ie(skb, sdata) || diff --git a/trunk/net/mac80211/util.c b/trunk/net/mac80211/util.c index 7439d26bf5f9..4b1466d5b6a1 100644 --- a/trunk/net/mac80211/util.c +++ b/trunk/net/mac80211/util.c @@ -367,14 +367,14 @@ void ieee80211_add_pending_skb(struct ieee80211_local *local, spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); } -void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, - struct sk_buff_head *skbs, - void (*fn)(void *data), void *data) +int ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, + struct sk_buff_head *skbs, + void (*fn)(void *data), void *data) { struct ieee80211_hw *hw = &local->hw; struct sk_buff *skb; unsigned long flags; - int queue, i; + int queue, ret = 0, i; spin_lock_irqsave(&local->queue_stop_reason_lock, flags); for (i = 0; i < hw->queues; i++) @@ -389,6 +389,7 @@ void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, continue; } + ret++; queue = skb_get_queue_mapping(skb); __skb_queue_tail(&local->pending[queue], skb); } @@ -400,12 +401,14 @@ void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, __ieee80211_wake_queue(hw, i, IEEE80211_QUEUE_STOP_REASON_SKB_ADD); spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); + + return ret; } -void ieee80211_add_pending_skbs(struct ieee80211_local *local, - struct sk_buff_head *skbs) +int ieee80211_add_pending_skbs(struct ieee80211_local *local, + struct sk_buff_head *skbs) { - ieee80211_add_pending_skbs_fn(local, skbs, NULL, NULL); + return ieee80211_add_pending_skbs_fn(local, skbs, NULL, NULL); } void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, @@ -629,8 +632,8 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata) qparam.uapsd = false; - sdata->tx_conf[queue] = qparam; - drv_conf_tx(local, sdata, queue, &qparam); + local->tx_conf[queue] = qparam; + drv_conf_tx(local, queue, &qparam); } /* after reinitialize QoS TX queues setting to default, @@ -896,18 +899,14 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, const u8 *ssid, size_t ssid_len, const u8 *ie, size_t ie_len, - u32 ratemask, bool directed, bool no_cck) + u32 ratemask, bool directed) { struct sk_buff *skb; skb = ieee80211_build_probe_req(sdata, dst, ratemask, ssid, ssid_len, ie, ie_len, directed); - if (skb) { - if (no_cck) - IEEE80211_SKB_CB(skb)->flags |= - IEEE80211_TX_CTL_NO_CCK_RATE; + if (skb) ieee80211_tx_skb(sdata, skb); - } } u32 ieee80211_sta_get_rates(struct ieee80211_local *local, @@ -1041,15 +1040,8 @@ int ieee80211_reconfig(struct ieee80211_local *local) mutex_unlock(&local->sta_mtx); /* reconfigure tx conf */ - list_for_each_entry(sdata, &local->interfaces, list) { - if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN || - sdata->vif.type == NL80211_IFTYPE_MONITOR || - !ieee80211_sdata_running(sdata)) - continue; - - for (i = 0; i < hw->queues; i++) - drv_conf_tx(local, sdata, i, &sdata->tx_conf[i]); - } + for (i = 0; i < hw->queues; i++) + drv_conf_tx(local, i, &local->tx_conf[i]); /* reconfigure hardware */ ieee80211_hw_config(local, ~0); @@ -1122,7 +1114,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) list_for_each_entry(sta, &local->sta_list, list) { ieee80211_sta_tear_down_BA_sessions(sta, true); - clear_sta_flag(sta, WLAN_STA_BLOCK_BA); + clear_sta_flags(sta, WLAN_STA_BLOCK_BA); } mutex_unlock(&local->sta_mtx); @@ -1361,60 +1353,3 @@ void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif) _ieee80211_enable_rssi_reports(sdata, 0, 0); } EXPORT_SYMBOL(ieee80211_disable_rssi_reports); - -int ieee80211_add_srates_ie(struct ieee80211_vif *vif, struct sk_buff *skb) -{ - struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); - struct ieee80211_local *local = sdata->local; - struct ieee80211_supported_band *sband; - int rate; - u8 i, rates, *pos; - - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - rates = sband->n_bitrates; - if (rates > 8) - rates = 8; - - if (skb_tailroom(skb) < rates + 2) - return -ENOMEM; - - pos = skb_put(skb, rates + 2); - *pos++ = WLAN_EID_SUPP_RATES; - *pos++ = rates; - for (i = 0; i < rates; i++) { - rate = sband->bitrates[i].bitrate; - *pos++ = (u8) (rate / 5); - } - - return 0; -} - -int ieee80211_add_ext_srates_ie(struct ieee80211_vif *vif, struct sk_buff *skb) -{ - struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); - struct ieee80211_local *local = sdata->local; - struct ieee80211_supported_band *sband; - int rate; - u8 i, exrates, *pos; - - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - exrates = sband->n_bitrates; - if (exrates > 8) - exrates -= 8; - else - exrates = 0; - - if (skb_tailroom(skb) < exrates + 2) - return -ENOMEM; - - if (exrates) { - pos = skb_put(skb, exrates + 2); - *pos++ = WLAN_EID_EXT_SUPP_RATES; - *pos++ = exrates; - for (i = 8; i < sband->n_bitrates; i++) { - rate = sband->bitrates[i].bitrate; - *pos++ = (u8) (rate / 5); - } - } - return 0; -} diff --git a/trunk/net/mac80211/wme.c b/trunk/net/mac80211/wme.c index fd52e695c071..971004c9b04f 100644 --- a/trunk/net/mac80211/wme.c +++ b/trunk/net/mac80211/wme.c @@ -72,7 +72,7 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, case NL80211_IFTYPE_AP_VLAN: sta = rcu_dereference(sdata->u.vlan.sta); if (sta) { - qos = test_sta_flag(sta, WLAN_STA_WME); + qos = get_sta_flags(sta) & WLAN_STA_WME; break; } case NL80211_IFTYPE_AP: @@ -99,7 +99,7 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, if (!sta && ra && !is_multicast_ether_addr(ra)) { sta = sta_info_get(sdata, ra); if (sta) - qos = test_sta_flag(sta, WLAN_STA_WME); + qos = get_sta_flags(sta) & WLAN_STA_WME; } rcu_read_unlock(); diff --git a/trunk/net/mac80211/work.c b/trunk/net/mac80211/work.c index af374fab1a12..bac34394c05e 100644 --- a/trunk/net/mac80211/work.c +++ b/trunk/net/mac80211/work.c @@ -458,7 +458,7 @@ ieee80211_direct_probe(struct ieee80211_work *wk) */ ieee80211_send_probe_req(sdata, NULL, wk->probe_auth.ssid, wk->probe_auth.ssid_len, NULL, 0, - (u32) -1, true, false); + (u32) -1, true); wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; run_again(local, wk->timeout); diff --git a/trunk/net/nfc/nci/core.c b/trunk/net/nfc/nci/core.c index 4047e29acb3b..895e5fdf464a 100644 --- a/trunk/net/nfc/nci/core.c +++ b/trunk/net/nfc/nci/core.c @@ -135,10 +135,8 @@ static void nci_init_req(struct nci_dev *ndev, unsigned long opt) static void nci_init_complete_req(struct nci_dev *ndev, unsigned long opt) { - struct nci_core_conn_create_cmd conn_cmd; struct nci_rf_disc_map_cmd cmd; - struct disc_map_config *cfg = cmd.mapping_configs; - __u8 *num = &cmd.num_mapping_configs; + struct nci_core_conn_create_cmd conn_cmd; int i; /* create static rf connection */ @@ -147,30 +145,36 @@ static void nci_init_complete_req(struct nci_dev *ndev, unsigned long opt) nci_send_cmd(ndev, NCI_OP_CORE_CONN_CREATE_CMD, 2, &conn_cmd); /* set rf mapping configurations */ - *num = 0; + cmd.num_mapping_configs = 0; /* by default mapping is set to NCI_RF_INTERFACE_FRAME */ for (i = 0; i < ndev->num_supported_rf_interfaces; i++) { if (ndev->supported_rf_interfaces[i] == NCI_RF_INTERFACE_ISO_DEP) { - cfg[*num].rf_protocol = NCI_RF_PROTOCOL_ISO_DEP; - cfg[*num].mode = NCI_DISC_MAP_MODE_BOTH; - cfg[*num].rf_interface_type = NCI_RF_INTERFACE_ISO_DEP; - (*num)++; + cmd.mapping_configs[cmd.num_mapping_configs] + .rf_protocol = NCI_RF_PROTOCOL_ISO_DEP; + cmd.mapping_configs[cmd.num_mapping_configs] + .mode = NCI_DISC_MAP_MODE_BOTH; + cmd.mapping_configs[cmd.num_mapping_configs] + .rf_interface_type = NCI_RF_INTERFACE_ISO_DEP; + cmd.num_mapping_configs++; } else if (ndev->supported_rf_interfaces[i] == NCI_RF_INTERFACE_NFC_DEP) { - cfg[*num].rf_protocol = NCI_RF_PROTOCOL_NFC_DEP; - cfg[*num].mode = NCI_DISC_MAP_MODE_BOTH; - cfg[*num].rf_interface_type = NCI_RF_INTERFACE_NFC_DEP; - (*num)++; + cmd.mapping_configs[cmd.num_mapping_configs] + .rf_protocol = NCI_RF_PROTOCOL_NFC_DEP; + cmd.mapping_configs[cmd.num_mapping_configs] + .mode = NCI_DISC_MAP_MODE_BOTH; + cmd.mapping_configs[cmd.num_mapping_configs] + .rf_interface_type = NCI_RF_INTERFACE_NFC_DEP; + cmd.num_mapping_configs++; } - if (*num == NCI_MAX_NUM_MAPPING_CONFIGS) + if (cmd.num_mapping_configs == NCI_MAX_NUM_MAPPING_CONFIGS) break; } nci_send_cmd(ndev, NCI_OP_RF_DISCOVER_MAP_CMD, - (1 + ((*num)*sizeof(struct disc_map_config))), + (1 + (cmd.num_mapping_configs*sizeof(struct disc_map_config))), &cmd); } @@ -361,13 +365,8 @@ static int nci_start_poll(struct nfc_dev *nfc_dev, __u32 protocols) return -EBUSY; } - if (ndev->target_active_prot) { - nfc_err("there is an active target"); - return -EBUSY; - } - if (test_bit(NCI_POLL_ACTIVE, &ndev->flags)) { - nfc_dbg("target is active, implicitly deactivate..."); + nfc_dbg("target already active, first deactivate..."); rc = nci_request(ndev, nci_rf_deactivate_req, 0, msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT)); @@ -453,7 +452,6 @@ static int nci_data_exchange(struct nfc_dev *nfc_dev, __u32 target_idx, void *cb_context) { struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); - int rc; nfc_dbg("entry, target_idx %d, len %d", target_idx, skb->len); @@ -462,18 +460,11 @@ static int nci_data_exchange(struct nfc_dev *nfc_dev, __u32 target_idx, return -EINVAL; } - if (test_and_set_bit(NCI_DATA_EXCHANGE, &ndev->flags)) - return -EBUSY; - /* store cb and context to be used on receiving data */ ndev->data_exchange_cb = cb; ndev->data_exchange_cb_context = cb_context; - rc = nci_send_data(ndev, ndev->conn_id, skb); - if (rc) - clear_bit(NCI_DATA_EXCHANGE, &ndev->flags); - - return rc; + return nci_send_data(ndev, ndev->conn_id, skb); } static struct nfc_ops nci_nfc_ops = { @@ -499,19 +490,19 @@ struct nci_dev *nci_allocate_device(struct nci_ops *ops, int tx_headroom, int tx_tailroom) { - struct nci_dev *ndev; + struct nci_dev *ndev = NULL; nfc_dbg("entry, supported_protocols 0x%x", supported_protocols); if (!ops->open || !ops->close || !ops->send) - return NULL; + goto exit; if (!supported_protocols) - return NULL; + goto exit; ndev = kzalloc(sizeof(struct nci_dev), GFP_KERNEL); if (!ndev) - return NULL; + goto exit; ndev->ops = ops; ndev->tx_headroom = tx_headroom; @@ -526,11 +517,13 @@ struct nci_dev *nci_allocate_device(struct nci_ops *ops, nfc_set_drvdata(ndev->nfc_dev, ndev); - return ndev; + goto exit; free_exit: kfree(ndev); - return NULL; + +exit: + return ndev; } EXPORT_SYMBOL(nci_allocate_device); diff --git a/trunk/net/nfc/nci/data.c b/trunk/net/nfc/nci/data.c index e5ed90fc1a9c..141790ada4aa 100644 --- a/trunk/net/nfc/nci/data.c +++ b/trunk/net/nfc/nci/data.c @@ -54,8 +54,6 @@ void nci_data_exchange_complete(struct nci_dev *ndev, /* no waiting callback, free skb */ kfree_skb(skb); } - - clear_bit(NCI_DATA_EXCHANGE, &ndev->flags); } /* ----------------- NCI TX Data ----------------- */ diff --git a/trunk/net/nfc/nci/ntf.c b/trunk/net/nfc/nci/ntf.c index 96633f5cda4f..8dd75352ab6c 100644 --- a/trunk/net/nfc/nci/ntf.c +++ b/trunk/net/nfc/nci/ntf.c @@ -215,7 +215,7 @@ static void nci_rf_deactivate_ntf_packet(struct nci_dev *ndev, } /* complete the data exchange transaction, if exists */ - if (test_bit(NCI_DATA_EXCHANGE, &ndev->flags)) + if (ndev->data_exchange_cb) nci_data_exchange_complete(ndev, NULL, -EIO); } diff --git a/trunk/net/rfkill/rfkill-gpio.c b/trunk/net/rfkill/rfkill-gpio.c index 128677d69056..256c5ddd2d72 100644 --- a/trunk/net/rfkill/rfkill-gpio.c +++ b/trunk/net/rfkill/rfkill-gpio.c @@ -101,14 +101,6 @@ static int rfkill_gpio_probe(struct platform_device *pdev) if (!rfkill) return -ENOMEM; - if (pdata->gpio_runtime_setup) { - ret = pdata->gpio_runtime_setup(pdev); - if (ret) { - pr_warn("%s: can't set up gpio\n", __func__); - return ret; - } - } - rfkill->pdata = pdata; len = strlen(pdata->name); @@ -190,10 +182,7 @@ static int rfkill_gpio_probe(struct platform_device *pdev) static int rfkill_gpio_remove(struct platform_device *pdev) { struct rfkill_gpio_data *rfkill = platform_get_drvdata(pdev); - struct rfkill_gpio_platform_data *pdata = pdev->dev.platform_data; - if (pdata->gpio_runtime_close) - pdata->gpio_runtime_close(pdev); rfkill_unregister(rfkill->rfkill_dev); rfkill_destroy(rfkill->rfkill_dev); if (gpio_is_valid(rfkill->pdata->shutdown_gpio)) diff --git a/trunk/net/wireless/core.h b/trunk/net/wireless/core.h index b9ec3061ed72..796a4bdf8b0d 100644 --- a/trunk/net/wireless/core.h +++ b/trunk/net/wireless/core.h @@ -375,8 +375,7 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, struct ieee80211_channel *chan, bool offchan, enum nl80211_channel_type channel_type, bool channel_type_valid, unsigned int wait, - const u8 *buf, size_t len, bool no_cck, - u64 *cookie); + const u8 *buf, size_t len, u64 *cookie); /* SME */ int __cfg80211_connect(struct cfg80211_registered_device *rdev, @@ -407,7 +406,6 @@ void cfg80211_sme_failed_assoc(struct wireless_dev *wdev); bool cfg80211_sme_failed_reassoc(struct wireless_dev *wdev); /* internal helpers */ -bool cfg80211_supported_cipher_suite(struct wiphy *wiphy, u32 cipher); int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, struct key_params *params, int key_idx, bool pairwise, const u8 *mac_addr); diff --git a/trunk/net/wireless/mlme.c b/trunk/net/wireless/mlme.c index 21fc9702f81c..61adea540e02 100644 --- a/trunk/net/wireless/mlme.c +++ b/trunk/net/wireless/mlme.c @@ -900,8 +900,7 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, struct ieee80211_channel *chan, bool offchan, enum nl80211_channel_type channel_type, bool channel_type_valid, unsigned int wait, - const u8 *buf, size_t len, bool no_cck, - u64 *cookie) + const u8 *buf, size_t len, u64 *cookie) { struct wireless_dev *wdev = dev->ieee80211_ptr; const struct ieee80211_mgmt *mgmt; @@ -992,7 +991,7 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, /* Transmit the Action frame as requested by user space */ return rdev->ops->mgmt_tx(&rdev->wiphy, dev, chan, offchan, channel_type, channel_type_valid, - wait, buf, len, no_cck, cookie); + wait, buf, len, cookie); } bool cfg80211_rx_mgmt(struct net_device *dev, int freq, const u8 *buf, diff --git a/trunk/net/wireless/nl80211.c b/trunk/net/wireless/nl80211.c index edf655aeea00..3c6427abdf34 100644 --- a/trunk/net/wireless/nl80211.c +++ b/trunk/net/wireless/nl80211.c @@ -191,12 +191,6 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { .len = IEEE80211_MAX_DATA_LEN }, [NL80211_ATTR_ROAM_SUPPORT] = { .type = NLA_FLAG }, [NL80211_ATTR_SCHED_SCAN_MATCH] = { .type = NLA_NESTED }, - [NL80211_ATTR_TX_NO_CCK_RATE] = { .type = NLA_FLAG }, - [NL80211_ATTR_TDLS_ACTION] = { .type = NLA_U8 }, - [NL80211_ATTR_TDLS_DIALOG_TOKEN] = { .type = NLA_U8 }, - [NL80211_ATTR_TDLS_OPERATION] = { .type = NLA_U8 }, - [NL80211_ATTR_TDLS_SUPPORT] = { .type = NLA_FLAG }, - [NL80211_ATTR_TDLS_EXTERNAL_SETUP] = { .type = NLA_FLAG }, }; /* policy for the key attributes */ @@ -737,12 +731,9 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, NLA_PUT_FLAG(msg, NL80211_ATTR_SUPPORT_MESH_AUTH); if (dev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) NLA_PUT_FLAG(msg, NL80211_ATTR_SUPPORT_AP_UAPSD); + if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_FW_ROAM) NLA_PUT_FLAG(msg, NL80211_ATTR_ROAM_SUPPORT); - if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) - NLA_PUT_FLAG(msg, NL80211_ATTR_TDLS_SUPPORT); - if (dev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) - NLA_PUT_FLAG(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP); NLA_PUT(msg, NL80211_ATTR_CIPHER_SUITES, sizeof(u32) * dev->wiphy.n_cipher_suites, @@ -885,10 +876,6 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, } CMD(set_channel, SET_CHANNEL); CMD(set_wds_peer, SET_WDS_PEER); - if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) { - CMD(tdls_mgmt, TDLS_MGMT); - CMD(tdls_oper, TDLS_OPER); - } if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) CMD(sched_scan_start, START_SCHED_SCAN); @@ -1248,11 +1235,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) goto bad_res; } - if (!netdev) { - result = -EINVAL; - goto bad_res; - } - nla_for_each_nested(nl_txq_params, info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS], rem_txq_params) { @@ -1265,7 +1247,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) goto bad_res; result = rdev->ops->set_txq_params(&rdev->wiphy, - netdev, &txq_params); if (result) goto bad_res; @@ -2530,25 +2511,18 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) break; case NL80211_IFTYPE_P2P_CLIENT: case NL80211_IFTYPE_STATION: - /* disallow things sta doesn't support */ + /* disallow everything but AUTHORIZED flag */ if (params.plink_action) err = -EINVAL; if (params.vlan) err = -EINVAL; - if (params.supported_rates && - !(params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) + if (params.supported_rates) err = -EINVAL; if (params.ht_capa) err = -EINVAL; if (params.listen_interval >= 0) err = -EINVAL; - if (params.sta_flags_mask & - ~(BIT(NL80211_STA_FLAG_AUTHORIZED) | - BIT(NL80211_STA_FLAG_TDLS_PEER))) - err = -EINVAL; - /* can't change the TDLS bit */ - if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) && - (params.sta_flags_mask & BIT(NL80211_STA_FLAG_TDLS_PEER))) + if (params.sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED)) err = -EINVAL; break; case NL80211_IFTYPE_MESH_POINT: @@ -2639,7 +2613,7 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) /* parse WME attributes if sta is WME capable */ if ((rdev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) && - (params.sta_flags_set & BIT(NL80211_STA_FLAG_WME)) && + (params.sta_flags_set & NL80211_STA_FLAG_WME) && info->attrs[NL80211_ATTR_STA_WME]) { struct nlattr *tb[NL80211_STA_WME_MAX + 1]; struct nlattr *nla; @@ -2662,25 +2636,12 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) if (params.max_sp & ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK) return -EINVAL; - - params.sta_modify_mask |= STATION_PARAM_APPLY_UAPSD; } if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT && - dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO && - dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) - return -EINVAL; - - /* - * Only managed stations can add TDLS peers, and only when the - * wiphy supports external TDLS setup. - */ - if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION && - !((params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) && - (rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) && - (rdev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP))) + dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) return -EINVAL; err = get_vlan(info, rdev, ¶ms.vlan); @@ -3659,9 +3620,6 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) } } - request->no_cck = - nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]); - request->dev = dev; request->wiphy = &rdev->wiphy; @@ -4168,6 +4126,22 @@ static bool nl80211_valid_wpa_versions(u32 wpa_versions) NL80211_WPA_VERSION_2)); } +static bool nl80211_valid_akm_suite(u32 akm) +{ + return akm == WLAN_AKM_SUITE_8021X || + akm == WLAN_AKM_SUITE_PSK; +} + +static bool nl80211_valid_cipher_suite(u32 cipher) +{ + return cipher == WLAN_CIPHER_SUITE_WEP40 || + cipher == WLAN_CIPHER_SUITE_WEP104 || + cipher == WLAN_CIPHER_SUITE_TKIP || + cipher == WLAN_CIPHER_SUITE_CCMP || + cipher == WLAN_CIPHER_SUITE_AES_CMAC; +} + + static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) { struct cfg80211_registered_device *rdev = info->user_ptr[0]; @@ -4300,8 +4274,7 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, memcpy(settings->ciphers_pairwise, data, len); for (i = 0; i < settings->n_ciphers_pairwise; i++) - if (!cfg80211_supported_cipher_suite( - &rdev->wiphy, + if (!nl80211_valid_cipher_suite( settings->ciphers_pairwise[i])) return -EINVAL; } @@ -4309,8 +4282,7 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, if (info->attrs[NL80211_ATTR_CIPHER_SUITE_GROUP]) { settings->cipher_group = nla_get_u32(info->attrs[NL80211_ATTR_CIPHER_SUITE_GROUP]); - if (!cfg80211_supported_cipher_suite(&rdev->wiphy, - settings->cipher_group)) + if (!nl80211_valid_cipher_suite(settings->cipher_group)) return -EINVAL; } @@ -4323,7 +4295,7 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, if (info->attrs[NL80211_ATTR_AKM_SUITES]) { void *data; - int len; + int len, i; data = nla_data(info->attrs[NL80211_ATTR_AKM_SUITES]); len = nla_len(info->attrs[NL80211_ATTR_AKM_SUITES]); @@ -4332,10 +4304,11 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, if (len % sizeof(u32)) return -EINVAL; - if (settings->n_akm_suites > NL80211_MAX_NR_AKM_SUITES) - return -EINVAL; - memcpy(settings->akm_suites, data, len); + + for (i = 0; i < settings->n_ciphers_pairwise; i++) + if (!nl80211_valid_akm_suite(settings->akm_suites[i])) + return -EINVAL; } return 0; @@ -4996,57 +4969,6 @@ static int nl80211_flush_pmksa(struct sk_buff *skb, struct genl_info *info) return rdev->ops->flush_pmksa(&rdev->wiphy, dev); } -static int nl80211_tdls_mgmt(struct sk_buff *skb, struct genl_info *info) -{ - struct cfg80211_registered_device *rdev = info->user_ptr[0]; - struct net_device *dev = info->user_ptr[1]; - u8 action_code, dialog_token; - u16 status_code; - u8 *peer; - - if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) || - !rdev->ops->tdls_mgmt) - return -EOPNOTSUPP; - - if (!info->attrs[NL80211_ATTR_TDLS_ACTION] || - !info->attrs[NL80211_ATTR_STATUS_CODE] || - !info->attrs[NL80211_ATTR_TDLS_DIALOG_TOKEN] || - !info->attrs[NL80211_ATTR_IE] || - !info->attrs[NL80211_ATTR_MAC]) - return -EINVAL; - - peer = nla_data(info->attrs[NL80211_ATTR_MAC]); - action_code = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_ACTION]); - status_code = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]); - dialog_token = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_DIALOG_TOKEN]); - - return rdev->ops->tdls_mgmt(&rdev->wiphy, dev, peer, action_code, - dialog_token, status_code, - nla_data(info->attrs[NL80211_ATTR_IE]), - nla_len(info->attrs[NL80211_ATTR_IE])); -} - -static int nl80211_tdls_oper(struct sk_buff *skb, struct genl_info *info) -{ - struct cfg80211_registered_device *rdev = info->user_ptr[0]; - struct net_device *dev = info->user_ptr[1]; - enum nl80211_tdls_operation operation; - u8 *peer; - - if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) || - !rdev->ops->tdls_oper) - return -EOPNOTSUPP; - - if (!info->attrs[NL80211_ATTR_TDLS_OPERATION] || - !info->attrs[NL80211_ATTR_MAC]) - return -EINVAL; - - operation = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_OPERATION]); - peer = nla_data(info->attrs[NL80211_ATTR_MAC]); - - return rdev->ops->tdls_oper(&rdev->wiphy, dev, peer, operation); -} - static int nl80211_remain_on_channel(struct sk_buff *skb, struct genl_info *info) { @@ -5267,7 +5189,6 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) struct sk_buff *msg; unsigned int wait = 0; bool offchan; - bool no_cck; if (!info->attrs[NL80211_ATTR_FRAME] || !info->attrs[NL80211_ATTR_WIPHY_FREQ]) @@ -5304,8 +5225,6 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) offchan = info->attrs[NL80211_ATTR_OFFCHANNEL_TX_OK]; - no_cck = nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]); - freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); chan = rdev_freq_to_chan(rdev, freq, channel_type); if (chan == NULL) @@ -5326,7 +5245,7 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) channel_type_valid, wait, nla_data(info->attrs[NL80211_ATTR_FRAME]), nla_len(info->attrs[NL80211_ATTR_FRAME]), - no_cck, &cookie); + &cookie); if (err) goto free_msg; @@ -6362,22 +6281,6 @@ static struct genl_ops nl80211_ops[] = { .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | NL80211_FLAG_NEED_RTNL, }, - { - .cmd = NL80211_CMD_TDLS_MGMT, - .doit = nl80211_tdls_mgmt, - .policy = nl80211_policy, - .flags = GENL_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | - NL80211_FLAG_NEED_RTNL, - }, - { - .cmd = NL80211_CMD_TDLS_OPER, - .doit = nl80211_tdls_oper, - .policy = nl80211_policy, - .flags = GENL_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | - NL80211_FLAG_NEED_RTNL, - }, }; static struct genl_multicast_group nl80211_mlme_mcgrp = { diff --git a/trunk/net/wireless/util.c b/trunk/net/wireless/util.c index 2f178f73943f..39dbf4ad7ca1 100644 --- a/trunk/net/wireless/util.c +++ b/trunk/net/wireless/util.c @@ -151,19 +151,12 @@ void ieee80211_set_bitrate_flags(struct wiphy *wiphy) set_mandatory_flags_band(wiphy->bands[band], band); } -bool cfg80211_supported_cipher_suite(struct wiphy *wiphy, u32 cipher) -{ - int i; - for (i = 0; i < wiphy->n_cipher_suites; i++) - if (cipher == wiphy->cipher_suites[i]) - return true; - return false; -} - int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, struct key_params *params, int key_idx, bool pairwise, const u8 *mac_addr) { + int i; + if (key_idx > 5) return -EINVAL; @@ -233,7 +226,10 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, } } - if (!cfg80211_supported_cipher_suite(&rdev->wiphy, params->cipher)) + for (i = 0; i < rdev->wiphy.n_cipher_suites; i++) + if (params->cipher == rdev->wiphy.cipher_suites[i]) + break; + if (i == rdev->wiphy.n_cipher_suites) return -EINVAL; return 0; @@ -396,9 +392,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, } break; case cpu_to_le16(0): - if (iftype != NL80211_IFTYPE_ADHOC && - iftype != NL80211_IFTYPE_STATION) - return -1; + if (iftype != NL80211_IFTYPE_ADHOC) + return -1; break; }