From 1812fdebf62784398666a2ccc6f2e49b1688d574 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Tue, 20 Nov 2012 23:25:54 -0200 Subject: [PATCH] --- yaml --- r: 341944 b: refs/heads/master c: dc2a0e20fbc85a71c63aa4330b496fda33f6bf80 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/MAINTAINERS | 4 +- trunk/drivers/bcma/driver_pci_host.c | 10 +- trunk/drivers/bluetooth/ath3k.c | 1 - trunk/drivers/bluetooth/btusb.c | 1 - trunk/drivers/net/wireless/ath/Kconfig | 7 +- trunk/drivers/net/wireless/ath/ar5523/Kconfig | 1 - trunk/drivers/net/wireless/ath/ath5k/Kconfig | 1 - trunk/drivers/net/wireless/ath/ath5k/base.c | 2 +- .../net/wireless/ath/ath6kl/cfg80211.c | 27 +- trunk/drivers/net/wireless/ath/ath6kl/wmi.c | 5 +- trunk/drivers/net/wireless/ath/ath9k/Kconfig | 1 - .../net/wireless/ath/ath9k/ar9003_mci.c | 1 + trunk/drivers/net/wireless/ath/ath9k/ath9k.h | 41 +- trunk/drivers/net/wireless/ath/ath9k/beacon.c | 2 +- trunk/drivers/net/wireless/ath/ath9k/btcoex.c | 1 - trunk/drivers/net/wireless/ath/ath9k/btcoex.h | 1 - trunk/drivers/net/wireless/ath/ath9k/common.h | 8 + trunk/drivers/net/wireless/ath/ath9k/debug.c | 407 ++---- trunk/drivers/net/wireless/ath/ath9k/debug.h | 35 +- trunk/drivers/net/wireless/ath/ath9k/gpio.c | 58 +- trunk/drivers/net/wireless/ath/ath9k/htc.h | 4 +- .../net/wireless/ath/ath9k/htc_drv_beacon.c | 2 +- .../net/wireless/ath/ath9k/htc_drv_debug.c | 8 +- .../net/wireless/ath/ath9k/htc_drv_gpio.c | 2 +- .../net/wireless/ath/ath9k/htc_drv_init.c | 8 +- .../net/wireless/ath/ath9k/htc_drv_main.c | 4 +- .../net/wireless/ath/ath9k/htc_drv_txrx.c | 28 +- trunk/drivers/net/wireless/ath/ath9k/hw.c | 2 +- trunk/drivers/net/wireless/ath/ath9k/init.c | 6 +- trunk/drivers/net/wireless/ath/ath9k/link.c | 5 +- trunk/drivers/net/wireless/ath/ath9k/main.c | 173 ++- trunk/drivers/net/wireless/ath/ath9k/mci.c | 42 +- trunk/drivers/net/wireless/ath/ath9k/pci.c | 15 +- trunk/drivers/net/wireless/ath/ath9k/rc.c | 53 +- trunk/drivers/net/wireless/ath/ath9k/rc.h | 16 - trunk/drivers/net/wireless/ath/ath9k/recv.c | 2 +- trunk/drivers/net/wireless/ath/ath9k/xmit.c | 29 +- .../drivers/net/wireless/ath/carl9170/Kconfig | 1 - trunk/drivers/net/wireless/b43/xmit.c | 2 +- trunk/drivers/net/wireless/b43legacy/xmit.c | 2 +- trunk/drivers/net/wireless/brcm80211/Kconfig | 11 - .../net/wireless/brcm80211/brcmfmac/fweh.c | 7 +- .../net/wireless/brcm80211/brcmfmac/usb.c | 1 - .../wireless/brcm80211/brcmfmac/wl_cfg80211.c | 152 +- .../wireless/brcm80211/brcmfmac/wl_cfg80211.h | 3 + .../net/wireless/brcm80211/brcmsmac/Makefile | 3 +- .../net/wireless/brcm80211/brcmsmac/ampdu.c | 723 +++++----- .../net/wireless/brcm80211/brcmsmac/ampdu.h | 29 +- .../net/wireless/brcm80211/brcmsmac/antsel.c | 4 +- .../brcm80211/brcmsmac/brcms_trace_events.h | 175 +-- .../net/wireless/brcm80211/brcmsmac/channel.c | 10 +- .../net/wireless/brcm80211/brcmsmac/debug.c | 157 --- .../net/wireless/brcm80211/brcmsmac/debug.h | 75 - .../net/wireless/brcm80211/brcmsmac/dma.c | 345 ++--- .../net/wireless/brcm80211/brcmsmac/dma.h | 11 +- .../wireless/brcm80211/brcmsmac/mac80211_if.c | 152 +- .../net/wireless/brcm80211/brcmsmac/main.c | 1246 ++++++++++++----- .../net/wireless/brcm80211/brcmsmac/main.h | 48 +- .../wireless/brcm80211/brcmsmac/phy/phy_lcn.c | 471 +++---- .../brcm80211/brcmsmac/phy/phytbl_lcn.c | 64 +- .../net/wireless/brcm80211/brcmsmac/pub.h | 42 +- .../net/wireless/brcm80211/brcmsmac/stf.c | 8 +- .../net/wireless/brcm80211/brcmsmac/types.h | 3 +- .../net/wireless/brcm80211/include/defs.h | 11 +- trunk/drivers/net/wireless/ipw2x00/ipw2200.c | 37 +- trunk/drivers/net/wireless/iwlegacy/3945.c | 2 +- .../drivers/net/wireless/iwlegacy/4965-mac.c | 4 +- trunk/drivers/net/wireless/iwlwifi/dvm/dev.h | 1 + .../net/wireless/iwlwifi/dvm/mac80211.c | 28 +- trunk/drivers/net/wireless/iwlwifi/dvm/main.c | 4 +- trunk/drivers/net/wireless/iwlwifi/dvm/rx.c | 4 +- .../drivers/net/wireless/iwlwifi/iwl-config.h | 2 +- trunk/drivers/net/wireless/iwlwifi/iwl-fh.h | 2 +- trunk/drivers/net/wireless/iwlwifi/pcie/drv.c | 1 + .../net/wireless/iwlwifi/pcie/internal.h | 104 +- trunk/drivers/net/wireless/iwlwifi/pcie/rx.c | 380 ++--- .../drivers/net/wireless/iwlwifi/pcie/trans.c | 1018 +++++++++++++- trunk/drivers/net/wireless/iwlwifi/pcie/tx.c | 1146 ++++----------- trunk/drivers/net/wireless/libertas/cfg.c | 24 +- trunk/drivers/net/wireless/mac80211_hwsim.c | 104 +- trunk/drivers/net/wireless/mwifiex/cfg80211.c | 61 +- trunk/drivers/net/wireless/mwifiex/cmdevt.c | 11 +- trunk/drivers/net/wireless/mwifiex/fw.h | 2 - trunk/drivers/net/wireless/mwifiex/main.h | 2 + trunk/drivers/net/wireless/mwifiex/sdio.c | 11 +- .../drivers/net/wireless/mwifiex/sta_event.c | 1 + .../drivers/net/wireless/mwifiex/sta_ioctl.c | 10 +- trunk/drivers/net/wireless/mwifiex/usb.c | 2 +- trunk/drivers/net/wireless/orinoco/cfg.c | 11 +- trunk/drivers/net/wireless/p54/p54pci.c | 13 +- trunk/drivers/net/wireless/p54/txrx.c | 6 +- trunk/drivers/net/wireless/rndis_wlan.c | 2 +- trunk/drivers/net/wireless/rt2x00/rt2800lib.c | 2 +- trunk/drivers/net/wireless/rt2x00/rt2x00dev.c | 7 - .../net/wireless/rtl818x/rtl8180/dev.c | 2 +- .../net/wireless/rtl818x/rtl8187/dev.c | 2 +- trunk/drivers/net/wireless/rtlwifi/pci.c | 2 - trunk/drivers/net/wireless/rtlwifi/pci.h | 2 - .../net/wireless/rtlwifi/rtl8192ce/sw.c | 9 +- .../net/wireless/rtlwifi/rtl8192ce/trx.c | 2 +- .../net/wireless/rtlwifi/rtl8192cu/sw.c | 1 - .../net/wireless/rtlwifi/rtl8192cu/trx.c | 2 +- .../net/wireless/rtlwifi/rtl8192de/sw.c | 9 +- .../net/wireless/rtlwifi/rtl8192de/trx.c | 2 +- .../net/wireless/rtlwifi/rtl8192se/def.h | 3 +- .../net/wireless/rtlwifi/rtl8192se/dm.c | 20 +- .../net/wireless/rtlwifi/rtl8192se/hw.c | 3 +- .../net/wireless/rtlwifi/rtl8192se/hw.h | 2 +- .../net/wireless/rtlwifi/rtl8192se/sw.c | 18 +- .../net/wireless/rtlwifi/rtl8192se/trx.c | 2 +- .../net/wireless/rtlwifi/rtl8723ae/sw.c | 9 +- .../net/wireless/rtlwifi/rtl8723ae/trx.c | 2 +- trunk/drivers/net/wireless/ti/wl1251/rx.c | 2 +- trunk/drivers/net/wireless/ti/wlcore/main.c | 9 +- trunk/drivers/nfc/pn533.c | 25 +- trunk/drivers/nfc/pn544/i2c.c | 2 +- trunk/drivers/ssb/driver_mipscore.c | 14 +- trunk/include/linux/bcma/bcma.h | 5 - trunk/include/linux/ieee80211.h | 40 - trunk/include/linux/nfc/pn544.h | 104 ++ trunk/include/linux/platform_data/pn544.h | 44 - trunk/include/linux/ssb/ssb_driver_extif.h | 42 - trunk/include/net/cfg80211.h | 189 +-- trunk/include/net/mac80211.h | 105 +- trunk/include/net/nfc/hci.h | 3 - trunk/include/uapi/linux/nl80211.h | 106 +- trunk/net/bluetooth/hci_core.c | 4 +- trunk/net/bluetooth/mgmt.c | 12 +- trunk/net/bluetooth/rfcomm/sock.c | 4 +- trunk/net/bluetooth/smp.c | 2 +- trunk/net/core/net-sysfs.c | 20 - trunk/net/mac80211/agg-rx.c | 2 +- trunk/net/mac80211/agg-tx.c | 12 +- trunk/net/mac80211/cfg.c | 138 +- trunk/net/mac80211/chan.c | 128 +- trunk/net/mac80211/debugfs_key.c | 6 +- trunk/net/mac80211/debugfs_netdev.c | 2 + trunk/net/mac80211/debugfs_sta.c | 19 +- trunk/net/mac80211/driver-ops.h | 40 +- trunk/net/mac80211/ht.c | 4 +- trunk/net/mac80211/ibss.c | 83 +- trunk/net/mac80211/ieee80211_i.h | 35 +- trunk/net/mac80211/iface.c | 5 +- trunk/net/mac80211/key.c | 15 +- trunk/net/mac80211/key.h | 8 +- trunk/net/mac80211/main.c | 29 +- trunk/net/mac80211/mesh.c | 36 +- trunk/net/mac80211/mesh.h | 14 + trunk/net/mac80211/mesh_plink.c | 47 +- trunk/net/mac80211/mesh_sync.c | 46 +- trunk/net/mac80211/mlme.c | 94 +- trunk/net/mac80211/offchannel.c | 10 +- trunk/net/mac80211/pm.c | 44 +- trunk/net/mac80211/rate.c | 5 +- trunk/net/mac80211/rate.h | 2 +- trunk/net/mac80211/rx.c | 128 +- trunk/net/mac80211/scan.c | 11 +- trunk/net/mac80211/sta_info.c | 23 +- trunk/net/mac80211/sta_info.h | 27 +- trunk/net/mac80211/status.c | 9 - trunk/net/mac80211/trace.h | 40 +- trunk/net/mac80211/tx.c | 29 +- trunk/net/mac80211/util.c | 137 +- trunk/net/mac80211/wme.c | 40 +- trunk/net/nfc/hci/command.c | 4 +- trunk/net/nfc/hci/core.c | 25 +- trunk/net/nfc/llcp/commands.c | 32 +- trunk/net/nfc/llcp/llcp.c | 19 +- trunk/net/wireless/chan.c | 280 +--- trunk/net/wireless/core.h | 23 +- trunk/net/wireless/ibss.c | 27 +- trunk/net/wireless/mesh.c | 49 +- trunk/net/wireless/mlme.c | 36 +- trunk/net/wireless/nl80211.c | 462 +++--- trunk/net/wireless/nl80211.h | 8 +- trunk/net/wireless/rdev-ops.h | 42 +- trunk/net/wireless/reg.c | 5 +- trunk/net/wireless/scan.c | 45 +- trunk/net/wireless/trace.h | 318 ++--- trunk/net/wireless/util.c | 79 +- trunk/net/wireless/wext-compat.c | 28 +- trunk/net/wireless/wext-sme.c | 11 +- 183 files changed, 5149 insertions(+), 6209 deletions(-) delete mode 100644 trunk/drivers/net/wireless/brcm80211/brcmsmac/debug.c delete mode 100644 trunk/drivers/net/wireless/brcm80211/brcmsmac/debug.h create mode 100644 trunk/include/linux/nfc/pn544.h delete mode 100644 trunk/include/linux/platform_data/pn544.h diff --git a/[refs] b/[refs] index e45a2e2e94b4..e7138e01b8b3 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 55cec505559dade9e7776de8f3d23fc3e54e091d +refs/heads/master: dc2a0e20fbc85a71c63aa4330b496fda33f6bf80 diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index 46ce7c6d527d..568ea9373091 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -1658,9 +1658,10 @@ F: drivers/net/ethernet/broadcom/tg3.* BROADCOM BRCM80211 IEEE802.11n WIRELESS DRIVER M: Brett Rudley +M: Roland Vossen M: Arend van Spriel M: Franky (Zhenhui) Lin -M: Hante Meuleman +M: Kan Yan L: linux-wireless@vger.kernel.org L: brcm80211-dev-list@broadcom.com S: Supported @@ -5066,7 +5067,6 @@ F: net/nfc/ F: include/linux/nfc.h F: include/net/nfc/ F: drivers/nfc/ -F: include/linux/platform_data/pn544.h NFS, SUNRPC, AND LOCKD CLIENTS M: Trond Myklebust diff --git a/trunk/drivers/bcma/driver_pci_host.c b/trunk/drivers/bcma/driver_pci_host.c index e6b5c89469dc..e56449506695 100644 --- a/trunk/drivers/bcma/driver_pci_host.c +++ b/trunk/drivers/bcma/driver_pci_host.c @@ -538,7 +538,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, bcma_core_pci_fixup_pcibridge); static void bcma_core_pci_fixup_addresses(struct pci_dev *dev) { struct resource *res; - int pos, err; + int pos; if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) { /* This is not a device on the PCI-core bridge. */ @@ -551,12 +551,8 @@ static void bcma_core_pci_fixup_addresses(struct pci_dev *dev) for (pos = 0; pos < 6; pos++) { res = &dev->resource[pos]; - if (res->flags & (IORESOURCE_IO | IORESOURCE_MEM)) { - err = pci_assign_resource(dev, pos); - if (err) - pr_err("PCI: Problem fixing up the addresses on %s\n", - pci_name(dev)); - } + if (res->flags & (IORESOURCE_IO | IORESOURCE_MEM)) + pci_assign_resource(dev, pos); } } DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, bcma_core_pci_fixup_addresses); diff --git a/trunk/drivers/bluetooth/ath3k.c b/trunk/drivers/bluetooth/ath3k.c index b00000e8aef6..fc2de5528dcc 100644 --- a/trunk/drivers/bluetooth/ath3k.c +++ b/trunk/drivers/bluetooth/ath3k.c @@ -67,7 +67,6 @@ static struct usb_device_id ath3k_table[] = { { USB_DEVICE(0x13d3, 0x3304) }, { USB_DEVICE(0x0930, 0x0215) }, { USB_DEVICE(0x0489, 0xE03D) }, - { USB_DEVICE(0x0489, 0xE027) }, /* Atheros AR9285 Malbec with sflash firmware */ { USB_DEVICE(0x03F0, 0x311D) }, diff --git a/trunk/drivers/bluetooth/btusb.c b/trunk/drivers/bluetooth/btusb.c index a1d4ede5b892..5693b9b31477 100644 --- a/trunk/drivers/bluetooth/btusb.c +++ b/trunk/drivers/bluetooth/btusb.c @@ -125,7 +125,6 @@ static struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x13d3, 0x3304), .driver_info = BTUSB_IGNORE }, { USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE }, { USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE }, - { USB_DEVICE(0x0489, 0xe027), .driver_info = BTUSB_IGNORE }, /* Atheros AR9285 Malbec with sflash firmware */ { USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE }, diff --git a/trunk/drivers/net/wireless/ath/Kconfig b/trunk/drivers/net/wireless/ath/Kconfig index 1a67a4f829fe..c25dcf192fec 100644 --- a/trunk/drivers/net/wireless/ath/Kconfig +++ b/trunk/drivers/net/wireless/ath/Kconfig @@ -1,7 +1,4 @@ -config ATH_COMMON - tristate - -menuconfig ATH_CARDS +menuconfig ATH_COMMON tristate "Atheros Wireless Cards" depends on CFG80211 && (!UML || BROKEN) ---help--- @@ -17,7 +14,7 @@ menuconfig ATH_CARDS http://wireless.kernel.org/en/users/Drivers/Atheros -if ATH_CARDS +if ATH_COMMON config ATH_DEBUG bool "Atheros wireless debugging" diff --git a/trunk/drivers/net/wireless/ath/ar5523/Kconfig b/trunk/drivers/net/wireless/ath/ar5523/Kconfig index 0d320cc7769b..11d99ee8de51 100644 --- a/trunk/drivers/net/wireless/ath/ar5523/Kconfig +++ b/trunk/drivers/net/wireless/ath/ar5523/Kconfig @@ -1,7 +1,6 @@ config AR5523 tristate "Atheros AR5523 wireless driver support" depends on MAC80211 && USB - select ATH_COMMON select FW_LOADER ---help--- This module add support for AR5523 based USB dongles such as D-Link diff --git a/trunk/drivers/net/wireless/ath/ath5k/Kconfig b/trunk/drivers/net/wireless/ath/ath5k/Kconfig index c9f81a388f15..338c5c42357d 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/Kconfig +++ b/trunk/drivers/net/wireless/ath/ath5k/Kconfig @@ -1,7 +1,6 @@ config ATH5K tristate "Atheros 5xxx wireless cards support" depends on (PCI || ATHEROS_AR231X) && MAC80211 - select ATH_COMMON select MAC80211_LEDS select LEDS_CLASS select NEW_LEDS diff --git a/trunk/drivers/net/wireless/ath/ath5k/base.c b/trunk/drivers/net/wireless/ath/ath5k/base.c index 2fd5bab2e22a..cdd19232960c 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/base.c +++ b/trunk/drivers/net/wireless/ath/ath5k/base.c @@ -1349,7 +1349,7 @@ ath5k_receive_frame(struct ath5k_hw *ah, struct sk_buff *skb, * right now, so it's not too bad... */ rxs->mactime = ath5k_extend_tsf(ah, rs->rs_tstamp); - rxs->flag |= RX_FLAG_MACTIME_START; + rxs->flag |= RX_FLAG_MACTIME_MPDU; rxs->freq = ah->curchan->center_freq; rxs->band = ah->curchan->band; diff --git a/trunk/drivers/net/wireless/ath/ath6kl/cfg80211.c b/trunk/drivers/net/wireless/ath/ath6kl/cfg80211.c index 5516a8ccc3c6..83d8c5eabbee 100644 --- a/trunk/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/trunk/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -1074,18 +1074,15 @@ void ath6kl_cfg80211_scan_complete_event(struct ath6kl_vif *vif, bool aborted) void ath6kl_cfg80211_ch_switch_notify(struct ath6kl_vif *vif, int freq, enum wmi_phy_mode mode) { - struct cfg80211_chan_def chandef; + enum nl80211_channel_type type; ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "channel switch notify nw_type %d freq %d mode %d\n", vif->nw_type, freq, mode); - cfg80211_chandef_create(&chandef, - ieee80211_get_channel(vif->ar->wiphy, freq), - (mode == WMI_11G_HT20) ? - NL80211_CHAN_HT20 : NL80211_CHAN_NO_HT); + type = (mode == WMI_11G_HT20) ? NL80211_CHAN_HT20 : NL80211_CHAN_NO_HT; - cfg80211_ch_switch_notify(vif->ndev, &chandef); + cfg80211_ch_switch_notify(vif->ndev, freq, type); } static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, @@ -1597,8 +1594,8 @@ static int ath6kl_cfg80211_join_ibss(struct wiphy *wiphy, vif->ssid_len = ibss_param->ssid_len; memcpy(vif->ssid, ibss_param->ssid, vif->ssid_len); - if (ibss_param->chandef.chan) - vif->ch_hint = ibss_param->chandef.chan->center_freq; + if (ibss_param->channel) + vif->ch_hint = ibss_param->channel->center_freq; if (ibss_param->channel_fixed) { /* @@ -2881,7 +2878,7 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev, p.ssid_len = vif->ssid_len; memcpy(p.ssid, vif->ssid, vif->ssid_len); p.dot11_auth_mode = vif->dot11_auth_mode; - p.ch = cpu_to_le16(info->chandef.chan->center_freq); + p.ch = cpu_to_le16(info->channel->center_freq); /* Enable uAPSD support by default */ res = ath6kl_wmi_ap_set_apsd(ar->wmi, vif->fw_vif_idx, true); @@ -2912,9 +2909,8 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev, return res; } - if (ath6kl_set_htcap(vif, info->chandef.chan->band, - cfg80211_get_chandef_type(&info->chandef) - != NL80211_CHAN_NO_HT)) + if (ath6kl_set_htcap(vif, info->channel->band, + info->channel_type != NL80211_CHAN_NO_HT)) return -EIO; /* @@ -3010,6 +3006,7 @@ static int ath6kl_change_station(struct wiphy *wiphy, struct net_device *dev, static int ath6kl_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev, struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, unsigned int duration, u64 *cookie) { @@ -3168,8 +3165,10 @@ static bool ath6kl_is_p2p_go_ssid(const u8 *buf, size_t len) static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, struct ieee80211_channel *chan, bool offchan, - unsigned int wait, const u8 *buf, size_t len, - bool no_cck, bool dont_wait_for_ack, u64 *cookie) + enum nl80211_channel_type channel_type, + bool channel_type_valid, unsigned int wait, + const u8 *buf, size_t len, bool no_cck, + bool dont_wait_for_ack, u64 *cookie) { struct ath6kl_vif *vif = ath6kl_vif_from_wdev(wdev); struct ath6kl *ar = ath6kl_priv(vif->ndev); diff --git a/trunk/drivers/net/wireless/ath/ath6kl/wmi.c b/trunk/drivers/net/wireless/ath/ath6kl/wmi.c index 998f8b0f62fd..55ccf9770339 100644 --- a/trunk/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/trunk/drivers/net/wireless/ath/ath6kl/wmi.c @@ -474,7 +474,7 @@ static int ath6kl_wmi_remain_on_chnl_event_rx(struct wmi *wmi, u8 *datap, return -EINVAL; } id = vif->last_roc_id; - cfg80211_ready_on_channel(&vif->wdev, id, chan, + cfg80211_ready_on_channel(&vif->wdev, id, chan, NL80211_CHAN_NO_HT, dur, GFP_ATOMIC); return 0; @@ -513,7 +513,8 @@ static int ath6kl_wmi_cancel_remain_on_chnl_event_rx(struct wmi *wmi, else id = vif->last_roc_id; /* timeout on uncanceled r-o-c */ vif->last_cancel_roc_id = 0; - cfg80211_remain_on_channel_expired(&vif->wdev, id, chan, GFP_ATOMIC); + cfg80211_remain_on_channel_expired(&vif->wdev, id, chan, + NL80211_CHAN_NO_HT, GFP_ATOMIC); return 0; } diff --git a/trunk/drivers/net/wireless/ath/ath9k/Kconfig b/trunk/drivers/net/wireless/ath/ath9k/Kconfig index 5fc15bf8be09..c7aa6646123e 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/Kconfig +++ b/trunk/drivers/net/wireless/ath/ath9k/Kconfig @@ -17,7 +17,6 @@ config ATH9K_BTCOEX_SUPPORT config ATH9K tristate "Atheros 802.11n wireless cards support" depends on MAC80211 - select ATH_COMMON select ATH9K_HW select MAC80211_LEDS select LEDS_CLASS diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_mci.c b/trunk/drivers/net/wireless/ath/ath9k/ar9003_mci.c index 8dd069259e7b..42b4412d6794 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_mci.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_mci.c @@ -714,6 +714,7 @@ bool ar9003_mci_start_reset(struct ath_hw *ah, struct ath9k_channel *chan) return true; } +EXPORT_SYMBOL(ar9003_mci_start_reset); int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan, struct ath9k_hw_cal_data *caldata) diff --git a/trunk/drivers/net/wireless/ath/ath9k/ath9k.h b/trunk/drivers/net/wireless/ath/ath9k/ath9k.h index 86e26a19efda..4e125d8904a0 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/trunk/drivers/net/wireless/ath/ath9k/ath9k.h @@ -129,10 +129,10 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd, #define ATH_TXMAXTRY 13 #define TID_TO_WME_AC(_tid) \ - ((((_tid) == 0) || ((_tid) == 3)) ? IEEE80211_AC_BE : \ - (((_tid) == 1) || ((_tid) == 2)) ? IEEE80211_AC_BK : \ - (((_tid) == 4) || ((_tid) == 5)) ? IEEE80211_AC_VI : \ - IEEE80211_AC_VO) + ((((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE : \ + (((_tid) == 1) || ((_tid) == 2)) ? WME_AC_BK : \ + (((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI : \ + WME_AC_VO) #define ATH_AGGR_DELIM_SZ 4 #define ATH_AGGR_MINPLEN 256 /* in bytes, minimum packet length */ @@ -259,21 +259,19 @@ struct ath_atx_tid { }; struct ath_node { - struct ath_softc *sc; +#ifdef CONFIG_ATH9K_DEBUGFS + struct list_head list; /* for sc->nodes */ +#endif struct ieee80211_sta *sta; /* station struct we're part of */ struct ieee80211_vif *vif; /* interface with which we're associated */ - struct ath_atx_tid tid[IEEE80211_NUM_TIDS]; - struct ath_atx_ac ac[IEEE80211_NUM_ACS]; + struct ath_atx_tid tid[WME_NUM_TID]; + struct ath_atx_ac ac[WME_NUM_AC]; int ps_key; u16 maxampdu; u8 mpdudensity; bool sleeping; - -#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS) - struct dentry *node_stat; -#endif }; #define AGGR_CLEANUP BIT(1) @@ -301,9 +299,9 @@ struct ath_tx { struct list_head txbuf; struct ath_txq txq[ATH9K_NUM_TX_QUEUES]; struct ath_descdma txdma; - struct ath_txq *txq_map[IEEE80211_NUM_ACS]; - u32 txq_max_pending[IEEE80211_NUM_ACS]; - u16 max_aggr_framelen[IEEE80211_NUM_ACS][4][32]; + struct ath_txq *txq_map[WME_NUM_AC]; + u32 txq_max_pending[WME_NUM_AC]; + u16 max_aggr_framelen[WME_NUM_AC][4][32]; }; struct ath_rx_edma { @@ -463,12 +461,6 @@ void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type); /* BTCOEX */ /**********/ -#define ATH_DUMP_BTCOEX(_s, _val) \ - do { \ - len += snprintf(buf + len, size - len, \ - "%20s : %10d\n", _s, (_val)); \ - } while (0) - enum bt_op_flags { BT_OP_PRIORITY_DETECTED, BT_OP_SCAN, @@ -490,7 +482,6 @@ struct ath_btcoex { int rssi_count; struct ath_gen_timer *no_stomp_timer; /* Timer for no BT stomping */ struct ath_mci_profile mci; - u8 stomp_audio; }; #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT @@ -503,7 +494,7 @@ void ath9k_btcoex_timer_pause(struct ath_softc *sc); void ath9k_btcoex_handle_interrupt(struct ath_softc *sc, u32 status); u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen); void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc); -int ath9k_dump_btcoex(struct ath_softc *sc, u8 *buf, u32 size); +int ath9k_dump_btcoex(struct ath_softc *sc, u8 *buf, u32 len, u32 size); #else static inline int ath9k_init_btcoex(struct ath_softc *sc) { @@ -530,7 +521,8 @@ static inline u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, static inline void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc) { } -static inline int ath9k_dump_btcoex(struct ath_softc *sc, u8 *buf, u32 size) +static inline int ath9k_dump_btcoex(struct ath_softc *sc, u8 *buf, + u32 len, u32 size) { return 0; } @@ -725,6 +717,9 @@ struct ath_softc { #ifdef CONFIG_ATH9K_DEBUGFS struct ath9k_debug debug; + spinlock_t nodes_lock; + struct list_head nodes; /* basically, stations */ + unsigned int tx_complete_poll_work_seen; #endif struct ath_beacon_config cur_beacon_conf; struct delayed_work tx_complete_work; diff --git a/trunk/drivers/net/wireless/ath/ath9k/beacon.c b/trunk/drivers/net/wireless/ath/ath9k/beacon.c index 531fffd801a3..1b48414dca95 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/beacon.c +++ b/trunk/drivers/net/wireless/ath/ath9k/beacon.c @@ -46,7 +46,7 @@ static void ath9k_beaconq_config(struct ath_softc *sc) qi.tqi_cwmax = 0; } else { /* Adhoc mode; important thing is to use 2x cwmin. */ - txq = sc->tx.txq_map[IEEE80211_AC_BE]; + txq = sc->tx.txq_map[WME_AC_BE]; ath9k_hw_get_txq_props(ah, txq->axq_qnum, &qi_be); qi.tqi_aifs = qi_be.tqi_aifs; if (ah->slottime == ATH9K_SLOT_TIME_20) diff --git a/trunk/drivers/net/wireless/ath/ath9k/btcoex.c b/trunk/drivers/net/wireless/ath/ath9k/btcoex.c index 9963b0bf9f72..c90e9bc4b026 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/btcoex.c +++ b/trunk/drivers/net/wireless/ath/ath9k/btcoex.c @@ -49,7 +49,6 @@ static const u32 mci_wlan_weights[ATH_BTCOEX_STOMP_MAX] { 0x01017d01, 0x3b3b3b01, 0x3b3b3b01, 0x3b3b3b3b }, /* STOMP_LOW */ { 0x01017d01, 0x01010101, 0x01010101, 0x01010101 }, /* STOMP_NONE */ { 0x01017d01, 0x013b0101, 0x3b3b0101, 0x3b3b013b }, /* STOMP_LOW_FTP */ - { 0xffffff01, 0xffffffff, 0xffffff01, 0xffffffff }, /* STOMP_AUDIO */ }; void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum) diff --git a/trunk/drivers/net/wireless/ath/ath9k/btcoex.h b/trunk/drivers/net/wireless/ath/ath9k/btcoex.h index 6de26ea5d5fa..2f84ab273d0c 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/btcoex.h +++ b/trunk/drivers/net/wireless/ath/ath9k/btcoex.h @@ -50,7 +50,6 @@ enum ath_stomp_type { ATH_BTCOEX_STOMP_LOW, ATH_BTCOEX_STOMP_NONE, ATH_BTCOEX_STOMP_LOW_FTP, - ATH_BTCOEX_STOMP_AUDIO, ATH_BTCOEX_STOMP_MAX }; diff --git a/trunk/drivers/net/wireless/ath/ath9k/common.h b/trunk/drivers/net/wireless/ath/ath9k/common.h index 5f845beeb18b..ad14fecc76c6 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/common.h +++ b/trunk/drivers/net/wireless/ath/ath9k/common.h @@ -23,10 +23,18 @@ /* Common header for Atheros 802.11n base driver cores */ +#define WME_NUM_TID 16 #define WME_BA_BMP_SIZE 64 #define WME_MAX_BA WME_BA_BMP_SIZE #define ATH_TID_MAX_BUFS (2 * WME_MAX_BA) +/* These must match mac80211 skb queue mapping numbers */ +#define WME_AC_VO 0 +#define WME_AC_VI 1 +#define WME_AC_BE 2 +#define WME_AC_BK 3 +#define WME_NUM_AC 4 + #define ATH_RSSI_DUMMY_MARKER 0x127 #define ATH_RSSI_LPF_LEN 10 #define RSSI_LPF_THRESHOLD -20 diff --git a/trunk/drivers/net/wireless/ath/ath9k/debug.c b/trunk/drivers/net/wireless/ath/ath9k/debug.c index 13ff9edc2401..a8be94b2a53a 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/debug.c +++ b/trunk/drivers/net/wireless/ath/ath9k/debug.c @@ -512,19 +512,62 @@ static const struct file_operations fops_interrupt = { .llseek = default_llseek, }; +#define PR_QNUM(_n) sc->tx.txq_map[_n]->axq_qnum +#define PR(str, elem) \ + do { \ + len += snprintf(buf + len, size - len, \ + "%s%13u%11u%10u%10u\n", str, \ + sc->debug.stats.txstats[PR_QNUM(WME_AC_BE)].elem, \ + sc->debug.stats.txstats[PR_QNUM(WME_AC_BK)].elem, \ + sc->debug.stats.txstats[PR_QNUM(WME_AC_VI)].elem, \ + sc->debug.stats.txstats[PR_QNUM(WME_AC_VO)].elem); \ + if (len >= size) \ + goto done; \ +} while(0) + +#define PRX(str, elem) \ +do { \ + len += snprintf(buf + len, size - len, \ + "%s%13u%11u%10u%10u\n", str, \ + (unsigned int)(sc->tx.txq_map[WME_AC_BE]->elem), \ + (unsigned int)(sc->tx.txq_map[WME_AC_BK]->elem), \ + (unsigned int)(sc->tx.txq_map[WME_AC_VI]->elem), \ + (unsigned int)(sc->tx.txq_map[WME_AC_VO]->elem)); \ + if (len >= size) \ + goto done; \ +} while(0) + +#define PRQLE(str, elem) \ +do { \ + len += snprintf(buf + len, size - len, \ + "%s%13i%11i%10i%10i\n", str, \ + list_empty(&sc->tx.txq_map[WME_AC_BE]->elem), \ + list_empty(&sc->tx.txq_map[WME_AC_BK]->elem), \ + list_empty(&sc->tx.txq_map[WME_AC_VI]->elem), \ + list_empty(&sc->tx.txq_map[WME_AC_VO]->elem)); \ + if (len >= size) \ + goto done; \ +} while (0) + static ssize_t read_file_xmit(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct ath_softc *sc = file->private_data; char *buf; - unsigned int len = 0, size = 2048; + unsigned int len = 0, size = 8000; + int i; ssize_t retval = 0; + char tmp[32]; buf = kzalloc(size, GFP_KERNEL); if (buf == NULL) return -ENOMEM; - len += sprintf(buf, "%30s %10s%10s%10s\n\n", + len += sprintf(buf, "Num-Tx-Queues: %i tx-queues-setup: 0x%x" + " poll-work-seen: %u\n" + "%30s %10s%10s%10s\n\n", + ATH9K_NUM_TX_QUEUES, sc->tx.txqsetup, + sc->tx_complete_poll_work_seen, "BE", "BK", "VI", "VO"); PR("MPDUs Queued: ", queued); @@ -544,11 +587,62 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf, PR("DELIM Underrun: ", delim_underrun); PR("TX-Pkts-All: ", tx_pkts_all); PR("TX-Bytes-All: ", tx_bytes_all); - PR("HW-put-tx-buf: ", puttxbuf); - PR("HW-tx-start: ", txstart); - PR("HW-tx-proc-desc: ", txprocdesc); + PR("hw-put-tx-buf: ", puttxbuf); + PR("hw-tx-start: ", txstart); + PR("hw-tx-proc-desc: ", txprocdesc); PR("TX-Failed: ", txfailed); + len += snprintf(buf + len, size - len, + "%s%11p%11p%10p%10p\n", "txq-memory-address:", + sc->tx.txq_map[WME_AC_BE], + sc->tx.txq_map[WME_AC_BK], + sc->tx.txq_map[WME_AC_VI], + sc->tx.txq_map[WME_AC_VO]); + if (len >= size) + goto done; + + PRX("axq-qnum: ", axq_qnum); + PRX("axq-depth: ", axq_depth); + PRX("axq-ampdu_depth: ", axq_ampdu_depth); + PRX("axq-stopped ", stopped); + PRX("tx-in-progress ", axq_tx_inprogress); + PRX("pending-frames ", pending_frames); + PRX("txq_headidx: ", txq_headidx); + PRX("txq_tailidx: ", txq_headidx); + + PRQLE("axq_q empty: ", axq_q); + PRQLE("axq_acq empty: ", axq_acq); + for (i = 0; i < ATH_TXFIFO_DEPTH; i++) { + snprintf(tmp, sizeof(tmp) - 1, "txq_fifo[%i] empty: ", i); + PRQLE(tmp, txq_fifo[i]); + } + /* Print out more detailed queue-info */ + for (i = 0; i <= WME_AC_BK; i++) { + struct ath_txq *txq = &(sc->tx.txq[i]); + struct ath_atx_ac *ac; + struct ath_atx_tid *tid; + if (len >= size) + goto done; + spin_lock_bh(&txq->axq_lock); + if (!list_empty(&txq->axq_acq)) { + ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, + list); + len += snprintf(buf + len, size - len, + "txq[%i] first-ac: %p sched: %i\n", + i, ac, ac->sched); + if (list_empty(&ac->tid_q) || (len >= size)) + goto done_for; + tid = list_first_entry(&ac->tid_q, struct ath_atx_tid, + list); + len += snprintf(buf + len, size - len, + " first-tid: %p sched: %i paused: %i\n", + tid, tid->sched, tid->paused); + } + done_for: + spin_unlock_bh(&txq->axq_lock); + } + +done: if (len > size) len = size; @@ -558,41 +652,62 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf, return retval; } -static ssize_t read_file_queues(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) +static ssize_t read_file_stations(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) { struct ath_softc *sc = file->private_data; - struct ath_txq *txq; char *buf; - unsigned int len = 0, size = 1024; + unsigned int len = 0, size = 64000; + struct ath_node *an = NULL; ssize_t retval = 0; - int i; - char *qname[4] = {"VO", "VI", "BE", "BK"}; + int q; buf = kzalloc(size, GFP_KERNEL); if (buf == NULL) return -ENOMEM; - for (i = 0; i < IEEE80211_NUM_ACS; i++) { - txq = sc->tx.txq_map[i]; - len += snprintf(buf + len, size - len, "(%s): ", qname[i]); - - ath_txq_lock(sc, txq); - - len += snprintf(buf + len, size - len, "%s: %d ", - "qnum", txq->axq_qnum); - len += snprintf(buf + len, size - len, "%s: %2d ", - "qdepth", txq->axq_depth); - len += snprintf(buf + len, size - len, "%s: %2d ", - "ampdu-depth", txq->axq_ampdu_depth); - len += snprintf(buf + len, size - len, "%s: %3d ", - "pending", txq->pending_frames); - len += snprintf(buf + len, size - len, "%s: %d\n", - "stopped", txq->stopped); + len += snprintf(buf + len, size - len, + "Stations:\n" + " tid: addr sched paused buf_q-empty an ac baw\n" + " ac: addr sched tid_q-empty txq\n"); + + spin_lock(&sc->nodes_lock); + list_for_each_entry(an, &sc->nodes, list) { + unsigned short ma = an->maxampdu; + if (ma == 0) + ma = 65535; /* see ath_lookup_rate */ + len += snprintf(buf + len, size - len, + "iface: %pM sta: %pM max-ampdu: %hu mpdu-density: %uus\n", + an->vif->addr, an->sta->addr, ma, + (unsigned int)(an->mpdudensity)); + if (len >= size) + goto done; + + for (q = 0; q < WME_NUM_TID; q++) { + struct ath_atx_tid *tid = &(an->tid[q]); + len += snprintf(buf + len, size - len, + " tid: %p %s %s %i %p %p %hu\n", + tid, tid->sched ? "sched" : "idle", + tid->paused ? "paused" : "running", + skb_queue_empty(&tid->buf_q), + tid->an, tid->ac, tid->baw_size); + if (len >= size) + goto done; + } - ath_txq_unlock(sc, txq); + for (q = 0; q < WME_NUM_AC; q++) { + struct ath_atx_ac *ac = &(an->ac[q]); + len += snprintf(buf + len, size - len, + " ac: %p %s %i %p\n", + ac, ac->sched ? "sched" : "idle", + list_empty(&ac->tid_q), ac->txq); + if (len >= size) + goto done; + } } +done: + spin_unlock(&sc->nodes_lock); if (len > size) len = size; @@ -722,9 +837,6 @@ static ssize_t read_file_reset(struct file *file, char __user *user_buf, len += snprintf(buf + len, sizeof(buf) - len, "%17s: %2d\n", "PLL RX Hang", sc->debug.stats.reset[RESET_TYPE_PLL_HANG]); - len += snprintf(buf + len, sizeof(buf) - len, - "%17s: %2d\n", "MCI Reset", - sc->debug.stats.reset[RESET_TYPE_MCI]); if (len > sizeof(buf)) len = sizeof(buf); @@ -807,8 +919,8 @@ static const struct file_operations fops_xmit = { .llseek = default_llseek, }; -static const struct file_operations fops_queues = { - .read = read_file_queues, +static const struct file_operations fops_stations = { + .read = read_file_stations, .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, @@ -1487,14 +1599,8 @@ static ssize_t read_file_btcoex(struct file *file, char __user *user_buf, if (buf == NULL) return -ENOMEM; - if (!sc->sc_ah->common.btcoex_enabled) { - len = snprintf(buf, size, "%s\n", - "BTCOEX is disabled"); - goto exit; - } + len = ath9k_dump_btcoex(sc, buf, len, size); - len = ath9k_dump_btcoex(sc, buf, size); -exit: retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); kfree(buf); @@ -1509,215 +1615,6 @@ static const struct file_operations fops_btcoex = { }; #endif -static ssize_t read_file_node_stat(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath_node *an = file->private_data; - struct ath_softc *sc = an->sc; - struct ath_atx_tid *tid; - struct ath_atx_ac *ac; - struct ath_txq *txq; - u32 len = 0, size = 4096; - char *buf; - size_t retval; - int tidno, acno; - - buf = kzalloc(size, GFP_KERNEL); - if (buf == NULL) - return -ENOMEM; - - if (!an->sta->ht_cap.ht_supported) { - len = snprintf(buf, size, "%s\n", - "HT not supported"); - goto exit; - } - - len = snprintf(buf, size, "Max-AMPDU: %d\n", - an->maxampdu); - len += snprintf(buf + len, size - len, "MPDU Density: %d\n\n", - an->mpdudensity); - - len += snprintf(buf + len, size - len, - "%2s%7s\n", "AC", "SCHED"); - - for (acno = 0, ac = &an->ac[acno]; - acno < IEEE80211_NUM_ACS; acno++, ac++) { - txq = ac->txq; - ath_txq_lock(sc, txq); - len += snprintf(buf + len, size - len, - "%2d%7d\n", - acno, ac->sched); - ath_txq_unlock(sc, txq); - } - - len += snprintf(buf + len, size - len, - "\n%3s%11s%10s%10s%10s%10s%9s%6s%8s\n", - "TID", "SEQ_START", "SEQ_NEXT", "BAW_SIZE", - "BAW_HEAD", "BAW_TAIL", "BAR_IDX", "SCHED", "PAUSED"); - - for (tidno = 0, tid = &an->tid[tidno]; - tidno < IEEE80211_NUM_TIDS; tidno++, tid++) { - txq = tid->ac->txq; - ath_txq_lock(sc, txq); - len += snprintf(buf + len, size - len, - "%3d%11d%10d%10d%10d%10d%9d%6d%8d\n", - tid->tidno, tid->seq_start, tid->seq_next, - tid->baw_size, tid->baw_head, tid->baw_tail, - tid->bar_index, tid->sched, tid->paused); - ath_txq_unlock(sc, txq); - } -exit: - retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); - kfree(buf); - - return retval; -} - -static const struct file_operations fops_node_stat = { - .read = read_file_node_stat, - .open = simple_open, - .owner = THIS_MODULE, - .llseek = default_llseek, -}; - -void ath9k_sta_add_debugfs(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct dentry *dir) -{ - struct ath_node *an = (struct ath_node *)sta->drv_priv; - an->node_stat = debugfs_create_file("node_stat", S_IRUGO, - dir, an, &fops_node_stat); -} - -void ath9k_sta_remove_debugfs(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct dentry *dir) -{ - struct ath_node *an = (struct ath_node *)sta->drv_priv; - debugfs_remove(an->node_stat); -} - -/* Ethtool support for get-stats */ - -#define AMKSTR(nm) #nm "_BE", #nm "_BK", #nm "_VI", #nm "_VO" -static const char ath9k_gstrings_stats[][ETH_GSTRING_LEN] = { - "tx_pkts_nic", - "tx_bytes_nic", - "rx_pkts_nic", - "rx_bytes_nic", - AMKSTR(d_tx_pkts), - AMKSTR(d_tx_bytes), - AMKSTR(d_tx_mpdus_queued), - AMKSTR(d_tx_mpdus_completed), - AMKSTR(d_tx_mpdu_xretries), - AMKSTR(d_tx_aggregates), - AMKSTR(d_tx_ampdus_queued_hw), - AMKSTR(d_tx_ampdus_queued_sw), - AMKSTR(d_tx_ampdus_completed), - AMKSTR(d_tx_ampdu_retries), - AMKSTR(d_tx_ampdu_xretries), - AMKSTR(d_tx_fifo_underrun), - AMKSTR(d_tx_op_exceeded), - AMKSTR(d_tx_timer_expiry), - AMKSTR(d_tx_desc_cfg_err), - AMKSTR(d_tx_data_underrun), - AMKSTR(d_tx_delim_underrun), - "d_rx_decrypt_crc_err", - "d_rx_phy_err", - "d_rx_mic_err", - "d_rx_pre_delim_crc_err", - "d_rx_post_delim_crc_err", - "d_rx_decrypt_busy_err", - - "d_rx_phyerr_radar", - "d_rx_phyerr_ofdm_timing", - "d_rx_phyerr_cck_timing", - -}; -#define ATH9K_SSTATS_LEN ARRAY_SIZE(ath9k_gstrings_stats) - -void ath9k_get_et_strings(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - u32 sset, u8 *data) -{ - if (sset == ETH_SS_STATS) - memcpy(data, *ath9k_gstrings_stats, - sizeof(ath9k_gstrings_stats)); -} - -int ath9k_get_et_sset_count(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, int sset) -{ - if (sset == ETH_SS_STATS) - return ATH9K_SSTATS_LEN; - return 0; -} - -#define AWDATA(elem) \ - do { \ - data[i++] = sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BE)].elem; \ - data[i++] = sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BK)].elem; \ - data[i++] = sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VI)].elem; \ - data[i++] = sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VO)].elem; \ - } while (0) - -#define AWDATA_RX(elem) \ - do { \ - data[i++] = sc->debug.stats.rxstats.elem; \ - } while (0) - -void ath9k_get_et_stats(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ethtool_stats *stats, u64 *data) -{ - struct ath_softc *sc = hw->priv; - int i = 0; - - data[i++] = (sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BE)].tx_pkts_all + - sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BK)].tx_pkts_all + - sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VI)].tx_pkts_all + - sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VO)].tx_pkts_all); - data[i++] = (sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BE)].tx_bytes_all + - sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BK)].tx_bytes_all + - sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VI)].tx_bytes_all + - sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VO)].tx_bytes_all); - AWDATA_RX(rx_pkts_all); - AWDATA_RX(rx_bytes_all); - - AWDATA(tx_pkts_all); - AWDATA(tx_bytes_all); - AWDATA(queued); - AWDATA(completed); - AWDATA(xretries); - AWDATA(a_aggr); - AWDATA(a_queued_hw); - AWDATA(a_queued_sw); - AWDATA(a_completed); - AWDATA(a_retries); - AWDATA(a_xretries); - AWDATA(fifo_underrun); - AWDATA(xtxop); - AWDATA(timer_exp); - AWDATA(desc_cfg_err); - AWDATA(data_underrun); - AWDATA(delim_underrun); - - AWDATA_RX(decrypt_crc_err); - AWDATA_RX(phy_err); - AWDATA_RX(mic_err); - AWDATA_RX(pre_delim_crc_err); - AWDATA_RX(post_delim_crc_err); - AWDATA_RX(decrypt_busy_err); - - AWDATA_RX(phy_err_stats[ATH9K_PHYERR_RADAR]); - AWDATA_RX(phy_err_stats[ATH9K_PHYERR_OFDM_TIMING]); - AWDATA_RX(phy_err_stats[ATH9K_PHYERR_CCK_TIMING]); - - WARN_ON(i != ATH9K_SSTATS_LEN); -} - int ath9k_init_debug(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); @@ -1741,16 +1638,16 @@ int ath9k_init_debug(struct ath_hw *ah) &fops_interrupt); debugfs_create_file("xmit", S_IRUSR, sc->debug.debugfs_phy, sc, &fops_xmit); - debugfs_create_file("queues", S_IRUSR, sc->debug.debugfs_phy, sc, - &fops_queues); debugfs_create_u32("qlen_bk", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, - &sc->tx.txq_max_pending[IEEE80211_AC_BK]); + &sc->tx.txq_max_pending[WME_AC_BK]); debugfs_create_u32("qlen_be", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, - &sc->tx.txq_max_pending[IEEE80211_AC_BE]); + &sc->tx.txq_max_pending[WME_AC_BE]); debugfs_create_u32("qlen_vi", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, - &sc->tx.txq_max_pending[IEEE80211_AC_VI]); + &sc->tx.txq_max_pending[WME_AC_VI]); debugfs_create_u32("qlen_vo", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, - &sc->tx.txq_max_pending[IEEE80211_AC_VO]); + &sc->tx.txq_max_pending[WME_AC_VO]); + debugfs_create_file("stations", S_IRUSR, sc->debug.debugfs_phy, sc, + &fops_stations); debugfs_create_file("misc", S_IRUSR, sc->debug.debugfs_phy, sc, &fops_misc); debugfs_create_file("reset", S_IRUSR, sc->debug.debugfs_phy, sc, diff --git a/trunk/drivers/net/wireless/ath/ath9k/debug.h b/trunk/drivers/net/wireless/ath/ath9k/debug.h index 72d4893311b1..2ed9785a38fa 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/debug.h +++ b/trunk/drivers/net/wireless/ath/ath9k/debug.h @@ -41,7 +41,6 @@ enum ath_reset_type { RESET_TYPE_PLL_HANG, RESET_TYPE_MAC_HANG, RESET_TYPE_BEACON_STUCK, - RESET_TYPE_MCI, __RESET_TYPE_MAX }; @@ -179,21 +178,6 @@ struct ath_tx_stats { u32 txfailed; }; -/* - * Various utility macros to print TX/Queue counters. - */ -#define PR_QNUM(_n) sc->tx.txq_map[_n]->axq_qnum -#define TXSTATS sc->debug.stats.txstats -#define PR(str, elem) \ - do { \ - len += snprintf(buf + len, size - len, \ - "%s%13u%11u%10u%10u\n", str, \ - TXSTATS[PR_QNUM(IEEE80211_AC_BE)].elem, \ - TXSTATS[PR_QNUM(IEEE80211_AC_BK)].elem, \ - TXSTATS[PR_QNUM(IEEE80211_AC_VI)].elem, \ - TXSTATS[PR_QNUM(IEEE80211_AC_VO)].elem); \ - } while(0) - #define RX_STAT_INC(c) (sc->debug.stats.rxstats.c++) /** @@ -242,7 +226,7 @@ struct ath_rx_stats { struct ath_stats { struct ath_interrupt_stats istats; - struct ath_tx_stats txstats[IEEE80211_NUM_ACS]; + struct ath_tx_stats txstats[ATH9K_NUM_TX_QUEUES]; struct ath_rx_stats rxstats; struct ath_dfs_stats dfs_stats; u32 reset[__RESET_TYPE_MAX]; @@ -307,22 +291,7 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, struct ath_tx_status *ts, struct ath_txq *txq, unsigned int flags); void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs); -int ath9k_get_et_sset_count(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, int sset); -void ath9k_get_et_stats(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ethtool_stats *stats, u64 *data); -void ath9k_get_et_strings(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - u32 sset, u8 *data); -void ath9k_sta_add_debugfs(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct dentry *dir); -void ath9k_sta_remove_debugfs(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct dentry *dir); + #else #define RX_STAT_INC(c) /* NOP */ diff --git a/trunk/drivers/net/wireless/ath/ath9k/gpio.c b/trunk/drivers/net/wireless/ath/ath9k/gpio.c index 4b412aaf4f36..a8ea57b9f49c 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/gpio.c +++ b/trunk/drivers/net/wireless/ath/ath9k/gpio.c @@ -247,9 +247,6 @@ static void ath_btcoex_period_timer(unsigned long data) stomp_type = ATH_BTCOEX_STOMP_ALL; timer_period = btcoex->btscan_no_stomp; } - } else if (btcoex->stomp_audio >= 5) { - stomp_type = ATH_BTCOEX_STOMP_AUDIO; - btcoex->stomp_audio = 0; } ath9k_hw_btcoex_bt_stomp(ah, stomp_type); @@ -298,7 +295,7 @@ static void ath_btcoex_no_stomp_timer(void *arg) (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI) && test_bit(BT_OP_SCAN, &btcoex->op_flags))) ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE); - else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) + else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_LOW); ath9k_hw_btcoex_enable(ah); @@ -474,7 +471,7 @@ int ath9k_init_btcoex(struct ath_softc *sc) r = ath_init_btcoex_timer(sc); if (r) return -1; - txq = sc->tx.txq_map[IEEE80211_AC_BE]; + txq = sc->tx.txq_map[WME_AC_BE]; ath9k_hw_init_btcoex_hw(sc->sc_ah, txq->axq_qnum); sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW; if (ath9k_hw_mci_is_enabled(ah)) { @@ -497,31 +494,35 @@ int ath9k_init_btcoex(struct ath_softc *sc) return 0; } -static int ath9k_dump_mci_btcoex(struct ath_softc *sc, u8 *buf, u32 size) +int ath9k_dump_btcoex(struct ath_softc *sc, u8 *buf, u32 len, u32 size) { +#define ATH_DUMP_BTCOEX(_s, _val) \ + do { \ + len += snprintf(buf + len, size - len, \ + "%20s : %10d\n", _s, (_val)); \ + } while (0) + struct ath_btcoex *btcoex = &sc->btcoex; struct ath_mci_profile *mci = &btcoex->mci; struct ath_hw *ah = sc->sc_ah; struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; - u32 len = 0; int i; ATH_DUMP_BTCOEX("Total BT profiles", NUM_PROF(mci)); - ATH_DUMP_BTCOEX("MGMT", mci->num_mgmt); - ATH_DUMP_BTCOEX("SCO", mci->num_sco); - ATH_DUMP_BTCOEX("A2DP", mci->num_a2dp); - ATH_DUMP_BTCOEX("HID", mci->num_hid); - ATH_DUMP_BTCOEX("PAN", mci->num_pan); - ATH_DUMP_BTCOEX("ACL", mci->num_other_acl); - ATH_DUMP_BTCOEX("BDR", mci->num_bdr); + ATH_DUMP_BTCOEX("Number of MGMT", mci->num_mgmt); + ATH_DUMP_BTCOEX("Number of SCO", mci->num_sco); + ATH_DUMP_BTCOEX("Number of A2DP", mci->num_a2dp); + ATH_DUMP_BTCOEX("Number of HID", mci->num_hid); + ATH_DUMP_BTCOEX("Number of PAN", mci->num_pan); + ATH_DUMP_BTCOEX("Number of ACL", mci->num_other_acl); + ATH_DUMP_BTCOEX("Number of BDR", mci->num_bdr); ATH_DUMP_BTCOEX("Aggr. Limit", mci->aggr_limit); ATH_DUMP_BTCOEX("Stomp Type", btcoex->bt_stomp_type); ATH_DUMP_BTCOEX("BTCoex Period (msec)", btcoex->btcoex_period); ATH_DUMP_BTCOEX("Duty Cycle", btcoex->duty_cycle); ATH_DUMP_BTCOEX("BT Wait time", btcoex->bt_wait_time); ATH_DUMP_BTCOEX("Concurrent Tx", btcoex_hw->mci.concur_tx); - ATH_DUMP_BTCOEX("Concurrent RSSI cnt", btcoex->rssi_count); - + ATH_DUMP_BTCOEX("Concur RSSI count", btcoex->rssi_count); len += snprintf(buf + len, size - len, "BT Weights: "); for (i = 0; i < AR9300_NUM_BT_WEIGHTS; i++) len += snprintf(buf + len, size - len, "%08x ", @@ -536,32 +537,9 @@ static int ath9k_dump_mci_btcoex(struct ath_softc *sc, u8 *buf, u32 size) for (i = 0; i < ATH_BTCOEX_STOMP_MAX; i++) len += snprintf(buf + len, size - len, "%08x ", btcoex_hw->tx_prio[i]); - len += snprintf(buf + len, size - len, "\n"); +#undef ATH_DUMP_BTCOEX return len; } - -static int ath9k_dump_legacy_btcoex(struct ath_softc *sc, u8 *buf, u32 size) -{ - - struct ath_btcoex *btcoex = &sc->btcoex; - u32 len = 0; - - ATH_DUMP_BTCOEX("Stomp Type", btcoex->bt_stomp_type); - ATH_DUMP_BTCOEX("BTCoex Period (msec)", btcoex->btcoex_period); - ATH_DUMP_BTCOEX("Duty Cycle", btcoex->duty_cycle); - ATH_DUMP_BTCOEX("BT Wait time", btcoex->bt_wait_time); - - return len; -} - -int ath9k_dump_btcoex(struct ath_softc *sc, u8 *buf, u32 size) -{ - if (ath9k_hw_mci_is_enabled(sc->sc_ah)) - return ath9k_dump_mci_btcoex(sc, buf, size); - else - return ath9k_dump_legacy_btcoex(sc, buf, size); -} - #endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */ diff --git a/trunk/drivers/net/wireless/ath/ath9k/htc.h b/trunk/drivers/net/wireless/ath/ath9k/htc.h index 96bfb18078fa..b30596fcf73a 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/htc.h +++ b/trunk/drivers/net/wireless/ath/ath9k/htc.h @@ -331,7 +331,7 @@ struct ath_tx_stats { u32 skb_success; u32 skb_failed; u32 cab_queued; - u32 queue_stats[IEEE80211_NUM_ACS]; + u32 queue_stats[WME_NUM_AC]; }; struct ath_rx_stats { @@ -493,7 +493,7 @@ struct ath9k_htc_priv { int beaconq; int cabq; - int hwq_map[IEEE80211_NUM_ACS]; + int hwq_map[WME_NUM_AC]; #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT struct ath_btcoex btcoex; diff --git a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c index d0ce1f5bba10..1318d79f5c44 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c @@ -33,7 +33,7 @@ void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv) qi.tqi_cwmin = 0; qi.tqi_cwmax = 0; } else if (priv->ah->opmode == NL80211_IFTYPE_ADHOC) { - int qnum = priv->hwq_map[IEEE80211_AC_BE]; + int qnum = priv->hwq_map[WME_AC_BE]; ath9k_hw_get_txq_props(ah, qnum, &qi_be); diff --git a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_debug.c index 87110de577ef..3035deb7a0cd 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_debug.c +++ b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_debug.c @@ -218,16 +218,16 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf, len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", "BE queued", - priv->debug.tx_stats.queue_stats[IEEE80211_AC_BE]); + priv->debug.tx_stats.queue_stats[WME_AC_BE]); len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", "BK queued", - priv->debug.tx_stats.queue_stats[IEEE80211_AC_BK]); + priv->debug.tx_stats.queue_stats[WME_AC_BK]); len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", "VI queued", - priv->debug.tx_stats.queue_stats[IEEE80211_AC_VI]); + priv->debug.tx_stats.queue_stats[WME_AC_VI]); len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", "VO queued", - priv->debug.tx_stats.queue_stats[IEEE80211_AC_VO]); + priv->debug.tx_stats.queue_stats[WME_AC_VO]); if (len > sizeof(buf)) len = sizeof(buf); 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 105582d6b714..0eacfc13c915 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c +++ b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c @@ -207,7 +207,7 @@ void ath9k_htc_init_btcoex(struct ath9k_htc_priv *priv, char *product) priv->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW; ath9k_hw_btcoex_init_3wire(priv->ah); ath_htc_init_btcoex_work(priv); - qnum = priv->hwq_map[IEEE80211_AC_BE]; + qnum = priv->hwq_map[WME_AC_BE]; ath9k_hw_init_btcoex_hw(priv->ah, qnum); break; default: diff --git a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 05d5ba66cac3..5ecf1287dddd 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -549,20 +549,20 @@ static int ath9k_init_queues(struct ath9k_htc_priv *priv) goto err; } - if (!ath9k_htc_txq_setup(priv, IEEE80211_AC_BE)) { + if (!ath9k_htc_txq_setup(priv, WME_AC_BE)) { ath_err(common, "Unable to setup xmit queue for BE traffic\n"); goto err; } - if (!ath9k_htc_txq_setup(priv, IEEE80211_AC_BK)) { + if (!ath9k_htc_txq_setup(priv, WME_AC_BK)) { ath_err(common, "Unable to setup xmit queue for BK traffic\n"); goto err; } - if (!ath9k_htc_txq_setup(priv, IEEE80211_AC_VI)) { + if (!ath9k_htc_txq_setup(priv, WME_AC_VI)) { ath_err(common, "Unable to setup xmit queue for VI traffic\n"); goto err; } - if (!ath9k_htc_txq_setup(priv, IEEE80211_AC_VO)) { + if (!ath9k_htc_txq_setup(priv, WME_AC_VO)) { ath_err(common, "Unable to setup xmit queue for VO traffic\n"); goto err; } 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 9c07a8fa5134..02cce95331d8 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1349,7 +1349,7 @@ static int ath9k_htc_conf_tx(struct ieee80211_hw *hw, struct ath9k_tx_queue_info qi; int ret = 0, qnum; - if (queue >= IEEE80211_NUM_ACS) + if (queue >= WME_NUM_AC) return 0; mutex_lock(&priv->mutex); @@ -1376,7 +1376,7 @@ static int ath9k_htc_conf_tx(struct ieee80211_hw *hw, } if ((priv->ah->opmode == NL80211_IFTYPE_ADHOC) && - (qnum == priv->hwq_map[IEEE80211_AC_BE])) + (qnum == priv->hwq_map[WME_AC_BE])) ath9k_htc_beaconq_config(priv); out: ath9k_htc_ps_restore(priv); diff --git a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 28cd50ee521a..06cdcb772d78 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -21,10 +21,10 @@ /******/ static const int subtype_txq_to_hwq[] = { - [IEEE80211_AC_BE] = ATH_TXQ_AC_BE, - [IEEE80211_AC_BK] = ATH_TXQ_AC_BK, - [IEEE80211_AC_VI] = ATH_TXQ_AC_VI, - [IEEE80211_AC_VO] = ATH_TXQ_AC_VO, + [WME_AC_BE] = ATH_TXQ_AC_BE, + [WME_AC_BK] = ATH_TXQ_AC_BK, + [WME_AC_VI] = ATH_TXQ_AC_VI, + [WME_AC_VO] = ATH_TXQ_AC_VO, }; #define ATH9K_HTC_INIT_TXQ(subtype) do { \ @@ -41,15 +41,15 @@ int get_hw_qnum(u16 queue, int *hwq_map) { switch (queue) { case 0: - return hwq_map[IEEE80211_AC_VO]; + return hwq_map[WME_AC_VO]; case 1: - return hwq_map[IEEE80211_AC_VI]; + return hwq_map[WME_AC_VI]; case 2: - return hwq_map[IEEE80211_AC_BE]; + return hwq_map[WME_AC_BE]; case 3: - return hwq_map[IEEE80211_AC_BK]; + return hwq_map[WME_AC_BK]; default: - return hwq_map[IEEE80211_AC_BE]; + return hwq_map[WME_AC_BE]; } } @@ -106,20 +106,20 @@ static inline enum htc_endpoint_id get_htc_epid(struct ath9k_htc_priv *priv, switch (qnum) { case 0: - TX_QSTAT_INC(IEEE80211_AC_VO); + TX_QSTAT_INC(WME_AC_VO); epid = priv->data_vo_ep; break; case 1: - TX_QSTAT_INC(IEEE80211_AC_VI); + TX_QSTAT_INC(WME_AC_VI); epid = priv->data_vi_ep; break; case 2: - TX_QSTAT_INC(IEEE80211_AC_BE); + TX_QSTAT_INC(WME_AC_BE); epid = priv->data_be_ep; break; case 3: default: - TX_QSTAT_INC(IEEE80211_AC_BK); + TX_QSTAT_INC(WME_AC_BK); epid = priv->data_bk_ep; break; } @@ -1082,7 +1082,7 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv, rx_status->freq = hw->conf.channel->center_freq; rx_status->signal = rxbuf->rxstatus.rs_rssi + ATH_DEFAULT_NOISE_FLOOR; rx_status->antenna = rxbuf->rxstatus.rs_antenna; - rx_status->flag |= RX_FLAG_MACTIME_START; + rx_status->flag |= RX_FLAG_MACTIME_MPDU; return true; diff --git a/trunk/drivers/net/wireless/ath/ath9k/hw.c b/trunk/drivers/net/wireless/ath/ath9k/hw.c index e06bcec655a7..756191b9eeda 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/hw.c +++ b/trunk/drivers/net/wireless/ath/ath9k/hw.c @@ -1456,7 +1456,7 @@ static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type) switch (type) { case ATH9K_RESET_POWER_ON: ret = ath9k_hw_set_reset_power_on(ah); - if (ret) + if (!ret) ah->reset_power_on = true; break; case ATH9K_RESET_WARM: diff --git a/trunk/drivers/net/wireless/ath/ath9k/init.c b/trunk/drivers/net/wireless/ath/ath9k/init.c index 80cae53a33e5..546bae93647b 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/init.c +++ b/trunk/drivers/net/wireless/ath/ath9k/init.c @@ -435,7 +435,7 @@ static int ath9k_init_queues(struct ath_softc *sc) sc->config.cabqReadytime = ATH_CABQ_READY_TIME; ath_cabq_update(sc); - for (i = 0; i < IEEE80211_NUM_ACS; i++) { + for (i = 0; i < WME_NUM_AC; i++) { sc->tx.txq_map[i] = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, i); sc->tx.txq_map[i]->mac80211_qnum = i; sc->tx.txq_max_pending[i] = ATH_MAX_QDEPTH; @@ -563,6 +563,10 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, spin_lock_init(&sc->sc_serial_rw); spin_lock_init(&sc->sc_pm_lock); mutex_init(&sc->mutex); +#ifdef CONFIG_ATH9K_DEBUGFS + spin_lock_init(&sc->nodes_lock); + INIT_LIST_HEAD(&sc->nodes); +#endif #ifdef CONFIG_ATH9K_MAC_DEBUG spin_lock_init(&sc->debug.samp_lock); #endif diff --git a/trunk/drivers/net/wireless/ath/ath9k/link.c b/trunk/drivers/net/wireless/ath/ath9k/link.c index fc6b075ad635..223b9693527e 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/link.c +++ b/trunk/drivers/net/wireless/ath/ath9k/link.c @@ -27,6 +27,9 @@ void ath_tx_complete_poll_work(struct work_struct *work) struct ath_txq *txq; int i; bool needreset = false; +#ifdef CONFIG_ATH9K_DEBUGFS + sc->tx_complete_poll_work_seen++; +#endif for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) if (ATH_TXQ_SETUP(sc, i)) { @@ -208,7 +211,7 @@ static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int int time_left; memset(&txctl, 0, sizeof(txctl)); - txctl.txq = sc->tx.txq_map[IEEE80211_AC_BE]; + txctl.txq = sc->tx.txq_map[WME_AC_BE]; memset(tx_info, 0, sizeof(*tx_info)); tx_info->band = hw->conf.channel->band; diff --git a/trunk/drivers/net/wireless/ath/ath9k/main.c b/trunk/drivers/net/wireless/ath/ath9k/main.c index be30a9af1528..9594b6fcdf06 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/main.c +++ b/trunk/drivers/net/wireless/ath/ath9k/main.c @@ -331,7 +331,11 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta, u8 density; an = (struct ath_node *)sta->drv_priv; - an->sc = sc; +#ifdef CONFIG_ATH9K_DEBUGFS + spin_lock(&sc->nodes_lock); + list_add(&an->list, &sc->nodes); + spin_unlock(&sc->nodes_lock); +#endif an->sta = sta; an->vif = vif; @@ -348,6 +352,13 @@ static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta) { struct ath_node *an = (struct ath_node *)sta->drv_priv; +#ifdef CONFIG_ATH9K_DEBUGFS + spin_lock(&sc->nodes_lock); + list_del(&an->list); + spin_unlock(&sc->nodes_lock); + an->sta = NULL; +#endif + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) ath_tx_node_cleanup(sc, an); } @@ -483,6 +494,17 @@ irqreturn_t ath_isr(int irq, void *dev) if (status & SCHED_INTR) sched = true; +#ifdef CONFIG_PM_SLEEP + if (status & ATH9K_INT_BMISS) { + if (atomic_read(&sc->wow_sleep_proc_intr) == 0) { + ath_dbg(common, ANY, "during WoW we got a BMISS\n"); + atomic_inc(&sc->wow_got_bmiss_intr); + atomic_dec(&sc->wow_sleep_proc_intr); + } + ath_dbg(common, INTERRUPT, "beacon miss interrupt\n"); + } +#endif + /* * If a FATAL or RXORN interrupt is received, we have to reset the * chip immediately. @@ -501,15 +523,7 @@ irqreturn_t ath_isr(int irq, void *dev) goto chip_reset; } -#ifdef CONFIG_PM_SLEEP - if (status & ATH9K_INT_BMISS) { - if (atomic_read(&sc->wow_sleep_proc_intr) == 0) { - ath_dbg(common, ANY, "during WoW we got a BMISS\n"); - atomic_inc(&sc->wow_got_bmiss_intr); - atomic_dec(&sc->wow_sleep_proc_intr); - } - } -#endif + if (status & ATH9K_INT_SWBA) tasklet_schedule(&sc->bcon_tasklet); @@ -1314,7 +1328,7 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw, struct ath9k_tx_queue_info qi; int ret = 0; - if (queue >= IEEE80211_NUM_ACS) + if (queue >= WME_NUM_AC) return 0; txq = sc->tx.txq_map[queue]; @@ -1883,6 +1897,134 @@ static int ath9k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant) return 0; } +#ifdef CONFIG_ATH9K_DEBUGFS + +/* Ethtool support for get-stats */ + +#define AMKSTR(nm) #nm "_BE", #nm "_BK", #nm "_VI", #nm "_VO" +static const char ath9k_gstrings_stats[][ETH_GSTRING_LEN] = { + "tx_pkts_nic", + "tx_bytes_nic", + "rx_pkts_nic", + "rx_bytes_nic", + AMKSTR(d_tx_pkts), + AMKSTR(d_tx_bytes), + AMKSTR(d_tx_mpdus_queued), + AMKSTR(d_tx_mpdus_completed), + AMKSTR(d_tx_mpdu_xretries), + AMKSTR(d_tx_aggregates), + AMKSTR(d_tx_ampdus_queued_hw), + AMKSTR(d_tx_ampdus_queued_sw), + AMKSTR(d_tx_ampdus_completed), + AMKSTR(d_tx_ampdu_retries), + AMKSTR(d_tx_ampdu_xretries), + AMKSTR(d_tx_fifo_underrun), + AMKSTR(d_tx_op_exceeded), + AMKSTR(d_tx_timer_expiry), + AMKSTR(d_tx_desc_cfg_err), + AMKSTR(d_tx_data_underrun), + AMKSTR(d_tx_delim_underrun), + + "d_rx_decrypt_crc_err", + "d_rx_phy_err", + "d_rx_mic_err", + "d_rx_pre_delim_crc_err", + "d_rx_post_delim_crc_err", + "d_rx_decrypt_busy_err", + + "d_rx_phyerr_radar", + "d_rx_phyerr_ofdm_timing", + "d_rx_phyerr_cck_timing", + +}; +#define ATH9K_SSTATS_LEN ARRAY_SIZE(ath9k_gstrings_stats) + +static void ath9k_get_et_strings(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + u32 sset, u8 *data) +{ + if (sset == ETH_SS_STATS) + memcpy(data, *ath9k_gstrings_stats, + sizeof(ath9k_gstrings_stats)); +} + +static int ath9k_get_et_sset_count(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, int sset) +{ + if (sset == ETH_SS_STATS) + return ATH9K_SSTATS_LEN; + return 0; +} + +#define PR_QNUM(_n) (sc->tx.txq_map[_n]->axq_qnum) +#define AWDATA(elem) \ + do { \ + data[i++] = sc->debug.stats.txstats[PR_QNUM(WME_AC_BE)].elem; \ + data[i++] = sc->debug.stats.txstats[PR_QNUM(WME_AC_BK)].elem; \ + data[i++] = sc->debug.stats.txstats[PR_QNUM(WME_AC_VI)].elem; \ + data[i++] = sc->debug.stats.txstats[PR_QNUM(WME_AC_VO)].elem; \ + } while (0) + +#define AWDATA_RX(elem) \ + do { \ + data[i++] = sc->debug.stats.rxstats.elem; \ + } while (0) + +static void ath9k_get_et_stats(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ethtool_stats *stats, u64 *data) +{ + struct ath_softc *sc = hw->priv; + int i = 0; + + data[i++] = (sc->debug.stats.txstats[PR_QNUM(WME_AC_BE)].tx_pkts_all + + sc->debug.stats.txstats[PR_QNUM(WME_AC_BK)].tx_pkts_all + + sc->debug.stats.txstats[PR_QNUM(WME_AC_VI)].tx_pkts_all + + sc->debug.stats.txstats[PR_QNUM(WME_AC_VO)].tx_pkts_all); + data[i++] = (sc->debug.stats.txstats[PR_QNUM(WME_AC_BE)].tx_bytes_all + + sc->debug.stats.txstats[PR_QNUM(WME_AC_BK)].tx_bytes_all + + sc->debug.stats.txstats[PR_QNUM(WME_AC_VI)].tx_bytes_all + + sc->debug.stats.txstats[PR_QNUM(WME_AC_VO)].tx_bytes_all); + AWDATA_RX(rx_pkts_all); + AWDATA_RX(rx_bytes_all); + + AWDATA(tx_pkts_all); + AWDATA(tx_bytes_all); + AWDATA(queued); + AWDATA(completed); + AWDATA(xretries); + AWDATA(a_aggr); + AWDATA(a_queued_hw); + AWDATA(a_queued_sw); + AWDATA(a_completed); + AWDATA(a_retries); + AWDATA(a_xretries); + AWDATA(fifo_underrun); + AWDATA(xtxop); + AWDATA(timer_exp); + AWDATA(desc_cfg_err); + AWDATA(data_underrun); + AWDATA(delim_underrun); + + AWDATA_RX(decrypt_crc_err); + AWDATA_RX(phy_err); + AWDATA_RX(mic_err); + AWDATA_RX(pre_delim_crc_err); + AWDATA_RX(post_delim_crc_err); + AWDATA_RX(decrypt_busy_err); + + AWDATA_RX(phy_err_stats[ATH9K_PHYERR_RADAR]); + AWDATA_RX(phy_err_stats[ATH9K_PHYERR_OFDM_TIMING]); + AWDATA_RX(phy_err_stats[ATH9K_PHYERR_CCK_TIMING]); + + WARN_ON(i != ATH9K_SSTATS_LEN); +} + +/* End of ethtool get-stats functions */ + +#endif + + #ifdef CONFIG_PM_SLEEP static void ath9k_wow_map_triggers(struct ath_softc *sc, @@ -2276,12 +2418,7 @@ struct ieee80211_ops ath9k_ops = { #ifdef CONFIG_ATH9K_DEBUGFS .get_et_sset_count = ath9k_get_et_sset_count, - .get_et_stats = ath9k_get_et_stats, - .get_et_strings = ath9k_get_et_strings, -#endif - -#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS) - .sta_add_debugfs = ath9k_sta_add_debugfs, - .sta_remove_debugfs = ath9k_sta_remove_debugfs, + .get_et_stats = ath9k_get_et_stats, + .get_et_strings = ath9k_get_et_strings, #endif }; diff --git a/trunk/drivers/net/wireless/ath/ath9k/mci.c b/trunk/drivers/net/wireless/ath/ath9k/mci.c index 5c02702f21e7..0dd2cbb52d65 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/mci.c +++ b/trunk/drivers/net/wireless/ath/ath9k/mci.c @@ -207,6 +207,23 @@ static void ath_mci_update_scheme(struct ath_softc *sc) ath9k_btcoex_timer_resume(sc); } +static void ath_mci_wait_btcal_done(struct ath_softc *sc) +{ + struct ath_hw *ah = sc->sc_ah; + + /* Stop tx & rx */ + ieee80211_stop_queues(sc->hw); + ath_stoprecv(sc); + ath_drain_all_txq(sc, false); + + /* Wait for cal done */ + ar9003_mci_start_reset(ah, ah->curchan); + + /* Resume tx & rx */ + ath_startrecv(sc); + ieee80211_wake_queues(sc->hw); +} + static void ath_mci_cal_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload) { struct ath_hw *ah = sc->sc_ah; @@ -218,7 +235,7 @@ static void ath_mci_cal_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload) case MCI_GPM_BT_CAL_REQ: if (mci_hw->bt_state == MCI_BT_AWAKE) { mci_hw->bt_state = MCI_BT_CAL_START; - ath9k_queue_reset(sc, RESET_TYPE_MCI); + ath_mci_wait_btcal_done(sc); } ath_dbg(common, MCI, "MCI State : %d\n", mci_hw->bt_state); break; @@ -257,9 +274,8 @@ static void ath_mci_set_concur_txprio(struct ath_softc *sc) { struct ath_btcoex *btcoex = &sc->btcoex; struct ath_mci_profile *mci = &btcoex->mci; - u8 stomp_txprio[ATH_BTCOEX_STOMP_MAX]; + u8 stomp_txprio[] = { 0, 0, 0, 0 }; /* all, low, none, low_ftp */ - memset(stomp_txprio, 0, sizeof(stomp_txprio)); if (mci->num_mgmt) { stomp_txprio[ATH_BTCOEX_STOMP_ALL] = ATH_MCI_INQUIRY_PRIO; if (!mci->num_pan && !mci->num_other_acl) @@ -562,8 +578,6 @@ void ath_mci_intr(struct ath_softc *sc) mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_GPM; while (more_data == MCI_GPM_MORE) { - if (test_bit(SC_OP_HW_RESET, &sc->sc_flags)) - return; pgpm = mci->gpm_buf.bf_addr; offset = ar9003_mci_get_next_gpm_offset(ah, false, @@ -730,30 +744,12 @@ void ath9k_mci_set_txpower(struct ath_softc *sc, bool setchannel, ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit, false); } -static void ath9k_mci_stomp_audio(struct ath_softc *sc) -{ - struct ath_hw *ah = sc->sc_ah; - struct ath_btcoex *btcoex = &sc->btcoex; - struct ath_mci_profile *mci = &btcoex->mci; - - if (!mci->num_sco && !mci->num_a2dp) - return; - - if (ah->stats.avgbrssi > 25) { - btcoex->stomp_audio = 0; - return; - } - - btcoex->stomp_audio++; -} void ath9k_mci_update_rssi(struct ath_softc *sc) { struct ath_hw *ah = sc->sc_ah; struct ath_btcoex *btcoex = &sc->btcoex; struct ath9k_hw_mci *mci_hw = &sc->sc_ah->btcoex_hw.mci; - ath9k_mci_stomp_audio(sc); - if (!(mci_hw->config & ATH_MCI_CONFIG_CONCUR_TX)) return; diff --git a/trunk/drivers/net/wireless/ath/ath9k/pci.c b/trunk/drivers/net/wireless/ath/ath9k/pci.c index 8e9b826f878b..9553203ee624 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/pci.c +++ b/trunk/drivers/net/wireless/ath/ath9k/pci.c @@ -287,7 +287,7 @@ static void ath_pci_remove(struct pci_dev *pdev) pci_release_region(pdev, 0); } -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_PM static int ath_pci_suspend(struct device *device) { @@ -333,15 +333,22 @@ static int ath_pci_resume(struct device *device) return 0; } -static SIMPLE_DEV_PM_OPS(ath9k_pm_ops, ath_pci_suspend, ath_pci_resume); +static const struct dev_pm_ops ath9k_pm_ops = { + .suspend = ath_pci_suspend, + .resume = ath_pci_resume, + .freeze = ath_pci_suspend, + .thaw = ath_pci_resume, + .poweroff = ath_pci_suspend, + .restore = ath_pci_resume, +}; #define ATH9K_PM_OPS (&ath9k_pm_ops) -#else /* !CONFIG_PM_SLEEP */ +#else /* !CONFIG_PM */ #define ATH9K_PM_OPS NULL -#endif /* !CONFIG_PM_SLEEP */ +#endif /* !CONFIG_PM */ MODULE_DEVICE_TABLE(pci, ath_pci_id_table); diff --git a/trunk/drivers/net/wireless/ath/ath9k/rc.c b/trunk/drivers/net/wireless/ath/ath9k/rc.c index 714558d1ba78..27ed80b54881 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/rc.c +++ b/trunk/drivers/net/wireless/ath/ath9k/rc.c @@ -982,6 +982,16 @@ static void ath_rc_update_per(struct ath_softc *sc, } } +static void ath_debug_stat_retries(struct ath_rate_priv *rc, int rix, + int xretries, int retries, u8 per) +{ + struct ath_rc_stats *stats = &rc->rcstats[rix]; + + stats->xretries += xretries; + stats->retries += retries; + stats->per = per; +} + static void ath_rc_update_ht(struct ath_softc *sc, struct ath_rate_priv *ath_rc_priv, struct ieee80211_tx_info *tx_info, @@ -1055,6 +1065,14 @@ static void ath_rc_update_ht(struct ath_softc *sc, } +static void ath_debug_stat_rc(struct ath_rate_priv *rc, int final_rate) +{ + struct ath_rc_stats *stats; + + stats = &rc->rcstats[final_rate]; + stats->success++; +} + static void ath_rc_tx_status(struct ath_softc *sc, struct ath_rate_priv *ath_rc_priv, struct sk_buff *skb) @@ -1332,25 +1350,7 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, } } -#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS) - -void ath_debug_stat_rc(struct ath_rate_priv *rc, int final_rate) -{ - struct ath_rc_stats *stats; - - stats = &rc->rcstats[final_rate]; - stats->success++; -} - -void ath_debug_stat_retries(struct ath_rate_priv *rc, int rix, - int xretries, int retries, u8 per) -{ - struct ath_rc_stats *stats = &rc->rcstats[rix]; - - stats->xretries += xretries; - stats->retries += retries; - stats->per = per; -} +#ifdef CONFIG_ATH9K_DEBUGFS static ssize_t read_file_rcstat(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) @@ -1428,17 +1428,10 @@ static void ath_rate_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir) { struct ath_rate_priv *rc = priv_sta; - rc->debugfs_rcstats = debugfs_create_file("rc_stats", S_IRUGO, - dir, rc, &fops_rcstat); -} - -static void ath_rate_remove_sta_debugfs(void *priv, void *priv_sta) -{ - struct ath_rate_priv *rc = priv_sta; - debugfs_remove(rc->debugfs_rcstats); + debugfs_create_file("rc_stats", S_IRUGO, dir, rc, &fops_rcstat); } -#endif /* CONFIG_MAC80211_DEBUGFS && CONFIG_ATH9K_DEBUGFS */ +#endif /* CONFIG_ATH9K_DEBUGFS */ static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) { @@ -1483,10 +1476,8 @@ static struct rate_control_ops ath_rate_ops = { .free = ath_rate_free, .alloc_sta = ath_rate_alloc_sta, .free_sta = ath_rate_free_sta, - -#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS) +#ifdef CONFIG_ATH9K_DEBUGFS .add_sta_debugfs = ath_rate_add_sta_debugfs, - .remove_sta_debugfs = ath_rate_remove_sta_debugfs, #endif }; diff --git a/trunk/drivers/net/wireless/ath/ath9k/rc.h b/trunk/drivers/net/wireless/ath/ath9k/rc.h index 267dbfcfaa96..268e67dc5fb2 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/rc.h +++ b/trunk/drivers/net/wireless/ath/ath9k/rc.h @@ -211,26 +211,10 @@ struct ath_rate_priv { struct ath_rateset neg_ht_rates; const struct ath_rate_table *rate_table; -#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS) struct dentry *debugfs_rcstats; struct ath_rc_stats rcstats[RATE_TABLE_SIZE]; -#endif }; -#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS) -void ath_debug_stat_rc(struct ath_rate_priv *rc, int final_rate); -void ath_debug_stat_retries(struct ath_rate_priv *rc, int rix, - int xretries, int retries, u8 per); -#else -static inline void ath_debug_stat_rc(struct ath_rate_priv *rc, int final_rate) -{ -} -static inline void ath_debug_stat_retries(struct ath_rate_priv *rc, int rix, - int xretries, int retries, u8 per) -{ -} -#endif - #ifdef CONFIG_ATH9K_RATE_CONTROL int ath_rate_control_register(void); void ath_rate_control_unregister(void); diff --git a/trunk/drivers/net/wireless/ath/ath9k/recv.c b/trunk/drivers/net/wireless/ath/ath9k/recv.c index 6aafbb77c498..a04028bce28b 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/recv.c +++ b/trunk/drivers/net/wireless/ath/ath9k/recv.c @@ -976,7 +976,7 @@ static int ath9k_rx_skb_preprocess(struct ath_common *common, rx_status->freq = hw->conf.channel->center_freq; rx_status->signal = ah->noise + rx_stats->rs_rssi; rx_status->antenna = rx_stats->rs_antenna; - rx_status->flag |= RX_FLAG_MACTIME_START; + rx_status->flag |= RX_FLAG_MACTIME_MPDU; if (rx_stats->rs_moreaggr) rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL; diff --git a/trunk/drivers/net/wireless/ath/ath9k/xmit.c b/trunk/drivers/net/wireless/ath/ath9k/xmit.c index 90e48a0fafe5..1ffca7511fa8 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/xmit.c +++ b/trunk/drivers/net/wireless/ath/ath9k/xmit.c @@ -312,6 +312,7 @@ static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc) } bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list); + bf->bf_next = NULL; list_del(&bf->list); spin_unlock_bh(&sc->tx.txbuflock); @@ -393,7 +394,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0, seq_first; u32 ba[WME_BA_BMP_SIZE >> 5]; int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0; - bool rc_update = true, isba; + bool rc_update = true; struct ieee80211_tx_rate rates[4]; struct ath_frame_info *fi; int nframes; @@ -437,17 +438,13 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK; tid = ATH_AN_2_TID(an, tidno); seq_first = tid->seq_start; - isba = ts->ts_flags & ATH9K_TX_BA; /* * The hardware occasionally sends a tx status for the wrong TID. * In this case, the BA status cannot be considered valid and all * subframes need to be retransmitted - * - * Only BlockAcks have a TID and therefore normal Acks cannot be - * checked */ - if (isba && tidno != ts->tid) + if (tidno != ts->tid) txok = false; isaggr = bf_isaggr(bf); @@ -1262,7 +1259,7 @@ void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc, int tidno; for (tidno = 0, tid = &an->tid[tidno]; - tidno < IEEE80211_NUM_TIDS; tidno++, tid++) { + tidno < WME_NUM_TID; tidno++, tid++) { if (!tid->sched) continue; @@ -1296,7 +1293,7 @@ void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an) int tidno; for (tidno = 0, tid = &an->tid[tidno]; - tidno < IEEE80211_NUM_TIDS; tidno++, tid++) { + tidno < WME_NUM_TID; tidno++, tid++) { ac = tid->ac; txq = ac->txq; @@ -1353,10 +1350,10 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype) struct ath_hw *ah = sc->sc_ah; struct ath9k_tx_queue_info qi; static const int subtype_txq_to_hwq[] = { - [IEEE80211_AC_BE] = ATH_TXQ_AC_BE, - [IEEE80211_AC_BK] = ATH_TXQ_AC_BK, - [IEEE80211_AC_VI] = ATH_TXQ_AC_VI, - [IEEE80211_AC_VO] = ATH_TXQ_AC_VO, + [WME_AC_BE] = ATH_TXQ_AC_BE, + [WME_AC_BK] = ATH_TXQ_AC_BK, + [WME_AC_VI] = ATH_TXQ_AC_VI, + [WME_AC_VO] = ATH_TXQ_AC_VO, }; int axq_qnum, i; @@ -2318,8 +2315,6 @@ void ath_tx_edma_tasklet(struct ath_softc *sc) ath_txq_lock(sc, txq); - TX_STAT_INC(txq->axq_qnum, txprocdesc); - if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) { ath_txq_unlock(sc, txq); return; @@ -2447,7 +2442,7 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) int tidno, acno; for (tidno = 0, tid = &an->tid[tidno]; - tidno < IEEE80211_NUM_TIDS; + tidno < WME_NUM_TID; tidno++, tid++) { tid->an = an; tid->tidno = tidno; @@ -2465,7 +2460,7 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) } for (acno = 0, ac = &an->ac[acno]; - acno < IEEE80211_NUM_ACS; acno++, ac++) { + acno < WME_NUM_AC; acno++, ac++) { ac->sched = false; ac->txq = sc->tx.txq_map[acno]; INIT_LIST_HEAD(&ac->tid_q); @@ -2480,7 +2475,7 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an) int tidno; for (tidno = 0, tid = &an->tid[tidno]; - tidno < IEEE80211_NUM_TIDS; tidno++, tid++) { + tidno < WME_NUM_TID; tidno++, tid++) { ac = tid->ac; txq = ac->txq; diff --git a/trunk/drivers/net/wireless/ath/carl9170/Kconfig b/trunk/drivers/net/wireless/ath/carl9170/Kconfig index 13a204598766..267d5dcf82dc 100644 --- a/trunk/drivers/net/wireless/ath/carl9170/Kconfig +++ b/trunk/drivers/net/wireless/ath/carl9170/Kconfig @@ -1,7 +1,6 @@ config CARL9170 tristate "Linux Community AR9170 802.11n USB support" depends on USB && MAC80211 && EXPERIMENTAL - select ATH_COMMON select FW_LOADER select CRC32 help diff --git a/trunk/drivers/net/wireless/b43/xmit.c b/trunk/drivers/net/wireless/b43/xmit.c index 8cb206a89083..136510edf3cf 100644 --- a/trunk/drivers/net/wireless/b43/xmit.c +++ b/trunk/drivers/net/wireless/b43/xmit.c @@ -796,7 +796,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) status.mactime += mactime; if (low_mactime_now <= mactime) status.mactime -= 0x10000; - status.flag |= RX_FLAG_MACTIME_START; + status.flag |= RX_FLAG_MACTIME_MPDU; } chanid = (chanstat & B43_RX_CHAN_ID) >> B43_RX_CHAN_ID_SHIFT; diff --git a/trunk/drivers/net/wireless/b43legacy/xmit.c b/trunk/drivers/net/wireless/b43legacy/xmit.c index 849a28c80302..b8ffea6f5c64 100644 --- a/trunk/drivers/net/wireless/b43legacy/xmit.c +++ b/trunk/drivers/net/wireless/b43legacy/xmit.c @@ -557,7 +557,7 @@ void b43legacy_rx(struct b43legacy_wldev *dev, status.mactime += mactime; if (low_mactime_now <= mactime) status.mactime -= 0x10000; - status.flag |= RX_FLAG_MACTIME_START; + status.flag |= RX_FLAG_MACTIME_MPDU; } chanid = (chanstat & B43legacy_RX_CHAN_ID) >> diff --git a/trunk/drivers/net/wireless/brcm80211/Kconfig b/trunk/drivers/net/wireless/brcm80211/Kconfig index 1d92d874ebb6..b480088b3dbe 100644 --- a/trunk/drivers/net/wireless/brcm80211/Kconfig +++ b/trunk/drivers/net/wireless/brcm80211/Kconfig @@ -55,17 +55,6 @@ config BRCMFMAC_USB IEEE802.11n embedded FullMAC WLAN driver. Say Y if you want to use the driver for an USB wireless card. -config BRCM_TRACING - bool "Broadcom device tracing" - depends on BRCMSMAC || BRCMFMAC - ---help--- - If you say Y here, the Broadcom wireless drivers will register - with ftrace to dump event information into the trace ringbuffer. - Tracing can be enabled at runtime to aid in debugging wireless - issues. This option adds a small amount of overhead when tracing - is disabled. If unsure, say Y to allow developers to better help - you when wireless problems occur. - config BRCMDBG bool "Broadcom driver debug functions" depends on BRCMSMAC || BRCMFMAC diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/fweh.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/fweh.c index 7a00c4614baf..1e4188cc1b5a 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/fweh.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/fweh.c @@ -314,7 +314,7 @@ static void brcmf_fweh_event_worker(struct work_struct *work) while ((event = brcmf_fweh_dequeue_event(fweh))) { ifp = drvr->iflist[event->ifidx]; - brcmf_dbg(EVENT, "event %s (%u) ifidx %u bsscfg %u addr %pM\n", + brcmf_dbg(EVENT, "event %s (%u) ifidx %u bsscfg %u addr %pM:\n", brcmf_fweh_event_name(event->code), event->code, event->emsg.ifidx, event->emsg.bsscfgidx, event->emsg.addr); @@ -337,7 +337,7 @@ static void brcmf_fweh_event_worker(struct work_struct *work) emsg.version, emsg.flags, emsg.status, emsg.reason); brcmf_dbg_hex_dump(BRCMF_EVENT_ON(), event->data, min_t(u32, emsg.datalen, 64), - "event payload, len=%d\n", emsg.datalen); + "appended:"); /* special handling of interface event */ if (event->code == BRCMF_E_IF) { @@ -494,9 +494,6 @@ void brcmf_fweh_process_event(struct brcmf_pub *drvr, alloc_flag = GFP_ATOMIC; event = kzalloc(sizeof(*event) + datalen, alloc_flag); - if (!event) - return; - event->code = code; event->ifidx = *ifidx; diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/usb.c index 39a5baa92f21..feaca14a1dbe 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/usb.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 96bc349d7f6c..769c134c6618 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -447,7 +447,7 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, struct vif_params *params) { struct brcmf_if *ifp = netdev_priv(ndev); - struct brcmf_cfg80211_vif *vif = ifp->vif; + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); s32 infra = 0; s32 ap = 0; s32 err = 0; @@ -461,15 +461,15 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, type); return -EOPNOTSUPP; case NL80211_IFTYPE_ADHOC: - vif->mode = WL_MODE_IBSS; + cfg->conf->mode = WL_MODE_IBSS; infra = 0; break; case NL80211_IFTYPE_STATION: - vif->mode = WL_MODE_BSS; + cfg->conf->mode = WL_MODE_BSS; infra = 1; break; case NL80211_IFTYPE_AP: - vif->mode = WL_MODE_AP; + cfg->conf->mode = WL_MODE_AP; ap = 1; break; default: @@ -478,16 +478,18 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, } if (ap) { - set_bit(BRCMF_VIF_STATUS_AP_CREATING, &vif->sme_state); + set_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state); WL_INFO("IF Type = AP\n"); } else { - err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, infra); + err = brcmf_fil_cmd_int_set(netdev_priv(ndev), + BRCMF_C_SET_INFRA, infra); if (err) { WL_ERR("WLC_SET_INFRA error (%d)\n", err); err = -EAGAIN; goto done; } - WL_INFO("IF Type = %s\n", (vif->mode == WL_MODE_IBSS) ? + WL_INFO("IF Type = %s\n", + (cfg->conf->mode == WL_MODE_IBSS) ? "Adhoc" : "Infra"); } ndev->ieee80211_ptr->iftype = type; @@ -961,21 +963,22 @@ static void brcmf_ch_to_chanspec(int ch, struct brcmf_join_params *join_params, } } -static void brcmf_link_down(struct brcmf_cfg80211_vif *vif) +static void brcmf_link_down(struct brcmf_cfg80211_info *cfg) { + struct net_device *ndev = NULL; s32 err = 0; WL_TRACE("Enter\n"); - if (test_bit(BRCMF_VIF_STATUS_CONNECTED, &vif->sme_state)) { + if (cfg->link_up) { + ndev = cfg_to_ndev(cfg); WL_INFO("Call WLC_DISASSOC to stop excess roaming\n "); - err = brcmf_fil_cmd_data_set(vif->ifp, + err = brcmf_fil_cmd_data_set(netdev_priv(ndev), BRCMF_C_DISASSOC, NULL, 0); if (err) WL_ERR("WLC_DISASSOC failed (%d)\n", err); - clear_bit(BRCMF_VIF_STATUS_CONNECTED, &vif->sme_state); + cfg->link_up = false; } - clear_bit(BRCMF_VIF_STATUS_CONNECTING, &vif->sme_state); WL_TRACE("Exit\n"); } @@ -1010,8 +1013,8 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, else WL_CONN("No BSSID specified\n"); - if (params->chandef.chan) - WL_CONN("channel: %d\n", params->chandef.chan->center_freq); + if (params->channel) + WL_CONN("channel: %d\n", params->channel->center_freq); else WL_CONN("no channel specified\n"); @@ -1084,12 +1087,12 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, } /* Channel */ - if (params->chandef.chan) { + if (params->channel) { u32 target_channel; cfg->channel = ieee80211_frequency_to_channel( - params->chandef.chan->center_freq); + params->channel->center_freq); if (params->channel_fixed) { /* adding chanspec */ brcmf_ch_to_chanspec(cfg->channel, @@ -1127,6 +1130,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, static s32 brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev) { + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_if *ifp = netdev_priv(ndev); s32 err = 0; @@ -1134,7 +1138,7 @@ brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev) if (!check_vif_up(ifp->vif)) return -EIO; - brcmf_link_down(ifp->vif); + brcmf_link_down(cfg); WL_TRACE("Exit\n"); @@ -1492,6 +1496,7 @@ static s32 brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev, u16 reason_code) { + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_if *ifp = netdev_priv(ndev); struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; struct brcmf_scb_val_le scbval; @@ -1510,6 +1515,8 @@ brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev, if (err) WL_ERR("error (%d)\n", err); + cfg->link_up = false; + WL_TRACE("Exit\n"); return err; } @@ -1709,6 +1716,7 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, u8 key_idx, bool pairwise, const u8 *mac_addr, struct key_params *params) { + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_if *ifp = netdev_priv(ndev); struct brcmf_wsec_key key; s32 val; @@ -1750,7 +1758,7 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, WL_CONN("WLAN_CIPHER_SUITE_WEP104\n"); break; case WLAN_CIPHER_SUITE_TKIP: - if (ifp->vif->mode != WL_MODE_AP) { + if (cfg->conf->mode != WL_MODE_AP) { WL_CONN("Swapping key\n"); memcpy(keybuf, &key.data[24], sizeof(keybuf)); memcpy(&key.data[24], &key.data[16], sizeof(keybuf)); @@ -1900,6 +1908,7 @@ static s32 brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, u8 *mac, struct station_info *sinfo) { + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_if *ifp = netdev_priv(ndev); struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; struct brcmf_scb_val_le scb_val; @@ -1913,7 +1922,7 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, if (!check_vif_up(ifp->vif)) return -EIO; - if (ifp->vif->mode == WL_MODE_AP) { + if (cfg->conf->mode == WL_MODE_AP) { memcpy(&sta_info_le, mac, ETH_ALEN); err = brcmf_fil_iovar_data_get(ifp, "sta_info", &sta_info_le, @@ -1930,7 +1939,7 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, } WL_TRACE("STA idle time : %d ms, connected time :%d sec\n", sinfo->inactive_time, sinfo->connected_time); - } else if (ifp->vif->mode == WL_MODE_BSS) { + } else if (cfg->conf->mode == WL_MODE_BSS) { if (memcmp(mac, bssid, ETH_ALEN)) { WL_ERR("Wrong Mac address cfg_mac-%pM wl_bssid-%pM\n", mac, bssid); @@ -2240,9 +2249,9 @@ static s32 wl_inform_ibss(struct brcmf_cfg80211_info *cfg, return err; } -static bool brcmf_is_ibssmode(struct brcmf_cfg80211_vif *vif) +static bool brcmf_is_ibssmode(struct brcmf_cfg80211_info *cfg) { - return vif->mode == WL_MODE_IBSS; + return cfg->conf->mode == WL_MODE_IBSS; } /* @@ -2327,7 +2336,7 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg) s32 err = 0; WL_TRACE("Enter\n"); - if (brcmf_is_ibssmode(ifp->vif)) + if (brcmf_is_ibssmode(cfg)) return err; ssid = &profile->ssid; @@ -2587,13 +2596,17 @@ static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy, * While going to suspend if associated with AP disassociate * from AP to save power while system is in suspended state */ - brcmf_link_down(vif); - - /* Make sure WPA_Supplicant receives all the event - * generated due to DISASSOC call to the fw to keep - * the state fw and WPA_Supplicant state consistent - */ - brcmf_delay(500); + if (test_bit(BRCMF_VIF_STATUS_CONNECTED, &vif->sme_state) || + test_bit(BRCMF_VIF_STATUS_CONNECTING, &vif->sme_state)) { + WL_INFO("Disassociating from AP before suspend\n"); + brcmf_link_down(cfg); + + /* Make sure WPA_Supplicant receives all the event + * generated due to DISASSOC call to the fw to keep + * the state fw and WPA_Supplicant state consistent + */ + brcmf_delay(500); + } } /* end any scanning */ @@ -3293,12 +3306,11 @@ brcmf_parse_vndr_ies(const u8 *vndr_ie_buf, u32 vndr_ie_len, if (vndr_ies->count >= MAX_VNDR_IE_NUMBER) break; next: - remaining_len -= (ie->len + TLV_HDR_LEN); - if (remaining_len <= TLV_HDR_LEN) + remaining_len -= ie->len; + if (remaining_len <= 2) ie = NULL; else - ie = (struct brcmf_tlv *)(((u8 *)ie) + ie->len + - TLV_HDR_LEN); + ie = (struct brcmf_tlv *)(((u8 *)ie) + ie->len); } return err; } @@ -3397,11 +3409,11 @@ s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag, } } - if (mgmt_ie_buf && *mgmt_ie_len) { + if (mgmt_ie_buf != NULL) { if (parsed_ie_buf_len && (parsed_ie_buf_len == *mgmt_ie_len) && (memcmp(mgmt_ie_buf, curr_ie_buf, parsed_ie_buf_len) == 0)) { - WL_TRACE("Previous mgmt IE equals to current IE\n"); + WL_TRACE("Previous mgmt IE is equals to current IE"); goto exit; } @@ -3439,16 +3451,6 @@ s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag, for (i = 0; i < new_vndr_ies.count; i++) { vndrie_info = &new_vndr_ies.ie_info[i]; - /* verify remained buf size before copy data */ - if (remained_buf_len < (vndrie_info->vndrie.len + - VNDR_IE_VSIE_OFFSET)) { - WL_ERR("no space in mgmt_ie_buf: len left %d", - remained_buf_len); - break; - } - remained_buf_len -= (vndrie_info->ie_len + - VNDR_IE_VSIE_OFFSET); - WL_TRACE("ADDED ID : %d, Len: %d, OUI:%02x:%02x:%02x\n", vndrie_info->vndrie.id, vndrie_info->vndrie.len, @@ -3460,6 +3462,13 @@ s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag, vndrie_info->ie_ptr, vndrie_info->ie_len, "add"); + /* verify remained buf size before copy data */ + remained_buf_len -= vndrie_info->ie_len; + if (remained_buf_len < 0) { + WL_ERR("no space in mgmt_ie_buf: len left %d", + remained_buf_len); + break; + } /* save the parsed IE in wl struct */ memcpy(ptr + (*mgmt_ie_len), vndrie_info->ie_ptr, @@ -3497,8 +3506,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, s32 bssidx = 0; WL_TRACE("channel_type=%d, beacon_interval=%d, dtim_period=%d,\n", - cfg80211_get_chandef_type(&settings->chandef), - settings->beacon_interval, + settings->channel_type, settings->beacon_interval, settings->dtim_period); WL_TRACE("ssid=%s(%zu), auth_type=%d, inactivity_timeout=%d\n", settings->ssid, settings->ssid_len, settings->auth_type, @@ -3634,20 +3642,22 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) { struct brcmf_if *ifp = netdev_priv(ndev); + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); s32 err = -EPERM; WL_TRACE("Enter\n"); - if (ifp->vif->mode == WL_MODE_AP) { + if (cfg->conf->mode == WL_MODE_AP) { /* Due to most likely deauths outstanding we sleep */ /* first to make sure they get processed by fw. */ msleep(400); - err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 0); + err = brcmf_fil_cmd_int_set(netdev_priv(ndev), + BRCMF_C_SET_AP, 0); if (err < 0) { WL_ERR("setting AP mode failed %d\n", err); goto exit; } - err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 0); + err = brcmf_fil_cmd_int_set(netdev_priv(ndev), BRCMF_C_UP, 0); if (err < 0) { WL_ERR("BRCMF_C_UP error %d\n", err); goto exit; @@ -3838,20 +3848,23 @@ static void brcmf_free_vif(struct brcmf_cfg80211_vif *vif) } } -static bool brcmf_is_linkup(const struct brcmf_event_msg *e) +static bool brcmf_is_linkup(struct brcmf_cfg80211_info *cfg, + const struct brcmf_event_msg *e) { u32 event = e->event_code; u32 status = e->status; if (event == BRCMF_E_SET_SSID && status == BRCMF_E_STATUS_SUCCESS) { WL_CONN("Processing set ssid\n"); + cfg->link_up = true; return true; } return false; } -static bool brcmf_is_linkdown(const struct brcmf_event_msg *e) +static bool brcmf_is_linkdown(struct brcmf_cfg80211_info *cfg, + const struct brcmf_event_msg *e) { u32 event = e->event_code; u16 flags = e->flags; @@ -4101,11 +4114,11 @@ brcmf_notify_connect_status(struct brcmf_if *ifp, struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; s32 err = 0; - if (ifp->vif->mode == WL_MODE_AP) { + if (cfg->conf->mode == WL_MODE_AP) { err = brcmf_notify_connect_status_ap(cfg, ndev, e, data); - } else if (brcmf_is_linkup(e)) { + } else if (brcmf_is_linkup(cfg, e)) { WL_CONN("Linkup\n"); - if (brcmf_is_ibssmode(ifp->vif)) { + if (brcmf_is_ibssmode(cfg)) { memcpy(profile->bssid, e->addr, ETH_ALEN); wl_inform_ibss(cfg, ndev, e->addr); cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL); @@ -4115,19 +4128,26 @@ brcmf_notify_connect_status(struct brcmf_if *ifp, &ifp->vif->sme_state); } else brcmf_bss_connect_done(cfg, ndev, e, true); - } else if (brcmf_is_linkdown(e)) { + } else if (brcmf_is_linkdown(cfg, e)) { WL_CONN("Linkdown\n"); - if (!brcmf_is_ibssmode(ifp->vif)) { - brcmf_bss_connect_done(cfg, ndev, e, false); + if (brcmf_is_ibssmode(cfg)) { + clear_bit(BRCMF_VIF_STATUS_CONNECTING, + &ifp->vif->sme_state); if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state)) + brcmf_link_down(cfg); + } else { + brcmf_bss_connect_done(cfg, ndev, e, false); + if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTED, + &ifp->vif->sme_state)) { cfg80211_disconnected(ndev, 0, NULL, 0, GFP_KERNEL); + brcmf_link_down(cfg); + } } - brcmf_link_down(ifp->vif); brcmf_init_prof(ndev_to_prof(ndev)); } else if (brcmf_is_nonetwork(cfg, e)) { - if (brcmf_is_ibssmode(ifp->vif)) + if (brcmf_is_ibssmode(cfg)) clear_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state); else @@ -4176,6 +4196,7 @@ brcmf_notify_mic_status(struct brcmf_if *ifp, static void brcmf_init_conf(struct brcmf_cfg80211_conf *conf) { + conf->mode = (u32)-1; conf->frag_threshold = (u32)-1; conf->rts_threshold = (u32)-1; conf->retry_short = (u32)-1; @@ -4260,6 +4281,7 @@ static s32 wl_init_priv(struct brcmf_cfg80211_info *cfg) mutex_init(&cfg->usr_sync); brcmf_init_escan(cfg); brcmf_init_conf(cfg->conf); + brcmf_link_down(cfg); return err; } @@ -4267,6 +4289,7 @@ static s32 wl_init_priv(struct brcmf_cfg80211_info *cfg) static void wl_deinit_priv(struct brcmf_cfg80211_info *cfg) { cfg->dongle_up = false; /* dongle down */ + brcmf_link_down(cfg); brcmf_abort_scanning(cfg); brcmf_deinit_priv_mem(cfg); } @@ -4513,8 +4536,11 @@ static s32 __brcmf_cfg80211_down(struct brcmf_if *ifp) * While going down, if associated with AP disassociate * from AP to save power */ - if (check_vif_up(ifp->vif)) { - brcmf_link_down(ifp->vif); + if ((test_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state) || + test_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state)) && + check_vif_up(ifp->vif)) { + WL_INFO("Disassociating from AP"); + brcmf_link_down(cfg); /* Make sure WPA_Supplicant receives all the event generated due to DISASSOC call to the fw to keep diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h b/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h index d60de187e7d9..e2ef8519ea84 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h @@ -128,6 +128,7 @@ enum wl_mode { /* dongle configuration */ struct brcmf_cfg80211_conf { + u32 mode; /* adhoc , infrastructure or ap */ u32 frag_threshold; u32 rts_threshold; u32 retry_short; @@ -358,6 +359,7 @@ struct brcmf_pno_scanresults_le { * @active_scan: current scan mode. * @sched_escan: e-scan for scheduled scan support running. * @ibss_starter: indicates this sta is ibss starter. + * @link_up: link/connection up flag. * @pwr_save: indicate whether dongle to support power save mode. * @dongle_up: indicate whether dongle up or not. * @roam_on: on/off switch for dongle self-roaming. @@ -389,6 +391,7 @@ struct brcmf_cfg80211_info { bool active_scan; bool sched_escan; bool ibss_starter; + bool link_up; bool pwr_save; bool dongle_up; bool roam_on; diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/Makefile b/trunk/drivers/net/wireless/brcm80211/brcmsmac/Makefile index d3d4151c3eda..e227c4c68ef9 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/Makefile +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/Makefile @@ -40,8 +40,7 @@ BRCMSMAC_OFILES := \ phy/phytbl_n.o \ phy/phy_qmath.o \ dma.o \ - brcms_trace_events.o \ - debug.o + brcms_trace_events.o MODULEPFX := brcmsmac diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c b/trunk/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c index 1de94f30564f..be5bcfb9153b 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c @@ -21,8 +21,6 @@ #include "antsel.h" #include "main.h" #include "ampdu.h" -#include "debug.h" -#include "brcms_trace_events.h" /* max number of mpdus in an ampdu */ #define AMPDU_MAX_MPDU 32 @@ -42,6 +40,8 @@ #define AMPDU_DEF_RETRY_LIMIT 5 /* default tx retry limit at reg rate */ #define AMPDU_DEF_RR_RETRY_LIMIT 2 +/* default weight of ampdu in txfifo */ +#define AMPDU_DEF_TXPKT_WEIGHT 2 /* default ffpld reserved bytes */ #define AMPDU_DEF_FFPLD_RSVD 2048 /* # of inis to be freed on detach */ @@ -114,6 +114,7 @@ struct brcms_fifo_info { * mpdu_density: min mpdu spacing (0-7) ==> 2^(x-1)/8 usec * max_pdu: max pdus allowed in ampdu * dur: max duration of an ampdu (in msec) + * txpkt_weight: weight of ampdu in txfifo; reduces rate lag * rx_factor: maximum rx ampdu factor (0-3) ==> 2^(13+x) bytes * ffpld_rsvd: number of bytes to reserve for preload * max_txlen: max size of ampdu per mcs, bw and sgi @@ -135,6 +136,7 @@ struct ampdu_info { u8 mpdu_density; s8 max_pdu; u8 dur; + u8 txpkt_weight; u8 rx_factor; u32 ffpld_rsvd; u32 max_txlen[MCS_TABLE_SIZE][2][2]; @@ -181,19 +183,18 @@ static bool brcms_c_ampdu_cap(struct ampdu_info *ampdu) static int brcms_c_ampdu_set(struct ampdu_info *ampdu, bool on) { struct brcms_c_info *wlc = ampdu->wlc; - struct bcma_device *core = wlc->hw->d11core; wlc->pub->_ampdu = false; if (on) { if (!(wlc->pub->_n_enab & SUPPORT_11N)) { - brcms_err(core, "wl%d: driver not nmode enabled\n", - wlc->pub->unit); + wiphy_err(ampdu->wlc->wiphy, "wl%d: driver not " + "nmode enabled\n", wlc->pub->unit); return -ENOTSUPP; } if (!brcms_c_ampdu_cap(ampdu)) { - brcms_err(core, "wl%d: device not ampdu capable\n", - wlc->pub->unit); + wiphy_err(ampdu->wlc->wiphy, "wl%d: device not " + "ampdu capable\n", wlc->pub->unit); return -ENOTSUPP; } wlc->pub->_ampdu = on; @@ -246,6 +247,7 @@ struct ampdu_info *brcms_c_ampdu_attach(struct brcms_c_info *wlc) ampdu->mpdu_density = AMPDU_DEF_MPDU_DENSITY; ampdu->max_pdu = AUTO; ampdu->dur = AMPDU_MAX_DUR; + ampdu->txpkt_weight = AMPDU_DEF_TXPKT_WEIGHT; ampdu->ffpld_rsvd = AMPDU_DEF_FFPLD_RSVD; /* @@ -372,8 +374,7 @@ static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int fid) offsetof(struct macstat, txfunfl[fid])); new_txunfl = (u16) (cur_txunfl - fifo->prev_txfunfl); if (new_txunfl == 0) { - brcms_dbg_ht(wlc->hw->d11core, - "TX status FRAG set but no tx underflows\n"); + BCMMSG(wlc->wiphy, "TX status FRAG set but no tx underflows\n"); return -1; } fifo->prev_txfunfl = cur_txunfl; @@ -395,8 +396,8 @@ static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int fid) if (fifo->accum_txfunfl < 10) return 0; - brcms_dbg_ht(wlc->hw->d11core, "ampdu_count %d tx_underflows %d\n", - current_ampdu_cnt, fifo->accum_txfunfl); + BCMMSG(wlc->wiphy, "ampdu_count %d tx_underflows %d\n", + current_ampdu_cnt, fifo->accum_txfunfl); /* compute the current ratio of tx unfl per ampdu. @@ -449,10 +450,9 @@ static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int fid) (max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size)) / (max_mpdu * FFPLD_MPDU_SIZE)) * 100; - brcms_dbg_ht(wlc->hw->d11core, - "DMA estimated transfer rate %d; " - "pre-load size %d\n", - fifo->dmaxferrate, fifo->ampdu_pld_size); + BCMMSG(wlc->wiphy, "DMA estimated transfer rate %d; " + "pre-load size %d\n", + fifo->dmaxferrate, fifo->ampdu_pld_size); } else { /* decrease ampdu size */ @@ -486,7 +486,7 @@ brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid, scb_ampdu = &scb->scb_ampdu; if (!ampdu->ini_enable[tid]) { - brcms_err(wlc->hw->d11core, "%s: Rejecting tid %d\n", + wiphy_err(ampdu->wlc->wiphy, "%s: Rejecting tid %d\n", __func__, tid); return; } @@ -498,324 +498,378 @@ brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid, scb_ampdu->max_rx_ampdu_bytes = max_rx_ampdu_bytes; } -void brcms_c_ampdu_reset_session(struct brcms_ampdu_session *session, - struct brcms_c_info *wlc) +int +brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi, + struct sk_buff **pdu, int prec) { - session->wlc = wlc; - skb_queue_head_init(&session->skb_list); - session->max_ampdu_len = 0; /* determined from first MPDU */ - session->max_ampdu_frames = 0; /* determined from first MPDU */ - session->ampdu_len = 0; - session->dma_len = 0; -} + struct brcms_c_info *wlc; + struct sk_buff *p, *pkt[AMPDU_MAX_MPDU]; + u8 tid, ndelim; + int err = 0; + u8 preamble_type = BRCMS_GF_PREAMBLE; + u8 fbr_preamble_type = BRCMS_GF_PREAMBLE; + u8 rts_preamble_type = BRCMS_LONG_PREAMBLE; + u8 rts_fbr_preamble_type = BRCMS_LONG_PREAMBLE; -/* - * Preps the given packet for AMPDU based on the session data. If the - * frame cannot be accomodated in the current session, -ENOSPC is - * returned. - */ -int brcms_c_ampdu_add_frame(struct brcms_ampdu_session *session, - struct sk_buff *p) -{ - struct brcms_c_info *wlc = session->wlc; - struct ampdu_info *ampdu = wlc->ampdu; - struct scb *scb = &wlc->pri_scb; - struct scb_ampdu *scb_ampdu = &scb->scb_ampdu; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(p); - struct ieee80211_tx_rate *txrate = tx_info->status.rates; - struct d11txh *txh = (struct d11txh *)p->data; - unsigned ampdu_frames; - u8 ndelim, tid; + bool rr = true, fbr = false; + uint i, count = 0, fifo, seg_cnt = 0; + u16 plen, len, seq = 0, mcl, mch, index, frameid, dma_len = 0; + u32 ampdu_len, max_ampdu_bytes = 0; + struct d11txh *txh = NULL; u8 *plcp; - uint len; - u16 mcl; + struct ieee80211_hdr *h; + struct scb *scb; + struct scb_ampdu *scb_ampdu; + struct scb_ampdu_tid_ini *ini; + u8 mcs = 0; + bool use_rts = false, use_cts = false; + u32 rspec = 0, rspec_fallback = 0; + u32 rts_rspec = 0, rts_rspec_fallback = 0; + u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ; + struct ieee80211_rts *rts; + u8 rr_retry_limit; + struct brcms_fifo_info *f; bool fbr_iscck; - bool rr; - - ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM]; - plcp = (u8 *)(txh + 1); - fbr_iscck = !(le16_to_cpu(txh->XtraFrameTypes) & 0x03); - len = fbr_iscck ? BRCMS_GET_CCK_PLCP_LEN(txh->FragPLCPFallback) : - BRCMS_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback); - len = roundup(len, 4) + (ndelim + 1) * AMPDU_DELIMITER_LEN; + struct ieee80211_tx_info *tx_info; + u16 qlen; + struct wiphy *wiphy; - ampdu_frames = skb_queue_len(&session->skb_list); - if (ampdu_frames != 0) { - struct sk_buff *first; + wlc = ampdu->wlc; + wiphy = wlc->wiphy; + p = *pdu; - if (ampdu_frames + 1 > session->max_ampdu_frames || - session->ampdu_len + len > session->max_ampdu_len) - return -ENOSPC; + tid = (u8) (p->priority); - /* - * We aren't really out of space if the new frame is of - * a different priority, but we want the same behaviour - * so return -ENOSPC anyway. - * - * XXX: The old AMPDU code did this, but is it really - * necessary? - */ - first = skb_peek(&session->skb_list); - if (p->priority != first->priority) - return -ENOSPC; - } + f = ampdu->fifo_tb + prio2fifo[tid]; - /* - * Now that we're sure this frame can be accomodated, update the - * session information. - */ - session->ampdu_len += len; - session->dma_len += p->len; + scb = &wlc->pri_scb; + scb_ampdu = &scb->scb_ampdu; + ini = &scb_ampdu->ini[tid]; - tid = (u8)p->priority; + /* Let pressure continue to build ... */ + qlen = pktq_plen(&qi->q, prec); + if (ini->tx_in_transit > 0 && + qlen < min(scb_ampdu->max_pdu, ini->ba_wsize)) + /* Collect multiple MPDU's to be sent in the next AMPDU */ + return -EBUSY; - /* Handle retry limits */ - if (txrate[0].count <= ampdu->rr_retry_limit_tid[tid]) { - txrate[0].count++; - rr = true; - } else { - txrate[1].count++; - rr = false; - } + /* at this point we intend to transmit an AMPDU */ + rr_retry_limit = ampdu->rr_retry_limit_tid[tid]; + ampdu_len = 0; + dma_len = 0; + while (p) { + struct ieee80211_tx_rate *txrate; - if (ampdu_frames == 0) { - u8 plcp0, plcp3, is40, sgi, mcs; - uint fifo = le16_to_cpu(txh->TxFrameID) & TXFID_QUEUE_MASK; - struct brcms_fifo_info *f = &du->fifo_tb[fifo]; + tx_info = IEEE80211_SKB_CB(p); + txrate = tx_info->status.rates; - if (rr) { - plcp0 = plcp[0]; - plcp3 = plcp[3]; + if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { + err = brcms_c_prep_pdu(wlc, p, &fifo); } else { - plcp0 = txh->FragPLCPFallback[0]; - plcp3 = txh->FragPLCPFallback[3]; + wiphy_err(wiphy, "%s: AMPDU flag is off!\n", __func__); + *pdu = NULL; + err = 0; + break; + } + + if (err) { + if (err == -EBUSY) { + wiphy_err(wiphy, "wl%d: sendampdu: " + "prep_xdu retry; seq 0x%x\n", + wlc->pub->unit, seq); + *pdu = p; + break; + } + /* error in the packet; reject it */ + wiphy_err(wiphy, "wl%d: sendampdu: prep_xdu " + "rejected; seq 0x%x\n", wlc->pub->unit, seq); + *pdu = NULL; + break; } - /* Limit AMPDU size based on MCS */ - is40 = (plcp0 & MIMO_PLCP_40MHZ) ? 1 : 0; - sgi = plcp3_issgi(plcp3) ? 1 : 0; - mcs = plcp0 & ~MIMO_PLCP_40MHZ; - session->max_ampdu_len = min(scb_ampdu->max_rx_ampdu_bytes, - ampdu->max_txlen[mcs][is40][sgi]); + /* pkt is good to be aggregated */ + txh = (struct d11txh *) p->data; + plcp = (u8 *) (txh + 1); + h = (struct ieee80211_hdr *)(plcp + D11_PHY_HDR_LEN); + seq = le16_to_cpu(h->seq_ctrl) >> SEQNUM_SHIFT; + index = TX_SEQ_TO_INDEX(seq); - session->max_ampdu_frames = scb_ampdu->max_pdu; - if (mcs_2_rate(mcs, true, false) >= f->dmaxferrate) { - session->max_ampdu_frames = - min_t(u16, f->mcs2ampdu_table[mcs], - session->max_ampdu_frames); + /* check mcl fields and test whether it can be agg'd */ + mcl = le16_to_cpu(txh->MacTxControlLow); + mcl &= ~TXC_AMPDU_MASK; + fbr_iscck = !(le16_to_cpu(txh->XtraFrameTypes) & 0x3); + txh->PreloadSize = 0; /* always default to 0 */ + + /* Handle retry limits */ + if (txrate[0].count <= rr_retry_limit) { + txrate[0].count++; + rr = true; + fbr = false; + } else { + fbr = true; + rr = false; + txrate[1].count++; } - } - /* - * Treat all frames as "middle" frames of AMPDU here. First and - * last frames must be fixed up after all MPDUs have been prepped. - */ - mcl = le16_to_cpu(txh->MacTxControlLow); - mcl &= ~TXC_AMPDU_MASK; - mcl |= (TXC_AMPDU_MIDDLE << TXC_AMPDU_SHIFT); - mcl &= ~(TXC_STARTMSDU | TXC_SENDRTS | TXC_SENDCTS); - txh->MacTxControlLow = cpu_to_le16(mcl); - txh->PreloadSize = 0; /* always default to 0 */ + /* extract the length info */ + len = fbr_iscck ? BRCMS_GET_CCK_PLCP_LEN(txh->FragPLCPFallback) + : BRCMS_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback); - skb_queue_tail(&session->skb_list, p); + /* retrieve null delimiter count */ + ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM]; + seg_cnt += 1; - return 0; -} + BCMMSG(wlc->wiphy, "wl%d: mpdu %d plcp_len %d\n", + wlc->pub->unit, count, len); -void brcms_c_ampdu_finalize(struct brcms_ampdu_session *session) -{ - struct brcms_c_info *wlc = session->wlc; - struct ampdu_info *ampdu = wlc->ampdu; - struct sk_buff *first, *last; - struct d11txh *txh; - struct ieee80211_tx_info *tx_info; - struct ieee80211_tx_rate *txrate; - u8 ndelim; - u8 *plcp; - uint len; - uint fifo; - struct brcms_fifo_info *f; - u16 mcl; - bool fbr; - bool fbr_iscck; - struct ieee80211_rts *rts; - bool use_rts = false, use_cts = false; - u16 dma_len = session->dma_len; - u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ; - u32 rspec = 0, rspec_fallback = 0; - u32 rts_rspec = 0, rts_rspec_fallback = 0; - u8 plcp0, plcp3, is40, sgi, mcs; - u16 mch; - u8 preamble_type = BRCMS_GF_PREAMBLE; - u8 fbr_preamble_type = BRCMS_GF_PREAMBLE; - u8 rts_preamble_type = BRCMS_LONG_PREAMBLE; - u8 rts_fbr_preamble_type = BRCMS_LONG_PREAMBLE; + /* + * aggregateable mpdu. For ucode/hw agg, + * test whether need to break or change the epoch + */ + if (count == 0) { + mcl |= (TXC_AMPDU_FIRST << TXC_AMPDU_SHIFT); + /* refill the bits since might be a retx mpdu */ + mcl |= TXC_STARTMSDU; + rts = (struct ieee80211_rts *)&txh->rts_frame; + + if (ieee80211_is_rts(rts->frame_control)) { + mcl |= TXC_SENDRTS; + use_rts = true; + } + if (ieee80211_is_cts(rts->frame_control)) { + mcl |= TXC_SENDCTS; + use_cts = true; + } + } else { + mcl |= (TXC_AMPDU_MIDDLE << TXC_AMPDU_SHIFT); + mcl &= ~(TXC_STARTMSDU | TXC_SENDRTS | TXC_SENDCTS); + } - if (skb_queue_empty(&session->skb_list)) - return; + len = roundup(len, 4); + ampdu_len += (len + (ndelim + 1) * AMPDU_DELIMITER_LEN); - first = skb_peek(&session->skb_list); - last = skb_peek_tail(&session->skb_list); - - /* Need to fix up last MPDU first to adjust AMPDU length */ - txh = (struct d11txh *)last->data; - fifo = le16_to_cpu(txh->TxFrameID) & TXFID_QUEUE_MASK; - f = &du->fifo_tb[fifo]; - - mcl = le16_to_cpu(txh->MacTxControlLow); - mcl &= ~TXC_AMPDU_MASK; - mcl |= (TXC_AMPDU_LAST << TXC_AMPDU_SHIFT); - txh->MacTxControlLow = cpu_to_le16(mcl); - - /* remove the null delimiter after last mpdu */ - ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM]; - txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM] = 0; - session->ampdu_len -= ndelim * AMPDU_DELIMITER_LEN; - - /* remove the pad len from last mpdu */ - fbr_iscck = ((le16_to_cpu(txh->XtraFrameTypes) & 0x3) == 0); - len = fbr_iscck ? BRCMS_GET_CCK_PLCP_LEN(txh->FragPLCPFallback) : - BRCMS_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback); - session->ampdu_len -= roundup(len, 4) - len; - - /* Now fix up the first MPDU */ - tx_info = IEEE80211_SKB_CB(first); - txrate = tx_info->status.rates; - txh = (struct d11txh *)first->data; - plcp = (u8 *)(txh + 1); - rts = (struct ieee80211_rts *)&txh->rts_frame; - - mcl = le16_to_cpu(txh->MacTxControlLow); - /* If only one MPDU leave it marked as last */ - if (first != last) { - mcl &= ~TXC_AMPDU_MASK; - mcl |= (TXC_AMPDU_FIRST << TXC_AMPDU_SHIFT); - } - mcl |= TXC_STARTMSDU; - if (ieee80211_is_rts(rts->frame_control)) { - mcl |= TXC_SENDRTS; - use_rts = true; - } - if (ieee80211_is_cts(rts->frame_control)) { - mcl |= TXC_SENDCTS; - use_cts = true; - } - txh->MacTxControlLow = cpu_to_le16(mcl); + dma_len += (u16) p->len; - fbr = txrate[1].count > 0; - if (!fbr) { - plcp0 = plcp[0]; - plcp3 = plcp[3]; - } else { - plcp0 = txh->FragPLCPFallback[0]; - plcp3 = txh->FragPLCPFallback[3]; - } - is40 = (plcp0 & MIMO_PLCP_40MHZ) ? 1 : 0; - sgi = plcp3_issgi(plcp3) ? 1 : 0; - mcs = plcp0 & ~MIMO_PLCP_40MHZ; - - if (is40) { - if (CHSPEC_SB_UPPER(wlc_phy_chanspec_get(wlc->band->pi))) - mimo_ctlchbw = PHY_TXC1_BW_20MHZ_UP; - else - mimo_ctlchbw = PHY_TXC1_BW_20MHZ; - } + BCMMSG(wlc->wiphy, "wl%d: ampdu_len %d" + " seg_cnt %d null delim %d\n", + wlc->pub->unit, ampdu_len, seg_cnt, ndelim); - /* rebuild the rspec and rspec_fallback */ - rspec = RSPEC_MIMORATE; - rspec |= plcp[0] & ~MIMO_PLCP_40MHZ; - if (plcp[0] & MIMO_PLCP_40MHZ) - rspec |= (PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT); + txh->MacTxControlLow = cpu_to_le16(mcl); - fbr_iscck = !(le16_to_cpu(txh->XtraFrameTypes) & 0x03); - if (fbr_iscck) { - rspec_fallback = - cck_rspec(cck_phy2mac_rate(txh->FragPLCPFallback[0])); - } else { - rspec_fallback = RSPEC_MIMORATE; - rspec_fallback |= txh->FragPLCPFallback[0] & ~MIMO_PLCP_40MHZ; - if (txh->FragPLCPFallback[0] & MIMO_PLCP_40MHZ) - rspec_fallback |= PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT; - } + /* this packet is added */ + pkt[count++] = p; - if (use_rts || use_cts) { - rts_rspec = - brcms_c_rspec_to_rts_rspec(wlc, rspec, - false, mimo_ctlchbw); - rts_rspec_fallback = - brcms_c_rspec_to_rts_rspec(wlc, rspec_fallback, - false, mimo_ctlchbw); - } + /* patch the first MPDU */ + if (count == 1) { + u8 plcp0, plcp3, is40, sgi; - BRCMS_SET_MIMO_PLCP_LEN(plcp, session->ampdu_len); - /* mark plcp to indicate ampdu */ - BRCMS_SET_MIMO_PLCP_AMPDU(plcp); + if (rr) { + plcp0 = plcp[0]; + plcp3 = plcp[3]; + } else { + plcp0 = txh->FragPLCPFallback[0]; + plcp3 = txh->FragPLCPFallback[3]; - /* reset the mixed mode header durations */ - if (txh->MModeLen) { - u16 mmodelen = brcms_c_calc_lsig_len(wlc, rspec, - session->ampdu_len); - txh->MModeLen = cpu_to_le16(mmodelen); - preamble_type = BRCMS_MM_PREAMBLE; - } - if (txh->MModeFbrLen) { - u16 mmfbrlen = brcms_c_calc_lsig_len(wlc, rspec_fallback, - session->ampdu_len); - txh->MModeFbrLen = cpu_to_le16(mmfbrlen); - fbr_preamble_type = BRCMS_MM_PREAMBLE; - } + } + is40 = (plcp0 & MIMO_PLCP_40MHZ) ? 1 : 0; + sgi = plcp3_issgi(plcp3) ? 1 : 0; + mcs = plcp0 & ~MIMO_PLCP_40MHZ; + max_ampdu_bytes = + min(scb_ampdu->max_rx_ampdu_bytes, + ampdu->max_txlen[mcs][is40][sgi]); + + if (is40) + mimo_ctlchbw = + CHSPEC_SB_UPPER(wlc_phy_chanspec_get( + wlc->band->pi)) + ? PHY_TXC1_BW_20MHZ_UP : PHY_TXC1_BW_20MHZ; + + /* rebuild the rspec and rspec_fallback */ + rspec = RSPEC_MIMORATE; + rspec |= plcp[0] & ~MIMO_PLCP_40MHZ; + if (plcp[0] & MIMO_PLCP_40MHZ) + rspec |= (PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT); + + if (fbr_iscck) /* CCK */ + rspec_fallback = cck_rspec(cck_phy2mac_rate + (txh->FragPLCPFallback[0])); + else { /* MIMO */ + rspec_fallback = RSPEC_MIMORATE; + rspec_fallback |= + txh->FragPLCPFallback[0] & ~MIMO_PLCP_40MHZ; + if (txh->FragPLCPFallback[0] & MIMO_PLCP_40MHZ) + rspec_fallback |= + (PHY_TXC1_BW_40MHZ << + RSPEC_BW_SHIFT); + } - /* set the preload length */ - if (mcs_2_rate(mcs, true, false) >= f->dmaxferrate) { - dma_len = min(dma_len, f->ampdu_pld_size); - txh->PreloadSize = cpu_to_le16(dma_len); - } else { - txh->PreloadSize = 0; - } + if (use_rts || use_cts) { + rts_rspec = + brcms_c_rspec_to_rts_rspec(wlc, + rspec, false, mimo_ctlchbw); + rts_rspec_fallback = + brcms_c_rspec_to_rts_rspec(wlc, + rspec_fallback, false, mimo_ctlchbw); + } + } + + /* if (first mpdu for host agg) */ + /* test whether to add more */ + if ((mcs_2_rate(mcs, true, false) >= f->dmaxferrate) && + (count == f->mcs2ampdu_table[mcs])) { + BCMMSG(wlc->wiphy, "wl%d: PR 37644: stopping" + " ampdu at %d for mcs %d\n", + wlc->pub->unit, count, mcs); + break; + } + + if (count == scb_ampdu->max_pdu) + break; + + /* + * check to see if the next pkt is + * a candidate for aggregation + */ + p = pktq_ppeek(&qi->q, prec); + if (p) { + tx_info = IEEE80211_SKB_CB(p); + if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && + ((u8) (p->priority) == tid)) { + plen = p->len + AMPDU_MAX_MPDU_OVERHEAD; + plen = max(scb_ampdu->min_len, plen); - mch = le16_to_cpu(txh->MacTxControlHigh); + if ((plen + ampdu_len) > max_ampdu_bytes) { + p = NULL; + continue; + } - /* update RTS dur fields */ - if (use_rts || use_cts) { - u16 durid; - if ((mch & TXC_PREAMBLE_RTS_MAIN_SHORT) == - TXC_PREAMBLE_RTS_MAIN_SHORT) - rts_preamble_type = BRCMS_SHORT_PREAMBLE; + /* + * check if there are enough + * descriptors available + */ + if (*wlc->core->txavail[fifo] <= seg_cnt + 1) { + wiphy_err(wiphy, "%s: No fifo space " + "!!\n", __func__); + p = NULL; + continue; + } + /* next packet fit for aggregation so dequeue */ + p = brcmu_pktq_pdeq(&qi->q, prec); + } else { + p = NULL; + } + } + } /* end while(p) */ - if ((mch & TXC_PREAMBLE_RTS_FB_SHORT) == - TXC_PREAMBLE_RTS_FB_SHORT) - rts_fbr_preamble_type = BRCMS_SHORT_PREAMBLE; + ini->tx_in_transit += count; - durid = brcms_c_compute_rtscts_dur(wlc, use_cts, rts_rspec, - rspec, rts_preamble_type, - preamble_type, - session->ampdu_len, true); - rts->duration = cpu_to_le16(durid); - durid = brcms_c_compute_rtscts_dur(wlc, use_cts, - rts_rspec_fallback, - rspec_fallback, - rts_fbr_preamble_type, - fbr_preamble_type, - session->ampdu_len, true); - txh->RTSDurFallback = cpu_to_le16(durid); - /* set TxFesTimeNormal */ - txh->TxFesTimeNormal = rts->duration; - /* set fallback rate version of TxFesTimeNormal */ - txh->TxFesTimeFallback = txh->RTSDurFallback; - } + if (count) { + /* patch up the last txh */ + txh = (struct d11txh *) pkt[count - 1]->data; + mcl = le16_to_cpu(txh->MacTxControlLow); + mcl &= ~TXC_AMPDU_MASK; + mcl |= (TXC_AMPDU_LAST << TXC_AMPDU_SHIFT); + txh->MacTxControlLow = cpu_to_le16(mcl); + + /* remove the null delimiter after last mpdu */ + ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM]; + txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM] = 0; + ampdu_len -= ndelim * AMPDU_DELIMITER_LEN; + + /* remove the pad len from last mpdu */ + fbr_iscck = ((le16_to_cpu(txh->XtraFrameTypes) & 0x3) == 0); + len = fbr_iscck ? BRCMS_GET_CCK_PLCP_LEN(txh->FragPLCPFallback) + : BRCMS_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback); + ampdu_len -= roundup(len, 4) - len; + + /* patch up the first txh & plcp */ + txh = (struct d11txh *) pkt[0]->data; + plcp = (u8 *) (txh + 1); - /* set flag and plcp for fallback rate */ - if (fbr) { - mch |= TXC_AMPDU_FBR; - txh->MacTxControlHigh = cpu_to_le16(mch); + BRCMS_SET_MIMO_PLCP_LEN(plcp, ampdu_len); + /* mark plcp to indicate ampdu */ BRCMS_SET_MIMO_PLCP_AMPDU(plcp); - BRCMS_SET_MIMO_PLCP_AMPDU(txh->FragPLCPFallback); - } - brcms_dbg_ht(wlc->hw->d11core, "wl%d: count %d ampdu_len %d\n", - wlc->pub->unit, skb_queue_len(&session->skb_list), - session->ampdu_len); + /* reset the mixed mode header durations */ + if (txh->MModeLen) { + u16 mmodelen = + brcms_c_calc_lsig_len(wlc, rspec, ampdu_len); + txh->MModeLen = cpu_to_le16(mmodelen); + preamble_type = BRCMS_MM_PREAMBLE; + } + if (txh->MModeFbrLen) { + u16 mmfbrlen = + brcms_c_calc_lsig_len(wlc, rspec_fallback, + ampdu_len); + txh->MModeFbrLen = cpu_to_le16(mmfbrlen); + fbr_preamble_type = BRCMS_MM_PREAMBLE; + } + + /* set the preload length */ + if (mcs_2_rate(mcs, true, false) >= f->dmaxferrate) { + dma_len = min(dma_len, f->ampdu_pld_size); + txh->PreloadSize = cpu_to_le16(dma_len); + } else + txh->PreloadSize = 0; + + mch = le16_to_cpu(txh->MacTxControlHigh); + + /* update RTS dur fields */ + if (use_rts || use_cts) { + u16 durid; + rts = (struct ieee80211_rts *)&txh->rts_frame; + if ((mch & TXC_PREAMBLE_RTS_MAIN_SHORT) == + TXC_PREAMBLE_RTS_MAIN_SHORT) + rts_preamble_type = BRCMS_SHORT_PREAMBLE; + + if ((mch & TXC_PREAMBLE_RTS_FB_SHORT) == + TXC_PREAMBLE_RTS_FB_SHORT) + rts_fbr_preamble_type = BRCMS_SHORT_PREAMBLE; + + durid = + brcms_c_compute_rtscts_dur(wlc, use_cts, rts_rspec, + rspec, rts_preamble_type, + preamble_type, ampdu_len, + true); + rts->duration = cpu_to_le16(durid); + durid = brcms_c_compute_rtscts_dur(wlc, use_cts, + rts_rspec_fallback, + rspec_fallback, + rts_fbr_preamble_type, + fbr_preamble_type, + ampdu_len, true); + txh->RTSDurFallback = cpu_to_le16(durid); + /* set TxFesTimeNormal */ + txh->TxFesTimeNormal = rts->duration; + /* set fallback rate version of TxFesTimeNormal */ + txh->TxFesTimeFallback = txh->RTSDurFallback; + } + + /* set flag and plcp for fallback rate */ + if (fbr) { + mch |= TXC_AMPDU_FBR; + txh->MacTxControlHigh = cpu_to_le16(mch); + BRCMS_SET_MIMO_PLCP_AMPDU(plcp); + BRCMS_SET_MIMO_PLCP_AMPDU(txh->FragPLCPFallback); + } + + BCMMSG(wlc->wiphy, "wl%d: count %d ampdu_len %d\n", + wlc->pub->unit, count, ampdu_len); + + /* inform rate_sel if it this is a rate probe pkt */ + frameid = le16_to_cpu(txh->TxFrameID); + if (frameid & TXFID_RATE_PROBE_MASK) + wiphy_err(wiphy, "%s: XXX what to do with " + "TXFID_RATE_PROBE_MASK!?\n", __func__); + + for (i = 0; i < count; i++) + brcms_c_txfifo(wlc, fifo, pkt[i], i == (count - 1), + ampdu->txpkt_weight); + + } + /* endif (count) */ + return err; } static void @@ -855,6 +909,7 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb, u8 antselid = 0; u8 retry_limit, rr_retry_limit; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(p); + struct wiphy *wiphy = wlc->wiphy; #ifdef DEBUG u8 hole[AMPDU_MAX_MPDU]; @@ -900,14 +955,13 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb, if (supr_status) { update_rate = false; if (supr_status == TX_STATUS_SUPR_BADCH) { - brcms_err(wlc->hw->d11core, + wiphy_err(wiphy, "%s: Pkt tx suppressed, illegal channel possibly %d\n", __func__, CHSPEC_CHANNEL( wlc->default_bss->chanspec)); } else { if (supr_status != TX_STATUS_SUPR_FRAG) - brcms_err(wlc->hw->d11core, - "%s: supr_status 0x%x\n", + wiphy_err(wiphy, "%s: supr_status 0x%x\n", __func__, supr_status); } /* no need to retry for badch; will fail again */ @@ -923,14 +977,20 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb, * if there were underflows, but pre-loading * is not active, notify rate adaptation. */ - if (brcms_c_ffpld_check_txfunfl(wlc, queue) > 0) + if (brcms_c_ffpld_check_txfunfl(wlc, + prio2fifo[tid]) > 0) tx_error = true; } } else if (txs->phyerr) { update_rate = false; - brcms_err(wlc->hw->d11core, - "%s: ampdu tx phy error (0x%x)\n", + wiphy_err(wiphy, "%s: ampdu tx phy error (0x%x)\n", __func__, txs->phyerr); + + if (brcm_msg_level & LOG_ERROR_VAL) { + brcmu_prpkt("txpkt (AMPDU)", p); + brcms_c_print_txdesc((struct d11txh *) p->data); + } + brcms_c_print_txstatus(txs); } } @@ -943,8 +1003,6 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb, h = (struct ieee80211_hdr *)(plcp + D11_PHY_HDR_LEN); seq = le16_to_cpu(h->seq_ctrl) >> SEQNUM_SHIFT; - trace_brcms_txdesc(&wlc->hw->d11core->dev, txh, sizeof(*txh)); - if (tot_mpdu == 0) { mcs = plcp[0] & MIMO_PLCP_MCS_MASK; mimoantsel = le16_to_cpu(txh->ABI_MimoAntSel); @@ -954,10 +1012,10 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb, ack_recd = false; if (ba_recd) { bindex = MODSUB_POW2(seq, start_seq, SEQNUM_MAX); - brcms_dbg_ht(wlc->hw->d11core, - "tid %d seq %d, start_seq %d, bindex %d set %d, index %d\n", - tid, seq, start_seq, bindex, - isset(bitmap, bindex), index); + BCMMSG(wiphy, + "tid %d seq %d, start_seq %d, bindex %d set %d, index %d\n", + tid, seq, start_seq, bindex, + isset(bitmap, bindex), index); /* if acked then clear bit and free packet */ if ((bindex < AMPDU_TX_BA_MAX_WSIZE) && isset(bitmap, bindex)) { @@ -988,16 +1046,14 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb, /* either retransmit or send bar if ack not recd */ if (!ack_recd) { if (retry && (ini->txretry[index] < (int)retry_limit)) { - int ret; ini->txretry[index]++; ini->tx_in_transit--; - ret = brcms_c_txfifo(wlc, queue, p); /* - * We shouldn't be out of space in the DMA - * ring here since we're reinserting a frame - * that was just pulled out. + * Use high prededence for retransmit to + * give some punch */ - WARN_ONCE(ret, "queue %d out of txds\n", queue); + brcms_c_txq_enq(wlc, scb, p, + BRCMS_PRIO_TO_HI_PREC(tid)); } else { /* Retry timeout */ ini->tx_in_transit--; @@ -1008,9 +1064,9 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb, IEEE80211_TX_STAT_AMPDU_NO_BACK; skb_pull(p, D11_PHY_HDR_LEN); skb_pull(p, D11_TXH_LEN); - brcms_dbg_ht(wlc->hw->d11core, - "BA Timeout, seq %d, in_transit %d\n", - seq, ini->tx_in_transit); + BCMMSG(wiphy, + "BA Timeout, seq %d, in_transit %d\n", + seq, ini->tx_in_transit); ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw, p); } @@ -1024,9 +1080,12 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb, p = dma_getnexttxp(wlc->hw->di[queue], DMA_RANGE_TRANSMITTED); } + brcms_c_send_q(wlc); /* update rate state */ antselid = brcms_c_antsel_antsel2id(wlc->asi, mimoantsel); + + brcms_c_txfifo_complete(wlc, queue, ampdu->txpkt_weight); } void @@ -1074,8 +1133,6 @@ brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb, while (p) { tx_info = IEEE80211_SKB_CB(p); txh = (struct d11txh *) p->data; - trace_brcms_txdesc(&wlc->hw->d11core->dev, txh, - sizeof(*txh)); mcl = le16_to_cpu(txh->MacTxControlLow); brcmu_pkt_buf_free_skb(p); /* break out if last packet of ampdu */ @@ -1085,6 +1142,7 @@ brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb, p = dma_getnexttxp(wlc->hw->di[queue], DMA_RANGE_TRANSMITTED); } + brcms_c_txfifo_complete(wlc, queue, ampdu->txpkt_weight); } } @@ -1123,6 +1181,23 @@ void brcms_c_ampdu_shm_upd(struct ampdu_info *ampdu) } } +/* + * callback function that helps flushing ampdu packets from a priority queue + */ +static bool cb_del_ampdu_pkt(struct sk_buff *mpdu, void *arg_a) +{ + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(mpdu); + struct cb_del_ampdu_pars *ampdu_pars = + (struct cb_del_ampdu_pars *)arg_a; + bool rc; + + rc = tx_info->flags & IEEE80211_TX_CTL_AMPDU ? true : false; + rc = rc && (tx_info->rate_driver_data[0] == NULL || ampdu_pars->sta == NULL || + tx_info->rate_driver_data[0] == ampdu_pars->sta); + rc = rc && ((u8)(mpdu->priority) == ampdu_pars->tid); + return rc; +} + /* * callback function that helps invalidating ampdu packets in a DMA queue */ @@ -1143,5 +1218,15 @@ static void dma_cb_fn_ampdu(void *txi, void *arg_a) void brcms_c_ampdu_flush(struct brcms_c_info *wlc, struct ieee80211_sta *sta, u16 tid) { + struct brcms_txq_info *qi = wlc->pkt_queue; + struct pktq *pq = &qi->q; + int prec; + struct cb_del_ampdu_pars ampdu_pars; + + ampdu_pars.sta = sta; + ampdu_pars.tid = tid; + for (prec = 0; prec < pq->num_prec; prec++) + brcmu_pktq_pflush(pq, prec, true, cb_del_ampdu_pkt, + (void *)&du_pars); brcms_c_inval_dma_pkts(wlc->hw, sta, dma_cb_fn_ampdu); } diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/ampdu.h b/trunk/drivers/net/wireless/brcm80211/brcmsmac/ampdu.h index 73d01e586109..421f4ba7c63c 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/ampdu.h +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/ampdu.h @@ -17,34 +17,11 @@ #ifndef _BRCM_AMPDU_H_ #define _BRCM_AMPDU_H_ -/* - * Data structure representing an in-progress session for accumulating - * frames for AMPDU. - * - * wlc: pointer to common driver data - * skb_list: queue of skb's for AMPDU - * max_ampdu_len: maximum length for this AMPDU - * max_ampdu_frames: maximum number of frames for this AMPDU - * ampdu_len: total number of bytes accumulated for this AMPDU - * dma_len: DMA length of this AMPDU - */ -struct brcms_ampdu_session { - struct brcms_c_info *wlc; - struct sk_buff_head skb_list; - unsigned max_ampdu_len; - u16 max_ampdu_frames; - u16 ampdu_len; - u16 dma_len; -}; - -extern void brcms_c_ampdu_reset_session(struct brcms_ampdu_session *session, - struct brcms_c_info *wlc); -extern int brcms_c_ampdu_add_frame(struct brcms_ampdu_session *session, - struct sk_buff *p); -extern void brcms_c_ampdu_finalize(struct brcms_ampdu_session *session); - extern struct ampdu_info *brcms_c_ampdu_attach(struct brcms_c_info *wlc); extern void brcms_c_ampdu_detach(struct ampdu_info *ampdu); +extern int brcms_c_sendampdu(struct ampdu_info *ampdu, + struct brcms_txq_info *qi, + struct sk_buff **aggp, int prec); extern void brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb, struct sk_buff *p, struct tx_status *txs); extern void brcms_c_ampdu_macaddr_upd(struct brcms_c_info *wlc); diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/antsel.c b/trunk/drivers/net/wireless/brcm80211/brcmsmac/antsel.c index 54c616919590..55e12c327911 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/antsel.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/antsel.c @@ -21,7 +21,6 @@ #include "main.h" #include "phy_shim.h" #include "antsel.h" -#include "debug.h" #define ANT_SELCFG_AUTO 0x80 /* bit indicates antenna sel AUTO */ #define ANT_SELCFG_MASK 0x33 /* antenna configuration mask */ @@ -138,8 +137,7 @@ struct antsel_info *brcms_c_antsel_attach(struct brcms_c_info *wlc) asi->antsel_avail = false; } else { asi->antsel_avail = false; - brcms_err(wlc->hw->d11core, - "antsel_attach: 2o3 " + wiphy_err(wlc->wiphy, "antsel_attach: 2o3 " "board cfg invalid\n"); } diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.h b/trunk/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.h index 871781e6a713..27dd73eef56d 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.h +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.h @@ -14,29 +14,22 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM brcmsmac + #if !defined(__TRACE_BRCMSMAC_H) || defined(TRACE_HEADER_MULTI_READ) #define __TRACE_BRCMSMAC_H -#include -#include #include #include "mac80211_if.h" -#ifndef CONFIG_BRCM_TRACING +#ifndef CONFIG_BRCMDBG #undef TRACE_EVENT #define TRACE_EVENT(name, proto, ...) \ static inline void trace_ ## name(proto) {} -#undef DECLARE_EVENT_CLASS -#define DECLARE_EVENT_CLASS(...) -#undef DEFINE_EVENT -#define DEFINE_EVENT(evt_class, name, proto, ...) \ -static inline void trace_ ## name(proto) {} #endif -#undef TRACE_SYSTEM -#define TRACE_SYSTEM brcmsmac - /* * We define a tracepoint, its arguments, its printk format and its * 'fast binary record' layout. @@ -85,165 +78,9 @@ TRACE_EVENT(brcms_dpc, ) ); -TRACE_EVENT(brcms_macintstatus, - TP_PROTO(const struct device *dev, int in_isr, u32 macintstatus, - u32 mask), - TP_ARGS(dev, in_isr, macintstatus, mask), - TP_STRUCT__entry( - __string(dev, dev_name(dev)) - __field(int, in_isr) - __field(u32, macintstatus) - __field(u32, mask) - ), - TP_fast_assign( - __assign_str(dev, dev_name(dev)); - __entry->in_isr = in_isr; - __entry->macintstatus = macintstatus; - __entry->mask = mask; - ), - TP_printk("[%s] in_isr=%d macintstatus=%#x mask=%#x", __get_str(dev), - __entry->in_isr, __entry->macintstatus, __entry->mask) -); - -#undef TRACE_SYSTEM -#define TRACE_SYSTEM brcmsmac_tx - -TRACE_EVENT(brcms_txdesc, - TP_PROTO(const struct device *dev, - void *txh, size_t txh_len), - TP_ARGS(dev, txh, txh_len), - TP_STRUCT__entry( - __string(dev, dev_name(dev)) - __dynamic_array(u8, txh, txh_len) - ), - TP_fast_assign( - __assign_str(dev, dev_name(dev)); - memcpy(__get_dynamic_array(txh), txh, txh_len); - ), - TP_printk("[%s] txdesc", __get_str(dev)) -); - -TRACE_EVENT(brcms_txstatus, - TP_PROTO(const struct device *dev, u16 framelen, u16 frameid, - u16 status, u16 lasttxtime, u16 sequence, u16 phyerr, - u16 ackphyrxsh), - TP_ARGS(dev, framelen, frameid, status, lasttxtime, sequence, phyerr, - ackphyrxsh), - TP_STRUCT__entry( - __string(dev, dev_name(dev)) - __field(u16, framelen) - __field(u16, frameid) - __field(u16, status) - __field(u16, lasttxtime) - __field(u16, sequence) - __field(u16, phyerr) - __field(u16, ackphyrxsh) - ), - TP_fast_assign( - __assign_str(dev, dev_name(dev)); - __entry->framelen = framelen; - __entry->frameid = frameid; - __entry->status = status; - __entry->lasttxtime = lasttxtime; - __entry->sequence = sequence; - __entry->phyerr = phyerr; - __entry->ackphyrxsh = ackphyrxsh; - ), - TP_printk("[%s] FrameId %#04x TxStatus %#04x LastTxTime %#04x " - "Seq %#04x PHYTxStatus %#04x RxAck %#04x", - __get_str(dev), __entry->frameid, __entry->status, - __entry->lasttxtime, __entry->sequence, __entry->phyerr, - __entry->ackphyrxsh) -); - -TRACE_EVENT(brcms_ampdu_session, - TP_PROTO(const struct device *dev, unsigned max_ampdu_len, - u16 max_ampdu_frames, u16 ampdu_len, u16 ampdu_frames, - u16 dma_len), - TP_ARGS(dev, max_ampdu_len, max_ampdu_frames, ampdu_len, ampdu_frames, - dma_len), - TP_STRUCT__entry( - __string(dev, dev_name(dev)) - __field(unsigned, max_ampdu_len) - __field(u16, max_ampdu_frames) - __field(u16, ampdu_len) - __field(u16, ampdu_frames) - __field(u16, dma_len) - ), - TP_fast_assign( - __assign_str(dev, dev_name(dev)); - __entry->max_ampdu_len = max_ampdu_len; - __entry->max_ampdu_frames = max_ampdu_frames; - __entry->ampdu_len = ampdu_len; - __entry->ampdu_frames = ampdu_frames; - __entry->dma_len = dma_len; - ), - TP_printk("[%s] ampdu session max_len=%u max_frames=%u len=%u frames=%u dma_len=%u", - __get_str(dev), __entry->max_ampdu_len, - __entry->max_ampdu_frames, __entry->ampdu_len, - __entry->ampdu_frames, __entry->dma_len) -); - -#undef TRACE_SYSTEM -#define TRACE_SYSTEM brcmsmac_msg - -#define MAX_MSG_LEN 100 - -DECLARE_EVENT_CLASS(brcms_msg_event, - TP_PROTO(struct va_format *vaf), - TP_ARGS(vaf), - TP_STRUCT__entry( - __dynamic_array(char, msg, MAX_MSG_LEN) - ), - TP_fast_assign( - WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg), - MAX_MSG_LEN, vaf->fmt, - *vaf->va) >= MAX_MSG_LEN); - ), - TP_printk("%s", __get_str(msg)) -); - -DEFINE_EVENT(brcms_msg_event, brcms_info, - TP_PROTO(struct va_format *vaf), - TP_ARGS(vaf) -); - -DEFINE_EVENT(brcms_msg_event, brcms_warn, - TP_PROTO(struct va_format *vaf), - TP_ARGS(vaf) -); - -DEFINE_EVENT(brcms_msg_event, brcms_err, - TP_PROTO(struct va_format *vaf), - TP_ARGS(vaf) -); - -DEFINE_EVENT(brcms_msg_event, brcms_crit, - TP_PROTO(struct va_format *vaf), - TP_ARGS(vaf) -); - -TRACE_EVENT(brcms_dbg, - TP_PROTO(u32 level, const char *func, struct va_format *vaf), - TP_ARGS(level, func, vaf), - TP_STRUCT__entry( - __field(u32, level) - __string(func, func) - __dynamic_array(char, msg, MAX_MSG_LEN) - ), - TP_fast_assign( - __entry->level = level; - __assign_str(func, func); - WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg), - MAX_MSG_LEN, vaf->fmt, - *vaf->va) >= MAX_MSG_LEN); - ), - TP_printk("%s: %s", __get_str(func), __get_str(msg)) -); - #endif /* __TRACE_BRCMSMAC_H */ -#ifdef CONFIG_BRCM_TRACING +#ifdef CONFIG_BRCMDBG #undef TRACE_INCLUDE_PATH #define TRACE_INCLUDE_PATH . @@ -252,4 +89,4 @@ TRACE_EVENT(brcms_dbg, #include -#endif /* CONFIG_BRCM_TRACING */ +#endif /* CONFIG_BRCMDBG */ diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/channel.c b/trunk/drivers/net/wireless/brcm80211/brcmsmac/channel.c index a90b72202ec5..64a48f06d68b 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/channel.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/channel.c @@ -26,7 +26,6 @@ #include "stf.h" #include "channel.h" #include "mac80211_if.h" -#include "debug.h" /* QDB() macro takes a dB value and converts to a quarter dB value */ #define QDB(n) ((n) * BRCMS_TXPWR_DB_FACTOR) @@ -337,6 +336,8 @@ struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc) const char *ccode = sprom->alpha2; int ccode_len = sizeof(sprom->alpha2); + BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); + wlc_cm = kzalloc(sizeof(struct brcms_cm_info), GFP_ATOMIC); if (wlc_cm == NULL) return NULL; @@ -614,8 +615,8 @@ brcms_c_valid_chanspec_ext(struct brcms_cm_info *wlc_cm, u16 chspec) /* check the chanspec */ if (brcms_c_chspec_malformed(chspec)) { - brcms_err(wlc->hw->d11core, "wl%d: malformed chanspec 0x%x\n", - wlc->pub->unit, chspec); + wiphy_err(wlc->wiphy, "wl%d: malformed chanspec 0x%x\n", + wlc->pub->unit, chspec); return false; } @@ -737,8 +738,7 @@ static int brcms_reg_notifier(struct wiphy *wiphy, mboolclr(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE); } else { mboolset(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE); - brcms_err(wlc->hw->d11core, - "wl%d: %s: no valid channel for \"%s\"\n", + wiphy_err(wlc->wiphy, "wl%d: %s: no valid channel for \"%s\"\n", wlc->pub->unit, __func__, request->alpha2); } diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/debug.c b/trunk/drivers/net/wireless/brcm80211/brcmsmac/debug.c deleted file mode 100644 index be84791857cb..000000000000 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/debug.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (c) 2012 Broadcom Corporation - * Copyright (c) 2012 Canonical Ltd. - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include "types.h" -#include "main.h" -#include "debug.h" -#include "brcms_trace_events.h" - -static struct dentry *root_folder; - -void brcms_debugfs_init(void) -{ - root_folder = debugfs_create_dir(KBUILD_MODNAME, NULL); - if (IS_ERR(root_folder)) - root_folder = NULL; -} - -void brcms_debugfs_exit(void) -{ - if (!root_folder) - return; - - debugfs_remove_recursive(root_folder); - root_folder = NULL; -} - -int brcms_debugfs_attach(struct brcms_pub *drvr) -{ - if (!root_folder) - return -ENODEV; - - drvr->dbgfs_dir = debugfs_create_dir( - dev_name(&drvr->wlc->hw->d11core->dev), root_folder); - return PTR_RET(drvr->dbgfs_dir); -} - -void brcms_debugfs_detach(struct brcms_pub *drvr) -{ - if (!IS_ERR_OR_NULL(drvr->dbgfs_dir)) - debugfs_remove_recursive(drvr->dbgfs_dir); -} - -struct dentry *brcms_debugfs_get_devdir(struct brcms_pub *drvr) -{ - return drvr->dbgfs_dir; -} - -static -ssize_t brcms_debugfs_hardware_read(struct file *f, char __user *data, - size_t count, loff_t *ppos) -{ - char buf[128]; - int res; - struct brcms_pub *drvr = f->private_data; - - /* only allow read from start */ - if (*ppos > 0) - return 0; - - res = scnprintf(buf, sizeof(buf), - "board vendor: %x\n" - "board type: %x\n" - "board revision: %x\n" - "board flags: %x\n" - "board flags2: %x\n" - "firmware revision: %x\n", - drvr->wlc->hw->d11core->bus->boardinfo.vendor, - drvr->wlc->hw->d11core->bus->boardinfo.type, - drvr->wlc->hw->boardrev, - drvr->wlc->hw->boardflags, - drvr->wlc->hw->boardflags2, - drvr->wlc->ucode_rev - ); - - return simple_read_from_buffer(data, count, ppos, buf, res); -} - -static const struct file_operations brcms_debugfs_hardware_ops = { - .owner = THIS_MODULE, - .open = simple_open, - .read = brcms_debugfs_hardware_read -}; - -void brcms_debugfs_create_files(struct brcms_pub *drvr) -{ - struct dentry *dentry = drvr->dbgfs_dir; - - if (!IS_ERR_OR_NULL(dentry)) - debugfs_create_file("hardware", S_IRUGO, dentry, - drvr, &brcms_debugfs_hardware_ops); -} - -#define __brcms_fn(fn) \ -void __brcms_ ##fn(struct device *dev, const char *fmt, ...) \ -{ \ - struct va_format vaf = { \ - .fmt = fmt, \ - }; \ - va_list args; \ - \ - va_start(args, fmt); \ - vaf.va = &args; \ - dev_ ##fn(dev, "%pV", &vaf); \ - trace_brcms_ ##fn(&vaf); \ - va_end(args); \ -} - -__brcms_fn(info) -__brcms_fn(warn) -__brcms_fn(err) -__brcms_fn(crit) - -#if defined(CONFIG_BRCMDBG) || defined(CONFIG_BRCM_TRACING) -void __brcms_dbg(struct device *dev, u32 level, const char *func, - const char *fmt, ...) -{ - struct va_format vaf = { - .fmt = fmt, - }; - va_list args; - - va_start(args, fmt); - vaf.va = &args; -#ifdef CONFIG_BRCMDBG - if ((brcm_msg_level & level) && net_ratelimit()) - dev_err(dev, "%s %pV", func, &vaf); -#endif - trace_brcms_dbg(level, func, &vaf); - va_end(args); -} -#endif diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/debug.h b/trunk/drivers/net/wireless/brcm80211/brcmsmac/debug.h deleted file mode 100644 index 796836b0f469..000000000000 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/debug.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2012 Broadcom Corporation - * - * 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. - */ -#ifndef _BRCMS_DEBUG_H_ -#define _BRCMS_DEBUG_H_ - -#include -#include -#include -#include -#include "main.h" -#include "mac80211_if.h" - -__printf(2, 3) -void __brcms_info(struct device *dev, const char *fmt, ...); -__printf(2, 3) -void __brcms_warn(struct device *dev, const char *fmt, ...); -__printf(2, 3) -void __brcms_err(struct device *dev, const char *fmt, ...); -__printf(2, 3) -void __brcms_crit(struct device *dev, const char *fmt, ...); - -#if defined(CONFIG_BRCMDBG) || defined(CONFIG_BRCM_TRACING) -__printf(4, 5) -void __brcms_dbg(struct device *dev, u32 level, const char *func, - const char *fmt, ...); -#else -static inline __printf(4, 5) -void __brcms_dbg(struct device *dev, u32 level, const char *func, - const char *fmt, ...) -{ -} -#endif - -/* - * Debug macros cannot be used when wlc is uninitialized. Generally - * this means any code that could run before brcms_c_attach() has - * returned successfully probably shouldn't use the following macros. - */ - -#define brcms_dbg(core, l, f, a...) __brcms_dbg(&(core)->dev, l, __func__, f, ##a) -#define brcms_info(core, f, a...) __brcms_info(&(core)->dev, f, ##a) -#define brcms_warn(core, f, a...) __brcms_warn(&(core)->dev, f, ##a) -#define brcms_err(core, f, a...) __brcms_err(&(core)->dev, f, ##a) -#define brcms_crit(core, f, a...) __brcms_crit(&(core)->dev, f, ##a) - -#define brcms_dbg_info(core, f, a...) brcms_dbg(core, BRCM_DL_INFO, f, ##a) -#define brcms_dbg_mac80211(core, f, a...) brcms_dbg(core, BRCM_DL_MAC80211, f, ##a) -#define brcms_dbg_rx(core, f, a...) brcms_dbg(core, BRCM_DL_RX, f, ##a) -#define brcms_dbg_tx(core, f, a...) brcms_dbg(core, BRCM_DL_TX, f, ##a) -#define brcms_dbg_int(core, f, a...) brcms_dbg(core, BRCM_DL_INT, f, ##a) -#define brcms_dbg_dma(core, f, a...) brcms_dbg(core, BRCM_DL_DMA, f, ##a) -#define brcms_dbg_ht(core, f, a...) brcms_dbg(core, BRCM_DL_HT, f, ##a) - -struct brcms_pub; -void brcms_debugfs_init(void); -void brcms_debugfs_exit(void); -int brcms_debugfs_attach(struct brcms_pub *drvr); -void brcms_debugfs_detach(struct brcms_pub *drvr); -struct dentry *brcms_debugfs_get_devdir(struct brcms_pub *drvr); -void brcms_debugfs_create_files(struct brcms_pub *drvr); - -#endif /* _BRCMS_DEBUG_H_ */ diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/dma.c b/trunk/drivers/net/wireless/brcm80211/brcmsmac/dma.c index 1860c572b3c4..5e53305bd9a9 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/dma.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/dma.c @@ -14,22 +14,17 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include -#include -#include #include #include #include "types.h" -#include "main.h" #include "dma.h" #include "soc.h" -#include "scb.h" -#include "ampdu.h" -#include "debug.h" -#include "brcms_trace_events.h" /* * dma register field offset calculation @@ -181,6 +176,28 @@ #define BCMEXTRAHDROOM 172 +/* debug/trace */ +#ifdef DEBUG +#define DMA_ERROR(fmt, ...) \ +do { \ + if (*di->msg_level & 1) \ + pr_debug("%s: " fmt, __func__, ##__VA_ARGS__); \ +} while (0) +#define DMA_TRACE(fmt, ...) \ +do { \ + if (*di->msg_level & 2) \ + pr_debug("%s: " fmt, __func__, ##__VA_ARGS__); \ +} while (0) +#else +#define DMA_ERROR(fmt, ...) \ + no_printk(fmt, ##__VA_ARGS__) +#define DMA_TRACE(fmt, ...) \ + no_printk(fmt, ##__VA_ARGS__) +#endif /* DEBUG */ + +#define DMA_NONE(fmt, ...) \ + no_printk(fmt, ##__VA_ARGS__) + #define MAXNAMEL 8 /* 8 char names */ /* macros to convert between byte offsets and indexes */ @@ -207,14 +224,12 @@ struct dma64desc { /* dma engine software state */ struct dma_info { struct dma_pub dma; /* exported structure */ + uint *msg_level; /* message level pointer */ char name[MAXNAMEL]; /* callers name for diag msgs */ struct bcma_device *core; struct device *dmadev; - /* session information for AMPDU */ - struct brcms_ampdu_session ampdu_session; - bool dma64; /* this dma engine is operating in 64-bit mode */ bool addrext; /* this dma engine supports DmaExtendedAddrChanges */ @@ -283,6 +298,12 @@ struct dma_info { bool aligndesc_4k; }; +/* + * default dma message level (if input msg_level + * pointer is null in dma_attach()) + */ +static uint dma_msg_level; + /* Check for odd number of 1's */ static u32 parity32(__le32 data) { @@ -332,7 +353,7 @@ static uint prevtxd(struct dma_info *di, uint i) static uint nextrxd(struct dma_info *di, uint i) { - return rxd(di, i + 1); + return txd(di, i + 1); } static uint ntxdactive(struct dma_info *di, uint h, uint t) @@ -349,8 +370,10 @@ static uint _dma_ctrlflags(struct dma_info *di, uint mask, uint flags) { uint dmactrlflags; - if (di == NULL) + if (di == NULL) { + DMA_ERROR("NULL dma handle\n"); return 0; + } dmactrlflags = di->dma.dmactrlflags; dmactrlflags &= ~mask; @@ -400,15 +423,13 @@ static bool _dma_isaddrext(struct dma_info *di) /* not all tx or rx channel are available */ if (di->d64txregbase != 0) { if (!_dma64_addrext(di, DMA64TXREGOFFS(di, control))) - brcms_dbg_dma(di->core, - "%s: DMA64 tx doesn't have AE set\n", - di->name); + DMA_ERROR("%s: DMA64 tx doesn't have AE set\n", + di->name); return true; } else if (di->d64rxregbase != 0) { if (!_dma64_addrext(di, DMA64RXREGOFFS(di, control))) - brcms_dbg_dma(di->core, - "%s: DMA64 rx doesn't have AE set\n", - di->name); + DMA_ERROR("%s: DMA64 rx doesn't have AE set\n", + di->name); return true; } @@ -509,9 +530,8 @@ static bool dma64_alloc(struct dma_info *di, uint direction) va = dma_ringalloc(di, D64RINGALIGN, size, &align_bits, &alloced, &di->txdpaorig); if (va == NULL) { - brcms_dbg_dma(di->core, - "%s: DMA_ALLOC_CONSISTENT(ntxd) failed\n", - di->name); + DMA_ERROR("%s: DMA_ALLOC_CONSISTENT(ntxd) failed\n", + di->name); return false; } align = (1 << align_bits); @@ -524,9 +544,8 @@ static bool dma64_alloc(struct dma_info *di, uint direction) va = dma_ringalloc(di, D64RINGALIGN, size, &align_bits, &alloced, &di->rxdpaorig); if (va == NULL) { - brcms_dbg_dma(di->core, - "%s: DMA_ALLOC_CONSISTENT(nrxd) failed\n", - di->name); + DMA_ERROR("%s: DMA_ALLOC_CONSISTENT(nrxd) failed\n", + di->name); return false; } align = (1 << align_bits); @@ -545,13 +564,12 @@ static bool _dma_alloc(struct dma_info *di, uint direction) return dma64_alloc(di, direction); } -struct dma_pub *dma_attach(char *name, struct brcms_c_info *wlc, +struct dma_pub *dma_attach(char *name, struct si_pub *sih, + struct bcma_device *core, uint txregbase, uint rxregbase, uint ntxd, uint nrxd, uint rxbufsize, int rxextheadroom, - uint nrxpost, uint rxoffset) + uint nrxpost, uint rxoffset, uint *msg_level) { - struct si_pub *sih = wlc->hw->sih; - struct bcma_device *core = wlc->hw->d11core; struct dma_info *di; u8 rev = core->id.rev; uint size; @@ -562,6 +580,9 @@ struct dma_pub *dma_attach(char *name, struct brcms_c_info *wlc, if (di == NULL) return NULL; + di->msg_level = msg_level ? msg_level : &dma_msg_level; + + di->dma64 = ((bcma_aread32(core, BCMA_IOST) & SISF_DMA64) == SISF_DMA64); @@ -577,11 +598,11 @@ struct dma_pub *dma_attach(char *name, struct brcms_c_info *wlc, */ _dma_ctrlflags(di, DMA_CTRL_ROC | DMA_CTRL_PEN, 0); - brcms_dbg_dma(di->core, "%s: %s flags 0x%x ntxd %d nrxd %d " - "rxbufsize %d rxextheadroom %d nrxpost %d rxoffset %d " - "txregbase %u rxregbase %u\n", name, "DMA64", - di->dma.dmactrlflags, ntxd, nrxd, rxbufsize, - rxextheadroom, nrxpost, rxoffset, txregbase, rxregbase); + DMA_TRACE("%s: %s flags 0x%x ntxd %d nrxd %d " + "rxbufsize %d rxextheadroom %d nrxpost %d rxoffset %d " + "txregbase %u rxregbase %u\n", name, "DMA64", + di->dma.dmactrlflags, ntxd, nrxd, rxbufsize, + rxextheadroom, nrxpost, rxoffset, txregbase, rxregbase); /* make a private copy of our callers name */ strncpy(di->name, name, MAXNAMEL); @@ -643,8 +664,8 @@ struct dma_pub *dma_attach(char *name, struct brcms_c_info *wlc, di->dmadesc_align = 4; /* 16 byte alignment */ } - brcms_dbg_dma(di->core, "DMA descriptor align_needed %d, align %d\n", - di->aligndesc_4k, di->dmadesc_align); + DMA_NONE("DMA descriptor align_needed %d, align %d\n", + di->aligndesc_4k, di->dmadesc_align); /* allocate tx packet pointer vector */ if (ntxd) { @@ -682,27 +703,21 @@ struct dma_pub *dma_attach(char *name, struct brcms_c_info *wlc, if ((di->ddoffsetlow != 0) && !di->addrext) { if (di->txdpa > SI_PCI_DMA_SZ) { - brcms_dbg_dma(di->core, - "%s: txdpa 0x%x: addrext not supported\n", - di->name, (u32)di->txdpa); + DMA_ERROR("%s: txdpa 0x%x: addrext not supported\n", + di->name, (u32)di->txdpa); goto fail; } if (di->rxdpa > SI_PCI_DMA_SZ) { - brcms_dbg_dma(di->core, - "%s: rxdpa 0x%x: addrext not supported\n", - di->name, (u32)di->rxdpa); + DMA_ERROR("%s: rxdpa 0x%x: addrext not supported\n", + di->name, (u32)di->rxdpa); goto fail; } } - /* Initialize AMPDU session */ - brcms_c_ampdu_reset_session(&di->ampdu_session, wlc); - - brcms_dbg_dma(di->core, - "ddoffsetlow 0x%x ddoffsethigh 0x%x dataoffsetlow 0x%x dataoffsethigh 0x%x addrext %d\n", - di->ddoffsetlow, di->ddoffsethigh, - di->dataoffsetlow, di->dataoffsethigh, - di->addrext); + DMA_TRACE("ddoffsetlow 0x%x ddoffsethigh 0x%x dataoffsetlow 0x%x dataoffsethigh 0x%x addrext %d\n", + di->ddoffsetlow, di->ddoffsethigh, + di->dataoffsetlow, di->dataoffsethigh, + di->addrext); return (struct dma_pub *) di; @@ -748,7 +763,7 @@ void dma_detach(struct dma_pub *pub) { struct dma_info *di = (struct dma_info *)pub; - brcms_dbg_dma(di->core, "%s:\n", di->name); + DMA_TRACE("%s:\n", di->name); /* free dma descriptor rings */ if (di->txd64) @@ -824,7 +839,7 @@ static void _dma_rxenable(struct dma_info *di) uint dmactrlflags = di->dma.dmactrlflags; u32 control; - brcms_dbg_dma(di->core, "%s:\n", di->name); + DMA_TRACE("%s:\n", di->name); control = D64_RC_RE | (bcma_read32(di->core, DMA64RXREGOFFS(di, control)) & @@ -844,7 +859,7 @@ void dma_rxinit(struct dma_pub *pub) { struct dma_info *di = (struct dma_info *)pub; - brcms_dbg_dma(di->core, "%s:\n", di->name); + DMA_TRACE("%s:\n", di->name); if (di->nrxd == 0) return; @@ -939,7 +954,7 @@ int dma_rx(struct dma_pub *pub, struct sk_buff_head *skb_list) return 0; len = le16_to_cpu(*(__le16 *) (p->data)); - brcms_dbg_dma(di->core, "%s: dma_rx len %d\n", di->name, len); + DMA_TRACE("%s: dma_rx len %d\n", di->name, len); dma_spin_for_len(len, p); /* set actual length */ @@ -966,15 +981,14 @@ int dma_rx(struct dma_pub *pub, struct sk_buff_head *skb_list) DMA64RXREGOFFS(di, status0)) & D64_RS0_CD_MASK) - di->rcvptrbase) & D64_RS0_CD_MASK, struct dma64desc); - brcms_dbg_dma(di->core, - "rxin %d rxout %d, hw_curr %d\n", - di->rxin, di->rxout, cur); + DMA_ERROR("rxin %d rxout %d, hw_curr %d\n", + di->rxin, di->rxout, cur); } #endif /* DEBUG */ if ((di->dma.dmactrlflags & DMA_CTRL_RXMULTI) == 0) { - brcms_dbg_dma(di->core, "%s: bad frame length (%d)\n", - di->name, len); + DMA_ERROR("%s: bad frame length (%d)\n", + di->name, len); skb_queue_walk_safe(&dma_frames, p, next) { skb_unlink(p, &dma_frames); brcmu_pkt_buf_free_skb(p); @@ -991,7 +1005,7 @@ int dma_rx(struct dma_pub *pub, struct sk_buff_head *skb_list) static bool dma64_rxidle(struct dma_info *di) { - brcms_dbg_dma(di->core, "%s:\n", di->name); + DMA_TRACE("%s:\n", di->name); if (di->nrxd == 0) return true; @@ -1002,17 +1016,6 @@ static bool dma64_rxidle(struct dma_info *di) D64_RS0_CD_MASK)); } -static bool dma64_txidle(struct dma_info *di) -{ - if (di->ntxd == 0) - return true; - - return ((bcma_read32(di->core, - DMA64TXREGOFFS(di, status0)) & D64_XS0_CD_MASK) == - (bcma_read32(di->core, DMA64TXREGOFFS(di, ptr)) & - D64_XS0_CD_MASK)); -} - /* * post receive buffers * return false is refill failed completely and ring is empty this will stall @@ -1044,7 +1047,7 @@ bool dma_rxfill(struct dma_pub *pub) n = di->nrxpost - nrxdactive(di, rxin, rxout); - brcms_dbg_dma(di->core, "%s: post %d\n", di->name, n); + DMA_TRACE("%s: post %d\n", di->name, n); if (di->rxbufsize > BCMEXTRAHDROOM) extra_offset = di->rxextrahdrroom; @@ -1057,11 +1060,9 @@ bool dma_rxfill(struct dma_pub *pub) p = brcmu_pkt_buf_get_skb(di->rxbufsize + extra_offset); if (p == NULL) { - brcms_dbg_dma(di->core, "%s: out of rxbufs\n", - di->name); + DMA_ERROR("%s: out of rxbufs\n", di->name); if (i == 0 && dma64_rxidle(di)) { - brcms_dbg_dma(di->core, "%s: ring is empty !\n", - di->name); + DMA_ERROR("%s: ring is empty !\n", di->name); ring_empty = true; } di->dma.rxnobuf++; @@ -1106,7 +1107,7 @@ void dma_rxreclaim(struct dma_pub *pub) struct dma_info *di = (struct dma_info *)pub; struct sk_buff *p; - brcms_dbg_dma(di->core, "%s:\n", di->name); + DMA_TRACE("%s:\n", di->name); while ((p = _dma_getnextrxp(di, true))) brcmu_pkt_buf_free_skb(p); @@ -1137,7 +1138,7 @@ void dma_txinit(struct dma_pub *pub) struct dma_info *di = (struct dma_info *)pub; u32 control = D64_XC_XE; - brcms_dbg_dma(di->core, "%s:\n", di->name); + DMA_TRACE("%s:\n", di->name); if (di->ntxd == 0) return; @@ -1169,7 +1170,7 @@ void dma_txsuspend(struct dma_pub *pub) { struct dma_info *di = (struct dma_info *)pub; - brcms_dbg_dma(di->core, "%s:\n", di->name); + DMA_TRACE("%s:\n", di->name); if (di->ntxd == 0) return; @@ -1181,7 +1182,7 @@ void dma_txresume(struct dma_pub *pub) { struct dma_info *di = (struct dma_info *)pub; - brcms_dbg_dma(di->core, "%s:\n", di->name); + DMA_TRACE("%s:\n", di->name); if (di->ntxd == 0) return; @@ -1204,11 +1205,11 @@ void dma_txreclaim(struct dma_pub *pub, enum txd_range range) struct dma_info *di = (struct dma_info *)pub; struct sk_buff *p; - brcms_dbg_dma(di->core, "%s: %s\n", - di->name, - range == DMA_RANGE_ALL ? "all" : - range == DMA_RANGE_TRANSMITTED ? "transmitted" : - "transferred"); + DMA_TRACE("%s: %s\n", + di->name, + range == DMA_RANGE_ALL ? "all" : + range == DMA_RANGE_TRANSMITTED ? "transmitted" : + "transferred"); if (di->txin == di->txout) return; @@ -1263,18 +1264,24 @@ bool dma_rxreset(struct dma_pub *pub) return status == D64_RS0_RS_DISABLED; } -static void dma_txenq(struct dma_info *di, struct sk_buff *p) +/* + * !! tx entry routine + * WARNING: call must check the return value for error. + * the error(toss frames) could be fatal and cause many subsequent hard + * to debug problems + */ +int dma_txfast(struct dma_pub *pub, struct sk_buff *p, bool commit) { + struct dma_info *di = (struct dma_info *)pub; unsigned char *data; uint len; u16 txout; u32 flags = 0; dma_addr_t pa; - txout = di->txout; + DMA_TRACE("%s:\n", di->name); - if (WARN_ON(nexttxd(di, txout) == di->txin)) - return; + txout = di->txout; /* * obtain and initialize transmit descriptor entry. @@ -1282,6 +1289,14 @@ static void dma_txenq(struct dma_info *di, struct sk_buff *p) data = p->data; len = p->len; + /* no use to transmit a zero length packet */ + if (len == 0) + return 0; + + /* return nonzero if out of tx descriptors */ + if (nexttxd(di, txout) == di->txin) + goto outoftxd; + /* get physical address of buffer start */ pa = dma_map_single(di->dmadev, data, len, DMA_TO_DEVICE); @@ -1303,147 +1318,23 @@ static void dma_txenq(struct dma_info *di, struct sk_buff *p) /* bump the tx descriptor index */ di->txout = txout; -} - -static void ampdu_finalize(struct dma_info *di) -{ - struct brcms_ampdu_session *session = &di->ampdu_session; - struct sk_buff *p; - - trace_brcms_ampdu_session(&session->wlc->hw->d11core->dev, - session->max_ampdu_len, - session->max_ampdu_frames, - session->ampdu_len, - skb_queue_len(&session->skb_list), - session->dma_len); - - if (WARN_ON(skb_queue_empty(&session->skb_list))) - return; - - brcms_c_ampdu_finalize(session); - - while (!skb_queue_empty(&session->skb_list)) { - p = skb_dequeue(&session->skb_list); - dma_txenq(di, p); - } - - bcma_write32(di->core, DMA64TXREGOFFS(di, ptr), - di->xmtptrbase + I2B(di->txout, struct dma64desc)); - brcms_c_ampdu_reset_session(session, session->wlc); -} - -static void prep_ampdu_frame(struct dma_info *di, struct sk_buff *p) -{ - struct brcms_ampdu_session *session = &di->ampdu_session; - int ret; - - ret = brcms_c_ampdu_add_frame(session, p); - if (ret == -ENOSPC) { - /* - * AMPDU cannot accomodate this frame. Close out the in- - * progress AMPDU session and start a new one. - */ - ampdu_finalize(di); - ret = brcms_c_ampdu_add_frame(session, p); - } - - WARN_ON(ret); -} - -/* Update count of available tx descriptors based on current DMA state */ -static void dma_update_txavail(struct dma_info *di) -{ - /* - * Available space is number of descriptors less the number of - * active descriptors and the number of queued AMPDU frames. - */ - di->dma.txavail = di->ntxd - ntxdactive(di, di->txin, di->txout) - - skb_queue_len(&di->ampdu_session.skb_list) - 1; -} - -/* - * !! tx entry routine - * WARNING: call must check the return value for error. - * the error(toss frames) could be fatal and cause many subsequent hard - * to debug problems - */ -int dma_txfast(struct brcms_c_info *wlc, struct dma_pub *pub, - struct sk_buff *p) -{ - struct dma_info *di = (struct dma_info *)pub; - struct brcms_ampdu_session *session = &di->ampdu_session; - struct ieee80211_tx_info *tx_info; - bool is_ampdu; - - /* no use to transmit a zero length packet */ - if (p->len == 0) - return 0; - - /* return nonzero if out of tx descriptors */ - if (di->dma.txavail == 0 || nexttxd(di, di->txout) == di->txin) - goto outoftxd; - - tx_info = IEEE80211_SKB_CB(p); - is_ampdu = tx_info->flags & IEEE80211_TX_CTL_AMPDU; - if (is_ampdu) - prep_ampdu_frame(di, p); - else - dma_txenq(di, p); - - /* tx flow control */ - dma_update_txavail(di); /* kick the chip */ - if (is_ampdu) { - /* - * Start sending data if we've got a full AMPDU, there's - * no more space in the DMA ring, or the ring isn't - * currently transmitting. - */ - if (skb_queue_len(&session->skb_list) == session->max_ampdu_frames || - di->dma.txavail == 0 || dma64_txidle(di)) - ampdu_finalize(di); - } else { + if (commit) bcma_write32(di->core, DMA64TXREGOFFS(di, ptr), - di->xmtptrbase + I2B(di->txout, struct dma64desc)); - } + di->xmtptrbase + I2B(txout, struct dma64desc)); + + /* tx flow control */ + di->dma.txavail = di->ntxd - ntxdactive(di, di->txin, di->txout) - 1; return 0; outoftxd: - brcms_dbg_dma(di->core, "%s: out of txds !!!\n", di->name); + DMA_ERROR("%s: out of txds !!!\n", di->name); brcmu_pkt_buf_free_skb(p); di->dma.txavail = 0; di->dma.txnobuf++; - return -ENOSPC; -} - -void dma_txflush(struct dma_pub *pub) -{ - struct dma_info *di = (struct dma_info *)pub; - struct brcms_ampdu_session *session = &di->ampdu_session; - - if (!skb_queue_empty(&session->skb_list)) - ampdu_finalize(di); -} - -int dma_txpending(struct dma_pub *pub) -{ - struct dma_info *di = (struct dma_info *)pub; - return ntxdactive(di, di->txin, di->txout); -} - -/* - * If we have an active AMPDU session and are not transmitting, - * this function will force tx to start. - */ -void dma_kick_tx(struct dma_pub *pub) -{ - struct dma_info *di = (struct dma_info *)pub; - struct brcms_ampdu_session *session = &di->ampdu_session; - - if (!skb_queue_empty(&session->skb_list) && dma64_txidle(di)) - ampdu_finalize(di); + return -1; } /* @@ -1463,11 +1354,11 @@ struct sk_buff *dma_getnexttxp(struct dma_pub *pub, enum txd_range range) u16 active_desc; struct sk_buff *txp; - brcms_dbg_dma(di->core, "%s: %s\n", - di->name, - range == DMA_RANGE_ALL ? "all" : - range == DMA_RANGE_TRANSMITTED ? "transmitted" : - "transferred"); + DMA_TRACE("%s: %s\n", + di->name, + range == DMA_RANGE_ALL ? "all" : + range == DMA_RANGE_TRANSMITTED ? "transmitted" : + "transferred"); if (di->ntxd == 0) return NULL; @@ -1521,13 +1412,13 @@ struct sk_buff *dma_getnexttxp(struct dma_pub *pub, enum txd_range range) di->txin = i; /* tx flow control */ - dma_update_txavail(di); + di->dma.txavail = di->ntxd - ntxdactive(di, di->txin, di->txout) - 1; return txp; bogus: - brcms_dbg_dma(di->core, "bogus curr: start %d end %d txout %d\n", - start, end, di->txout); + DMA_NONE("bogus curr: start %d end %d txout %d\n", + start, end, di->txout); return NULL; } diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/dma.h b/trunk/drivers/net/wireless/brcm80211/brcmsmac/dma.h index ff5b80b09046..cc269ee5c499 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/dma.h +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/dma.h @@ -74,11 +74,12 @@ struct dma_pub { uint txnobuf; /* tx out of dma descriptors */ }; -extern struct dma_pub *dma_attach(char *name, struct brcms_c_info *wlc, +extern struct dma_pub *dma_attach(char *name, struct si_pub *sih, + struct bcma_device *d11core, uint txregbase, uint rxregbase, uint ntxd, uint nrxd, uint rxbufsize, int rxextheadroom, - uint nrxpost, uint rxoffset); + uint nrxpost, uint rxoffset, uint *msg_level); void dma_rxinit(struct dma_pub *pub); int dma_rx(struct dma_pub *pub, struct sk_buff_head *skb_list); @@ -86,11 +87,7 @@ bool dma_rxfill(struct dma_pub *pub); bool dma_rxreset(struct dma_pub *pub); bool dma_txreset(struct dma_pub *pub); void dma_txinit(struct dma_pub *pub); -int dma_txfast(struct brcms_c_info *wlc, struct dma_pub *pub, - struct sk_buff *p0); -void dma_txflush(struct dma_pub *pub); -int dma_txpending(struct dma_pub *pub); -void dma_kick_tx(struct dma_pub *pub); +int dma_txfast(struct dma_pub *pub, struct sk_buff *p0, bool commit); void dma_txsuspend(struct dma_pub *pub); bool dma_txsuspended(struct dma_pub *pub); void dma_txresume(struct dma_pub *pub); diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/trunk/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index 85dbaf8ac997..a744ea5a9559 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c @@ -33,7 +33,6 @@ #include "ucode_loader.h" #include "mac80211_if.h" #include "main.h" -#include "debug.h" #define N_TX_QUEUES 4 /* #tx queues on mac80211<->driver interface */ @@ -99,14 +98,10 @@ static struct bcma_device_id brcms_coreid_table[] = { }; MODULE_DEVICE_TABLE(bcma, brcms_coreid_table); -#if defined(CONFIG_BRCMDBG) -/* - * Module parameter for setting the debug message level. Available - * flags are specified by the BRCM_DL_* macros in - * drivers/net/wireless/brcm80211/include/defs.h. - */ -module_param_named(debug, brcm_msg_level, uint, S_IRUGO | S_IWUSR); -#endif +#ifdef DEBUG +static int msglevel = 0xdeadbeef; +module_param(msglevel, int, 0); +#endif /* DEBUG */ static struct ieee80211_channel brcms_2ghz_chantable[] = { CHAN2GHZ(1, 2412, IEEE80211_CHAN_NO_HT40MINUS), @@ -281,12 +276,12 @@ static void brcms_ops_tx(struct ieee80211_hw *hw, spin_lock_bh(&wl->lock); if (!wl->pub->up) { - brcms_err(wl->wlc->hw->d11core, "ops->tx called while down\n"); + wiphy_err(wl->wiphy, "ops->tx called while down\n"); kfree_skb(skb); goto done; } - if (brcms_c_sendpkt_mac80211(wl->wlc, skb, hw)) - tx_info->rate_driver_data[0] = control->sta; + brcms_c_sendpkt_mac80211(wl->wlc, skb, hw); + tx_info->rate_driver_data[0] = control->sta; done: spin_unlock_bh(&wl->lock); } @@ -318,8 +313,8 @@ static int brcms_ops_start(struct ieee80211_hw *hw) spin_unlock_bh(&wl->lock); if (err != 0) - brcms_err(wl->wlc->hw->d11core, "%s: brcms_up() returned %d\n", - __func__, err); + wiphy_err(hw->wiphy, "%s: brcms_up() returned %d\n", __func__, + err); return err; } @@ -337,7 +332,7 @@ static void brcms_ops_stop(struct ieee80211_hw *hw) status = brcms_c_chipmatch(wl->wlc->hw->d11core); spin_unlock_bh(&wl->lock); if (!status) { - brcms_err(wl->wlc->hw->d11core, + wiphy_err(wl->wiphy, "wl: brcms_ops_stop: chipmatch failed\n"); return; } @@ -355,9 +350,8 @@ brcms_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) /* Just STA for now */ if (vif->type != NL80211_IFTYPE_STATION) { - brcms_err(wl->wlc->hw->d11core, - "%s: Attempt to add type %d, only STA for now\n", - __func__, vif->type); + wiphy_err(hw->wiphy, "%s: Attempt to add type %d, only" + " STA for now\n", __func__, vif->type); return -EOPNOTSUPP; } @@ -376,9 +370,9 @@ static int brcms_ops_config(struct ieee80211_hw *hw, u32 changed) { struct ieee80211_conf *conf = &hw->conf; struct brcms_info *wl = hw->priv; - struct bcma_device *core = wl->wlc->hw->d11core; int err = 0; int new_int; + struct wiphy *wiphy = hw->wiphy; spin_lock_bh(&wl->lock); if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) { @@ -386,26 +380,25 @@ static int brcms_ops_config(struct ieee80211_hw *hw, u32 changed) conf->listen_interval); } if (changed & IEEE80211_CONF_CHANGE_MONITOR) - brcms_dbg_info(core, "%s: change monitor mode: %s\n", - __func__, conf->flags & IEEE80211_CONF_MONITOR ? - "true" : "false"); + wiphy_dbg(wiphy, "%s: change monitor mode: %s\n", + __func__, conf->flags & IEEE80211_CONF_MONITOR ? + "true" : "false"); if (changed & IEEE80211_CONF_CHANGE_PS) - brcms_err(core, "%s: change power-save mode: %s (implement)\n", + wiphy_err(wiphy, "%s: change power-save mode: %s (implement)\n", __func__, conf->flags & IEEE80211_CONF_PS ? "true" : "false"); if (changed & IEEE80211_CONF_CHANGE_POWER) { err = brcms_c_set_tx_power(wl->wlc, conf->power_level); if (err < 0) { - brcms_err(core, "%s: Error setting power_level\n", + wiphy_err(wiphy, "%s: Error setting power_level\n", __func__); goto config_out; } new_int = brcms_c_get_tx_power(wl->wlc); if (new_int != conf->power_level) - brcms_err(core, - "%s: Power level req != actual, %d %d\n", - __func__, conf->power_level, + wiphy_err(wiphy, "%s: Power level req != actual, %d %d" + "\n", __func__, conf->power_level, new_int); } if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { @@ -432,13 +425,13 @@ brcms_ops_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_bss_conf *info, u32 changed) { struct brcms_info *wl = hw->priv; - struct bcma_device *core = wl->wlc->hw->d11core; + struct wiphy *wiphy = hw->wiphy; if (changed & BSS_CHANGED_ASSOC) { /* association status changed (associated/disassociated) * also implies a change in the AID. */ - brcms_err(core, "%s: %s: %sassociated\n", KBUILD_MODNAME, + wiphy_err(wiphy, "%s: %s: %sassociated\n", KBUILD_MODNAME, __func__, info->assoc ? "" : "dis"); spin_lock_bh(&wl->lock); brcms_c_associate_upd(wl->wlc, info->assoc); @@ -498,7 +491,7 @@ brcms_ops_bss_info_changed(struct ieee80211_hw *hw, error = brcms_c_set_rateset(wl->wlc, &rs); spin_unlock_bh(&wl->lock); if (error) - brcms_err(core, "changing basic rates failed: %d\n", + wiphy_err(wiphy, "changing basic rates failed: %d\n", error); } if (changed & BSS_CHANGED_BEACON_INT) { @@ -515,30 +508,30 @@ brcms_ops_bss_info_changed(struct ieee80211_hw *hw, } if (changed & BSS_CHANGED_BEACON) /* Beacon data changed, retrieve new beacon (beaconing modes) */ - brcms_err(core, "%s: beacon changed\n", __func__); + wiphy_err(wiphy, "%s: beacon changed\n", __func__); if (changed & BSS_CHANGED_BEACON_ENABLED) { /* Beaconing should be enabled/disabled (beaconing modes) */ - brcms_err(core, "%s: Beacon enabled: %s\n", __func__, + wiphy_err(wiphy, "%s: Beacon enabled: %s\n", __func__, info->enable_beacon ? "true" : "false"); } if (changed & BSS_CHANGED_CQM) { /* Connection quality monitor config changed */ - brcms_err(core, "%s: cqm change: threshold %d, hys %d " + wiphy_err(wiphy, "%s: cqm change: threshold %d, hys %d " " (implement)\n", __func__, info->cqm_rssi_thold, info->cqm_rssi_hyst); } if (changed & BSS_CHANGED_IBSS) { /* IBSS join status changed */ - brcms_err(core, "%s: IBSS joined: %s (implement)\n", - __func__, info->ibss_joined ? "true" : "false"); + wiphy_err(wiphy, "%s: IBSS joined: %s (implement)\n", __func__, + info->ibss_joined ? "true" : "false"); } if (changed & BSS_CHANGED_ARP_FILTER) { /* Hardware ARP filter address list or state changed */ - brcms_err(core, "%s: arp filtering: enabled %s, count %d" + wiphy_err(wiphy, "%s: arp filtering: enabled %s, count %d" " (implement)\n", __func__, info->arp_filter_enabled ? "true" : "false", info->arp_addr_cnt); } @@ -548,8 +541,8 @@ brcms_ops_bss_info_changed(struct ieee80211_hw *hw, * QoS for this association was enabled/disabled. * Note that it is only ever disabled for station mode. */ - brcms_err(core, "%s: qos enabled: %s (implement)\n", - __func__, info->qos ? "true" : "false"); + wiphy_err(wiphy, "%s: qos enabled: %s (implement)\n", __func__, + info->qos ? "true" : "false"); } return; } @@ -560,25 +553,25 @@ brcms_ops_configure_filter(struct ieee80211_hw *hw, unsigned int *total_flags, u64 multicast) { struct brcms_info *wl = hw->priv; - struct bcma_device *core = wl->wlc->hw->d11core; + struct wiphy *wiphy = hw->wiphy; changed_flags &= MAC_FILTERS; *total_flags &= MAC_FILTERS; if (changed_flags & FIF_PROMISC_IN_BSS) - brcms_dbg_info(core, "FIF_PROMISC_IN_BSS\n"); + wiphy_dbg(wiphy, "FIF_PROMISC_IN_BSS\n"); if (changed_flags & FIF_ALLMULTI) - brcms_dbg_info(core, "FIF_ALLMULTI\n"); + wiphy_dbg(wiphy, "FIF_ALLMULTI\n"); if (changed_flags & FIF_FCSFAIL) - brcms_dbg_info(core, "FIF_FCSFAIL\n"); + wiphy_dbg(wiphy, "FIF_FCSFAIL\n"); if (changed_flags & FIF_CONTROL) - brcms_dbg_info(core, "FIF_CONTROL\n"); + wiphy_dbg(wiphy, "FIF_CONTROL\n"); if (changed_flags & FIF_OTHER_BSS) - brcms_dbg_info(core, "FIF_OTHER_BSS\n"); + wiphy_dbg(wiphy, "FIF_OTHER_BSS\n"); if (changed_flags & FIF_PSPOLL) - brcms_dbg_info(core, "FIF_PSPOLL\n"); + wiphy_dbg(wiphy, "FIF_PSPOLL\n"); if (changed_flags & FIF_BCN_PRBRESP_PROMISC) - brcms_dbg_info(core, "FIF_BCN_PRBRESP_PROMISC\n"); + wiphy_dbg(wiphy, "FIF_BCN_PRBRESP_PROMISC\n"); spin_lock_bh(&wl->lock); brcms_c_mac_promisc(wl->wlc, *total_flags); @@ -660,8 +653,8 @@ brcms_ops_ampdu_action(struct ieee80211_hw *hw, status = brcms_c_aggregatable(wl->wlc, tid); spin_unlock_bh(&wl->lock); if (!status) { - brcms_err(wl->wlc->hw->d11core, - "START: tid %d is not agg\'able\n", tid); + wiphy_err(wl->wiphy, "START: tid %d is not agg\'able\n", + tid); return -EINVAL; } ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); @@ -688,8 +681,8 @@ brcms_ops_ampdu_action(struct ieee80211_hw *hw, /* Power save wakeup */ break; default: - brcms_err(wl->wlc->hw->d11core, - "%s: Invalid command, ignoring\n", __func__); + wiphy_err(wl->wiphy, "%s: Invalid command, ignoring\n", + __func__); } return 0; @@ -846,10 +839,8 @@ static void brcms_free(struct brcms_info *wl) /* kill dpc */ tasklet_kill(&wl->tasklet); - if (wl->pub) { - brcms_debugfs_detach(wl->pub); + if (wl->pub) brcms_c_module_unregister(wl->pub, "linux", wl); - } /* free common resources */ if (wl->wlc) { @@ -898,22 +889,27 @@ static void brcms_remove(struct bcma_device *pdev) static irqreturn_t brcms_isr(int irq, void *dev_id) { struct brcms_info *wl; - irqreturn_t ret = IRQ_NONE; + bool ours, wantdpc; wl = (struct brcms_info *) dev_id; spin_lock(&wl->isr_lock); /* call common first level interrupt handler */ - if (brcms_c_isr(wl->wlc)) { - /* schedule second level handler */ - tasklet_schedule(&wl->tasklet); - ret = IRQ_HANDLED; + ours = brcms_c_isr(wl->wlc, &wantdpc); + if (ours) { + /* if more to do... */ + if (wantdpc) { + + /* ...and call the second level interrupt handler */ + /* schedule dpc */ + tasklet_schedule(&wl->tasklet); + } } spin_unlock(&wl->isr_lock); - return ret; + return IRQ_RETVAL(ours); } /* @@ -1079,8 +1075,6 @@ static struct brcms_info *brcms_attach(struct bcma_device *pdev) regulatory_hint(wl->wiphy, wl->pub->srom_ccode)) wiphy_err(wl->wiphy, "%s: regulatory hint failed\n", __func__); - brcms_debugfs_attach(wl->pub); - brcms_debugfs_create_files(wl->pub); n_adapters_found++; return wl; @@ -1150,13 +1144,14 @@ static int brcms_suspend(struct bcma_device *pdev) wl->pub->hw_up = false; spin_unlock_bh(&wl->lock); - brcms_dbg_info(wl->wlc->hw->d11core, "brcms_suspend ok\n"); + pr_debug("brcms_suspend ok\n"); return 0; } static int brcms_resume(struct bcma_device *pdev) { + pr_debug("brcms_resume ok\n"); return 0; } @@ -1189,7 +1184,10 @@ static DECLARE_WORK(brcms_driver_work, brcms_driver_init); static int __init brcms_module_init(void) { - brcms_debugfs_init(); +#ifdef DEBUG + if (msglevel != 0xdeadbeef) + brcm_msg_level = msglevel; +#endif if (!schedule_work(&brcms_driver_work)) return -EBUSY; @@ -1207,7 +1205,6 @@ static void __exit brcms_module_exit(void) { cancel_work_sync(&brcms_driver_work); bcma_driver_unregister(&brcms_bcma_driver); - brcms_debugfs_exit(); } module_init(brcms_module_init); @@ -1219,7 +1216,7 @@ module_exit(brcms_module_exit); void brcms_txflowcontrol(struct brcms_info *wl, struct brcms_if *wlif, bool state, int prio) { - brcms_err(wl->wlc->hw->d11core, "Shouldn't be here %s\n", __func__); + wiphy_err(wl->wiphy, "Shouldn't be here %s\n", __func__); } /* @@ -1227,8 +1224,7 @@ void brcms_txflowcontrol(struct brcms_info *wl, struct brcms_if *wlif, */ void brcms_init(struct brcms_info *wl) { - brcms_dbg_info(wl->wlc->hw->d11core, "Initializing wl%d\n", - wl->pub->unit); + BCMMSG(wl->pub->ieee_hw->wiphy, "wl%d\n", wl->pub->unit); brcms_reset(wl); brcms_c_init(wl->wlc, wl->mute_tx); } @@ -1238,7 +1234,7 @@ void brcms_init(struct brcms_info *wl) */ uint brcms_reset(struct brcms_info *wl) { - brcms_dbg_info(wl->wlc->hw->d11core, "Resetting wl%d\n", wl->pub->unit); + BCMMSG(wl->pub->ieee_hw->wiphy, "wl%d\n", wl->pub->unit); brcms_c_reset(wl->wlc); /* dpc will not be rescheduled */ @@ -1252,7 +1248,7 @@ uint brcms_reset(struct brcms_info *wl) void brcms_fatal_error(struct brcms_info *wl) { - brcms_err(wl->wlc->hw->d11core, "wl%d: fatal error, reinitializing\n", + wiphy_err(wl->wlc->wiphy, "wl%d: fatal error, reinitializing\n", wl->wlc->pub->unit); brcms_reset(wl); ieee80211_restart_hw(wl->pub->ieee_hw); @@ -1400,9 +1396,8 @@ void brcms_add_timer(struct brcms_timer *t, uint ms, int periodic) #ifdef DEBUG if (t->set) - brcms_dbg_info(t->wl->wlc->hw->d11core, - "%s: Already set. Name: %s, per %d\n", - __func__, t->name, periodic); + wiphy_err(hw->wiphy, "%s: Already set. Name: %s, per %d\n", + __func__, t->name, periodic); #endif t->ms = ms; t->periodic = (bool) periodic; @@ -1491,8 +1486,8 @@ int brcms_ucode_init_buf(struct brcms_info *wl, void **pbuf, u32 idx) } } } - brcms_err(wl->wlc->hw->d11core, - "ERROR: ucode buf tag:%d can not be found!\n", idx); + wiphy_err(wl->wiphy, "ERROR: ucode buf tag:%d can not be found!\n", + idx); *pbuf = NULL; fail: return -ENODATA; @@ -1515,7 +1510,7 @@ int brcms_ucode_init_uint(struct brcms_info *wl, size_t *n_bytes, u32 idx) pdata = wl->fw.fw_bin[i]->data + le32_to_cpu(hdr->offset); if (le32_to_cpu(hdr->len) != 4) { - brcms_err(wl->wlc->hw->d11core, + wiphy_err(wl->wiphy, "ERROR: fw hdr len\n"); return -ENOMSG; } @@ -1524,8 +1519,7 @@ int brcms_ucode_init_uint(struct brcms_info *wl, size_t *n_bytes, u32 idx) } } } - brcms_err(wl->wlc->hw->d11core, - "ERROR: ucode tag:%d can not be found!\n", idx); + wiphy_err(wl->wiphy, "ERROR: ucode tag:%d can not be found!\n", idx); return -ENOMSG; } @@ -1566,8 +1560,8 @@ int brcms_check_firmwares(struct brcms_info *wl) sizeof(struct firmware_hdr)); rc = -EBADF; } else if (fw->size < MIN_FW_SIZE || fw->size > MAX_FW_SIZE) { - wiphy_err(wl->wiphy, "%s: out of bounds fw file size %zu\n", - __func__, fw->size); + wiphy_err(wl->wiphy, "%s: out of bounds fw file size " + "%zu\n", __func__, fw->size); rc = -EBADF; } else { /* check if ucode section overruns firmware image */ diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/main.c b/trunk/drivers/net/wireless/brcm80211/brcmsmac/main.c index 8fce68751e47..565c15abbed5 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/main.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/main.c @@ -34,9 +34,12 @@ #include "ucode_loader.h" #include "main.h" #include "soc.h" -#include "dma.h" -#include "debug.h" -#include "brcms_trace_events.h" + +/* + * Indication for txflowcontrol that all priority bits in + * TXQ_STOP_FOR_PRIOFC_MASK are to be considered. + */ +#define ALLPRIO -1 /* watchdog timer, in unit of ms */ #define TIMER_INTERVAL_WATCHDOG 1000 @@ -123,6 +126,21 @@ #define BRCMS_TEMPSENSE_PERIOD 10 /* 10 second timeout */ +/* precedences numbers for wlc queues. These are twice as may levels as + * 802.1D priorities. + * Odd numbers are used for HI priority traffic at same precedence levels + * These constants are used ONLY by wlc_prio2prec_map. Do not use them + * elsewhere. + */ +#define _BRCMS_PREC_NONE 0 /* None = - */ +#define _BRCMS_PREC_BK 2 /* BK - Background */ +#define _BRCMS_PREC_BE 4 /* BE - Best-effort */ +#define _BRCMS_PREC_EE 6 /* EE - Excellent-effort */ +#define _BRCMS_PREC_CL 8 /* CL - Controlled Load */ +#define _BRCMS_PREC_VI 10 /* Vi - Video */ +#define _BRCMS_PREC_VO 12 /* Vo - Voice */ +#define _BRCMS_PREC_NC 14 /* NC - Network Control */ + /* synthpu_dly times in us */ #define SYNTHPU_DLY_APHY_US 3700 #define SYNTHPU_DLY_BPHY_US 1050 @@ -219,17 +237,17 @@ #define MAX_DMA_SEGS 4 -/* # of entries in Tx FIFO */ -#define NTXD 64 +/* Max # of entries in Tx FIFO based on 4kb page size */ +#define NTXD 256 /* Max # of entries in Rx FIFO based on 4kb page size */ #define NRXD 256 -/* Amount of headroom to leave in Tx FIFO */ -#define TX_HEADROOM 4 - /* try to keep this # rbufs posted to the chip */ #define NRXBUFPOST 32 +/* data msg txq hiwat mark */ +#define BRCMS_DATAHIWAT 50 + /* max # frames to process in brcms_c_recv() */ #define RXBND 8 /* max # tx status to process in wlc_txstatus() */ @@ -265,8 +283,24 @@ struct edcf_acparam { u16 TXOP; } __packed; +const u8 prio2fifo[NUMPRIO] = { + TX_AC_BE_FIFO, /* 0 BE AC_BE Best Effort */ + TX_AC_BK_FIFO, /* 1 BK AC_BK Background */ + TX_AC_BK_FIFO, /* 2 -- AC_BK Background */ + TX_AC_BE_FIFO, /* 3 EE AC_BE Best Effort */ + TX_AC_VI_FIFO, /* 4 CL AC_VI Video */ + TX_AC_VI_FIFO, /* 5 VI AC_VI Video */ + TX_AC_VO_FIFO, /* 6 VO AC_VO Voice */ + TX_AC_VO_FIFO /* 7 NC AC_VO Voice */ +}; + /* debug/trace */ -uint brcm_msg_level; +uint brcm_msg_level = +#if defined(DEBUG) + LOG_ERROR_VAL; +#else + 0; +#endif /* DEBUG */ /* TX FIFO number to WME/802.1E Access Category */ static const u8 wme_fifo2ac[] = { @@ -286,6 +320,18 @@ static const u8 wme_ac2fifo[] = { TX_AC_BK_FIFO }; +/* 802.1D Priority to precedence queue mapping */ +const u8 wlc_prio2prec_map[] = { + _BRCMS_PREC_BE, /* 0 BE - Best-effort */ + _BRCMS_PREC_BK, /* 1 BK - Background */ + _BRCMS_PREC_NONE, /* 2 None = - */ + _BRCMS_PREC_EE, /* 3 EE - Excellent-effort */ + _BRCMS_PREC_CL, /* 4 CL - Controlled Load */ + _BRCMS_PREC_VI, /* 5 Vi - Video */ + _BRCMS_PREC_VO, /* 6 Vo - Voice */ + _BRCMS_PREC_NC, /* 7 NC - Network Control */ +}; + static const u16 xmtfifo_sz[][NFIFO] = { /* corerev 17: 5120, 49152, 49152, 5376, 4352, 1280 */ {20, 192, 192, 21, 17, 5}, @@ -325,36 +371,6 @@ static const char fifo_names[6][0]; static struct brcms_c_info *wlc_info_dbg = (struct brcms_c_info *) (NULL); #endif -/* Mapping of ieee80211 AC numbers to tx fifos */ -static const u8 ac_to_fifo_mapping[IEEE80211_NUM_ACS] = { - [IEEE80211_AC_VO] = TX_AC_VO_FIFO, - [IEEE80211_AC_VI] = TX_AC_VI_FIFO, - [IEEE80211_AC_BE] = TX_AC_BE_FIFO, - [IEEE80211_AC_BK] = TX_AC_BK_FIFO, -}; - -/* Mapping of tx fifos to ieee80211 AC numbers */ -static const u8 fifo_to_ac_mapping[IEEE80211_NUM_ACS] = { - [TX_AC_BK_FIFO] = IEEE80211_AC_BK, - [TX_AC_BE_FIFO] = IEEE80211_AC_BE, - [TX_AC_VI_FIFO] = IEEE80211_AC_VI, - [TX_AC_VO_FIFO] = IEEE80211_AC_VO, -}; - -static u8 brcms_ac_to_fifo(u8 ac) -{ - if (ac >= ARRAY_SIZE(ac_to_fifo_mapping)) - return TX_AC_BE_FIFO; - return ac_to_fifo_mapping[ac]; -} - -static u8 brcms_fifo_to_ac(u8 fifo) -{ - if (fifo >= ARRAY_SIZE(fifo_to_ac_mapping)) - return IEEE80211_AC_BE; - return fifo_to_ac_mapping[fifo]; -} - /* Find basic rate for a given rate */ static u8 brcms_basic_rate(struct brcms_c_info *wlc, u32 rspec) { @@ -399,15 +415,10 @@ static bool brcms_deviceremoved(struct brcms_c_info *wlc) } /* sum the individual fifo tx pending packet counts */ -static int brcms_txpktpendtot(struct brcms_c_info *wlc) +static s16 brcms_txpktpendtot(struct brcms_c_info *wlc) { - int i; - int pending = 0; - - for (i = 0; i < ARRAY_SIZE(wlc->hw->di); i++) - if (wlc->hw->di[i]) - pending += dma_txpending(wlc->hw->di[i]); - return pending; + return wlc->core->txpktpend[0] + wlc->core->txpktpend[1] + + wlc->core->txpktpend[2] + wlc->core->txpktpend[3]; } static bool brcms_is_mband_unlocked(struct brcms_c_info *wlc) @@ -615,11 +626,14 @@ static uint brcms_c_calc_frame_time(struct brcms_c_info *wlc, u32 ratespec, uint rate = rspec2rate(ratespec); if (rate == 0) { - brcms_err(wlc->hw->d11core, "wl%d: WAR: using rate of 1 mbps\n", + wiphy_err(wlc->wiphy, "wl%d: WAR: using rate of 1 mbps\n", wlc->pub->unit); rate = BRCM_RATE_1M; } + BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, preamble_type %d, len%d\n", + wlc->pub->unit, ratespec, preamble_type, mac_len); + if (is_mcs_rate(ratespec)) { uint mcs = ratespec & RSPEC_RATE_MASK; int tot_streams = mcs_2_txstreams(mcs) + rspec_stc(ratespec); @@ -682,7 +696,7 @@ static void brcms_c_write_inits(struct brcms_hardware *wlc_hw, u16 size; u32 value; - brcms_dbg_info(wlc_hw->d11core, "wl%d\n", wlc_hw->unit); + BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); for (i = 0; inits[i].addr != cpu_to_le16(0xffff); i++) { size = le16_to_cpu(inits[i].size); @@ -711,6 +725,7 @@ static void brcms_c_write_mhf(struct brcms_hardware *wlc_hw, u16 *mhfs) static void brcms_c_ucode_bsinit(struct brcms_hardware *wlc_hw) { + struct wiphy *wiphy = wlc_hw->wlc->wiphy; struct brcms_ucode *ucode = &wlc_hw->wlc->wl->ucode; /* init microcode host flags */ @@ -721,9 +736,8 @@ static void brcms_c_ucode_bsinit(struct brcms_hardware *wlc_hw) if (BRCMS_ISNPHY(wlc_hw->band)) brcms_c_write_inits(wlc_hw, ucode->d11n0bsinitvals16); else - brcms_err(wlc_hw->d11core, - "%s: wl%d: unsupported phy in corerev %d\n", - __func__, wlc_hw->unit, + wiphy_err(wiphy, "%s: wl%d: unsupported phy in corerev" + " %d\n", __func__, wlc_hw->unit, wlc_hw->corerev); } else { if (D11REV_IS(wlc_hw->corerev, 24)) { @@ -731,14 +745,12 @@ static void brcms_c_ucode_bsinit(struct brcms_hardware *wlc_hw) brcms_c_write_inits(wlc_hw, ucode->d11lcn0bsinitvals24); else - brcms_err(wlc_hw->d11core, - "%s: wl%d: unsupported phy in core rev %d\n", - __func__, wlc_hw->unit, - wlc_hw->corerev); + wiphy_err(wiphy, "%s: wl%d: unsupported phy in" + " core rev %d\n", __func__, + wlc_hw->unit, wlc_hw->corerev); } else { - brcms_err(wlc_hw->d11core, - "%s: wl%d: unsupported corerev %d\n", - __func__, wlc_hw->unit, wlc_hw->corerev); + wiphy_err(wiphy, "%s: wl%d: unsupported corerev %d\n", + __func__, wlc_hw->unit, wlc_hw->corerev); } } } @@ -753,7 +765,7 @@ static void brcms_b_core_ioctl(struct brcms_hardware *wlc_hw, u32 m, u32 v) static void brcms_b_core_phy_clk(struct brcms_hardware *wlc_hw, bool clk) { - brcms_dbg_info(wlc_hw->d11core, "wl%d: clk %d\n", wlc_hw->unit, clk); + BCMMSG(wlc_hw->wlc->wiphy, "wl%d: clk %d\n", wlc_hw->unit, clk); wlc_hw->phyclk = clk; @@ -778,8 +790,8 @@ static void brcms_b_core_phy_clk(struct brcms_hardware *wlc_hw, bool clk) /* low-level band switch utility routine */ static void brcms_c_setxband(struct brcms_hardware *wlc_hw, uint bandunit) { - brcms_dbg_mac80211(wlc_hw->d11core, "wl%d: bandunit %d\n", wlc_hw->unit, - bandunit); + BCMMSG(wlc_hw->wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit, + bandunit); wlc_hw->band = wlc_hw->bandstate[bandunit]; @@ -807,7 +819,7 @@ static u32 brcms_c_setband_inact(struct brcms_c_info *wlc, uint bandunit) u32 macintmask; u32 macctrl; - brcms_dbg_mac80211(wlc_hw->d11core, "wl%d\n", wlc_hw->unit); + BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit); macctrl = bcma_read32(wlc_hw->d11core, D11REGOFFS(maccontrol)); WARN_ON((macctrl & MCTL_EN_MAC) != 0); @@ -829,10 +841,9 @@ static u32 brcms_c_setband_inact(struct brcms_c_info *wlc, uint bandunit) static bool brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs) { - struct sk_buff *p = NULL; - uint queue = NFIFO; - struct dma_pub *dma = NULL; - struct d11txh *txh = NULL; + struct sk_buff *p; + uint queue; + struct d11txh *txh; struct scb *scb = NULL; bool free_pdu; int tx_rts, tx_frame_count, tx_rts_count; @@ -843,11 +854,6 @@ brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs) struct ieee80211_tx_info *tx_info; struct ieee80211_tx_rate *txrate; int i; - bool fatal = true; - - trace_brcms_txstatus(&wlc->hw->d11core->dev, txs->framelen, - txs->frameid, txs->status, txs->lasttxtime, - txs->sequence, txs->phyerr, txs->ackphyrxsh); /* discard intermediate indications for ucode with one legitimate case: * e.g. if "useRTS" is set. ucode did a successful rts/cts exchange, @@ -856,36 +862,34 @@ brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs) */ if (!(txs->status & TX_STATUS_AMPDU) && (txs->status & TX_STATUS_INTERMEDIATE)) { - brcms_dbg_tx(wlc->hw->d11core, "INTERMEDIATE but not AMPDU\n"); - fatal = false; - goto out; + BCMMSG(wlc->wiphy, "INTERMEDIATE but not AMPDU\n"); + return false; } queue = txs->frameid & TXFID_QUEUE_MASK; if (queue >= NFIFO) { - brcms_err(wlc->hw->d11core, "queue %u >= NFIFO\n", queue); - goto out; + p = NULL; + goto fatal; } - dma = wlc->hw->di[queue]; - p = dma_getnexttxp(wlc->hw->di[queue], DMA_RANGE_TRANSMITTED); - if (p == NULL) { - brcms_err(wlc->hw->d11core, "dma_getnexttxp returned null!\n"); - goto out; - } + if (p == NULL) + goto fatal; txh = (struct d11txh *) (p->data); mcl = le16_to_cpu(txh->MacTxControlLow); - if (txs->phyerr) - brcms_err(wlc->hw->d11core, "phyerr 0x%x, rate 0x%x\n", - txs->phyerr, txh->MainRates); - - if (txs->frameid != le16_to_cpu(txh->TxFrameID)) { - brcms_err(wlc->hw->d11core, "frameid != txh->TxFrameID\n"); - goto out; + if (txs->phyerr) { + if (brcm_msg_level & LOG_ERROR_VAL) { + wiphy_err(wlc->wiphy, "phyerr 0x%x, rate 0x%x\n", + txs->phyerr, txh->MainRates); + brcms_c_print_txdesc(txh); + } + brcms_c_print_txstatus(txs); } + + if (txs->frameid != le16_to_cpu(txh->TxFrameID)) + goto fatal; tx_info = IEEE80211_SKB_CB(p); h = (struct ieee80211_hdr *)((u8 *) (txh + 1) + D11_PHY_HDR_LEN); @@ -894,24 +898,14 @@ brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs) if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { brcms_c_ampdu_dotxstatus(wlc->ampdu, scb, p, txs); - fatal = false; - goto out; + return false; } - /* - * brcms_c_ampdu_dotxstatus() will trace tx descriptors for AMPDU - * frames; this traces them for the rest. - */ - trace_brcms_txdesc(&wlc->hw->d11core->dev, txh, sizeof(*txh)); - supr_status = txs->status & TX_STATUS_SUPR_MASK; - if (supr_status == TX_STATUS_SUPR_BADCH) { - unsigned xfts = le16_to_cpu(txh->XtraFrameTypes); - brcms_dbg_tx(wlc->hw->d11core, - "Pkt tx suppressed, dest chan %u, current %d\n", - (xfts >> XFTS_CHANNEL_SHIFT) & 0xff, - CHSPEC_CHANNEL(wlc->default_bss->chanspec)); - } + if (supr_status == TX_STATUS_SUPR_BADCH) + BCMMSG(wlc->wiphy, + "%s: Pkt tx suppressed, possibly channel %d\n", + __func__, CHSPEC_CHANNEL(wlc->default_bss->chanspec)); tx_rts = le16_to_cpu(txh->MacTxControlLow) & TXC_SENDRTS; tx_frame_count = @@ -922,7 +916,7 @@ brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs) lastframe = !ieee80211_has_morefrags(h->frame_control); if (!lastframe) { - brcms_err(wlc->hw->d11core, "Not last frame!\n"); + wiphy_err(wlc->wiphy, "Not last frame!\n"); } else { /* * Set information to be consumed by Minstrel ht. @@ -988,37 +982,26 @@ brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs) totlen = p->len; free_pdu = true; + brcms_c_txfifo_complete(wlc, queue, 1); + if (lastframe) { /* remove PLCP & Broadcom tx descriptor header */ skb_pull(p, D11_PHY_HDR_LEN); skb_pull(p, D11_TXH_LEN); ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw, p); } else { - brcms_err(wlc->hw->d11core, - "%s: Not last frame => not calling tx_status\n", - __func__); + wiphy_err(wlc->wiphy, "%s: Not last frame => not calling " + "tx_status\n", __func__); } - fatal = false; + return false; - out: - if (fatal) { - if (txh) - trace_brcms_txdesc(&wlc->hw->d11core->dev, txh, - sizeof(*txh)); - if (p) - brcmu_pkt_buf_free_skb(p); - } + fatal: + if (p) + brcmu_pkt_buf_free_skb(p); - if (dma && queue < NFIFO) { - u16 ac_queue = brcms_fifo_to_ac(queue); - if (dma->txavail > TX_HEADROOM && queue < TX_BCMC_FIFO && - ieee80211_queue_stopped(wlc->pub->ieee_hw, ac_queue)) - ieee80211_wake_queue(wlc->pub->ieee_hw, ac_queue); - dma_kick_tx(dma); - } + return true; - return fatal; } /* process tx completion events in BMAC @@ -1028,6 +1011,7 @@ static bool brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal) { bool morepending = false; + struct brcms_c_info *wlc = wlc_hw->wlc; struct bcma_device *core; struct tx_status txstatus, *txs; u32 s1, s2; @@ -1038,23 +1022,19 @@ brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal) */ uint max_tx_num = bound ? TXSBND : -1; + BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit); + txs = &txstatus; core = wlc_hw->d11core; *fatal = false; s1 = bcma_read32(core, D11REGOFFS(frmtxstatus)); while (!(*fatal) && (s1 & TXS_V)) { - /* !give others some time to run! */ - if (n >= max_tx_num) { - morepending = true; - break; - } if (s1 == 0xffffffff) { - brcms_err(core, "wl%d: %s: dead chip\n", wlc_hw->unit, - __func__); - *fatal = true; - return false; + wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n", + wlc_hw->unit, __func__); + return morepending; } s2 = bcma_read32(core, D11REGOFFS(frmtxstatus2)); @@ -1066,12 +1046,20 @@ brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal) *fatal = brcms_c_dotxstatus(wlc_hw->wlc, txs); + /* !give others some time to run! */ + if (++n >= max_tx_num) + break; s1 = bcma_read32(core, D11REGOFFS(frmtxstatus)); - n++; } if (*fatal) - return false; + return 0; + + if (n >= max_tx_num) + morepending = true; + + if (!pktq_empty(&wlc->pkt_queue->q)) + brcms_c_send_q(wlc); return morepending; } @@ -1124,6 +1112,7 @@ static bool brcms_b_attach_dmapio(struct brcms_c_info *wlc, uint j, bool wme) u16 pio_mhf2 = 0; struct brcms_hardware *wlc_hw = wlc->hw; uint unit = wlc_hw->unit; + struct wiphy *wiphy = wlc->wiphy; /* name and offsets for dma_attach */ snprintf(name, sizeof(name), "wl%d", unit); @@ -1136,12 +1125,12 @@ static bool brcms_b_attach_dmapio(struct brcms_c_info *wlc, uint j, bool wme) * TX: TX_AC_BK_FIFO (TX AC Background data packets) * RX: RX_FIFO (RX data packets) */ - wlc_hw->di[0] = dma_attach(name, wlc, + wlc_hw->di[0] = dma_attach(name, wlc_hw->sih, wlc_hw->d11core, (wme ? dmareg(DMA_TX, 0) : 0), dmareg(DMA_RX, 0), (wme ? NTXD : 0), NRXD, RXBUFSZ, -1, NRXBUFPOST, - BRCMS_HWRXOFF); + BRCMS_HWRXOFF, &brcm_msg_level); dma_attach_err |= (NULL == wlc_hw->di[0]); /* @@ -1150,9 +1139,10 @@ static bool brcms_b_attach_dmapio(struct brcms_c_info *wlc, uint j, bool wme) * (legacy) TX_DATA_FIFO (TX data packets) * RX: UNUSED */ - wlc_hw->di[1] = dma_attach(name, wlc, + wlc_hw->di[1] = dma_attach(name, wlc_hw->sih, wlc_hw->d11core, dmareg(DMA_TX, 1), 0, - NTXD, 0, 0, -1, 0, 0); + NTXD, 0, 0, -1, 0, 0, + &brcm_msg_level); dma_attach_err |= (NULL == wlc_hw->di[1]); /* @@ -1160,26 +1150,26 @@ static bool brcms_b_attach_dmapio(struct brcms_c_info *wlc, uint j, bool wme) * TX: TX_AC_VI_FIFO (TX AC Video data packets) * RX: UNUSED */ - wlc_hw->di[2] = dma_attach(name, wlc, + wlc_hw->di[2] = dma_attach(name, wlc_hw->sih, wlc_hw->d11core, dmareg(DMA_TX, 2), 0, - NTXD, 0, 0, -1, 0, 0); + NTXD, 0, 0, -1, 0, 0, + &brcm_msg_level); dma_attach_err |= (NULL == wlc_hw->di[2]); /* * FIFO 3 * TX: TX_AC_VO_FIFO (TX AC Voice data packets) * (legacy) TX_CTL_FIFO (TX control & mgmt packets) */ - wlc_hw->di[3] = dma_attach(name, wlc, + wlc_hw->di[3] = dma_attach(name, wlc_hw->sih, wlc_hw->d11core, dmareg(DMA_TX, 3), 0, NTXD, 0, 0, -1, - 0, 0); + 0, 0, &brcm_msg_level); dma_attach_err |= (NULL == wlc_hw->di[3]); /* Cleaner to leave this as if with AP defined */ if (dma_attach_err) { - brcms_err(wlc_hw->d11core, - "wl%d: wlc_attach: dma_attach failed\n", - unit); + wiphy_err(wiphy, "wl%d: wlc_attach: dma_attach failed" + "\n", unit); return false; } @@ -1513,7 +1503,8 @@ brcms_b_set_addrmatch(struct brcms_hardware *wlc_hw, int match_reg_offset, u16 mac_m; u16 mac_h; - brcms_dbg_rx(core, "wl%d: brcms_b_set_addrmatch\n", wlc_hw->unit); + BCMMSG(wlc_hw->wlc->wiphy, "wl%d: brcms_b_set_addrmatch\n", + wlc_hw->unit); mac_l = addr[0] | (addr[1] << 8); mac_m = addr[2] | (addr[3] << 8); @@ -1536,7 +1527,7 @@ brcms_b_write_template_ram(struct brcms_hardware *wlc_hw, int offset, int len, __le32 word_le; __be32 word_be; bool be_bit; - brcms_dbg_info(core, "wl%d\n", wlc_hw->unit); + BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); bcma_write32(core, D11REGOFFS(tplatewrptr), offset); @@ -1709,8 +1700,8 @@ static void brcms_b_bsinit(struct brcms_c_info *wlc, u16 chanspec) { struct brcms_hardware *wlc_hw = wlc->hw; - brcms_dbg_mac80211(wlc_hw->d11core, "wl%d: bandunit %d\n", wlc_hw->unit, - wlc_hw->band->bandunit); + BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit, + wlc_hw->band->bandunit); brcms_c_ucode_bsinit(wlc_hw); @@ -1745,6 +1736,8 @@ static void brcms_b_bsinit(struct brcms_c_info *wlc, u16 chanspec) /* Perform a soft reset of the PHY PLL */ void brcms_b_core_phypll_reset(struct brcms_hardware *wlc_hw) { + BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); + ai_cc_reg(wlc_hw->sih, offsetof(struct chipcregs, chipcontrol_addr), ~0, 0); udelay(1); @@ -1789,7 +1782,7 @@ void brcms_b_phy_reset(struct brcms_hardware *wlc_hw) u32 phy_bw_clkbits; bool phy_in_reset = false; - brcms_dbg_info(wlc_hw->d11core, "wl%d: reset phy\n", wlc_hw->unit); + BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); if (pih == NULL) return; @@ -1923,7 +1916,7 @@ static void brcms_c_get_macaddr(struct brcms_hardware *wlc_hw, u8 etheraddr[ETH_ /* power both the pll and external oscillator on/off */ static void brcms_b_xtal(struct brcms_hardware *wlc_hw, bool want) { - brcms_dbg_info(wlc_hw->d11core, "wl%d: want %d\n", wlc_hw->unit, want); + BCMMSG(wlc_hw->wlc->wiphy, "wl%d: want %d\n", wlc_hw->unit, want); /* * dont power down if plldown is false or @@ -2012,7 +2005,7 @@ void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags) if (flags == BRCMS_USE_COREFLAGS) flags = (wlc_hw->band->pi ? wlc_hw->band->core_flags : 0); - brcms_dbg_info(wlc_hw->d11core, "wl%d: core reset\n", wlc_hw->unit); + BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); /* request FAST clock if not on */ fastclk = wlc_hw->forcefastclk; @@ -2023,13 +2016,13 @@ void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags) if (bcma_core_is_enabled(wlc_hw->d11core)) { for (i = 0; i < NFIFO; i++) if ((wlc_hw->di[i]) && (!dma_txreset(wlc_hw->di[i]))) - brcms_err(wlc_hw->d11core, "wl%d: %s: " + wiphy_err(wlc_hw->wlc->wiphy, "wl%d: %s: " "dma_txreset[%d]: cannot stop dma\n", wlc_hw->unit, __func__, i); if ((wlc_hw->di[RX_FIFO]) && (!wlc_dma_rxreset(wlc_hw, RX_FIFO))) - brcms_err(wlc_hw->d11core, "wl%d: %s: dma_rxreset" + wiphy_err(wlc_hw->wlc->wiphy, "wl%d: %s: dma_rxreset" "[%d]: cannot stop dma\n", wlc_hw->unit, __func__, RX_FIFO); } @@ -2242,7 +2235,7 @@ static void brcms_ucode_write(struct brcms_hardware *wlc_hw, uint i; uint count; - brcms_dbg_info(wlc_hw->d11core, "wl%d\n", wlc_hw->unit); + BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); count = (nbytes / sizeof(u32)); @@ -2270,8 +2263,8 @@ static void brcms_ucode_download(struct brcms_hardware *wlc_hw) ucode->bcm43xx_16_mimosz); wlc_hw->ucode_loaded = true; } else - brcms_err(wlc_hw->d11core, - "%s: wl%d: unsupported phy in corerev %d\n", + wiphy_err(wlc->wiphy, "%s: wl%d: unsupported phy in " + "corerev %d\n", __func__, wlc_hw->unit, wlc_hw->corerev); } else if (D11REV_IS(wlc_hw->corerev, 24)) { if (BRCMS_ISLCNPHY(wlc_hw->band)) { @@ -2279,8 +2272,8 @@ static void brcms_ucode_download(struct brcms_hardware *wlc_hw) ucode->bcm43xx_24_lcnsz); wlc_hw->ucode_loaded = true; } else { - brcms_err(wlc_hw->d11core, - "%s: wl%d: unsupported phy in corerev %d\n", + wiphy_err(wlc->wiphy, "%s: wl%d: unsupported phy in " + "corerev %d\n", __func__, wlc_hw->unit, wlc_hw->corerev); } } @@ -2317,6 +2310,7 @@ static void brcms_b_fifoerrors(struct brcms_hardware *wlc_hw) uint unit; uint intstatus, idx; struct bcma_device *core = wlc_hw->d11core; + struct wiphy *wiphy = wlc_hw->wlc->wiphy; unit = wlc_hw->unit; @@ -2329,39 +2323,39 @@ static void brcms_b_fifoerrors(struct brcms_hardware *wlc_hw) if (!intstatus) continue; - brcms_dbg_int(core, "wl%d: intstatus%d 0x%x\n", - unit, idx, intstatus); + BCMMSG(wlc_hw->wlc->wiphy, "wl%d: intstatus%d 0x%x\n", + unit, idx, intstatus); if (intstatus & I_RO) { - brcms_err(core, "wl%d: fifo %d: receive fifo " + wiphy_err(wiphy, "wl%d: fifo %d: receive fifo " "overflow\n", unit, idx); fatal = true; } if (intstatus & I_PC) { - brcms_err(core, "wl%d: fifo %d: descriptor error\n", - unit, idx); + wiphy_err(wiphy, "wl%d: fifo %d: descriptor error\n", + unit, idx); fatal = true; } if (intstatus & I_PD) { - brcms_err(core, "wl%d: fifo %d: data error\n", unit, + wiphy_err(wiphy, "wl%d: fifo %d: data error\n", unit, idx); fatal = true; } if (intstatus & I_DE) { - brcms_err(core, "wl%d: fifo %d: descriptor protocol " + wiphy_err(wiphy, "wl%d: fifo %d: descriptor protocol " "error\n", unit, idx); fatal = true; } if (intstatus & I_RU) - brcms_err(core, "wl%d: fifo %d: receive descriptor " + wiphy_err(wiphy, "wl%d: fifo %d: receive descriptor " "underflow\n", idx, unit); if (intstatus & I_XU) { - brcms_err(core, "wl%d: fifo %d: transmit fifo " + wiphy_err(wiphy, "wl%d: fifo %d: transmit fifo " "underflow\n", idx, unit); fatal = true; } @@ -2522,13 +2516,13 @@ static inline u32 wlc_intstatus(struct brcms_c_info *wlc, bool in_isr) { struct brcms_hardware *wlc_hw = wlc->hw; struct bcma_device *core = wlc_hw->d11core; - u32 macintstatus, mask; + u32 macintstatus; /* macintstatus includes a DMA interrupt summary bit */ macintstatus = bcma_read32(core, D11REGOFFS(macintstatus)); - mask = in_isr ? wlc->macintmask : wlc->defmacintmask; - trace_brcms_macintstatus(&core->dev, in_isr, macintstatus, mask); + BCMMSG(wlc->wiphy, "wl%d: macintstatus: 0x%x\n", wlc_hw->unit, + macintstatus); /* detect cardbus removed, in power down(suspend) and in reset */ if (brcms_deviceremoved(wlc)) @@ -2541,12 +2535,16 @@ static inline u32 wlc_intstatus(struct brcms_c_info *wlc, bool in_isr) return 0; /* defer unsolicited interrupts */ - macintstatus &= mask; + macintstatus &= (in_isr ? wlc->macintmask : wlc->defmacintmask); /* if not for us */ if (macintstatus == 0) return 0; + /* interrupts are already turned off for CFE build + * Caution: For CFE Turning off the interrupts again has some undesired + * consequences + */ /* turn off the interrupts */ bcma_write32(core, D11REGOFFS(macintmask), 0); (void)bcma_read32(core, D11REGOFFS(macintmask)); @@ -2589,31 +2587,33 @@ bool brcms_c_intrsupd(struct brcms_c_info *wlc) /* * First-level interrupt processing. - * Return true if this was our interrupt - * and if further brcms_c_dpc() processing is required, + * Return true if this was our interrupt, false otherwise. + * *wantdpc will be set to true if further brcms_c_dpc() processing is required, * false otherwise. */ -bool brcms_c_isr(struct brcms_c_info *wlc) +bool brcms_c_isr(struct brcms_c_info *wlc, bool *wantdpc) { struct brcms_hardware *wlc_hw = wlc->hw; u32 macintstatus; + *wantdpc = false; + if (!wlc_hw->up || !wlc->macintmask) return false; /* read and clear macintstatus and intstatus registers */ macintstatus = wlc_intstatus(wlc, true); - if (macintstatus == 0xffffffff) { - brcms_err(wlc_hw->d11core, - "DEVICEREMOVED detected in the ISR code path\n"); - return false; - } + if (macintstatus == 0xffffffff) + wiphy_err(wlc->wiphy, "DEVICEREMOVED detected in the ISR code" + " path\n"); /* it is not for us */ if (macintstatus == 0) return false; + *wantdpc = true; + /* save interrupt status bits */ wlc->macintstatus = macintstatus; @@ -2626,9 +2626,10 @@ void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc) struct brcms_hardware *wlc_hw = wlc->hw; struct bcma_device *core = wlc_hw->d11core; u32 mc, mi; + struct wiphy *wiphy = wlc->wiphy; - brcms_dbg_mac80211(core, "wl%d: bandunit %d\n", wlc_hw->unit, - wlc_hw->band->bandunit); + BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit, + wlc_hw->band->bandunit); /* * Track overlapping suspend requests @@ -2643,7 +2644,7 @@ void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc) mc = bcma_read32(core, D11REGOFFS(maccontrol)); if (mc == 0xffffffff) { - brcms_err(core, "wl%d: %s: dead chip\n", wlc_hw->unit, + wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit, __func__); brcms_down(wlc->wl); return; @@ -2654,7 +2655,7 @@ void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc) mi = bcma_read32(core, D11REGOFFS(macintstatus)); if (mi == 0xffffffff) { - brcms_err(core, "wl%d: %s: dead chip\n", wlc_hw->unit, + wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit, __func__); brcms_down(wlc->wl); return; @@ -2667,10 +2668,10 @@ void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc) BRCMS_MAX_MAC_SUSPEND); if (!(bcma_read32(core, D11REGOFFS(macintstatus)) & MI_MACSSPNDD)) { - brcms_err(core, "wl%d: wlc_suspend_mac_and_wait: waited %d uS" + wiphy_err(wiphy, "wl%d: wlc_suspend_mac_and_wait: waited %d uS" " and MI_MACSSPNDD is still not on.\n", wlc_hw->unit, BRCMS_MAX_MAC_SUSPEND); - brcms_err(core, "wl%d: psmdebug 0x%08x, phydebug 0x%08x, " + wiphy_err(wiphy, "wl%d: psmdebug 0x%08x, phydebug 0x%08x, " "psm_brc 0x%04x\n", wlc_hw->unit, bcma_read32(core, D11REGOFFS(psmdebug)), bcma_read32(core, D11REGOFFS(phydebug)), @@ -2679,7 +2680,7 @@ void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc) mc = bcma_read32(core, D11REGOFFS(maccontrol)); if (mc == 0xffffffff) { - brcms_err(core, "wl%d: %s: dead chip\n", wlc_hw->unit, + wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit, __func__); brcms_down(wlc->wl); return; @@ -2695,8 +2696,8 @@ void brcms_c_enable_mac(struct brcms_c_info *wlc) struct bcma_device *core = wlc_hw->d11core; u32 mc, mi; - brcms_dbg_mac80211(core, "wl%d: bandunit %d\n", wlc_hw->unit, - wlc->band->bandunit); + BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit, + wlc->band->bandunit); /* * Track overlapping suspend requests @@ -2739,6 +2740,8 @@ static bool brcms_b_validate_chip_access(struct brcms_hardware *wlc_hw) u32 w, val; struct wiphy *wiphy = wlc_hw->wlc->wiphy; + BCMMSG(wiphy, "wl%d\n", wlc_hw->unit); + /* Validate dchip register access */ bcma_write32(core, D11REGOFFS(objaddr), OBJADDR_SHM_SEL | 0); @@ -2799,7 +2802,7 @@ void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on) struct bcma_device *core = wlc_hw->d11core; u32 tmp; - brcms_dbg_info(core, "wl%d\n", wlc_hw->unit); + BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); tmp = 0; @@ -2815,8 +2818,8 @@ void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on) tmp = bcma_read32(core, D11REGOFFS(clk_ctl_st)); if ((tmp & CCS_ERSRC_AVAIL_HT) != CCS_ERSRC_AVAIL_HT) - brcms_err(core, "%s: turn on PHY PLL failed\n", - __func__); + wiphy_err(wlc_hw->wlc->wiphy, "%s: turn on PHY" + " PLL failed\n", __func__); } else { bcma_set32(core, D11REGOFFS(clk_ctl_st), tmp | CCS_ERSRC_REQ_D11PLL | @@ -2832,8 +2835,8 @@ void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on) (CCS_ERSRC_AVAIL_D11PLL | CCS_ERSRC_AVAIL_PHYPLL)) != (CCS_ERSRC_AVAIL_D11PLL | CCS_ERSRC_AVAIL_PHYPLL)) - brcms_err(core, "%s: turn on PHY PLL failed\n", - __func__); + wiphy_err(wlc_hw->wlc->wiphy, "%s: turn on " + "PHY PLL failed\n", __func__); } } else { /* @@ -2851,7 +2854,7 @@ static void brcms_c_coredisable(struct brcms_hardware *wlc_hw) { bool dev_gone; - brcms_dbg_info(wlc_hw->d11core, "wl%d: disable core\n", wlc_hw->unit); + BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); dev_gone = brcms_deviceremoved(wlc_hw->wlc); @@ -2881,14 +2884,12 @@ static void brcms_c_flushqueues(struct brcms_c_info *wlc) uint i; /* free any posted tx packets */ - for (i = 0; i < NFIFO; i++) { + for (i = 0; i < NFIFO; i++) if (wlc_hw->di[i]) { dma_txreclaim(wlc_hw->di[i], DMA_RANGE_ALL); - if (i < TX_BCMC_FIFO) - ieee80211_wake_queue(wlc->pub->ieee_hw, - brcms_fifo_to_ac(i)); + wlc->core->txpktpend[i] = 0; + BCMMSG(wlc->wiphy, "pktpend fifo %d clrd\n", i); } - } /* free any posted rx packets */ dma_rxreclaim(wlc_hw->di[RX_FIFO]); @@ -3108,7 +3109,7 @@ static void brcms_c_statsupd(struct brcms_c_info *wlc) /* check for rx fifo 0 overflow */ delta = (u16) (wlc->core->macstat_snapshot->rxf0ovfl - rxf0ovfl); if (delta) - brcms_err(wlc->hw->d11core, "wl%d: %u rx fifo 0 overflows!\n", + wiphy_err(wlc->wiphy, "wl%d: %u rx fifo 0 overflows!\n", wlc->pub->unit, delta); /* check for tx fifo underflows */ @@ -3117,9 +3118,8 @@ static void brcms_c_statsupd(struct brcms_c_info *wlc) (u16) (wlc->core->macstat_snapshot->txfunfl[i] - txfunfl[i]); if (delta) - brcms_err(wlc->hw->d11core, - "wl%d: %u tx fifo %d underflows!\n", - wlc->pub->unit, delta, i); + wiphy_err(wlc->wiphy, "wl%d: %u tx fifo %d underflows!" + "\n", wlc->pub->unit, delta, i); } #endif /* DEBUG */ @@ -3132,6 +3132,8 @@ static void brcms_c_statsupd(struct brcms_c_info *wlc) static void brcms_b_reset(struct brcms_hardware *wlc_hw) { + BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); + /* reset the core */ if (!brcms_deviceremoved(wlc_hw->wlc)) brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS); @@ -3142,7 +3144,7 @@ static void brcms_b_reset(struct brcms_hardware *wlc_hw) void brcms_c_reset(struct brcms_c_info *wlc) { - brcms_dbg_info(wlc->hw->d11core, "wl%d\n", wlc->pub->unit); + BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); /* slurp up hw mac counters before core reset */ brcms_c_statsupd(wlc); @@ -3187,9 +3189,10 @@ static void brcms_b_coreinit(struct brcms_c_info *wlc) bool fifosz_fixup = false; int err = 0; u16 buf[NFIFO]; + struct wiphy *wiphy = wlc->wiphy; struct brcms_ucode *ucode = &wlc_hw->wlc->wl->ucode; - brcms_dbg_info(core, "wl%d: core init\n", wlc_hw->unit); + BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit); /* reset PSM */ brcms_b_mctrl(wlc_hw, ~0, (MCTL_IHR_EN | MCTL_PSM_JMP_0 | MCTL_WAKE)); @@ -3209,7 +3212,7 @@ static void brcms_b_coreinit(struct brcms_c_info *wlc) SPINWAIT(((bcma_read32(core, D11REGOFFS(macintstatus)) & MI_MACSSPNDD) == 0), 1000 * 1000); if ((bcma_read32(core, D11REGOFFS(macintstatus)) & MI_MACSSPNDD) == 0) - brcms_err(core, "wl%d: wlc_coreinit: ucode did not self-" + wiphy_err(wiphy, "wl%d: wlc_coreinit: ucode did not self-" "suspend!\n", wlc_hw->unit); brcms_c_gpio_init(wlc); @@ -3220,18 +3223,18 @@ static void brcms_b_coreinit(struct brcms_c_info *wlc) if (BRCMS_ISNPHY(wlc_hw->band)) brcms_c_write_inits(wlc_hw, ucode->d11n0initvals16); else - brcms_err(core, "%s: wl%d: unsupported phy in corerev" + wiphy_err(wiphy, "%s: wl%d: unsupported phy in corerev" " %d\n", __func__, wlc_hw->unit, wlc_hw->corerev); } else if (D11REV_IS(wlc_hw->corerev, 24)) { if (BRCMS_ISLCNPHY(wlc_hw->band)) brcms_c_write_inits(wlc_hw, ucode->d11lcn0initvals24); else - brcms_err(core, "%s: wl%d: unsupported phy in corerev" + wiphy_err(wiphy, "%s: wl%d: unsupported phy in corerev" " %d\n", __func__, wlc_hw->unit, wlc_hw->corerev); } else { - brcms_err(core, "%s: wl%d: unsupported corerev %d\n", + wiphy_err(wiphy, "%s: wl%d: unsupported corerev %d\n", __func__, wlc_hw->unit, wlc_hw->corerev); } @@ -3273,7 +3276,7 @@ static void brcms_b_coreinit(struct brcms_c_info *wlc) err = -1; } if (err != 0) - brcms_err(core, "wlc_coreinit: txfifo mismatch: ucode size %d" + wiphy_err(wiphy, "wlc_coreinit: txfifo mismatch: ucode size %d" " driver size %d index %d\n", buf[i], wlc_hw->xmtfifo_sz[i], i); @@ -3356,6 +3359,8 @@ static brcms_b_init(struct brcms_hardware *wlc_hw, u16 chanspec) { bool fastclk; struct brcms_c_info *wlc = wlc_hw->wlc; + BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); + /* request FAST clock if not on */ fastclk = wlc_hw->forcefastclk; if (!fastclk) @@ -3448,7 +3453,7 @@ static void brcms_c_rate_lookup_init(struct brcms_c_info *wlc, rate = (rateset->rates[i] & BRCMS_RATE_MASK); if (rate > BRCM_MAXRATE) { - brcms_err(wlc->hw->d11core, "brcms_c_rate_lookup_init: " + wiphy_err(wlc->wiphy, "brcms_c_rate_lookup_init: " "invalid rate 0x%X in rate set\n", rateset->rates[i]); continue; @@ -3524,6 +3529,7 @@ static void brcms_c_bandinit_ordered(struct brcms_c_info *wlc, uint parkband; uint i, band_order[2]; + BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); /* * We might have been bandlocked during down and the chip * power-cycled (hibernate). Figure out the right band to park on @@ -3704,8 +3710,8 @@ static void brcms_c_set_ratetable(struct brcms_c_info *wlc) /* band-specific init */ static void brcms_c_bsinit(struct brcms_c_info *wlc) { - brcms_dbg_info(wlc->hw->d11core, "wl%d: bandunit %d\n", - wlc->pub->unit, wlc->band->bandunit); + BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", + wlc->pub->unit, wlc->band->bandunit); /* write ucode ACK/CTS rate table */ brcms_c_set_ratetable(wlc); @@ -3728,8 +3734,7 @@ brcms_c_duty_cycle_set(struct brcms_c_info *wlc, int duty_cycle, bool isOFDM, isOFDM ? M_TX_IDLE_BUSY_RATIO_X_16_OFDM : M_TX_IDLE_BUSY_RATIO_X_16_CCK; if (duty_cycle > 100 || duty_cycle < 0) { - brcms_err(wlc->hw->d11core, - "wl%d: duty cycle value off limit\n", + wiphy_err(wlc->wiphy, "wl%d: duty cycle value off limit\n", wlc->pub->unit); return -EINVAL; } @@ -3747,6 +3752,40 @@ brcms_c_duty_cycle_set(struct brcms_c_info *wlc, int duty_cycle, bool isOFDM, return 0; } +/* + * Initialize the base precedence map for dequeueing + * from txq based on WME settings + */ +static void brcms_c_tx_prec_map_init(struct brcms_c_info *wlc) +{ + wlc->tx_prec_map = BRCMS_PREC_BMP_ALL; + memset(wlc->fifo2prec_map, 0, NFIFO * sizeof(u16)); + + wlc->fifo2prec_map[TX_AC_BK_FIFO] = BRCMS_PREC_BMP_AC_BK; + wlc->fifo2prec_map[TX_AC_BE_FIFO] = BRCMS_PREC_BMP_AC_BE; + wlc->fifo2prec_map[TX_AC_VI_FIFO] = BRCMS_PREC_BMP_AC_VI; + wlc->fifo2prec_map[TX_AC_VO_FIFO] = BRCMS_PREC_BMP_AC_VO; +} + +static void +brcms_c_txflowcontrol_signal(struct brcms_c_info *wlc, + struct brcms_txq_info *qi, bool on, int prio) +{ + /* transmit flowcontrol is not yet implemented */ +} + +static void brcms_c_txflowcontrol_reset(struct brcms_c_info *wlc) +{ + struct brcms_txq_info *qi; + + for (qi = wlc->tx_queues; qi != NULL; qi = qi->next) { + if (qi->stopped) { + brcms_c_txflowcontrol_signal(wlc, qi, OFF, ALLPRIO); + qi->stopped = 0; + } + } +} + /* push sw hps and wake state through hardware */ static void brcms_c_set_ps_ctrl(struct brcms_c_info *wlc) { @@ -3756,8 +3795,7 @@ static void brcms_c_set_ps_ctrl(struct brcms_c_info *wlc) hps = brcms_c_ps_allowed(wlc); - brcms_dbg_mac80211(wlc->hw->d11core, "wl%d: hps %d\n", wlc->pub->unit, - hps); + BCMMSG(wlc->wiphy, "wl%d: hps %d\n", wlc->pub->unit, hps); v1 = bcma_read32(wlc->hw->d11core, D11REGOFFS(maccontrol)); v2 = MCTL_WAKE; @@ -3843,8 +3881,7 @@ brcms_b_set_chanspec(struct brcms_hardware *wlc_hw, u16 chanspec, { uint bandunit; - brcms_dbg_mac80211(wlc_hw->d11core, "wl%d: 0x%x\n", wlc_hw->unit, - chanspec); + BCMMSG(wlc_hw->wlc->wiphy, "wl%d: 0x%x\n", wlc_hw->unit, chanspec); wlc_hw->chanspec = chanspec; @@ -3905,7 +3942,7 @@ static void brcms_c_set_chanspec(struct brcms_c_info *wlc, u16 chanspec) u16 old_chanspec = wlc->chanspec; if (!brcms_c_valid_chanspec_db(wlc->cmi, chanspec)) { - brcms_err(wlc->hw->d11core, "wl%d: %s: Bad channel %d\n", + wiphy_err(wlc->wiphy, "wl%d: %s: Bad channel %d\n", wlc->pub->unit, __func__, CHSPEC_CHANNEL(chanspec)); return; } @@ -3916,8 +3953,8 @@ static void brcms_c_set_chanspec(struct brcms_c_info *wlc, u16 chanspec) if (wlc->band->bandunit != bandunit || wlc->bandinit_pending) { switchband = true; if (wlc->bandlocked) { - brcms_err(wlc->hw->d11core, - "wl%d: %s: chspec %d band is locked!\n", + wiphy_err(wlc->wiphy, "wl%d: %s: chspec %d " + "band is locked!\n", wlc->pub->unit, __func__, CHSPEC_CHANNEL(chanspec)); return; @@ -3981,10 +4018,6 @@ void brcms_c_beacon_phytxctl_txant_upd(struct brcms_c_info *wlc, */ void brcms_c_protection_upd(struct brcms_c_info *wlc, uint idx, int val) { - /* - * Cannot use brcms_dbg_* here because this function is called - * before wlc is sufficiently initialized. - */ BCMMSG(wlc->wiphy, "idx %d, val %d\n", idx, val); switch (idx) { @@ -4057,8 +4090,8 @@ void brcms_c_wme_setparams(struct brcms_c_info *wlc, u16 aci, /* Only apply params if the core is out of reset and has clocks */ if (!wlc->clk) { - brcms_err(wlc->hw->d11core, "wl%d: %s : no-clock\n", - wlc->pub->unit, __func__); + wiphy_err(wlc->wiphy, "wl%d: %s : no-clock\n", wlc->pub->unit, + __func__); return; } @@ -4076,7 +4109,7 @@ void brcms_c_wme_setparams(struct brcms_c_info *wlc, u16 aci, if (acp_shm.aifs < EDCF_AIFSN_MIN || acp_shm.aifs > EDCF_AIFSN_MAX) { - brcms_err(wlc->hw->d11core, "wl%d: edcf_setparams: bad " + wiphy_err(wlc->wiphy, "wl%d: edcf_setparams: bad " "aifs %d\n", wlc->pub->unit, acp_shm.aifs); } else { acp_shm.cwmin = params->cw_min; @@ -4191,8 +4224,8 @@ static void brcms_c_radio_timer(void *arg) struct brcms_c_info *wlc = (struct brcms_c_info *) arg; if (brcms_deviceremoved(wlc)) { - brcms_err(wlc->hw->d11core, "wl%d: %s: dead chip\n", - wlc->pub->unit, __func__); + wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n", wlc->pub->unit, + __func__); brcms_down(wlc->wl); return; } @@ -4205,6 +4238,8 @@ static void brcms_b_watchdog(struct brcms_c_info *wlc) { struct brcms_hardware *wlc_hw = wlc->hw; + BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit); + if (!wlc_hw->up) return; @@ -4223,14 +4258,14 @@ static void brcms_b_watchdog(struct brcms_c_info *wlc) /* common watchdog code */ static void brcms_c_watchdog(struct brcms_c_info *wlc) { - brcms_dbg_info(wlc->hw->d11core, "wl%d\n", wlc->pub->unit); + BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); if (!wlc->pub->up) return; if (brcms_deviceremoved(wlc)) { - brcms_err(wlc->hw->d11core, "wl%d: %s: dead chip\n", - wlc->pub->unit, __func__); + wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n", wlc->pub->unit, + __func__); brcms_down(wlc->wl); return; } @@ -4402,13 +4437,13 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core, struct ssb_sprom *sprom = &core->bus->sprom; if (core->bus->hosttype == BCMA_HOSTTYPE_PCI) - brcms_dbg_info(core, "wl%d: vendor 0x%x device 0x%x\n", unit, - pcidev->vendor, - pcidev->device); + BCMMSG(wlc->wiphy, "wl%d: vendor 0x%x device 0x%x\n", unit, + pcidev->vendor, + pcidev->device); else - brcms_dbg_info(core, "wl%d: vendor 0x%x device 0x%x\n", unit, - core->bus->boardinfo.vendor, - core->bus->boardinfo.type); + BCMMSG(wlc->wiphy, "wl%d: vendor 0x%x device 0x%x\n", unit, + core->bus->boardinfo.vendor, + core->bus->boardinfo.type); wme = true; @@ -4680,9 +4715,8 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core, goto fail; } - brcms_dbg_info(wlc_hw->d11core, "deviceid 0x%x nbands %d board 0x%x\n", - wlc_hw->deviceid, wlc_hw->_nbands, - ai_get_boardtype(wlc_hw->sih)); + BCMMSG(wlc->wiphy, "deviceid 0x%x nbands %d board 0x%x\n", + wlc_hw->deviceid, wlc_hw->_nbands, ai_get_boardtype(wlc_hw->sih)); return err; @@ -4802,6 +4836,56 @@ static void brcms_c_bss_default_init(struct brcms_c_info *wlc) bi->flags |= BRCMS_BSS_HT; } +static struct brcms_txq_info *brcms_c_txq_alloc(struct brcms_c_info *wlc) +{ + struct brcms_txq_info *qi, *p; + + qi = kzalloc(sizeof(struct brcms_txq_info), GFP_ATOMIC); + if (qi != NULL) { + /* + * Have enough room for control packets along with HI watermark + * Also, add room to txq for total psq packets if all the SCBs + * leave PS mode. The watermark for flowcontrol to OS packets + * will remain the same + */ + brcmu_pktq_init(&qi->q, BRCMS_PREC_COUNT, + 2 * BRCMS_DATAHIWAT + PKTQ_LEN_DEFAULT); + + /* add this queue to the the global list */ + p = wlc->tx_queues; + if (p == NULL) { + wlc->tx_queues = qi; + } else { + while (p->next != NULL) + p = p->next; + p->next = qi; + } + } + return qi; +} + +static void brcms_c_txq_free(struct brcms_c_info *wlc, + struct brcms_txq_info *qi) +{ + struct brcms_txq_info *p; + + if (qi == NULL) + return; + + /* remove the queue from the linked list */ + p = wlc->tx_queues; + if (p == qi) + wlc->tx_queues = p->next; + else { + while (p != NULL && p->next != qi) + p = p->next; + if (p != NULL) + p->next = p->next->next; + } + + kfree(qi); +} + static void brcms_c_update_mimo_band_bwcap(struct brcms_c_info *wlc, u8 bwcap) { uint i; @@ -4907,6 +4991,8 @@ uint brcms_c_detach(struct brcms_c_info *wlc) if (wlc == NULL) return 0; + BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); + callbacks += brcms_b_detach(wlc); /* delete software timers */ @@ -4919,6 +5005,10 @@ uint brcms_c_detach(struct brcms_c_info *wlc) brcms_c_detach_module(wlc); + + while (wlc->tx_queues != NULL) + brcms_c_txq_free(wlc, wlc->tx_queues); + brcms_c_detach_mfree(wlc); return callbacks; } @@ -4936,7 +5026,7 @@ static void brcms_b_hw_up(struct brcms_hardware *wlc_hw) if (wlc_hw->wlc->pub->hw_up) return; - brcms_dbg_info(wlc_hw->d11core, "wl%d\n", wlc_hw->unit); + BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); /* * Enable pll and xtal, initialize the power control registers, @@ -4973,7 +5063,7 @@ static void brcms_b_hw_up(struct brcms_hardware *wlc_hw) static int brcms_b_up_prep(struct brcms_hardware *wlc_hw) { - brcms_dbg_info(wlc_hw->d11core, "wl%d\n", wlc_hw->unit); + BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); /* * Enable pll and xtal, initialize the power control registers, @@ -5012,6 +5102,8 @@ static int brcms_b_up_prep(struct brcms_hardware *wlc_hw) static int brcms_b_up_finish(struct brcms_hardware *wlc_hw) { + BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); + wlc_hw->up = true; wlc_phy_hw_state_upd(wlc_hw->band->pi, true); @@ -5043,7 +5135,7 @@ int brcms_c_up(struct brcms_c_info *wlc) { struct ieee80211_channel *ch; - brcms_dbg_info(wlc->hw->d11core, "wl%d\n", wlc->pub->unit); + BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); /* HW is turned off so don't try to access it */ if (wlc->pub->hw_off || brcms_deviceremoved(wlc)) @@ -5084,8 +5176,8 @@ int brcms_c_up(struct brcms_c_info *wlc) WL_RADIO_HW_DISABLE); if (bsscfg->enable && bsscfg->BSS) - brcms_err(wlc->hw->d11core, - "wl%d: up: rfdisable -> " + wiphy_err(wlc->wiphy, "wl%d: up" + ": rfdisable -> " "bsscfg_disable()\n", wlc->pub->unit); } @@ -5145,6 +5237,8 @@ static int brcms_b_bmac_down_prep(struct brcms_hardware *wlc_hw) bool dev_gone; uint callbacks = 0; + BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); + if (!wlc_hw->up) return callbacks; @@ -5171,6 +5265,8 @@ static int brcms_b_down_finish(struct brcms_hardware *wlc_hw) uint callbacks = 0; bool dev_gone; + BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); + if (!wlc_hw->up) return callbacks; @@ -5218,14 +5314,14 @@ uint brcms_c_down(struct brcms_c_info *wlc) uint callbacks = 0; int i; bool dev_gone = false; + struct brcms_txq_info *qi; - brcms_dbg_info(wlc->hw->d11core, "wl%d\n", wlc->pub->unit); + BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); /* check if we are already in the going down path */ if (wlc->going_down) { - brcms_err(wlc->hw->d11core, - "wl%d: %s: Driver going down so return\n", - wlc->pub->unit, __func__); + wiphy_err(wlc->wiphy, "wl%d: %s: Driver going down so return" + "\n", wlc->pub->unit, __func__); return 0; } if (!wlc->pub->up) @@ -5257,6 +5353,13 @@ uint brcms_c_down(struct brcms_c_info *wlc) wlc_phy_mute_upd(wlc->band->pi, false, PHY_MUTE_ALL); + /* clear txq flow control */ + brcms_c_txflowcontrol_reset(wlc); + + /* flush tx queues */ + for (qi = wlc->tx_queues; qi != NULL; qi = qi->next) + brcmu_pktq_flush(&qi->q, true, NULL, NULL); + callbacks += brcms_b_down_finish(wlc->hw); /* brcms_b_down_finish has done brcms_c_coredisable(). so clk is off */ @@ -5338,7 +5441,7 @@ int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config) default: /* Error */ - brcms_err(wlc->hw->d11core, "wl%d: %s: invalid gmode %d\n", + wiphy_err(wlc->wiphy, "wl%d: %s: invalid gmode %d\n", wlc->pub->unit, __func__, gmode); return -ENOTSUPP; } @@ -5642,6 +5745,45 @@ int brcms_c_module_unregister(struct brcms_pub *pub, const char *name, return -ENODATA; } +void brcms_c_print_txstatus(struct tx_status *txs) +{ + pr_debug("\ntxpkt (MPDU) Complete\n"); + + pr_debug("FrameID: %04x TxStatus: %04x\n", txs->frameid, txs->status); + + pr_debug("[15:12] %d frame attempts\n", + (txs->status & TX_STATUS_FRM_RTX_MASK) >> + TX_STATUS_FRM_RTX_SHIFT); + pr_debug(" [11:8] %d rts attempts\n", + (txs->status & TX_STATUS_RTS_RTX_MASK) >> + TX_STATUS_RTS_RTX_SHIFT); + pr_debug(" [7] %d PM mode indicated\n", + txs->status & TX_STATUS_PMINDCTD ? 1 : 0); + pr_debug(" [6] %d intermediate status\n", + txs->status & TX_STATUS_INTERMEDIATE ? 1 : 0); + pr_debug(" [5] %d AMPDU\n", + txs->status & TX_STATUS_AMPDU ? 1 : 0); + pr_debug(" [4:2] %d Frame Suppressed Reason (%s)\n", + (txs->status & TX_STATUS_SUPR_MASK) >> TX_STATUS_SUPR_SHIFT, + (const char *[]) { + "None", + "PMQ Entry", + "Flush request", + "Previous frag failure", + "Channel mismatch", + "Lifetime Expiry", + "Underflow" + } [(txs->status & TX_STATUS_SUPR_MASK) >> + TX_STATUS_SUPR_SHIFT]); + pr_debug(" [1] %d acked\n", + txs->status & TX_STATUS_ACK_RCV ? 1 : 0); + + pr_debug("LastTxTime: %04x Seq: %04x PHYTxStatus: %04x RxAckRSSI: %04x RxAckSQ: %04x\n", + txs->lasttxtime, txs->sequence, txs->phyerr, + (txs->ackphyrxsh & PRXS1_JSSI_MASK) >> PRXS1_JSSI_SHIFT, + (txs->ackphyrxsh & PRXS1_SQ_MASK) >> PRXS1_SQ_SHIFT); +} + static bool brcms_c_chipmatch_pci(struct bcma_device *core) { struct pci_dev *pcidev = core->bus->host_pci; @@ -5690,6 +5832,184 @@ bool brcms_c_chipmatch(struct bcma_device *core) } } +#if defined(DEBUG) +void brcms_c_print_txdesc(struct d11txh *txh) +{ + u16 mtcl = le16_to_cpu(txh->MacTxControlLow); + u16 mtch = le16_to_cpu(txh->MacTxControlHigh); + u16 mfc = le16_to_cpu(txh->MacFrameControl); + u16 tfest = le16_to_cpu(txh->TxFesTimeNormal); + u16 ptcw = le16_to_cpu(txh->PhyTxControlWord); + u16 ptcw_1 = le16_to_cpu(txh->PhyTxControlWord_1); + u16 ptcw_1_Fbr = le16_to_cpu(txh->PhyTxControlWord_1_Fbr); + u16 ptcw_1_Rts = le16_to_cpu(txh->PhyTxControlWord_1_Rts); + u16 ptcw_1_FbrRts = le16_to_cpu(txh->PhyTxControlWord_1_FbrRts); + u16 mainrates = le16_to_cpu(txh->MainRates); + u16 xtraft = le16_to_cpu(txh->XtraFrameTypes); + u8 *iv = txh->IV; + u8 *ra = txh->TxFrameRA; + u16 tfestfb = le16_to_cpu(txh->TxFesTimeFallback); + u8 *rtspfb = txh->RTSPLCPFallback; + u16 rtsdfb = le16_to_cpu(txh->RTSDurFallback); + u8 *fragpfb = txh->FragPLCPFallback; + u16 fragdfb = le16_to_cpu(txh->FragDurFallback); + u16 mmodelen = le16_to_cpu(txh->MModeLen); + u16 mmodefbrlen = le16_to_cpu(txh->MModeFbrLen); + u16 tfid = le16_to_cpu(txh->TxFrameID); + u16 txs = le16_to_cpu(txh->TxStatus); + u16 mnmpdu = le16_to_cpu(txh->MaxNMpdus); + u16 mabyte = le16_to_cpu(txh->MaxABytes_MRT); + u16 mabyte_f = le16_to_cpu(txh->MaxABytes_FBR); + u16 mmbyte = le16_to_cpu(txh->MinMBytes); + + u8 *rtsph = txh->RTSPhyHeader; + struct ieee80211_rts rts = txh->rts_frame; + + /* add plcp header along with txh descriptor */ + brcmu_dbg_hex_dump(txh, sizeof(struct d11txh) + 48, + "Raw TxDesc + plcp header:\n"); + + pr_debug("TxCtlLow: %04x ", mtcl); + pr_debug("TxCtlHigh: %04x ", mtch); + pr_debug("FC: %04x ", mfc); + pr_debug("FES Time: %04x\n", tfest); + pr_debug("PhyCtl: %04x%s ", ptcw, + (ptcw & PHY_TXC_SHORT_HDR) ? " short" : ""); + pr_debug("PhyCtl_1: %04x ", ptcw_1); + pr_debug("PhyCtl_1_Fbr: %04x\n", ptcw_1_Fbr); + pr_debug("PhyCtl_1_Rts: %04x ", ptcw_1_Rts); + pr_debug("PhyCtl_1_Fbr_Rts: %04x\n", ptcw_1_FbrRts); + pr_debug("MainRates: %04x ", mainrates); + pr_debug("XtraFrameTypes: %04x ", xtraft); + pr_debug("\n"); + + print_hex_dump_bytes("SecIV:", DUMP_PREFIX_OFFSET, iv, sizeof(txh->IV)); + print_hex_dump_bytes("RA:", DUMP_PREFIX_OFFSET, + ra, sizeof(txh->TxFrameRA)); + + pr_debug("Fb FES Time: %04x ", tfestfb); + print_hex_dump_bytes("Fb RTS PLCP:", DUMP_PREFIX_OFFSET, + rtspfb, sizeof(txh->RTSPLCPFallback)); + pr_debug("RTS DUR: %04x ", rtsdfb); + print_hex_dump_bytes("PLCP:", DUMP_PREFIX_OFFSET, + fragpfb, sizeof(txh->FragPLCPFallback)); + pr_debug("DUR: %04x", fragdfb); + pr_debug("\n"); + + pr_debug("MModeLen: %04x ", mmodelen); + pr_debug("MModeFbrLen: %04x\n", mmodefbrlen); + + pr_debug("FrameID: %04x\n", tfid); + pr_debug("TxStatus: %04x\n", txs); + + pr_debug("MaxNumMpdu: %04x\n", mnmpdu); + pr_debug("MaxAggbyte: %04x\n", mabyte); + pr_debug("MaxAggbyte_fb: %04x\n", mabyte_f); + pr_debug("MinByte: %04x\n", mmbyte); + + print_hex_dump_bytes("RTS PLCP:", DUMP_PREFIX_OFFSET, + rtsph, sizeof(txh->RTSPhyHeader)); + print_hex_dump_bytes("RTS Frame:", DUMP_PREFIX_OFFSET, + (u8 *)&rts, sizeof(txh->rts_frame)); + pr_debug("\n"); +} +#endif /* defined(DEBUG) */ + +#if defined(DEBUG) +static int +brcms_c_format_flags(const struct brcms_c_bit_desc *bd, u32 flags, char *buf, + int len) +{ + int i; + char *p = buf; + char hexstr[16]; + int slen = 0, nlen = 0; + u32 bit; + const char *name; + + if (len < 2 || !buf) + return 0; + + buf[0] = '\0'; + + for (i = 0; flags != 0; i++) { + bit = bd[i].bit; + name = bd[i].name; + if (bit == 0 && flags != 0) { + /* print any unnamed bits */ + snprintf(hexstr, 16, "0x%X", flags); + name = hexstr; + flags = 0; /* exit loop */ + } else if ((flags & bit) == 0) + continue; + flags &= ~bit; + nlen = strlen(name); + slen += nlen; + /* count btwn flag space */ + if (flags != 0) + slen += 1; + /* need NULL char as well */ + if (len <= slen) + break; + /* copy NULL char but don't count it */ + strncpy(p, name, nlen + 1); + p += nlen; + /* copy btwn flag space and NULL char */ + if (flags != 0) + p += snprintf(p, 2, " "); + len -= slen; + } + + /* indicate the str was too short */ + if (flags != 0) { + if (len < 2) + p -= 2 - len; /* overwrite last char */ + p += snprintf(p, 2, ">"); + } + + return (int)(p - buf); +} +#endif /* defined(DEBUG) */ + +#if defined(DEBUG) +void brcms_c_print_rxh(struct d11rxhdr *rxh) +{ + u16 len = rxh->RxFrameSize; + u16 phystatus_0 = rxh->PhyRxStatus_0; + u16 phystatus_1 = rxh->PhyRxStatus_1; + u16 phystatus_2 = rxh->PhyRxStatus_2; + u16 phystatus_3 = rxh->PhyRxStatus_3; + u16 macstatus1 = rxh->RxStatus1; + u16 macstatus2 = rxh->RxStatus2; + char flagstr[64]; + char lenbuf[20]; + static const struct brcms_c_bit_desc macstat_flags[] = { + {RXS_FCSERR, "FCSErr"}, + {RXS_RESPFRAMETX, "Reply"}, + {RXS_PBPRES, "PADDING"}, + {RXS_DECATMPT, "DeCr"}, + {RXS_DECERR, "DeCrErr"}, + {RXS_BCNSENT, "Bcn"}, + {0, NULL} + }; + + brcmu_dbg_hex_dump(rxh, sizeof(struct d11rxhdr), "Raw RxDesc:\n"); + + brcms_c_format_flags(macstat_flags, macstatus1, flagstr, 64); + + snprintf(lenbuf, sizeof(lenbuf), "0x%x", len); + + pr_debug("RxFrameSize: %6s (%d)%s\n", lenbuf, len, + (rxh->PhyRxStatus_0 & PRXS0_SHORTH) ? " short preamble" : ""); + pr_debug("RxPHYStatus: %04x %04x %04x %04x\n", + phystatus_0, phystatus_1, phystatus_2, phystatus_3); + pr_debug("RxMACStatus: %x %s\n", macstatus1, flagstr); + pr_debug("RXMACaggtype: %x\n", + (macstatus2 & RXS_AGGTYPE_MASK)); + pr_debug("RxTSFTime: %04x\n", rxh->RxTSFTime); +} +#endif /* defined(DEBUG) */ + u16 brcms_b_rate_shm_offset(struct brcms_hardware *wlc_hw, u8 rate) { u16 table_ptr; @@ -5713,6 +6033,86 @@ u16 brcms_b_rate_shm_offset(struct brcms_hardware *wlc_hw, u8 rate) return 2 * brcms_b_read_shm(wlc_hw, table_ptr + (index * 2)); } +static bool +brcms_c_prec_enq_head(struct brcms_c_info *wlc, struct pktq *q, + struct sk_buff *pkt, int prec, bool head) +{ + struct sk_buff *p; + int eprec = -1; /* precedence to evict from */ + + /* Determine precedence from which to evict packet, if any */ + if (pktq_pfull(q, prec)) + eprec = prec; + else if (pktq_full(q)) { + p = brcmu_pktq_peek_tail(q, &eprec); + if (eprec > prec) { + wiphy_err(wlc->wiphy, "%s: Failing: eprec %d > prec %d" + "\n", __func__, eprec, prec); + return false; + } + } + + /* Evict if needed */ + if (eprec >= 0) { + bool discard_oldest; + + discard_oldest = ac_bitmap_tst(0, eprec); + + /* Refuse newer packet unless configured to discard oldest */ + if (eprec == prec && !discard_oldest) { + wiphy_err(wlc->wiphy, "%s: No where to go, prec == %d" + "\n", __func__, prec); + return false; + } + + /* Evict packet according to discard policy */ + p = discard_oldest ? brcmu_pktq_pdeq(q, eprec) : + brcmu_pktq_pdeq_tail(q, eprec); + brcmu_pkt_buf_free_skb(p); + } + + /* Enqueue */ + if (head) + p = brcmu_pktq_penq_head(q, prec, pkt); + else + p = brcmu_pktq_penq(q, prec, pkt); + + return true; +} + +/* + * Attempts to queue a packet onto a multiple-precedence queue, + * if necessary evicting a lower precedence packet from the queue. + * + * 'prec' is the precedence number that has already been mapped + * from the packet priority. + * + * Returns true if packet consumed (queued), false if not. + */ +static bool brcms_c_prec_enq(struct brcms_c_info *wlc, struct pktq *q, + struct sk_buff *pkt, int prec) +{ + return brcms_c_prec_enq_head(wlc, q, pkt, prec, false); +} + +void brcms_c_txq_enq(struct brcms_c_info *wlc, struct scb *scb, + struct sk_buff *sdu, uint prec) +{ + struct brcms_txq_info *qi = wlc->pkt_queue; /* Check me */ + struct pktq *q = &qi->q; + int prio; + + prio = sdu->priority; + + if (!brcms_c_prec_enq(wlc, q, sdu, prec)) { + /* + * we might hit this condtion in case + * packet flooding from mac80211 stack + */ + brcmu_pkt_buf_free_skb(sdu); + } +} + /* * bcmc_fid_generate: * Generate frame ID for a BCMC packet. The frag field is not used @@ -5740,6 +6140,8 @@ brcms_c_calc_ack_time(struct brcms_c_info *wlc, u32 rspec, { uint dur = 0; + BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, preamble_type %d\n", + wlc->pub->unit, rspec, preamble_type); /* * Spec 9.6: ack rate is the highest rate in BSSBasicRateSet that * is less than or equal to the rate of the immediately previous @@ -5757,6 +6159,8 @@ static uint brcms_c_calc_cts_time(struct brcms_c_info *wlc, u32 rspec, u8 preamble_type) { + BCMMSG(wlc->wiphy, "wl%d: ratespec 0x%x, preamble_type %d\n", + wlc->pub->unit, rspec, preamble_type); return brcms_c_calc_ack_time(wlc, rspec, preamble_type); } @@ -5764,6 +6168,8 @@ static uint brcms_c_calc_ba_time(struct brcms_c_info *wlc, u32 rspec, u8 preamble_type) { + BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, " + "preamble_type %d\n", wlc->pub->unit, rspec, preamble_type); /* * Spec 9.6: ack rate is the highest rate in BSSBasicRateSet that * is less than or equal to the rate of the immediately previous @@ -5817,6 +6223,9 @@ brcms_c_calc_frame_len(struct brcms_c_info *wlc, u32 ratespec, uint nsyms, mac_len, Ndps, kNdps; uint rate = rspec2rate(ratespec); + BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, preamble_type %d, dur %d\n", + wlc->pub->unit, ratespec, preamble_type, dur); + if (is_mcs_rate(ratespec)) { uint mcs = ratespec & RSPEC_RATE_MASK; int tot_streams = mcs_2_txstreams(mcs) + rspec_stc(ratespec); @@ -5883,7 +6292,7 @@ static bool brcms_c_valid_rate(struct brcms_c_info *wlc, u32 rspec, int band, return true; error: if (verbose) - brcms_err(wlc->hw->d11core, "wl%d: valid_rate: rate spec 0x%x " + wiphy_err(wlc->wiphy, "wl%d: valid_rate: rate spec 0x%x " "not in hw_rateset\n", wlc->pub->unit, rspec); return false; @@ -5893,7 +6302,6 @@ static u32 mac80211_wlc_set_nrate(struct brcms_c_info *wlc, struct brcms_band *cur_band, u32 int_val) { - struct bcma_device *core = wlc->hw->d11core; u8 stf = (int_val & NRATE_STF_MASK) >> NRATE_STF_SHIFT; u8 rate = int_val & NRATE_RATE_MASK; u32 rspec; @@ -5910,7 +6318,7 @@ mac80211_wlc_set_nrate(struct brcms_c_info *wlc, struct brcms_band *cur_band, if ((wlc->pub->_n_enab & SUPPORT_11N) && ismcs) { /* mcs only allowed when nmode */ if (stf > PHY_TXC1_MODE_SDM) { - brcms_err(core, "wl%d: %s: Invalid stf\n", + wiphy_err(wlc->wiphy, "wl%d: %s: Invalid stf\n", wlc->pub->unit, __func__); bcmerror = -EINVAL; goto done; @@ -5921,8 +6329,8 @@ mac80211_wlc_set_nrate(struct brcms_c_info *wlc, struct brcms_band *cur_band, if (!CHSPEC_IS40(wlc->home_chanspec) || ((stf != PHY_TXC1_MODE_SISO) && (stf != PHY_TXC1_MODE_CDD))) { - brcms_err(core, "wl%d: %s: Invalid mcs 32\n", - wlc->pub->unit, __func__); + wiphy_err(wlc->wiphy, "wl%d: %s: Invalid mcs " + "32\n", wlc->pub->unit, __func__); bcmerror = -EINVAL; goto done; } @@ -5930,9 +6338,9 @@ mac80211_wlc_set_nrate(struct brcms_c_info *wlc, struct brcms_band *cur_band, } else if (rate > HIGHEST_SINGLE_STREAM_MCS) { /* mcs > 7 must use stf SDM */ if (stf != PHY_TXC1_MODE_SDM) { - brcms_dbg_mac80211(core, "wl%d: enabling " - "SDM mode for mcs %d\n", - wlc->pub->unit, rate); + BCMMSG(wlc->wiphy, "wl%d: enabling " + "SDM mode for mcs %d\n", + wlc->pub->unit, rate); stf = PHY_TXC1_MODE_SDM; } } else { @@ -5943,15 +6351,15 @@ mac80211_wlc_set_nrate(struct brcms_c_info *wlc, struct brcms_band *cur_band, if ((stf > PHY_TXC1_MODE_STBC) || (!BRCMS_STBC_CAP_PHY(wlc) && (stf == PHY_TXC1_MODE_STBC))) { - brcms_err(core, "wl%d: %s: Invalid STBC\n", - wlc->pub->unit, __func__); + wiphy_err(wlc->wiphy, "wl%d: %s: Invalid STBC" + "\n", wlc->pub->unit, __func__); bcmerror = -EINVAL; goto done; } } } else if (is_ofdm_rate(rate)) { if ((stf != PHY_TXC1_MODE_CDD) && (stf != PHY_TXC1_MODE_SISO)) { - brcms_err(core, "wl%d: %s: Invalid OFDM\n", + wiphy_err(wlc->wiphy, "wl%d: %s: Invalid OFDM\n", wlc->pub->unit, __func__); bcmerror = -EINVAL; goto done; @@ -5959,20 +6367,20 @@ mac80211_wlc_set_nrate(struct brcms_c_info *wlc, struct brcms_band *cur_band, } else if (is_cck_rate(rate)) { if ((cur_band->bandtype != BRCM_BAND_2G) || (stf != PHY_TXC1_MODE_SISO)) { - brcms_err(core, "wl%d: %s: Invalid CCK\n", + wiphy_err(wlc->wiphy, "wl%d: %s: Invalid CCK\n", wlc->pub->unit, __func__); bcmerror = -EINVAL; goto done; } } else { - brcms_err(core, "wl%d: %s: Unknown rate type\n", + wiphy_err(wlc->wiphy, "wl%d: %s: Unknown rate type\n", wlc->pub->unit, __func__); bcmerror = -EINVAL; goto done; } /* make sure multiple antennae are available for non-siso rates */ if ((stf != PHY_TXC1_MODE_SISO) && (wlc->stf->txstreams == 1)) { - brcms_err(core, "wl%d: %s: SISO antenna but !SISO " + wiphy_err(wlc->wiphy, "wl%d: %s: SISO antenna but !SISO " "request\n", wlc->pub->unit, __func__); bcmerror = -EINVAL; goto done; @@ -6041,7 +6449,7 @@ static void brcms_c_cck_plcp_set(struct brcms_c_info *wlc, int rate_500, break; default: - brcms_err(wlc->hw->d11core, + wiphy_err(wlc->wiphy, "brcms_c_cck_plcp_set: unsupported rate %d\n", rate_500); rate_500 = BRCM_RATE_1M; @@ -6174,7 +6582,7 @@ static u16 brcms_c_phytxctl1_calc(struct brcms_c_info *wlc, u32 rspec) bw = rspec_get_bw(rspec); /* 10Mhz is not supported yet */ if (bw < PHY_TXC1_BW_20MHZ) { - brcms_err(wlc->hw->d11core, "phytxctl1_calc: bw %d is " + wiphy_err(wlc->wiphy, "phytxctl1_calc: bw %d is " "not supported yet, set to 20L\n", bw); bw = PHY_TXC1_BW_20MHZ; } @@ -6201,7 +6609,7 @@ static u16 brcms_c_phytxctl1_calc(struct brcms_c_info *wlc, u32 rspec) /* get the phyctl byte from rate phycfg table */ phycfg = brcms_c_rate_legacy_phyctl(rspec2rate(rspec)); if (phycfg == -1) { - brcms_err(wlc->hw->d11core, "phytxctl1_calc: wrong " + wiphy_err(wlc->wiphy, "phytxctl1_calc: wrong " "legacy OFDM/CCK rate\n"); phycfg = 0; } @@ -6281,9 +6689,8 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw, if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { /* non-AP STA should never use BCMC queue */ if (queue == TX_BCMC_FIFO) { - brcms_err(wlc->hw->d11core, - "wl%d: %s: ASSERT queue == TX_BCMC!\n", - wlc->pub->unit, __func__); + wiphy_err(wlc->wiphy, "wl%d: %s: ASSERT queue == " + "TX_BCMC!\n", wlc->pub->unit, __func__); frameid = bcmc_fid_generate(wlc, NULL, txh); } else { /* Increment the counter for first fragment */ @@ -6453,8 +6860,7 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw, if ((txrate[k]->flags & IEEE80211_TX_RC_MCS) && (!is_mcs_rate(rspec[k]))) { - brcms_err(wlc->hw->d11core, - "wl%d: %s: IEEE80211_TX_" + wiphy_err(wlc->wiphy, "wl%d: %s: IEEE80211_TX_" "RC_MCS != is_mcs_rate(rspec)\n", wlc->pub->unit, __func__); } @@ -6848,16 +7254,14 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw, wlc->fragthresh[queue] = (u16) newfragthresh; } else { - brcms_err(wlc->hw->d11core, - "wl%d: %s txop invalid " + wiphy_err(wlc->wiphy, "wl%d: %s txop invalid " "for rate %d\n", wlc->pub->unit, fifo_names[queue], rspec2rate(rspec[0])); } if (dur > wlc->edcf_txop[ac]) - brcms_err(wlc->hw->d11core, - "wl%d: %s: %s txop " + wiphy_err(wlc->wiphy, "wl%d: %s: %s txop " "exceeded phylen %d/%d dur %d/%d\n", wlc->pub->unit, __func__, fifo_names[queue], @@ -6869,33 +7273,79 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw, return 0; } -static int brcms_c_tx(struct brcms_c_info *wlc, struct sk_buff *skb) +void brcms_c_sendpkt_mac80211(struct brcms_c_info *wlc, struct sk_buff *sdu, + struct ieee80211_hw *hw) { - struct dma_pub *dma; - int fifo, ret = -ENOSPC; - struct d11txh *txh; - u16 frameid = INVALIDFID; + u8 prio; + uint fifo; + struct scb *scb = &wlc->pri_scb; + struct ieee80211_hdr *d11_header = (struct ieee80211_hdr *)(sdu->data); - fifo = brcms_ac_to_fifo(skb_get_queue_mapping(skb)); - dma = wlc->hw->di[fifo]; - txh = (struct d11txh *)(skb->data); + /* + * 802.11 standard requires management traffic + * to go at highest priority + */ + prio = ieee80211_is_data(d11_header->frame_control) ? sdu->priority : + MAXPRIO; + fifo = prio2fifo[prio]; + if (brcms_c_d11hdrs_mac80211(wlc, hw, sdu, scb, 0, 1, fifo, 0)) + return; + brcms_c_txq_enq(wlc, scb, sdu, BRCMS_PRIO_TO_PREC(prio)); + brcms_c_send_q(wlc); +} - if (dma->txavail == 0) { - /* - * We sometimes get a frame from mac80211 after stopping - * the queues. This only ever seems to be a single frame - * and is seems likely to be a race. TX_HEADROOM should - * ensure that we have enough space to handle these stray - * packets, so warn if there isn't. If we're out of space - * in the tx ring and the tx queue isn't stopped then - * we've really got a bug; warn loudly if that happens. - */ - brcms_warn(wlc->hw->d11core, - "Received frame for tx with no space in DMA ring\n"); - WARN_ON(!ieee80211_queue_stopped(wlc->pub->ieee_hw, - skb_get_queue_mapping(skb))); - return -ENOSPC; +void brcms_c_send_q(struct brcms_c_info *wlc) +{ + struct sk_buff *pkt[DOT11_MAXNUMFRAGS]; + int prec; + u16 prec_map; + int err = 0, i, count; + uint fifo; + struct brcms_txq_info *qi = wlc->pkt_queue; + struct pktq *q = &qi->q; + struct ieee80211_tx_info *tx_info; + + prec_map = wlc->tx_prec_map; + + /* Send all the enq'd pkts that we can. + * Dequeue packets with precedence with empty HW fifo only + */ + while (prec_map && (pkt[0] = brcmu_pktq_mdeq(q, prec_map, &prec))) { + tx_info = IEEE80211_SKB_CB(pkt[0]); + if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { + err = brcms_c_sendampdu(wlc->ampdu, qi, pkt, prec); + } else { + count = 1; + err = brcms_c_prep_pdu(wlc, pkt[0], &fifo); + if (!err) { + for (i = 0; i < count; i++) + brcms_c_txfifo(wlc, fifo, pkt[i], true, + 1); + } + } + + if (err == -EBUSY) { + brcmu_pktq_penq_head(q, prec, pkt[0]); + /* + * If send failed due to any other reason than a + * change in HW FIFO condition, quit. Otherwise, + * read the new prec_map! + */ + if (prec_map == wlc->tx_prec_map) + break; + prec_map = wlc->tx_prec_map; + } } +} + +void +brcms_c_txfifo(struct brcms_c_info *wlc, uint fifo, struct sk_buff *p, + bool commit, s8 txpktpend) +{ + u16 frameid = INVALIDFID; + struct d11txh *txh; + + txh = (struct d11txh *) (p->data); /* When a BC/MC frame is being committed to the BCMC fifo * via DMA (NOT PIO), update ucode or BSS info as appropriate. @@ -6903,6 +7353,16 @@ static int brcms_c_tx(struct brcms_c_info *wlc, struct sk_buff *skb) if (fifo == TX_BCMC_FIFO) frameid = le16_to_cpu(txh->TxFrameID); + /* + * Bump up pending count for if not using rpc. If rpc is + * used, this will be handled in brcms_b_txfifo() + */ + if (commit) { + wlc->core->txpktpend[fifo] += txpktpend; + BCMMSG(wlc->wiphy, "pktpend inc %d to %d\n", + txpktpend, wlc->core->txpktpend[fifo]); + } + /* Commit BCMC sequence number in the SHM frame ID location */ if (frameid != INVALIDFID) { /* @@ -6912,55 +7372,8 @@ static int brcms_c_tx(struct brcms_c_info *wlc, struct sk_buff *skb) brcms_b_write_shm(wlc->hw, M_BCMC_FID, frameid); } - ret = brcms_c_txfifo(wlc, fifo, skb); - /* - * The only reason for brcms_c_txfifo to fail is because - * there weren't any DMA descriptors, but we've already - * checked for that. So if it does fail yell loudly. - */ - WARN_ON_ONCE(ret); - - return ret; -} - -bool brcms_c_sendpkt_mac80211(struct brcms_c_info *wlc, struct sk_buff *sdu, - struct ieee80211_hw *hw) -{ - uint fifo; - struct scb *scb = &wlc->pri_scb; - - fifo = brcms_ac_to_fifo(skb_get_queue_mapping(sdu)); - brcms_c_d11hdrs_mac80211(wlc, hw, sdu, scb, 0, 1, fifo, 0); - if (!brcms_c_tx(wlc, sdu)) - return true; - - /* packet discarded */ - dev_kfree_skb_any(sdu); - return false; -} - -int -brcms_c_txfifo(struct brcms_c_info *wlc, uint fifo, struct sk_buff *p) -{ - struct dma_pub *dma = wlc->hw->di[fifo]; - int ret; - u16 queue; - - ret = dma_txfast(wlc, dma, p); - if (ret < 0) + if (dma_txfast(wlc->hw->di[fifo], p, commit) < 0) wiphy_err(wlc->wiphy, "txfifo: fatal, toss frames !!!\n"); - - /* - * Stop queue if DMA ring is full. Reserve some free descriptors, - * as we sometimes receive a frame from mac80211 after the queues - * are stopped. - */ - queue = skb_get_queue_mapping(p); - if (dma->txavail <= TX_HEADROOM && fifo < TX_BCMC_FIFO && - !ieee80211_queue_stopped(wlc->pub->ieee_hw, queue)) - ieee80211_stop_queue(wlc->pub->ieee_hw, queue); - - return ret; } u32 @@ -7010,6 +7423,19 @@ brcms_c_rspec_to_rts_rspec(struct brcms_c_info *wlc, u32 rspec, return rts_rspec; } +void +brcms_c_txfifo_complete(struct brcms_c_info *wlc, uint fifo, s8 txpktpend) +{ + wlc->core->txpktpend[fifo] -= txpktpend; + BCMMSG(wlc->wiphy, "pktpend dec %d to %d\n", txpktpend, + wlc->core->txpktpend[fifo]); + + /* There is more room; mark precedences related to this FIFO sendable */ + wlc->tx_prec_map |= wlc->fifo2prec_map[fifo]; + + /* figure out which bsscfg is being worked on... */ +} + /* Update beacon listen interval in shared memory */ static void brcms_c_bcn_li_upd(struct brcms_c_info *wlc) { @@ -7082,7 +7508,7 @@ prep_mac80211_status(struct brcms_c_info *wlc, struct d11rxhdr *rxh, /* fill in TSF and flag its presence */ rx_status->mactime = brcms_c_recover_tsf64(wlc, rxh); - rx_status->flag |= RX_FLAG_MACTIME_START; + rx_status->flag |= RX_FLAG_MACTIME_MPDU; channel = BRCMS_CHAN_CHANNEL(rxh->RxChan); @@ -7145,8 +7571,7 @@ prep_mac80211_status(struct brcms_c_info *wlc, struct d11rxhdr *rxh, rx_status->rate_idx = 11; break; default: - brcms_err(wlc->hw->d11core, - "%s: Unknown rate\n", __func__); + wiphy_err(wlc->wiphy, "%s: Unknown rate\n", __func__); } /* @@ -7165,7 +7590,7 @@ prep_mac80211_status(struct brcms_c_info *wlc, struct d11rxhdr *rxh, } else if (is_ofdm_rate(rspec)) { rx_status->flag |= RX_FLAG_SHORTPRE; } else { - brcms_err(wlc->hw->d11core, "%s: Unknown modulation\n", + wiphy_err(wlc->wiphy, "%s: Unknown modulation\n", __func__); } } @@ -7175,12 +7600,12 @@ prep_mac80211_status(struct brcms_c_info *wlc, struct d11rxhdr *rxh, if (rxh->RxStatus1 & RXS_DECERR) { rx_status->flag |= RX_FLAG_FAILED_PLCP_CRC; - brcms_err(wlc->hw->d11core, "%s: RX_FLAG_FAILED_PLCP_CRC\n", + wiphy_err(wlc->wiphy, "%s: RX_FLAG_FAILED_PLCP_CRC\n", __func__); } if (rxh->RxStatus1 & RXS_FCSERR) { rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; - brcms_err(wlc->hw->d11core, "%s: RX_FLAG_FAILED_FCS_CRC\n", + wiphy_err(wlc->wiphy, "%s: RX_FLAG_FAILED_FCS_CRC\n", __func__); } } @@ -7224,6 +7649,9 @@ brcms_c_calc_lsig_len(struct brcms_c_info *wlc, u32 ratespec, { uint nsyms, len = 0, kNdps; + BCMMSG(wlc->wiphy, "wl%d: rate %d, len%d\n", + wlc->pub->unit, rspec2rate(ratespec), mac_len); + if (is_mcs_rate(ratespec)) { uint mcs = ratespec & RSPEC_RATE_MASK; int tot_streams = (mcs_2_txstreams(mcs) + 1) + @@ -7455,6 +7883,35 @@ void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend) brcms_c_bss_update_probe_resp(wlc, bsscfg, suspend); } +/* prepares pdu for transmission. returns BCM error codes */ +int brcms_c_prep_pdu(struct brcms_c_info *wlc, struct sk_buff *pdu, uint *fifop) +{ + uint fifo; + struct d11txh *txh; + struct ieee80211_hdr *h; + struct scb *scb; + + txh = (struct d11txh *) (pdu->data); + h = (struct ieee80211_hdr *)((u8 *) (txh + 1) + D11_PHY_HDR_LEN); + + /* get the pkt queue info. This was put at brcms_c_sendctl or + * brcms_c_send for PDU */ + fifo = le16_to_cpu(txh->TxFrameID) & TXFID_QUEUE_MASK; + + scb = NULL; + + *fifop = fifo; + + /* return if insufficient dma resources */ + if (*wlc->core->txavail[fifo] < MAX_DMA_SEGS) { + /* Mark precedences related to this FIFO, unsendable */ + /* A fifo is full. Clear precedences related to that FIFO */ + wlc->tx_prec_map &= ~(wlc->fifo2prec_map[fifo]); + return -EBUSY; + } + return 0; +} + int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo, uint *blocks) { @@ -7520,15 +7977,13 @@ int brcms_c_get_curband(struct brcms_c_info *wlc) void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc, bool drop) { int timeout = 20; - int i; - /* Kick DMA to send any pending AMPDU */ - for (i = 0; i < ARRAY_SIZE(wlc->hw->di); i++) - if (wlc->hw->di[i]) - dma_txflush(wlc->hw->di[i]); + /* flush packet queue when requested */ + if (drop) + brcmu_pktq_flush(&wlc->pkt_queue->q, false, NULL, NULL); /* wait for queue and DMA fifos to run dry */ - while (brcms_txpktpendtot(wlc) > 0) { + while (!pktq_empty(&wlc->pkt_queue->q) || brcms_txpktpendtot(wlc) > 0) { brcms_msleep(wlc->wl, 1); if (--timeout == 0) @@ -7577,6 +8032,8 @@ static void brcms_c_recv(struct brcms_c_info *wlc, struct sk_buff *p) uint len; bool is_amsdu; + BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); + /* frame starts with rxhdr */ rxh = (struct d11rxhdr *) (p->data); @@ -7586,9 +8043,8 @@ static void brcms_c_recv(struct brcms_c_info *wlc, struct sk_buff *p) /* MAC inserts 2 pad bytes for a4 headers or QoS or A-MSDU subframes */ if (rxh->RxStatus1 & RXS_PBPRES) { if (p->len < 2) { - brcms_err(wlc->hw->d11core, - "wl%d: recv: rcvd runt of len %d\n", - wlc->pub->unit, p->len); + wiphy_err(wlc->wiphy, "wl%d: recv: rcvd runt of " + "len %d\n", wlc->pub->unit, p->len); goto toss; } skb_pull(p, 2); @@ -7632,19 +8088,17 @@ brcms_b_recv(struct brcms_hardware *wlc_hw, uint fifo, bool bound) uint n = 0; uint bound_limit = bound ? RXBND : -1; - bool morepending; + BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); skb_queue_head_init(&recv_frames); /* gather received frames */ - do { + while (dma_rx(wlc_hw->di[fifo], &recv_frames)) { + /* !give others some time to run! */ - if (n >= bound_limit) + if (++n >= bound_limit) break; - - morepending = dma_rx(wlc_hw->di[fifo], &recv_frames); - n++; - } while (morepending); + } /* post more rbufs */ dma_rxfill(wlc_hw->di[fifo]); @@ -7674,7 +8128,7 @@ brcms_b_recv(struct brcms_hardware *wlc_hw, uint fifo, bool bound) brcms_c_recv(wlc_hw->wlc, p); } - return morepending; + return n >= bound_limit; } /* second-level interrupt processing @@ -7686,9 +8140,10 @@ bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded) u32 macintstatus; struct brcms_hardware *wlc_hw = wlc->hw; struct bcma_device *core = wlc_hw->d11core; + struct wiphy *wiphy = wlc->wiphy; if (brcms_deviceremoved(wlc)) { - brcms_err(core, "wl%d: %s: dead chip\n", wlc_hw->unit, + wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit, __func__); brcms_down(wlc->wl); return false; @@ -7698,8 +8153,8 @@ bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded) macintstatus = wlc->macintstatus; wlc->macintstatus = 0; - brcms_dbg_int(core, "wl%d: macintstatus 0x%x\n", - wlc_hw->unit, macintstatus); + BCMMSG(wlc->wiphy, "wl%d: macintstatus 0x%x\n", + wlc_hw->unit, macintstatus); WARN_ON(macintstatus & MI_PRQ); /* PRQ Interrupt in non-MBSS */ @@ -7709,7 +8164,7 @@ bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded) if (brcms_b_txstatus(wlc->hw, bounded, &fatal)) wlc->macintstatus |= MI_TFS; if (fatal) { - brcms_err(core, "MI_TFS: fatal\n"); + wiphy_err(wiphy, "MI_TFS: fatal\n"); goto fatal; } } @@ -7719,7 +8174,7 @@ bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded) /* ATIM window end */ if (macintstatus & MI_ATIMWINEND) { - brcms_dbg_info(core, "end of ATIM window\n"); + BCMMSG(wlc->wiphy, "end of ATIM window\n"); bcma_set32(core, D11REGOFFS(maccommand), wlc->qvalid); wlc->qvalid = 0; } @@ -7737,7 +8192,7 @@ bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded) wlc_phy_noise_sample_intr(wlc_hw->band->pi); if (macintstatus & MI_GP0) { - brcms_err(core, "wl%d: PSM microcode watchdog fired at %d " + wiphy_err(wiphy, "wl%d: PSM microcode watchdog fired at %d " "(seconds). Resetting.\n", wlc_hw->unit, wlc_hw->now); printk_once("%s : PSM Watchdog, chipid 0x%x, chiprev 0x%x\n", @@ -7751,11 +8206,15 @@ bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded) bcma_write32(core, D11REGOFFS(gptimer), 0); if (macintstatus & MI_RFDISABLE) { - brcms_dbg_info(core, "wl%d: BMAC Detected a change on the" - " RF Disable Input\n", wlc_hw->unit); + BCMMSG(wlc->wiphy, "wl%d: BMAC Detected a change on the" + " RF Disable Input\n", wlc_hw->unit); brcms_rfkill_set_hw_state(wlc->wl); } + /* send any enq'd tx packets. Just makes sure to jump start tx */ + if (!pktq_empty(&wlc->pkt_queue->q)) + brcms_c_send_q(wlc); + /* it isn't done and needs to be resched if macintstatus is non-zero */ return wlc->macintstatus != 0; @@ -7770,7 +8229,7 @@ void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx) struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.channel; u16 chanspec; - brcms_dbg_info(core, "wl%d\n", wlc->pub->unit); + BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); chanspec = ch20mhz_chspec(ch->hw_value); @@ -7827,6 +8286,9 @@ void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx) bcma_set16(core, D11REGOFFS(ifs_ctl), IFS_USEEDCF); brcms_c_edcf_setparams(wlc, false); + /* Init precedence maps for empty FIFOs */ + brcms_c_tx_prec_map_init(wlc); + /* read the ucode version if we have not yet done so */ if (wlc->ucode_rev == 0) { wlc->ucode_rev = @@ -7841,6 +8303,9 @@ void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx) if (mute_tx) brcms_b_mute(wlc->hw, true); + /* clear tx flow control */ + brcms_c_txflowcontrol_reset(wlc); + /* enable the RF Disable Delay timer */ bcma_write32(core, D11REGOFFS(rfdisabledly), RFDISABLE_DEFAULT); @@ -7999,6 +8464,15 @@ brcms_c_attach(struct brcms_info *wl, struct bcma_device *core, uint unit, * Complete the wlc default state initializations.. */ + /* allocate our initial queue */ + wlc->pkt_queue = brcms_c_txq_alloc(wlc); + if (wlc->pkt_queue == NULL) { + wiphy_err(wl->wiphy, "wl%d: %s: failed to malloc tx queue\n", + unit, __func__); + err = 100; + goto fail; + } + wlc->bsscfg->wlc = wlc; wlc->mimoft = FT_HT; diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/main.h b/trunk/drivers/net/wireless/brcm80211/brcmsmac/main.h index fb447747c2c6..8debc74c54e1 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/main.h +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/main.h @@ -101,6 +101,9 @@ #define DATA_BLOCK_TX_SUPR (1 << 4) +/* 802.1D Priority to TX FIFO number for wme */ +extern const u8 prio2fifo[]; + /* Ucode MCTL_WAKE override bits */ #define BRCMS_WAKE_OVERRIDE_CLKCTL 0x01 #define BRCMS_WAKE_OVERRIDE_PHYREG 0x02 @@ -239,6 +242,7 @@ struct brcms_core { /* fifo */ uint *txavail[NFIFO]; /* # tx descriptors available */ + s16 txpktpend[NFIFO]; /* tx admission control */ struct macstat *macstat_snapshot; /* mac hw prev read values */ }; @@ -378,6 +382,19 @@ struct brcms_hardware { */ }; +/* TX Queue information + * + * Each flow of traffic out of the device has a TX Queue with independent + * flow control. Several interfaces may be associated with a single TX Queue + * if they belong to the same flow of traffic from the device. For multi-channel + * operation there are independent TX Queues for each channel. + */ +struct brcms_txq_info { + struct brcms_txq_info *next; + struct pktq q; + uint stopped; /* tx flow control bits */ +}; + /* * Principal common driver data structure. * @@ -418,8 +435,11 @@ struct brcms_hardware { * WDlast: last time wlc_watchdog() was called. * edcf_txop[IEEE80211_NUM_ACS]: current txop for each ac. * wme_retries: per-AC retry limits. + * tx_prec_map: Precedence map based on HW FIFO space. + * fifo2prec_map[NFIFO]: pointer to fifo2_prec map based on WME. * bsscfg: set of BSS configurations, idx 0 is default and always valid. * cfg: the primary bsscfg (can be AP or STA). + * tx_queues: common TX Queue list. * modulecb: * mimoft: SIGN or 11N. * cck_40txbw: 11N, cck tx b/w override when in 40MHZ mode. @@ -449,6 +469,7 @@ struct brcms_hardware { * tempsense_lasttime; * tx_duty_cycle_ofdm: maximum allowed duty cycle for OFDM. * tx_duty_cycle_cck: maximum allowed duty cycle for CCK. + * pkt_queue: txq for transmit packets. * wiphy: * pri_scb: primary Station Control Block */ @@ -512,9 +533,14 @@ struct brcms_c_info { u16 edcf_txop[IEEE80211_NUM_ACS]; u16 wme_retries[IEEE80211_NUM_ACS]; + u16 tx_prec_map; + u16 fifo2prec_map[NFIFO]; struct brcms_bss_cfg *bsscfg; + /* tx queue */ + struct brcms_txq_info *tx_queues; + struct modulecb *modulecb; u8 mimoft; @@ -559,6 +585,7 @@ struct brcms_c_info { u16 tx_duty_cycle_ofdm; u16 tx_duty_cycle_cck; + struct brcms_txq_info *pkt_queue; struct wiphy *wiphy; struct scb pri_scb; }; @@ -610,13 +637,30 @@ struct brcms_bss_cfg { struct brcms_bss_info *current_bss; }; -extern int brcms_c_txfifo(struct brcms_c_info *wlc, uint fifo, - struct sk_buff *p); +extern void brcms_c_txfifo(struct brcms_c_info *wlc, uint fifo, + struct sk_buff *p, + bool commit, s8 txpktpend); +extern void brcms_c_txfifo_complete(struct brcms_c_info *wlc, uint fifo, + s8 txpktpend); +extern void brcms_c_txq_enq(struct brcms_c_info *wlc, struct scb *scb, + struct sk_buff *sdu, uint prec); +extern void brcms_c_print_txstatus(struct tx_status *txs); extern int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo, uint *blocks); +#if defined(DEBUG) +extern void brcms_c_print_txdesc(struct d11txh *txh); +#else +static inline void brcms_c_print_txdesc(struct d11txh *txh) +{ +} +#endif + extern int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config); extern void brcms_c_mac_promisc(struct brcms_c_info *wlc, uint filter_flags); +extern void brcms_c_send_q(struct brcms_c_info *wlc); +extern int brcms_c_prep_pdu(struct brcms_c_info *wlc, struct sk_buff *pdu, + uint *fifo); extern u16 brcms_c_calc_lsig_len(struct brcms_c_info *wlc, u32 ratespec, uint mac_len); extern u32 brcms_c_rspec_to_rts_rspec(struct brcms_c_info *wlc, diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c b/trunk/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c index 606b534347bc..abfd78822fb8 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c @@ -1137,9 +1137,8 @@ wlc_lcnphy_set_rx_gain_by_distribution(struct brcms_phy *pi, gain0_15 = ((biq1 & 0xf) << 12) | ((tia & 0xf) << 8) | ((lna2 & 0x3) << 6) | - ((lna2 & 0x3) << 4) | - ((lna1 & 0x3) << 2) | - ((lna1 & 0x3) << 0); + ((lna2 & + 0x3) << 4) | ((lna1 & 0x3) << 2) | ((lna1 & 0x3) << 0); mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0); mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0); @@ -1157,8 +1156,6 @@ wlc_lcnphy_set_rx_gain_by_distribution(struct brcms_phy *pi, } mod_phy_reg(pi, 0x44d, (0x1 << 0), (!trsw) << 0); - mod_phy_reg(pi, 0x4b1, (0x3 << 11), lna1 << 11); - mod_phy_reg(pi, 0x4e6, (0x3 << 3), lna1 << 3); } @@ -1331,43 +1328,6 @@ static u32 wlc_lcnphy_measure_digital_power(struct brcms_phy *pi, u16 nsamples) return (iq_est.i_pwr + iq_est.q_pwr) / nsamples; } -static bool wlc_lcnphy_rx_iq_cal_gain(struct brcms_phy *pi, u16 biq1_gain, - u16 tia_gain, u16 lna2_gain) -{ - u32 i_thresh_l, q_thresh_l; - u32 i_thresh_h, q_thresh_h; - struct lcnphy_iq_est iq_est_h, iq_est_l; - - wlc_lcnphy_set_rx_gain_by_distribution(pi, 0, 0, 0, biq1_gain, tia_gain, - lna2_gain, 0); - - wlc_lcnphy_rx_gain_override_enable(pi, true); - wlc_lcnphy_start_tx_tone(pi, 2000, (40 >> 1), 0); - usleep_range(500, 500); - write_radio_reg(pi, RADIO_2064_REG112, 0); - if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_l)) - return false; - - wlc_lcnphy_start_tx_tone(pi, 2000, 40, 0); - usleep_range(500, 500); - write_radio_reg(pi, RADIO_2064_REG112, 0); - if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_h)) - return false; - - i_thresh_l = (iq_est_l.i_pwr << 1); - i_thresh_h = (iq_est_l.i_pwr << 2) + iq_est_l.i_pwr; - - q_thresh_l = (iq_est_l.q_pwr << 1); - q_thresh_h = (iq_est_l.q_pwr << 2) + iq_est_l.q_pwr; - if ((iq_est_h.i_pwr > i_thresh_l) && - (iq_est_h.i_pwr < i_thresh_h) && - (iq_est_h.q_pwr > q_thresh_l) && - (iq_est_h.q_pwr < q_thresh_h)) - return true; - - return false; -} - static bool wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi, const struct lcnphy_rx_iqcomp *iqcomp, @@ -1382,8 +1342,8 @@ wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi, RFOverrideVal0_old, rfoverride2_old, rfoverride2val_old, rfoverride3_old, rfoverride3val_old, rfoverride4_old, rfoverride4val_old, afectrlovr_old, afectrlovrval_old; - int tia_gain, lna2_gain, biq1_gain; - bool set_gain; + int tia_gain; + u32 received_power, rx_pwr_threshold; u16 old_sslpnCalibClkEnCtrl, old_sslpnRxFeClkEnCtrl; u16 values_to_save[11]; s16 *ptr; @@ -1408,134 +1368,126 @@ wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi, goto cal_done; } - WARN_ON(module != 1); - tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); - wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); - - for (i = 0; i < 11; i++) - values_to_save[i] = - read_radio_reg(pi, rxiq_cal_rf_reg[i]); - Core1TxControl_old = read_phy_reg(pi, 0x631); - - or_phy_reg(pi, 0x631, 0x0015); - - RFOverride0_old = read_phy_reg(pi, 0x44c); - RFOverrideVal0_old = read_phy_reg(pi, 0x44d); - rfoverride2_old = read_phy_reg(pi, 0x4b0); - rfoverride2val_old = read_phy_reg(pi, 0x4b1); - rfoverride3_old = read_phy_reg(pi, 0x4f9); - rfoverride3val_old = read_phy_reg(pi, 0x4fa); - rfoverride4_old = read_phy_reg(pi, 0x938); - rfoverride4val_old = read_phy_reg(pi, 0x939); - afectrlovr_old = read_phy_reg(pi, 0x43b); - afectrlovrval_old = read_phy_reg(pi, 0x43c); - old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da); - old_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db); - - tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi); - if (tx_gain_override_old) { - wlc_lcnphy_get_tx_gain(pi, &old_gains); - tx_gain_index_old = pi_lcn->lcnphy_current_index; - } - - wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_idx); + if (module == 1) { - mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0); - mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0); + tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); + wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); - mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1); - mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1); + for (i = 0; i < 11; i++) + values_to_save[i] = + read_radio_reg(pi, rxiq_cal_rf_reg[i]); + Core1TxControl_old = read_phy_reg(pi, 0x631); + + or_phy_reg(pi, 0x631, 0x0015); + + RFOverride0_old = read_phy_reg(pi, 0x44c); + RFOverrideVal0_old = read_phy_reg(pi, 0x44d); + rfoverride2_old = read_phy_reg(pi, 0x4b0); + rfoverride2val_old = read_phy_reg(pi, 0x4b1); + rfoverride3_old = read_phy_reg(pi, 0x4f9); + rfoverride3val_old = read_phy_reg(pi, 0x4fa); + rfoverride4_old = read_phy_reg(pi, 0x938); + rfoverride4val_old = read_phy_reg(pi, 0x939); + afectrlovr_old = read_phy_reg(pi, 0x43b); + afectrlovrval_old = read_phy_reg(pi, 0x43c); + old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da); + old_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db); + + tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi); + if (tx_gain_override_old) { + wlc_lcnphy_get_tx_gain(pi, &old_gains); + tx_gain_index_old = pi_lcn->lcnphy_current_index; + } - write_radio_reg(pi, RADIO_2064_REG116, 0x06); - write_radio_reg(pi, RADIO_2064_REG12C, 0x07); - write_radio_reg(pi, RADIO_2064_REG06A, 0xd3); - write_radio_reg(pi, RADIO_2064_REG098, 0x03); - write_radio_reg(pi, RADIO_2064_REG00B, 0x7); - mod_radio_reg(pi, RADIO_2064_REG113, 1 << 4, 1 << 4); - write_radio_reg(pi, RADIO_2064_REG01D, 0x01); - write_radio_reg(pi, RADIO_2064_REG114, 0x01); - write_radio_reg(pi, RADIO_2064_REG02E, 0x10); - write_radio_reg(pi, RADIO_2064_REG12A, 0x08); - - mod_phy_reg(pi, 0x938, (0x1 << 0), 1 << 0); - mod_phy_reg(pi, 0x939, (0x1 << 0), 0 << 0); - mod_phy_reg(pi, 0x938, (0x1 << 1), 1 << 1); - mod_phy_reg(pi, 0x939, (0x1 << 1), 1 << 1); - mod_phy_reg(pi, 0x938, (0x1 << 2), 1 << 2); - mod_phy_reg(pi, 0x939, (0x1 << 2), 1 << 2); - mod_phy_reg(pi, 0x938, (0x1 << 3), 1 << 3); - mod_phy_reg(pi, 0x939, (0x1 << 3), 1 << 3); - mod_phy_reg(pi, 0x938, (0x1 << 5), 1 << 5); - mod_phy_reg(pi, 0x939, (0x1 << 5), 0 << 5); + wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_idx); - mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0); - mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0); + mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0); + mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0); - write_phy_reg(pi, 0x6da, 0xffff); - or_phy_reg(pi, 0x6db, 0x3); + mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1); + mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1); - wlc_lcnphy_set_trsw_override(pi, tx_switch, rx_switch); - set_gain = false; - - lna2_gain = 3; - while ((lna2_gain >= 0) && !set_gain) { - tia_gain = 4; - - while ((tia_gain >= 0) && !set_gain) { - biq1_gain = 6; - - while ((biq1_gain >= 0) && !set_gain) { - set_gain = wlc_lcnphy_rx_iq_cal_gain(pi, - (u16) - biq1_gain, - (u16) - tia_gain, - (u16) - lna2_gain); - biq1_gain -= 1; - } + write_radio_reg(pi, RADIO_2064_REG116, 0x06); + write_radio_reg(pi, RADIO_2064_REG12C, 0x07); + write_radio_reg(pi, RADIO_2064_REG06A, 0xd3); + write_radio_reg(pi, RADIO_2064_REG098, 0x03); + write_radio_reg(pi, RADIO_2064_REG00B, 0x7); + mod_radio_reg(pi, RADIO_2064_REG113, 1 << 4, 1 << 4); + write_radio_reg(pi, RADIO_2064_REG01D, 0x01); + write_radio_reg(pi, RADIO_2064_REG114, 0x01); + write_radio_reg(pi, RADIO_2064_REG02E, 0x10); + write_radio_reg(pi, RADIO_2064_REG12A, 0x08); + + mod_phy_reg(pi, 0x938, (0x1 << 0), 1 << 0); + mod_phy_reg(pi, 0x939, (0x1 << 0), 0 << 0); + mod_phy_reg(pi, 0x938, (0x1 << 1), 1 << 1); + mod_phy_reg(pi, 0x939, (0x1 << 1), 1 << 1); + mod_phy_reg(pi, 0x938, (0x1 << 2), 1 << 2); + mod_phy_reg(pi, 0x939, (0x1 << 2), 1 << 2); + mod_phy_reg(pi, 0x938, (0x1 << 3), 1 << 3); + mod_phy_reg(pi, 0x939, (0x1 << 3), 1 << 3); + mod_phy_reg(pi, 0x938, (0x1 << 5), 1 << 5); + mod_phy_reg(pi, 0x939, (0x1 << 5), 0 << 5); + + mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0); + mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0); + + wlc_lcnphy_start_tx_tone(pi, 2000, 120, 0); + write_phy_reg(pi, 0x6da, 0xffff); + or_phy_reg(pi, 0x6db, 0x3); + wlc_lcnphy_set_trsw_override(pi, tx_switch, rx_switch); + wlc_lcnphy_rx_gain_override_enable(pi, true); + + tia_gain = 8; + rx_pwr_threshold = 950; + while (tia_gain > 0) { tia_gain -= 1; + wlc_lcnphy_set_rx_gain_by_distribution(pi, + 0, 0, 2, 2, + (u16) + tia_gain, 1, 0); + udelay(500); + + received_power = + wlc_lcnphy_measure_digital_power(pi, 2000); + if (received_power < rx_pwr_threshold) + break; } - lna2_gain -= 1; - } + result = wlc_lcnphy_calc_rx_iq_comp(pi, 0xffff); - if (set_gain) - result = wlc_lcnphy_calc_rx_iq_comp(pi, 1024); - else - result = false; + wlc_lcnphy_stop_tx_tone(pi); - wlc_lcnphy_stop_tx_tone(pi); + write_phy_reg(pi, 0x631, Core1TxControl_old); - write_phy_reg(pi, 0x631, Core1TxControl_old); - - write_phy_reg(pi, 0x44c, RFOverrideVal0_old); - write_phy_reg(pi, 0x44d, RFOverrideVal0_old); - write_phy_reg(pi, 0x4b0, rfoverride2_old); - write_phy_reg(pi, 0x4b1, rfoverride2val_old); - write_phy_reg(pi, 0x4f9, rfoverride3_old); - write_phy_reg(pi, 0x4fa, rfoverride3val_old); - write_phy_reg(pi, 0x938, rfoverride4_old); - write_phy_reg(pi, 0x939, rfoverride4val_old); - write_phy_reg(pi, 0x43b, afectrlovr_old); - write_phy_reg(pi, 0x43c, afectrlovrval_old); - write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl); - write_phy_reg(pi, 0x6db, old_sslpnRxFeClkEnCtrl); + write_phy_reg(pi, 0x44c, RFOverrideVal0_old); + write_phy_reg(pi, 0x44d, RFOverrideVal0_old); + write_phy_reg(pi, 0x4b0, rfoverride2_old); + write_phy_reg(pi, 0x4b1, rfoverride2val_old); + write_phy_reg(pi, 0x4f9, rfoverride3_old); + write_phy_reg(pi, 0x4fa, rfoverride3val_old); + write_phy_reg(pi, 0x938, rfoverride4_old); + write_phy_reg(pi, 0x939, rfoverride4val_old); + write_phy_reg(pi, 0x43b, afectrlovr_old); + write_phy_reg(pi, 0x43c, afectrlovrval_old); + write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl); + write_phy_reg(pi, 0x6db, old_sslpnRxFeClkEnCtrl); - wlc_lcnphy_clear_trsw_override(pi); + wlc_lcnphy_clear_trsw_override(pi); - mod_phy_reg(pi, 0x44c, (0x1 << 2), 0 << 2); + mod_phy_reg(pi, 0x44c, (0x1 << 2), 0 << 2); - for (i = 0; i < 11; i++) - write_radio_reg(pi, rxiq_cal_rf_reg[i], - values_to_save[i]); + for (i = 0; i < 11; i++) + write_radio_reg(pi, rxiq_cal_rf_reg[i], + values_to_save[i]); - if (tx_gain_override_old) - wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_index_old); - else - wlc_lcnphy_disable_tx_gain_override(pi); + if (tx_gain_override_old) + wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_index_old); + else + wlc_lcnphy_disable_tx_gain_override(pi); - wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl); - wlc_lcnphy_rx_gain_override_enable(pi, false); + wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl); + wlc_lcnphy_rx_gain_override_enable(pi, false); + } cal_done: kfree(ptr); @@ -1829,17 +1781,6 @@ wlc_lcnphy_radio_2064_channel_tune_4313(struct brcms_phy *pi, u8 channel) write_radio_reg(pi, RADIO_2064_REG038, 3); write_radio_reg(pi, RADIO_2064_REG091, 7); } - - if (!(pi->sh->boardflags & BFL_FEM)) { - u8 reg038[14] = {0xd, 0xe, 0xd, 0xd, 0xd, 0xc, - 0xa, 0xb, 0xb, 0x3, 0x3, 0x2, 0x0, 0x0}; - - write_radio_reg(pi, RADIO_2064_REG02A, 0xf); - write_radio_reg(pi, RADIO_2064_REG091, 0x3); - write_radio_reg(pi, RADIO_2064_REG038, 0x3); - - write_radio_reg(pi, RADIO_2064_REG038, reg038[channel - 1]); - } } static int @@ -1919,6 +1860,41 @@ wlc_lcnphy_load_tx_iir_filter(struct brcms_phy *pi, bool is_ofdm, s16 filt_type) return (filt_index != -1) ? 0 : -1; } +void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi, u16 chanspec) +{ + u8 channel = CHSPEC_CHANNEL(chanspec); + + wlc_phy_chanspec_radio_set((struct brcms_phy_pub *) pi, chanspec); + + wlc_lcnphy_set_chanspec_tweaks(pi, pi->radio_chanspec); + + or_phy_reg(pi, 0x44a, 0x44); + write_phy_reg(pi, 0x44a, 0x80); + + wlc_lcnphy_radio_2064_channel_tune_4313(pi, channel); + udelay(1000); + + wlc_lcnphy_toggle_afe_pwdn(pi); + + write_phy_reg(pi, 0x657, lcnphy_sfo_cfg[channel - 1].ptcentreTs20); + write_phy_reg(pi, 0x658, lcnphy_sfo_cfg[channel - 1].ptcentreFactor); + + if (CHSPEC_CHANNEL(pi->radio_chanspec) == 14) { + mod_phy_reg(pi, 0x448, (0x3 << 8), (2) << 8); + + wlc_lcnphy_load_tx_iir_filter(pi, false, 3); + } else { + mod_phy_reg(pi, 0x448, (0x3 << 8), (1) << 8); + + wlc_lcnphy_load_tx_iir_filter(pi, false, 2); + } + + wlc_lcnphy_load_tx_iir_filter(pi, true, 0); + + mod_phy_reg(pi, 0x4eb, (0x7 << 3), (1) << 3); + +} + static u16 wlc_lcnphy_get_pa_gain(struct brcms_phy *pi) { u16 pa_gain; @@ -1960,21 +1936,6 @@ static void wlc_lcnphy_set_tx_gain(struct brcms_phy *pi, wlc_lcnphy_enable_tx_gain_override(pi); } -static u8 wlc_lcnphy_get_bbmult(struct brcms_phy *pi) -{ - u16 m0m1; - struct phytbl_info tab; - - tab.tbl_ptr = &m0m1; - tab.tbl_len = 1; - tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL; - tab.tbl_offset = 87; - tab.tbl_width = 16; - wlc_lcnphy_read_table(pi, &tab); - - return (u8) ((m0m1 & 0xff00) >> 8); -} - static void wlc_lcnphy_set_bbmult(struct brcms_phy *pi, u8 m0) { u16 m0m1 = (u16) m0 << 8; @@ -2034,16 +1995,6 @@ wlc_lcnphy_set_tssi_mux(struct brcms_phy *pi, enum lcnphy_tssi_mode pos) } else { mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0x1); mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8); - mod_radio_reg(pi, RADIO_2064_REG028, 0x1, 0x0); - mod_radio_reg(pi, RADIO_2064_REG11A, 0x4, 1<<2); - mod_radio_reg(pi, RADIO_2064_REG036, 0x10, 0x0); - mod_radio_reg(pi, RADIO_2064_REG11A, 0x10, 1<<4); - mod_radio_reg(pi, RADIO_2064_REG036, 0x3, 0x0); - mod_radio_reg(pi, RADIO_2064_REG035, 0xff, 0x77); - mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0xe<<1); - mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 1<<7); - mod_radio_reg(pi, RADIO_2064_REG005, 0x7, 1<<1); - mod_radio_reg(pi, RADIO_2064_REG029, 0xf0, 0<<4); } } else { mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0x1) << 2); @@ -2130,14 +2081,12 @@ static void wlc_lcnphy_pwrctrl_rssiparams(struct brcms_phy *pi) (auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12)); mod_radio_reg(pi, RADIO_2064_REG082, (1 << 5), (1 << 5)); - mod_radio_reg(pi, RADIO_2064_REG07C, (1 << 0), (1 << 0)); } static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi) { struct phytbl_info tab; u32 rfseq, ind; - u8 tssi_sel; tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; tab.tbl_width = 32; @@ -2159,13 +2108,7 @@ static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi) mod_phy_reg(pi, 0x503, (0x1 << 4), (1) << 4); - if (pi->sh->boardflags & BFL_FEM) { - tssi_sel = 0x1; - wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_EXT); - } else { - tssi_sel = 0xe; - wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_POST_PA); - } + wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_EXT); mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14); mod_phy_reg(pi, 0x4a4, (0x1 << 15), (1) << 15); @@ -2201,10 +2144,9 @@ static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi) mod_phy_reg(pi, 0x49a, (0x1ff << 0), (0xff) << 0); if (LCNREV_IS(pi->pubpi.phy_rev, 2)) { - mod_radio_reg(pi, RADIO_2064_REG028, 0xf, tssi_sel); + mod_radio_reg(pi, RADIO_2064_REG028, 0xf, 0xe); mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4); } else { - mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, tssi_sel << 1); mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1); mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 1 << 3); } @@ -2251,10 +2193,6 @@ static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi) mod_phy_reg(pi, 0x4d7, (0xf << 8), (0) << 8); - mod_radio_reg(pi, RADIO_2064_REG035, 0xff, 0x0); - mod_radio_reg(pi, RADIO_2064_REG036, 0x3, 0x0); - mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8); - wlc_lcnphy_pwrctrl_rssiparams(pi); } @@ -2873,8 +2811,6 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi) read_radio_reg(pi, RADIO_2064_REG007) & 1; u16 SAVE_jtag_auxpga = read_radio_reg(pi, RADIO_2064_REG0FF) & 0x10; u16 SAVE_iqadc_aux_en = read_radio_reg(pi, RADIO_2064_REG11F) & 4; - u8 SAVE_bbmult = wlc_lcnphy_get_bbmult(pi); - idleTssi = read_phy_reg(pi, 0x4ab); suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) & MCTL_EN_MAC)); @@ -2892,12 +2828,6 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi) mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 1 << 4); mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 1 << 2); wlc_lcnphy_tssi_setup(pi); - - mod_phy_reg(pi, 0x4d7, (0x1 << 0), (1 << 0)); - mod_phy_reg(pi, 0x4d7, (0x1 << 6), (1 << 6)); - - wlc_lcnphy_set_bbmult(pi, 0x0); - wlc_phy_do_dummy_tx(pi, true, OFF); idleTssi = ((read_phy_reg(pi, 0x4ab) & (0x1ff << 0)) >> 0); @@ -2919,7 +2849,6 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi) mod_phy_reg(pi, 0x44c, (0x1 << 12), (0) << 12); - wlc_lcnphy_set_bbmult(pi, SAVE_bbmult); wlc_lcnphy_set_tx_gain_override(pi, tx_gain_override_old); wlc_lcnphy_set_tx_gain(pi, &old_gains); wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl); @@ -3133,11 +3062,6 @@ static void wlc_lcnphy_tx_pwr_ctrl_init(struct brcms_phy_pub *ppi) wlc_lcnphy_write_table(pi, &tab); tab.tbl_offset++; } - mod_phy_reg(pi, 0x4d0, (0x1 << 0), (0) << 0); - mod_phy_reg(pi, 0x4d3, (0xff << 0), (0) << 0); - mod_phy_reg(pi, 0x4d3, (0xff << 8), (0) << 8); - mod_phy_reg(pi, 0x4d0, (0x1 << 4), (0) << 4); - mod_phy_reg(pi, 0x4d0, (0x1 << 2), (0) << 2); mod_phy_reg(pi, 0x410, (0x1 << 7), (0) << 7); @@ -3151,6 +3075,21 @@ static void wlc_lcnphy_tx_pwr_ctrl_init(struct brcms_phy_pub *ppi) wlapi_enable_mac(pi->sh->physhim); } +static u8 wlc_lcnphy_get_bbmult(struct brcms_phy *pi) +{ + u16 m0m1; + struct phytbl_info tab; + + tab.tbl_ptr = &m0m1; + tab.tbl_len = 1; + tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL; + tab.tbl_offset = 87; + tab.tbl_width = 16; + wlc_lcnphy_read_table(pi, &tab); + + return (u8) ((m0m1 & 0xff00) >> 8); +} + static void wlc_lcnphy_set_pa_gain(struct brcms_phy *pi, u16 gain) { mod_phy_reg(pi, 0x4fb, @@ -3939,6 +3878,7 @@ static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi) target_gains.pad_gain = 21; target_gains.dac_gain = 0; wlc_lcnphy_set_tx_gain(pi, &target_gains); + wlc_lcnphy_set_tx_pwr_by_index(pi, 16); if (LCNREV_IS(pi->pubpi.phy_rev, 1) || pi_lcn->lcnphy_hw_iqcal_en) { @@ -3949,7 +3889,6 @@ static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi) lcnphy_recal ? LCNPHY_CAL_RECAL : LCNPHY_CAL_FULL), false); } else { - wlc_lcnphy_set_tx_pwr_by_index(pi, 16); wlc_lcnphy_tx_iqlo_soft_cal_full(pi); } @@ -4374,22 +4313,17 @@ wlc_lcnphy_load_tx_gain_table(struct brcms_phy *pi, if (CHSPEC_IS5G(pi->radio_chanspec)) pa_gain = 0x70; else - pa_gain = 0x60; + pa_gain = 0x70; if (pi->sh->boardflags & BFL_FEM) pa_gain = 0x10; - tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; tab.tbl_width = 32; tab.tbl_len = 1; tab.tbl_ptr = &val; for (j = 0; j < 128; j++) { - if (pi->sh->boardflags & BFL_FEM) - gm_gain = gain_table[j].gm; - else - gm_gain = 15; - + gm_gain = gain_table[j].gm; val = (((u32) pa_gain << 24) | (gain_table[j].pad << 16) | (gain_table[j].pga << 8) | gm_gain); @@ -4600,10 +4534,7 @@ static void wlc_radio_2064_init(struct brcms_phy *pi) write_phy_reg(pi, 0x4ea, 0x4688); - if (pi->sh->boardflags & BFL_FEM) - mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0); - else - mod_phy_reg(pi, 0x4eb, (0x7 << 0), 3 << 0); + mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0); mod_phy_reg(pi, 0x4eb, (0x7 << 6), 0 << 6); @@ -4614,13 +4545,6 @@ static void wlc_radio_2064_init(struct brcms_phy *pi) wlc_lcnphy_rcal(pi); wlc_lcnphy_rc_cal(pi); - - if (!(pi->sh->boardflags & BFL_FEM)) { - write_radio_reg(pi, RADIO_2064_REG032, 0x6f); - write_radio_reg(pi, RADIO_2064_REG033, 0x19); - write_radio_reg(pi, RADIO_2064_REG039, 0xe); - } - } static void wlc_lcnphy_radio_init(struct brcms_phy *pi) @@ -4650,20 +4574,22 @@ static void wlc_lcnphy_tbl_init(struct brcms_phy *pi) wlc_lcnphy_write_table(pi, &tab); } - if (!(pi->sh->boardflags & BFL_FEM)) { - tab.tbl_id = LCNPHY_TBL_ID_RFSEQ; - tab.tbl_width = 16; - tab.tbl_ptr = &val; - tab.tbl_len = 1; + tab.tbl_id = LCNPHY_TBL_ID_RFSEQ; + tab.tbl_width = 16; + tab.tbl_ptr = &val; + tab.tbl_len = 1; - val = 150; - tab.tbl_offset = 0; - wlc_lcnphy_write_table(pi, &tab); + val = 114; + tab.tbl_offset = 0; + wlc_lcnphy_write_table(pi, &tab); - val = 220; - tab.tbl_offset = 1; - wlc_lcnphy_write_table(pi, &tab); - } + val = 130; + tab.tbl_offset = 1; + wlc_lcnphy_write_table(pi, &tab); + + val = 6; + tab.tbl_offset = 8; + wlc_lcnphy_write_table(pi, &tab); if (CHSPEC_IS2G(pi->radio_chanspec)) { if (pi->sh->boardflags & BFL_FEM) @@ -5020,44 +4946,6 @@ void wlc_phy_txpower_recalc_target_lcnphy(struct brcms_phy *pi) } } -void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi, u16 chanspec) -{ - u8 channel = CHSPEC_CHANNEL(chanspec); - - wlc_phy_chanspec_radio_set((struct brcms_phy_pub *)pi, chanspec); - - wlc_lcnphy_set_chanspec_tweaks(pi, pi->radio_chanspec); - - or_phy_reg(pi, 0x44a, 0x44); - write_phy_reg(pi, 0x44a, 0x80); - - wlc_lcnphy_radio_2064_channel_tune_4313(pi, channel); - udelay(1000); - - wlc_lcnphy_toggle_afe_pwdn(pi); - - write_phy_reg(pi, 0x657, lcnphy_sfo_cfg[channel - 1].ptcentreTs20); - write_phy_reg(pi, 0x658, lcnphy_sfo_cfg[channel - 1].ptcentreFactor); - - if (CHSPEC_CHANNEL(pi->radio_chanspec) == 14) { - mod_phy_reg(pi, 0x448, (0x3 << 8), (2) << 8); - - wlc_lcnphy_load_tx_iir_filter(pi, false, 3); - } else { - mod_phy_reg(pi, 0x448, (0x3 << 8), (1) << 8); - - wlc_lcnphy_load_tx_iir_filter(pi, false, 2); - } - - if (pi->sh->boardflags & BFL_FEM) - wlc_lcnphy_load_tx_iir_filter(pi, true, 0); - else - wlc_lcnphy_load_tx_iir_filter(pi, true, 3); - - mod_phy_reg(pi, 0x4eb, (0x7 << 3), (1) << 3); - wlc_lcnphy_tssi_setup(pi); -} - void wlc_phy_detach_lcnphy(struct brcms_phy *pi) { kfree(pi->u.pi_lcnphy); @@ -5094,7 +4982,8 @@ bool wlc_phy_attach_lcnphy(struct brcms_phy *pi) if (!wlc_phy_txpwr_srom_read_lcnphy(pi)) return false; - if (LCNREV_IS(pi->pubpi.phy_rev, 1)) { + if ((pi->sh->boardflags & BFL_FEM) && + (LCNREV_IS(pi->pubpi.phy_rev, 1))) { if (pi_lcn->lcnphy_tempsense_option == 3) { pi->hwpwrctrl = true; pi->hwpwrctrl_capable = true; diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c b/trunk/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c index b7e95acc2084..622c01ca72c5 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c @@ -1992,70 +1992,70 @@ static const u16 dot11lcn_sw_ctrl_tbl_4313_epa_rev0[] = { }; static const u16 dot11lcn_sw_ctrl_tbl_4313_rev0[] = { - 0x0009, 0x000a, - 0x0005, - 0x0006, 0x0009, - 0x000a, - 0x0005, 0x0006, - 0x0009, - 0x000a, 0x0005, - 0x0006, - 0x0009, 0x000a, - 0x0005, - 0x0006, 0x0009, - 0x000a, - 0x0005, 0x0006, - 0x0009, - 0x000a, 0x0005, - 0x0006, - 0x0009, 0x000a, - 0x0005, - 0x0006, 0x0009, - 0x000a, - 0x0005, 0x0006, - 0x0009, - 0x000a, 0x0005, - 0x0006, - 0x0009, 0x000a, - 0x0005, - 0x0006, 0x0009, - 0x000a, - 0x0005, 0x0006, - 0x0009, - 0x000a, 0x0005, - 0x0006, + 0x000a, 0x0009, + 0x0006, + 0x0005, 0x000a, + 0x0009, + 0x0006, 0x0005, + 0x000a, + 0x0009, 0x0006, + 0x0005, + 0x000a, 0x0009, + 0x0006, + 0x0005, 0x000a, + 0x0009, + 0x0006, 0x0005, + 0x000a, + 0x0009, 0x0006, + 0x0005, + 0x000a, 0x0009, + 0x0006, + 0x0005, 0x000a, + 0x0009, + 0x0006, 0x0005, + 0x000a, + 0x0009, 0x0006, + 0x0005, + 0x000a, 0x0009, + 0x0006, + 0x0005, 0x000a, + 0x0009, + 0x0006, 0x0005, + 0x000a, + 0x0009, 0x0006, + 0x0005, }; static const u16 dot11lcn_sw_ctrl_tbl_rev0[] = { diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/pub.h b/trunk/drivers/net/wireless/brcm80211/brcmsmac/pub.h index 4fb2834f4e64..5855f4fd16dc 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/pub.h +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/pub.h @@ -176,7 +176,6 @@ struct brcms_pub { bool phy_11ncapable; /* the PHY/HW is capable of 802.11N */ struct wl_cnt *_cnt; /* low-level counters in driver */ - struct dentry *dbgfs_dir; }; enum wlc_par_id { @@ -201,6 +200,43 @@ enum wlc_par_id { /* WL11N Support */ #define AMPDU_AGG_HOST 1 +/* pri is priority encoded in the packet. This maps the Packet priority to + * enqueue precedence as defined in wlc_prec_map + */ +extern const u8 wlc_prio2prec_map[]; +#define BRCMS_PRIO_TO_PREC(pri) wlc_prio2prec_map[(pri) & 7] + +#define BRCMS_PREC_COUNT 16 /* Max precedence level implemented */ + +/* Mask to describe all precedence levels */ +#define BRCMS_PREC_BMP_ALL MAXBITVAL(BRCMS_PREC_COUNT) + +/* + * This maps priority to one precedence higher - Used by PS-Poll response + * packets to simulate enqueue-at-head operation, but still maintain the + * order on the queue + */ +#define BRCMS_PRIO_TO_HI_PREC(pri) min(BRCMS_PRIO_TO_PREC(pri) + 1,\ + BRCMS_PREC_COUNT - 1) + +/* Define a bitmap of precedences comprised by each AC */ +#define BRCMS_PREC_BMP_AC_BE (NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_BE)) | \ + NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_BE)) | \ + NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_EE)) | \ + NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_EE))) +#define BRCMS_PREC_BMP_AC_BK (NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_BK)) | \ + NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_BK)) | \ + NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_NONE)) | \ + NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_NONE))) +#define BRCMS_PREC_BMP_AC_VI (NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_CL)) | \ + NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_CL)) | \ + NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_VI)) | \ + NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_VI))) +#define BRCMS_PREC_BMP_AC_VO (NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_VO)) | \ + NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_VO)) | \ + NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_NC)) | \ + NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_NC))) + /* network protection config */ #define BRCMS_PROT_G_SPEC 1 /* SPEC g protection */ #define BRCMS_PROT_G_OVR 2 /* SPEC g prot override */ @@ -283,9 +319,9 @@ extern void brcms_c_intrson(struct brcms_c_info *wlc); extern u32 brcms_c_intrsoff(struct brcms_c_info *wlc); extern void brcms_c_intrsrestore(struct brcms_c_info *wlc, u32 macintmask); extern bool brcms_c_intrsupd(struct brcms_c_info *wlc); -extern bool brcms_c_isr(struct brcms_c_info *wlc); +extern bool brcms_c_isr(struct brcms_c_info *wlc, bool *wantdpc); extern bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded); -extern bool brcms_c_sendpkt_mac80211(struct brcms_c_info *wlc, +extern void brcms_c_sendpkt_mac80211(struct brcms_c_info *wlc, struct sk_buff *sdu, struct ieee80211_hw *hw); extern bool brcms_c_aggregatable(struct brcms_c_info *wlc, u8 tid); diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/stf.c b/trunk/drivers/net/wireless/brcm80211/brcmsmac/stf.c index dd9162722495..ed1d1aa71d2d 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/stf.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/stf.c @@ -23,7 +23,6 @@ #include "channel.h" #include "main.h" #include "stf.h" -#include "debug.h" #define MIN_SPATIAL_EXPANSION 0 #define MAX_SPATIAL_EXPANSION 1 @@ -161,8 +160,8 @@ bool brcms_c_stf_stbc_rx_set(struct brcms_c_info *wlc, s32 int_val) static int brcms_c_stf_txcore_set(struct brcms_c_info *wlc, u8 Nsts, u8 core_mask) { - brcms_dbg_ht(wlc->hw->d11core, "wl%d: Nsts %d core_mask %x\n", - wlc->pub->unit, Nsts, core_mask); + BCMMSG(wlc->wiphy, "wl%d: Nsts %d core_mask %x\n", + wlc->pub->unit, Nsts, core_mask); if (hweight8(core_mask) > wlc->stf->txstreams) core_mask = 0; @@ -195,8 +194,7 @@ static int brcms_c_stf_spatial_policy_set(struct brcms_c_info *wlc, int val) int i; u8 core_mask = 0; - brcms_dbg_ht(wlc->hw->d11core, "wl%d: val %x\n", wlc->pub->unit, - val); + BCMMSG(wlc->wiphy, "wl%d: val %x\n", wlc->pub->unit, val); wlc->stf->spatial_policy = (s8) val; for (i = 1; i <= MAX_STREAMS_SUPPORTED; i++) { diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/types.h b/trunk/drivers/net/wireless/brcm80211/brcmsmac/types.h index ae1f3ad40d45..e11ae83111e4 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/types.h +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/types.h @@ -246,7 +246,7 @@ #define BCMMSG(dev, fmt, args...) \ do { \ - if (brcm_msg_level & BRCM_DL_INFO) \ + if (brcm_msg_level & LOG_TRACE_VAL) \ wiphy_err(dev, "%s: " fmt, __func__, ##args); \ } while (0) @@ -281,6 +281,7 @@ struct ieee80211_tx_queue_params; struct brcms_info; struct brcms_c_info; struct brcms_hardware; +struct brcms_txq_info; struct brcms_band; struct dma_pub; struct si_pub; diff --git a/trunk/drivers/net/wireless/brcm80211/include/defs.h b/trunk/drivers/net/wireless/brcm80211/include/defs.h index fb7cbcf81179..f0d8c04a9c8c 100644 --- a/trunk/drivers/net/wireless/brcm80211/include/defs.h +++ b/trunk/drivers/net/wireless/brcm80211/include/defs.h @@ -78,14 +78,9 @@ #define PM_OFF 0 #define PM_MAX 1 -/* Debug levels */ -#define BRCM_DL_INFO 0x00000001 -#define BRCM_DL_MAC80211 0x00000002 -#define BRCM_DL_RX 0x00000004 -#define BRCM_DL_TX 0x00000008 -#define BRCM_DL_INT 0x00000010 -#define BRCM_DL_DMA 0x00000020 -#define BRCM_DL_HT 0x00000040 +/* Message levels */ +#define LOG_ERROR_VAL 0x00000001 +#define LOG_TRACE_VAL 0x00000002 #define PM_OFF 0 #define PM_MAX 1 diff --git a/trunk/drivers/net/wireless/ipw2x00/ipw2200.c b/trunk/drivers/net/wireless/ipw2x00/ipw2200.c index 482f505f3f35..fea96b58ab89 100644 --- a/trunk/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/trunk/drivers/net/wireless/ipw2x00/ipw2200.c @@ -11269,31 +11269,10 @@ static const struct libipw_geo ipw_geos[] = { } }; -static void ipw_set_geo(struct ipw_priv *priv) -{ - int j; - - for (j = 0; j < ARRAY_SIZE(ipw_geos); j++) { - if (!memcmp(&priv->eeprom[EEPROM_COUNTRY_CODE], - ipw_geos[j].name, 3)) - break; - } - - if (j == ARRAY_SIZE(ipw_geos)) { - IPW_WARNING("SKU [%c%c%c] not recognized.\n", - priv->eeprom[EEPROM_COUNTRY_CODE + 0], - priv->eeprom[EEPROM_COUNTRY_CODE + 1], - priv->eeprom[EEPROM_COUNTRY_CODE + 2]); - j = 0; - } - - libipw_set_geo(priv->ieee, &ipw_geos[j]); -} - #define MAX_HW_RESTARTS 5 static int ipw_up(struct ipw_priv *priv) { - int rc, i; + int rc, i, j; /* Age scan list entries found before suspend */ if (priv->suspend_time) { @@ -11331,7 +11310,19 @@ static int ipw_up(struct ipw_priv *priv) memcpy(priv->net_dev->dev_addr, priv->mac_addr, ETH_ALEN); memcpy(priv->net_dev->perm_addr, priv->mac_addr, ETH_ALEN); - ipw_set_geo(priv); + for (j = 0; j < ARRAY_SIZE(ipw_geos); j++) { + if (!memcmp(&priv->eeprom[EEPROM_COUNTRY_CODE], + ipw_geos[j].name, 3)) + break; + } + if (j == ARRAY_SIZE(ipw_geos)) { + IPW_WARNING("SKU [%c%c%c] not recognized.\n", + priv->eeprom[EEPROM_COUNTRY_CODE + 0], + priv->eeprom[EEPROM_COUNTRY_CODE + 1], + priv->eeprom[EEPROM_COUNTRY_CODE + 2]); + j = 0; + } + libipw_set_geo(priv->ieee, &ipw_geos[j]); if (priv->status & STATUS_RF_KILL_SW) { IPW_WARNING("Radio disabled by module parameter.\n"); diff --git a/trunk/drivers/net/wireless/iwlegacy/3945.c b/trunk/drivers/net/wireless/iwlegacy/3945.c index e0b9d7fa5de0..87e539894330 100644 --- a/trunk/drivers/net/wireless/iwlegacy/3945.c +++ b/trunk/drivers/net/wireless/iwlegacy/3945.c @@ -516,7 +516,7 @@ static void il3945_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb) { struct ieee80211_hdr *header; - struct ieee80211_rx_status rx_status = {}; + struct ieee80211_rx_status rx_status; struct il_rx_pkt *pkt = rxb_addr(rxb); struct il3945_rx_frame_stats *rx_stats = IL_RX_STATS(pkt); struct il3945_rx_frame_hdr *rx_hdr = IL_RX_HDR(pkt); diff --git a/trunk/drivers/net/wireless/iwlegacy/4965-mac.c b/trunk/drivers/net/wireless/iwlegacy/4965-mac.c index 07ffa575e3ef..eac4dc8bc879 100644 --- a/trunk/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/trunk/drivers/net/wireless/iwlegacy/4965-mac.c @@ -613,7 +613,7 @@ void il4965_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb) { struct ieee80211_hdr *header; - struct ieee80211_rx_status rx_status = {}; + struct ieee80211_rx_status rx_status; struct il_rx_pkt *pkt = rxb_addr(rxb); struct il_rx_phy_res *phy_res; __le32 rx_pkt_status; @@ -686,7 +686,7 @@ il4965_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb) /* TSF isn't reliable. In order to allow smooth user experience, * this W/A doesn't propagate it to the mac80211 */ - /*rx_status.flag |= RX_FLAG_MACTIME_START; */ + /*rx_status.flag |= RX_FLAG_MACTIME_MPDU; */ il->ucode_beacon_time = le32_to_cpu(phy_res->beacon_time_stamp); diff --git a/trunk/drivers/net/wireless/iwlwifi/dvm/dev.h b/trunk/drivers/net/wireless/iwlwifi/dvm/dev.h index 29c571a56251..8141f91c3725 100644 --- a/trunk/drivers/net/wireless/iwlwifi/dvm/dev.h +++ b/trunk/drivers/net/wireless/iwlwifi/dvm/dev.h @@ -789,6 +789,7 @@ struct iwl_priv { /* remain-on-channel offload support */ struct ieee80211_channel *hw_roc_channel; 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; diff --git a/trunk/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/trunk/drivers/net/wireless/iwlwifi/dvm/mac80211.c index fb959b00b208..cb443d54f9b9 100644 --- a/trunk/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/trunk/drivers/net/wireless/iwlwifi/dvm/mac80211.c @@ -168,13 +168,8 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | IEEE80211_HW_SUPPORTS_STATIC_SMPS; - /* - * Enable 11w if advertised by firmware and software crypto - * is not enabled (as the firmware will interpret some mgmt - * packets, so enabling it with software crypto isn't safe) - */ - if (priv->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_MFP && - !iwlwifi_mod_params.sw_crypto) + /* enable 11w if the uCode advertise */ + if (capa->flags & IWL_UCODE_TLV_FLAGS_MFP) hw->flags |= IEEE80211_HW_MFP_CAPABLE; hw->sta_data_size = sizeof(struct iwl_station_priv); @@ -524,7 +519,7 @@ static void iwlagn_mac_tx(struct ieee80211_hw *hw, ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate); if (iwlagn_tx_skb(priv, control->sta, skb)) - ieee80211_free_txskb(hw, skb); + dev_kfree_skb_any(skb); } static void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw, @@ -1035,8 +1030,8 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop) } static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, struct ieee80211_channel *channel, + enum nl80211_channel_type channel_type, int duration) { struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); @@ -1068,6 +1063,7 @@ static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw, } priv->hw_roc_channel = channel; + priv->hw_roc_chantype = channel_type; /* convert from ms to TU */ priv->hw_roc_duration = DIV_ROUND_UP(1000 * duration, 1024); priv->hw_roc_start_notified = false; @@ -1356,20 +1352,6 @@ static int iwlagn_mac_add_interface(struct ieee80211_hw *hw, vif_priv->ctx = ctx; ctx->vif = vif; - /* - * In SNIFFER device type, the firmware reports the FCS to - * the host, rather than snipping it off. Unfortunately, - * mac80211 doesn't (yet) provide a per-packet flag for - * this, so that we have to set the hardware flag based - * on the interfaces added. As the monitor interface can - * only be present by itself, and will be removed before - * other interfaces are added, this is safe. - */ - if (vif->type == NL80211_IFTYPE_MONITOR) - priv->hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS; - else - priv->hw->flags &= ~IEEE80211_HW_RX_INCLUDES_FCS; - err = iwl_setup_interface(priv, ctx); if (!err || reset) goto out; diff --git a/trunk/drivers/net/wireless/iwlwifi/dvm/main.c b/trunk/drivers/net/wireless/iwlwifi/dvm/main.c index e3a07c916812..03cbfa765f87 100644 --- a/trunk/drivers/net/wireless/iwlwifi/dvm/main.c +++ b/trunk/drivers/net/wireless/iwlwifi/dvm/main.c @@ -1191,6 +1191,8 @@ static void iwl_option_config(struct iwl_priv *priv) static int iwl_eeprom_init_hw_params(struct iwl_priv *priv) { + priv->eeprom_data->sku = priv->eeprom_data->sku; + if (priv->eeprom_data->sku & EEPROM_SKU_CAP_11N_ENABLE && !priv->cfg->ht_params) { IWL_ERR(priv, "Invalid 11n configuration\n"); @@ -2105,7 +2107,7 @@ static void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb) info = IEEE80211_SKB_CB(skb); iwl_trans_free_tx_cmd(priv->trans, info->driver_data[1]); - ieee80211_free_txskb(priv->hw, skb); + dev_kfree_skb_any(skb); } static void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state) diff --git a/trunk/drivers/net/wireless/iwlwifi/dvm/rx.c b/trunk/drivers/net/wireless/iwlwifi/dvm/rx.c index cac4f37cc427..9a8d5020774e 100644 --- a/trunk/drivers/net/wireless/iwlwifi/dvm/rx.c +++ b/trunk/drivers/net/wireless/iwlwifi/dvm/rx.c @@ -899,7 +899,7 @@ static int iwlagn_rx_reply_rx(struct iwl_priv *priv, struct iwl_device_cmd *cmd) { struct ieee80211_hdr *header; - struct ieee80211_rx_status rx_status = {}; + struct ieee80211_rx_status rx_status; struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_rx_phy_res *phy_res; __le32 rx_pkt_status; @@ -949,7 +949,7 @@ static int iwlagn_rx_reply_rx(struct iwl_priv *priv, /* TSF isn't reliable. In order to allow smooth user experience, * this W/A doesn't propagate it to the mac80211 */ - /*rx_status.flag |= RX_FLAG_MACTIME_START;*/ + /*rx_status.flag |= RX_FLAG_MACTIME_MPDU;*/ priv->ucode_beacon_time = le32_to_cpu(phy_res->beacon_time_stamp); diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-config.h b/trunk/drivers/net/wireless/iwlwifi/iwl-config.h index 196266aa5a9d..87f465a49df1 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-config.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-config.h @@ -150,7 +150,7 @@ enum iwl_led_mode { struct iwl_base_params { int eeprom_size; int num_of_queues; /* def: HW dependent */ - /* for iwl_pcie_apm_init() */ + /* for iwl_apm_init() */ u32 pll_cfg_val; const u16 max_ll_items; diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-fh.h b/trunk/drivers/net/wireless/iwlwifi/iwl-fh.h index ec48563d3c6a..806046641747 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-fh.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-fh.h @@ -267,7 +267,7 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(unsigned int chnl) #define FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS (20) #define FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS (4) -#define RX_RB_TIMEOUT (0x11) +#define RX_RB_TIMEOUT (0x10) #define FH_RCSR_RX_CONFIG_CHNL_EN_PAUSE_VAL (0x00000000) #define FH_RCSR_RX_CONFIG_CHNL_EN_PAUSE_EOF_VAL (0x40000000) diff --git a/trunk/drivers/net/wireless/iwlwifi/pcie/drv.c b/trunk/drivers/net/wireless/iwlwifi/pcie/drv.c index 956fe6c370bc..2a4675396707 100644 --- a/trunk/drivers/net/wireless/iwlwifi/pcie/drv.c +++ b/trunk/drivers/net/wireless/iwlwifi/pcie/drv.c @@ -69,6 +69,7 @@ #include "iwl-trans.h" #include "iwl-drv.h" +#include "iwl-trans.h" #include "cfg.h" #include "internal.h" diff --git a/trunk/drivers/net/wireless/iwlwifi/pcie/internal.h b/trunk/drivers/net/wireless/iwlwifi/pcie/internal.h index d91d2e8c62f5..1f065c630d43 100644 --- a/trunk/drivers/net/wireless/iwlwifi/pcie/internal.h +++ b/trunk/drivers/net/wireless/iwlwifi/pcie/internal.h @@ -73,7 +73,7 @@ struct isr_statistics { }; /** - * struct iwl_rxq - Rx queue + * struct iwl_rx_queue - Rx queue * @bd: driver's pointer to buffer of receive buffer descriptors (rbd) * @bd_dma: bus address of buffer of receive buffer descriptors (rbd) * @pool: @@ -91,7 +91,7 @@ struct isr_statistics { * * NOTE: rx_free and rx_used are used as a FIFO for iwl_rx_mem_buffers */ -struct iwl_rxq { +struct iwl_rx_queue { __le32 *bd; dma_addr_t bd_dma; struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS]; @@ -157,8 +157,8 @@ struct iwl_cmd_meta { * 32 since we don't need so many commands pending. Since the HW * still uses 256 BDs for DMA though, n_bd stays 256. As a result, * the software buffers (in the variables @meta, @txb in struct - * iwl_txq) only have 32 entries, while the HW buffers (@tfds in - * the same struct) have 256. + * iwl_tx_queue) only have 32 entries, while the HW buffers (@tfds + * in the same struct) have 256. * This means that we end up with the following: * HW entries: | 0 | ... | N * 32 | ... | N * 32 + 31 | ... | 255 | * SW entries: | 0 | ... | 31 | @@ -182,7 +182,7 @@ struct iwl_queue { #define TFD_TX_CMD_SLOTS 256 #define TFD_CMD_SLOTS 32 -struct iwl_pcie_txq_entry { +struct iwl_pcie_tx_queue_entry { struct iwl_device_cmd *cmd; struct iwl_device_cmd *copy_cmd; struct sk_buff *skb; @@ -192,7 +192,7 @@ struct iwl_pcie_txq_entry { }; /** - * struct iwl_txq - Tx Queue for DMA + * struct iwl_tx_queue - Tx Queue for DMA * @q: generic Rx/Tx queue descriptor * @tfds: transmit frame descriptors (DMA memory) * @entries: transmit entries (driver state) @@ -205,10 +205,10 @@ struct iwl_pcie_txq_entry { * A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame * descriptors) and required locking structures. */ -struct iwl_txq { +struct iwl_tx_queue { struct iwl_queue q; struct iwl_tfd *tfds; - struct iwl_pcie_txq_entry *entries; + struct iwl_pcie_tx_queue_entry *entries; spinlock_t lock; struct timer_list stuck_timer; struct iwl_trans_pcie *trans_pcie; @@ -238,7 +238,7 @@ struct iwl_txq { * @wd_timeout: queue watchdog timeout (jiffies) */ struct iwl_trans_pcie { - struct iwl_rxq rxq; + struct iwl_rx_queue rxq; struct work_struct rx_replenish; struct iwl_trans *trans; struct iwl_drv *drv; @@ -260,7 +260,7 @@ struct iwl_trans_pcie { struct iwl_dma_ptr scd_bc_tbls; struct iwl_dma_ptr kw; - struct iwl_txq *txq; + struct iwl_tx_queue *txq; unsigned long queue_used[BITS_TO_LONGS(IWL_MAX_HW_QUEUES)]; unsigned long queue_stopped[BITS_TO_LONGS(IWL_MAX_HW_QUEUES)]; @@ -287,16 +287,10 @@ struct iwl_trans_pcie { unsigned long wd_timeout; }; -/** - * enum iwl_pcie_status: status of the PCIe transport - * @STATUS_HCMD_ACTIVE: a SYNC command is being processed - * @STATUS_DEVICE_ENABLED: APM is enabled - * @STATUS_TPOWER_PMI: the device might be asleep (need to wake it up) - * @STATUS_INT_ENABLED: interrupts are enabled - * @STATUS_RFKILL: the HW RFkill switch is in KILL position - * @STATUS_FW_ERROR: the fw is in error state - */ -enum iwl_pcie_status { +/***************************************************** +* DRIVER STATUS FUNCTIONS +******************************************************/ +enum { STATUS_HCMD_ACTIVE, STATUS_DEVICE_ENABLED, STATUS_TPOWER_PMI, @@ -315,10 +309,6 @@ iwl_trans_pcie_get_trans(struct iwl_trans_pcie *trans_pcie) trans_specific); } -/* - * Convention: trans API functions: iwl_trans_pcie_XXX - * Other functions: iwl_pcie_XXX - */ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, const struct pci_device_id *ent, const struct iwl_cfg *cfg); @@ -327,43 +317,51 @@ void iwl_trans_pcie_free(struct iwl_trans *trans); /***************************************************** * RX ******************************************************/ -int iwl_pcie_rx_init(struct iwl_trans *trans); -void iwl_pcie_tasklet(struct iwl_trans *trans); -int iwl_pcie_rx_stop(struct iwl_trans *trans); -void iwl_pcie_rx_free(struct iwl_trans *trans); +void iwl_bg_rx_replenish(struct work_struct *data); +void iwl_irq_tasklet(struct iwl_trans *trans); +void iwl_rx_replenish(struct iwl_trans *trans); +void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, + struct iwl_rx_queue *q); /***************************************************** -* ICT - interrupt handling +* ICT ******************************************************/ -irqreturn_t iwl_pcie_isr_ict(int irq, void *data); -int iwl_pcie_alloc_ict(struct iwl_trans *trans); -void iwl_pcie_free_ict(struct iwl_trans *trans); -void iwl_pcie_reset_ict(struct iwl_trans *trans); -void iwl_pcie_disable_ict(struct iwl_trans *trans); +void iwl_reset_ict(struct iwl_trans *trans); +void iwl_disable_ict(struct iwl_trans *trans); +int iwl_alloc_isr_ict(struct iwl_trans *trans); +void iwl_free_isr_ict(struct iwl_trans *trans); +irqreturn_t iwl_isr_ict(int irq, void *data); /***************************************************** * TX / HCMD ******************************************************/ -int iwl_pcie_tx_init(struct iwl_trans *trans); -void iwl_pcie_tx_start(struct iwl_trans *trans, u32 scd_base_addr); -int iwl_pcie_tx_stop(struct iwl_trans *trans); -void iwl_pcie_tx_free(struct iwl_trans *trans); +void iwl_txq_update_write_ptr(struct iwl_trans *trans, + struct iwl_tx_queue *txq); +int iwlagn_txq_attach_buf_to_tfd(struct iwl_trans *trans, + struct iwl_tx_queue *txq, + 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); +void iwl_tx_cmd_complete(struct iwl_trans *trans, + struct iwl_rx_cmd_buffer *rxb, int handler_status); +void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans, + struct iwl_tx_queue *txq, + u16 byte_cnt); void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo, int sta_id, int tid, int frame_limit, u16 ssn); void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int queue); -int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, - struct iwl_device_cmd *dev_cmd, int txq_id); -void iwl_pcie_txq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_txq *txq); -int iwl_trans_pcie_send_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd); -void iwl_pcie_hcmd_complete(struct iwl_trans *trans, - struct iwl_rx_cmd_buffer *rxb, int handler_status); -void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn, - struct sk_buff_head *skbs); +void iwl_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq, + enum dma_data_direction dma_dir); +int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, + struct sk_buff_head *skbs); +void iwl_tx_queue_unmap(struct iwl_trans *trans, int txq_id); +int iwl_queue_space(const struct iwl_queue *q); + /***************************************************** * Error handling ******************************************************/ -int iwl_pcie_dump_fh(struct iwl_trans *trans, char **buf); -void iwl_pcie_dump_csr(struct iwl_trans *trans); +int iwl_dump_fh(struct iwl_trans *trans, char **buf); +void iwl_dump_csr(struct iwl_trans *trans); /***************************************************** * Helpers @@ -399,7 +397,7 @@ static inline void iwl_enable_rfkill_int(struct iwl_trans *trans) } static inline void iwl_wake_queue(struct iwl_trans *trans, - struct iwl_txq *txq) + struct iwl_tx_queue *txq) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); @@ -410,7 +408,7 @@ static inline void iwl_wake_queue(struct iwl_trans *trans, } static inline void iwl_stop_queue(struct iwl_trans *trans, - struct iwl_txq *txq) + struct iwl_tx_queue *txq) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); @@ -422,7 +420,7 @@ static inline void iwl_stop_queue(struct iwl_trans *trans, txq->q.id); } -static inline bool iwl_queue_used(const struct iwl_queue *q, int i) +static inline int iwl_queue_used(const struct iwl_queue *q, int i) { return q->write_ptr >= q->read_ptr ? (i >= q->read_ptr && i < q->write_ptr) : @@ -434,8 +432,8 @@ static inline u8 get_cmd_index(struct iwl_queue *q, u32 index) return index & (q->n_window - 1); } -static inline const char *get_cmd_string(struct iwl_trans_pcie *trans_pcie, - u8 cmd) +static inline const char * +trans_pcie_get_cmd_string(struct iwl_trans_pcie *trans_pcie, u8 cmd) { if (!trans_pcie->command_names || !trans_pcie->command_names[cmd]) return "UNKNOWN"; diff --git a/trunk/drivers/net/wireless/iwlwifi/pcie/rx.c b/trunk/drivers/net/wireless/iwlwifi/pcie/rx.c index bb32510fdd62..11a93eddc84f 100644 --- a/trunk/drivers/net/wireless/iwlwifi/pcie/rx.c +++ b/trunk/drivers/net/wireless/iwlwifi/pcie/rx.c @@ -76,7 +76,7 @@ * + A list of pre-allocated SKBs is stored in iwl->rxq->rx_free. When * iwl->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled * to replenish the iwl->rxq->rx_free. - * + In iwl_pcie_rx_replenish (scheduled) if 'processed' != 'read' then the + * + In iwl_rx_replenish (scheduled) if 'processed' != 'read' then the * iwl->rxq is replenished and the READ INDEX is updated (updating the * 'processed' and 'read' driver indexes as well) * + A received packet is processed and handed to the kernel network stack, @@ -89,28 +89,28 @@ * * Driver sequence: * - * iwl_rxq_alloc() Allocates rx_free - * iwl_pcie_rx_replenish() Replenishes rx_free list from rx_used, and calls - * iwl_pcie_rxq_restock - * iwl_pcie_rxq_restock() Moves available buffers from rx_free into Rx + * iwl_rx_queue_alloc() Allocates rx_free + * iwl_rx_replenish() Replenishes rx_free list from rx_used, and calls + * iwl_rx_queue_restock + * iwl_rx_queue_restock() Moves available buffers from rx_free into Rx * queue, updates firmware pointers, and updates * the WRITE index. If insufficient rx_free buffers - * are available, schedules iwl_pcie_rx_replenish + * are available, schedules iwl_rx_replenish * * -- enable interrupts -- - * ISR - iwl_rx() Detach iwl_rx_mem_buffers from pool up to the + * ISR - iwl_rx() Detach iwl_rx_mem_buffers from pool up to the * READ INDEX, detaching the SKB from the pool. * Moves the packet buffer from queue to rx_used. - * Calls iwl_pcie_rxq_restock to refill any empty + * Calls iwl_rx_queue_restock to refill any empty * slots. * ... * */ -/* - * iwl_rxq_space - Return number of free slots available in queue. +/** + * iwl_rx_queue_space - Return number of free slots available in queue. */ -static int iwl_rxq_space(const struct iwl_rxq *q) +static int iwl_rx_queue_space(const struct iwl_rx_queue *q) { int s = q->read - q->write; if (s <= 0) @@ -122,28 +122,11 @@ static int iwl_rxq_space(const struct iwl_rxq *q) return s; } -/* - * iwl_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr - */ -static inline __le32 iwl_pcie_dma_addr2rbd_ptr(dma_addr_t dma_addr) -{ - return cpu_to_le32((u32)(dma_addr >> 8)); -} - -/* - * iwl_pcie_rx_stop - stops the Rx DMA - */ -int iwl_pcie_rx_stop(struct iwl_trans *trans) -{ - iwl_write_direct32(trans, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); - return iwl_poll_direct_bit(trans, FH_MEM_RSSR_RX_STATUS_REG, - FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000); -} - -/* - * iwl_pcie_rxq_inc_wr_ptr - Update the write pointer for the RX queue +/** + * iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue */ -static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_rxq *q) +void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, + struct iwl_rx_queue *q) { unsigned long flags; u32 reg; @@ -193,8 +176,16 @@ static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_rxq *q) spin_unlock_irqrestore(&q->lock, flags); } -/* - * iwl_pcie_rxq_restock - refill RX queue from pre-allocated pool +/** + * iwl_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr + */ +static inline __le32 iwl_dma_addr2rbd_ptr(dma_addr_t dma_addr) +{ + return cpu_to_le32((u32)(dma_addr >> 8)); +} + +/** + * iwl_rx_queue_restock - refill RX queue from pre-allocated pool * * If there are slots in the RX queue that need to be restocked, * and we have free pre-allocated buffers, fill the ranks as much @@ -204,10 +195,10 @@ static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_rxq *q) * also updates the memory address in the firmware to reference the new * target buffer. */ -static void iwl_pcie_rxq_restock(struct iwl_trans *trans) +static void iwl_rx_queue_restock(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rxq *rxq = &trans_pcie->rxq; + struct iwl_rx_queue *rxq = &trans_pcie->rxq; struct iwl_rx_mem_buffer *rxb; unsigned long flags; @@ -223,7 +214,7 @@ static void iwl_pcie_rxq_restock(struct iwl_trans *trans) return; spin_lock_irqsave(&rxq->lock, flags); - while ((iwl_rxq_space(rxq) > 0) && (rxq->free_count)) { + while ((iwl_rx_queue_space(rxq) > 0) && (rxq->free_count)) { /* The overwritten rxb must be a used one */ rxb = rxq->queue[rxq->write]; BUG_ON(rxb && rxb->page); @@ -234,7 +225,7 @@ static void iwl_pcie_rxq_restock(struct iwl_trans *trans) list_del(&rxb->list); /* Point to Rx buffer via next RBD in circular buffer */ - rxq->bd[rxq->write] = iwl_pcie_dma_addr2rbd_ptr(rxb->page_dma); + rxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(rxb->page_dma); rxq->queue[rxq->write] = rxb; rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; rxq->free_count--; @@ -251,23 +242,23 @@ static void iwl_pcie_rxq_restock(struct iwl_trans *trans) spin_lock_irqsave(&rxq->lock, flags); rxq->need_update = 1; spin_unlock_irqrestore(&rxq->lock, flags); - iwl_pcie_rxq_inc_wr_ptr(trans, rxq); + iwl_rx_queue_update_write_ptr(trans, rxq); } } /* - * iwl_pcie_rxq_alloc_rbs - allocate a page for each used RBD + * iwl_rx_allocate - allocate a page for each used RBD * * A used RBD is an Rx buffer that has been given to the stack. To use it again * a page must be allocated and the RBD must point to the page. This function * doesn't change the HW pointer but handles the list of pages that is used by - * iwl_pcie_rxq_restock. The latter function will update the HW to use the newly + * iwl_rx_queue_restock. The latter function will update the HW to use the newly * allocated buffers. */ -static void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans, gfp_t priority) +static void iwl_rx_allocate(struct iwl_trans *trans, gfp_t priority) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rxq *rxq = &trans_pcie->rxq; + struct iwl_rx_queue *rxq = &trans_pcie->rxq; struct iwl_rx_mem_buffer *rxb; struct page *page; unsigned long flags; @@ -327,14 +318,6 @@ static void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans, gfp_t priority) dma_map_page(trans->dev, page, 0, PAGE_SIZE << trans_pcie->rx_page_order, DMA_FROM_DEVICE); - if (dma_mapping_error(trans->dev, rxb->page_dma)) { - rxb->page = NULL; - spin_lock_irqsave(&rxq->lock, flags); - list_add(&rxb->list, &rxq->rx_used); - spin_unlock_irqrestore(&rxq->lock, flags); - __free_pages(page, trans_pcie->rx_page_order); - return; - } /* dma address must be no more than 36 bits */ BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36)); /* and also 256 byte aligned! */ @@ -349,227 +332,47 @@ static void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans, gfp_t priority) } } -static void iwl_pcie_rxq_free_rbs(struct iwl_trans *trans) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rxq *rxq = &trans_pcie->rxq; - int i; - - /* Fill the rx_used queue with _all_ of the Rx buffers */ - for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) { - /* In the reset function, these buffers may have been allocated - * to an SKB, so we need to unmap and free potential storage */ - if (rxq->pool[i].page != NULL) { - dma_unmap_page(trans->dev, rxq->pool[i].page_dma, - PAGE_SIZE << trans_pcie->rx_page_order, - DMA_FROM_DEVICE); - __free_pages(rxq->pool[i].page, - trans_pcie->rx_page_order); - rxq->pool[i].page = NULL; - } - list_add_tail(&rxq->pool[i].list, &rxq->rx_used); - } -} - /* - * iwl_pcie_rx_replenish - Move all used buffers from rx_used to rx_free + * iwl_rx_replenish - Move all used buffers from rx_used to rx_free * * When moving to rx_free an page is allocated for the slot. * - * Also restock the Rx queue via iwl_pcie_rxq_restock. + * Also restock the Rx queue via iwl_rx_queue_restock. * This is called as a scheduled work item (except for during initialization) */ -static void iwl_pcie_rx_replenish(struct iwl_trans *trans) +void iwl_rx_replenish(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); unsigned long flags; - iwl_pcie_rxq_alloc_rbs(trans, GFP_KERNEL); + iwl_rx_allocate(trans, GFP_KERNEL); spin_lock_irqsave(&trans_pcie->irq_lock, flags); - iwl_pcie_rxq_restock(trans); + iwl_rx_queue_restock(trans); spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); } -static void iwl_pcie_rx_replenish_now(struct iwl_trans *trans) +static void iwl_rx_replenish_now(struct iwl_trans *trans) { - iwl_pcie_rxq_alloc_rbs(trans, GFP_ATOMIC); + iwl_rx_allocate(trans, GFP_ATOMIC); - iwl_pcie_rxq_restock(trans); + iwl_rx_queue_restock(trans); } -static void iwl_pcie_rx_replenish_work(struct work_struct *data) +void iwl_bg_rx_replenish(struct work_struct *data) { struct iwl_trans_pcie *trans_pcie = container_of(data, struct iwl_trans_pcie, rx_replenish); - iwl_pcie_rx_replenish(trans_pcie->trans); -} - -static int iwl_pcie_rx_alloc(struct iwl_trans *trans) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rxq *rxq = &trans_pcie->rxq; - struct device *dev = trans->dev; - - memset(&trans_pcie->rxq, 0, sizeof(trans_pcie->rxq)); - - spin_lock_init(&rxq->lock); - - if (WARN_ON(rxq->bd || rxq->rb_stts)) - return -EINVAL; - - /* Allocate the circular buffer of Read Buffer Descriptors (RBDs) */ - rxq->bd = dma_zalloc_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE, - &rxq->bd_dma, GFP_KERNEL); - if (!rxq->bd) - goto err_bd; - - /*Allocate the driver's pointer to receive buffer status */ - rxq->rb_stts = dma_zalloc_coherent(dev, sizeof(*rxq->rb_stts), - &rxq->rb_stts_dma, GFP_KERNEL); - if (!rxq->rb_stts) - goto err_rb_stts; - - return 0; - -err_rb_stts: - dma_free_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE, - rxq->bd, rxq->bd_dma); - memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma)); - rxq->bd = NULL; -err_bd: - return -ENOMEM; + iwl_rx_replenish(trans_pcie->trans); } -static void iwl_pcie_rx_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - u32 rb_size; - const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */ - - if (trans_pcie->rx_buf_size_8k) - rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K; - else - rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K; - - /* Stop Rx DMA */ - iwl_write_direct32(trans, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); - - /* Reset driver's Rx queue write index */ - iwl_write_direct32(trans, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0); - - /* Tell device where to find RBD circular buffer in DRAM */ - iwl_write_direct32(trans, FH_RSCSR_CHNL0_RBDCB_BASE_REG, - (u32)(rxq->bd_dma >> 8)); - - /* Tell device where in DRAM to update its Rx status */ - iwl_write_direct32(trans, FH_RSCSR_CHNL0_STTS_WPTR_REG, - rxq->rb_stts_dma >> 4); - - /* Enable Rx DMA - * FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY is set because of HW bug in - * the credit mechanism in 5000 HW RX FIFO - * Direct rx interrupts to hosts - * Rx buffer size 4 or 8k - * RB timeout 0x10 - * 256 RBDs - */ - iwl_write_direct32(trans, FH_MEM_RCSR_CHNL0_CONFIG_REG, - FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | - FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY | - FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | - rb_size| - (RX_RB_TIMEOUT << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)| - (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS)); - - /* Set interrupt coalescing timer to default (2048 usecs) */ - iwl_write8(trans, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); -} - -int iwl_pcie_rx_init(struct iwl_trans *trans) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rxq *rxq = &trans_pcie->rxq; - - int i, err; - unsigned long flags; - - if (!rxq->bd) { - err = iwl_pcie_rx_alloc(trans); - if (err) - return err; - } - - spin_lock_irqsave(&rxq->lock, flags); - INIT_LIST_HEAD(&rxq->rx_free); - INIT_LIST_HEAD(&rxq->rx_used); - - INIT_WORK(&trans_pcie->rx_replenish, - iwl_pcie_rx_replenish_work); - - iwl_pcie_rxq_free_rbs(trans); - - for (i = 0; i < RX_QUEUE_SIZE; i++) - rxq->queue[i] = NULL; - - /* Set us so that we have processed and used all buffers, but have - * not restocked the Rx queue with fresh buffers */ - rxq->read = rxq->write = 0; - rxq->write_actual = 0; - rxq->free_count = 0; - spin_unlock_irqrestore(&rxq->lock, flags); - - iwl_pcie_rx_replenish(trans); - - iwl_pcie_rx_hw_init(trans, rxq); - - spin_lock_irqsave(&trans_pcie->irq_lock, flags); - rxq->need_update = 1; - iwl_pcie_rxq_inc_wr_ptr(trans, rxq); - spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); - - return 0; -} - -void iwl_pcie_rx_free(struct iwl_trans *trans) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rxq *rxq = &trans_pcie->rxq; - unsigned long flags; - - /*if rxq->bd is NULL, it means that nothing has been allocated, - * exit now */ - if (!rxq->bd) { - IWL_DEBUG_INFO(trans, "Free NULL rx context\n"); - return; - } - - spin_lock_irqsave(&rxq->lock, flags); - iwl_pcie_rxq_free_rbs(trans); - spin_unlock_irqrestore(&rxq->lock, flags); - - dma_free_coherent(trans->dev, sizeof(__le32) * RX_QUEUE_SIZE, - rxq->bd, rxq->bd_dma); - memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma)); - rxq->bd = NULL; - - if (rxq->rb_stts) - dma_free_coherent(trans->dev, - sizeof(struct iwl_rb_status), - rxq->rb_stts, rxq->rb_stts_dma); - else - IWL_DEBUG_INFO(trans, "Free rxq->rb_stts which is NULL\n"); - memset(&rxq->rb_stts_dma, 0, sizeof(rxq->rb_stts_dma)); - rxq->rb_stts = NULL; -} - -static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans, +static void iwl_rx_handle_rxbuf(struct iwl_trans *trans, struct iwl_rx_mem_buffer *rxb) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rxq *rxq = &trans_pcie->rxq; - struct iwl_txq *txq = &trans_pcie->txq[trans_pcie->cmd_queue]; + struct iwl_rx_queue *rxq = &trans_pcie->rxq; + struct iwl_tx_queue *txq = &trans_pcie->txq[trans_pcie->cmd_queue]; unsigned long flags; bool page_stolen = false; int max_len = PAGE_SIZE << trans_pcie->rx_page_order; @@ -599,7 +402,8 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans, break; IWL_DEBUG_RX(trans, "cmd at offset %d: %s (0x%.2x)\n", - rxcb._offset, get_cmd_string(trans_pcie, pkt->hdr.cmd), + rxcb._offset, + trans_pcie_get_cmd_string(trans_pcie, pkt->hdr.cmd), pkt->hdr.cmd); len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; @@ -631,7 +435,7 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans, cmd_index = get_cmd_index(&txq->q, index); if (reclaim) { - struct iwl_pcie_txq_entry *ent; + struct iwl_pcie_tx_queue_entry *ent; ent = &txq->entries[cmd_index]; cmd = ent->copy_cmd; WARN_ON_ONCE(!cmd && ent->meta.flags & CMD_WANT_HCMD); @@ -661,7 +465,7 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans, * iwl_trans_send_cmd() * as we reclaim the driver command queue */ if (!rxcb._page_stolen) - iwl_pcie_hcmd_complete(trans, &rxcb, err); + iwl_tx_cmd_complete(trans, &rxcb, err); else IWL_WARN(trans, "Claim null rxb?\n"); } @@ -685,31 +489,24 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans, dma_map_page(trans->dev, rxb->page, 0, PAGE_SIZE << trans_pcie->rx_page_order, DMA_FROM_DEVICE); - if (dma_mapping_error(trans->dev, rxb->page_dma)) { - /* - * free the page(s) as well to not break - * the invariant that the items on the used - * list have no page(s) - */ - __free_pages(rxb->page, trans_pcie->rx_page_order); - rxb->page = NULL; - list_add_tail(&rxb->list, &rxq->rx_used); - } else { - list_add_tail(&rxb->list, &rxq->rx_free); - rxq->free_count++; - } + list_add_tail(&rxb->list, &rxq->rx_free); + rxq->free_count++; } else list_add_tail(&rxb->list, &rxq->rx_used); spin_unlock_irqrestore(&rxq->lock, flags); } -/* - * iwl_pcie_rx_handle - Main entry function for receiving responses from fw +/** + * iwl_rx_handle - Main entry function for receiving responses from uCode + * + * Uses the priv->rx_handlers callback function array to invoke + * the appropriate handlers, including command responses, + * frame-received notifications, and other notifications. */ -static void iwl_pcie_rx_handle(struct iwl_trans *trans) +static void iwl_rx_handle(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rxq *rxq = &trans_pcie->rxq; + struct iwl_rx_queue *rxq = &trans_pcie->rxq; u32 r, i; u8 fill_rx = 0; u32 count = 8; @@ -740,7 +537,7 @@ static void iwl_pcie_rx_handle(struct iwl_trans *trans) IWL_DEBUG_RX(trans, "rxbuf: HW = %d, SW = %d (%p)\n", r, i, rxb); - iwl_pcie_rx_handle_rb(trans, rxb); + iwl_rx_handle_rxbuf(trans, rxb); i = (i + 1) & RX_QUEUE_MASK; /* If there are a lot of unused frames, @@ -749,7 +546,7 @@ static void iwl_pcie_rx_handle(struct iwl_trans *trans) count++; if (count >= 8) { rxq->read = i; - iwl_pcie_rx_replenish_now(trans); + iwl_rx_replenish_now(trans); count = 0; } } @@ -758,15 +555,15 @@ static void iwl_pcie_rx_handle(struct iwl_trans *trans) /* Backtrack one entry */ rxq->read = i; if (fill_rx) - iwl_pcie_rx_replenish_now(trans); + iwl_rx_replenish_now(trans); else - iwl_pcie_rxq_restock(trans); + iwl_rx_queue_restock(trans); } -/* - * iwl_pcie_irq_handle_error - called for HW or SW error interrupt from card +/** + * iwl_irq_handle_error - called for HW or SW error interrupt from card */ -static void iwl_pcie_irq_handle_error(struct iwl_trans *trans) +static void iwl_irq_handle_error(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); @@ -782,8 +579,8 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans) return; } - iwl_pcie_dump_csr(trans); - iwl_pcie_dump_fh(trans, NULL); + iwl_dump_csr(trans); + iwl_dump_fh(trans, NULL); set_bit(STATUS_FW_ERROR, &trans_pcie->status); clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status); @@ -792,7 +589,8 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans) iwl_op_mode_nic_error(trans->op_mode); } -void iwl_pcie_tasklet(struct iwl_trans *trans) +/* tasklet for iwlagn interrupt */ +void iwl_irq_tasklet(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct isr_statistics *isr_stats = &trans_pcie->isr_stats; @@ -844,7 +642,7 @@ void iwl_pcie_tasklet(struct iwl_trans *trans) iwl_disable_interrupts(trans); isr_stats->hw++; - iwl_pcie_irq_handle_error(trans); + iwl_irq_handle_error(trans); handled |= CSR_INT_BIT_HW_ERR; @@ -907,16 +705,17 @@ void iwl_pcie_tasklet(struct iwl_trans *trans) IWL_ERR(trans, "Microcode SW error detected. " " Restarting 0x%X.\n", inta); isr_stats->sw++; - iwl_pcie_irq_handle_error(trans); + iwl_irq_handle_error(trans); handled |= CSR_INT_BIT_SW_ERR; } /* uCode wakes up after power-down sleep */ if (inta & CSR_INT_BIT_WAKEUP) { IWL_DEBUG_ISR(trans, "Wakeup interrupt\n"); - iwl_pcie_rxq_inc_wr_ptr(trans, &trans_pcie->rxq); + iwl_rx_queue_update_write_ptr(trans, &trans_pcie->rxq); for (i = 0; i < trans->cfg->base_params->num_of_queues; i++) - iwl_pcie_txq_inc_wr_ptr(trans, &trans_pcie->txq[i]); + iwl_txq_update_write_ptr(trans, + &trans_pcie->txq[i]); isr_stats->wakeup++; @@ -954,7 +753,7 @@ void iwl_pcie_tasklet(struct iwl_trans *trans) iwl_write8(trans, CSR_INT_PERIODIC_REG, CSR_INT_PERIODIC_DIS); - iwl_pcie_rx_handle(trans); + iwl_rx_handle(trans); /* * Enable periodic interrupt in 8 msec only if we received @@ -1012,7 +811,7 @@ void iwl_pcie_tasklet(struct iwl_trans *trans) #define ICT_COUNT (ICT_SIZE / sizeof(u32)) /* Free dram table */ -void iwl_pcie_free_ict(struct iwl_trans *trans) +void iwl_free_isr_ict(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); @@ -1025,12 +824,13 @@ void iwl_pcie_free_ict(struct iwl_trans *trans) } } + /* * allocate dram shared table, it is an aligned memory * block of ICT_SIZE. * also reset all data related to ICT table interrupt. */ -int iwl_pcie_alloc_ict(struct iwl_trans *trans) +int iwl_alloc_isr_ict(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); @@ -1043,7 +843,7 @@ int iwl_pcie_alloc_ict(struct iwl_trans *trans) /* just an API sanity check ... it is guaranteed to be aligned */ if (WARN_ON(trans_pcie->ict_tbl_dma & (ICT_SIZE - 1))) { - iwl_pcie_free_ict(trans); + iwl_free_isr_ict(trans); return -EINVAL; } @@ -1064,7 +864,7 @@ int iwl_pcie_alloc_ict(struct iwl_trans *trans) /* Device is going up inform it about using ICT interrupt table, * also we need to tell the driver to start using ICT interrupt. */ -void iwl_pcie_reset_ict(struct iwl_trans *trans) +void iwl_reset_ict(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); u32 val; @@ -1094,7 +894,7 @@ void iwl_pcie_reset_ict(struct iwl_trans *trans) } /* Device is going down disable ict interrupt usage */ -void iwl_pcie_disable_ict(struct iwl_trans *trans) +void iwl_disable_ict(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); unsigned long flags; @@ -1105,7 +905,7 @@ void iwl_pcie_disable_ict(struct iwl_trans *trans) } /* legacy (non-ICT) ISR. Assumes that trans_pcie->irq_lock is held */ -static irqreturn_t iwl_pcie_isr(int irq, void *data) +static irqreturn_t iwl_isr(int irq, void *data) { struct iwl_trans *trans = data; struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); @@ -1152,7 +952,7 @@ static irqreturn_t iwl_pcie_isr(int irq, void *data) #endif trans_pcie->inta |= inta; - /* iwl_pcie_tasklet() will service interrupts and re-enable them */ + /* iwl_irq_tasklet() will service interrupts and re-enable them */ if (likely(inta)) tasklet_schedule(&trans_pcie->irq_tasklet); else if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) && @@ -1177,7 +977,7 @@ static irqreturn_t iwl_pcie_isr(int irq, void *data) * the interrupt we need to service, driver will set the entries back to 0 and * set index. */ -irqreturn_t iwl_pcie_isr_ict(int irq, void *data) +irqreturn_t iwl_isr_ict(int irq, void *data) { struct iwl_trans *trans = data; struct iwl_trans_pcie *trans_pcie; @@ -1197,13 +997,14 @@ irqreturn_t iwl_pcie_isr_ict(int irq, void *data) * use legacy interrupt. */ if (unlikely(!trans_pcie->use_ict)) { - irqreturn_t ret = iwl_pcie_isr(irq, data); + irqreturn_t ret = iwl_isr(irq, data); spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); return ret; } trace_iwlwifi_dev_irq(trans->dev); + /* Disable (but don't clear!) interrupts here to avoid * back-to-back ISRs and sporadic interrupts from our NIC. * If we have something to service, the tasklet will re-enable ints. @@ -1212,6 +1013,7 @@ irqreturn_t iwl_pcie_isr_ict(int irq, void *data) inta_mask = iwl_read32(trans, CSR_INT_MASK); /* just for debug */ iwl_write32(trans, CSR_INT_MASK, 0x00000000); + /* Ignore interrupt if there's nothing in NIC to service. * This may be due to IRQ shared with another device, * or due to sporadic interrupts thrown from our NIC. */ @@ -1260,7 +1062,7 @@ irqreturn_t iwl_pcie_isr_ict(int irq, void *data) inta &= trans_pcie->inta_mask; trans_pcie->inta |= inta; - /* iwl_pcie_tasklet() will service interrupts and re-enable them */ + /* iwl_irq_tasklet() will service interrupts and re-enable them */ if (likely(inta)) tasklet_schedule(&trans_pcie->irq_tasklet); else if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) && diff --git a/trunk/drivers/net/wireless/iwlwifi/pcie/trans.c b/trunk/drivers/net/wireless/iwlwifi/pcie/trans.c index f6c21e7edaf2..f21bf661931d 100644 --- a/trunk/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/trunk/drivers/net/wireless/iwlwifi/pcie/trans.c @@ -74,8 +74,585 @@ #include "iwl-prph.h" #include "iwl-agn-hw.h" #include "internal.h" +/* FIXME: need to abstract out TX command (once we know what it looks like) */ +#include "dvm/commands.h" -static void iwl_pcie_set_pwr_vmain(struct iwl_trans *trans) +#define SCD_QUEUECHAIN_SEL_ALL(trans, trans_pcie) \ + (((1<cfg->base_params->num_of_queues) - 1) &\ + (~(1<<(trans_pcie)->cmd_queue))) + +static int iwl_trans_rx_alloc(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 device *dev = trans->dev; + + memset(&trans_pcie->rxq, 0, sizeof(trans_pcie->rxq)); + + spin_lock_init(&rxq->lock); + + if (WARN_ON(rxq->bd || rxq->rb_stts)) + return -EINVAL; + + /* Allocate the circular buffer of Read Buffer Descriptors (RBDs) */ + rxq->bd = dma_zalloc_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE, + &rxq->bd_dma, GFP_KERNEL); + if (!rxq->bd) + goto err_bd; + + /*Allocate the driver's pointer to receive buffer status */ + rxq->rb_stts = dma_zalloc_coherent(dev, sizeof(*rxq->rb_stts), + &rxq->rb_stts_dma, GFP_KERNEL); + if (!rxq->rb_stts) + goto err_rb_stts; + + return 0; + +err_rb_stts: + dma_free_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE, + rxq->bd, rxq->bd_dma); + memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma)); + rxq->bd = NULL; +err_bd: + return -ENOMEM; +} + +static void iwl_trans_rxq_free_rx_bufs(struct iwl_trans *trans) +{ + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_rx_queue *rxq = &trans_pcie->rxq; + int i; + + /* Fill the rx_used queue with _all_ of the Rx buffers */ + for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) { + /* In the reset function, these buffers may have been allocated + * to an SKB, so we need to unmap and free potential storage */ + if (rxq->pool[i].page != NULL) { + dma_unmap_page(trans->dev, rxq->pool[i].page_dma, + PAGE_SIZE << trans_pcie->rx_page_order, + DMA_FROM_DEVICE); + __free_pages(rxq->pool[i].page, + trans_pcie->rx_page_order); + rxq->pool[i].page = NULL; + } + list_add_tail(&rxq->pool[i].list, &rxq->rx_used); + } +} + +static void iwl_trans_rx_hw_init(struct iwl_trans *trans, + struct iwl_rx_queue *rxq) +{ + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + u32 rb_size; + const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */ + u32 rb_timeout = RX_RB_TIMEOUT; /* FIXME: RX_RB_TIMEOUT for all devices? */ + + if (trans_pcie->rx_buf_size_8k) + rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K; + else + rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K; + + /* Stop Rx DMA */ + iwl_write_direct32(trans, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); + + /* Reset driver's Rx queue write index */ + iwl_write_direct32(trans, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0); + + /* Tell device where to find RBD circular buffer in DRAM */ + iwl_write_direct32(trans, FH_RSCSR_CHNL0_RBDCB_BASE_REG, + (u32)(rxq->bd_dma >> 8)); + + /* Tell device where in DRAM to update its Rx status */ + iwl_write_direct32(trans, FH_RSCSR_CHNL0_STTS_WPTR_REG, + rxq->rb_stts_dma >> 4); + + /* Enable Rx DMA + * FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY is set because of HW bug in + * the credit mechanism in 5000 HW RX FIFO + * Direct rx interrupts to hosts + * Rx buffer size 4 or 8k + * RB timeout 0x10 + * 256 RBDs + */ + iwl_write_direct32(trans, FH_MEM_RCSR_CHNL0_CONFIG_REG, + FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | + FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY | + FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | + rb_size| + (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)| + (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS)); + + /* Set interrupt coalescing timer to default (2048 usecs) */ + iwl_write8(trans, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); +} + +static int iwl_rx_init(struct iwl_trans *trans) +{ + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_rx_queue *rxq = &trans_pcie->rxq; + + int i, err; + unsigned long flags; + + if (!rxq->bd) { + err = iwl_trans_rx_alloc(trans); + if (err) + return err; + } + + spin_lock_irqsave(&rxq->lock, flags); + INIT_LIST_HEAD(&rxq->rx_free); + INIT_LIST_HEAD(&rxq->rx_used); + + iwl_trans_rxq_free_rx_bufs(trans); + + for (i = 0; i < RX_QUEUE_SIZE; i++) + rxq->queue[i] = NULL; + + /* Set us so that we have processed and used all buffers, but have + * not restocked the Rx queue with fresh buffers */ + rxq->read = rxq->write = 0; + rxq->write_actual = 0; + rxq->free_count = 0; + spin_unlock_irqrestore(&rxq->lock, flags); + + iwl_rx_replenish(trans); + + iwl_trans_rx_hw_init(trans, rxq); + + spin_lock_irqsave(&trans_pcie->irq_lock, flags); + rxq->need_update = 1; + iwl_rx_queue_update_write_ptr(trans, rxq); + spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); + + return 0; +} + +static void iwl_trans_pcie_rx_free(struct iwl_trans *trans) +{ + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_rx_queue *rxq = &trans_pcie->rxq; + unsigned long flags; + + /*if rxq->bd is NULL, it means that nothing has been allocated, + * exit now */ + if (!rxq->bd) { + IWL_DEBUG_INFO(trans, "Free NULL rx context\n"); + return; + } + + spin_lock_irqsave(&rxq->lock, flags); + iwl_trans_rxq_free_rx_bufs(trans); + spin_unlock_irqrestore(&rxq->lock, flags); + + dma_free_coherent(trans->dev, sizeof(__le32) * RX_QUEUE_SIZE, + rxq->bd, rxq->bd_dma); + memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma)); + rxq->bd = NULL; + + if (rxq->rb_stts) + dma_free_coherent(trans->dev, + sizeof(struct iwl_rb_status), + rxq->rb_stts, rxq->rb_stts_dma); + else + IWL_DEBUG_INFO(trans, "Free rxq->rb_stts which is NULL\n"); + memset(&rxq->rb_stts_dma, 0, sizeof(rxq->rb_stts_dma)); + rxq->rb_stts = NULL; +} + +static int iwl_trans_rx_stop(struct iwl_trans *trans) +{ + + /* stop Rx DMA */ + iwl_write_direct32(trans, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); + return iwl_poll_direct_bit(trans, FH_MEM_RSSR_RX_STATUS_REG, + FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000); +} + +static int iwlagn_alloc_dma_ptr(struct iwl_trans *trans, + struct iwl_dma_ptr *ptr, size_t size) +{ + if (WARN_ON(ptr->addr)) + return -EINVAL; + + ptr->addr = dma_alloc_coherent(trans->dev, size, + &ptr->dma, GFP_KERNEL); + if (!ptr->addr) + return -ENOMEM; + ptr->size = size; + return 0; +} + +static void iwlagn_free_dma_ptr(struct iwl_trans *trans, + struct iwl_dma_ptr *ptr) +{ + if (unlikely(!ptr->addr)) + return; + + dma_free_coherent(trans->dev, ptr->size, ptr->addr, ptr->dma); + memset(ptr, 0, sizeof(*ptr)); +} + +static void iwl_trans_pcie_queue_stuck_timer(unsigned long data) +{ + struct iwl_tx_queue *txq = (void *)data; + struct iwl_queue *q = &txq->q; + struct iwl_trans_pcie *trans_pcie = txq->trans_pcie; + struct iwl_trans *trans = iwl_trans_pcie_get_trans(trans_pcie); + u32 scd_sram_addr = trans_pcie->scd_base_addr + + SCD_TX_STTS_QUEUE_OFFSET(txq->q.id); + u8 buf[16]; + int i; + + spin_lock(&txq->lock); + /* check if triggered erroneously */ + if (txq->q.read_ptr == txq->q.write_ptr) { + spin_unlock(&txq->lock); + return; + } + spin_unlock(&txq->lock); + + IWL_ERR(trans, "Queue %d stuck for %u ms.\n", txq->q.id, + jiffies_to_msecs(trans_pcie->wd_timeout)); + IWL_ERR(trans, "Current SW read_ptr %d write_ptr %d\n", + txq->q.read_ptr, txq->q.write_ptr); + + iwl_read_targ_mem_bytes(trans, scd_sram_addr, buf, sizeof(buf)); + + iwl_print_hex_error(trans, buf, sizeof(buf)); + + for (i = 0; i < FH_TCSR_CHNL_NUM; i++) + IWL_ERR(trans, "FH TRBs(%d) = 0x%08x\n", i, + iwl_read_direct32(trans, FH_TX_TRB_REG(i))); + + for (i = 0; i < trans->cfg->base_params->num_of_queues; i++) { + u32 status = iwl_read_prph(trans, SCD_QUEUE_STATUS_BITS(i)); + u8 fifo = (status >> SCD_QUEUE_STTS_REG_POS_TXF) & 0x7; + bool active = !!(status & BIT(SCD_QUEUE_STTS_REG_POS_ACTIVE)); + u32 tbl_dw = + iwl_read_targ_mem(trans, + trans_pcie->scd_base_addr + + SCD_TRANS_TBL_OFFSET_QUEUE(i)); + + if (i & 0x1) + tbl_dw = (tbl_dw & 0xFFFF0000) >> 16; + else + tbl_dw = tbl_dw & 0x0000FFFF; + + IWL_ERR(trans, + "Q %d is %sactive and mapped to fifo %d ra_tid 0x%04x [%d,%d]\n", + i, active ? "" : "in", fifo, tbl_dw, + iwl_read_prph(trans, + SCD_QUEUE_RDPTR(i)) & (txq->q.n_bd - 1), + iwl_read_prph(trans, SCD_QUEUE_WRPTR(i))); + } + + for (i = q->read_ptr; i != q->write_ptr; + i = iwl_queue_inc_wrap(i, q->n_bd)) { + struct iwl_tx_cmd *tx_cmd = + (struct iwl_tx_cmd *)txq->entries[i].cmd->payload; + IWL_ERR(trans, "scratch %d = 0x%08x\n", i, + get_unaligned_le32(&tx_cmd->scratch)); + } + + iwl_op_mode_nic_error(trans->op_mode); +} + +static int iwl_trans_txq_alloc(struct iwl_trans *trans, + struct iwl_tx_queue *txq, int slots_num, + u32 txq_id) +{ + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + size_t tfd_sz = sizeof(struct iwl_tfd) * TFD_QUEUE_SIZE_MAX; + int i; + + if (WARN_ON(txq->entries || txq->tfds)) + return -EINVAL; + + setup_timer(&txq->stuck_timer, iwl_trans_pcie_queue_stuck_timer, + (unsigned long)txq); + txq->trans_pcie = trans_pcie; + + txq->q.n_window = slots_num; + + txq->entries = kcalloc(slots_num, + sizeof(struct iwl_pcie_tx_queue_entry), + GFP_KERNEL); + + if (!txq->entries) + goto error; + + if (txq_id == trans_pcie->cmd_queue) + for (i = 0; i < slots_num; i++) { + txq->entries[i].cmd = + kmalloc(sizeof(struct iwl_device_cmd), + GFP_KERNEL); + if (!txq->entries[i].cmd) + goto error; + } + + /* Circular buffer of transmit frame descriptors (TFDs), + * shared with device */ + txq->tfds = dma_alloc_coherent(trans->dev, tfd_sz, + &txq->q.dma_addr, GFP_KERNEL); + if (!txq->tfds) { + IWL_ERR(trans, "dma_alloc_coherent(%zd) failed\n", tfd_sz); + goto error; + } + txq->q.id = txq_id; + + return 0; +error: + if (txq->entries && txq_id == trans_pcie->cmd_queue) + for (i = 0; i < slots_num; i++) + kfree(txq->entries[i].cmd); + kfree(txq->entries); + txq->entries = NULL; + + return -ENOMEM; + +} + +static int iwl_trans_txq_init(struct iwl_trans *trans, struct iwl_tx_queue *txq, + int slots_num, u32 txq_id) +{ + int ret; + + txq->need_update = 0; + + /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise + * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */ + BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1)); + + /* Initialize queue's high/low-water marks, and head/tail indexes */ + ret = iwl_queue_init(&txq->q, TFD_QUEUE_SIZE_MAX, slots_num, + txq_id); + if (ret) + return ret; + + spin_lock_init(&txq->lock); + + /* + * Tell nic where to find circular buffer of Tx Frame Descriptors for + * given Tx queue, and enable the DMA channel used for that queue. + * Circular buffer (TFD queue in DRAM) physical base address */ + iwl_write_direct32(trans, FH_MEM_CBBC_QUEUE(txq_id), + txq->q.dma_addr >> 8); + + return 0; +} + +/* + * iwl_tx_queue_unmap - Unmap any remaining DMA mappings and free skb's + */ +void iwl_tx_queue_unmap(struct iwl_trans *trans, int txq_id) +{ + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id]; + struct iwl_queue *q = &txq->q; + enum dma_data_direction dma_dir; + + if (!q->n_bd) + return; + + /* In the command queue, all the TBs are mapped as BIDI + * so unmap them as such. + */ + if (txq_id == trans_pcie->cmd_queue) + dma_dir = DMA_BIDIRECTIONAL; + else + dma_dir = DMA_TO_DEVICE; + + spin_lock_bh(&txq->lock); + while (q->write_ptr != q->read_ptr) { + iwl_txq_free_tfd(trans, txq, dma_dir); + q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); + } + spin_unlock_bh(&txq->lock); +} + +/** + * iwl_tx_queue_free - Deallocate DMA queue. + * @txq: Transmit queue to deallocate. + * + * Empty queue by removing and destroying all BD's. + * Free all buffers. + * 0-fill, but do not free "txq" descriptor structure. + */ +static void iwl_tx_queue_free(struct iwl_trans *trans, int txq_id) +{ + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id]; + struct device *dev = trans->dev; + int i; + + if (WARN_ON(!txq)) + return; + + iwl_tx_queue_unmap(trans, txq_id); + + /* De-alloc array of command/tx buffers */ + if (txq_id == trans_pcie->cmd_queue) + for (i = 0; i < txq->q.n_window; i++) { + kfree(txq->entries[i].cmd); + kfree(txq->entries[i].copy_cmd); + kfree(txq->entries[i].free_buf); + } + + /* De-alloc circular buffer of TFDs */ + if (txq->q.n_bd) { + dma_free_coherent(dev, sizeof(struct iwl_tfd) * + txq->q.n_bd, txq->tfds, txq->q.dma_addr); + memset(&txq->q.dma_addr, 0, sizeof(txq->q.dma_addr)); + } + + kfree(txq->entries); + txq->entries = NULL; + + del_timer_sync(&txq->stuck_timer); + + /* 0-fill queue descriptor structure */ + memset(txq, 0, sizeof(*txq)); +} + +/** + * iwl_trans_tx_free - Free TXQ Context + * + * Destroy all TX DMA queues and structures + */ +static void iwl_trans_pcie_tx_free(struct iwl_trans *trans) +{ + int txq_id; + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + + /* Tx queues */ + if (trans_pcie->txq) { + for (txq_id = 0; + txq_id < trans->cfg->base_params->num_of_queues; txq_id++) + iwl_tx_queue_free(trans, txq_id); + } + + kfree(trans_pcie->txq); + trans_pcie->txq = NULL; + + iwlagn_free_dma_ptr(trans, &trans_pcie->kw); + + iwlagn_free_dma_ptr(trans, &trans_pcie->scd_bc_tbls); +} + +/** + * iwl_trans_tx_alloc - allocate TX context + * Allocate all Tx DMA structures and initialize them + * + * @param priv + * @return error code + */ +static int iwl_trans_tx_alloc(struct iwl_trans *trans) +{ + int ret; + int txq_id, slots_num; + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + + u16 scd_bc_tbls_size = trans->cfg->base_params->num_of_queues * + sizeof(struct iwlagn_scd_bc_tbl); + + /*It is not allowed to alloc twice, so warn when this happens. + * We cannot rely on the previous allocation, so free and fail */ + if (WARN_ON(trans_pcie->txq)) { + ret = -EINVAL; + goto error; + } + + ret = iwlagn_alloc_dma_ptr(trans, &trans_pcie->scd_bc_tbls, + scd_bc_tbls_size); + if (ret) { + IWL_ERR(trans, "Scheduler BC Table allocation failed\n"); + goto error; + } + + /* Alloc keep-warm buffer */ + ret = iwlagn_alloc_dma_ptr(trans, &trans_pcie->kw, IWL_KW_SIZE); + if (ret) { + IWL_ERR(trans, "Keep Warm allocation failed\n"); + goto error; + } + + trans_pcie->txq = kcalloc(trans->cfg->base_params->num_of_queues, + sizeof(struct iwl_tx_queue), GFP_KERNEL); + if (!trans_pcie->txq) { + IWL_ERR(trans, "Not enough memory for txq\n"); + ret = ENOMEM; + goto error; + } + + /* Alloc and init all Tx queues, including the command queue (#4/#9) */ + for (txq_id = 0; txq_id < trans->cfg->base_params->num_of_queues; + txq_id++) { + slots_num = (txq_id == trans_pcie->cmd_queue) ? + TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; + ret = iwl_trans_txq_alloc(trans, &trans_pcie->txq[txq_id], + slots_num, txq_id); + if (ret) { + IWL_ERR(trans, "Tx %d queue alloc failed\n", txq_id); + goto error; + } + } + + return 0; + +error: + iwl_trans_pcie_tx_free(trans); + + return ret; +} +static int iwl_tx_init(struct iwl_trans *trans) +{ + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + int ret; + int txq_id, slots_num; + unsigned long flags; + bool alloc = false; + + if (!trans_pcie->txq) { + ret = iwl_trans_tx_alloc(trans); + if (ret) + goto error; + alloc = true; + } + + spin_lock_irqsave(&trans_pcie->irq_lock, flags); + + /* Turn off all Tx DMA fifos */ + iwl_write_prph(trans, SCD_TXFACT, 0); + + /* Tell NIC where to find the "keep warm" buffer */ + iwl_write_direct32(trans, FH_KW_MEM_ADDR_REG, + trans_pcie->kw.dma >> 4); + + spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); + + /* Alloc and init all Tx queues, including the command queue (#4/#9) */ + for (txq_id = 0; txq_id < trans->cfg->base_params->num_of_queues; + txq_id++) { + slots_num = (txq_id == trans_pcie->cmd_queue) ? + TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; + ret = iwl_trans_txq_init(trans, &trans_pcie->txq[txq_id], + slots_num, txq_id); + if (ret) { + IWL_ERR(trans, "Tx %d queue init failed\n", txq_id); + goto error; + } + } + + return 0; +error: + /*Upon error, free only if we allocated something */ + if (alloc) + iwl_trans_pcie_tx_free(trans); + return ret; +} + +static void iwl_set_pwr_vmain(struct iwl_trans *trans) { /* * (for documentation purposes) @@ -97,11 +674,18 @@ static void iwl_pcie_set_pwr_vmain(struct iwl_trans *trans) #define PCI_CFG_LINK_CTRL_VAL_L0S_EN 0x01 #define PCI_CFG_LINK_CTRL_VAL_L1_EN 0x02 -static void iwl_pcie_apm_config(struct iwl_trans *trans) +static u16 iwl_pciexp_link_ctrl(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - u16 lctl; + u16 pci_lnk_ctl; + pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_LNKCTL, + &pci_lnk_ctl); + return pci_lnk_ctl; +} + +static void iwl_apm_config(struct iwl_trans *trans) +{ /* * HW bug W/A for instability in PCIe bus L0S->L1 transition. * Check if BIOS (or OS) enabled L1-ASPM on this device. @@ -110,7 +694,7 @@ static void iwl_pcie_apm_config(struct iwl_trans *trans) * If not (unlikely), enable L0S, so there is at least some * power savings, even without L1. */ - pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_LNKCTL, &lctl); + u16 lctl = iwl_pciexp_link_ctrl(trans); if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) == PCI_CFG_LINK_CTRL_VAL_L1_EN) { @@ -127,10 +711,10 @@ static void iwl_pcie_apm_config(struct iwl_trans *trans) /* * Start up NIC's basic functionality after it has been reset - * (e.g. after platform boot, or shutdown via iwl_pcie_apm_stop()) + * (e.g. after platform boot, or shutdown via iwl_apm_stop()) * NOTE: This does not load uCode nor start the embedded processor */ -static int iwl_pcie_apm_init(struct iwl_trans *trans) +static int iwl_apm_init(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); int ret = 0; @@ -162,7 +746,7 @@ static int iwl_pcie_apm_init(struct iwl_trans *trans) iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A); - iwl_pcie_apm_config(trans); + iwl_apm_config(trans); /* Configure analog phase-lock-loop before activating to D0A */ if (trans->cfg->base_params->pll_cfg_val) @@ -208,7 +792,7 @@ static int iwl_pcie_apm_init(struct iwl_trans *trans) return ret; } -static int iwl_pcie_apm_stop_master(struct iwl_trans *trans) +static int iwl_apm_stop_master(struct iwl_trans *trans) { int ret = 0; @@ -226,7 +810,7 @@ static int iwl_pcie_apm_stop_master(struct iwl_trans *trans) return ret; } -static void iwl_pcie_apm_stop(struct iwl_trans *trans) +static void iwl_apm_stop(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); IWL_DEBUG_INFO(trans, "Stop card, put in low power state\n"); @@ -234,7 +818,7 @@ static void iwl_pcie_apm_stop(struct iwl_trans *trans) clear_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status); /* Stop device's DMA activity */ - iwl_pcie_apm_stop_master(trans); + iwl_apm_stop_master(trans); /* Reset the entire device */ iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); @@ -249,29 +833,29 @@ static void iwl_pcie_apm_stop(struct iwl_trans *trans) CSR_GP_CNTRL_REG_FLAG_INIT_DONE); } -static int iwl_pcie_nic_init(struct iwl_trans *trans) +static int iwl_nic_init(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); unsigned long flags; /* nic_init */ spin_lock_irqsave(&trans_pcie->irq_lock, flags); - iwl_pcie_apm_init(trans); + iwl_apm_init(trans); /* Set interrupt coalescing calibration timer to default (512 usecs) */ iwl_write8(trans, CSR_INT_COALESCING, IWL_HOST_INT_CALIB_TIMEOUT_DEF); spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); - iwl_pcie_set_pwr_vmain(trans); + iwl_set_pwr_vmain(trans); iwl_op_mode_nic_config(trans->op_mode); /* Allocate the RX queue, or reset if it is already allocated */ - iwl_pcie_rx_init(trans); + iwl_rx_init(trans); /* Allocate or reset and init all Tx and Command queues */ - if (iwl_pcie_tx_init(trans)) + if (iwl_tx_init(trans)) return -ENOMEM; if (trans->cfg->base_params->shadow_reg_enable) { @@ -286,7 +870,7 @@ static int iwl_pcie_nic_init(struct iwl_trans *trans) #define HW_READY_TIMEOUT (50) /* Note: returns poll_bit return value, which is >= 0 if success */ -static int iwl_pcie_set_hw_ready(struct iwl_trans *trans) +static int iwl_set_hw_ready(struct iwl_trans *trans) { int ret; @@ -304,14 +888,14 @@ static int iwl_pcie_set_hw_ready(struct iwl_trans *trans) } /* Note: returns standard 0/-ERROR code */ -static int iwl_pcie_prepare_card_hw(struct iwl_trans *trans) +static int iwl_prepare_card_hw(struct iwl_trans *trans) { int ret; int t = 0; IWL_DEBUG_INFO(trans, "iwl_trans_prepare_card_hw enter\n"); - ret = iwl_pcie_set_hw_ready(trans); + ret = iwl_set_hw_ready(trans); /* If the card is ready, exit 0 */ if (ret >= 0) return 0; @@ -321,7 +905,7 @@ static int iwl_pcie_prepare_card_hw(struct iwl_trans *trans) CSR_HW_IF_CONFIG_REG_PREPARE); do { - ret = iwl_pcie_set_hw_ready(trans); + ret = iwl_set_hw_ready(trans); if (ret >= 0) return 0; @@ -335,7 +919,7 @@ static int iwl_pcie_prepare_card_hw(struct iwl_trans *trans) /* * ucode */ -static int iwl_pcie_load_firmware_chunk(struct iwl_trans *trans, u32 dst_addr, +static int iwl_load_firmware_chunk(struct iwl_trans *trans, u32 dst_addr, dma_addr_t phy_addr, u32 byte_cnt) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); @@ -382,7 +966,7 @@ static int iwl_pcie_load_firmware_chunk(struct iwl_trans *trans, u32 dst_addr, return 0; } -static int iwl_pcie_load_section(struct iwl_trans *trans, u8 section_num, +static int iwl_load_section(struct iwl_trans *trans, u8 section_num, const struct fw_desc *section) { u8 *v_addr; @@ -403,9 +987,8 @@ static int iwl_pcie_load_section(struct iwl_trans *trans, u8 section_num, copy_size = min_t(u32, PAGE_SIZE, section->len - offset); memcpy(v_addr, (u8 *)section->data + offset, copy_size); - ret = iwl_pcie_load_firmware_chunk(trans, - section->offset + offset, - p_addr, copy_size); + ret = iwl_load_firmware_chunk(trans, section->offset + offset, + p_addr, copy_size); if (ret) { IWL_ERR(trans, "Could not load the [%d] uCode section\n", @@ -418,7 +1001,7 @@ static int iwl_pcie_load_section(struct iwl_trans *trans, u8 section_num, return ret; } -static int iwl_pcie_load_given_ucode(struct iwl_trans *trans, +static int iwl_load_given_ucode(struct iwl_trans *trans, const struct fw_img *image) { int i, ret = 0; @@ -427,7 +1010,7 @@ static int iwl_pcie_load_given_ucode(struct iwl_trans *trans, if (!image->sec[i].data) break; - ret = iwl_pcie_load_section(trans, i, &image->sec[i]); + ret = iwl_load_section(trans, i, &image->sec[i]); if (ret) return ret; } @@ -446,7 +1029,7 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, bool hw_rfkill; /* This may fail if AMT took ownership of the device */ - if (iwl_pcie_prepare_card_hw(trans)) { + if (iwl_prepare_card_hw(trans)) { IWL_WARN(trans, "Exit HW not ready\n"); return -EIO; } @@ -463,7 +1046,7 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, iwl_write32(trans, CSR_INT, 0xFFFFFFFF); - ret = iwl_pcie_nic_init(trans); + ret = iwl_nic_init(trans); if (ret) { IWL_ERR(trans, "Unable to init nic\n"); return ret; @@ -483,13 +1066,129 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); /* Load the given image to the HW */ - return iwl_pcie_load_given_ucode(trans, fw); + return iwl_load_given_ucode(trans, fw); +} + +/* + * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask + */ +static void iwl_trans_txq_set_sched(struct iwl_trans *trans, u32 mask) +{ + struct iwl_trans_pcie __maybe_unused *trans_pcie = + IWL_TRANS_GET_PCIE_TRANS(trans); + + iwl_write_prph(trans, SCD_TXFACT, mask); +} + +static void iwl_tx_start(struct iwl_trans *trans, u32 scd_base_addr) +{ + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + u32 a; + int chan; + u32 reg_val; + + /* make sure all queue are not stopped/used */ + memset(trans_pcie->queue_stopped, 0, sizeof(trans_pcie->queue_stopped)); + memset(trans_pcie->queue_used, 0, sizeof(trans_pcie->queue_used)); + + trans_pcie->scd_base_addr = + iwl_read_prph(trans, SCD_SRAM_BASE_ADDR); + + WARN_ON(scd_base_addr != 0 && + scd_base_addr != trans_pcie->scd_base_addr); + + a = trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_LOWER_BOUND; + /* reset conext data memory */ + for (; a < trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_UPPER_BOUND; + a += 4) + iwl_write_targ_mem(trans, a, 0); + /* reset tx status memory */ + for (; a < trans_pcie->scd_base_addr + SCD_TX_STTS_MEM_UPPER_BOUND; + a += 4) + iwl_write_targ_mem(trans, a, 0); + for (; a < trans_pcie->scd_base_addr + + SCD_TRANS_TBL_OFFSET_QUEUE( + trans->cfg->base_params->num_of_queues); + a += 4) + iwl_write_targ_mem(trans, a, 0); + + iwl_write_prph(trans, SCD_DRAM_BASE_ADDR, + trans_pcie->scd_bc_tbls.dma >> 10); + + /* The chain extension of the SCD doesn't work well. This feature is + * enabled by default by the HW, so we need to disable it manually. + */ + iwl_write_prph(trans, SCD_CHAINEXT_EN, 0); + + iwl_trans_ac_txq_enable(trans, trans_pcie->cmd_queue, + trans_pcie->cmd_fifo); + + /* Activate all Tx DMA/FIFO channels */ + iwl_trans_txq_set_sched(trans, IWL_MASK(0, 7)); + + /* Enable DMA channel */ + for (chan = 0; chan < FH_TCSR_CHNL_NUM ; chan++) + iwl_write_direct32(trans, FH_TCSR_CHNL_TX_CONFIG_REG(chan), + FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | + FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE); + + /* Update FH chicken bits */ + reg_val = iwl_read_direct32(trans, FH_TX_CHICKEN_BITS_REG); + iwl_write_direct32(trans, FH_TX_CHICKEN_BITS_REG, + reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); + + /* Enable L1-Active */ + iwl_clear_bits_prph(trans, APMG_PCIDEV_STT_REG, + APMG_PCIDEV_STT_VAL_L1_ACT_DIS); } static void iwl_trans_pcie_fw_alive(struct iwl_trans *trans, u32 scd_addr) { - iwl_pcie_reset_ict(trans); - iwl_pcie_tx_start(trans, scd_addr); + iwl_reset_ict(trans); + iwl_tx_start(trans, scd_addr); +} + +/** + * iwlagn_txq_ctx_stop - Stop all Tx DMA channels + */ +static int iwl_trans_tx_stop(struct iwl_trans *trans) +{ + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + int ch, txq_id, ret; + unsigned long flags; + + /* Turn off all Tx DMA fifos */ + spin_lock_irqsave(&trans_pcie->irq_lock, flags); + + iwl_trans_txq_set_sched(trans, 0); + + /* Stop each Tx DMA channel, and wait for it to be idle */ + for (ch = 0; ch < FH_TCSR_CHNL_NUM; ch++) { + iwl_write_direct32(trans, + FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); + ret = iwl_poll_direct_bit(trans, FH_TSSR_TX_STATUS_REG, + FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), 1000); + if (ret < 0) + IWL_ERR(trans, + "Failing on timeout while stopping DMA channel %d [0x%08x]\n", + ch, + iwl_read_direct32(trans, + FH_TSSR_TX_STATUS_REG)); + } + spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); + + if (!trans_pcie->txq) { + IWL_WARN(trans, + "Stopping tx queues that aren't allocated...\n"); + return 0; + } + + /* Unmap DMA from host system and free skb's */ + for (txq_id = 0; txq_id < trans->cfg->base_params->num_of_queues; + txq_id++) + iwl_tx_queue_unmap(trans, txq_id); + + return 0; } static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) @@ -503,7 +1202,7 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); /* device going down, Stop using ICT table */ - iwl_pcie_disable_ict(trans); + iwl_disable_ict(trans); /* * If a HW restart happens during firmware loading, @@ -513,8 +1212,8 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) * already dead. */ if (test_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status)) { - iwl_pcie_tx_stop(trans); - iwl_pcie_rx_stop(trans); + iwl_trans_tx_stop(trans); + iwl_trans_rx_stop(trans); /* Power-down device's busmaster DMA clocks */ iwl_write_prph(trans, APMG_CLK_DIS_REG, @@ -527,7 +1226,7 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); /* Stop the device, and put it in low power state */ - iwl_pcie_apm_stop(trans); + iwl_apm_stop(trans); /* Upon stop, the APM issues an interrupt if HW RF kill is set. * Clean again the interrupt here @@ -566,6 +1265,171 @@ static void iwl_trans_pcie_wowlan_suspend(struct iwl_trans *trans) CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); } +static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, + struct iwl_device_cmd *dev_cmd, int txq_id) +{ + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct iwl_tx_cmd *tx_cmd = (struct iwl_tx_cmd *) dev_cmd->payload; + struct iwl_cmd_meta *out_meta; + struct iwl_tx_queue *txq; + struct iwl_queue *q; + dma_addr_t phys_addr = 0; + dma_addr_t txcmd_phys; + dma_addr_t scratch_phys; + u16 len, firstlen, secondlen; + u8 wait_write_ptr = 0; + __le16 fc = hdr->frame_control; + u8 hdr_len = ieee80211_hdrlen(fc); + u16 __maybe_unused wifi_seq; + + txq = &trans_pcie->txq[txq_id]; + q = &txq->q; + + if (unlikely(!test_bit(txq_id, trans_pcie->queue_used))) { + WARN_ON_ONCE(1); + return -EINVAL; + } + + spin_lock(&txq->lock); + + /* In AGG mode, the index in the ring must correspond to the WiFi + * sequence number. This is a HW requirements to help the SCD to parse + * the BA. + * Check here that the packets are in the right place on the ring. + */ +#ifdef CONFIG_IWLWIFI_DEBUG + wifi_seq = SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); + WARN_ONCE((iwl_read_prph(trans, SCD_AGGR_SEL) & BIT(txq_id)) && + ((wifi_seq & 0xff) != q->write_ptr), + "Q: %d WiFi Seq %d tfdNum %d", + txq_id, wifi_seq, q->write_ptr); +#endif + + /* Set up driver data for this TFD */ + txq->entries[q->write_ptr].skb = skb; + txq->entries[q->write_ptr].cmd = dev_cmd; + + dev_cmd->hdr.cmd = REPLY_TX; + dev_cmd->hdr.sequence = + cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) | + INDEX_TO_SEQ(q->write_ptr))); + + /* Set up first empty entry in queue's array of Tx/cmd buffers */ + out_meta = &txq->entries[q->write_ptr].meta; + + /* + * Use the first empty entry in this queue's command buffer array + * to contain the Tx command and MAC header concatenated together + * (payload data will be in another buffer). + * Size of this varies, due to varying MAC header length. + * If end is not dword aligned, we'll have 2 extra bytes at the end + * of the MAC header (device reads on dword boundaries). + * We'll tell device about this padding later. + */ + len = sizeof(struct iwl_tx_cmd) + + sizeof(struct iwl_cmd_header) + hdr_len; + firstlen = (len + 3) & ~3; + + /* Tell NIC about any 2-byte padding after MAC header */ + if (firstlen != len) + tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK; + + /* Physical address of this Tx command's header (not MAC header!), + * within command buffer array. */ + txcmd_phys = dma_map_single(trans->dev, + &dev_cmd->hdr, firstlen, + DMA_BIDIRECTIONAL); + if (unlikely(dma_mapping_error(trans->dev, txcmd_phys))) + goto out_err; + dma_unmap_addr_set(out_meta, mapping, txcmd_phys); + dma_unmap_len_set(out_meta, len, firstlen); + + if (!ieee80211_has_morefrags(fc)) { + txq->need_update = 1; + } else { + wait_write_ptr = 1; + txq->need_update = 0; + } + + /* Set up TFD's 2nd entry to point directly to remainder of skb, + * if any (802.11 null frames have no payload). */ + secondlen = skb->len - hdr_len; + if (secondlen > 0) { + phys_addr = dma_map_single(trans->dev, skb->data + hdr_len, + secondlen, DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(trans->dev, phys_addr))) { + dma_unmap_single(trans->dev, + dma_unmap_addr(out_meta, mapping), + dma_unmap_len(out_meta, len), + DMA_BIDIRECTIONAL); + goto out_err; + } + } + + /* Attach buffers to TFD */ + iwlagn_txq_attach_buf_to_tfd(trans, txq, txcmd_phys, firstlen, 1); + if (secondlen > 0) + iwlagn_txq_attach_buf_to_tfd(trans, txq, phys_addr, + secondlen, 0); + + scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) + + offsetof(struct iwl_tx_cmd, scratch); + + /* take back ownership of DMA buffer to enable update */ + dma_sync_single_for_cpu(trans->dev, txcmd_phys, firstlen, + DMA_BIDIRECTIONAL); + tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys); + tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys); + + IWL_DEBUG_TX(trans, "sequence nr = 0X%x\n", + le16_to_cpu(dev_cmd->hdr.sequence)); + IWL_DEBUG_TX(trans, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags)); + + /* Set up entry for this TFD in Tx byte-count array */ + iwl_trans_txq_update_byte_cnt_tbl(trans, txq, le16_to_cpu(tx_cmd->len)); + + dma_sync_single_for_device(trans->dev, txcmd_phys, firstlen, + DMA_BIDIRECTIONAL); + + trace_iwlwifi_dev_tx(trans->dev, skb, + &txq->tfds[txq->q.write_ptr], + sizeof(struct iwl_tfd), + &dev_cmd->hdr, firstlen, + skb->data + hdr_len, secondlen); + trace_iwlwifi_dev_tx_data(trans->dev, skb, + skb->data + hdr_len, secondlen); + + /* start timer if queue currently empty */ + if (txq->need_update && q->read_ptr == q->write_ptr && + trans_pcie->wd_timeout) + mod_timer(&txq->stuck_timer, jiffies + trans_pcie->wd_timeout); + + /* Tell device the write index *just past* this latest filled TFD */ + q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); + iwl_txq_update_write_ptr(trans, txq); + + /* + * At this point the frame is "transmitted" successfully + * and we will get a TX status notification eventually, + * regardless of the value of ret. "ret" only indicates + * whether or not we should update the write pointer. + */ + if (iwl_queue_space(q) < q->high_mark) { + if (wait_write_ptr) { + txq->need_update = 1; + iwl_txq_update_write_ptr(trans, txq); + } else { + iwl_stop_queue(trans, txq); + } + } + spin_unlock(&txq->lock); + return 0; + out_err: + spin_unlock(&txq->lock); + return -1; +} + static int iwl_trans_pcie_start_hw(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); @@ -576,28 +1440,29 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans) if (!trans_pcie->irq_requested) { tasklet_init(&trans_pcie->irq_tasklet, (void (*)(unsigned long)) - iwl_pcie_tasklet, (unsigned long)trans); + iwl_irq_tasklet, (unsigned long)trans); - iwl_pcie_alloc_ict(trans); + iwl_alloc_isr_ict(trans); - err = request_irq(trans_pcie->irq, iwl_pcie_isr_ict, - IRQF_SHARED, DRV_NAME, trans); + err = request_irq(trans_pcie->irq, iwl_isr_ict, IRQF_SHARED, + DRV_NAME, trans); if (err) { IWL_ERR(trans, "Error allocating IRQ %d\n", trans_pcie->irq); goto error; } + INIT_WORK(&trans_pcie->rx_replenish, iwl_bg_rx_replenish); trans_pcie->irq_requested = true; } - err = iwl_pcie_prepare_card_hw(trans); + err = iwl_prepare_card_hw(trans); if (err) { IWL_ERR(trans, "Error while preparing HW: %d\n", err); goto err_free_irq; } - iwl_pcie_apm_init(trans); + iwl_apm_init(trans); /* From now on, the op_mode will be kept updated about RF kill state */ iwl_enable_rfkill_int(trans); @@ -611,7 +1476,7 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans) trans_pcie->irq_requested = false; free_irq(trans_pcie->irq, trans); error: - iwl_pcie_free_ict(trans); + iwl_free_isr_ict(trans); tasklet_kill(&trans_pcie->irq_tasklet); return err; } @@ -627,7 +1492,7 @@ static void iwl_trans_pcie_stop_hw(struct iwl_trans *trans, iwl_disable_interrupts(trans); spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); - iwl_pcie_apm_stop(trans); + iwl_apm_stop(trans); spin_lock_irqsave(&trans_pcie->irq_lock, flags); iwl_disable_interrupts(trans); @@ -651,6 +1516,27 @@ static void iwl_trans_pcie_stop_hw(struct iwl_trans *trans, } } +static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn, + struct sk_buff_head *skbs) +{ + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id]; + /* n_bd is usually 256 => n_bd - 1 = 0xff */ + int tfd_num = ssn & (txq->q.n_bd - 1); + + spin_lock(&txq->lock); + + if (txq->q.read_ptr != tfd_num) { + IWL_DEBUG_TX_REPLY(trans, "[Q %d] %d -> %d (%d)\n", + txq_id, txq->q.read_ptr, tfd_num, ssn); + iwl_tx_queue_reclaim(trans, txq_id, tfd_num, skbs); + if (iwl_queue_space(&txq->q) > txq->q.low_mark) + iwl_wake_queue(trans, txq); + } + + spin_unlock(&txq->lock); +} + static void iwl_trans_pcie_write8(struct iwl_trans *trans, u32 ofs, u8 val) { writeb(val, IWL_TRANS_GET_PCIE_TRANS(trans)->hw_base + ofs); @@ -697,12 +1583,12 @@ void iwl_trans_pcie_free(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - iwl_pcie_tx_free(trans); - iwl_pcie_rx_free(trans); + iwl_trans_pcie_tx_free(trans); + iwl_trans_pcie_rx_free(trans); if (trans_pcie->irq_requested == true) { free_irq(trans_pcie->irq, trans); - iwl_pcie_free_ict(trans); + iwl_free_isr_ict(trans); } pci_disable_msi(trans_pcie->pci_dev); @@ -748,10 +1634,10 @@ static int iwl_trans_pcie_resume(struct iwl_trans *trans) #define IWL_FLUSH_WAIT_MS 2000 -static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans) +static int iwl_trans_pcie_wait_tx_queue_empty(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_txq *txq; + struct iwl_tx_queue *txq; struct iwl_queue *q; int cnt; unsigned long now = jiffies; @@ -795,7 +1681,7 @@ static const char *get_fh_string(int cmd) #undef IWL_CMD } -int iwl_pcie_dump_fh(struct iwl_trans *trans, char **buf) +int iwl_dump_fh(struct iwl_trans *trans, char **buf) { int i; static const u32 fh_tbl[] = { @@ -874,7 +1760,7 @@ static const char *get_csr_string(int cmd) #undef IWL_CMD } -void iwl_pcie_dump_csr(struct iwl_trans *trans) +void iwl_dump_csr(struct iwl_trans *trans) { int i; static const u32 csr_tbl[] = { @@ -931,6 +1817,7 @@ static ssize_t iwl_dbgfs_##name##_write(struct file *file, \ const char __user *user_buf, \ size_t count, loff_t *ppos); + #define DEBUGFS_READ_FILE_OPS(name) \ DEBUGFS_READ_FUNC(name); \ static const struct file_operations iwl_dbgfs_##name##_ops = { \ @@ -963,7 +1850,7 @@ static ssize_t iwl_dbgfs_tx_queue_read(struct file *file, { struct iwl_trans *trans = file->private_data; struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_txq *txq; + struct iwl_tx_queue *txq; struct iwl_queue *q; char *buf; int pos = 0; @@ -1000,7 +1887,7 @@ static ssize_t iwl_dbgfs_rx_queue_read(struct file *file, { struct iwl_trans *trans = file->private_data; struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rxq *rxq = &trans_pcie->rxq; + struct iwl_rx_queue *rxq = &trans_pcie->rxq; char buf[256]; int pos = 0; const size_t bufsz = sizeof(buf); @@ -1119,7 +2006,7 @@ static ssize_t iwl_dbgfs_csr_write(struct file *file, if (sscanf(buf, "%d", &csr) != 1) return -EFAULT; - iwl_pcie_dump_csr(trans); + iwl_dump_csr(trans); return count; } @@ -1133,7 +2020,7 @@ static ssize_t iwl_dbgfs_fh_reg_read(struct file *file, int pos = 0; ssize_t ret = -EFAULT; - ret = pos = iwl_pcie_dump_fh(trans, &buf); + ret = pos = iwl_dump_fh(trans, &buf); if (buf) { ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); @@ -1202,7 +2089,7 @@ static const struct iwl_trans_ops trans_ops_pcie = { .wowlan_suspend = iwl_trans_pcie_wowlan_suspend, - .send_cmd = iwl_trans_pcie_send_hcmd, + .send_cmd = iwl_trans_pcie_send_cmd, .tx = iwl_trans_pcie_tx, .reclaim = iwl_trans_pcie_reclaim, @@ -1212,7 +2099,7 @@ static const struct iwl_trans_ops trans_ops_pcie = { .dbgfs_register = iwl_trans_pcie_dbgfs_register, - .wait_tx_queue_empty = iwl_trans_pcie_wait_txq_empty, + .wait_tx_queue_empty = iwl_trans_pcie_wait_tx_queue_empty, #ifdef CONFIG_PM_SLEEP .suspend = iwl_trans_pcie_suspend, @@ -1237,7 +2124,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, trans = kzalloc(sizeof(struct iwl_trans) + sizeof(struct iwl_trans_pcie), GFP_KERNEL); - if (!trans) + if (WARN_ON(!trans)) return NULL; trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); @@ -1293,15 +2180,8 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00); err = pci_enable_msi(pdev); - if (err) { + if (err) dev_err(&pdev->dev, "pci_enable_msi failed(0X%x)\n", err); - /* enable rfkill interrupt: hw bug w/a */ - pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); - if (pci_cmd & PCI_COMMAND_INTX_DISABLE) { - pci_cmd &= ~PCI_COMMAND_INTX_DISABLE; - pci_write_config_word(pdev, PCI_COMMAND, pci_cmd); - } - } trans->dev = &pdev->dev; trans_pcie->irq = pdev->irq; @@ -1311,6 +2191,14 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, snprintf(trans->hw_id_str, sizeof(trans->hw_id_str), "PCI ID: 0x%04X:0x%04X", pdev->device, pdev->subsystem_device); + /* TODO: Move this away, not needed if not MSI */ + /* enable rfkill interrupt: hw bug w/a */ + pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); + if (pci_cmd & PCI_COMMAND_INTX_DISABLE) { + pci_cmd &= ~PCI_COMMAND_INTX_DISABLE; + pci_write_config_word(pdev, PCI_COMMAND, pci_cmd); + } + /* Initialize the wait queue for commands */ init_waitqueue_head(&trans_pcie->wait_command_queue); spin_lock_init(&trans->reg_lock); diff --git a/trunk/drivers/net/wireless/iwlwifi/pcie/tx.c b/trunk/drivers/net/wireless/iwlwifi/pcie/tx.c index 6c5b867c353a..dcc7e1256e39 100644 --- a/trunk/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/trunk/drivers/net/wireless/iwlwifi/pcie/tx.c @@ -42,170 +42,12 @@ #define IWL_TX_CRC_SIZE 4 #define IWL_TX_DELIMITER_SIZE 4 -/*************** DMA-QUEUE-GENERAL-FUNCTIONS ***** - * DMA services - * - * Theory of operation - * - * A Tx or Rx queue resides in host DRAM, and is comprised of a circular buffer - * of buffer descriptors, each of which points to one or more data buffers for - * the device to read from or fill. Driver and device exchange status of each - * queue via "read" and "write" pointers. Driver keeps minimum of 2 empty - * entries in each circular buffer, to protect against confusing empty and full - * queue states. - * - * The device reads or writes the data in the queues via the device's several - * DMA/FIFO channels. Each queue is mapped to a single DMA channel. - * - * For Tx queue, there are low mark and high mark limits. If, after queuing - * the packet for Tx, free space become < low mark, Tx queue stopped. When - * reclaiming packets (on 'tx done IRQ), if free space become > high mark, - * Tx queue resumed. - * - ***************************************************/ -static int iwl_queue_space(const struct iwl_queue *q) -{ - int s = q->read_ptr - q->write_ptr; - - if (q->read_ptr > q->write_ptr) - s -= q->n_bd; - - if (s <= 0) - s += q->n_window; - /* keep some reserve to not confuse empty and full situations */ - s -= 2; - if (s < 0) - s = 0; - return s; -} - -/* - * iwl_queue_init - Initialize queue's high/low-water and read/write indexes - */ -static int iwl_queue_init(struct iwl_queue *q, int count, int slots_num, u32 id) -{ - q->n_bd = count; - q->n_window = slots_num; - q->id = id; - - /* count must be power-of-two size, otherwise iwl_queue_inc_wrap - * and iwl_queue_dec_wrap are broken. */ - if (WARN_ON(!is_power_of_2(count))) - return -EINVAL; - - /* slots_num must be power-of-two size, otherwise - * get_cmd_index is broken. */ - if (WARN_ON(!is_power_of_2(slots_num))) - return -EINVAL; - - q->low_mark = q->n_window / 4; - if (q->low_mark < 4) - q->low_mark = 4; - - q->high_mark = q->n_window / 8; - if (q->high_mark < 2) - q->high_mark = 2; - - q->write_ptr = 0; - q->read_ptr = 0; - - return 0; -} - -static int iwl_pcie_alloc_dma_ptr(struct iwl_trans *trans, - struct iwl_dma_ptr *ptr, size_t size) -{ - if (WARN_ON(ptr->addr)) - return -EINVAL; - - ptr->addr = dma_alloc_coherent(trans->dev, size, - &ptr->dma, GFP_KERNEL); - if (!ptr->addr) - return -ENOMEM; - ptr->size = size; - return 0; -} - -static void iwl_pcie_free_dma_ptr(struct iwl_trans *trans, - struct iwl_dma_ptr *ptr) -{ - if (unlikely(!ptr->addr)) - return; - - dma_free_coherent(trans->dev, ptr->size, ptr->addr, ptr->dma); - memset(ptr, 0, sizeof(*ptr)); -} - -static void iwl_pcie_txq_stuck_timer(unsigned long data) -{ - struct iwl_txq *txq = (void *)data; - struct iwl_queue *q = &txq->q; - struct iwl_trans_pcie *trans_pcie = txq->trans_pcie; - struct iwl_trans *trans = iwl_trans_pcie_get_trans(trans_pcie); - u32 scd_sram_addr = trans_pcie->scd_base_addr + - SCD_TX_STTS_QUEUE_OFFSET(txq->q.id); - u8 buf[16]; - int i; - - spin_lock(&txq->lock); - /* check if triggered erroneously */ - if (txq->q.read_ptr == txq->q.write_ptr) { - spin_unlock(&txq->lock); - return; - } - spin_unlock(&txq->lock); - - IWL_ERR(trans, "Queue %d stuck for %u ms.\n", txq->q.id, - jiffies_to_msecs(trans_pcie->wd_timeout)); - IWL_ERR(trans, "Current SW read_ptr %d write_ptr %d\n", - txq->q.read_ptr, txq->q.write_ptr); - - iwl_read_targ_mem_bytes(trans, scd_sram_addr, buf, sizeof(buf)); - - iwl_print_hex_error(trans, buf, sizeof(buf)); - - for (i = 0; i < FH_TCSR_CHNL_NUM; i++) - IWL_ERR(trans, "FH TRBs(%d) = 0x%08x\n", i, - iwl_read_direct32(trans, FH_TX_TRB_REG(i))); - - for (i = 0; i < trans->cfg->base_params->num_of_queues; i++) { - u32 status = iwl_read_prph(trans, SCD_QUEUE_STATUS_BITS(i)); - u8 fifo = (status >> SCD_QUEUE_STTS_REG_POS_TXF) & 0x7; - bool active = !!(status & BIT(SCD_QUEUE_STTS_REG_POS_ACTIVE)); - u32 tbl_dw = - iwl_read_targ_mem(trans, - trans_pcie->scd_base_addr + - SCD_TRANS_TBL_OFFSET_QUEUE(i)); - - if (i & 0x1) - tbl_dw = (tbl_dw & 0xFFFF0000) >> 16; - else - tbl_dw = tbl_dw & 0x0000FFFF; - - IWL_ERR(trans, - "Q %d is %sactive and mapped to fifo %d ra_tid 0x%04x [%d,%d]\n", - i, active ? "" : "in", fifo, tbl_dw, - iwl_read_prph(trans, - SCD_QUEUE_RDPTR(i)) & (txq->q.n_bd - 1), - iwl_read_prph(trans, SCD_QUEUE_WRPTR(i))); - } - - for (i = q->read_ptr; i != q->write_ptr; - i = iwl_queue_inc_wrap(i, q->n_bd)) { - struct iwl_tx_cmd *tx_cmd = - (struct iwl_tx_cmd *)txq->entries[i].cmd->payload; - IWL_ERR(trans, "scratch %d = 0x%08x\n", i, - get_unaligned_le32(&tx_cmd->scratch)); - } - - iwl_op_mode_nic_error(trans->op_mode); -} - -/* - * iwl_pcie_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array +/** + * iwl_trans_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array */ -static void iwl_pcie_txq_update_byte_cnt_tbl(struct iwl_trans *trans, - struct iwl_txq *txq, u16 byte_cnt) +void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans, + struct iwl_tx_queue *txq, + u16 byte_cnt) { struct iwlagn_scd_bc_tbl *scd_bc_tbl; struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); @@ -246,36 +88,10 @@ static void iwl_pcie_txq_update_byte_cnt_tbl(struct iwl_trans *trans, tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent; } -static void iwl_pcie_txq_inval_byte_cnt_tbl(struct iwl_trans *trans, - struct iwl_txq *txq) -{ - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwlagn_scd_bc_tbl *scd_bc_tbl = trans_pcie->scd_bc_tbls.addr; - int txq_id = txq->q.id; - int read_ptr = txq->q.read_ptr; - u8 sta_id = 0; - __le16 bc_ent; - struct iwl_tx_cmd *tx_cmd = - (void *)txq->entries[txq->q.read_ptr].cmd->payload; - - WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX); - - if (txq_id != trans_pcie->cmd_queue) - sta_id = tx_cmd->sta_id; - - bc_ent = cpu_to_le16(1 | (sta_id << 12)); - scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent; - - if (read_ptr < TFD_QUEUE_SIZE_BC_DUP) - scd_bc_tbl[txq_id]. - tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent; -} - -/* - * iwl_pcie_txq_inc_wr_ptr - Send new write index to hardware +/** + * iwl_txq_update_write_ptr - Send new write index to hardware */ -void iwl_pcie_txq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_txq *txq) +void iwl_txq_update_write_ptr(struct iwl_trans *trans, struct iwl_tx_queue *txq) { u32 reg = 0; int txq_id = txq->q.id; @@ -321,7 +137,7 @@ void iwl_pcie_txq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_txq *txq) txq->need_update = 0; } -static inline dma_addr_t iwl_pcie_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx) +static inline dma_addr_t iwl_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx) { struct iwl_tfd_tb *tb = &tfd->tbs[idx]; @@ -333,15 +149,15 @@ static inline dma_addr_t iwl_pcie_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx) return addr; } -static inline u16 iwl_pcie_tfd_tb_get_len(struct iwl_tfd *tfd, u8 idx) +static inline u16 iwl_tfd_tb_get_len(struct iwl_tfd *tfd, u8 idx) { struct iwl_tfd_tb *tb = &tfd->tbs[idx]; return le16_to_cpu(tb->hi_n_len) >> 4; } -static inline void iwl_pcie_tfd_set_tb(struct iwl_tfd *tfd, u8 idx, - dma_addr_t addr, u16 len) +static inline void iwl_tfd_set_tb(struct iwl_tfd *tfd, u8 idx, + dma_addr_t addr, u16 len) { struct iwl_tfd_tb *tb = &tfd->tbs[idx]; u16 hi_n_len = len << 4; @@ -355,20 +171,19 @@ static inline void iwl_pcie_tfd_set_tb(struct iwl_tfd *tfd, u8 idx, tfd->num_tbs = idx + 1; } -static inline u8 iwl_pcie_tfd_get_num_tbs(struct iwl_tfd *tfd) +static inline u8 iwl_tfd_get_num_tbs(struct iwl_tfd *tfd) { return tfd->num_tbs & 0x1f; } -static void iwl_pcie_tfd_unmap(struct iwl_trans *trans, - struct iwl_cmd_meta *meta, struct iwl_tfd *tfd, - enum dma_data_direction dma_dir) +static void iwl_unmap_tfd(struct iwl_trans *trans, struct iwl_cmd_meta *meta, + struct iwl_tfd *tfd, enum dma_data_direction dma_dir) { int i; int num_tbs; /* Sanity check on number of chunks */ - num_tbs = iwl_pcie_tfd_get_num_tbs(tfd); + num_tbs = iwl_tfd_get_num_tbs(tfd); if (num_tbs >= IWL_NUM_OF_TBS) { IWL_ERR(trans, "Too many chunks: %i\n", num_tbs); @@ -385,14 +200,14 @@ static void iwl_pcie_tfd_unmap(struct iwl_trans *trans, /* Unmap chunks, if any. */ for (i = 1; i < num_tbs; i++) - dma_unmap_single(trans->dev, iwl_pcie_tfd_tb_get_addr(tfd, i), - iwl_pcie_tfd_tb_get_len(tfd, i), dma_dir); + dma_unmap_single(trans->dev, iwl_tfd_tb_get_addr(tfd, i), + iwl_tfd_tb_get_len(tfd, i), dma_dir); tfd->num_tbs = 0; } -/* - * iwl_pcie_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr] +/** + * iwl_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr] * @trans - transport private data * @txq - tx queue * @dma_dir - the direction of the DMA mapping @@ -400,8 +215,8 @@ static void iwl_pcie_tfd_unmap(struct iwl_trans *trans, * Does NOT advance any TFD circular buffer read/write indexes * Does NOT free the TFD itself (which is within circular buffer) */ -static void iwl_pcie_txq_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq, - enum dma_data_direction dma_dir) +void iwl_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq, + enum dma_data_direction dma_dir) { struct iwl_tfd *tfd_tmp = txq->tfds; @@ -412,8 +227,8 @@ static void iwl_pcie_txq_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq, lockdep_assert_held(&txq->lock); /* We have only q->n_window txq->entries, but we use q->n_bd tfds */ - iwl_pcie_tfd_unmap(trans, &txq->entries[idx].meta, &tfd_tmp[rd_ptr], - dma_dir); + iwl_unmap_tfd(trans, &txq->entries[idx].meta, &tfd_tmp[rd_ptr], + dma_dir); /* free SKB */ if (txq->entries) { @@ -432,8 +247,10 @@ static void iwl_pcie_txq_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq, } } -static int iwl_pcie_txq_build_tfd(struct iwl_trans *trans, struct iwl_txq *txq, - dma_addr_t addr, u16 len, u8 reset) +int iwlagn_txq_attach_buf_to_tfd(struct iwl_trans *trans, + struct iwl_tx_queue *txq, + dma_addr_t addr, u16 len, + u8 reset) { struct iwl_queue *q; struct iwl_tfd *tfd, *tfd_tmp; @@ -446,7 +263,7 @@ static int iwl_pcie_txq_build_tfd(struct iwl_trans *trans, struct iwl_txq *txq, if (reset) memset(tfd, 0, sizeof(*tfd)); - num_tbs = iwl_pcie_tfd_get_num_tbs(tfd); + num_tbs = iwl_tfd_get_num_tbs(tfd); /* Each TFD can point to a maximum 20 Tx buffers */ if (num_tbs >= IWL_NUM_OF_TBS) { @@ -462,534 +279,108 @@ static int iwl_pcie_txq_build_tfd(struct iwl_trans *trans, struct iwl_txq *txq, IWL_ERR(trans, "Unaligned address = %llx\n", (unsigned long long)addr); - iwl_pcie_tfd_set_tb(tfd, num_tbs, addr, len); - - return 0; -} - -static int iwl_pcie_txq_alloc(struct iwl_trans *trans, - struct iwl_txq *txq, int slots_num, - u32 txq_id) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - size_t tfd_sz = sizeof(struct iwl_tfd) * TFD_QUEUE_SIZE_MAX; - int i; - - if (WARN_ON(txq->entries || txq->tfds)) - return -EINVAL; - - setup_timer(&txq->stuck_timer, iwl_pcie_txq_stuck_timer, - (unsigned long)txq); - txq->trans_pcie = trans_pcie; - - txq->q.n_window = slots_num; - - txq->entries = kcalloc(slots_num, - sizeof(struct iwl_pcie_txq_entry), - GFP_KERNEL); - - if (!txq->entries) - goto error; - - if (txq_id == trans_pcie->cmd_queue) - for (i = 0; i < slots_num; i++) { - txq->entries[i].cmd = - kmalloc(sizeof(struct iwl_device_cmd), - GFP_KERNEL); - if (!txq->entries[i].cmd) - goto error; - } - - /* Circular buffer of transmit frame descriptors (TFDs), - * shared with device */ - txq->tfds = dma_alloc_coherent(trans->dev, tfd_sz, - &txq->q.dma_addr, GFP_KERNEL); - if (!txq->tfds) { - IWL_ERR(trans, "dma_alloc_coherent(%zd) failed\n", tfd_sz); - goto error; - } - txq->q.id = txq_id; - - return 0; -error: - if (txq->entries && txq_id == trans_pcie->cmd_queue) - for (i = 0; i < slots_num; i++) - kfree(txq->entries[i].cmd); - kfree(txq->entries); - txq->entries = NULL; - - return -ENOMEM; - -} - -static int iwl_pcie_txq_init(struct iwl_trans *trans, struct iwl_txq *txq, - int slots_num, u32 txq_id) -{ - int ret; - - txq->need_update = 0; - - /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise - * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */ - BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1)); - - /* Initialize queue's high/low-water marks, and head/tail indexes */ - ret = iwl_queue_init(&txq->q, TFD_QUEUE_SIZE_MAX, slots_num, - txq_id); - if (ret) - return ret; - - spin_lock_init(&txq->lock); - - /* - * Tell nic where to find circular buffer of Tx Frame Descriptors for - * given Tx queue, and enable the DMA channel used for that queue. - * Circular buffer (TFD queue in DRAM) physical base address */ - iwl_write_direct32(trans, FH_MEM_CBBC_QUEUE(txq_id), - txq->q.dma_addr >> 8); + iwl_tfd_set_tb(tfd, num_tbs, addr, len); return 0; } -/* - * iwl_pcie_txq_unmap - Unmap any remaining DMA mappings and free skb's - */ -static void iwl_pcie_txq_unmap(struct iwl_trans *trans, int txq_id) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_txq *txq = &trans_pcie->txq[txq_id]; - struct iwl_queue *q = &txq->q; - enum dma_data_direction dma_dir; - - if (!q->n_bd) - return; - - /* In the command queue, all the TBs are mapped as BIDI - * so unmap them as such. - */ - if (txq_id == trans_pcie->cmd_queue) - dma_dir = DMA_BIDIRECTIONAL; - else - dma_dir = DMA_TO_DEVICE; - - spin_lock_bh(&txq->lock); - while (q->write_ptr != q->read_ptr) { - iwl_pcie_txq_free_tfd(trans, txq, dma_dir); - q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); - } - spin_unlock_bh(&txq->lock); -} - -/* - * iwl_pcie_txq_free - Deallocate DMA queue. - * @txq: Transmit queue to deallocate. +/*************** DMA-QUEUE-GENERAL-FUNCTIONS ***** + * DMA services * - * Empty queue by removing and destroying all BD's. - * Free all buffers. - * 0-fill, but do not free "txq" descriptor structure. - */ -static void iwl_pcie_txq_free(struct iwl_trans *trans, int txq_id) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_txq *txq = &trans_pcie->txq[txq_id]; - struct device *dev = trans->dev; - int i; - - if (WARN_ON(!txq)) - return; - - iwl_pcie_txq_unmap(trans, txq_id); - - /* De-alloc array of command/tx buffers */ - if (txq_id == trans_pcie->cmd_queue) - for (i = 0; i < txq->q.n_window; i++) { - kfree(txq->entries[i].cmd); - kfree(txq->entries[i].copy_cmd); - kfree(txq->entries[i].free_buf); - } - - /* De-alloc circular buffer of TFDs */ - if (txq->q.n_bd) { - dma_free_coherent(dev, sizeof(struct iwl_tfd) * - txq->q.n_bd, txq->tfds, txq->q.dma_addr); - memset(&txq->q.dma_addr, 0, sizeof(txq->q.dma_addr)); - } - - kfree(txq->entries); - txq->entries = NULL; - - del_timer_sync(&txq->stuck_timer); - - /* 0-fill queue descriptor structure */ - memset(txq, 0, sizeof(*txq)); -} - -/* - * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask - */ -static void iwl_pcie_txq_set_sched(struct iwl_trans *trans, u32 mask) -{ - struct iwl_trans_pcie __maybe_unused *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - - iwl_write_prph(trans, SCD_TXFACT, mask); -} - -void iwl_pcie_tx_start(struct iwl_trans *trans, u32 scd_base_addr) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - u32 a; - int chan; - u32 reg_val; - - /* make sure all queue are not stopped/used */ - memset(trans_pcie->queue_stopped, 0, sizeof(trans_pcie->queue_stopped)); - memset(trans_pcie->queue_used, 0, sizeof(trans_pcie->queue_used)); - - trans_pcie->scd_base_addr = - iwl_read_prph(trans, SCD_SRAM_BASE_ADDR); - - WARN_ON(scd_base_addr != 0 && - scd_base_addr != trans_pcie->scd_base_addr); - - a = trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_LOWER_BOUND; - /* reset conext data memory */ - for (; a < trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_UPPER_BOUND; - a += 4) - iwl_write_targ_mem(trans, a, 0); - /* reset tx status memory */ - for (; a < trans_pcie->scd_base_addr + SCD_TX_STTS_MEM_UPPER_BOUND; - a += 4) - iwl_write_targ_mem(trans, a, 0); - for (; a < trans_pcie->scd_base_addr + - SCD_TRANS_TBL_OFFSET_QUEUE( - trans->cfg->base_params->num_of_queues); - a += 4) - iwl_write_targ_mem(trans, a, 0); - - iwl_write_prph(trans, SCD_DRAM_BASE_ADDR, - trans_pcie->scd_bc_tbls.dma >> 10); - - /* The chain extension of the SCD doesn't work well. This feature is - * enabled by default by the HW, so we need to disable it manually. - */ - iwl_write_prph(trans, SCD_CHAINEXT_EN, 0); - - iwl_trans_ac_txq_enable(trans, trans_pcie->cmd_queue, - trans_pcie->cmd_fifo); - - /* Activate all Tx DMA/FIFO channels */ - iwl_pcie_txq_set_sched(trans, IWL_MASK(0, 7)); - - /* Enable DMA channel */ - for (chan = 0; chan < FH_TCSR_CHNL_NUM; chan++) - iwl_write_direct32(trans, FH_TCSR_CHNL_TX_CONFIG_REG(chan), - FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | - FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE); - - /* Update FH chicken bits */ - reg_val = iwl_read_direct32(trans, FH_TX_CHICKEN_BITS_REG); - iwl_write_direct32(trans, FH_TX_CHICKEN_BITS_REG, - reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); - - /* Enable L1-Active */ - iwl_clear_bits_prph(trans, APMG_PCIDEV_STT_REG, - APMG_PCIDEV_STT_VAL_L1_ACT_DIS); -} - -/* - * iwl_pcie_tx_stop - Stop all Tx DMA channels - */ -int iwl_pcie_tx_stop(struct iwl_trans *trans) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - int ch, txq_id, ret; - unsigned long flags; - - /* Turn off all Tx DMA fifos */ - spin_lock_irqsave(&trans_pcie->irq_lock, flags); - - iwl_pcie_txq_set_sched(trans, 0); - - /* Stop each Tx DMA channel, and wait for it to be idle */ - for (ch = 0; ch < FH_TCSR_CHNL_NUM; ch++) { - iwl_write_direct32(trans, - FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); - ret = iwl_poll_direct_bit(trans, FH_TSSR_TX_STATUS_REG, - FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), 1000); - if (ret < 0) - IWL_ERR(trans, - "Failing on timeout while stopping DMA channel %d [0x%08x]\n", - ch, - iwl_read_direct32(trans, - FH_TSSR_TX_STATUS_REG)); - } - spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); - - if (!trans_pcie->txq) { - IWL_WARN(trans, - "Stopping tx queues that aren't allocated...\n"); - return 0; - } - - /* Unmap DMA from host system and free skb's */ - for (txq_id = 0; txq_id < trans->cfg->base_params->num_of_queues; - txq_id++) - iwl_pcie_txq_unmap(trans, txq_id); - - return 0; -} - -/* - * iwl_trans_tx_free - Free TXQ Context + * Theory of operation * - * Destroy all TX DMA queues and structures - */ -void iwl_pcie_tx_free(struct iwl_trans *trans) -{ - int txq_id; - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - - /* Tx queues */ - if (trans_pcie->txq) { - for (txq_id = 0; - txq_id < trans->cfg->base_params->num_of_queues; txq_id++) - iwl_pcie_txq_free(trans, txq_id); - } + * A Tx or Rx queue resides in host DRAM, and is comprised of a circular buffer + * of buffer descriptors, each of which points to one or more data buffers for + * the device to read from or fill. Driver and device exchange status of each + * queue via "read" and "write" pointers. Driver keeps minimum of 2 empty + * entries in each circular buffer, to protect against confusing empty and full + * queue states. + * + * The device reads or writes the data in the queues via the device's several + * DMA/FIFO channels. Each queue is mapped to a single DMA channel. + * + * For Tx queue, there are low mark and high mark limits. If, after queuing + * the packet for Tx, free space become < low mark, Tx queue stopped. When + * reclaiming packets (on 'tx done IRQ), if free space become > high mark, + * Tx queue resumed. + * + ***************************************************/ - kfree(trans_pcie->txq); - trans_pcie->txq = NULL; +int iwl_queue_space(const struct iwl_queue *q) +{ + int s = q->read_ptr - q->write_ptr; - iwl_pcie_free_dma_ptr(trans, &trans_pcie->kw); + if (q->read_ptr > q->write_ptr) + s -= q->n_bd; - iwl_pcie_free_dma_ptr(trans, &trans_pcie->scd_bc_tbls); + if (s <= 0) + s += q->n_window; + /* keep some reserve to not confuse empty and full situations */ + s -= 2; + if (s < 0) + s = 0; + return s; } -/* - * iwl_pcie_tx_alloc - allocate TX context - * Allocate all Tx DMA structures and initialize them +/** + * iwl_queue_init - Initialize queue's high/low-water and read/write indexes */ -static int iwl_pcie_tx_alloc(struct iwl_trans *trans) +int iwl_queue_init(struct iwl_queue *q, int count, int slots_num, u32 id) { - int ret; - int txq_id, slots_num; - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - - u16 scd_bc_tbls_size = trans->cfg->base_params->num_of_queues * - sizeof(struct iwlagn_scd_bc_tbl); - - /*It is not allowed to alloc twice, so warn when this happens. - * We cannot rely on the previous allocation, so free and fail */ - if (WARN_ON(trans_pcie->txq)) { - ret = -EINVAL; - goto error; - } - - ret = iwl_pcie_alloc_dma_ptr(trans, &trans_pcie->scd_bc_tbls, - scd_bc_tbls_size); - if (ret) { - IWL_ERR(trans, "Scheduler BC Table allocation failed\n"); - goto error; - } - - /* Alloc keep-warm buffer */ - ret = iwl_pcie_alloc_dma_ptr(trans, &trans_pcie->kw, IWL_KW_SIZE); - if (ret) { - IWL_ERR(trans, "Keep Warm allocation failed\n"); - goto error; - } - - trans_pcie->txq = kcalloc(trans->cfg->base_params->num_of_queues, - sizeof(struct iwl_txq), GFP_KERNEL); - if (!trans_pcie->txq) { - IWL_ERR(trans, "Not enough memory for txq\n"); - ret = ENOMEM; - goto error; - } - - /* Alloc and init all Tx queues, including the command queue (#4/#9) */ - for (txq_id = 0; txq_id < trans->cfg->base_params->num_of_queues; - txq_id++) { - slots_num = (txq_id == trans_pcie->cmd_queue) ? - TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; - ret = iwl_pcie_txq_alloc(trans, &trans_pcie->txq[txq_id], - slots_num, txq_id); - if (ret) { - IWL_ERR(trans, "Tx %d queue alloc failed\n", txq_id); - goto error; - } - } - - return 0; - -error: - iwl_pcie_tx_free(trans); - - return ret; -} -int iwl_pcie_tx_init(struct iwl_trans *trans) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - int ret; - int txq_id, slots_num; - unsigned long flags; - bool alloc = false; - - if (!trans_pcie->txq) { - ret = iwl_pcie_tx_alloc(trans); - if (ret) - goto error; - alloc = true; - } + q->n_bd = count; + q->n_window = slots_num; + q->id = id; - spin_lock_irqsave(&trans_pcie->irq_lock, flags); + /* count must be power-of-two size, otherwise iwl_queue_inc_wrap + * and iwl_queue_dec_wrap are broken. */ + if (WARN_ON(!is_power_of_2(count))) + return -EINVAL; - /* Turn off all Tx DMA fifos */ - iwl_write_prph(trans, SCD_TXFACT, 0); + /* slots_num must be power-of-two size, otherwise + * get_cmd_index is broken. */ + if (WARN_ON(!is_power_of_2(slots_num))) + return -EINVAL; - /* Tell NIC where to find the "keep warm" buffer */ - iwl_write_direct32(trans, FH_KW_MEM_ADDR_REG, - trans_pcie->kw.dma >> 4); + q->low_mark = q->n_window / 4; + if (q->low_mark < 4) + q->low_mark = 4; - spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); + q->high_mark = q->n_window / 8; + if (q->high_mark < 2) + q->high_mark = 2; - /* Alloc and init all Tx queues, including the command queue (#4/#9) */ - for (txq_id = 0; txq_id < trans->cfg->base_params->num_of_queues; - txq_id++) { - slots_num = (txq_id == trans_pcie->cmd_queue) ? - TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; - ret = iwl_pcie_txq_init(trans, &trans_pcie->txq[txq_id], - slots_num, txq_id); - if (ret) { - IWL_ERR(trans, "Tx %d queue init failed\n", txq_id); - goto error; - } - } + q->write_ptr = q->read_ptr = 0; return 0; -error: - /*Upon error, free only if we allocated something */ - if (alloc) - iwl_pcie_tx_free(trans); - return ret; -} - -static inline void iwl_pcie_txq_progress(struct iwl_trans_pcie *trans_pcie, - struct iwl_txq *txq) -{ - if (!trans_pcie->wd_timeout) - return; - - /* - * if empty delete timer, otherwise move timer forward - * since we're making progress on this queue - */ - if (txq->q.read_ptr == txq->q.write_ptr) - del_timer(&txq->stuck_timer); - else - mod_timer(&txq->stuck_timer, jiffies + trans_pcie->wd_timeout); -} - -/* Frees buffers until index _not_ inclusive */ -void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn, - struct sk_buff_head *skbs) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_txq *txq = &trans_pcie->txq[txq_id]; - /* n_bd is usually 256 => n_bd - 1 = 0xff */ - int tfd_num = ssn & (txq->q.n_bd - 1); - struct iwl_queue *q = &txq->q; - int last_to_free; - - /* This function is not meant to release cmd queue*/ - if (WARN_ON(txq_id == trans_pcie->cmd_queue)) - return; - - spin_lock(&txq->lock); - - if (txq->q.read_ptr == tfd_num) - goto out; - - IWL_DEBUG_TX_REPLY(trans, "[Q %d] %d -> %d (%d)\n", - txq_id, txq->q.read_ptr, tfd_num, ssn); - - /*Since we free until index _not_ inclusive, the one before index is - * the last we will free. This one must be used */ - last_to_free = iwl_queue_dec_wrap(tfd_num, q->n_bd); - - if (!iwl_queue_used(q, last_to_free)) { - IWL_ERR(trans, - "%s: Read index for DMA queue txq id (%d), last_to_free %d is out of range [0-%d] %d %d.\n", - __func__, txq_id, last_to_free, q->n_bd, - q->write_ptr, q->read_ptr); - goto out; - } - - if (WARN_ON(!skb_queue_empty(skbs))) - goto out; - - for (; - q->read_ptr != tfd_num; - q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { - - if (WARN_ON_ONCE(txq->entries[txq->q.read_ptr].skb == NULL)) - continue; - - __skb_queue_tail(skbs, txq->entries[txq->q.read_ptr].skb); - - txq->entries[txq->q.read_ptr].skb = NULL; - - iwl_pcie_txq_inval_byte_cnt_tbl(trans, txq); - - iwl_pcie_txq_free_tfd(trans, txq, DMA_TO_DEVICE); - } - - iwl_pcie_txq_progress(trans_pcie, txq); - - if (iwl_queue_space(&txq->q) > txq->q.low_mark) - iwl_wake_queue(trans, txq); -out: - spin_unlock(&txq->lock); } -/* - * iwl_pcie_cmdq_reclaim - Reclaim TX command queue entries already Tx'd - * - * When FW advances 'R' index, all entries between old and new 'R' index - * need to be reclaimed. As result, some free space forms. If there is - * enough free space (> low mark), wake the stack that feeds us. - */ -static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx) +static void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_trans *trans, + struct iwl_tx_queue *txq) { - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_txq *txq = &trans_pcie->txq[txq_id]; - struct iwl_queue *q = &txq->q; - int nfreed = 0; - - lockdep_assert_held(&txq->lock); + struct iwl_trans_pcie *trans_pcie = + IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwlagn_scd_bc_tbl *scd_bc_tbl = trans_pcie->scd_bc_tbls.addr; + int txq_id = txq->q.id; + int read_ptr = txq->q.read_ptr; + u8 sta_id = 0; + __le16 bc_ent; + struct iwl_tx_cmd *tx_cmd = + (void *)txq->entries[txq->q.read_ptr].cmd->payload; - if ((idx >= q->n_bd) || (!iwl_queue_used(q, idx))) { - IWL_ERR(trans, - "%s: Read index for DMA queue txq id (%d), index %d is out of range [0-%d] %d %d.\n", - __func__, txq_id, idx, q->n_bd, - q->write_ptr, q->read_ptr); - return; - } + WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX); - for (idx = iwl_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx; - q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { + if (txq_id != trans_pcie->cmd_queue) + sta_id = tx_cmd->sta_id; - if (nfreed++ > 0) { - IWL_ERR(trans, "HCMD skipped: index (%d) %d %d\n", - idx, q->write_ptr, q->read_ptr); - iwl_op_mode_nic_error(trans->op_mode); - } - } + bc_ent = cpu_to_le16(1 | (sta_id << 12)); + scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent; - iwl_pcie_txq_progress(trans_pcie, txq); + if (read_ptr < TFD_QUEUE_SIZE_BC_DUP) + scd_bc_tbl[txq_id]. + tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent; } -static int iwl_pcie_txq_set_ratid_map(struct iwl_trans *trans, u16 ra_tid, +static int iwl_txq_set_ratid_map(struct iwl_trans *trans, u16 ra_tid, u16 txq_id) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); @@ -1014,8 +405,7 @@ static int iwl_pcie_txq_set_ratid_map(struct iwl_trans *trans, u16 ra_tid, return 0; } -static inline void iwl_pcie_txq_set_inactive(struct iwl_trans *trans, - u16 txq_id) +static inline void iwl_txq_set_inactive(struct iwl_trans *trans, u16 txq_id) { /* Simply stop the queue, but don't change any configuration; * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */ @@ -1034,7 +424,7 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo, WARN_ONCE(1, "queue %d already used - expect issues", txq_id); /* Stop this Tx queue before configuring it */ - iwl_pcie_txq_set_inactive(trans, txq_id); + iwl_txq_set_inactive(trans, txq_id); /* Set this queue as a chain-building queue unless it is CMD queue */ if (txq_id != trans_pcie->cmd_queue) @@ -1045,7 +435,7 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo, u16 ra_tid = BUILD_RAxTID(sta_id, tid); /* Map receiver-address / traffic-ID to this queue */ - iwl_pcie_txq_set_ratid_map(trans, ra_tid, txq_id); + iwl_txq_set_ratid_map(trans, ra_tid, txq_id); /* enable aggregations for the queue */ iwl_set_bits_prph(trans, SCD_AGGR_SEL, BIT(txq_id)); @@ -1099,20 +489,20 @@ void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id) return; } - iwl_pcie_txq_set_inactive(trans, txq_id); + iwl_txq_set_inactive(trans, txq_id); _iwl_write_targ_mem_dwords(trans, stts_addr, zero_val, ARRAY_SIZE(zero_val)); - iwl_pcie_txq_unmap(trans, txq_id); + iwl_tx_queue_unmap(trans, txq_id); IWL_DEBUG_TX_QUEUES(trans, "Deactivate queue %d\n", txq_id); } /*************** HOST COMMAND QUEUE FUNCTIONS *****/ -/* - * iwl_pcie_enqueue_hcmd - enqueue a uCode command +/** + * iwl_enqueue_hcmd - enqueue a uCode command * @priv: device private data point * @cmd: a point to the ucode command structure * @@ -1120,11 +510,10 @@ void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id) * failed. On success, it turns the index (> 0) of command in the * command queue. */ -static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, - struct iwl_host_cmd *cmd) +static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_txq *txq = &trans_pcie->txq[trans_pcie->cmd_queue]; + struct iwl_tx_queue *txq = &trans_pcie->txq[trans_pcie->cmd_queue]; struct iwl_queue *q = &txq->q; struct iwl_device_cmd *out_cmd; struct iwl_cmd_meta *out_meta; @@ -1187,7 +576,8 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, */ if (WARN(copy_size > TFD_MAX_PAYLOAD_SIZE, "Command %s (%#x) is too large (%d bytes)\n", - get_cmd_string(trans_pcie, cmd->id), cmd->id, copy_size)) { + trans_pcie_get_cmd_string(trans_pcie, cmd->id), + cmd->id, copy_size)) { idx = -EINVAL; goto free_dup_buf; } @@ -1250,7 +640,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, IWL_DEBUG_HC(trans, "Sending command %s (#%x), seq: 0x%04X, %d bytes at %d[%d]:%d\n", - get_cmd_string(trans_pcie, out_cmd->hdr.cmd), + trans_pcie_get_cmd_string(trans_pcie, out_cmd->hdr.cmd), out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence), cmd_size, q->write_ptr, idx, trans_pcie->cmd_queue); @@ -1264,7 +654,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, dma_unmap_addr_set(out_meta, mapping, phys_addr); dma_unmap_len_set(out_meta, len, copy_size); - iwl_pcie_txq_build_tfd(trans, txq, phys_addr, copy_size, 1); + iwlagn_txq_attach_buf_to_tfd(trans, txq, phys_addr, copy_size, 1); for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { const void *data = cmd->data[i]; @@ -1279,14 +669,15 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, phys_addr = dma_map_single(trans->dev, (void *)data, cmd->len[i], DMA_BIDIRECTIONAL); if (dma_mapping_error(trans->dev, phys_addr)) { - iwl_pcie_tfd_unmap(trans, out_meta, - &txq->tfds[q->write_ptr], - DMA_BIDIRECTIONAL); + iwl_unmap_tfd(trans, out_meta, + &txq->tfds[q->write_ptr], + DMA_BIDIRECTIONAL); idx = -ENOMEM; goto out; } - iwl_pcie_txq_build_tfd(trans, txq, phys_addr, cmd->len[i], 0); + iwlagn_txq_attach_buf_to_tfd(trans, txq, phys_addr, + cmd->len[i], 0); } out_meta->flags = cmd->flags; @@ -1305,7 +696,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, /* Increment and update queue's write index */ q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); - iwl_pcie_txq_inc_wr_ptr(trans, txq); + iwl_txq_update_write_ptr(trans, txq); out: spin_unlock_bh(&txq->lock); @@ -1315,8 +706,63 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, return idx; } -/* - * iwl_pcie_hcmd_complete - Pull unused buffers off the queue and reclaim them +static inline void iwl_queue_progress(struct iwl_trans_pcie *trans_pcie, + struct iwl_tx_queue *txq) +{ + if (!trans_pcie->wd_timeout) + return; + + /* + * if empty delete timer, otherwise move timer forward + * since we're making progress on this queue + */ + if (txq->q.read_ptr == txq->q.write_ptr) + del_timer(&txq->stuck_timer); + else + mod_timer(&txq->stuck_timer, jiffies + trans_pcie->wd_timeout); +} + +/** + * iwl_hcmd_queue_reclaim - Reclaim TX command queue entries already Tx'd + * + * When FW advances 'R' index, all entries between old and new 'R' index + * need to be reclaimed. As result, some free space forms. If there is + * enough free space (> low mark), wake the stack that feeds us. + */ +static void iwl_hcmd_queue_reclaim(struct iwl_trans *trans, int txq_id, + int idx) +{ + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id]; + struct iwl_queue *q = &txq->q; + int nfreed = 0; + + lockdep_assert_held(&txq->lock); + + if ((idx >= q->n_bd) || (iwl_queue_used(q, idx) == 0)) { + IWL_ERR(trans, + "%s: Read index for DMA queue txq id (%d), index %d is out of range [0-%d] %d %d.\n", + __func__, txq_id, idx, q->n_bd, + q->write_ptr, q->read_ptr); + return; + } + + for (idx = iwl_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx; + q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { + + if (nfreed++ > 0) { + IWL_ERR(trans, "HCMD skipped: index (%d) %d %d\n", + idx, q->write_ptr, q->read_ptr); + iwl_op_mode_nic_error(trans->op_mode); + } + + } + + iwl_queue_progress(trans_pcie, txq); +} + +/** + * 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) @@ -1325,8 +771,8 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, * will be executed. The attached skb (if present) will only be freed * if the callback returns 1 */ -void iwl_pcie_hcmd_complete(struct iwl_trans *trans, - struct iwl_rx_cmd_buffer *rxb, int handler_status) +void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_cmd_buffer *rxb, + int handler_status) { struct iwl_rx_packet *pkt = rxb_addr(rxb); u16 sequence = le16_to_cpu(pkt->hdr.sequence); @@ -1336,7 +782,7 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans, struct iwl_device_cmd *cmd; struct iwl_cmd_meta *meta; struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_txq *txq = &trans_pcie->txq[trans_pcie->cmd_queue]; + struct iwl_tx_queue *txq = &trans_pcie->txq[trans_pcie->cmd_queue]; /* If a Tx command is being handled and it isn't in the actual * command queue then there a command routing bug has been introduced @@ -1356,7 +802,7 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans, cmd = txq->entries[cmd_index].cmd; meta = &txq->entries[cmd_index].meta; - iwl_pcie_tfd_unmap(trans, meta, &txq->tfds[index], DMA_BIDIRECTIONAL); + iwl_unmap_tfd(trans, meta, &txq->tfds[index], DMA_BIDIRECTIONAL); /* Input error checking is done when commands are added to queue. */ if (meta->flags & CMD_WANT_SKB) { @@ -1368,17 +814,19 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans, meta->source->handler_status = handler_status; } - iwl_pcie_cmdq_reclaim(trans, txq_id, index); + iwl_hcmd_queue_reclaim(trans, txq_id, index); if (!(meta->flags & CMD_ASYNC)) { if (!test_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status)) { IWL_WARN(trans, "HCMD_ACTIVE already clear for command %s\n", - get_cmd_string(trans_pcie, cmd->hdr.cmd)); + trans_pcie_get_cmd_string(trans_pcie, + cmd->hdr.cmd)); } clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status); IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command %s\n", - get_cmd_string(trans_pcie, cmd->hdr.cmd)); + trans_pcie_get_cmd_string(trans_pcie, + cmd->hdr.cmd)); wake_up(&trans_pcie->wait_command_queue); } @@ -1389,8 +837,7 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans, #define HOST_COMPLETE_TIMEOUT (2 * HZ) -static int iwl_pcie_send_hcmd_async(struct iwl_trans *trans, - struct iwl_host_cmd *cmd) +static int iwl_send_cmd_async(struct iwl_trans *trans, struct iwl_host_cmd *cmd) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); int ret; @@ -1399,43 +846,43 @@ static int iwl_pcie_send_hcmd_async(struct iwl_trans *trans, if (WARN_ON(cmd->flags & CMD_WANT_SKB)) return -EINVAL; - ret = iwl_pcie_enqueue_hcmd(trans, cmd); + + ret = iwl_enqueue_hcmd(trans, cmd); if (ret < 0) { IWL_ERR(trans, "Error sending %s: enqueue_hcmd failed: %d\n", - get_cmd_string(trans_pcie, cmd->id), ret); + trans_pcie_get_cmd_string(trans_pcie, cmd->id), ret); return ret; } return 0; } -static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans, - struct iwl_host_cmd *cmd) +static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); int cmd_idx; int ret; IWL_DEBUG_INFO(trans, "Attempting to send sync command %s\n", - get_cmd_string(trans_pcie, cmd->id)); + trans_pcie_get_cmd_string(trans_pcie, cmd->id)); if (WARN_ON(test_and_set_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status))) { IWL_ERR(trans, "Command %s: a command is already active!\n", - get_cmd_string(trans_pcie, cmd->id)); + trans_pcie_get_cmd_string(trans_pcie, cmd->id)); return -EIO; } IWL_DEBUG_INFO(trans, "Setting HCMD_ACTIVE for command %s\n", - get_cmd_string(trans_pcie, cmd->id)); + trans_pcie_get_cmd_string(trans_pcie, cmd->id)); - cmd_idx = iwl_pcie_enqueue_hcmd(trans, cmd); + cmd_idx = iwl_enqueue_hcmd(trans, cmd); if (cmd_idx < 0) { ret = cmd_idx; clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status); IWL_ERR(trans, "Error sending %s: enqueue_hcmd failed: %d\n", - get_cmd_string(trans_pcie, cmd->id), ret); + trans_pcie_get_cmd_string(trans_pcie, cmd->id), ret); return ret; } @@ -1445,13 +892,13 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans, HOST_COMPLETE_TIMEOUT); if (!ret) { if (test_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status)) { - struct iwl_txq *txq = + struct iwl_tx_queue *txq = &trans_pcie->txq[trans_pcie->cmd_queue]; struct iwl_queue *q = &txq->q; IWL_ERR(trans, "Error sending %s: time out after %dms.\n", - get_cmd_string(trans_pcie, cmd->id), + trans_pcie_get_cmd_string(trans_pcie, cmd->id), jiffies_to_msecs(HOST_COMPLETE_TIMEOUT)); IWL_ERR(trans, @@ -1461,7 +908,8 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans, clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status); IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command %s\n", - get_cmd_string(trans_pcie, cmd->id)); + trans_pcie_get_cmd_string(trans_pcie, + cmd->id)); ret = -ETIMEDOUT; goto cancel; } @@ -1469,7 +917,7 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans, if (test_bit(STATUS_FW_ERROR, &trans_pcie->status)) { IWL_ERR(trans, "FW error in SYNC CMD %s\n", - get_cmd_string(trans_pcie, cmd->id)); + trans_pcie_get_cmd_string(trans_pcie, cmd->id)); ret = -EIO; goto cancel; } @@ -1482,7 +930,7 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans, if ((cmd->flags & CMD_WANT_SKB) && !cmd->resp_pkt) { IWL_ERR(trans, "Error: Response NULL in '%s'\n", - get_cmd_string(trans_pcie, cmd->id)); + trans_pcie_get_cmd_string(trans_pcie, cmd->id)); ret = -EIO; goto cancel; } @@ -1509,7 +957,7 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans, return ret; } -int iwl_trans_pcie_send_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) +int iwl_trans_pcie_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); @@ -1520,172 +968,62 @@ int iwl_trans_pcie_send_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) return -ERFKILL; if (cmd->flags & CMD_ASYNC) - return iwl_pcie_send_hcmd_async(trans, cmd); + return iwl_send_cmd_async(trans, cmd); /* We still can fail on RFKILL that can be asserted while we wait */ - return iwl_pcie_send_hcmd_sync(trans, cmd); + return iwl_send_cmd_sync(trans, cmd); } -int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, - struct iwl_device_cmd *dev_cmd, int txq_id) +/* Frees buffers until index _not_ inclusive */ +int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, + struct sk_buff_head *skbs) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct iwl_tx_cmd *tx_cmd = (struct iwl_tx_cmd *)dev_cmd->payload; - struct iwl_cmd_meta *out_meta; - struct iwl_txq *txq; - struct iwl_queue *q; - dma_addr_t phys_addr = 0; - dma_addr_t txcmd_phys; - dma_addr_t scratch_phys; - u16 len, firstlen, secondlen; - u8 wait_write_ptr = 0; - __le16 fc = hdr->frame_control; - u8 hdr_len = ieee80211_hdrlen(fc); - u16 __maybe_unused wifi_seq; - - txq = &trans_pcie->txq[txq_id]; - q = &txq->q; - - if (unlikely(!test_bit(txq_id, trans_pcie->queue_used))) { - WARN_ON_ONCE(1); - return -EINVAL; - } + struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id]; + struct iwl_queue *q = &txq->q; + int last_to_free; + int freed = 0; - spin_lock(&txq->lock); + /* This function is not meant to release cmd queue*/ + if (WARN_ON(txq_id == trans_pcie->cmd_queue)) + return 0; - /* In AGG mode, the index in the ring must correspond to the WiFi - * sequence number. This is a HW requirements to help the SCD to parse - * the BA. - * Check here that the packets are in the right place on the ring. - */ -#ifdef CONFIG_IWLWIFI_DEBUG - wifi_seq = SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); - WARN_ONCE((iwl_read_prph(trans, SCD_AGGR_SEL) & BIT(txq_id)) && - ((wifi_seq & 0xff) != q->write_ptr), - "Q: %d WiFi Seq %d tfdNum %d", - txq_id, wifi_seq, q->write_ptr); -#endif - - /* Set up driver data for this TFD */ - txq->entries[q->write_ptr].skb = skb; - txq->entries[q->write_ptr].cmd = dev_cmd; - - dev_cmd->hdr.cmd = REPLY_TX; - dev_cmd->hdr.sequence = - cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) | - INDEX_TO_SEQ(q->write_ptr))); - - /* Set up first empty entry in queue's array of Tx/cmd buffers */ - out_meta = &txq->entries[q->write_ptr].meta; + lockdep_assert_held(&txq->lock); - /* - * Use the first empty entry in this queue's command buffer array - * to contain the Tx command and MAC header concatenated together - * (payload data will be in another buffer). - * Size of this varies, due to varying MAC header length. - * If end is not dword aligned, we'll have 2 extra bytes at the end - * of the MAC header (device reads on dword boundaries). - * We'll tell device about this padding later. - */ - len = sizeof(struct iwl_tx_cmd) + - sizeof(struct iwl_cmd_header) + hdr_len; - firstlen = (len + 3) & ~3; - - /* Tell NIC about any 2-byte padding after MAC header */ - if (firstlen != len) - tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK; - - /* Physical address of this Tx command's header (not MAC header!), - * within command buffer array. */ - txcmd_phys = dma_map_single(trans->dev, - &dev_cmd->hdr, firstlen, - DMA_BIDIRECTIONAL); - if (unlikely(dma_mapping_error(trans->dev, txcmd_phys))) - goto out_err; - dma_unmap_addr_set(out_meta, mapping, txcmd_phys); - dma_unmap_len_set(out_meta, len, firstlen); - - if (!ieee80211_has_morefrags(fc)) { - txq->need_update = 1; - } else { - wait_write_ptr = 1; - txq->need_update = 0; - } + /*Since we free until index _not_ inclusive, the one before index is + * the last we will free. This one must be used */ + last_to_free = iwl_queue_dec_wrap(index, q->n_bd); - /* Set up TFD's 2nd entry to point directly to remainder of skb, - * if any (802.11 null frames have no payload). */ - secondlen = skb->len - hdr_len; - if (secondlen > 0) { - phys_addr = dma_map_single(trans->dev, skb->data + hdr_len, - secondlen, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(trans->dev, phys_addr))) { - dma_unmap_single(trans->dev, - dma_unmap_addr(out_meta, mapping), - dma_unmap_len(out_meta, len), - DMA_BIDIRECTIONAL); - goto out_err; - } + if ((index >= q->n_bd) || + (iwl_queue_used(q, last_to_free) == 0)) { + IWL_ERR(trans, + "%s: Read index for DMA queue txq id (%d), last_to_free %d is out of range [0-%d] %d %d.\n", + __func__, txq_id, last_to_free, q->n_bd, + q->write_ptr, q->read_ptr); + return 0; } - /* Attach buffers to TFD */ - iwl_pcie_txq_build_tfd(trans, txq, txcmd_phys, firstlen, 1); - if (secondlen > 0) - iwl_pcie_txq_build_tfd(trans, txq, phys_addr, secondlen, 0); - - scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) + - offsetof(struct iwl_tx_cmd, scratch); + if (WARN_ON(!skb_queue_empty(skbs))) + return 0; - /* take back ownership of DMA buffer to enable update */ - dma_sync_single_for_cpu(trans->dev, txcmd_phys, firstlen, - DMA_BIDIRECTIONAL); - tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys); - tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys); + for (; + q->read_ptr != index; + q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { - IWL_DEBUG_TX(trans, "sequence nr = 0X%x\n", - le16_to_cpu(dev_cmd->hdr.sequence)); - IWL_DEBUG_TX(trans, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags)); + if (WARN_ON_ONCE(txq->entries[txq->q.read_ptr].skb == NULL)) + continue; - /* Set up entry for this TFD in Tx byte-count array */ - iwl_pcie_txq_update_byte_cnt_tbl(trans, txq, le16_to_cpu(tx_cmd->len)); + __skb_queue_tail(skbs, txq->entries[txq->q.read_ptr].skb); - dma_sync_single_for_device(trans->dev, txcmd_phys, firstlen, - DMA_BIDIRECTIONAL); + txq->entries[txq->q.read_ptr].skb = NULL; - trace_iwlwifi_dev_tx(trans->dev, skb, - &txq->tfds[txq->q.write_ptr], - sizeof(struct iwl_tfd), - &dev_cmd->hdr, firstlen, - skb->data + hdr_len, secondlen); - trace_iwlwifi_dev_tx_data(trans->dev, skb, - skb->data + hdr_len, secondlen); + iwlagn_txq_inval_byte_cnt_tbl(trans, txq); - /* start timer if queue currently empty */ - if (txq->need_update && q->read_ptr == q->write_ptr && - trans_pcie->wd_timeout) - mod_timer(&txq->stuck_timer, jiffies + trans_pcie->wd_timeout); + iwl_txq_free_tfd(trans, txq, DMA_TO_DEVICE); + freed++; + } - /* Tell device the write index *just past* this latest filled TFD */ - q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); - iwl_pcie_txq_inc_wr_ptr(trans, txq); + iwl_queue_progress(trans_pcie, txq); - /* - * At this point the frame is "transmitted" successfully - * and we will get a TX status notification eventually, - * regardless of the value of ret. "ret" only indicates - * whether or not we should update the write pointer. - */ - if (iwl_queue_space(q) < q->high_mark) { - if (wait_write_ptr) { - txq->need_update = 1; - iwl_pcie_txq_inc_wr_ptr(trans, txq); - } else { - iwl_stop_queue(trans, txq); - } - } - spin_unlock(&txq->lock); - return 0; -out_err: - spin_unlock(&txq->lock); - return -1; + return freed; } diff --git a/trunk/drivers/net/wireless/libertas/cfg.c b/trunk/drivers/net/wireless/libertas/cfg.c index ec36868f6fc5..1c10b542ab23 100644 --- a/trunk/drivers/net/wireless/libertas/cfg.c +++ b/trunk/drivers/net/wireless/libertas/cfg.c @@ -436,19 +436,19 @@ static int lbs_add_wpa_tlv(u8 *tlv, const u8 *ie, u8 ie_len) */ static int lbs_cfg_set_monitor_channel(struct wiphy *wiphy, - struct cfg80211_chan_def *chandef) + struct ieee80211_channel *channel, + enum nl80211_channel_type channel_type) { struct lbs_private *priv = wiphy_priv(wiphy); int ret = -ENOTSUPP; lbs_deb_enter_args(LBS_DEB_CFG80211, "freq %d, type %d", - chandef->chan->center_freq, - cfg80211_get_chandef_type(chandef)); + channel->center_freq, channel_type); - if (cfg80211_get_chandef_type(chandef) != NL80211_CHAN_NO_HT) + if (channel_type != NL80211_CHAN_NO_HT) goto out; - ret = lbs_set_channel(priv, chandef->chan->hw_value); + ret = lbs_set_channel(priv, channel->hw_value); out: lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); @@ -1734,7 +1734,7 @@ static void lbs_join_post(struct lbs_private *priv, /* Fake DS channel IE */ *fake++ = WLAN_EID_DS_PARAMS; *fake++ = 1; - *fake++ = params->chandef.chan->hw_value; + *fake++ = params->channel->hw_value; /* Fake IBSS params IE */ *fake++ = WLAN_EID_IBSS_PARAMS; *fake++ = 2; @@ -1755,7 +1755,7 @@ static void lbs_join_post(struct lbs_private *priv, lbs_deb_hex(LBS_DEB_CFG80211, "IE", fake_ie, fake - fake_ie); bss = cfg80211_inform_bss(priv->wdev->wiphy, - params->chandef.chan, + params->channel, bssid, 0, capability, @@ -1833,7 +1833,7 @@ static int lbs_ibss_join_existing(struct lbs_private *priv, cmd.bss.beaconperiod = cpu_to_le16(params->beacon_interval); cmd.bss.ds.header.id = WLAN_EID_DS_PARAMS; cmd.bss.ds.header.len = 1; - cmd.bss.ds.channel = params->chandef.chan->hw_value; + cmd.bss.ds.channel = params->channel->hw_value; cmd.bss.ibss.header.id = WLAN_EID_IBSS_PARAMS; cmd.bss.ibss.header.len = 2; cmd.bss.ibss.atimwindow = 0; @@ -1942,7 +1942,7 @@ static int lbs_ibss_start_new(struct lbs_private *priv, cmd.ibss.atimwindow = 0; cmd.ds.header.id = WLAN_EID_DS_PARAMS; cmd.ds.header.len = 1; - cmd.ds.channel = params->chandef.chan->hw_value; + cmd.ds.channel = params->channel->hw_value; /* Only v8 and below support setting probe delay */ if (MRVL_FW_MAJOR_REV(priv->fwrelease) <= 8) cmd.probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME); @@ -1987,18 +1987,18 @@ static int lbs_join_ibss(struct wiphy *wiphy, struct net_device *dev, lbs_deb_enter(LBS_DEB_CFG80211); - if (!params->chandef.chan) { + if (!params->channel) { ret = -ENOTSUPP; goto out; } - ret = lbs_set_channel(priv, params->chandef.chan->hw_value); + ret = lbs_set_channel(priv, params->channel->hw_value); if (ret) goto out; /* Search if someone is beaconing. This assumes that the * bss list is populated already */ - bss = cfg80211_get_bss(wiphy, params->chandef.chan, params->bssid, + bss = cfg80211_get_bss(wiphy, params->channel, params->bssid, params->ssid, params->ssid_len, WLAN_CAPABILITY_IBSS, WLAN_CAPABILITY_IBSS); diff --git a/trunk/drivers/net/wireless/mac80211_hwsim.c b/trunk/drivers/net/wireless/mac80211_hwsim.c index 2aa8a1aa1184..a8ec7086ad09 100644 --- a/trunk/drivers/net/wireless/mac80211_hwsim.c +++ b/trunk/drivers/net/wireless/mac80211_hwsim.c @@ -681,7 +681,7 @@ static void mac80211_hwsim_tx_iter(void *_data, u8 *addr, return; if (!hwsim_chans_compat(data->channel, - rcu_dereference(vif->chanctx_conf)->def.chan)) + rcu_dereference(vif->chanctx_conf)->channel)) return; data->receive = true; @@ -699,7 +699,7 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw, struct ieee80211_rate *txrate = ieee80211_get_tx_rate(hw, info); memset(&rx_status, 0, sizeof(rx_status)); - rx_status.flag |= RX_FLAG_MACTIME_START; + rx_status.flag |= RX_FLAG_MACTIME_MPDU; rx_status.freq = chan->center_freq; rx_status.band = chan->band; rx_status.rate_idx = info->control.rates[0].idx; @@ -751,11 +751,7 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw, continue; } - /* - * reserve some space for our vendor and the normal - * radiotap header, since we're copying anyway - */ - nskb = skb_copy_expand(skb, 64, 0, GFP_ATOMIC); + nskb = skb_copy(skb, GFP_ATOMIC); if (nskb == NULL) continue; @@ -773,33 +769,6 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw, (data->tsf_offset - data2->tsf_offset) + 24 * 8 * 10 / txrate->bitrate); -#if 0 - /* - * Don't enable this code by default as the OUI 00:00:00 - * is registered to Xerox so we shouldn't use it here, it - * might find its way into pcap files. - * Note that this code requires the headroom in the SKB - * that was allocated earlier. - */ - rx_status.vendor_radiotap_oui[0] = 0x00; - rx_status.vendor_radiotap_oui[1] = 0x00; - rx_status.vendor_radiotap_oui[2] = 0x00; - rx_status.vendor_radiotap_subns = 127; - /* - * Radiotap vendor namespaces can (and should) also be - * split into fields by using the standard radiotap - * presence bitmap mechanism. Use just BIT(0) here for - * the presence bitmap. - */ - rx_status.vendor_radiotap_bitmap = BIT(0); - /* We have 8 bytes of (dummy) data */ - rx_status.vendor_radiotap_len = 8; - /* For testing, also require it to be aligned */ - rx_status.vendor_radiotap_align = 8; - /* push the data */ - memcpy(skb_push(nskb, 8), "ABCDEFGH", 8); -#endif - memcpy(IEEE80211_SKB_RXCB(nskb), &rx_status, sizeof(rx_status)); ieee80211_rx_irqsafe(data2->hw, nskb); } @@ -832,7 +801,7 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, } else { chanctx_conf = rcu_dereference(txi->control.vif->chanctx_conf); if (chanctx_conf) - channel = chanctx_conf->def.chan; + channel = chanctx_conf->channel; else channel = NULL; } @@ -977,7 +946,7 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac, return; mac80211_hwsim_tx_frame(hw, skb, - rcu_dereference(vif->chanctx_conf)->def.chan); + rcu_dereference(vif->chanctx_conf)->channel); } @@ -1107,8 +1076,9 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, } if (changed & BSS_CHANGED_HT) { - wiphy_debug(hw->wiphy, " HT: op_mode=0x%x\n", - info->ht_operation_mode); + wiphy_debug(hw->wiphy, " HT: op_mode=0x%x, chantype=%s\n", + info->ht_operation_mode, + hwsim_chantypes[info->channel_type]); } if (changed & BSS_CHANGED_BASIC_RATES) { @@ -1367,6 +1337,7 @@ static int mac80211_hwsim_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req) { struct mac80211_hwsim_data *hwsim = hw->priv; + int i; mutex_lock(&hwsim->mutex); if (WARN_ON(hwsim->tmp_chan || hwsim->hw_scan_request)) { @@ -1379,6 +1350,11 @@ static int mac80211_hwsim_hw_scan(struct ieee80211_hw *hw, mutex_unlock(&hwsim->mutex); wiphy_debug(hw->wiphy, "hwsim hw_scan request\n"); + for (i = 0; i < req->n_channels; i++) + printk(KERN_DEBUG "hwsim hw_scan freq %d\n", + req->channels[i]->center_freq); + print_hex_dump(KERN_DEBUG, "scan IEs: ", DUMP_PREFIX_OFFSET, + 16, 1, req->ie, req->ie_len, 1); ieee80211_queue_delayed_work(hwsim->hw, &hwsim->hw_scan, 0); @@ -1446,8 +1422,8 @@ static void hw_roc_done(struct work_struct *work) } static int mac80211_hwsim_roc(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, int duration) { struct mac80211_hwsim_data *hwsim = hw->priv; @@ -1490,20 +1466,16 @@ static int mac80211_hwsim_add_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx) { hwsim_set_chanctx_magic(ctx); - wiphy_debug(hw->wiphy, - "add channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n", - ctx->def.chan->center_freq, ctx->def.width, - ctx->def.center_freq1, ctx->def.center_freq2); + wiphy_debug(hw->wiphy, "add channel context %d MHz/%d\n", + ctx->channel->center_freq, ctx->channel_type); return 0; } static void mac80211_hwsim_remove_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx) { - wiphy_debug(hw->wiphy, - "remove channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n", - ctx->def.chan->center_freq, ctx->def.width, - ctx->def.center_freq1, ctx->def.center_freq2); + wiphy_debug(hw->wiphy, "remove channel context %d MHz/%d\n", + ctx->channel->center_freq, ctx->channel_type); hwsim_check_chanctx_magic(ctx); hwsim_clear_chanctx_magic(ctx); } @@ -1513,10 +1485,8 @@ static void mac80211_hwsim_change_chanctx(struct ieee80211_hw *hw, u32 changed) { hwsim_check_chanctx_magic(ctx); - wiphy_debug(hw->wiphy, - "change channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n", - ctx->def.chan->center_freq, ctx->def.width, - ctx->def.center_freq1, ctx->def.center_freq2); + wiphy_debug(hw->wiphy, "change channel context %#x (%d MHz/%d)\n", + changed, ctx->channel->center_freq, ctx->channel_type); } static int mac80211_hwsim_assign_vif_chanctx(struct ieee80211_hw *hw, @@ -1638,7 +1608,7 @@ static void hwsim_send_ps_poll(void *dat, u8 *mac, struct ieee80211_vif *vif) rcu_read_lock(); mac80211_hwsim_tx_frame(data->hw, skb, - rcu_dereference(vif->chanctx_conf)->def.chan); + rcu_dereference(vif->chanctx_conf)->channel); rcu_read_unlock(); } @@ -1670,7 +1640,7 @@ static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac, rcu_read_lock(); mac80211_hwsim_tx_frame(data->hw, skb, - rcu_dereference(vif->chanctx_conf)->def.chan); + rcu_dereference(vif->chanctx_conf)->channel); rcu_read_unlock(); } @@ -2202,34 +2172,6 @@ static int __init init_mac80211_hwsim(void) sband->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; hw->wiphy->bands[band] = sband; - - if (channels == 1) - continue; - - sband->vht_cap.vht_supported = true; - sband->vht_cap.cap = - IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | - IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ | - IEEE80211_VHT_CAP_RXLDPC | - IEEE80211_VHT_CAP_SHORT_GI_80 | - IEEE80211_VHT_CAP_SHORT_GI_160 | - IEEE80211_VHT_CAP_TXSTBC | - IEEE80211_VHT_CAP_RXSTBC_1 | - IEEE80211_VHT_CAP_RXSTBC_2 | - IEEE80211_VHT_CAP_RXSTBC_3 | - IEEE80211_VHT_CAP_RXSTBC_4 | - IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT; - sband->vht_cap.vht_mcs.rx_mcs_map = - cpu_to_le16(IEEE80211_VHT_MCS_SUPPORT_0_8 << 0 | - IEEE80211_VHT_MCS_SUPPORT_0_8 << 2 | - IEEE80211_VHT_MCS_SUPPORT_0_9 << 4 | - IEEE80211_VHT_MCS_SUPPORT_0_8 << 6 | - IEEE80211_VHT_MCS_SUPPORT_0_8 << 8 | - IEEE80211_VHT_MCS_SUPPORT_0_9 << 10 | - IEEE80211_VHT_MCS_SUPPORT_0_9 << 12 | - IEEE80211_VHT_MCS_SUPPORT_0_8 << 14); - sband->vht_cap.vht_mcs.tx_mcs_map = - sband->vht_cap.vht_mcs.rx_mcs_map; } /* By default all radios are belonging to the first group */ data->group = 1; diff --git a/trunk/drivers/net/wireless/mwifiex/cfg80211.c b/trunk/drivers/net/wireless/mwifiex/cfg80211.c index a875499f8945..41be319665eb 100644 --- a/trunk/drivers/net/wireless/mwifiex/cfg80211.c +++ b/trunk/drivers/net/wireless/mwifiex/cfg80211.c @@ -180,8 +180,10 @@ mwifiex_form_mgmt_frame(struct sk_buff *skb, const u8 *buf, size_t len) static int mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, struct ieee80211_channel *chan, bool offchan, - unsigned int wait, const u8 *buf, size_t len, - bool no_cck, bool dont_wait_for_ack, u64 *cookie) + enum nl80211_channel_type channel_type, + bool channel_type_valid, unsigned int wait, + const u8 *buf, size_t len, bool no_cck, + bool dont_wait_for_ack, u64 *cookie) { struct sk_buff *skb; u16 pkt_len; @@ -251,6 +253,7 @@ static int mwifiex_cfg80211_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev, struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, unsigned int duration, u64 *cookie) { struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev); @@ -268,14 +271,15 @@ mwifiex_cfg80211_remain_on_channel(struct wiphy *wiphy, } ret = mwifiex_remain_on_chan_cfg(priv, HostCmd_ACT_GEN_SET, chan, - duration); + &channel_type, duration); if (!ret) { *cookie = random32() | 1; priv->roc_cfg.cookie = *cookie; priv->roc_cfg.chan = *chan; + priv->roc_cfg.chan_type = channel_type; - cfg80211_ready_on_channel(wdev, *cookie, chan, + cfg80211_ready_on_channel(wdev, *cookie, chan, channel_type, duration, GFP_ATOMIC); wiphy_dbg(wiphy, "info: ROC, cookie = 0x%llx\n", *cookie); @@ -298,11 +302,13 @@ mwifiex_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, return -ENOENT; ret = mwifiex_remain_on_chan_cfg(priv, HostCmd_ACT_GEN_REMOVE, - &priv->roc_cfg.chan, 0); + &priv->roc_cfg.chan, + &priv->roc_cfg.chan_type, 0); if (!ret) { cfg80211_remain_on_channel_expired(wdev, cookie, &priv->roc_cfg.chan, + priv->roc_cfg.chan_type, GFP_ATOMIC); memset(&priv->roc_cfg, 0, sizeof(struct mwifiex_roc_cfg)); @@ -1291,23 +1297,21 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, return -EINVAL; } - bss_cfg->channel = ieee80211_frequency_to_channel( - params->chandef.chan->center_freq); + bss_cfg->channel = + (u8)ieee80211_frequency_to_channel(params->channel->center_freq); /* Set appropriate bands */ - if (params->chandef.chan->band == IEEE80211_BAND_2GHZ) { + if (params->channel->band == IEEE80211_BAND_2GHZ) { bss_cfg->band_cfg = BAND_CONFIG_BG; - if (cfg80211_get_chandef_type(¶ms->chandef) == - NL80211_CHAN_NO_HT) + if (params->channel_type == NL80211_CHAN_NO_HT) config_bands = BAND_B | BAND_G; else config_bands = BAND_B | BAND_G | BAND_GN; } else { bss_cfg->band_cfg = BAND_CONFIG_A; - if (cfg80211_get_chandef_type(¶ms->chandef) == - NL80211_CHAN_NO_HT) + if (params->channel_type == NL80211_CHAN_NO_HT) config_bands = BAND_A; else config_bands = BAND_AN | BAND_A; @@ -1680,7 +1684,7 @@ static int mwifiex_set_ibss_params(struct mwifiex_private *priv, int index = 0, i; u8 config_bands = 0; - if (params->chandef.chan->band == IEEE80211_BAND_2GHZ) { + if (params->channel->band == IEEE80211_BAND_2GHZ) { if (!params->basic_rates) { config_bands = BAND_B | BAND_G; } else { @@ -1705,12 +1709,10 @@ static int mwifiex_set_ibss_params(struct mwifiex_private *priv, } } - if (cfg80211_get_chandef_type(¶ms->chandef) != - NL80211_CHAN_NO_HT) + if (params->channel_type != NL80211_CHAN_NO_HT) config_bands |= BAND_GN; } else { - if (cfg80211_get_chandef_type(¶ms->chandef) != - NL80211_CHAN_NO_HT) + if (params->channel_type == NL80211_CHAN_NO_HT) config_bands = BAND_A; else config_bands = BAND_AN | BAND_A; @@ -1727,10 +1729,9 @@ static int mwifiex_set_ibss_params(struct mwifiex_private *priv, } adapter->sec_chan_offset = - mwifiex_chan_type_to_sec_chan_offset( - cfg80211_get_chandef_type(¶ms->chandef)); - priv->adhoc_channel = ieee80211_frequency_to_channel( - params->chandef.chan->center_freq); + mwifiex_chan_type_to_sec_chan_offset(params->channel_type); + priv->adhoc_channel = + ieee80211_frequency_to_channel(params->channel->center_freq); wiphy_dbg(wiphy, "info: set ibss band %d, chan %d, chan offset %d\n", config_bands, priv->adhoc_channel, adapter->sec_chan_offset); @@ -1764,8 +1765,7 @@ mwifiex_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, ret = mwifiex_cfg80211_assoc(priv, params->ssid_len, params->ssid, params->bssid, priv->bss_mode, - params->chandef.chan, NULL, - params->privacy); + params->channel, NULL, params->privacy); done: if (!ret) { cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid, GFP_KERNEL); @@ -1948,21 +1948,6 @@ mwifiex_setup_ht_caps(struct ieee80211_sta_ht_cap *ht_info, else ht_info->cap &= ~IEEE80211_HT_CAP_TX_STBC; - if (ISSUPP_GREENFIELD(adapter->hw_dot_11n_dev_cap)) - ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD; - else - ht_info->cap &= ~IEEE80211_HT_CAP_GRN_FLD; - - if (ISENABLED_40MHZ_INTOLERANT(adapter->hw_dot_11n_dev_cap)) - ht_info->cap |= IEEE80211_HT_CAP_40MHZ_INTOLERANT; - else - ht_info->cap &= ~IEEE80211_HT_CAP_40MHZ_INTOLERANT; - - if (ISSUPP_RXLDPC(adapter->hw_dot_11n_dev_cap)) - ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING; - else - ht_info->cap &= ~IEEE80211_HT_CAP_LDPC_CODING; - ht_info->cap &= ~IEEE80211_HT_CAP_MAX_AMSDU; ht_info->cap |= IEEE80211_HT_CAP_SM_PS; diff --git a/trunk/drivers/net/wireless/mwifiex/cmdevt.c b/trunk/drivers/net/wireless/mwifiex/cmdevt.c index 5f438e6c2155..c9528b3e9e9a 100644 --- a/trunk/drivers/net/wireless/mwifiex/cmdevt.c +++ b/trunk/drivers/net/wireless/mwifiex/cmdevt.c @@ -890,6 +890,9 @@ mwifiex_cmd_timeout_func(unsigned long function_context) return; } cmd_node = adapter->curr_cmd; + if (cmd_node->wait_q_enabled) + adapter->cmd_wait_q.status = -ETIMEDOUT; + if (cmd_node) { adapter->dbg.timeout_cmd_id = adapter->dbg.last_cmd_id[adapter->dbg.last_cmd_index]; @@ -938,14 +941,6 @@ mwifiex_cmd_timeout_func(unsigned long function_context) dev_err(adapter->dev, "ps_mode=%d ps_state=%d\n", adapter->ps_mode, adapter->ps_state); - - if (cmd_node->wait_q_enabled) { - adapter->cmd_wait_q.status = -ETIMEDOUT; - wake_up_interruptible(&adapter->cmd_wait_q.wait); - mwifiex_cancel_pending_ioctl(adapter); - /* reset cmd_sent flag to unblock new commands */ - adapter->cmd_sent = false; - } } if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING) mwifiex_init_fw_complete(adapter); diff --git a/trunk/drivers/net/wireless/mwifiex/fw.h b/trunk/drivers/net/wireless/mwifiex/fw.h index 4dc8e2e9a889..dda588b35570 100644 --- a/trunk/drivers/net/wireless/mwifiex/fw.h +++ b/trunk/drivers/net/wireless/mwifiex/fw.h @@ -194,8 +194,6 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { #define ISSUPP_TXSTBC(Dot11nDevCap) (Dot11nDevCap & BIT(25)) #define ISSUPP_RXSTBC(Dot11nDevCap) (Dot11nDevCap & BIT(26)) #define ISSUPP_GREENFIELD(Dot11nDevCap) (Dot11nDevCap & BIT(29)) -#define ISENABLED_40MHZ_INTOLERANT(Dot11nDevCap) (Dot11nDevCap & BIT(8)) -#define ISSUPP_RXLDPC(Dot11nDevCap) (Dot11nDevCap & BIT(22)) /* httxcfg bitmap * 0 reserved diff --git a/trunk/drivers/net/wireless/mwifiex/main.h b/trunk/drivers/net/wireless/mwifiex/main.h index 1b3cfc821940..db57dd430e92 100644 --- a/trunk/drivers/net/wireless/mwifiex/main.h +++ b/trunk/drivers/net/wireless/mwifiex/main.h @@ -371,6 +371,7 @@ struct wps { struct mwifiex_roc_cfg { u64 cookie; struct ieee80211_channel chan; + enum nl80211_channel_type chan_type; }; struct mwifiex_adapter; @@ -1017,6 +1018,7 @@ int mwifiex_get_ver_ext(struct mwifiex_private *priv); int mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action, struct ieee80211_channel *chan, + enum nl80211_channel_type *channel_type, unsigned int duration); int mwifiex_set_bss_role(struct mwifiex_private *priv, u8 bss_role); diff --git a/trunk/drivers/net/wireless/mwifiex/sdio.c b/trunk/drivers/net/wireless/mwifiex/sdio.c index 5a1c1d0e5599..4fbbd611f630 100644 --- a/trunk/drivers/net/wireless/mwifiex/sdio.c +++ b/trunk/drivers/net/wireless/mwifiex/sdio.c @@ -161,6 +161,7 @@ static int mwifiex_sdio_suspend(struct device *dev) struct sdio_mmc_card *card; struct mwifiex_adapter *adapter; mmc_pm_flag_t pm_flag = 0; + int hs_actived = 0; int i; int ret = 0; @@ -187,14 +188,12 @@ static int mwifiex_sdio_suspend(struct device *dev) adapter = card->adapter; /* Enable the Host Sleep */ - if (!mwifiex_enable_hs(adapter)) { - dev_err(adapter->dev, "cmd: failed to suspend\n"); - return -EFAULT; + hs_actived = mwifiex_enable_hs(adapter); + if (hs_actived) { + pr_debug("cmd: suspend with MMC_PM_KEEP_POWER\n"); + ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); } - dev_dbg(adapter->dev, "cmd: suspend with MMC_PM_KEEP_POWER\n"); - ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); - /* Indicate device suspended */ adapter->is_suspended = true; diff --git a/trunk/drivers/net/wireless/mwifiex/sta_event.c b/trunk/drivers/net/wireless/mwifiex/sta_event.c index 41aafc7454ed..5b0d71969ba7 100644 --- a/trunk/drivers/net/wireless/mwifiex/sta_event.c +++ b/trunk/drivers/net/wireless/mwifiex/sta_event.c @@ -421,6 +421,7 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) cfg80211_remain_on_channel_expired(priv->wdev, priv->roc_cfg.cookie, &priv->roc_cfg.chan, + priv->roc_cfg.chan_type, GFP_ATOMIC); memset(&priv->roc_cfg, 0x00, sizeof(struct mwifiex_roc_cfg)); diff --git a/trunk/drivers/net/wireless/mwifiex/sta_ioctl.c b/trunk/drivers/net/wireless/mwifiex/sta_ioctl.c index 95e3ab531c93..c8b50c70a03d 100644 --- a/trunk/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/trunk/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -161,9 +161,8 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv, int ret; u8 *beacon_ie; struct mwifiex_bss_priv *bss_priv = (void *)bss->priv; - size_t beacon_ie_len = bss->len_information_elements; - beacon_ie = kmemdup(bss->information_elements, beacon_ie_len, + beacon_ie = kmemdup(bss->information_elements, bss->len_beacon_ies, GFP_KERNEL); if (!beacon_ie) { dev_err(priv->adapter->dev, " failed to alloc beacon_ie\n"); @@ -173,7 +172,7 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv, memcpy(bss_desc->mac_address, bss->bssid, ETH_ALEN); bss_desc->rssi = bss->signal; bss_desc->beacon_buf = beacon_ie; - bss_desc->beacon_buf_size = beacon_ie_len; + bss_desc->beacon_buf_size = bss->len_beacon_ies; bss_desc->beacon_period = bss->beacon_interval; bss_desc->cap_info_bitmap = bss->capability; bss_desc->bss_band = bss_priv->band; @@ -462,7 +461,7 @@ int mwifiex_enable_hs(struct mwifiex_adapter *adapter) } if (adapter->hs_activated) { - dev_dbg(adapter->dev, "cmd: HS Already activated\n"); + dev_dbg(adapter->dev, "cmd: HS Already actived\n"); return true; } @@ -1045,6 +1044,7 @@ mwifiex_get_ver_ext(struct mwifiex_private *priv) int mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action, struct ieee80211_channel *chan, + enum nl80211_channel_type *ct, unsigned int duration) { struct host_cmd_ds_remain_on_chan roc_cfg; @@ -1054,7 +1054,7 @@ mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action, roc_cfg.action = cpu_to_le16(action); if (action == HostCmd_ACT_GEN_SET) { roc_cfg.band_cfg = chan->band; - sc = mwifiex_chan_type_to_sec_chan_offset(NL80211_CHAN_NO_HT); + sc = mwifiex_chan_type_to_sec_chan_offset(*ct); roc_cfg.band_cfg |= (sc << 2); roc_cfg.channel = diff --git a/trunk/drivers/net/wireless/mwifiex/usb.c b/trunk/drivers/net/wireless/mwifiex/usb.c index 63ac9f2d11ae..bbe1f3518e4b 100644 --- a/trunk/drivers/net/wireless/mwifiex/usb.c +++ b/trunk/drivers/net/wireless/mwifiex/usb.c @@ -351,7 +351,7 @@ static int mwifiex_usb_probe(struct usb_interface *intf, card->udev = udev; card->intf = intf; - pr_debug("info: bcdUSB=%#x Device Class=%#x SubClass=%#x Protocol=%#x\n", + pr_debug("info: bcdUSB=%#x Device Class=%#x SubClass=%#x Protocl=%#x\n", udev->descriptor.bcdUSB, udev->descriptor.bDeviceClass, udev->descriptor.bDeviceSubClass, udev->descriptor.bDeviceProtocol); diff --git a/trunk/drivers/net/wireless/orinoco/cfg.c b/trunk/drivers/net/wireless/orinoco/cfg.c index d01edd2c50c5..7b751fba7e1f 100644 --- a/trunk/drivers/net/wireless/orinoco/cfg.c +++ b/trunk/drivers/net/wireless/orinoco/cfg.c @@ -161,23 +161,24 @@ static int orinoco_scan(struct wiphy *wiphy, } static int orinoco_set_monitor_channel(struct wiphy *wiphy, - struct cfg80211_chan_def *chandef) + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type) { struct orinoco_private *priv = wiphy_priv(wiphy); int err = 0; unsigned long flags; int channel; - if (!chandef->chan) + if (!chan) return -EINVAL; - if (cfg80211_get_chandef_type(chandef) != NL80211_CHAN_NO_HT) + if (channel_type != NL80211_CHAN_NO_HT) return -EINVAL; - if (chandef->chan->band != IEEE80211_BAND_2GHZ) + if (chan->band != IEEE80211_BAND_2GHZ) return -EINVAL; - channel = ieee80211_freq_to_dsss_chan(chandef->chan->center_freq); + channel = ieee80211_freq_to_dsss_chan(chan->center_freq); if ((channel < 1) || (channel > NUM_CHANNELS) || !(priv->channel_mask & (1 << (channel - 1)))) diff --git a/trunk/drivers/net/wireless/p54/p54pci.c b/trunk/drivers/net/wireless/p54/p54pci.c index 810c343e4e30..b4390797d78c 100644 --- a/trunk/drivers/net/wireless/p54/p54pci.c +++ b/trunk/drivers/net/wireless/p54/p54pci.c @@ -659,7 +659,7 @@ static void __devexit p54p_remove(struct pci_dev *pdev) p54_free_common(dev); } -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_PM static int p54p_suspend(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); @@ -681,12 +681,19 @@ static int p54p_resume(struct device *device) return pci_set_power_state(pdev, PCI_D0); } -static SIMPLE_DEV_PM_OPS(p54pci_pm_ops, p54p_suspend, p54p_resume); +static const struct dev_pm_ops p54pci_pm_ops = { + .suspend = p54p_suspend, + .resume = p54p_resume, + .freeze = p54p_suspend, + .thaw = p54p_resume, + .poweroff = p54p_suspend, + .restore = p54p_resume, +}; #define P54P_PM_OPS (&p54pci_pm_ops) #else #define P54P_PM_OPS (NULL) -#endif /* CONFIG_PM_SLEEP */ +#endif /* CONFIG_PM */ static struct pci_driver p54p_driver = { .name = "p54pci", diff --git a/trunk/drivers/net/wireless/p54/txrx.c b/trunk/drivers/net/wireless/p54/txrx.c index 12f0a34477f2..5861e13a6fd8 100644 --- a/trunk/drivers/net/wireless/p54/txrx.c +++ b/trunk/drivers/net/wireless/p54/txrx.c @@ -369,11 +369,7 @@ static int p54_rx_data(struct p54_common *priv, struct sk_buff *skb) rx_status->mactime = ((u64)priv->tsf_high32) << 32 | tsf32; priv->tsf_low32 = tsf32; - /* LMAC API Page 10/29 - s_lm_data_in - clock - * "usec accurate timestamp of hardware clock - * at end of frame (before OFDM SIFS EOF padding" - */ - rx_status->flag |= RX_FLAG_MACTIME_END; + rx_status->flag |= RX_FLAG_MACTIME_MPDU; if (hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_ALIGN)) header_len += hdr->align[0]; diff --git a/trunk/drivers/net/wireless/rndis_wlan.c b/trunk/drivers/net/wireless/rndis_wlan.c index abe1d039be81..5390af36c064 100644 --- a/trunk/drivers/net/wireless/rndis_wlan.c +++ b/trunk/drivers/net/wireless/rndis_wlan.c @@ -2293,7 +2293,7 @@ static int rndis_join_ibss(struct wiphy *wiphy, struct net_device *dev, { struct rndis_wlan_private *priv = wiphy_priv(wiphy); struct usbnet *usbdev = priv->usbdev; - struct ieee80211_channel *channel = params->chandef.chan; + struct ieee80211_channel *channel = params->channel; struct ndis_80211_ssid ssid; enum nl80211_auth_type auth_type; int ret, alg, length, chan = -1; diff --git a/trunk/drivers/net/wireless/rt2x00/rt2800lib.c b/trunk/drivers/net/wireless/rt2x00/rt2800lib.c index c0441a715c96..3bc206d06cd1 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2800lib.c @@ -2449,7 +2449,7 @@ static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev) /* * Check if temperature compensation is supported. */ - if (tssi_bounds[4] == 0xff || step == 0xff) + if (tssi_bounds[4] == 0xff) return 0; /* diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c b/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c index 66b3b17b16d2..67d167993d45 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -1182,13 +1182,6 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) */ rt2x00dev->hw->vif_data_size = sizeof(struct rt2x00_intf); - /* - * rt2x00 devices can only use the last n bits of the MAC address - * for virtual interfaces. - */ - rt2x00dev->hw->wiphy->addr_mask[ETH_ALEN - 1] = - (rt2x00dev->ops->max_ap_intf - 1); - /* * Determine which operating modes are supported, all modes * which require beaconing, depend on the availability of diff --git a/trunk/drivers/net/wireless/rtl818x/rtl8180/dev.c b/trunk/drivers/net/wireless/rtl818x/rtl8180/dev.c index b4218a5f2066..021d83e1b1d3 100644 --- a/trunk/drivers/net/wireless/rtl818x/rtl8180/dev.c +++ b/trunk/drivers/net/wireless/rtl818x/rtl8180/dev.c @@ -150,7 +150,7 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev) rx_status.freq = dev->conf.channel->center_freq; rx_status.band = dev->conf.channel->band; rx_status.mactime = le64_to_cpu(entry->tsft); - rx_status.flag |= RX_FLAG_MACTIME_START; + rx_status.flag |= RX_FLAG_MACTIME_MPDU; if (flags & RTL818X_RX_DESC_FLAG_CRC32_ERR) rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; diff --git a/trunk/drivers/net/wireless/rtl818x/rtl8187/dev.c b/trunk/drivers/net/wireless/rtl818x/rtl8187/dev.c index 52e6bebcf089..7811b6315973 100644 --- a/trunk/drivers/net/wireless/rtl818x/rtl8187/dev.c +++ b/trunk/drivers/net/wireless/rtl818x/rtl8187/dev.c @@ -381,7 +381,7 @@ static void rtl8187_rx_cb(struct urb *urb) rx_status.rate_idx = rate; rx_status.freq = dev->conf.channel->center_freq; rx_status.band = dev->conf.channel->band; - rx_status.flag |= RX_FLAG_MACTIME_START; + rx_status.flag |= RX_FLAG_MACTIME_MPDU; if (flags & RTL818X_RX_DESC_FLAG_CRC32_ERR) rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); diff --git a/trunk/drivers/net/wireless/rtlwifi/pci.c b/trunk/drivers/net/wireless/rtlwifi/pci.c index 086140cba026..f38e30a947bc 100644 --- a/trunk/drivers/net/wireless/rtlwifi/pci.c +++ b/trunk/drivers/net/wireless/rtlwifi/pci.c @@ -1982,7 +1982,6 @@ void rtl_pci_disconnect(struct pci_dev *pdev) } EXPORT_SYMBOL(rtl_pci_disconnect); -#ifdef CONFIG_PM_SLEEP /*************************************** kernel pci power state define: PCI_D0 ((pci_power_t __force) 0) @@ -2022,7 +2021,6 @@ int rtl_pci_resume(struct device *dev) return 0; } EXPORT_SYMBOL(rtl_pci_resume); -#endif /* CONFIG_PM_SLEEP */ struct rtl_intf_ops rtl_pci_ops = { .read_efuse_byte = read_efuse_byte, diff --git a/trunk/drivers/net/wireless/rtlwifi/pci.h b/trunk/drivers/net/wireless/rtlwifi/pci.h index 7ea50a32bafb..f71b12aa8cb4 100644 --- a/trunk/drivers/net/wireless/rtlwifi/pci.h +++ b/trunk/drivers/net/wireless/rtlwifi/pci.h @@ -239,10 +239,8 @@ extern struct rtl_intf_ops rtl_pci_ops; int __devinit rtl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id); void rtl_pci_disconnect(struct pci_dev *pdev); -#ifdef CONFIG_PM_SLEEP int rtl_pci_suspend(struct device *dev); int rtl_pci_resume(struct device *dev); -#endif /* CONFIG_PM_SLEEP */ static inline u8 pci_read8_sync(struct rtl_priv *rtlpriv, u32 addr) { return readb((u8 __iomem *) rtlpriv->io.pci_mem_start + addr); diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c index 49f663bd93ff..60451eea4d82 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c @@ -372,7 +372,14 @@ MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n"); MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n"); MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)"); -static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume); +static const struct dev_pm_ops rtlwifi_pm_ops = { + .suspend = rtl_pci_suspend, + .resume = rtl_pci_resume, + .freeze = rtl_pci_suspend, + .thaw = rtl_pci_resume, + .poweroff = rtl_pci_suspend, + .restore = rtl_pci_resume, +}; static struct pci_driver rtl92ce_driver = { .name = KBUILD_MODNAME, diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c index 173424756149..d7e1f0a7e48f 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c @@ -559,7 +559,7 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw, if (GET_RX_DESC_RXHT(pdesc)) rx_status->flag |= RX_FLAG_HT; - rx_status->flag |= RX_FLAG_MACTIME_START; + rx_status->flag |= RX_FLAG_MACTIME_MPDU; if (stats->decrypted) rx_status->flag |= RX_FLAG_DECRYPTED; diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c index b7e6607e6b6d..9970c2b1b199 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c @@ -297,7 +297,6 @@ static struct usb_device_id rtl8192c_usb_ids[] = { /*=== Customer ID ===*/ /****** 8188CU ********/ {RTL_USB_DEVICE(0x050d, 0x1102, rtl92cu_hal_cfg)}, /*Belkin - Edimax*/ - {RTL_USB_DEVICE(0x050d, 0x11f2, rtl92cu_hal_cfg)}, /*Belkin - ISY*/ {RTL_USB_DEVICE(0x06f8, 0xe033, rtl92cu_hal_cfg)}, /*Hercules - Edimax*/ {RTL_USB_DEVICE(0x07b8, 0x8188, rtl92cu_hal_cfg)}, /*Abocom - Abocom*/ {RTL_USB_DEVICE(0x07b8, 0x8189, rtl92cu_hal_cfg)}, /*Funai - Abocom*/ diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c index b6222eedb835..6e66f04c363f 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c @@ -334,7 +334,7 @@ bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw, rx_status->flag |= RX_FLAG_40MHZ; if (GET_RX_DESC_RX_HT(pdesc)) rx_status->flag |= RX_FLAG_HT; - rx_status->flag |= RX_FLAG_MACTIME_START; + rx_status->flag |= RX_FLAG_MACTIME_MPDU; if (stats->decrypted) rx_status->flag |= RX_FLAG_DECRYPTED; rx_status->rate_idx = rtlwifi_rate_mapping(hw, diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192de/sw.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192de/sw.c index e17f670d5c8e..480862c07f92 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192de/sw.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192de/sw.c @@ -378,7 +378,14 @@ MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n"); MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n"); MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)"); -static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume); +static const struct dev_pm_ops rtlwifi_pm_ops = { + .suspend = rtl_pci_suspend, + .resume = rtl_pci_resume, + .freeze = rtl_pci_suspend, + .thaw = rtl_pci_resume, + .poweroff = rtl_pci_suspend, + .restore = rtl_pci_resume, +}; static struct pci_driver rtl92de_driver = { .name = KBUILD_MODNAME, diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192de/trx.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192de/trx.c index f9f3861046c1..35bb9da6196a 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192de/trx.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192de/trx.c @@ -509,7 +509,7 @@ bool rtl92de_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, rx_status->flag |= RX_FLAG_40MHZ; if (GET_RX_DESC_RXHT(pdesc)) rx_status->flag |= RX_FLAG_HT; - rx_status->flag |= RX_FLAG_MACTIME_START; + rx_status->flag |= RX_FLAG_MACTIME_MPDU; if (stats->decrypted) rx_status->flag |= RX_FLAG_DECRYPTED; rx_status->rate_idx = rtlwifi_rate_mapping(hw, diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192se/def.h b/trunk/drivers/net/wireless/rtlwifi/rtl8192se/def.h index 2d255e02d795..20afec62ce05 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192se/def.h +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192se/def.h @@ -522,7 +522,8 @@ enum fwcmd_iotype { FW_CMD_IQK_ENABLE = 30, }; -/* Driver info contain PHY status +/* + * Driver info contain PHY status * and other variabel size info * PHY Status content as below */ diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192se/dm.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192se/dm.c index e551fe5f9ccd..bf79a52c8a52 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192se/dm.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192se/dm.c @@ -465,8 +465,8 @@ static void _rtl92s_dm_initial_gain_sta_beforeconnect(struct ieee80211_hw *hw) digtable->cur_igvalue = digtable->rx_gain_range_min; else - digtable->cur_igvalue = digtable->rssi_val + 10 - - digtable->back_val; + digtable->cur_igvalue = digtable->rssi_val + 10 - + digtable->back_val; if (falsealm_cnt->cnt_all > 10000) digtable->cur_igvalue = @@ -518,7 +518,7 @@ static void _rtl92s_dm_initial_gain_sta_beforeconnect(struct ieee80211_hw *hw) static void _rtl92s_dm_ctrl_initgain_bytwoport(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *dig = &rtlpriv->dm_digtable; + struct dig_t *digtable = &rtlpriv->dm_digtable; if (rtlpriv->mac80211.act_scanning) return; @@ -526,17 +526,17 @@ static void _rtl92s_dm_ctrl_initgain_bytwoport(struct ieee80211_hw *hw) /* Decide the current status and if modify initial gain or not */ if (rtlpriv->mac80211.link_state >= MAC80211_LINKED || rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC) - dig->cur_sta_cstate = DIG_STA_CONNECT; + digtable->cur_sta_cstate = DIG_STA_CONNECT; else - dig->cur_sta_cstate = DIG_STA_DISCONNECT; + digtable->cur_sta_cstate = DIG_STA_DISCONNECT; - dig->rssi_val = rtlpriv->dm.undec_sm_pwdb; + digtable->rssi_val = rtlpriv->dm.undec_sm_pwdb; /* Change dig mode to rssi */ - if (dig->cur_sta_cstate != DIG_STA_DISCONNECT) { - if (dig->dig_twoport_algorithm == + if (digtable->cur_sta_cstate != DIG_STA_DISCONNECT) { + if (digtable->dig_twoport_algorithm == DIG_TWO_PORT_ALGO_FALSE_ALARM) { - dig->dig_twoport_algorithm = DIG_TWO_PORT_ALGO_RSSI; + digtable->dig_twoport_algorithm = DIG_TWO_PORT_ALGO_RSSI; rtl92s_phy_set_fw_cmd(hw, FW_CMD_DIG_MODE_SS); } } @@ -544,7 +544,7 @@ static void _rtl92s_dm_ctrl_initgain_bytwoport(struct ieee80211_hw *hw) _rtl92s_dm_false_alarm_counter_statistics(hw); _rtl92s_dm_initial_gain_sta_beforeconnect(hw); - dig->pre_sta_cstate = dig->cur_sta_cstate; + digtable->pre_sta_cstate = digtable->cur_sta_cstate; } static void _rtl92s_dm_ctrl_initgain_byrssi(struct ieee80211_hw *hw) diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192se/hw.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192se/hw.c index 28526a7361f5..1d72779434ba 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192se/hw.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192se/hw.c @@ -1089,9 +1089,8 @@ int rtl92se_hw_init(struct ieee80211_hw *hw) return err; } -void rtl92se_set_mac_addr(struct rtl_io *io, const u8 *addr) +void rtl92se_set_mac_addr(struct rtl_io *io, const u8 * addr) { - /* This is a stub. */ } void rtl92se_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192se/hw.h b/trunk/drivers/net/wireless/rtlwifi/rtl8192se/hw.h index a8e068c76e47..1886c2644a26 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192se/hw.h +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192se/hw.h @@ -54,7 +54,7 @@ void rtl92se_disable_interrupt(struct ieee80211_hw *hw); int rtl92se_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type); void rtl92se_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid); -void rtl92se_set_mac_addr(struct rtl_io *io, const u8 *addr); +void rtl92se_set_mac_addr(struct rtl_io *io, const u8 * addr); void rtl92se_set_qos(struct ieee80211_hw *hw, int aci); void rtl92se_set_beacon_related_registers(struct ieee80211_hw *hw); void rtl92se_set_beacon_interval(struct ieee80211_hw *hw); diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192se/sw.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192se/sw.c index 45c3443fccc8..ad4b4803482d 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192se/sw.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192se/sw.c @@ -50,7 +50,8 @@ static void rtl92s_init_aspm_vars(struct ieee80211_hw *hw) /*close ASPM for AMD defaultly */ rtlpci->const_amdpci_aspm = 0; - /* ASPM PS mode. + /* + * ASPM PS mode. * 0 - Disable ASPM, * 1 - Enable ASPM without Clock Req, * 2 - Enable ASPM with Clock Req, @@ -66,7 +67,8 @@ static void rtl92s_init_aspm_vars(struct ieee80211_hw *hw) /*Setting for PCI-E bridge */ rtlpci->const_hostpci_aspm_setting = 0x02; - /* In Hw/Sw Radio Off situation. + /* + * In Hw/Sw Radio Off situation. * 0 - Default, * 1 - From ASPM setting without low Mac Pwr, * 2 - From ASPM setting with low Mac Pwr, @@ -75,7 +77,8 @@ static void rtl92s_init_aspm_vars(struct ieee80211_hw *hw) */ rtlpci->const_hwsw_rfoff_d3 = 2; - /* This setting works for those device with + /* + * This setting works for those device with * backdoor ASPM setting such as EPHY setting. * 0 - Not support ASPM, * 1 - Support ASPM, @@ -429,7 +432,14 @@ MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n"); MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n"); MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)"); -static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume); +static const struct dev_pm_ops rtlwifi_pm_ops = { + .suspend = rtl_pci_suspend, + .resume = rtl_pci_resume, + .freeze = rtl_pci_suspend, + .thaw = rtl_pci_resume, + .poweroff = rtl_pci_suspend, + .restore = rtl_pci_resume, +}; static struct pci_driver rtl92se_driver = { .name = KBUILD_MODNAME, diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192se/trx.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192se/trx.c index 0e9f6ebf078a..1ad51e711a32 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192se/trx.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192se/trx.c @@ -553,7 +553,7 @@ bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, if (stats->is_ht) rx_status->flag |= RX_FLAG_HT; - rx_status->flag |= RX_FLAG_MACTIME_START; + rx_status->flag |= RX_FLAG_MACTIME_MPDU; /* hw will set stats->decrypted true, if it finds the * frame is open data frame or mgmt frame, diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c b/trunk/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c index 18b0bc51766b..0afdc240f2fd 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c @@ -367,7 +367,14 @@ MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n"); MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n"); MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)"); -static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume); +static const struct dev_pm_ops rtlwifi_pm_ops = { + .suspend = rtl_pci_suspend, + .resume = rtl_pci_resume, + .freeze = rtl_pci_suspend, + .thaw = rtl_pci_resume, + .poweroff = rtl_pci_suspend, + .restore = rtl_pci_resume, +}; static struct pci_driver rtl8723ae_driver = { .name = KBUILD_MODNAME, diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c b/trunk/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c index 87331d826d73..9719d541e380 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c @@ -321,7 +321,7 @@ bool rtl8723ae_rx_query_desc(struct ieee80211_hw *hw, if (status->is_ht) rx_status->flag |= RX_FLAG_HT; - rx_status->flag |= RX_FLAG_MACTIME_START; + rx_status->flag |= RX_FLAG_MACTIME_MPDU; /* hw will set status->decrypted true, if it finds the * frame is open data frame or mgmt frame. diff --git a/trunk/drivers/net/wireless/ti/wl1251/rx.c b/trunk/drivers/net/wireless/ti/wl1251/rx.c index 23289d49dd31..6af35265c900 100644 --- a/trunk/drivers/net/wireless/ti/wl1251/rx.c +++ b/trunk/drivers/net/wireless/ti/wl1251/rx.c @@ -81,7 +81,7 @@ static void wl1251_rx_status(struct wl1251 *wl, status->freq = ieee80211_channel_to_frequency(desc->channel, status->band); - status->flag |= RX_FLAG_MACTIME_START; + status->flag |= RX_FLAG_MACTIME_MPDU; if (desc->flags & RX_DESC_ENCRYPTION_MASK) { status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED; diff --git a/trunk/drivers/net/wireless/ti/wlcore/main.c b/trunk/drivers/net/wireless/ti/wlcore/main.c index 4f1a05b92d2d..380cf1ff6cd1 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/main.c +++ b/trunk/drivers/net/wireless/ti/wlcore/main.c @@ -3791,7 +3791,7 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl, /* Handle HT information change */ if ((changed & BSS_CHANGED_HT) && - (bss_conf->chandef.width != NL80211_CHAN_WIDTH_20_NOHT)) { + (bss_conf->channel_type != NL80211_CHAN_NO_HT)) { ret = wl1271_acx_set_ht_information(wl, wlvif, bss_conf->ht_operation_mode); if (ret < 0) { @@ -3905,8 +3905,7 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, u32 rates; int ieoffset; wlvif->aid = bss_conf->aid; - wlvif->channel_type = - cfg80211_get_chandef_type(&bss_conf->chandef); + wlvif->channel_type = bss_conf->channel_type; wlvif->beacon_int = bss_conf->beacon_int; do_join = true; set_assoc = true; @@ -4072,7 +4071,7 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, /* Handle new association with HT. Do this after join. */ if (sta_exists) { if ((changed & BSS_CHANGED_HT) && - (bss_conf->chandef.width != NL80211_CHAN_WIDTH_20_NOHT)) { + (bss_conf->channel_type != NL80211_CHAN_NO_HT)) { ret = wl1271_acx_set_ht_capabilities(wl, &sta_ht_cap, true, @@ -4099,7 +4098,7 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, /* Handle HT information change. Done after join. */ if ((changed & BSS_CHANGED_HT) && - (bss_conf->chandef.width != NL80211_CHAN_WIDTH_20_NOHT)) { + (bss_conf->channel_type != NL80211_CHAN_NO_HT)) { ret = wl1271_acx_set_ht_information(wl, wlvif, bss_conf->ht_operation_mode); if (ret < 0) { diff --git a/trunk/drivers/nfc/pn533.c b/trunk/drivers/nfc/pn533.c index ada681b01a17..18e279d3e836 100644 --- a/trunk/drivers/nfc/pn533.c +++ b/trunk/drivers/nfc/pn533.c @@ -702,14 +702,13 @@ static void pn533_wq_cmd(struct work_struct *work) cmd = list_first_entry(&dev->cmd_queue, struct pn533_cmd, queue); - list_del(&cmd->queue); - mutex_unlock(&dev->cmd_lock); __pn533_send_cmd_frame_async(dev, cmd->out_frame, cmd->in_frame, cmd->in_frame_len, cmd->cmd_complete, cmd->arg, cmd->flags); + list_del(&cmd->queue); kfree(cmd); } @@ -1681,14 +1680,11 @@ static void pn533_deactivate_target(struct nfc_dev *nfc_dev, static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, u8 *params, int params_len) { + struct pn533_cmd_jump_dep *cmd; struct pn533_cmd_jump_dep_response *resp; struct nfc_target nfc_target; u8 target_gt_len; int rc; - struct pn533_cmd_jump_dep *cmd = (struct pn533_cmd_jump_dep *)arg; - u8 active = cmd->active; - - kfree(arg); if (params_len == -ENOENT) { nfc_dev_dbg(&dev->interface->dev, ""); @@ -1710,6 +1706,7 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, } resp = (struct pn533_cmd_jump_dep_response *) params; + cmd = (struct pn533_cmd_jump_dep *) arg; rc = resp->status & PN533_CMD_RET_MASK; if (rc != PN533_CMD_RET_SUCCESS) { nfc_dev_err(&dev->interface->dev, @@ -1739,7 +1736,7 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, if (rc == 0) rc = nfc_dep_link_is_up(dev->nfc_dev, dev->nfc_dev->targets[0].idx, - !active, NFC_RF_INITIATOR); + !cmd->active, NFC_RF_INITIATOR); return 0; } @@ -1824,8 +1821,12 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, rc = pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame, dev->in_maxlen, pn533_in_dep_link_up_complete, cmd, GFP_KERNEL); - if (rc < 0) - kfree(cmd); + if (rc) + goto out; + + +out: + kfree(cmd); return rc; } @@ -2079,12 +2080,8 @@ static int pn533_transceive(struct nfc_dev *nfc_dev, static int pn533_tm_send_complete(struct pn533 *dev, void *arg, u8 *params, int params_len) { - struct sk_buff *skb_out = arg; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); - dev_kfree_skb(skb_out); - if (params_len < 0) { nfc_dev_err(&dev->interface->dev, "Error %d when sending data", @@ -2122,7 +2119,7 @@ static int pn533_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb) rc = pn533_send_cmd_frame_async(dev, out_frame, dev->in_frame, dev->in_maxlen, pn533_tm_send_complete, - skb, GFP_KERNEL); + NULL, GFP_KERNEL); if (rc) { nfc_dev_err(&dev->interface->dev, "Error %d when trying to send data", rc); diff --git a/trunk/drivers/nfc/pn544/i2c.c b/trunk/drivers/nfc/pn544/i2c.c index 7da9071b68b6..fb430d882352 100644 --- a/trunk/drivers/nfc/pn544/i2c.c +++ b/trunk/drivers/nfc/pn544/i2c.c @@ -26,7 +26,7 @@ #include #include -#include +#include #include #include diff --git a/trunk/drivers/ssb/driver_mipscore.c b/trunk/drivers/ssb/driver_mipscore.c index 5bd05b136d22..b918ba922306 100644 --- a/trunk/drivers/ssb/driver_mipscore.c +++ b/trunk/drivers/ssb/driver_mipscore.c @@ -178,9 +178,9 @@ static void ssb_mips_serial_init(struct ssb_mipscore *mcore) { struct ssb_bus *bus = mcore->dev->bus; - if (ssb_extif_available(&bus->extif)) + if (bus->extif.dev) mcore->nr_serial_ports = ssb_extif_serial_init(&bus->extif, mcore->serial_ports); - else if (ssb_chipco_available(&bus->chipco)) + else if (bus->chipco.dev) mcore->nr_serial_ports = ssb_chipco_serial_init(&bus->chipco, mcore->serial_ports); else mcore->nr_serial_ports = 0; @@ -191,7 +191,7 @@ static void ssb_mips_flash_detect(struct ssb_mipscore *mcore) struct ssb_bus *bus = mcore->dev->bus; /* When there is no chipcommon on the bus there is 4MB flash */ - if (!ssb_chipco_available(&bus->chipco)) { + if (!bus->chipco.dev) { mcore->pflash.present = true; mcore->pflash.buswidth = 2; mcore->pflash.window = SSB_FLASH1; @@ -227,9 +227,9 @@ u32 ssb_cpu_clock(struct ssb_mipscore *mcore) if (bus->chipco.capabilities & SSB_CHIPCO_CAP_PMU) return ssb_pmu_get_cpu_clock(&bus->chipco); - if (ssb_extif_available(&bus->extif)) { + if (bus->extif.dev) { ssb_extif_get_clockcontrol(&bus->extif, &pll_type, &n, &m); - } else if (ssb_chipco_available(&bus->chipco)) { + } else if (bus->chipco.dev) { ssb_chipco_get_clockcpu(&bus->chipco, &pll_type, &n, &m); } else return 0; @@ -265,9 +265,9 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore) hz = 100000000; ns = 1000000000 / hz; - if (ssb_extif_available(&bus->extif)) + if (bus->extif.dev) ssb_extif_timing_init(&bus->extif, ns); - else if (ssb_chipco_available(&bus->chipco)) + else if (bus->chipco.dev) ssb_chipco_timing_init(&bus->chipco, ns); /* Assign IRQs to all cores on the bus, start with irq line 2, because serial usually takes 1 */ diff --git a/trunk/include/linux/bcma/bcma.h b/trunk/include/linux/bcma/bcma.h index 93b1e091b1e9..fd15d9829705 100644 --- a/trunk/include/linux/bcma/bcma.h +++ b/trunk/include/linux/bcma/bcma.h @@ -157,7 +157,6 @@ struct bcma_host_ops { /* Chip IDs of SoCs */ #define BCMA_CHIP_ID_BCM4706 0x5300 -#define BCMA_PKG_ID_BCM4706L 1 #define BCMA_CHIP_ID_BCM4716 0x4716 #define BCMA_PKG_ID_BCM4716 8 #define BCMA_PKG_ID_BCM4717 9 @@ -167,11 +166,7 @@ struct bcma_host_ops { #define BCMA_CHIP_ID_BCM4749 0x4749 #define BCMA_CHIP_ID_BCM5356 0x5356 #define BCMA_CHIP_ID_BCM5357 0x5357 -#define BCMA_PKG_ID_BCM5358 9 -#define BCMA_PKG_ID_BCM47186 10 -#define BCMA_PKG_ID_BCM5357 11 #define BCMA_CHIP_ID_BCM53572 53572 -#define BCMA_PKG_ID_BCM47188 9 struct bcma_device { struct bcma_bus *bus; diff --git a/trunk/include/linux/ieee80211.h b/trunk/include/linux/ieee80211.h index f9c5a787d350..4530d4960953 100644 --- a/trunk/include/linux/ieee80211.h +++ b/trunk/include/linux/ieee80211.h @@ -131,8 +131,6 @@ #define IEEE80211_MAX_MESH_ID_LEN 32 -#define IEEE80211_NUM_TIDS 16 - #define IEEE80211_QOS_CTL_LEN 2 /* 1d tag mask */ #define IEEE80211_QOS_CTL_TAG1D_MASK 0x0007 @@ -667,21 +665,6 @@ struct ieee80211_meshconf_ie { u8 meshconf_cap; } __attribute__ ((packed)); -/** - * enum mesh_config_capab_flags - Mesh Configuration IE capability field flags - * - * @IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS: STA is willing to establish - * additional mesh peerings with other mesh STAs - * @IEEE80211_MESHCONF_CAPAB_FORWARDING: the STA forwards MSDUs - * @IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING: TBTT adjustment procedure - * is ongoing - */ -enum mesh_config_capab_flags { - IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS = 0x01, - IEEE80211_MESHCONF_CAPAB_FORWARDING = 0x08, - IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING = 0x20, -}; - /** * struct ieee80211_rann_ie * @@ -1163,13 +1146,11 @@ struct ieee80211_ht_operation { * STA can receive. Rate expressed in units of 1 Mbps. * If this field is 0 this value should not be used to * consider the highest RX data rate supported. - * The top 3 bits of this field are reserved. * @tx_mcs_map: TX MCS map 2 bits for each stream, total 8 streams * @tx_highest: Indicates highest long GI VHT PPDU data rate * STA can transmit. Rate expressed in units of 1 Mbps. * If this field is 0 this value should not be used to * consider the highest TX data rate supported. - * The top 3 bits of this field are reserved. */ struct ieee80211_vht_mcs_info { __le16 rx_mcs_map; @@ -1178,27 +1159,6 @@ struct ieee80211_vht_mcs_info { __le16 tx_highest; } __packed; -/** - * enum ieee80211_vht_mcs_support - VHT MCS support definitions - * @IEEE80211_VHT_MCS_SUPPORT_0_7: MCSes 0-7 are supported for the - * number of streams - * @IEEE80211_VHT_MCS_SUPPORT_0_8: MCSes 0-8 are supported - * @IEEE80211_VHT_MCS_SUPPORT_0_9: MCSes 0-9 are supported - * @IEEE80211_VHT_MCS_NOT_SUPPORTED: This number of streams isn't supported - * - * These definitions are used in each 2-bit subfield of the @rx_mcs_map - * and @tx_mcs_map fields of &struct ieee80211_vht_mcs_info, which are - * both split into 8 subfields by number of streams. These values indicate - * which MCSes are supported for the number of streams the value appears - * for. - */ -enum ieee80211_vht_mcs_support { - IEEE80211_VHT_MCS_SUPPORT_0_7 = 0, - IEEE80211_VHT_MCS_SUPPORT_0_8 = 1, - IEEE80211_VHT_MCS_SUPPORT_0_9 = 2, - IEEE80211_VHT_MCS_NOT_SUPPORTED = 3, -}; - /** * struct ieee80211_vht_cap - VHT capabilities * diff --git a/trunk/include/linux/nfc/pn544.h b/trunk/include/linux/nfc/pn544.h new file mode 100644 index 000000000000..9890bbaf4328 --- /dev/null +++ b/trunk/include/linux/nfc/pn544.h @@ -0,0 +1,104 @@ +/* + * Driver include for the PN544 NFC chip. + * + * Copyright (C) Nokia Corporation + * + * Author: Jari Vanhala + * Contact: Matti Aaltoenn + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _PN544_H_ +#define _PN544_H_ + +#include + +#define PN544_DRIVER_NAME "pn544" +#define PN544_MAXWINDOW_SIZE 7 +#define PN544_WINDOW_SIZE 4 +#define PN544_RETRIES 10 +#define PN544_MAX_I2C_TRANSFER 0x0400 +#define PN544_MSG_MAX_SIZE 0x21 /* at normal HCI mode */ + +/* ioctl */ +#define PN544_CHAR_BASE 'P' +#define PN544_IOR(num, dtype) _IOR(PN544_CHAR_BASE, num, dtype) +#define PN544_IOW(num, dtype) _IOW(PN544_CHAR_BASE, num, dtype) +#define PN544_GET_FW_MODE PN544_IOW(1, unsigned int) +#define PN544_SET_FW_MODE PN544_IOW(2, unsigned int) +#define PN544_GET_DEBUG PN544_IOW(3, unsigned int) +#define PN544_SET_DEBUG PN544_IOW(4, unsigned int) + +/* Timing restrictions (ms) */ +#define PN544_RESETVEN_TIME 30 /* 7 */ +#define PN544_PVDDVEN_TIME 0 +#define PN544_VBATVEN_TIME 0 +#define PN544_GPIO4VEN_TIME 0 +#define PN544_WAKEUP_ACK 5 +#define PN544_WAKEUP_GUARD (PN544_WAKEUP_ACK + 1) +#define PN544_INACTIVITY_TIME 1000 +#define PN544_INTERFRAME_DELAY 200 /* us */ +#define PN544_BAUDRATE_CHANGE 150 /* us */ + +/* Debug bits */ +#define PN544_DEBUG_BUF 0x01 +#define PN544_DEBUG_READ 0x02 +#define PN544_DEBUG_WRITE 0x04 +#define PN544_DEBUG_IRQ 0x08 +#define PN544_DEBUG_CALLS 0x10 +#define PN544_DEBUG_MODE 0x20 + +/* Normal (HCI) mode */ +#define PN544_LLC_HCI_OVERHEAD 3 /* header + crc (to length) */ +#define PN544_LLC_MIN_SIZE (1 + PN544_LLC_HCI_OVERHEAD) /* length + */ +#define PN544_LLC_MAX_DATA (PN544_MSG_MAX_SIZE - 2) +#define PN544_LLC_MAX_HCI_SIZE (PN544_LLC_MAX_DATA - 2) + +struct pn544_llc_packet { + unsigned char length; /* of rest of packet */ + unsigned char header; + unsigned char data[PN544_LLC_MAX_DATA]; /* includes crc-ccitt */ +}; + +/* Firmware upgrade mode */ +#define PN544_FW_HEADER_SIZE 3 +/* max fw transfer is 1024bytes, but I2C limits it to 0xC0 */ +#define PN544_MAX_FW_DATA (PN544_MAX_I2C_TRANSFER - PN544_FW_HEADER_SIZE) + +struct pn544_fw_packet { + unsigned char command; /* status in answer */ + unsigned char length[2]; /* big-endian order (msf) */ + unsigned char data[PN544_MAX_FW_DATA]; +}; + +#ifdef __KERNEL__ +enum { + NFC_GPIO_ENABLE, + NFC_GPIO_FW_RESET, + NFC_GPIO_IRQ +}; + +/* board config */ +struct pn544_nfc_platform_data { + int (*request_resources) (struct i2c_client *client); + void (*free_resources) (void); + void (*enable) (int fw); + int (*test) (void); + void (*disable) (void); + int (*get_gpio)(int type); +}; +#endif /* __KERNEL__ */ + +#endif /* _PN544_H_ */ diff --git a/trunk/include/linux/platform_data/pn544.h b/trunk/include/linux/platform_data/pn544.h deleted file mode 100644 index 713bfd703342..000000000000 --- a/trunk/include/linux/platform_data/pn544.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Driver include for the PN544 NFC chip. - * - * Copyright (C) Nokia Corporation - * - * Author: Jari Vanhala - * Contact: Matti Aaltoenn - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _PN544_H_ -#define _PN544_H_ - -#include - -enum { - NFC_GPIO_ENABLE, - NFC_GPIO_FW_RESET, - NFC_GPIO_IRQ -}; - -/* board config */ -struct pn544_nfc_platform_data { - int (*request_resources) (struct i2c_client *client); - void (*free_resources) (void); - void (*enable) (int fw); - int (*test) (void); - void (*disable) (void); - int (*get_gpio)(int type); -}; - -#endif /* _PN544_H_ */ diff --git a/trunk/include/linux/ssb/ssb_driver_extif.h b/trunk/include/linux/ssb/ssb_driver_extif.h index 2604efa7dc4d..91161f0aa22b 100644 --- a/trunk/include/linux/ssb/ssb_driver_extif.h +++ b/trunk/include/linux/ssb/ssb_driver_extif.h @@ -204,53 +204,11 @@ void ssb_extif_get_clockcontrol(struct ssb_extif *extif, { } -static inline -void ssb_extif_timing_init(struct ssb_extif *extif, unsigned long ns) -{ -} - static inline void ssb_extif_watchdog_timer_set(struct ssb_extif *extif, u32 ticks) { } -static inline u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask) -{ - return 0; -} - -static inline u32 ssb_extif_gpio_out(struct ssb_extif *extif, u32 mask, - u32 value) -{ - return 0; -} - -static inline u32 ssb_extif_gpio_outen(struct ssb_extif *extif, u32 mask, - u32 value) -{ - return 0; -} - -static inline u32 ssb_extif_gpio_polarity(struct ssb_extif *extif, u32 mask, - u32 value) -{ - return 0; -} - -static inline u32 ssb_extif_gpio_intmask(struct ssb_extif *extif, u32 mask, - u32 value) -{ - return 0; -} - -#ifdef CONFIG_SSB_SERIAL -static inline int ssb_extif_serial_init(struct ssb_extif *extif, - struct ssb_serial_port *ports) -{ - return 0; -} -#endif /* CONFIG_SSB_SERIAL */ - #endif /* CONFIG_SSB_DRIVER_EXTIF */ #endif /* LINUX_SSB_EXTIFCORE_H_ */ diff --git a/trunk/include/net/cfg80211.h b/trunk/include/net/cfg80211.h index e78db2cf3d1b..81d725038f97 100644 --- a/trunk/include/net/cfg80211.h +++ b/trunk/include/net/cfg80211.h @@ -305,88 +305,6 @@ struct key_params { u32 cipher; }; -/** - * struct cfg80211_chan_def - channel definition - * @chan: the (control) channel - * @width: channel width - * @center_freq1: center frequency of first segment - * @center_freq2: center frequency of second segment - * (only with 80+80 MHz) - */ -struct cfg80211_chan_def { - struct ieee80211_channel *chan; - enum nl80211_chan_width width; - u32 center_freq1; - u32 center_freq2; -}; - -/** - * cfg80211_get_chandef_type - return old channel type from chandef - * @chandef: the channel definition - * - * Returns the old channel type (NOHT, HT20, HT40+/-) from a given - * chandef, which must have a bandwidth allowing this conversion. - */ -static inline enum nl80211_channel_type -cfg80211_get_chandef_type(const struct cfg80211_chan_def *chandef) -{ - switch (chandef->width) { - case NL80211_CHAN_WIDTH_20_NOHT: - return NL80211_CHAN_NO_HT; - case NL80211_CHAN_WIDTH_20: - return NL80211_CHAN_HT20; - case NL80211_CHAN_WIDTH_40: - if (chandef->center_freq1 > chandef->chan->center_freq) - return NL80211_CHAN_HT40PLUS; - return NL80211_CHAN_HT40MINUS; - default: - WARN_ON(1); - return NL80211_CHAN_NO_HT; - } -} - -/** - * cfg80211_chandef_create - create channel definition using channel type - * @chandef: the channel definition struct to fill - * @channel: the control channel - * @chantype: the channel type - * - * Given a channel type, create a channel definition. - */ -void cfg80211_chandef_create(struct cfg80211_chan_def *chandef, - struct ieee80211_channel *channel, - enum nl80211_channel_type chantype); - -/** - * cfg80211_chandef_identical - check if two channel definitions are identical - * @chandef1: first channel definition - * @chandef2: second channel definition - * - * Returns %true if the channels defined by the channel definitions are - * identical, %false otherwise. - */ -static inline bool -cfg80211_chandef_identical(const struct cfg80211_chan_def *chandef1, - const struct cfg80211_chan_def *chandef2) -{ - return (chandef1->chan == chandef2->chan && - chandef1->width == chandef2->width && - chandef1->center_freq1 == chandef2->center_freq1 && - chandef1->center_freq2 == chandef2->center_freq2); -} - -/** - * cfg80211_chandef_compatible - check if two channel definitions are compatible - * @chandef1: first channel definition - * @chandef2: second channel definition - * - * Returns %NULL if the given channel definitions are incompatible, - * chandef1 or chandef2 otherwise. - */ -const struct cfg80211_chan_def * -cfg80211_chandef_compatible(const struct cfg80211_chan_def *chandef1, - const struct cfg80211_chan_def *chandef2); - /** * enum survey_info_flags - survey information flags * @@ -508,7 +426,8 @@ struct cfg80211_beacon_data { * * Used to configure an AP interface. * - * @chandef: defines the channel to use + * @channel: the channel to start the AP on + * @channel_type: the channel type to use * @beacon: beacon data * @beacon_interval: beacon interval * @dtim_period: DTIM period @@ -522,7 +441,8 @@ struct cfg80211_beacon_data { * @inactivity_timeout: time in seconds to determine station's inactivity. */ struct cfg80211_ap_settings { - struct cfg80211_chan_def chandef; + struct ieee80211_channel *channel; + enum nl80211_channel_type channel_type; struct cfg80211_beacon_data beacon; @@ -662,24 +582,16 @@ enum station_info_flags { * Used by the driver to indicate the specific rate transmission * type for 802.11n transmissions. * - * @RATE_INFO_FLAGS_MCS: mcs field filled with HT MCS - * @RATE_INFO_FLAGS_VHT_MCS: mcs field filled with VHT MCS - * @RATE_INFO_FLAGS_40_MHZ_WIDTH: 40 MHz width transmission - * @RATE_INFO_FLAGS_80_MHZ_WIDTH: 80 MHz width transmission - * @RATE_INFO_FLAGS_80P80_MHZ_WIDTH: 80+80 MHz width transmission - * @RATE_INFO_FLAGS_160_MHZ_WIDTH: 160 MHz width transmission + * @RATE_INFO_FLAGS_MCS: @tx_bitrate_mcs filled + * @RATE_INFO_FLAGS_40_MHZ_WIDTH: 40 Mhz width transmission * @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval - * @RATE_INFO_FLAGS_60G: 60GHz MCS + * @RATE_INFO_FLAGS_60G: 60gHz MCS */ enum rate_info_flags { - RATE_INFO_FLAGS_MCS = BIT(0), - RATE_INFO_FLAGS_VHT_MCS = BIT(1), - RATE_INFO_FLAGS_40_MHZ_WIDTH = BIT(2), - RATE_INFO_FLAGS_80_MHZ_WIDTH = BIT(3), - RATE_INFO_FLAGS_80P80_MHZ_WIDTH = BIT(4), - RATE_INFO_FLAGS_160_MHZ_WIDTH = BIT(5), - RATE_INFO_FLAGS_SHORT_GI = BIT(6), - RATE_INFO_FLAGS_60G = BIT(7), + RATE_INFO_FLAGS_MCS = 1<<0, + RATE_INFO_FLAGS_40_MHZ_WIDTH = 1<<1, + RATE_INFO_FLAGS_SHORT_GI = 1<<2, + RATE_INFO_FLAGS_60G = 1<<3, }; /** @@ -690,13 +602,11 @@ enum rate_info_flags { * @flags: bitflag of flags from &enum rate_info_flags * @mcs: mcs index if struct describes a 802.11n bitrate * @legacy: bitrate in 100kbit/s for 802.11abg - * @nss: number of streams (VHT only) */ struct rate_info { u8 flags; u8 mcs; u16 legacy; - u8 nss; }; /** @@ -999,7 +909,8 @@ struct mesh_config { /** * struct mesh_setup - 802.11s mesh setup configuration - * @chandef: defines the channel to use + * @channel: the channel to start the mesh network on + * @channel_type: the channel type to use * @mesh_id: the mesh ID * @mesh_id_len: length of the mesh ID, at least 1 and at most 32 bytes * @sync_method: which synchronization method to use @@ -1014,7 +925,8 @@ struct mesh_config { * These parameters are fixed when the mesh is created. */ struct mesh_setup { - struct cfg80211_chan_def chandef; + struct ieee80211_channel *channel; + enum nl80211_channel_type channel_type; const u8 *mesh_id; u8 mesh_id_len; u8 sync_method; @@ -1354,7 +1266,8 @@ struct cfg80211_disassoc_request { * @ssid_len: The length of the SSID, will always be non-zero. * @bssid: Fixed BSSID requested, maybe be %NULL, if set do not * search for IBSSs with a different BSSID. - * @chandef: defines the channel to use if no other IBSS to join can be found + * @channel: The channel to use if no IBSS can be found to join. + * @channel_type: channel type (HT mode) * @channel_fixed: The channel should be fixed -- do not search for * IBSSs to join on other channels. * @ie: information element(s) to include in the beacon @@ -1372,7 +1285,8 @@ struct cfg80211_disassoc_request { struct cfg80211_ibss_params { u8 *ssid; u8 *bssid; - struct cfg80211_chan_def chandef; + struct ieee80211_channel *channel; + enum nl80211_channel_type channel_type; u8 *ie; u8 ssid_len, ie_len; u16 beacon_interval; @@ -1814,7 +1728,8 @@ struct cfg80211_ops { struct ieee80211_channel *chan); int (*set_monitor_channel)(struct wiphy *wiphy, - struct cfg80211_chan_def *chandef); + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type); int (*scan)(struct wiphy *wiphy, struct cfg80211_scan_request *request); @@ -1876,6 +1791,7 @@ struct cfg80211_ops { int (*remain_on_channel)(struct wiphy *wiphy, struct wireless_dev *wdev, struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, unsigned int duration, u64 *cookie); int (*cancel_remain_on_channel)(struct wiphy *wiphy, @@ -1884,8 +1800,10 @@ struct cfg80211_ops { int (*mgmt_tx)(struct wiphy *wiphy, struct wireless_dev *wdev, struct ieee80211_channel *chan, bool offchan, - unsigned int wait, const u8 *buf, size_t len, - bool no_cck, bool dont_wait_for_ack, u64 *cookie); + enum nl80211_channel_type channel_type, + bool channel_type_valid, unsigned int wait, + const u8 *buf, size_t len, bool no_cck, + bool dont_wait_for_ack, u64 *cookie); int (*mgmt_tx_cancel_wait)(struct wiphy *wiphy, struct wireless_dev *wdev, u64 cookie); @@ -1940,9 +1858,10 @@ struct cfg80211_ops { void (*get_et_strings)(struct wiphy *wiphy, struct net_device *dev, u32 sset, u8 *data); - int (*get_channel)(struct wiphy *wiphy, + struct ieee80211_channel * + (*get_channel)(struct wiphy *wiphy, struct wireless_dev *wdev, - struct cfg80211_chan_def *chandef); + enum nl80211_channel_type *type); int (*start_p2p_device)(struct wiphy *wiphy, struct wireless_dev *wdev); @@ -2550,7 +2469,8 @@ struct wireless_dev { spinlock_t event_lock; struct cfg80211_internal_bss *current_bss; /* associated / joined */ - struct cfg80211_chan_def preset_chandef; + struct ieee80211_channel *preset_chan; + enum nl80211_channel_type preset_chantype; /* for AP and mesh channel tracking */ struct ieee80211_channel *channel; @@ -3430,12 +3350,14 @@ void cfg80211_disconnected(struct net_device *dev, u16 reason, * @wdev: wireless device * @cookie: the request cookie * @chan: The current channel (from remain_on_channel request) + * @channel_type: Channel type * @duration: Duration in milliseconds that the driver intents to remain on the * channel * @gfp: allocation flags */ void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie, struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, unsigned int duration, gfp_t gfp); /** @@ -3443,10 +3365,12 @@ void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie, * @wdev: wireless device * @cookie: the request cookie * @chan: The current channel (from remain_on_channel request) + * @channel_type: Channel type * @gfp: allocation flags */ void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie, struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, gfp_t gfp); @@ -3646,44 +3570,28 @@ void cfg80211_report_obss_beacon(struct wiphy *wiphy, int freq, int sig_dbm); /** - * cfg80211_reg_can_beacon - check if beaconing is allowed + * cfg80211_can_beacon_sec_chan - test if ht40 on extension channel can be used * @wiphy: the wiphy - * @chandef: the channel definition + * @chan: main channel + * @channel_type: HT mode * * This function returns true if there is no secondary channel or the secondary - * channel(s) can be used for beaconing (i.e. is not a radar channel etc.) + * channel can be used for beaconing (i.e. is not a radar channel etc.) */ -bool cfg80211_reg_can_beacon(struct wiphy *wiphy, - struct cfg80211_chan_def *chandef); +bool cfg80211_can_beacon_sec_chan(struct wiphy *wiphy, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type); /* * cfg80211_ch_switch_notify - update wdev channel and notify userspace * @dev: the device which switched channels - * @chandef: the new channel definition + * @freq: new channel frequency (in MHz) + * @type: channel type * * Acquires wdev_lock, so must only be called from sleepable driver context! */ -void cfg80211_ch_switch_notify(struct net_device *dev, - struct cfg80211_chan_def *chandef); - -/* - * cfg80211_tdls_oper_request - request userspace to perform TDLS operation - * @dev: the device on which the operation is requested - * @peer: the MAC address of the peer device - * @oper: the requested TDLS operation (NL80211_TDLS_SETUP or - * NL80211_TDLS_TEARDOWN) - * @reason_code: the reason code for teardown request - * @gfp: allocation flags - * - * This function is used to request userspace to perform TDLS operation that - * requires knowledge of keys, i.e., link setup or teardown when the AP - * connection uses encryption. This is optional mechanism for the driver to use - * if it can automatically determine when a TDLS link could be useful (e.g., - * based on traffic and signal strength for a peer). - */ -void cfg80211_tdls_oper_request(struct net_device *dev, const u8 *peer, - enum nl80211_tdls_operation oper, - u16 reason_code, gfp_t gfp); +void cfg80211_ch_switch_notify(struct net_device *dev, int freq, + enum nl80211_channel_type type); /* * cfg80211_calculate_bitrate - calculate actual bitrate (in 100Kbps units) @@ -3725,9 +3633,8 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev); * the data is malformed or the attribute can't be found (respectively), * or the length of the found attribute (which can be zero). */ -int cfg80211_get_p2p_attr(const u8 *ies, unsigned int len, - enum ieee80211_p2p_attr_id attr, - u8 *buf, unsigned int bufsize); +unsigned int cfg80211_get_p2p_attr(const u8 *ies, unsigned int len, + u8 attr, u8 *buf, unsigned int bufsize); /* Logging, debugging and troubleshooting/diagnostic helpers. */ diff --git a/trunk/include/net/mac80211.h b/trunk/include/net/mac80211.h index db7680acd0da..a789dd1d4c10 100644 --- a/trunk/include/net/mac80211.h +++ b/trunk/include/net/mac80211.h @@ -145,11 +145,11 @@ struct ieee80211_low_level_stats { /** * enum ieee80211_chanctx_change - change flag for channel context - * @IEEE80211_CHANCTX_CHANGE_WIDTH: The channel width changed + * @IEEE80211_CHANCTX_CHANGE_CHANNEL_TYPE: The channel type was changed * @IEEE80211_CHANCTX_CHANGE_RX_CHAINS: The number of RX chains changed */ enum ieee80211_chanctx_change { - IEEE80211_CHANCTX_CHANGE_WIDTH = BIT(0), + IEEE80211_CHANCTX_CHANGE_CHANNEL_TYPE = BIT(0), IEEE80211_CHANCTX_CHANGE_RX_CHAINS = BIT(1), }; @@ -159,7 +159,8 @@ enum ieee80211_chanctx_change { * This is the driver-visible part. The ieee80211_chanctx * that contains it is visible in mac80211 only. * - * @def: the channel definition + * @channel: the channel to tune to + * @channel_type: the channel (HT) type * @rx_chains_static: The number of RX chains that must always be * active on the channel to receive MIMO transmissions * @rx_chains_dynamic: The number of RX chains that must be enabled @@ -169,7 +170,8 @@ enum ieee80211_chanctx_change { * sizeof(void *), size is determined in hw information. */ struct ieee80211_chanctx_conf { - struct cfg80211_chan_def def; + struct ieee80211_channel *channel; + enum nl80211_channel_type channel_type; u8 rx_chains_static, rx_chains_dynamic; @@ -286,8 +288,9 @@ enum ieee80211_rssi_event { * @mcast_rate: per-band multicast rate index + 1 (0: disabled) * @bssid: The BSSID for this BSS * @enable_beacon: whether beaconing should be enabled or not - * @chandef: Channel definition for this BSS -- the hardware might be - * configured a higher bandwidth than this BSS uses, for example. + * @channel_type: Channel type for this BSS -- the hardware might be + * configured for HT40+ while this BSS only uses no-HT, for + * example. * @ht_operation_mode: HT operation mode like in &struct ieee80211_ht_operation. * This field is only valid when the channel type is one of the HT types. * @cqm_rssi_thold: Connection quality monitor RSSI threshold, a zero value @@ -336,7 +339,7 @@ struct ieee80211_bss_conf { u16 ht_operation_mode; s32 cqm_rssi_thold; u32 cqm_rssi_hyst; - struct cfg80211_chan_def chandef; + enum nl80211_channel_type channel_type; __be32 arp_addr_list[IEEE80211_BSS_ARP_ADDR_LIST_LEN]; u8 arp_addr_cnt; bool arp_filter_enabled; @@ -499,14 +502,9 @@ enum mac80211_tx_control_flags { * This is set if the current BSS requires ERP protection. * @IEEE80211_TX_RC_USE_SHORT_PREAMBLE: Use short preamble. * @IEEE80211_TX_RC_MCS: HT rate. - * @IEEE80211_TX_RC_VHT_MCS: VHT MCS rate, in this case the idx field is split - * into a higher 4 bits (Nss) and lower 4 bits (MCS number) * @IEEE80211_TX_RC_GREEN_FIELD: Indicates whether this rate should be used in * Greenfield mode. * @IEEE80211_TX_RC_40_MHZ_WIDTH: Indicates if the Channel Width should be 40 MHz. - * @IEEE80211_TX_RC_80_MHZ_WIDTH: Indicates 80 MHz transmission - * @IEEE80211_TX_RC_160_MHZ_WIDTH: Indicates 160 MHz transmission - * (80+80 isn't supported yet) * @IEEE80211_TX_RC_DUP_DATA: The frame should be transmitted on both of the * adjacent 20 MHz channels, if the current channel type is * NL80211_CHAN_HT40MINUS or NL80211_CHAN_HT40PLUS. @@ -517,15 +515,12 @@ enum mac80211_rate_control_flags { IEEE80211_TX_RC_USE_CTS_PROTECT = BIT(1), IEEE80211_TX_RC_USE_SHORT_PREAMBLE = BIT(2), - /* rate index is an HT/VHT MCS instead of an index */ + /* rate index is an MCS rate number instead of an index */ IEEE80211_TX_RC_MCS = BIT(3), IEEE80211_TX_RC_GREEN_FIELD = BIT(4), IEEE80211_TX_RC_40_MHZ_WIDTH = BIT(5), IEEE80211_TX_RC_DUP_DATA = BIT(6), IEEE80211_TX_RC_SHORT_GI = BIT(7), - IEEE80211_TX_RC_VHT_MCS = BIT(8), - IEEE80211_TX_RC_80_MHZ_WIDTH = BIT(9), - IEEE80211_TX_RC_160_MHZ_WIDTH = BIT(10), }; @@ -568,32 +563,10 @@ enum mac80211_rate_control_flags { */ struct ieee80211_tx_rate { s8 idx; - u16 count:5, - flags:11; + u8 count; + u8 flags; } __packed; -#define IEEE80211_MAX_TX_RETRY 31 - -static inline void ieee80211_rate_set_vht(struct ieee80211_tx_rate *rate, - u8 mcs, u8 nss) -{ - WARN_ON(mcs & ~0xF); - WARN_ON(nss & ~0x7); - rate->idx = (nss << 4) | mcs; -} - -static inline u8 -ieee80211_rate_get_vht_mcs(const struct ieee80211_tx_rate *rate) -{ - return rate->idx & 0xF; -} - -static inline u8 -ieee80211_rate_get_vht_nss(const struct ieee80211_tx_rate *rate) -{ - return rate->idx >> 4; -} - /** * struct ieee80211_tx_info - skb transmit information * @@ -738,20 +711,13 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info) * the frame. * @RX_FLAG_FAILED_PLCP_CRC: Set this flag if the PCLP check failed on * the frame. - * @RX_FLAG_MACTIME_START: The timestamp passed in the RX status (@mactime + * @RX_FLAG_MACTIME_MPDU: The timestamp passed in the RX status (@mactime * field) is valid and contains the time the first symbol of the MPDU * was received. This is useful in monitor mode and for proper IBSS * merging. - * @RX_FLAG_MACTIME_END: The timestamp passed in the RX status (@mactime - * field) is valid and contains the time the last symbol of the MPDU - * (including FCS) was received. * @RX_FLAG_SHORTPRE: Short preamble was used for this frame * @RX_FLAG_HT: HT MCS was used and rate_idx is MCS index - * @RX_FLAG_VHT: VHT MCS was used and rate_index is MCS index * @RX_FLAG_40MHZ: HT40 (40 MHz) was used - * @RX_FLAG_80MHZ: 80 MHz was used - * @RX_FLAG_80P80MHZ: 80+80 MHz was used - * @RX_FLAG_160MHZ: 160 MHz was used * @RX_FLAG_SHORT_GI: Short guard interval was used * @RX_FLAG_NO_SIGNAL_VAL: The signal strength value is not present. * Valid only for data frames (mainly A-MPDU) @@ -779,7 +745,7 @@ enum mac80211_rx_flags { RX_FLAG_IV_STRIPPED = BIT(4), RX_FLAG_FAILED_FCS_CRC = BIT(5), RX_FLAG_FAILED_PLCP_CRC = BIT(6), - RX_FLAG_MACTIME_START = BIT(7), + RX_FLAG_MACTIME_MPDU = BIT(7), RX_FLAG_SHORTPRE = BIT(8), RX_FLAG_HT = BIT(9), RX_FLAG_40MHZ = BIT(10), @@ -793,11 +759,6 @@ enum mac80211_rx_flags { RX_FLAG_AMPDU_IS_LAST = BIT(18), RX_FLAG_AMPDU_DELIM_CRC_ERROR = BIT(19), RX_FLAG_AMPDU_DELIM_CRC_KNOWN = BIT(20), - RX_FLAG_MACTIME_END = BIT(21), - RX_FLAG_VHT = BIT(22), - RX_FLAG_80MHZ = BIT(23), - RX_FLAG_80P80MHZ = BIT(24), - RX_FLAG_160MHZ = BIT(25), }; /** @@ -818,39 +779,25 @@ enum mac80211_rx_flags { * @IEEE80211_HW_SIGNAL_* * @antenna: antenna used * @rate_idx: index of data rate into band's supported rates or MCS index if - * HT or VHT is used (%RX_FLAG_HT/%RX_FLAG_VHT) - * @vht_nss: number of streams (VHT only) + * HT rates are use (RX_FLAG_HT) * @flag: %RX_FLAG_* * @rx_flags: internal RX flags for mac80211 * @ampdu_reference: A-MPDU reference number, must be a different value for * each A-MPDU but the same for each subframe within one A-MPDU * @ampdu_delimiter_crc: A-MPDU delimiter CRC - * @vendor_radiotap_bitmap: radiotap vendor namespace presence bitmap - * @vendor_radiotap_len: radiotap vendor namespace length - * @vendor_radiotap_align: radiotap vendor namespace alignment. Note - * that the actual data must be at the start of the SKB data - * already. - * @vendor_radiotap_oui: radiotap vendor namespace OUI - * @vendor_radiotap_subns: radiotap vendor sub namespace */ struct ieee80211_rx_status { u64 mactime; u32 device_timestamp; u32 ampdu_reference; u32 flag; - u32 vendor_radiotap_bitmap; - u16 vendor_radiotap_len; u16 freq; u8 rate_idx; - u8 vht_nss; u8 rx_flags; u8 band; u8 antenna; s8 signal; u8 ampdu_delimiter_crc; - u8 vendor_radiotap_align; - u8 vendor_radiotap_oui[3]; - u8 vendor_radiotap_subns; }; /** @@ -2245,14 +2192,6 @@ enum ieee80211_rate_control_changed { * @sta_remove: Notifies low level driver about removal of an associated * station, AP, IBSS/WDS/mesh peer etc. This callback can sleep. * - * @sta_add_debugfs: Drivers can use this callback to add debugfs files - * when a station is added to mac80211's station list. This callback - * and @sta_remove_debugfs should be within a CONFIG_MAC80211_DEBUGFS - * conditional. This callback can sleep. - * - * @sta_remove_debugfs: Remove the debugfs files which were added using - * @sta_add_debugfs. This callback can sleep. - * * @sta_notify: Notifies low level driver about power state transition of an * associated station, AP, IBSS/WDS/mesh peer etc. For a VIF operating * in AP mode, this callback will not be called when the flag @@ -2534,16 +2473,6 @@ struct ieee80211_ops { struct ieee80211_sta *sta); int (*sta_remove)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta); -#ifdef CONFIG_MAC80211_DEBUGFS - void (*sta_add_debugfs)(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct dentry *dir); - void (*sta_remove_debugfs)(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct dentry *dir); -#endif void (*sta_notify)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum sta_notify_cmd, struct ieee80211_sta *sta); int (*sta_state)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, @@ -2585,8 +2514,8 @@ struct ieee80211_ops { int (*get_antenna)(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant); int (*remain_on_channel)(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, int duration); int (*cancel_remain_on_channel)(struct ieee80211_hw *hw); int (*set_ringparam)(struct ieee80211_hw *hw, u32 tx, u32 rx); diff --git a/trunk/include/net/nfc/hci.h b/trunk/include/net/nfc/hci.h index 671953e11575..639f50af42df 100644 --- a/trunk/include/net/nfc/hci.h +++ b/trunk/include/net/nfc/hci.h @@ -149,8 +149,6 @@ void *nfc_hci_get_clientdata(struct nfc_hci_dev *hdev); void nfc_hci_driver_failure(struct nfc_hci_dev *hdev, int err); -int nfc_hci_result_to_errno(u8 result); - /* Host IDs */ #define NFC_HCI_HOST_CONTROLLER_ID 0x00 #define NFC_HCI_TERMINAL_HOST_ID 0x01 @@ -237,6 +235,5 @@ int nfc_hci_send_response(struct nfc_hci_dev *hdev, u8 gate, u8 response, int nfc_hci_send_event(struct nfc_hci_dev *hdev, u8 gate, u8 event, const u8 *param, size_t param_len); int nfc_hci_target_discovered(struct nfc_hci_dev *hdev, u8 gate); -u32 nfc_hci_sak_to_protocol(u8 sak); #endif /* __NET_HCI_H */ diff --git a/trunk/include/uapi/linux/nl80211.h b/trunk/include/uapi/linux/nl80211.h index 33a417481ad8..cbd2d6bb907a 100644 --- a/trunk/include/uapi/linux/nl80211.h +++ b/trunk/include/uapi/linux/nl80211.h @@ -118,9 +118,8 @@ * to get a list of all present wiphys. * @NL80211_CMD_SET_WIPHY: set wiphy parameters, needs %NL80211_ATTR_WIPHY or * %NL80211_ATTR_IFINDEX; can be used to set %NL80211_ATTR_WIPHY_NAME, - * %NL80211_ATTR_WIPHY_TXQ_PARAMS, %NL80211_ATTR_WIPHY_FREQ (and the - * attributes determining the channel width; this is used for setting - * monitor mode channel), %NL80211_ATTR_WIPHY_RETRY_SHORT, + * %NL80211_ATTR_WIPHY_TXQ_PARAMS, %NL80211_ATTR_WIPHY_FREQ, + * %NL80211_ATTR_WIPHY_CHANNEL_TYPE, %NL80211_ATTR_WIPHY_RETRY_SHORT, * %NL80211_ATTR_WIPHY_RETRY_LONG, %NL80211_ATTR_WIPHY_FRAG_THRESHOLD, * and/or %NL80211_ATTR_WIPHY_RTS_THRESHOLD. * However, for setting the channel, see %NL80211_CMD_SET_CHANNEL @@ -172,7 +171,7 @@ * %NL80211_ATTR_AKM_SUITES, %NL80211_ATTR_PRIVACY, * %NL80211_ATTR_AUTH_TYPE and %NL80211_ATTR_INACTIVITY_TIMEOUT. * The channel to use can be set on the interface or be given using the - * %NL80211_ATTR_WIPHY_FREQ and the attributes determining channel width. + * %NL80211_ATTR_WIPHY_FREQ and %NL80211_ATTR_WIPHY_CHANNEL_TYPE attrs. * @NL80211_CMD_NEW_BEACON: old alias for %NL80211_CMD_START_AP * @NL80211_CMD_STOP_AP: Stop AP operation on the given interface * @NL80211_CMD_DEL_BEACON: old alias for %NL80211_CMD_STOP_AP @@ -402,7 +401,8 @@ * a response while being associated to an AP on another channel. * %NL80211_ATTR_IFINDEX is used to specify which interface (and thus * radio) is used. %NL80211_ATTR_WIPHY_FREQ is used to specify the - * frequency for the operation. + * frequency for the operation and %NL80211_ATTR_WIPHY_CHANNEL_TYPE may be + * optionally used to specify additional channel parameters. * %NL80211_ATTR_DURATION is used to specify the duration in milliseconds * to remain on the channel. This command is also used as an event to * notify when the requested duration starts (it may take a while for the @@ -440,11 +440,12 @@ * as an event indicating reception of a frame that was not processed in * kernel code, but is for us (i.e., which may need to be processed in a * user space application). %NL80211_ATTR_FRAME is used to specify the - * frame contents (including header). %NL80211_ATTR_WIPHY_FREQ is used - * to indicate on which channel the frame is to be transmitted or was - * received. If this channel is not the current channel (remain-on-channel - * or the operational channel) the device will switch to the given channel - * and transmit the frame, optionally waiting for a response for the time + * frame contents (including header). %NL80211_ATTR_WIPHY_FREQ (and + * optionally %NL80211_ATTR_WIPHY_CHANNEL_TYPE) is used to indicate on + * which channel the frame is to be transmitted or was received. If this + * channel is not the current channel (remain-on-channel or the + * operational channel) the device will switch to the given channel and + * transmit the frame, optionally waiting for a response for the time * 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. @@ -472,8 +473,8 @@ * command is used as an event to indicate the that a trigger level was * reached. * @NL80211_CMD_SET_CHANNEL: Set the channel (using %NL80211_ATTR_WIPHY_FREQ - * and the attributes determining channel width) the given interface - * (identifed by %NL80211_ATTR_IFINDEX) shall operate on. + * and %NL80211_ATTR_WIPHY_CHANNEL_TYPE) the given interface (identifed + * by %NL80211_ATTR_IFINDEX) shall operate on. * In case multiple channels are supported by the device, the mechanism * with which it switches channels is implementation-defined. * When a monitor interface is given, it can only switch channel while @@ -525,12 +526,6 @@ * of PMKSA caching dandidates. * * @NL80211_CMD_TDLS_OPER: Perform a high-level TDLS command (e.g. link setup). - * In addition, this can be used as an event to request userspace to take - * actions on TDLS links (set up a new link or tear down an existing one). - * In such events, %NL80211_ATTR_TDLS_OPERATION indicates the requested - * operation, %NL80211_ATTR_MAC contains the peer MAC address, and - * %NL80211_ATTR_REASON_CODE the reason code to be used (only with - * %NL80211_TDLS_TEARDOWN). * @NL80211_CMD_TDLS_MGMT: Send a TDLS management frame. * * @NL80211_CMD_UNEXPECTED_FRAME: Used by an application controlling an AP @@ -567,8 +562,8 @@ * * @NL80211_CMD_CH_SWITCH_NOTIFY: An AP or GO may decide to switch channels * independently of the userspace SME, send this event indicating - * %NL80211_ATTR_IFINDEX is now on %NL80211_ATTR_WIPHY_FREQ and the - * attributes determining channel width. + * %NL80211_ATTR_IFINDEX is now on %NL80211_ATTR_WIPHY_FREQ with + * %NL80211_ATTR_WIPHY_CHANNEL_TYPE. * * @NL80211_CMD_START_P2P_DEVICE: Start the given P2P Device, identified by * its %NL80211_ATTR_WDEV identifier. It must have been created with @@ -772,26 +767,14 @@ enum nl80211_commands { * /sys/class/ieee80211//index * @NL80211_ATTR_WIPHY_NAME: wiphy name (used for renaming) * @NL80211_ATTR_WIPHY_TXQ_PARAMS: a nested array of TX queue parameters - * @NL80211_ATTR_WIPHY_FREQ: frequency of the selected channel in MHz, - * defines the channel together with the (deprecated) - * %NL80211_ATTR_WIPHY_CHANNEL_TYPE attribute or the attributes - * %NL80211_ATTR_CHANNEL_WIDTH and if needed %NL80211_ATTR_CENTER_FREQ1 - * and %NL80211_ATTR_CENTER_FREQ2 - * @NL80211_ATTR_CHANNEL_WIDTH: u32 attribute containing one of the values - * of &enum nl80211_chan_width, describing the channel width. See the - * documentation of the enum for more information. - * @NL80211_ATTR_CENTER_FREQ1: Center frequency of the first part of the - * channel, used for anything but 20 MHz bandwidth - * @NL80211_ATTR_CENTER_FREQ2: Center frequency of the second part of the - * channel, used only for 80+80 MHz bandwidth + * @NL80211_ATTR_WIPHY_FREQ: frequency of the selected channel in MHz * @NL80211_ATTR_WIPHY_CHANNEL_TYPE: included with NL80211_ATTR_WIPHY_FREQ - * if HT20 or HT40 are to be used (i.e., HT disabled if not included): + * if HT20 or HT40 are allowed (i.e., 802.11n disabled if not included): * NL80211_CHAN_NO_HT = HT not allowed (i.e., same as not including * this attribute) * NL80211_CHAN_HT20 = HT20 only * NL80211_CHAN_HT40MINUS = secondary channel is below the primary channel * NL80211_CHAN_HT40PLUS = secondary channel is above the primary channel - * This attribute is now deprecated. * @NL80211_ATTR_WIPHY_RETRY_SHORT: TX retry limit for frames whose length is * less than or equal to the RTS threshold; allowed range: 1..255; * dot11ShortRetryLimit; u8 @@ -1566,10 +1549,6 @@ enum nl80211_attrs { NL80211_ATTR_SCAN_FLAGS, - NL80211_ATTR_CHANNEL_WIDTH, - NL80211_ATTR_CENTER_FREQ1, - NL80211_ATTR_CENTER_FREQ2, - /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -1734,15 +1713,10 @@ struct nl80211_sta_flag_update { * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved * @NL80211_RATE_INFO_BITRATE: total bitrate (u16, 100kbit/s) * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8) - * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 MHz dualchannel bitrate + * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval * @NL80211_RATE_INFO_BITRATE32: total bitrate (u32, 100kbit/s) * @NL80211_RATE_INFO_MAX: highest rate_info number currently defined - * @NL80211_RATE_INFO_VHT_MCS: MCS index for VHT (u8) - * @NL80211_RATE_INFO_VHT_NSS: number of streams in VHT (u8) - * @NL80211_RATE_INFO_80_MHZ_WIDTH: 80 MHz VHT rate - * @NL80211_RATE_INFO_80P80_MHZ_WIDTH: 80+80 MHz VHT rate - * @NL80211_RATE_INFO_160_MHZ_WIDTH: 160 MHz VHT rate * @__NL80211_RATE_INFO_AFTER_LAST: internal use */ enum nl80211_rate_info { @@ -1752,11 +1726,6 @@ enum nl80211_rate_info { NL80211_RATE_INFO_40_MHZ_WIDTH, NL80211_RATE_INFO_SHORT_GI, NL80211_RATE_INFO_BITRATE32, - NL80211_RATE_INFO_VHT_MCS, - NL80211_RATE_INFO_VHT_NSS, - NL80211_RATE_INFO_80_MHZ_WIDTH, - NL80211_RATE_INFO_80P80_MHZ_WIDTH, - NL80211_RATE_INFO_160_MHZ_WIDTH, /* keep last */ __NL80211_RATE_INFO_AFTER_LAST, @@ -2465,15 +2434,6 @@ enum nl80211_ac { #define NL80211_TXQ_Q_BE NL80211_AC_BE #define NL80211_TXQ_Q_BK NL80211_AC_BK -/** - * enum nl80211_channel_type - channel type - * @NL80211_CHAN_NO_HT: 20 MHz, non-HT channel - * @NL80211_CHAN_HT20: 20 MHz HT channel - * @NL80211_CHAN_HT40MINUS: HT40 channel, secondary channel - * below the control channel - * @NL80211_CHAN_HT40PLUS: HT40 channel, secondary channel - * above the control channel - */ enum nl80211_channel_type { NL80211_CHAN_NO_HT, NL80211_CHAN_HT20, @@ -2481,32 +2441,6 @@ enum nl80211_channel_type { NL80211_CHAN_HT40PLUS }; -/** - * enum nl80211_chan_width - channel width definitions - * - * These values are used with the %NL80211_ATTR_CHANNEL_WIDTH - * attribute. - * - * @NL80211_CHAN_WIDTH_20_NOHT: 20 MHz, non-HT channel - * @NL80211_CHAN_WIDTH_20: 20 MHz HT channel - * @NL80211_CHAN_WIDTH_40: 40 MHz channel, the %NL80211_ATTR_CENTER_FREQ1 - * attribute must be provided as well - * @NL80211_CHAN_WIDTH_80: 80 MHz channel, the %NL80211_ATTR_CENTER_FREQ1 - * attribute must be provided as well - * @NL80211_CHAN_WIDTH_80P80: 80+80 MHz channel, the %NL80211_ATTR_CENTER_FREQ1 - * and %NL80211_ATTR_CENTER_FREQ2 attributes must be provided as well - * @NL80211_CHAN_WIDTH_160: 160 MHz channel, the %NL80211_ATTR_CENTER_FREQ1 - * attribute must be provided as well - */ -enum nl80211_chan_width { - NL80211_CHAN_WIDTH_20_NOHT, - NL80211_CHAN_WIDTH_20, - NL80211_CHAN_WIDTH_40, - NL80211_CHAN_WIDTH_80, - NL80211_CHAN_WIDTH_80P80, - NL80211_CHAN_WIDTH_160, -}; - /** * enum nl80211_bss - netlink attributes for a BSS * @@ -3123,9 +3057,6 @@ enum nl80211_ap_sme_features { * @NL80211_FEATURE_SCAN_FLUSH: Scan flush is supported * @NL80211_FEATURE_AP_SCAN: Support scanning using an AP vif * @NL80211_FEATURE_VIF_TXPOWER: The driver supports per-vif TX power setting - * @NL80211_FEATURE_NEED_OBSS_SCAN: The driver expects userspace to perform - * OBSS scans and generate 20/40 BSS coex reports. This flag is used only - * for drivers implementing the CONNECT API, for AUTH/ASSOC it is implied. */ enum nl80211_feature_flags { NL80211_FEATURE_SK_TX_STATUS = 1 << 0, @@ -3138,7 +3069,6 @@ enum nl80211_feature_flags { NL80211_FEATURE_SCAN_FLUSH = 1 << 7, NL80211_FEATURE_AP_SCAN = 1 << 8, NL80211_FEATURE_VIF_TXPOWER = 1 << 9, - NL80211_FEATURE_NEED_OBSS_SCAN = 1 << 10, }; /** diff --git a/trunk/net/bluetooth/hci_core.c b/trunk/net/bluetooth/hci_core.c index 7140f83328a2..81f4bac098c9 100644 --- a/trunk/net/bluetooth/hci_core.c +++ b/trunk/net/bluetooth/hci_core.c @@ -1815,11 +1815,11 @@ int hci_register_dev(struct hci_dev *hdev) if (hdev->dev_type != HCI_AMP) set_bit(HCI_AUTO_OFF, &hdev->dev_flags); + schedule_work(&hdev->power_on); + hci_notify(hdev, HCI_DEV_REG); hci_dev_hold(hdev); - schedule_work(&hdev->power_on); - return id; err_wqueue: diff --git a/trunk/net/bluetooth/mgmt.c b/trunk/net/bluetooth/mgmt.c index 142764aec2af..dedbb1d8b2d2 100644 --- a/trunk/net/bluetooth/mgmt.c +++ b/trunk/net/bluetooth/mgmt.c @@ -326,7 +326,7 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data, struct hci_dev *d; size_t rp_len; u16 count; - int err; + int i, err; BT_DBG("sock %p", sk); @@ -347,7 +347,9 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data, return -ENOMEM; } - count = 0; + rp->num_controllers = cpu_to_le16(count); + + i = 0; list_for_each_entry(d, &hci_dev_list, list) { if (test_bit(HCI_SETUP, &d->dev_flags)) continue; @@ -355,13 +357,10 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data, if (!mgmt_valid_hdev(d)) continue; - rp->index[count++] = cpu_to_le16(d->id); + rp->index[i++] = cpu_to_le16(d->id); BT_DBG("Added hci%u", d->id); } - rp->num_controllers = cpu_to_le16(count); - rp_len = sizeof(*rp) + (2 * count); - read_unlock(&hci_dev_list_lock); err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp, @@ -1379,7 +1378,6 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data, continue; list_del(&match->list); - kfree(match); found++; } diff --git a/trunk/net/bluetooth/rfcomm/sock.c b/trunk/net/bluetooth/rfcomm/sock.c index 4ddef57d03a7..ce3f6658f4b2 100644 --- a/trunk/net/bluetooth/rfcomm/sock.c +++ b/trunk/net/bluetooth/rfcomm/sock.c @@ -467,7 +467,7 @@ static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int f long timeo; int err = 0; - lock_sock(sk); + lock_sock_nested(sk, SINGLE_DEPTH_NESTING); if (sk->sk_type != SOCK_STREAM) { err = -EINVAL; @@ -504,7 +504,7 @@ static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int f release_sock(sk); timeo = schedule_timeout(timeo); - lock_sock(sk); + lock_sock_nested(sk, SINGLE_DEPTH_NESTING); } __set_current_state(TASK_RUNNING); remove_wait_queue(sk_sleep(sk), &wait); diff --git a/trunk/net/bluetooth/smp.c b/trunk/net/bluetooth/smp.c index 68a9587c9694..9176bc17595c 100644 --- a/trunk/net/bluetooth/smp.c +++ b/trunk/net/bluetooth/smp.c @@ -267,7 +267,7 @@ static void smp_failure(struct l2cap_conn *conn, u8 reason, u8 send) clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->flags); mgmt_auth_failed(conn->hcon->hdev, conn->dst, hcon->type, - hcon->dst_type, HCI_ERROR_AUTH_FAILURE); + hcon->dst_type, reason); cancel_delayed_work_sync(&conn->security_timer); diff --git a/trunk/net/core/net-sysfs.c b/trunk/net/core/net-sysfs.c index 017a8bacfb27..bcf02f608cbf 100644 --- a/trunk/net/core/net-sysfs.c +++ b/trunk/net/core/net-sysfs.c @@ -429,17 +429,6 @@ static struct attribute_group netstat_group = { .name = "statistics", .attrs = netstat_attrs, }; - -#if IS_ENABLED(CONFIG_WIRELESS_EXT) || IS_ENABLED(CONFIG_CFG80211) -static struct attribute *wireless_attrs[] = { - NULL -}; - -static struct attribute_group wireless_group = { - .name = "wireless", - .attrs = wireless_attrs, -}; -#endif #endif /* CONFIG_SYSFS */ #ifdef CONFIG_RPS @@ -1420,15 +1409,6 @@ int netdev_register_kobject(struct net_device *net) groups++; *groups++ = &netstat_group; - -#if IS_ENABLED(CONFIG_WIRELESS_EXT) || IS_ENABLED(CONFIG_CFG80211) - if (net->ieee80211_ptr) - *groups++ = &wireless_group; -#if IS_ENABLED(CONFIG_WIRELESS_EXT) - else if (net->wireless_handlers) - *groups++ = &wireless_group; -#endif -#endif #endif /* CONFIG_SYSFS */ error = device_add(dev); diff --git a/trunk/net/mac80211/agg-rx.c b/trunk/net/mac80211/agg-rx.c index 808338a1bce5..186d9919b043 100644 --- a/trunk/net/mac80211/agg-rx.c +++ b/trunk/net/mac80211/agg-rx.c @@ -118,7 +118,7 @@ void ieee80211_stop_rx_ba_session(struct ieee80211_vif *vif, u16 ba_rx_bitmap, return; } - for (i = 0; i < IEEE80211_NUM_TIDS; i++) + for (i = 0; i < STA_TID_NUM; i++) if (ba_rx_bitmap & BIT(i)) set_bit(i, sta->ampdu_mlme.tid_rx_stop_requested); diff --git a/trunk/net/mac80211/agg-tx.c b/trunk/net/mac80211/agg-tx.c index 4152ed1034b8..3195a6307f50 100644 --- a/trunk/net/mac80211/agg-tx.c +++ b/trunk/net/mac80211/agg-tx.c @@ -448,7 +448,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, if (WARN_ON(!local->ops->ampdu_action)) return -EINVAL; - if ((tid >= IEEE80211_NUM_TIDS) || + if ((tid >= STA_TID_NUM) || !(local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION) || (local->hw.flags & IEEE80211_HW_TX_AMPDU_SETUP_IN_HW)) return -EINVAL; @@ -605,9 +605,9 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid) trace_api_start_tx_ba_cb(sdata, ra, tid); - if (tid >= IEEE80211_NUM_TIDS) { + if (tid >= STA_TID_NUM) { ht_dbg(sdata, "Bad TID value: tid = %d (>= %d)\n", - tid, IEEE80211_NUM_TIDS); + tid, STA_TID_NUM); return; } @@ -687,7 +687,7 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid) if (!local->ops->ampdu_action) return -EINVAL; - if (tid >= IEEE80211_NUM_TIDS) + if (tid >= STA_TID_NUM) return -EINVAL; spin_lock_bh(&sta->lock); @@ -722,9 +722,9 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid) trace_api_stop_tx_ba_cb(sdata, ra, tid); - if (tid >= IEEE80211_NUM_TIDS) { + if (tid >= STA_TID_NUM) { ht_dbg(sdata, "Bad TID value: tid = %d (>= %d)\n", - tid, IEEE80211_NUM_TIDS); + tid, STA_TID_NUM); return; } diff --git a/trunk/net/mac80211/cfg.c b/trunk/net/mac80211/cfg.c index 4965aa6424ec..80e0618b25ba 100644 --- a/trunk/net/mac80211/cfg.c +++ b/trunk/net/mac80211/cfg.c @@ -370,32 +370,30 @@ static int ieee80211_config_default_mgmt_key(struct wiphy *wiphy, return 0; } +static void rate_idx_to_bitrate(struct rate_info *rate, struct sta_info *sta, int idx) +{ + enum ieee80211_band band = ieee80211_get_sdata_band(sta->sdata); + + if (!(rate->flags & RATE_INFO_FLAGS_MCS)) { + struct ieee80211_supported_band *sband; + sband = sta->local->hw.wiphy->bands[band]; + rate->legacy = sband->bitrates[idx].bitrate; + } else + rate->mcs = idx; +} + void sta_set_rate_info_tx(struct sta_info *sta, const struct ieee80211_tx_rate *rate, struct rate_info *rinfo) { rinfo->flags = 0; - if (rate->flags & IEEE80211_TX_RC_MCS) { + if (rate->flags & IEEE80211_TX_RC_MCS) rinfo->flags |= RATE_INFO_FLAGS_MCS; - rinfo->mcs = rate->idx; - } else if (rate->flags & IEEE80211_TX_RC_VHT_MCS) { - rinfo->flags |= RATE_INFO_FLAGS_VHT_MCS; - rinfo->mcs = ieee80211_rate_get_vht_mcs(rate); - rinfo->nss = ieee80211_rate_get_vht_nss(rate); - } else { - struct ieee80211_supported_band *sband; - sband = sta->local->hw.wiphy->bands[ - ieee80211_get_sdata_band(sta->sdata)]; - rinfo->legacy = sband->bitrates[rate->idx].bitrate; - } if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) rinfo->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; - if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH) - rinfo->flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; - if (rate->flags & IEEE80211_TX_RC_160_MHZ_WIDTH) - rinfo->flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH; if (rate->flags & IEEE80211_TX_RC_SHORT_GI) rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI; + rate_idx_to_bitrate(rinfo, sta, rate->idx); } static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) @@ -446,32 +444,13 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate); sinfo->rxrate.flags = 0; - if (sta->last_rx_rate_flag & RX_FLAG_HT) { + if (sta->last_rx_rate_flag & RX_FLAG_HT) sinfo->rxrate.flags |= RATE_INFO_FLAGS_MCS; - sinfo->rxrate.mcs = sta->last_rx_rate_idx; - } else if (sta->last_rx_rate_flag & RX_FLAG_VHT) { - sinfo->rxrate.flags |= RATE_INFO_FLAGS_VHT_MCS; - sinfo->rxrate.nss = sta->last_rx_rate_vht_nss; - sinfo->rxrate.mcs = sta->last_rx_rate_idx; - } else { - struct ieee80211_supported_band *sband; - - sband = sta->local->hw.wiphy->bands[ - ieee80211_get_sdata_band(sta->sdata)]; - sinfo->rxrate.legacy = - sband->bitrates[sta->last_rx_rate_idx].bitrate; - } - if (sta->last_rx_rate_flag & RX_FLAG_40MHZ) sinfo->rxrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; if (sta->last_rx_rate_flag & RX_FLAG_SHORT_GI) sinfo->rxrate.flags |= RATE_INFO_FLAGS_SHORT_GI; - if (sta->last_rx_rate_flag & RX_FLAG_80MHZ) - sinfo->rxrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; - if (sta->last_rx_rate_flag & RX_FLAG_80P80MHZ) - sinfo->rxrate.flags |= RATE_INFO_FLAGS_80P80_MHZ_WIDTH; - if (sta->last_rx_rate_flag & RX_FLAG_160MHZ) - sinfo->rxrate.flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH; + rate_idx_to_bitrate(&sinfo->rxrate, sta, sta->last_rx_rate_idx); if (ieee80211_vif_is_mesh(&sdata->vif)) { #ifdef CONFIG_MAC80211_MESH @@ -636,7 +615,7 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy, rcu_read_lock(); chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); if (chanctx_conf) - channel = chanctx_conf->def.chan; + channel = chanctx_conf->channel; else channel = NULL; rcu_read_unlock(); @@ -756,13 +735,15 @@ static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, } static int ieee80211_set_monitor_channel(struct wiphy *wiphy, - struct cfg80211_chan_def *chandef) + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type) { struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_sub_if_data *sdata; int ret = 0; - if (cfg80211_chandef_identical(&local->monitor_chandef, chandef)) + if (local->monitor_channel == chan && + local->monitor_channel_type == channel_type) return 0; mutex_lock(&local->iflist_mtx); @@ -772,17 +753,20 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy, lockdep_is_held(&local->iflist_mtx)); if (sdata) { ieee80211_vif_release_channel(sdata); - ret = ieee80211_vif_use_channel(sdata, chandef, + ret = ieee80211_vif_use_channel( + sdata, chan, channel_type, IEEE80211_CHANCTX_EXCLUSIVE); } } else if (local->open_count == local->monitors) { - local->_oper_channel = chandef->chan; - local->_oper_channel_type = cfg80211_get_chandef_type(chandef); + local->_oper_channel = chan; + local->_oper_channel_type = channel_type; ieee80211_hw_config(local, 0); } - if (ret == 0) - local->monitor_chandef = *chandef; + if (ret == 0) { + local->monitor_channel = chan; + local->monitor_channel_type = channel_type; + } mutex_unlock(&local->iflist_mtx); return ret; @@ -904,7 +888,8 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, sdata->smps_mode = IEEE80211_SMPS_OFF; sdata->needed_rx_chains = sdata->local->rx_chains; - err = ieee80211_vif_use_channel(sdata, ¶ms->chandef, + err = ieee80211_vif_use_channel(sdata, params->channel, + params->channel_type, IEEE80211_CHANCTX_SHARED); if (err) return err; @@ -1722,7 +1707,8 @@ static int ieee80211_join_mesh(struct wiphy *wiphy, struct net_device *dev, sdata->smps_mode = IEEE80211_SMPS_OFF; sdata->needed_rx_chains = sdata->local->rx_chains; - err = ieee80211_vif_use_channel(sdata, &setup->chandef, + err = ieee80211_vif_use_channel(sdata, setup->channel, + setup->channel_type, IEEE80211_CHANCTX_SHARED); if (err) return err; @@ -2004,16 +1990,10 @@ static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) return err; } - if (changed & WIPHY_PARAM_RETRY_SHORT) { - if (wiphy->retry_short > IEEE80211_MAX_TX_RETRY) - return -EINVAL; + if (changed & WIPHY_PARAM_RETRY_SHORT) local->hw.conf.short_frame_max_tx_count = wiphy->retry_short; - } - if (changed & WIPHY_PARAM_RETRY_LONG) { - if (wiphy->retry_long > IEEE80211_MAX_TX_RETRY) - return -EINVAL; + if (changed & WIPHY_PARAM_RETRY_LONG) local->hw.conf.long_frame_max_tx_count = wiphy->retry_long; - } if (changed & (WIPHY_PARAM_RETRY_SHORT | WIPHY_PARAM_RETRY_LONG)) ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_RETRY_LIMITS); @@ -2149,7 +2129,7 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, * the new value until we associate. */ if (!sdata->u.mgd.associated || - sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT) + sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) return 0; ap = sdata->u.mgd.associated->bssid; @@ -2256,6 +2236,7 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, static int ieee80211_start_roc_work(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata, struct ieee80211_channel *channel, + enum nl80211_channel_type channel_type, unsigned int duration, u64 *cookie, struct sk_buff *txskb) { @@ -2273,6 +2254,7 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, return -ENOMEM; roc->chan = channel; + roc->chan_type = channel_type; roc->duration = duration; roc->req_duration = duration; roc->frame = txskb; @@ -2305,7 +2287,7 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, if (!duration) duration = 10; - ret = drv_remain_on_channel(local, sdata, channel, duration); + ret = drv_remain_on_channel(local, channel, channel_type, duration); if (ret) { kfree(roc); return ret; @@ -2316,7 +2298,7 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, out_check_combine: list_for_each_entry(tmp, &local->roc_list, list) { - if (tmp->chan != channel || tmp->sdata != sdata) + if (tmp->chan != channel || tmp->chan_type != channel_type) continue; /* @@ -2433,6 +2415,7 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, static int ieee80211_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev, struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, unsigned int duration, u64 *cookie) { @@ -2441,7 +2424,7 @@ static int ieee80211_remain_on_channel(struct wiphy *wiphy, int ret; mutex_lock(&local->mtx); - ret = ieee80211_start_roc_work(local, sdata, chan, + ret = ieee80211_start_roc_work(local, sdata, chan, channel_type, duration, cookie, NULL); mutex_unlock(&local->mtx); @@ -2534,8 +2517,10 @@ static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy, static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, struct ieee80211_channel *chan, bool offchan, - unsigned int wait, const u8 *buf, size_t len, - bool no_cck, bool dont_wait_for_ack, u64 *cookie) + enum nl80211_channel_type channel_type, + bool channel_type_valid, unsigned int wait, + const u8 *buf, size_t len, bool no_cck, + bool dont_wait_for_ack, u64 *cookie) { struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); struct ieee80211_local *local = sdata->local; @@ -2604,10 +2589,14 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, rcu_read_lock(); chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); - if (chanctx_conf) - need_offchan = chan != chanctx_conf->def.chan; - else + if (chanctx_conf) { + need_offchan = chan != chanctx_conf->channel; + if (channel_type_valid && + channel_type != chanctx_conf->channel_type) + need_offchan = true; + } else { need_offchan = true; + } rcu_read_unlock(); } @@ -2642,7 +2631,7 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, local->hw.offchannel_tx_hw_queue; /* This will handle all kinds of coalescing and immediate TX */ - ret = ieee80211_start_roc_work(local, sdata, chan, + ret = ieee80211_start_roc_work(local, sdata, chan, channel_type, wait, cookie, skb); if (ret) kfree_skb(skb); @@ -2684,9 +2673,6 @@ static void ieee80211_mgmt_frame_register(struct wiphy *wiphy, else local->probe_req_reg--; - if (!local->open_count) - break; - ieee80211_queue_work(&local->hw, &local->reconfig_filter); break; default: @@ -3076,7 +3062,7 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev, rcu_read_unlock(); return -EINVAL; } - band = chanctx_conf->def.chan->band; + band = chanctx_conf->channel->band; sta = sta_info_get(sdata, peer); if (sta) { qos = test_sta_flag(sta, WLAN_STA_WME); @@ -3133,23 +3119,23 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev, return 0; } -static int ieee80211_cfg_get_channel(struct wiphy *wiphy, - struct wireless_dev *wdev, - struct cfg80211_chan_def *chandef) +static struct ieee80211_channel * +ieee80211_cfg_get_channel(struct wiphy *wiphy, struct wireless_dev *wdev, + enum nl80211_channel_type *type) { struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); struct ieee80211_chanctx_conf *chanctx_conf; - int ret = -ENODATA; + struct ieee80211_channel *chan = NULL; rcu_read_lock(); chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); if (chanctx_conf) { - *chandef = chanctx_conf->def; - ret = 0; + *type = chanctx_conf->channel_type; + chan = chanctx_conf->channel; } rcu_read_unlock(); - return ret; + return chan; } #ifdef CONFIG_PM diff --git a/trunk/net/mac80211/chan.c b/trunk/net/mac80211/chan.c index 53f03120db55..a2b06d40aebf 100644 --- a/trunk/net/mac80211/chan.c +++ b/trunk/net/mac80211/chan.c @@ -8,47 +8,93 @@ #include "ieee80211_i.h" #include "driver-ops.h" -static void ieee80211_change_chandef(struct ieee80211_local *local, - struct ieee80211_chanctx *ctx, - const struct cfg80211_chan_def *chandef) +static bool +ieee80211_channel_types_are_compatible(enum nl80211_channel_type chantype1, + enum nl80211_channel_type chantype2, + enum nl80211_channel_type *compat) { - if (cfg80211_chandef_identical(&ctx->conf.def, chandef)) - return; + /* + * start out with chantype1 being the result, + * overwriting later if needed + */ + if (compat) + *compat = chantype1; + + switch (chantype1) { + case NL80211_CHAN_NO_HT: + if (compat) + *compat = chantype2; + break; + case NL80211_CHAN_HT20: + /* + * allow any change that doesn't go to no-HT + * (if it already is no-HT no change is needed) + */ + if (chantype2 == NL80211_CHAN_NO_HT) + break; + if (compat) + *compat = chantype2; + break; + case NL80211_CHAN_HT40PLUS: + case NL80211_CHAN_HT40MINUS: + /* allow smaller bandwidth and same */ + if (chantype2 == NL80211_CHAN_NO_HT) + break; + if (chantype2 == NL80211_CHAN_HT20) + break; + if (chantype2 == chantype1) + break; + return false; + } - WARN_ON(!cfg80211_chandef_compatible(&ctx->conf.def, chandef)); + return true; +} - ctx->conf.def = *chandef; - drv_change_chanctx(local, ctx, IEEE80211_CHANCTX_CHANGE_WIDTH); +static void ieee80211_change_chantype(struct ieee80211_local *local, + struct ieee80211_chanctx *ctx, + enum nl80211_channel_type chantype) +{ + if (chantype == ctx->conf.channel_type) + return; + + ctx->conf.channel_type = chantype; + drv_change_chanctx(local, ctx, IEEE80211_CHANCTX_CHANGE_CHANNEL_TYPE); if (!local->use_chanctx) { - local->_oper_channel_type = cfg80211_get_chandef_type(chandef); + local->_oper_channel_type = chantype; ieee80211_hw_config(local, 0); } } static struct ieee80211_chanctx * ieee80211_find_chanctx(struct ieee80211_local *local, - const struct cfg80211_chan_def *chandef, + struct ieee80211_channel *channel, + enum nl80211_channel_type channel_type, enum ieee80211_chanctx_mode mode) { struct ieee80211_chanctx *ctx; + enum nl80211_channel_type compat_type; lockdep_assert_held(&local->chanctx_mtx); if (mode == IEEE80211_CHANCTX_EXCLUSIVE) return NULL; + if (WARN_ON(!channel)) + return NULL; list_for_each_entry(ctx, &local->chanctx_list, list) { - const struct cfg80211_chan_def *compat; + compat_type = ctx->conf.channel_type; if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE) continue; - - compat = cfg80211_chandef_compatible(&ctx->conf.def, chandef); - if (!compat) + if (ctx->conf.channel != channel) + continue; + if (!ieee80211_channel_types_are_compatible(ctx->conf.channel_type, + channel_type, + &compat_type)) continue; - ieee80211_change_chandef(local, ctx, compat); + ieee80211_change_chantype(local, ctx, compat_type); return ctx; } @@ -58,7 +104,8 @@ ieee80211_find_chanctx(struct ieee80211_local *local, static struct ieee80211_chanctx * ieee80211_new_chanctx(struct ieee80211_local *local, - const struct cfg80211_chan_def *chandef, + struct ieee80211_channel *channel, + enum nl80211_channel_type channel_type, enum ieee80211_chanctx_mode mode) { struct ieee80211_chanctx *ctx; @@ -70,15 +117,15 @@ ieee80211_new_chanctx(struct ieee80211_local *local, if (!ctx) return ERR_PTR(-ENOMEM); - ctx->conf.def = *chandef; + ctx->conf.channel = channel; + ctx->conf.channel_type = channel_type; ctx->conf.rx_chains_static = 1; ctx->conf.rx_chains_dynamic = 1; ctx->mode = mode; if (!local->use_chanctx) { - local->_oper_channel_type = - cfg80211_get_chandef_type(chandef); - local->_oper_channel = chandef->chan; + local->_oper_channel_type = channel_type; + local->_oper_channel = channel; ieee80211_hw_config(local, 0); } else { err = drv_add_chanctx(local, ctx); @@ -131,37 +178,41 @@ static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data *sdata, return 0; } -static void ieee80211_recalc_chanctx_chantype(struct ieee80211_local *local, - struct ieee80211_chanctx *ctx) +static enum nl80211_channel_type +ieee80211_calc_chantype(struct ieee80211_local *local, + struct ieee80211_chanctx *ctx) { struct ieee80211_chanctx_conf *conf = &ctx->conf; struct ieee80211_sub_if_data *sdata; - const struct cfg80211_chan_def *compat = NULL; + enum nl80211_channel_type result = NL80211_CHAN_NO_HT; lockdep_assert_held(&local->chanctx_mtx); rcu_read_lock(); list_for_each_entry_rcu(sdata, &local->interfaces, list) { - if (!ieee80211_sdata_running(sdata)) continue; if (rcu_access_pointer(sdata->vif.chanctx_conf) != conf) continue; - if (!compat) - compat = &sdata->vif.bss_conf.chandef; - - compat = cfg80211_chandef_compatible( - &sdata->vif.bss_conf.chandef, compat); - if (!compat) - break; + WARN_ON_ONCE(!ieee80211_channel_types_are_compatible( + sdata->vif.bss_conf.channel_type, + result, &result)); } rcu_read_unlock(); - if (WARN_ON_ONCE(!compat)) - return; + return result; +} + +static void ieee80211_recalc_chanctx_chantype(struct ieee80211_local *local, + struct ieee80211_chanctx *ctx) +{ + enum nl80211_channel_type chantype; + + lockdep_assert_held(&local->chanctx_mtx); - ieee80211_change_chandef(local, ctx, compat); + chantype = ieee80211_calc_chantype(local, ctx); + ieee80211_change_chantype(local, ctx, chantype); } static void ieee80211_unassign_vif_chanctx(struct ieee80211_sub_if_data *sdata, @@ -286,7 +337,8 @@ void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local, } int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata, - const struct cfg80211_chan_def *chandef, + struct ieee80211_channel *channel, + enum nl80211_channel_type channel_type, enum ieee80211_chanctx_mode mode) { struct ieee80211_local *local = sdata->local; @@ -298,15 +350,15 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata, mutex_lock(&local->chanctx_mtx); __ieee80211_vif_release_channel(sdata); - ctx = ieee80211_find_chanctx(local, chandef, mode); + ctx = ieee80211_find_chanctx(local, channel, channel_type, mode); if (!ctx) - ctx = ieee80211_new_chanctx(local, chandef, mode); + ctx = ieee80211_new_chanctx(local, channel, channel_type, mode); if (IS_ERR(ctx)) { ret = PTR_ERR(ctx); goto out; } - sdata->vif.bss_conf.chandef = *chandef; + sdata->vif.bss_conf.channel_type = channel_type; ret = ieee80211_assign_vif_chanctx(sdata, ctx); if (ret) { diff --git a/trunk/net/mac80211/debugfs_key.c b/trunk/net/mac80211/debugfs_key.c index 2d4235497f1b..090d08ff22c4 100644 --- a/trunk/net/mac80211/debugfs_key.c +++ b/trunk/net/mac80211/debugfs_key.c @@ -116,7 +116,7 @@ static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) { struct ieee80211_key *key = file->private_data; - char buf[14*IEEE80211_NUM_TIDS+1], *p = buf; + char buf[14*NUM_RX_DATA_QUEUES+1], *p = buf; int i, len; const u8 *rpn; @@ -126,7 +126,7 @@ static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf, len = scnprintf(buf, sizeof(buf), "\n"); break; case WLAN_CIPHER_SUITE_TKIP: - for (i = 0; i < IEEE80211_NUM_TIDS; i++) + for (i = 0; i < NUM_RX_DATA_QUEUES; i++) p += scnprintf(p, sizeof(buf)+buf-p, "%08x %04x\n", key->u.tkip.rx[i].iv32, @@ -134,7 +134,7 @@ static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf, len = p - buf; break; case WLAN_CIPHER_SUITE_CCMP: - for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) { + for (i = 0; i < NUM_RX_DATA_QUEUES + 1; i++) { rpn = key->u.ccmp.rx_pn[i]; p += scnprintf(p, sizeof(buf)+buf-p, "%02x%02x%02x%02x%02x%02x\n", diff --git a/trunk/net/mac80211/debugfs_netdev.c b/trunk/net/mac80211/debugfs_netdev.c index cbde5cc49a40..ba9bd0ef119a 100644 --- a/trunk/net/mac80211/debugfs_netdev.c +++ b/trunk/net/mac80211/debugfs_netdev.c @@ -168,6 +168,7 @@ IEEE80211_IF_FILE(rc_rateidx_mcs_mask_5ghz, IEEE80211_IF_FILE(flags, flags, HEX); IEEE80211_IF_FILE(state, state, LHEX); +IEEE80211_IF_FILE(channel_type, vif.bss_conf.channel_type, DEC); IEEE80211_IF_FILE(txpower, vif.bss_conf.txpower, DEC); IEEE80211_IF_FILE(ap_power_level, ap_power_level, DEC); IEEE80211_IF_FILE(user_power_level, user_power_level, DEC); @@ -631,6 +632,7 @@ static void add_files(struct ieee80211_sub_if_data *sdata) DEBUGFS_ADD(flags); DEBUGFS_ADD(state); + DEBUGFS_ADD(channel_type); DEBUGFS_ADD(txpower); DEBUGFS_ADD(user_power_level); DEBUGFS_ADD(ap_power_level); diff --git a/trunk/net/mac80211/debugfs_sta.c b/trunk/net/mac80211/debugfs_sta.c index 89281d24b094..5ccec2c1e9f6 100644 --- a/trunk/net/mac80211/debugfs_sta.c +++ b/trunk/net/mac80211/debugfs_sta.c @@ -14,7 +14,6 @@ #include "debugfs.h" #include "debugfs_sta.h" #include "sta_info.h" -#include "driver-ops.h" /* sta attributtes */ @@ -132,10 +131,10 @@ STA_OPS(connected_time); static ssize_t sta_last_seq_ctrl_read(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) { - char buf[15*IEEE80211_NUM_TIDS], *p = buf; + char buf[15*NUM_RX_DATA_QUEUES], *p = buf; int i; struct sta_info *sta = file->private_data; - for (i = 0; i < IEEE80211_NUM_TIDS; i++) + for (i = 0; i < NUM_RX_DATA_QUEUES; i++) p += scnprintf(p, sizeof(buf)+buf-p, "%x ", le16_to_cpu(sta->last_seq_ctrl[i])); p += scnprintf(p, sizeof(buf)+buf-p, "\n"); @@ -146,7 +145,7 @@ STA_OPS(last_seq_ctrl); static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) { - char buf[71 + IEEE80211_NUM_TIDS * 40], *p = buf; + char buf[71 + STA_TID_NUM * 40], *p = buf; int i; struct sta_info *sta = file->private_data; struct tid_ampdu_rx *tid_rx; @@ -159,7 +158,7 @@ static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, p += scnprintf(p, sizeof(buf) + buf - p, "TID\t\tRX active\tDTKN\tSSN\t\tTX\tDTKN\tpending\n"); - for (i = 0; i < IEEE80211_NUM_TIDS; i++) { + for (i = 0; i < STA_TID_NUM; i++) { tid_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[i]); tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[i]); @@ -221,7 +220,7 @@ static ssize_t sta_agg_status_write(struct file *file, const char __user *userbu tid = simple_strtoul(buf, NULL, 0); - if (tid >= IEEE80211_NUM_TIDS) + if (tid >= STA_TID_NUM) return -EINVAL; if (tx) { @@ -335,8 +334,6 @@ STA_OPS(ht_capa); void ieee80211_sta_debugfs_add(struct sta_info *sta) { - struct ieee80211_local *local = sta->local; - struct ieee80211_sub_if_data *sdata = sta->sdata; struct dentry *stations_dir = sta->sdata->debugfs.subdir_stations; u8 mac[3*ETH_ALEN]; @@ -382,16 +379,10 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta) DEBUGFS_ADD_COUNTER(tx_retry_failed, tx_retry_failed); DEBUGFS_ADD_COUNTER(tx_retry_count, tx_retry_count); DEBUGFS_ADD_COUNTER(wep_weak_iv_count, wep_weak_iv_count); - - drv_sta_add_debugfs(local, sdata, &sta->sta, sta->debugfs.dir); } void ieee80211_sta_debugfs_remove(struct sta_info *sta) { - struct ieee80211_local *local = sta->local; - struct ieee80211_sub_if_data *sdata = sta->sdata; - - drv_sta_remove_debugfs(local, sdata, &sta->sta, sta->debugfs.dir); debugfs_remove_recursive(sta->debugfs.dir); sta->debugfs.dir = NULL; } diff --git a/trunk/net/mac80211/driver-ops.h b/trunk/net/mac80211/driver-ops.h index c6560cc7a9d6..4dc2577886ff 100644 --- a/trunk/net/mac80211/driver-ops.h +++ b/trunk/net/mac80211/driver-ops.h @@ -490,38 +490,6 @@ static inline void drv_sta_remove(struct ieee80211_local *local, trace_drv_return_void(local); } -#ifdef CONFIG_MAC80211_DEBUGFS -static inline void drv_sta_add_debugfs(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata, - struct ieee80211_sta *sta, - struct dentry *dir) -{ - might_sleep(); - - sdata = get_bss_sdata(sdata); - check_sdata_in_driver(sdata); - - if (local->ops->sta_add_debugfs) - local->ops->sta_add_debugfs(&local->hw, &sdata->vif, - sta, dir); -} - -static inline void drv_sta_remove_debugfs(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata, - struct ieee80211_sta *sta, - struct dentry *dir) -{ - might_sleep(); - - sdata = get_bss_sdata(sdata); - check_sdata_in_driver(sdata); - - if (local->ops->sta_remove_debugfs) - local->ops->sta_remove_debugfs(&local->hw, &sdata->vif, - sta, dir); -} -#endif - static inline __must_check int drv_sta_state(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata, @@ -736,17 +704,17 @@ static inline int drv_get_antenna(struct ieee80211_local *local, } static inline int drv_remain_on_channel(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata, struct ieee80211_channel *chan, + enum nl80211_channel_type chantype, unsigned int duration) { int ret; might_sleep(); - trace_drv_remain_on_channel(local, sdata, chan, duration); - ret = local->ops->remain_on_channel(&local->hw, &sdata->vif, - chan, duration); + trace_drv_remain_on_channel(local, chan, chantype, duration); + ret = local->ops->remain_on_channel(&local->hw, chan, chantype, + duration); trace_drv_return_int(local, ret); return ret; diff --git a/trunk/net/mac80211/ht.c b/trunk/net/mac80211/ht.c index a71d891794a4..4b4538d63925 100644 --- a/trunk/net/mac80211/ht.c +++ b/trunk/net/mac80211/ht.c @@ -185,7 +185,7 @@ void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta, bool tx) cancel_work_sync(&sta->ampdu_mlme.work); - for (i = 0; i < IEEE80211_NUM_TIDS; i++) { + for (i = 0; i < STA_TID_NUM; i++) { __ieee80211_stop_tx_ba_session(sta, i, WLAN_BACK_INITIATOR, tx); __ieee80211_stop_rx_ba_session(sta, i, WLAN_BACK_RECIPIENT, WLAN_REASON_QSTA_LEAVE_QBSS, tx); @@ -209,7 +209,7 @@ void ieee80211_ba_session_work(struct work_struct *work) return; mutex_lock(&sta->ampdu_mlme.mtx); - for (tid = 0; tid < IEEE80211_NUM_TIDS; tid++) { + for (tid = 0; tid < STA_TID_NUM; tid++) { if (test_and_clear_bit(tid, sta->ampdu_mlme.tid_rx_timer_expired)) ___ieee80211_stop_rx_ba_session( sta, tid, WLAN_BACK_RECIPIENT, diff --git a/trunk/net/mac80211/ibss.c b/trunk/net/mac80211/ibss.c index fa862b24a7e0..c7386b2b767e 100644 --- a/trunk/net/mac80211/ibss.c +++ b/trunk/net/mac80211/ibss.c @@ -51,7 +51,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, struct cfg80211_bss *bss; u32 bss_change; u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; - struct cfg80211_chan_def chandef; + enum nl80211_channel_type channel_type; lockdep_assert_held(&ifibss->mtx); @@ -79,14 +79,12 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; - cfg80211_chandef_create(&chandef, chan, ifibss->channel_type); - if (!cfg80211_reg_can_beacon(local->hw.wiphy, &chandef)) { - chandef.width = NL80211_CHAN_WIDTH_20; - chandef.center_freq1 = chan->center_freq; - } + channel_type = ifibss->channel_type; + if (!cfg80211_can_beacon_sec_chan(local->hw.wiphy, chan, channel_type)) + channel_type = NL80211_CHAN_HT20; ieee80211_vif_release_channel(sdata); - if (ieee80211_vif_use_channel(sdata, &chandef, + if (ieee80211_vif_use_channel(sdata, chan, channel_type, ifibss->fixed_channel ? IEEE80211_CHANCTX_SHARED : IEEE80211_CHANCTX_EXCLUSIVE)) { @@ -160,8 +158,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, ifibss->ie, ifibss->ie_len); /* add HT capability and information IEs */ - if (chandef.width != NL80211_CHAN_WIDTH_20_NOHT && - sband->ht_cap.ht_supported) { + if (channel_type && sband->ht_cap.ht_supported) { pos = skb_put(skb, 4 + sizeof(struct ieee80211_ht_cap) + sizeof(struct ieee80211_ht_operation)); @@ -173,7 +170,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, * keep them at 0 */ pos = ieee80211_ie_build_ht_oper(pos, &sband->ht_cap, - &chandef, 0); + chan, channel_type, 0); } if (local->hw.queues >= IEEE80211_NUM_ACS) { @@ -329,7 +326,7 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); if (WARN_ON_ONCE(!chanctx_conf)) return NULL; - band = chanctx_conf->def.chan->band; + band = chanctx_conf->channel->band; rcu_read_unlock(); sta = sta_info_alloc(sdata, addr, GFP_KERNEL); @@ -377,13 +374,11 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata, auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg); auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction); + if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) + return; ibss_dbg(sdata, "RX Auth SA=%pM DA=%pM BSSID=%pM (auth_transaction=%d)\n", mgmt->sa, mgmt->da, mgmt->bssid, auth_transaction); - - if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) - return; - sta_info_destroy_addr(sdata, mgmt->sa); sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, 0, false); rcu_read_unlock(); @@ -478,11 +473,9 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, sdata->u.ibss.channel_type != NL80211_CHAN_NO_HT) { /* we both use HT */ struct ieee80211_sta_ht_cap sta_ht_cap_new; - struct cfg80211_chan_def chandef; - - ieee80211_ht_oper_to_chandef(channel, - elems->ht_operation, - &chandef); + enum nl80211_channel_type channel_type = + ieee80211_ht_oper_to_channel_type( + elems->ht_operation); ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, elems->ht_cap_elem, @@ -492,9 +485,9 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, * fall back to HT20 if we don't use or use * the other extension channel */ - if (chandef.width != NL80211_CHAN_WIDTH_40 || - cfg80211_get_chandef_type(&chandef) != - sdata->u.ibss.channel_type) + if (!(channel_type == NL80211_CHAN_HT40MINUS || + channel_type == NL80211_CHAN_HT40PLUS) || + channel_type != sdata->u.ibss.channel_type) sta_ht_cap_new.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; @@ -550,11 +543,30 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, if (ether_addr_equal(cbss->bssid, sdata->u.ibss.bssid)) goto put_bss; - if (ieee80211_have_rx_timestamp(rx_status)) { - /* time when timestamp field was received */ - rx_timestamp = - ieee80211_calculate_rx_timestamp(local, rx_status, - len + FCS_LEN, 24); + if (rx_status->flag & RX_FLAG_MACTIME_MPDU) { + /* + * For correct IBSS merging we need mactime; since mactime is + * defined as the time the first data symbol of the frame hits + * the PHY, and the timestamp of the beacon is defined as "the + * time that the data symbol containing the first bit of the + * timestamp is transmitted to the PHY plus the transmitting + * STA's delays through its local PHY from the MAC-PHY + * interface to its interface with the WM" (802.11 11.1.2) + * - equals the time this bit arrives at the receiver - we have + * to take into account the offset between the two. + * + * E.g. at 1 MBit that means mactime is 192 usec earlier + * (=24 bytes * 8 usecs/byte) than the beacon timestamp. + */ + int rate; + + if (rx_status->flag & RX_FLAG_HT) + rate = 65; /* TODO: HT rates */ + else + rate = local->hw.wiphy->bands[band]-> + bitrates[rx_status->rate_idx].bitrate; + + rx_timestamp = rx_status->mactime + (24 * 8 * 10 / rate); } else { /* * second best option: get current TSF @@ -618,7 +630,7 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata, rcu_read_unlock(); return; } - band = chanctx_conf->def.chan->band; + band = chanctx_conf->channel->band; rcu_read_unlock(); sta = sta_info_alloc(sdata, addr, GFP_ATOMIC); @@ -1083,9 +1095,8 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, sdata->vif.bss_conf.beacon_int = params->beacon_interval; - sdata->u.ibss.channel = params->chandef.chan; - sdata->u.ibss.channel_type = - cfg80211_get_chandef_type(¶ms->chandef); + sdata->u.ibss.channel = params->channel; + sdata->u.ibss.channel_type = params->channel_type; sdata->u.ibss.fixed_channel = params->channel_fixed; if (params->ie) { @@ -1145,6 +1156,10 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) mutex_lock(&sdata->u.ibss.mtx); + sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH; + memset(sdata->u.ibss.bssid, 0, ETH_ALEN); + sdata->u.ibss.ssid_len = 0; + active_ibss = ieee80211_sta_active_ibss(sdata); if (!active_ibss && !is_zero_ether_addr(ifibss->bssid)) { @@ -1165,10 +1180,6 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) } } - ifibss->state = IEEE80211_IBSS_MLME_SEARCH; - memset(ifibss->bssid, 0, ETH_ALEN); - ifibss->ssid_len = 0; - sta_info_flush(sdata->local, sdata); spin_lock_bh(&ifibss->incomplete_lock); diff --git a/trunk/net/mac80211/ieee80211_i.h b/trunk/net/mac80211/ieee80211_i.h index 5c0d5a6946c1..e1fb97cc9a41 100644 --- a/trunk/net/mac80211/ieee80211_i.h +++ b/trunk/net/mac80211/ieee80211_i.h @@ -348,6 +348,7 @@ struct ieee80211_roc_work { struct ieee80211_sub_if_data *sdata; struct ieee80211_channel *chan; + enum nl80211_channel_type chan_type; bool started, abort, hw_begun, notified; @@ -363,7 +364,7 @@ enum ieee80211_sta_flags { IEEE80211_STA_BEACON_POLL = BIT(0), IEEE80211_STA_CONNECTION_POLL = BIT(1), IEEE80211_STA_CONTROL_PORT = BIT(2), - IEEE80211_STA_DISABLE_HT = BIT(4), + IEEE80211_STA_DISABLE_11N = BIT(4), IEEE80211_STA_CSA_RECEIVED = BIT(5), IEEE80211_STA_MFP_ENABLED = BIT(6), IEEE80211_STA_UAPSD_ENABLED = BIT(7), @@ -799,7 +800,7 @@ ieee80211_get_sdata_band(struct ieee80211_sub_if_data *sdata) rcu_read_lock(); chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); if (!WARN_ON(!chanctx_conf)) - band = chanctx_conf->def.chan->band; + band = chanctx_conf->channel->band; rcu_read_unlock(); return band; @@ -1047,6 +1048,7 @@ struct ieee80211_local { /* Temporary remain-on-channel for off-channel operations */ struct ieee80211_channel *tmp_channel; + enum nl80211_channel_type tmp_channel_type; /* channel contexts */ struct list_head chanctx_list; @@ -1156,7 +1158,8 @@ struct ieee80211_local { /* virtual monitor interface */ struct ieee80211_sub_if_data __rcu *monitor_sdata; - struct cfg80211_chan_def monitor_chandef; + struct ieee80211_channel *monitor_channel; + enum nl80211_channel_type monitor_channel_type; }; static inline struct ieee80211_sub_if_data * @@ -1256,18 +1259,7 @@ static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr) is_broadcast_ether_addr(raddr); } -static inline bool -ieee80211_have_rx_timestamp(struct ieee80211_rx_status *status) -{ - WARN_ON_ONCE(status->flag & RX_FLAG_MACTIME_START && - status->flag & RX_FLAG_MACTIME_END); - return status->flag & (RX_FLAG_MACTIME_START | RX_FLAG_MACTIME_END); -} -u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local, - struct ieee80211_rx_status *status, - unsigned int mpdu_len, - unsigned int mpdu_offset); int ieee80211_hw_config(struct ieee80211_local *local, u32 changed); void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx); void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, @@ -1396,8 +1388,6 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev); netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev); -void ieee80211_purge_tx_queue(struct ieee80211_hw *hw, - struct sk_buff_head *skbs); /* HT */ void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata, @@ -1515,7 +1505,7 @@ static inline void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata, } __ieee80211_tx_skb_tid_band(sdata, skb, tid, - chanctx_conf->def.chan->band); + chanctx_conf->channel->band); rcu_read_unlock(); } @@ -1604,7 +1594,8 @@ size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset); u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, u16 cap); u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, - const struct cfg80211_chan_def *chandef, + struct ieee80211_channel *channel, + enum nl80211_channel_type channel_type, u16 prot_mode); u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, u32 cap); @@ -1616,13 +1607,13 @@ int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata, enum ieee80211_band band); /* channel management */ -void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan, - struct ieee80211_ht_operation *ht_oper, - struct cfg80211_chan_def *chandef); +enum nl80211_channel_type +ieee80211_ht_oper_to_channel_type(struct ieee80211_ht_operation *ht_oper); int __must_check ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata, - const struct cfg80211_chan_def *chandef, + struct ieee80211_channel *channel, + enum nl80211_channel_type channel_type, enum ieee80211_chanctx_mode mode); void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata); diff --git a/trunk/net/mac80211/iface.c b/trunk/net/mac80211/iface.c index 5331662489f7..80ce90b29d9d 100644 --- a/trunk/net/mac80211/iface.c +++ b/trunk/net/mac80211/iface.c @@ -54,7 +54,7 @@ bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata) return false; } - power = chanctx_conf->def.chan->max_power; + power = chanctx_conf->channel->max_power; rcu_read_unlock(); if (sdata->user_power_level != IEEE80211_UNSET_POWER_LEVEL) @@ -415,7 +415,8 @@ static int ieee80211_add_virtual_monitor(struct ieee80211_local *local) goto out_unlock; } - ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef, + ret = ieee80211_vif_use_channel(sdata, local->monitor_channel, + local->monitor_channel_type, IEEE80211_CHANCTX_EXCLUSIVE); if (ret) { drv_remove_interface(local, sdata); diff --git a/trunk/net/mac80211/key.c b/trunk/net/mac80211/key.c index 619c5d697999..d27e61aaa71b 100644 --- a/trunk/net/mac80211/key.c +++ b/trunk/net/mac80211/key.c @@ -339,7 +339,7 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, key->conf.iv_len = TKIP_IV_LEN; key->conf.icv_len = TKIP_ICV_LEN; if (seq) { - for (i = 0; i < IEEE80211_NUM_TIDS; i++) { + for (i = 0; i < NUM_RX_DATA_QUEUES; i++) { key->u.tkip.rx[i].iv32 = get_unaligned_le32(&seq[2]); key->u.tkip.rx[i].iv16 = @@ -352,7 +352,7 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, key->conf.iv_len = CCMP_HDR_LEN; key->conf.icv_len = CCMP_MIC_LEN; if (seq) { - for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) + for (i = 0; i < NUM_RX_DATA_QUEUES + 1; i++) for (j = 0; j < CCMP_PN_LEN; j++) key->u.ccmp.rx_pn[i][j] = seq[CCMP_PN_LEN - j - 1]; @@ -372,9 +372,8 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, key->conf.iv_len = 0; key->conf.icv_len = sizeof(struct ieee80211_mmie); if (seq) - for (j = 0; j < CMAC_PN_LEN; j++) - key->u.aes_cmac.rx_pn[j] = - seq[CMAC_PN_LEN - j - 1]; + for (j = 0; j < 6; j++) + key->u.aes_cmac.rx_pn[j] = seq[6 - j - 1]; /* * Initialize AES key state here as an optimization so that * it does not need to be initialized for every packet. @@ -655,16 +654,16 @@ void ieee80211_get_key_rx_seq(struct ieee80211_key_conf *keyconf, switch (key->conf.cipher) { case WLAN_CIPHER_SUITE_TKIP: - if (WARN_ON(tid < 0 || tid >= IEEE80211_NUM_TIDS)) + if (WARN_ON(tid < 0 || tid >= NUM_RX_DATA_QUEUES)) return; seq->tkip.iv32 = key->u.tkip.rx[tid].iv32; seq->tkip.iv16 = key->u.tkip.rx[tid].iv16; break; case WLAN_CIPHER_SUITE_CCMP: - if (WARN_ON(tid < -1 || tid >= IEEE80211_NUM_TIDS)) + if (WARN_ON(tid < -1 || tid >= NUM_RX_DATA_QUEUES)) return; if (tid < 0) - pn = key->u.ccmp.rx_pn[IEEE80211_NUM_TIDS]; + pn = key->u.ccmp.rx_pn[NUM_RX_DATA_QUEUES]; else pn = key->u.ccmp.rx_pn[tid]; memcpy(seq->ccmp.pn, pn, CCMP_PN_LEN); diff --git a/trunk/net/mac80211/key.h b/trunk/net/mac80211/key.h index 7cff0d3a519c..7d4e31f037d7 100644 --- a/trunk/net/mac80211/key.h +++ b/trunk/net/mac80211/key.h @@ -30,6 +30,8 @@ #define TKIP_ICV_LEN 4 #define CMAC_PN_LEN 6 +#define NUM_RX_DATA_QUEUES 16 + struct ieee80211_local; struct ieee80211_sub_if_data; struct sta_info; @@ -80,17 +82,17 @@ struct ieee80211_key { struct tkip_ctx tx; /* last received RSC */ - struct tkip_ctx rx[IEEE80211_NUM_TIDS]; + struct tkip_ctx rx[NUM_RX_DATA_QUEUES]; } tkip; struct { atomic64_t tx_pn; /* * Last received packet number. The first - * IEEE80211_NUM_TIDS counters are used with Data + * NUM_RX_DATA_QUEUES counters are used with Data * frames and the last counter is used with Robust * Management frames. */ - u8 rx_pn[IEEE80211_NUM_TIDS + 1][CCMP_PN_LEN]; + u8 rx_pn[NUM_RX_DATA_QUEUES + 1][CCMP_PN_LEN]; struct crypto_cipher *tfm; u32 replays; /* dot11RSNAStatsCCMPReplays */ } ccmp; diff --git a/trunk/net/mac80211/main.c b/trunk/net/mac80211/main.c index f5e4c1f24bf2..70e87600cacc 100644 --- a/trunk/net/mac80211/main.c +++ b/trunk/net/mac80211/main.c @@ -115,7 +115,7 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local) channel_type = NL80211_CHAN_NO_HT; } else if (local->tmp_channel) { chan = local->tmp_channel; - channel_type = NL80211_CHAN_NO_HT; + channel_type = local->tmp_channel_type; } else { chan = local->_oper_channel; channel_type = local->_oper_channel_type; @@ -798,9 +798,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) local->_oper_channel = &sband->channels[0]; local->hw.conf.channel_type = NL80211_CHAN_NO_HT; } - cfg80211_chandef_create(&local->monitor_chandef, - &sband->channels[0], - NL80211_CHAN_NO_HT); + if (!local->monitor_channel) { + local->monitor_channel = &sband->channels[0]; + local->monitor_channel_type = NL80211_CHAN_NO_HT; + } channels += sband->n_channels; if (max_bitrates < sband->n_bitrates) @@ -883,22 +884,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) if (supp_ht) local->scan_ies_len += 2 + sizeof(struct ieee80211_ht_cap); - if (supp_vht) { + if (supp_vht) local->scan_ies_len += 2 + sizeof(struct ieee80211_vht_cap); - /* - * (for now at least), drivers wanting to use VHT must - * support channel contexts, as they contain all the - * necessary VHT information and the global hw config - * doesn't (yet) - */ - if (WARN_ON(!local->use_chanctx)) { - result = -EINVAL; - goto fail_wiphy_register; - } - } - if (!local->ops->hw_scan) { /* For hw_scan, driver needs to set these up. */ local->hw.wiphy->max_scan_ssids = 4; @@ -936,10 +925,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) local->hw.wiphy->cipher_suites, sizeof(u32) * local->hw.wiphy->n_cipher_suites, GFP_KERNEL); - if (!suites) { - result = -ENOMEM; - goto fail_wiphy_register; - } + if (!suites) + return -ENOMEM; for (r = 0; r < local->hw.wiphy->n_cipher_suites; r++) { u32 suite = local->hw.wiphy->cipher_suites[r]; if (suite == WLAN_CIPHER_SUITE_WEP40 || diff --git a/trunk/net/mac80211/mesh.c b/trunk/net/mac80211/mesh.c index 1bf03f9ff3ba..a350cab4b339 100644 --- a/trunk/net/mac80211/mesh.c +++ b/trunk/net/mac80211/mesh.c @@ -76,7 +76,7 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct ieee80211_local *local = sdata->local; u32 basic_rates = 0; - struct cfg80211_chan_def sta_chan_def; + enum nl80211_channel_type sta_channel_type = NL80211_CHAN_NO_HT; /* * As support for each feature is added, check for matching @@ -103,11 +103,17 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata, if (sdata->vif.bss_conf.basic_rates != basic_rates) goto mismatch; - ieee80211_ht_oper_to_chandef(sdata->vif.bss_conf.chandef.chan, - ie->ht_operation, &sta_chan_def); - - if (!cfg80211_chandef_compatible(&sdata->vif.bss_conf.chandef, - &sta_chan_def)) + if (ie->ht_operation) + sta_channel_type = + ieee80211_ht_oper_to_channel_type(ie->ht_operation); + + /* Disallow HT40+/- mismatch */ + if (ie->ht_operation && + (sdata->vif.bss_conf.channel_type == NL80211_CHAN_HT40MINUS || + sdata->vif.bss_conf.channel_type == NL80211_CHAN_HT40PLUS) && + (sta_channel_type == NL80211_CHAN_HT40MINUS || + sta_channel_type == NL80211_CHAN_HT40PLUS) && + sdata->vif.bss_conf.channel_type != sta_channel_type) goto mismatch; return true; @@ -123,7 +129,7 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata, bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie) { return (ie->mesh_config->meshconf_cap & - IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS) != 0; + MESHCONF_CAPAB_ACCEPT_PLINKS) != 0; } /** @@ -263,11 +269,11 @@ mesh_add_meshconf_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) neighbors = (neighbors > 15) ? 15 : neighbors; *pos++ = neighbors << 1; /* Mesh capability */ - *pos = IEEE80211_MESHCONF_CAPAB_FORWARDING; + *pos = MESHCONF_CAPAB_FORWARDING; *pos |= ifmsh->accepting_plinks ? - IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; + MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; *pos++ |= ifmsh->adjusting_tbtt ? - IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING : 0x00; + MESHCONF_CAPAB_TBTT_ADJUSTING : 0x00; *pos++ = 0x00; return 0; @@ -362,7 +368,7 @@ int mesh_add_ds_params_ie(struct sk_buff *skb, rcu_read_unlock(); return -EINVAL; } - chan = chanctx_conf->def.chan; + chan = chanctx_conf->channel; rcu_read_unlock(); sband = local->hw.wiphy->bands[chan->band]; @@ -386,7 +392,7 @@ int mesh_add_ht_cap_ie(struct sk_buff *skb, sband = local->hw.wiphy->bands[band]; if (!sband->ht_cap.ht_supported || - sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT) + sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) return 0; if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_cap)) @@ -405,7 +411,7 @@ int mesh_add_ht_oper_ie(struct sk_buff *skb, struct ieee80211_chanctx_conf *chanctx_conf; struct ieee80211_channel *channel; enum nl80211_channel_type channel_type = - cfg80211_get_chandef_type(&sdata->vif.bss_conf.chandef); + sdata->vif.bss_conf.channel_type; struct ieee80211_supported_band *sband; struct ieee80211_sta_ht_cap *ht_cap; u8 *pos; @@ -416,7 +422,7 @@ int mesh_add_ht_oper_ie(struct sk_buff *skb, rcu_read_unlock(); return -EINVAL; } - channel = chanctx_conf->def.chan; + channel = chanctx_conf->channel; rcu_read_unlock(); sband = local->hw.wiphy->bands[channel->band]; @@ -429,7 +435,7 @@ int mesh_add_ht_oper_ie(struct sk_buff *skb, return -ENOMEM; pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_operation)); - ieee80211_ie_build_ht_oper(pos, ht_cap, &sdata->vif.bss_conf.chandef, + ieee80211_ie_build_ht_oper(pos, ht_cap, channel, channel_type, sdata->vif.bss_conf.ht_operation_mode); return 0; diff --git a/trunk/net/mac80211/mesh.h b/trunk/net/mac80211/mesh.h index 7c9215fb2ac8..9285f3f67e66 100644 --- a/trunk/net/mac80211/mesh.h +++ b/trunk/net/mac80211/mesh.h @@ -18,6 +18,20 @@ /* Data structures */ +/** + * enum mesh_config_capab_flags - mesh config IE capability flags + * + * @MESHCONF_CAPAB_ACCEPT_PLINKS: STA is willing to establish + * additional mesh peerings with other mesh STAs + * @MESHCONF_CAPAB_FORWARDING: the STA forwards MSDUs + * @MESHCONF_CAPAB_TBTT_ADJUSTING: TBTT adjustment procedure is ongoing + */ +enum mesh_config_capab_flags { + MESHCONF_CAPAB_ACCEPT_PLINKS = BIT(0), + MESHCONF_CAPAB_FORWARDING = BIT(3), + MESHCONF_CAPAB_TBTT_ADJUSTING = BIT(5), +}; + /** * enum mesh_path_flags - mac80211 mesh path flags * diff --git a/trunk/net/mac80211/mesh_plink.c b/trunk/net/mac80211/mesh_plink.c index ca52dfdd5375..234fe755968b 100644 --- a/trunk/net/mac80211/mesh_plink.c +++ b/trunk/net/mac80211/mesh_plink.c @@ -19,6 +19,12 @@ #define mod_plink_timer(s, t) (mod_timer(&s->plink_timer, \ jiffies + HZ * t / 1000)) +#define dot11MeshMaxRetries(s) (s->u.mesh.mshcfg.dot11MeshMaxRetries) +#define dot11MeshRetryTimeout(s) (s->u.mesh.mshcfg.dot11MeshRetryTimeout) +#define dot11MeshConfirmTimeout(s) (s->u.mesh.mshcfg.dot11MeshConfirmTimeout) +#define dot11MeshHoldingTimeout(s) (s->u.mesh.mshcfg.dot11MeshHoldingTimeout) +#define dot11MeshMaxPeerLinks(s) (s->u.mesh.mshcfg.dot11MeshMaxPeerLinks) + /* We only need a valid sta if user configured a minimum rssi_threshold. */ #define rssi_threshold_check(sta, sdata) \ (sdata->u.mesh.mshcfg.rssi_threshold == 0 ||\ @@ -111,7 +117,7 @@ static u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata) u16 ht_opmode; bool non_ht_sta = false, ht20_sta = false; - if (sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT) + if (sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) return 0; rcu_read_lock(); @@ -120,14 +126,14 @@ static u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata) sta->plink_state != NL80211_PLINK_ESTAB) continue; - switch (sta->ch_width) { - case NL80211_CHAN_WIDTH_20_NOHT: + switch (sta->ch_type) { + case NL80211_CHAN_NO_HT: mpl_dbg(sdata, "mesh_plink %pM: nonHT sta (%pM) is present\n", sdata->vif.addr, sta->sta.addr); non_ht_sta = true; goto out; - case NL80211_CHAN_WIDTH_20: + case NL80211_CHAN_HT20: mpl_dbg(sdata, "mesh_plink %pM: HT20 sta (%pM) is present\n", sdata->vif.addr, sta->sta.addr); @@ -142,7 +148,7 @@ static u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata) if (non_ht_sta) ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED; else if (ht20_sta && - sdata->vif.bss_conf.chandef.width > NL80211_CHAN_WIDTH_20) + sdata->vif.bss_conf.channel_type > NL80211_CHAN_HT20) ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_20MHZ; else ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONE; @@ -372,7 +378,7 @@ static struct sta_info *mesh_peer_init(struct ieee80211_sub_if_data *sdata, sta->sta.supp_rates[band] = rates; if (elems->ht_cap_elem && - sdata->vif.bss_conf.chandef.width != NL80211_CHAN_WIDTH_20_NOHT) + sdata->vif.bss_conf.channel_type != NL80211_CHAN_NO_HT) ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, elems->ht_cap_elem, &sta->sta.ht_cap); @@ -380,15 +386,12 @@ static struct sta_info *mesh_peer_init(struct ieee80211_sub_if_data *sdata, memset(&sta->sta.ht_cap, 0, sizeof(sta->sta.ht_cap)); if (elems->ht_operation) { - struct cfg80211_chan_def chandef; - if (!(elems->ht_operation->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) sta->sta.ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; - ieee80211_ht_oper_to_chandef(sdata->vif.bss_conf.chandef.chan, - elems->ht_operation, &chandef); - sta->ch_width = chandef.width; + sta->ch_type = + ieee80211_ht_oper_to_channel_type(elems->ht_operation); } rate_control_rate_init(sta); @@ -427,7 +430,6 @@ static void mesh_plink_timer(unsigned long data) struct sta_info *sta; __le16 llid, plid, reason; struct ieee80211_sub_if_data *sdata; - struct mesh_config *mshcfg; /* * This STA is valid because sta_info_destroy() will @@ -454,13 +456,12 @@ static void mesh_plink_timer(unsigned long data) llid = sta->llid; plid = sta->plid; sdata = sta->sdata; - mshcfg = &sdata->u.mesh.mshcfg; switch (sta->plink_state) { case NL80211_PLINK_OPN_RCVD: case NL80211_PLINK_OPN_SNT: /* retry timer */ - if (sta->plink_retries < mshcfg->dot11MeshMaxRetries) { + if (sta->plink_retries < dot11MeshMaxRetries(sdata)) { u32 rand; mpl_dbg(sta->sdata, "Mesh plink for %pM (retry, timeout): %d %d\n", @@ -483,7 +484,7 @@ static void mesh_plink_timer(unsigned long data) if (!reason) reason = cpu_to_le16(WLAN_REASON_MESH_CONFIRM_TIMEOUT); sta->plink_state = NL80211_PLINK_HOLDING; - mod_plink_timer(sta, mshcfg->dot11MeshHoldingTimeout); + mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); spin_unlock_bh(&sta->lock); mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, sta->sta.addr, llid, plid, reason); @@ -542,7 +543,7 @@ int mesh_plink_open(struct sta_info *sta) return -EBUSY; } sta->plink_state = NL80211_PLINK_OPN_SNT; - mesh_plink_timer_set(sta, sdata->u.mesh.mshcfg.dot11MeshRetryTimeout); + mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata)); spin_unlock_bh(&sta->lock); mpl_dbg(sdata, "Mesh plink: starting establishment with %pM\n", @@ -569,7 +570,6 @@ void mesh_plink_block(struct sta_info *sta) void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len, struct ieee80211_rx_status *rx_status) { - struct mesh_config *mshcfg = &sdata->u.mesh.mshcfg; struct ieee802_11_elems elems; struct sta_info *sta; enum plink_event event; @@ -777,8 +777,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m sta->plid = plid; get_random_bytes(&llid, 2); sta->llid = llid; - mesh_plink_timer_set(sta, - mshcfg->dot11MeshRetryTimeout); + mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata)); spin_unlock_bh(&sta->lock); mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN, @@ -804,7 +803,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m sta->reason = reason; sta->plink_state = NL80211_PLINK_HOLDING; if (!mod_plink_timer(sta, - mshcfg->dot11MeshHoldingTimeout)) + dot11MeshHoldingTimeout(sdata))) sta->ignore_plink_timer = true; llid = sta->llid; @@ -826,7 +825,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m case CNF_ACPT: sta->plink_state = NL80211_PLINK_CNF_RCVD; if (!mod_plink_timer(sta, - mshcfg->dot11MeshConfirmTimeout)) + dot11MeshConfirmTimeout(sdata))) sta->ignore_plink_timer = true; spin_unlock_bh(&sta->lock); @@ -848,7 +847,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m sta->reason = reason; sta->plink_state = NL80211_PLINK_HOLDING; if (!mod_plink_timer(sta, - mshcfg->dot11MeshHoldingTimeout)) + dot11MeshHoldingTimeout(sdata))) sta->ignore_plink_timer = true; llid = sta->llid; @@ -889,7 +888,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m sta->reason = reason; sta->plink_state = NL80211_PLINK_HOLDING; if (!mod_plink_timer(sta, - mshcfg->dot11MeshHoldingTimeout)) + dot11MeshHoldingTimeout(sdata))) sta->ignore_plink_timer = true; llid = sta->llid; @@ -924,7 +923,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m changed |= __mesh_plink_deactivate(sta); sta->plink_state = NL80211_PLINK_HOLDING; llid = sta->llid; - mod_plink_timer(sta, mshcfg->dot11MeshHoldingTimeout); + mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); spin_unlock_bh(&sta->lock); changed |= mesh_set_ht_prot_mode(sdata); mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, diff --git a/trunk/net/mac80211/mesh_sync.c b/trunk/net/mac80211/mesh_sync.c index 0f40086cce18..407c8705e10d 100644 --- a/trunk/net/mac80211/mesh_sync.c +++ b/trunk/net/mac80211/mesh_sync.c @@ -43,7 +43,7 @@ struct sync_method { static bool mesh_peer_tbtt_adjusting(struct ieee802_11_elems *ie) { return (ie->mesh_config->meshconf_cap & - IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING) != 0; + MESHCONF_CAPAB_TBTT_ADJUSTING) != 0; } void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata) @@ -116,13 +116,43 @@ static void mesh_sync_offset_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, goto no_sync; } - if (ieee80211_have_rx_timestamp(rx_status)) - /* time when timestamp field was received */ - t_r = ieee80211_calculate_rx_timestamp(local, rx_status, - 24 + 12 + - elems->total_len + - FCS_LEN, - 24); + if (rx_status->flag & RX_FLAG_MACTIME_MPDU && rx_status->mactime) { + /* + * The mactime is defined as the time the first data symbol + * of the frame hits the PHY, and the timestamp of the beacon + * is defined as "the time that the data symbol containing the + * first bit of the timestamp is transmitted to the PHY plus + * the transmitting STA's delays through its local PHY from the + * MAC-PHY interface to its interface with the WM" (802.11 + * 11.1.2) + * + * T_r, in 13.13.2.2.2, is just defined as "the frame reception + * time" but we unless we interpret that time to be the same + * time of the beacon timestamp, the offset calculation will be + * off. Below we adjust t_r to be "the time at which the first + * symbol of the timestamp element in the beacon is received". + * This correction depends on the rate. + * + * Based on similar code in ibss.c + */ + int rate; + + if (rx_status->flag & RX_FLAG_HT) { + /* TODO: + * In principle there could be HT-beacons (Dual Beacon + * HT Operation options), but for now ignore them and + * just use the primary (i.e. non-HT) beacons for + * synchronization. + * */ + goto no_sync; + } else + rate = local->hw.wiphy->bands[rx_status->band]-> + bitrates[rx_status->rate_idx].bitrate; + + /* 24 bytes of header * 8 bits/byte * + * 10*(100 Kbps)/Mbps / rate (100 Kbps)*/ + t_r = rx_status->mactime + (24 * 8 * 10 / rate); + } /* Timing offset calculation (see 13.13.2.2.2) */ t_t = le64_to_cpu(mgmt->u.beacon.timestamp); diff --git a/trunk/net/mac80211/mlme.c b/trunk/net/mac80211/mlme.c index d2a4f78b4b0f..61614461e089 100644 --- a/trunk/net/mac80211/mlme.c +++ b/trunk/net/mac80211/mlme.c @@ -191,19 +191,17 @@ static u32 ieee80211_config_ht_tx(struct ieee80211_sub_if_data *sdata, rcu_read_unlock(); return 0; } - chan = chanctx_conf->def.chan; + chan = chanctx_conf->channel; rcu_read_unlock(); sband = local->hw.wiphy->bands[chan->band]; - switch (sdata->vif.bss_conf.chandef.width) { - case NL80211_CHAN_WIDTH_40: - if (sdata->vif.bss_conf.chandef.chan->center_freq > - sdata->vif.bss_conf.chandef.center_freq1 && - chan->flags & IEEE80211_CHAN_NO_HT40PLUS) + switch (sdata->vif.bss_conf.channel_type) { + case NL80211_CHAN_HT40PLUS: + if (chan->flags & IEEE80211_CHAN_NO_HT40PLUS) disable_40 = true; - if (sdata->vif.bss_conf.chandef.chan->center_freq < - sdata->vif.bss_conf.chandef.center_freq1 && - chan->flags & IEEE80211_CHAN_NO_HT40MINUS) + break; + case NL80211_CHAN_HT40MINUS: + if (chan->flags & IEEE80211_CHAN_NO_HT40MINUS) disable_40 = true; break; default: @@ -383,7 +381,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) rcu_read_unlock(); return; } - chan = chanctx_conf->def.chan; + chan = chanctx_conf->channel; rcu_read_unlock(); sband = local->hw.wiphy->bands[chan->band]; @@ -543,7 +541,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) offset = noffset; } - if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) + if (!(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) ieee80211_add_ht_ie(sdata, skb, assoc_data->ap_ht_param, sband, chan, sdata->smps_mode); @@ -1530,6 +1528,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); + ieee80211_vif_release_channel(sdata); + /* disassociated - set to defaults now */ ieee80211_set_wmm_default(sdata, false); @@ -1539,9 +1539,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, del_timer_sync(&sdata->u.mgd.chswitch_timer); sdata->u.mgd.timers_running = 0; - - ifmgd->flags = 0; - ieee80211_vif_release_channel(sdata); } void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, @@ -1867,7 +1864,6 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata, memset(sdata->u.mgd.bssid, 0, ETH_ALEN); ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); - sdata->u.mgd.flags = 0; ieee80211_vif_release_channel(sdata); } @@ -2110,7 +2106,6 @@ static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata, memset(sdata->u.mgd.bssid, 0, ETH_ALEN); ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); - sdata->u.mgd.flags = 0; ieee80211_vif_release_channel(sdata); } @@ -2175,7 +2170,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, sband = local->hw.wiphy->bands[ieee80211_get_sdata_band(sdata)]; - if (elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) + if (elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, elems.ht_cap_elem, &sta->sta.ht_cap); @@ -2227,7 +2222,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, changed |= BSS_CHANGED_QOS; if (elems.ht_operation && elems.wmm_param && - !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) + !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) changed |= ieee80211_config_ht_tx(sdata, elems.ht_operation, cbss->bssid, false); @@ -2478,11 +2473,11 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, return; } - if (rx_status->freq != chanctx_conf->def.chan->center_freq) { + if (rx_status->freq != chanctx_conf->channel->center_freq) { rcu_read_unlock(); return; } - chan = chanctx_conf->def.chan; + chan = chanctx_conf->channel; rcu_read_unlock(); if (ifmgd->assoc_data && !ifmgd->assoc_data->have_beacon && @@ -2663,7 +2658,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, if (elems.ht_cap_elem && elems.ht_operation && elems.wmm_param && - !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) + !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) changed |= ieee80211_config_ht_tx(sdata, elems.ht_operation, bssid, true); @@ -3193,7 +3188,6 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, const u8 *ht_oper_ie; const struct ieee80211_ht_operation *ht_oper = NULL; struct ieee80211_supported_band *sband; - struct cfg80211_chan_def chandef; sband = local->hw.wiphy->bands[cbss->channel->band]; @@ -3225,10 +3219,12 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, ht_cfreq, ht_oper->primary_chan, cbss->channel->band); ht_oper = NULL; + } else { + channel_type = NL80211_CHAN_HT20; } } - if (ht_oper) { + if (ht_oper && sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { /* * cfg80211 already verified that the channel itself can * be used, but it didn't check that we can do the right @@ -3241,26 +3237,19 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, channel_type = NL80211_CHAN_HT20; - if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { - switch (ht_oper->ht_param & - IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { - case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: - if (cbss->channel->flags & - IEEE80211_CHAN_NO_HT40PLUS) - ifmgd->flags |= - IEEE80211_STA_DISABLE_40MHZ; - else - channel_type = NL80211_CHAN_HT40PLUS; - break; - case IEEE80211_HT_PARAM_CHA_SEC_BELOW: - if (cbss->channel->flags & - IEEE80211_CHAN_NO_HT40MINUS) - ifmgd->flags |= - IEEE80211_STA_DISABLE_40MHZ; - else - channel_type = NL80211_CHAN_HT40MINUS; - break; - } + switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { + case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: + if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40PLUS) + ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; + else + channel_type = NL80211_CHAN_HT40PLUS; + break; + case IEEE80211_HT_PARAM_CHA_SEC_BELOW: + if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40MINUS) + ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; + else + channel_type = NL80211_CHAN_HT40MINUS; + break; } ht_cap_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, @@ -3273,15 +3262,13 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, sdata->needed_rx_chains = min(chains, local->rx_chains); } else { sdata->needed_rx_chains = 1; - sdata->u.mgd.flags |= IEEE80211_STA_DISABLE_HT; } /* will change later if needed */ sdata->smps_mode = IEEE80211_SMPS_OFF; ieee80211_vif_release_channel(sdata); - cfg80211_chandef_create(&chandef, cbss->channel, channel_type); - return ieee80211_vif_use_channel(sdata, &chandef, + return ieee80211_vif_use_channel(sdata, cbss->channel, channel_type, IEEE80211_CHANCTX_SHARED); } @@ -3543,6 +3530,13 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, /* prepare assoc data */ + /* + * keep only the 40 MHz disable bit set as it might have + * been set during authentication already, all other bits + * should be reset for a new connection + */ + ifmgd->flags &= IEEE80211_STA_DISABLE_40MHZ; + ifmgd->beacon_crc_valid = false; /* @@ -3556,7 +3550,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 || req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP || req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) { - ifmgd->flags |= IEEE80211_STA_DISABLE_HT; + ifmgd->flags |= IEEE80211_STA_DISABLE_11N; ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; netdev_info(sdata->dev, "disabling HT/VHT due to WEP/TKIP use\n"); @@ -3564,7 +3558,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, } if (req->flags & ASSOC_REQ_DISABLE_HT) { - ifmgd->flags |= IEEE80211_STA_DISABLE_HT; + ifmgd->flags |= IEEE80211_STA_DISABLE_11N; ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; } @@ -3572,7 +3566,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, sband = local->hw.wiphy->bands[req->bss->channel->band]; if (!sband->ht_cap.ht_supported || local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used) { - ifmgd->flags |= IEEE80211_STA_DISABLE_HT; + ifmgd->flags |= IEEE80211_STA_DISABLE_11N; if (!bss->wmm_used) netdev_info(sdata->dev, "disabling HT as WMM/QoS is not supported by the AP\n"); @@ -3617,7 +3611,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, assoc_data->ap_ht_param = ((struct ieee80211_ht_operation *)(ht_ie + 2))->ht_param; else - ifmgd->flags |= IEEE80211_STA_DISABLE_HT; + ifmgd->flags |= IEEE80211_STA_DISABLE_11N; if (bss->wmm_used && bss->uapsd_supported && (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) { diff --git a/trunk/net/mac80211/offchannel.c b/trunk/net/mac80211/offchannel.c index 5abddfe3e101..0cd42d52880c 100644 --- a/trunk/net/mac80211/offchannel.c +++ b/trunk/net/mac80211/offchannel.c @@ -205,8 +205,8 @@ void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc) } } else { cfg80211_ready_on_channel(&roc->sdata->wdev, roc->cookie, - roc->chan, roc->req_duration, - GFP_KERNEL); + roc->chan, roc->chan_type, + roc->req_duration, GFP_KERNEL); } roc->notified = true; @@ -283,7 +283,8 @@ void ieee80211_start_next_roc(struct ieee80211_local *local) if (!duration) duration = 10; - ret = drv_remain_on_channel(local, roc->sdata, roc->chan, + ret = drv_remain_on_channel(local, roc->chan, + roc->chan_type, duration); roc->started = true; @@ -320,7 +321,7 @@ void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc) if (!roc->mgmt_tx_cookie) cfg80211_remain_on_channel_expired(&roc->sdata->wdev, roc->cookie, roc->chan, - GFP_KERNEL); + roc->chan_type, GFP_KERNEL); list_for_each_entry_safe(dep, tmp, &roc->dependents, list) ieee80211_roc_notify_destroy(dep); @@ -358,6 +359,7 @@ void ieee80211_sw_roc_work(struct work_struct *work) ieee80211_recalc_idle(local); local->tmp_channel = roc->chan; + local->tmp_channel_type = roc->chan_type; ieee80211_hw_config(local, 0); /* tell userspace or send frame */ diff --git a/trunk/net/mac80211/pm.c b/trunk/net/mac80211/pm.c index 79a48f37d409..0f1c434638bc 100644 --- a/trunk/net/mac80211/pm.c +++ b/trunk/net/mac80211/pm.c @@ -33,7 +33,6 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_sub_if_data *sdata; struct sta_info *sta; - struct ieee80211_chanctx *ctx; if (!local->open_count) goto suspend; @@ -140,51 +139,14 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) rcu_access_pointer(sdata->u.ap.beacon)) drv_stop_ap(local, sdata); - if (local->use_chanctx) { - struct ieee80211_chanctx_conf *conf; - - mutex_lock(&local->chanctx_mtx); - conf = rcu_dereference_protected( - sdata->vif.chanctx_conf, - lockdep_is_held(&local->chanctx_mtx)); - if (conf) { - ctx = container_of(conf, - struct ieee80211_chanctx, - conf); - drv_unassign_vif_chanctx(local, sdata, ctx); - } - - mutex_unlock(&local->chanctx_mtx); - } + /* the interface is leaving the channel and is removed */ + ieee80211_vif_release_channel(sdata); drv_remove_interface(local, sdata); } sdata = rtnl_dereference(local->monitor_sdata); - if (sdata) { - if (local->use_chanctx) { - struct ieee80211_chanctx_conf *conf; - - mutex_lock(&local->chanctx_mtx); - conf = rcu_dereference_protected( - sdata->vif.chanctx_conf, - lockdep_is_held(&local->chanctx_mtx)); - if (conf) { - ctx = container_of(conf, - struct ieee80211_chanctx, - conf); - drv_unassign_vif_chanctx(local, sdata, ctx); - } - - mutex_unlock(&local->chanctx_mtx); - } - + if (sdata) drv_remove_interface(local, sdata); - } - - mutex_lock(&local->chanctx_mtx); - list_for_each_entry(ctx, &local->chanctx_list, list) - drv_remove_chanctx(local, ctx); - mutex_unlock(&local->chanctx_mtx); /* stop hardware - this must stop RX */ if (local->open_count) diff --git a/trunk/net/mac80211/rate.c b/trunk/net/mac80211/rate.c index dd88381c53b7..3313c117b322 100644 --- a/trunk/net/mac80211/rate.c +++ b/trunk/net/mac80211/rate.c @@ -391,7 +391,7 @@ static void rate_idx_match_mask(struct ieee80211_tx_rate *rate, return; /* if HT BSS, and we handle a data frame, also try HT rates */ - if (txrc->bss_conf->chandef.width == NL80211_CHAN_WIDTH_20_NOHT) + if (txrc->bss_conf->channel_type == NL80211_CHAN_NO_HT) return; fc = hdr->frame_control; @@ -408,7 +408,8 @@ static void rate_idx_match_mask(struct ieee80211_tx_rate *rate, alt_rate.flags |= IEEE80211_TX_RC_MCS; - if (txrc->bss_conf->chandef.width == NL80211_CHAN_WIDTH_40) + if ((txrc->bss_conf->channel_type == NL80211_CHAN_HT40MINUS) || + (txrc->bss_conf->channel_type == NL80211_CHAN_HT40PLUS)) alt_rate.flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; if (rate_idx_match_mcs_mask(&alt_rate, mcs_mask)) { diff --git a/trunk/net/mac80211/rate.h b/trunk/net/mac80211/rate.h index 301386dabf88..ec198ef6aa8a 100644 --- a/trunk/net/mac80211/rate.h +++ b/trunk/net/mac80211/rate.h @@ -65,7 +65,7 @@ static inline void rate_control_rate_init(struct sta_info *sta) return; } - sband = local->hw.wiphy->bands[chanctx_conf->def.chan->band]; + sband = local->hw.wiphy->bands[chanctx_conf->channel->band]; rcu_read_unlock(); ref->ops->rate_init(ref->priv, sband, ista, priv_sta); diff --git a/trunk/net/mac80211/rx.c b/trunk/net/mac80211/rx.c index 825f33cf7bbc..6ad330341b71 100644 --- a/trunk/net/mac80211/rx.c +++ b/trunk/net/mac80211/rx.c @@ -40,8 +40,6 @@ static struct sk_buff *remove_monitor_info(struct ieee80211_local *local, struct sk_buff *skb) { - struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); - if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) { if (likely(skb->len > FCS_LEN)) __pskb_trim(skb, skb->len - FCS_LEN); @@ -53,25 +51,19 @@ static struct sk_buff *remove_monitor_info(struct ieee80211_local *local, } } - if (status->vendor_radiotap_len) - __pskb_pull(skb, status->vendor_radiotap_len); - return skb; } static inline int should_drop_frame(struct sk_buff *skb, int present_fcs_len) { struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); - struct ieee80211_hdr *hdr; - - hdr = (void *)(skb->data + status->vendor_radiotap_len); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC | RX_FLAG_AMPDU_IS_ZEROLEN)) return 1; - if (unlikely(skb->len < 16 + present_fcs_len + - status->vendor_radiotap_len)) + if (unlikely(skb->len < 16 + present_fcs_len)) return 1; if (ieee80211_is_ctl(hdr->frame_control) && !ieee80211_is_pspoll(hdr->frame_control) && @@ -81,48 +73,32 @@ static inline int should_drop_frame(struct sk_buff *skb, int present_fcs_len) } static int -ieee80211_rx_radiotap_space(struct ieee80211_local *local, - struct ieee80211_rx_status *status) +ieee80211_rx_radiotap_len(struct ieee80211_local *local, + struct ieee80211_rx_status *status) { int len; /* always present fields */ len = sizeof(struct ieee80211_radiotap_header) + 9; - /* allocate extra bitmap */ - if (status->vendor_radiotap_len) - len += 4; - - if (ieee80211_have_rx_timestamp(status)) { - len = ALIGN(len, 8); + if (status->flag & RX_FLAG_MACTIME_MPDU) len += 8; - } if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) len += 1; - /* padding for RX_FLAGS if necessary */ - len = ALIGN(len, 2); + if (len & 1) /* padding for RX_FLAGS if necessary */ + len++; if (status->flag & RX_FLAG_HT) /* HT info */ len += 3; if (status->flag & RX_FLAG_AMPDU_DETAILS) { - len = ALIGN(len, 4); + /* padding */ + while (len & 3) + len++; len += 8; } - if (status->vendor_radiotap_len) { - if (WARN_ON_ONCE(status->vendor_radiotap_align == 0)) - status->vendor_radiotap_align = 1; - /* align standard part of vendor namespace */ - len = ALIGN(len, 2); - /* allocate standard part of vendor namespace */ - len += 6; - /* align vendor-defined part */ - len = ALIGN(len, status->vendor_radiotap_align); - /* vendor-defined part is already in skb */ - } - return len; } @@ -141,11 +117,6 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, struct ieee80211_radiotap_header *rthdr; unsigned char *pos; u16 rx_flags = 0; - int mpdulen; - - mpdulen = skb->len; - if (!(has_fcs && (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS))) - mpdulen += FCS_LEN; rthdr = (struct ieee80211_radiotap_header *)skb_push(skb, rtap_len); memset(rthdr, 0, rtap_len); @@ -156,29 +127,15 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, (1 << IEEE80211_RADIOTAP_CHANNEL) | (1 << IEEE80211_RADIOTAP_ANTENNA) | (1 << IEEE80211_RADIOTAP_RX_FLAGS)); - rthdr->it_len = cpu_to_le16(rtap_len + status->vendor_radiotap_len); + rthdr->it_len = cpu_to_le16(rtap_len); pos = (unsigned char *)(rthdr + 1); - if (status->vendor_radiotap_len) { - rthdr->it_present |= - cpu_to_le32(BIT(IEEE80211_RADIOTAP_VENDOR_NAMESPACE)) | - cpu_to_le32(BIT(IEEE80211_RADIOTAP_EXT)); - put_unaligned_le32(status->vendor_radiotap_bitmap, pos); - pos += 4; - } - /* the order of the following fields is important */ /* IEEE80211_RADIOTAP_TSFT */ - if (ieee80211_have_rx_timestamp(status)) { - /* padding */ - while ((pos - (u8 *)rthdr) & 7) - *pos++ = 0; - put_unaligned_le64( - ieee80211_calculate_rx_timestamp(local, status, - mpdulen, 0), - pos); + if (status->flag & RX_FLAG_MACTIME_MPDU) { + put_unaligned_le64(status->mactime, pos); rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_TSFT); pos += 8; } @@ -193,7 +150,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, pos++; /* IEEE80211_RADIOTAP_RATE */ - if (!rate || status->flag & (RX_FLAG_HT | RX_FLAG_VHT)) { + if (!rate || status->flag & RX_FLAG_HT) { /* * Without rate information don't add it. If we have, * MCS information is a separate field in radiotap, @@ -213,7 +170,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, if (status->band == IEEE80211_BAND_5GHZ) put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ, pos); - else if (status->flag & (RX_FLAG_HT | RX_FLAG_VHT)) + else if (status->flag & RX_FLAG_HT) put_unaligned_le16(IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ, pos); else if (rate && rate->flags & IEEE80211_RATE_ERP_G) @@ -246,7 +203,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, /* IEEE80211_RADIOTAP_RX_FLAGS */ /* ensure 2 byte alignment for the 2 byte field as required */ if ((pos - (u8 *)rthdr) & 1) - *pos++ = 0; + pos++; if (status->flag & RX_FLAG_FAILED_PLCP_CRC) rx_flags |= IEEE80211_RADIOTAP_F_RX_BADPLCP; put_unaligned_le16(rx_flags, pos); @@ -296,21 +253,6 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, *pos++ = 0; *pos++ = 0; } - - if (status->vendor_radiotap_len) { - /* ensure 2 byte alignment for the vendor field as required */ - if ((pos - (u8 *)rthdr) & 1) - *pos++ = 0; - *pos++ = status->vendor_radiotap_oui[0]; - *pos++ = status->vendor_radiotap_oui[1]; - *pos++ = status->vendor_radiotap_oui[2]; - *pos++ = status->vendor_radiotap_subns; - put_unaligned_le16(status->vendor_radiotap_len, pos); - pos += 2; - /* align the actual payload as requested */ - while ((pos - (u8 *)rthdr) & (status->vendor_radiotap_align - 1)) - *pos++ = 0; - } } /* @@ -339,13 +281,13 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, */ /* room for the radiotap header based on driver features */ - needed_headroom = ieee80211_rx_radiotap_space(local, status); + needed_headroom = ieee80211_rx_radiotap_len(local, status); if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) present_fcs_len = FCS_LEN; - /* ensure hdr->frame_control and vendor radiotap data are in skb head */ - if (!pskb_may_pull(origskb, 2 + status->vendor_radiotap_len)) { + /* make sure hdr->frame_control is on the linear part */ + if (!pskb_may_pull(origskb, 2)) { dev_kfree_skb(origskb); return NULL; } @@ -458,10 +400,10 @@ static void ieee80211_parse_qos(struct ieee80211_rx_data *rx) * * We also use that counter for non-QoS STAs. */ - seqno_idx = IEEE80211_NUM_TIDS; + seqno_idx = NUM_RX_DATA_QUEUES; security_idx = 0; if (ieee80211_is_mgmt(hdr->frame_control)) - security_idx = IEEE80211_NUM_TIDS; + security_idx = NUM_RX_DATA_QUEUES; tid = 0; } @@ -1341,22 +1283,17 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) /* * Update last_rx only for IBSS packets which are for the current - * BSSID and for station already AUTHORIZED to avoid keeping the - * current IBSS network alive in cases where other STAs start - * using different BSSID. This will also give the station another - * chance to restart the authentication/authorization in case - * something went wrong the first time. + * BSSID to avoid keeping the current IBSS network alive in cases + * where other STAs start using different BSSID. */ if (rx->sdata->vif.type == NL80211_IFTYPE_ADHOC) { u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len, NL80211_IFTYPE_ADHOC); - if (ether_addr_equal(bssid, rx->sdata->u.ibss.bssid) && - test_sta_flag(sta, WLAN_STA_AUTHORIZED)) { + if (ether_addr_equal(bssid, rx->sdata->u.ibss.bssid)) { sta->last_rx = jiffies; if (ieee80211_is_data(hdr->frame_control)) { sta->last_rx_rate_idx = status->rate_idx; sta->last_rx_rate_flag = status->flag; - sta->last_rx_rate_vht_nss = status->vht_nss; } } } else if (!is_multicast_ether_addr(hdr->addr1)) { @@ -1368,7 +1305,6 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) if (ieee80211_is_data(hdr->frame_control)) { sta->last_rx_rate_idx = status->rate_idx; sta->last_rx_rate_flag = status->flag; - sta->last_rx_rate_vht_nss = status->vht_nss; } } @@ -2649,7 +2585,7 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx, goto out_free_skb; /* room for the radiotap header based on driver features */ - needed_headroom = ieee80211_rx_radiotap_space(local, status); + needed_headroom = ieee80211_rx_radiotap_len(local, status); if (skb_headroom(skb) < needed_headroom && pskb_expand_head(skb, needed_headroom, 0, GFP_ATOMIC)) @@ -2712,8 +2648,7 @@ static void ieee80211_rx_handlers_result(struct ieee80211_rx_data *rx, status = IEEE80211_SKB_RXCB((rx->skb)); sband = rx->local->hw.wiphy->bands[status->band]; - if (!(status->flag & RX_FLAG_HT) && - !(status->flag & RX_FLAG_VHT)) + if (!(status->flag & RX_FLAG_HT)) rate = &sband->bitrates[status->rate_idx]; ieee80211_rx_cooked_monitor(rx, rate); @@ -2880,8 +2815,8 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx, status->rx_flags &= ~IEEE80211_RX_RA_MATCH; } else if (!rx->sta) { int rate_idx; - if (status->flag & (RX_FLAG_HT | RX_FLAG_VHT)) - rate_idx = 0; /* TODO: HT/VHT rates */ + if (status->flag & RX_FLAG_HT) + rate_idx = 0; /* TODO: HT rates */ else rate_idx = status->rate_idx; ieee80211_ibss_rx_no_sta(sdata, bssid, hdr->addr2, @@ -3157,13 +3092,6 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb) status->rate_idx, status->rate_idx)) goto drop; - } else if (status->flag & RX_FLAG_VHT) { - if (WARN_ONCE(status->rate_idx > 9 || - !status->vht_nss || - status->vht_nss > 8, - "Rate marked as a VHT rate but data is invalid: MCS: %d, NSS: %d\n", - status->rate_idx, status->vht_nss)) - goto drop; } else { if (WARN_ON(status->rate_idx >= sband->n_bitrates)) goto drop; diff --git a/trunk/net/mac80211/scan.c b/trunk/net/mac80211/scan.c index f3340279aba3..13d23299e696 100644 --- a/trunk/net/mac80211/scan.c +++ b/trunk/net/mac80211/scan.c @@ -174,6 +174,7 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb) u8 *elements; struct ieee80211_channel *channel; size_t baselen; + int freq; bool beacon; struct ieee802_11_elems elems; @@ -208,7 +209,13 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb) ieee802_11_parse_elems(elements, skb->len - baselen, &elems); - channel = ieee80211_get_channel(local->hw.wiphy, rx_status->freq); + if (elems.ds_params && elems.ds_params_len == 1) + freq = ieee80211_channel_to_frequency(elems.ds_params[0], + rx_status->band); + else + freq = rx_status->freq; + + channel = ieee80211_get_channel(local->hw.wiphy, freq); if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) return; @@ -927,7 +934,7 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, struct cfg80211_sched_scan_request *req) { struct ieee80211_local *local = sdata->local; - struct ieee80211_sched_scan_ies sched_scan_ies = {}; + struct ieee80211_sched_scan_ies sched_scan_ies; int ret, i; mutex_lock(&local->mtx); diff --git a/trunk/net/mac80211/sta_info.c b/trunk/net/mac80211/sta_info.c index f3e502502fee..f7bb54f9ab72 100644 --- a/trunk/net/mac80211/sta_info.c +++ b/trunk/net/mac80211/sta_info.c @@ -122,8 +122,8 @@ static void free_sta_work(struct work_struct *wk) for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { local->total_ps_buffered -= skb_queue_len(&sta->ps_tx_buf[ac]); - ieee80211_purge_tx_queue(&local->hw, &sta->ps_tx_buf[ac]); - ieee80211_purge_tx_queue(&local->hw, &sta->tx_filtered[ac]); + __skb_queue_purge(&sta->ps_tx_buf[ac]); + __skb_queue_purge(&sta->tx_filtered[ac]); } #ifdef CONFIG_MAC80211_MESH @@ -142,11 +142,11 @@ static void free_sta_work(struct work_struct *wk) * drivers have to handle aggregation stop being requested, followed * directly by station destruction. */ - for (i = 0; i < IEEE80211_NUM_TIDS; i++) { + for (i = 0; i < STA_TID_NUM; i++) { tid_tx = rcu_dereference_raw(sta->ampdu_mlme.tid_tx[i]); if (!tid_tx) continue; - ieee80211_purge_tx_queue(&local->hw, &tid_tx->pending); + __skb_queue_purge(&tid_tx->pending); kfree(tid_tx); } @@ -330,7 +330,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, return NULL; } - for (i = 0; i < IEEE80211_NUM_TIDS; i++) { + for (i = 0; i < STA_TID_NUM; i++) { /* * timer_to_tid must be initialized with identity mapping * to enable session_timer's data differentiation. See @@ -343,7 +343,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, skb_queue_head_init(&sta->tx_filtered[i]); } - for (i = 0; i < IEEE80211_NUM_TIDS; i++) + for (i = 0; i < NUM_RX_DATA_QUEUES; i++) sta->last_seq_ctrl[i] = cpu_to_le16(USHRT_MAX); sta_dbg(sdata, "Allocated STA %pM\n", sta->sta.addr); @@ -982,11 +982,10 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) struct ieee80211_local *local = sdata->local; struct sk_buff_head pending; int filtered = 0, buffered = 0, ac; - unsigned long flags; clear_sta_flag(sta, WLAN_STA_SP); - BUILD_BUG_ON(BITS_TO_LONGS(IEEE80211_NUM_TIDS) > 1); + BUILD_BUG_ON(BITS_TO_LONGS(STA_TID_NUM) > 1); sta->driver_buffered_tids = 0; if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS)) @@ -998,16 +997,12 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { int count = skb_queue_len(&pending), tmp; - spin_lock_irqsave(&sta->tx_filtered[ac].lock, flags); skb_queue_splice_tail_init(&sta->tx_filtered[ac], &pending); - spin_unlock_irqrestore(&sta->tx_filtered[ac].lock, flags); tmp = skb_queue_len(&pending); filtered += tmp - count; count = tmp; - spin_lock_irqsave(&sta->ps_tx_buf[ac].lock, flags); skb_queue_splice_tail_init(&sta->ps_tx_buf[ac], &pending); - spin_unlock_irqrestore(&sta->ps_tx_buf[ac].lock, flags); tmp = skb_queue_len(&pending); buffered += tmp - count; } @@ -1092,7 +1087,7 @@ static void ieee80211_send_null_response(struct ieee80211_sub_if_data *sdata, return; } - ieee80211_xmit(sdata, skb, chanctx_conf->def.chan->band); + ieee80211_xmit(sdata, skb, chanctx_conf->channel->band); rcu_read_unlock(); } @@ -1374,7 +1369,7 @@ void ieee80211_sta_set_buffered(struct ieee80211_sta *pubsta, { struct sta_info *sta = container_of(pubsta, struct sta_info, sta); - if (WARN_ON(tid >= IEEE80211_NUM_TIDS)) + if (WARN_ON(tid >= STA_TID_NUM)) return; if (buffered) diff --git a/trunk/net/mac80211/sta_info.h b/trunk/net/mac80211/sta_info.h index 6835cea4e402..c88f161f8118 100644 --- a/trunk/net/mac80211/sta_info.h +++ b/trunk/net/mac80211/sta_info.h @@ -80,6 +80,7 @@ enum ieee80211_sta_info_flags { WLAN_STA_TOFFSET_KNOWN, }; +#define STA_TID_NUM 16 #define ADDBA_RESP_INTERVAL HZ #define HT_AGG_MAX_RETRIES 15 #define HT_AGG_BURST_RETRIES 3 @@ -196,15 +197,15 @@ struct tid_ampdu_rx { struct sta_ampdu_mlme { struct mutex mtx; /* rx */ - struct tid_ampdu_rx __rcu *tid_rx[IEEE80211_NUM_TIDS]; - unsigned long tid_rx_timer_expired[BITS_TO_LONGS(IEEE80211_NUM_TIDS)]; - unsigned long tid_rx_stop_requested[BITS_TO_LONGS(IEEE80211_NUM_TIDS)]; + struct tid_ampdu_rx __rcu *tid_rx[STA_TID_NUM]; + unsigned long tid_rx_timer_expired[BITS_TO_LONGS(STA_TID_NUM)]; + unsigned long tid_rx_stop_requested[BITS_TO_LONGS(STA_TID_NUM)]; /* tx */ struct work_struct work; - struct tid_ampdu_tx __rcu *tid_tx[IEEE80211_NUM_TIDS]; - struct tid_ampdu_tx *tid_start_tx[IEEE80211_NUM_TIDS]; - unsigned long last_addba_req_time[IEEE80211_NUM_TIDS]; - u8 addba_req_num[IEEE80211_NUM_TIDS]; + struct tid_ampdu_tx __rcu *tid_tx[STA_TID_NUM]; + struct tid_ampdu_tx *tid_start_tx[STA_TID_NUM]; + unsigned long last_addba_req_time[STA_TID_NUM]; + u8 addba_req_num[STA_TID_NUM]; u8 dialog_token_allocator; }; @@ -227,7 +228,6 @@ struct sta_ampdu_mlme { * "the" transmit rate * @last_rx_rate_idx: rx status rate index of the last data packet * @last_rx_rate_flag: rx status flag of the last data packet - * @last_rx_rate_vht_nss: rx status nss of last data packet * @lock: used for locking all fields that require locking, see comments * in the header file. * @drv_unblock_wk: used for driver PS unblocking @@ -273,7 +273,7 @@ struct sta_ampdu_mlme { * @t_offset: timing offset relative to this host * @t_offset_setpoint: reference timing offset of this sta to be used when * calculating clockdrift - * @ch_width: peer's channel width + * @ch_type: peer's channel type * @debugfs: debug filesystem info * @dead: set to true when sta is unlinked * @uploaded: set to true when sta is uploaded to the driver @@ -330,7 +330,7 @@ struct sta_info { int last_signal; struct ewma avg_signal; /* Plus 1 for non-QoS frames */ - __le16 last_seq_ctrl[IEEE80211_NUM_TIDS + 1]; + __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES + 1]; /* Updated from TX status path only, no locking requirements */ unsigned long tx_filtered_count; @@ -344,15 +344,14 @@ struct sta_info { unsigned long tx_fragments; struct ieee80211_tx_rate last_tx_rate; int last_rx_rate_idx; - u32 last_rx_rate_flag; - u8 last_rx_rate_vht_nss; + int last_rx_rate_flag; u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1]; /* * Aggregation information, locked with lock. */ struct sta_ampdu_mlme ampdu_mlme; - u8 timer_to_tid[IEEE80211_NUM_TIDS]; + u8 timer_to_tid[STA_TID_NUM]; #ifdef CONFIG_MAC80211_MESH /* @@ -370,7 +369,7 @@ struct sta_info { struct timer_list plink_timer; s64 t_offset; s64 t_offset_setpoint; - enum nl80211_chan_width ch_width; + enum nl80211_channel_type ch_type; #endif #ifdef CONFIG_MAC80211_DEBUGFS diff --git a/trunk/net/mac80211/status.c b/trunk/net/mac80211/status.c index ab63237107c8..2d931ad0e90a 100644 --- a/trunk/net/mac80211/status.c +++ b/trunk/net/mac80211/status.c @@ -666,12 +666,3 @@ void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb) dev_kfree_skb_any(skb); } EXPORT_SYMBOL(ieee80211_free_txskb); - -void ieee80211_purge_tx_queue(struct ieee80211_hw *hw, - struct sk_buff_head *skbs) -{ - struct sk_buff *skb; - - while ((skb = __skb_dequeue(skbs))) - ieee80211_free_txskb(hw, skb); -} diff --git a/trunk/net/mac80211/trace.h b/trunk/net/mac80211/trace.h index a8270b441a6f..758836c85a80 100644 --- a/trunk/net/mac80211/trace.h +++ b/trunk/net/mac80211/trace.h @@ -28,21 +28,16 @@ #define VIF_PR_FMT " vif:%s(%d%s)" #define VIF_PR_ARG __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : "" -#define CHANCTX_ENTRY __field(u32, control_freq) \ - __field(u32, chan_width) \ - __field(u32, center_freq1) \ - __field(u32, center_freq2) \ +#define CHANCTX_ENTRY __field(int, freq) \ + __field(int, chantype) \ __field(u8, rx_chains_static) \ __field(u8, rx_chains_dynamic) -#define CHANCTX_ASSIGN __entry->control_freq = ctx->conf.def.chan->center_freq;\ - __entry->chan_width = ctx->conf.def.width; \ - __entry->center_freq1 = ctx->conf.def.center_freq1; \ - __entry->center_freq2 = ctx->conf.def.center_freq2; \ +#define CHANCTX_ASSIGN __entry->freq = ctx->conf.channel->center_freq; \ + __entry->chantype = ctx->conf.channel_type; \ __entry->rx_chains_static = ctx->conf.rx_chains_static; \ __entry->rx_chains_dynamic = ctx->conf.rx_chains_dynamic -#define CHANCTX_PR_FMT " control:%d MHz width:%d center: %d/%d MHz chains:%d/%d" -#define CHANCTX_PR_ARG __entry->control_freq, __entry->chan_width, \ - __entry->center_freq1, __entry->center_freq2, \ +#define CHANCTX_PR_FMT " freq:%d MHz chantype:%d chains:%d/%d" +#define CHANCTX_PR_ARG __entry->freq, __entry->chantype, \ __entry->rx_chains_static, __entry->rx_chains_dynamic @@ -339,8 +334,7 @@ TRACE_EVENT(drv_bss_info_changed, __field(u16, ht_operation_mode) __field(s32, cqm_rssi_thold); __field(s32, cqm_rssi_hyst); - __field(u32, channel_width); - __field(u32, channel_cfreq1); + __field(u32, channel_type); __dynamic_array(u32, arp_addr_list, info->arp_addr_cnt); __field(bool, arp_filter_enabled); __field(bool, qos); @@ -376,8 +370,7 @@ TRACE_EVENT(drv_bss_info_changed, __entry->ht_operation_mode = info->ht_operation_mode; __entry->cqm_rssi_thold = info->cqm_rssi_thold; __entry->cqm_rssi_hyst = info->cqm_rssi_hyst; - __entry->channel_width = info->chandef.width; - __entry->channel_cfreq1 = info->chandef.center_freq1; + __entry->channel_type = info->channel_type; memcpy(__get_dynamic_array(arp_addr_list), info->arp_addr_list, sizeof(u32) * info->arp_addr_cnt); __entry->arp_filter_enabled = info->arp_filter_enabled; @@ -1026,31 +1019,28 @@ TRACE_EVENT(drv_get_antenna, ); TRACE_EVENT(drv_remain_on_channel, - TP_PROTO(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata, - struct ieee80211_channel *chan, - unsigned int duration), + TP_PROTO(struct ieee80211_local *local, struct ieee80211_channel *chan, + enum nl80211_channel_type chantype, unsigned int duration), - TP_ARGS(local, sdata, chan, duration), + TP_ARGS(local, chan, chantype, duration), TP_STRUCT__entry( LOCAL_ENTRY - VIF_ENTRY __field(int, center_freq) + __field(int, channel_type) __field(unsigned int, duration) ), TP_fast_assign( LOCAL_ASSIGN; - VIF_ASSIGN; __entry->center_freq = chan->center_freq; + __entry->channel_type = chantype; __entry->duration = duration; ), TP_printk( - LOCAL_PR_FMT VIF_PR_FMT " freq:%dMHz duration:%dms", - LOCAL_PR_ARG, VIF_PR_ARG, - __entry->center_freq, __entry->duration + LOCAL_PR_FMT " freq:%dMHz duration:%dms", + LOCAL_PR_ARG, __entry->center_freq, __entry->duration ) ); diff --git a/trunk/net/mac80211/tx.c b/trunk/net/mac80211/tx.c index d287a4f2c01b..b5468876287e 100644 --- a/trunk/net/mac80211/tx.c +++ b/trunk/net/mac80211/tx.c @@ -1361,7 +1361,7 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx) if (tx->skb) ieee80211_free_txskb(&tx->local->hw, tx->skb); else - ieee80211_purge_tx_queue(&tx->local->hw, &tx->skbs); + __skb_queue_purge(&tx->skbs); return -1; } else if (unlikely(res == TX_QUEUED)) { I802_DEBUG_INC(tx->local->tx_handlers_queued); @@ -1676,7 +1676,7 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, if (!chanctx_conf) goto fail_rcu; - chan = chanctx_conf->def.chan; + chan = chanctx_conf->channel; /* * Frame injection is not allowed if beaconing is not allowed @@ -1779,7 +1779,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, chanctx_conf = rcu_dereference(ap_sdata->vif.chanctx_conf); if (!chanctx_conf) goto fail_rcu; - band = chanctx_conf->def.chan->band; + band = chanctx_conf->channel->band; if (sta) break; /* fall through */ @@ -1794,7 +1794,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); if (!chanctx_conf) goto fail_rcu; - band = chanctx_conf->def.chan->band; + band = chanctx_conf->channel->band; break; case NL80211_IFTYPE_WDS: fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); @@ -1871,7 +1871,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); if (!chanctx_conf) goto fail_rcu; - band = chanctx_conf->def.chan->band; + band = chanctx_conf->channel->band; break; #endif case NL80211_IFTYPE_STATION: @@ -1930,7 +1930,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); if (!chanctx_conf) goto fail_rcu; - band = chanctx_conf->def.chan->band; + band = chanctx_conf->channel->band; break; case NL80211_IFTYPE_ADHOC: /* DA SA BSSID */ @@ -1941,7 +1941,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); if (!chanctx_conf) goto fail_rcu; - band = chanctx_conf->def.chan->band; + band = chanctx_conf->channel->band; break; default: goto fail_rcu; @@ -2161,13 +2161,10 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, */ void ieee80211_clear_tx_pending(struct ieee80211_local *local) { - struct sk_buff *skb; int i; - for (i = 0; i < local->hw.queues; i++) { - while ((skb = skb_dequeue(&local->pending[i])) != NULL) - ieee80211_free_txskb(&local->hw, skb); - } + for (i = 0; i < local->hw.queues; i++) + skb_queue_purge(&local->pending[i]); } /* @@ -2194,7 +2191,7 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local, return true; } result = ieee80211_tx(sdata, skb, true, - chanctx_conf->def.chan->band); + chanctx_conf->channel->band); } else { struct sk_buff_head skbs; @@ -2458,7 +2455,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, *pos++ = WLAN_EID_SSID; *pos++ = 0x0; - band = chanctx_conf->def.chan->band; + band = chanctx_conf->channel->band; if (ieee80211_add_srates_ie(sdata, skb, true, band) || mesh_add_ds_params_ie(skb, sdata) || @@ -2477,7 +2474,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, goto out; } - band = chanctx_conf->def.chan->band; + band = chanctx_conf->channel->band; info = IEEE80211_SKB_CB(skb); @@ -2757,7 +2754,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, info = IEEE80211_SKB_CB(skb); tx.flags |= IEEE80211_TX_PS_BUFFERED; - info->band = chanctx_conf->def.chan->band; + info->band = chanctx_conf->channel->band; if (invoke_tx_handlers(&tx)) skb = NULL; diff --git a/trunk/net/mac80211/util.c b/trunk/net/mac80211/util.c index 08132ff98155..4e4f58513673 100644 --- a/trunk/net/mac80211/util.c +++ b/trunk/net/mac80211/util.c @@ -898,7 +898,7 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, rcu_read_lock(); chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); use_11b = (chanctx_conf && - chanctx_conf->def.chan->band == IEEE80211_BAND_2GHZ) && + chanctx_conf->channel->band == IEEE80211_BAND_2GHZ) && !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE); rcu_read_unlock(); @@ -991,7 +991,7 @@ void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); if (chanctx_conf && - chanctx_conf->def.chan->band == IEEE80211_BAND_2GHZ && + chanctx_conf->channel->band == IEEE80211_BAND_2GHZ && have_higher_than_11mbit) sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; else @@ -1417,12 +1417,10 @@ int ieee80211_reconfig(struct ieee80211_local *local) } /* add channel contexts */ - if (local->use_chanctx) { - mutex_lock(&local->chanctx_mtx); - list_for_each_entry(ctx, &local->chanctx_list, list) - WARN_ON(drv_add_chanctx(local, ctx)); - mutex_unlock(&local->chanctx_mtx); - } + mutex_lock(&local->chanctx_mtx); + list_for_each_entry(ctx, &local->chanctx_list, list) + WARN_ON(drv_add_chanctx(local, ctx)); + mutex_unlock(&local->chanctx_mtx); list_for_each_entry(sdata, &local->interfaces, list) { struct ieee80211_chanctx_conf *ctx_conf; @@ -1441,21 +1439,6 @@ int ieee80211_reconfig(struct ieee80211_local *local) mutex_unlock(&local->chanctx_mtx); } - sdata = rtnl_dereference(local->monitor_sdata); - if (sdata && local->use_chanctx && ieee80211_sdata_running(sdata)) { - struct ieee80211_chanctx_conf *ctx_conf; - - mutex_lock(&local->chanctx_mtx); - ctx_conf = rcu_dereference_protected(sdata->vif.chanctx_conf, - lockdep_is_held(&local->chanctx_mtx)); - if (ctx_conf) { - ctx = container_of(ctx_conf, struct ieee80211_chanctx, - conf); - drv_assign_vif_chanctx(local, sdata, ctx); - } - mutex_unlock(&local->chanctx_mtx); - } - /* add STAs back */ mutex_lock(&local->sta_mtx); list_for_each_entry(sta, &local->sta_list, list) { @@ -1572,8 +1555,6 @@ int ieee80211_reconfig(struct ieee80211_local *local) list_for_each_entry(sdata, &local->interfaces, list) { if (sdata->vif.type != NL80211_IFTYPE_STATION) continue; - if (!sdata->u.mgd.associated) - continue; ieee80211_send_nullfunc(local, sdata, 0); } @@ -1873,7 +1854,8 @@ u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, } u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, - const struct cfg80211_chan_def *chandef, + struct ieee80211_channel *channel, + enum nl80211_channel_type channel_type, u16 prot_mode) { struct ieee80211_ht_operation *ht_oper; @@ -1881,25 +1863,23 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, *pos++ = WLAN_EID_HT_OPERATION; *pos++ = sizeof(struct ieee80211_ht_operation); ht_oper = (struct ieee80211_ht_operation *)pos; - ht_oper->primary_chan = ieee80211_frequency_to_channel( - chandef->chan->center_freq); - switch (chandef->width) { - case NL80211_CHAN_WIDTH_160: - case NL80211_CHAN_WIDTH_80P80: - case NL80211_CHAN_WIDTH_80: - case NL80211_CHAN_WIDTH_40: - if (chandef->center_freq1 > chandef->chan->center_freq) - ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; - else - ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_BELOW; + ht_oper->primary_chan = + ieee80211_frequency_to_channel(channel->center_freq); + switch (channel_type) { + case NL80211_CHAN_HT40MINUS: + ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_BELOW; + break; + case NL80211_CHAN_HT40PLUS: + ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; break; + case NL80211_CHAN_HT20: default: ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_NONE; break; } if (ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 && - chandef->width != NL80211_CHAN_WIDTH_20_NOHT && - chandef->width != NL80211_CHAN_WIDTH_20) + channel_type != NL80211_CHAN_NO_HT && + channel_type != NL80211_CHAN_HT20) ht_oper->ht_param |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY; ht_oper->operation_mode = cpu_to_le16(prot_mode); @@ -1913,17 +1893,13 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, return pos + sizeof(struct ieee80211_ht_operation); } -void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan, - struct ieee80211_ht_operation *ht_oper, - struct cfg80211_chan_def *chandef) +enum nl80211_channel_type +ieee80211_ht_oper_to_channel_type(struct ieee80211_ht_operation *ht_oper) { enum nl80211_channel_type channel_type; - if (!ht_oper) { - cfg80211_chandef_create(chandef, control_chan, - NL80211_CHAN_NO_HT); - return; - } + if (!ht_oper) + return NL80211_CHAN_NO_HT; switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { case IEEE80211_HT_PARAM_CHA_SEC_NONE: @@ -1939,7 +1915,7 @@ void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan, channel_type = NL80211_CHAN_NO_HT; } - cfg80211_chandef_create(chandef, control_chan, channel_type); + return channel_type; } int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, @@ -2037,68 +2013,3 @@ u8 ieee80211_mcs_to_chains(const struct ieee80211_mcs_info *mcs) return 2; return 1; } - -/** - * ieee80211_calculate_rx_timestamp - calculate timestamp in frame - * @local: mac80211 hw info struct - * @status: RX status - * @mpdu_len: total MPDU length (including FCS) - * @mpdu_offset: offset into MPDU to calculate timestamp at - * - * This function calculates the RX timestamp at the given MPDU offset, taking - * into account what the RX timestamp was. An offset of 0 will just normalize - * the timestamp to TSF at beginning of MPDU reception. - */ -u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local, - struct ieee80211_rx_status *status, - unsigned int mpdu_len, - unsigned int mpdu_offset) -{ - u64 ts = status->mactime; - struct rate_info ri; - u16 rate; - - if (WARN_ON(!ieee80211_have_rx_timestamp(status))) - return 0; - - memset(&ri, 0, sizeof(ri)); - - /* Fill cfg80211 rate info */ - if (status->flag & RX_FLAG_HT) { - ri.mcs = status->rate_idx; - ri.flags |= RATE_INFO_FLAGS_MCS; - if (status->flag & RX_FLAG_40MHZ) - ri.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; - if (status->flag & RX_FLAG_SHORT_GI) - ri.flags |= RATE_INFO_FLAGS_SHORT_GI; - } else if (status->flag & RX_FLAG_VHT) { - ri.flags |= RATE_INFO_FLAGS_VHT_MCS; - ri.mcs = status->rate_idx; - ri.nss = status->vht_nss; - if (status->flag & RX_FLAG_40MHZ) - ri.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; - if (status->flag & RX_FLAG_80MHZ) - ri.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; - if (status->flag & RX_FLAG_80P80MHZ) - ri.flags |= RATE_INFO_FLAGS_80P80_MHZ_WIDTH; - if (status->flag & RX_FLAG_160MHZ) - ri.flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH; - if (status->flag & RX_FLAG_SHORT_GI) - ri.flags |= RATE_INFO_FLAGS_SHORT_GI; - } else { - struct ieee80211_supported_band *sband; - - sband = local->hw.wiphy->bands[status->band]; - ri.legacy = sband->bitrates[status->rate_idx].bitrate; - } - - rate = cfg80211_calculate_bitrate(&ri); - - /* rewind from end of MPDU */ - if (status->flag & RX_FLAG_MACTIME_END) - ts -= mpdu_len * 8 * 10 / rate; - - ts += mpdu_offset * 8 * 10 / rate; - - return ts; -} diff --git a/trunk/net/mac80211/wme.c b/trunk/net/mac80211/wme.c index 906f00cd6d2f..cea06e9f26f4 100644 --- a/trunk/net/mac80211/wme.c +++ b/trunk/net/mac80211/wme.c @@ -160,37 +160,31 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, return ieee80211_downgrade_queue(sdata, skb); } -/** - * ieee80211_set_qos_hdr - Fill in the QoS header if there is one. - * - * @sdata: local subif - * @skb: packet to be updated - */ void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) { struct ieee80211_hdr *hdr = (void *)skb->data; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - u8 *p; - u8 ack_policy, tid; - if (!ieee80211_is_data_qos(hdr->frame_control)) - return; + /* Fill in the QoS header if there is one. */ + if (ieee80211_is_data_qos(hdr->frame_control)) { + u8 *p = ieee80211_get_qos_ctl(hdr); + u8 ack_policy, tid; - p = ieee80211_get_qos_ctl(hdr); - tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; + tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; - /* preserve EOSP bit */ - ack_policy = *p & IEEE80211_QOS_CTL_EOSP; + /* preserve EOSP bit */ + ack_policy = *p & IEEE80211_QOS_CTL_EOSP; - if (is_multicast_ether_addr(hdr->addr1) || - sdata->noack_map & BIT(tid)) { - ack_policy |= IEEE80211_QOS_CTL_ACK_POLICY_NOACK; - info->flags |= IEEE80211_TX_CTL_NO_ACK; - } + if (is_multicast_ether_addr(hdr->addr1) || + sdata->noack_map & BIT(tid)) { + ack_policy |= IEEE80211_QOS_CTL_ACK_POLICY_NOACK; + info->flags |= IEEE80211_TX_CTL_NO_ACK; + } - /* qos header is 2 bytes */ - *p++ = ack_policy | tid; - *p = ieee80211_vif_is_mesh(&sdata->vif) ? - (IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT >> 8) : 0; + /* qos header is 2 bytes */ + *p++ = ack_policy | tid; + *p = ieee80211_vif_is_mesh(&sdata->vif) ? + (IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT >> 8) : 0; + } } diff --git a/trunk/net/nfc/hci/command.c b/trunk/net/nfc/hci/command.c index 7d99410e6c1a..07659cfd6d7b 100644 --- a/trunk/net/nfc/hci/command.c +++ b/trunk/net/nfc/hci/command.c @@ -344,7 +344,7 @@ int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate, return -EADDRINUSE; if (pipe != NFC_HCI_INVALID_PIPE) - goto open_pipe; + goto pipe_is_open; switch (dest_gate) { case NFC_HCI_LINK_MGMT_GATE: @@ -361,7 +361,6 @@ int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate, break; } -open_pipe: r = nfc_hci_open_pipe(hdev, pipe); if (r < 0) { if (pipe_created) @@ -372,6 +371,7 @@ int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate, return r; } +pipe_is_open: hdev->gate2pipe[dest_gate] = pipe; return 0; diff --git a/trunk/net/nfc/hci/core.c b/trunk/net/nfc/hci/core.c index 7bea574d5934..bc571b0efb92 100644 --- a/trunk/net/nfc/hci/core.c +++ b/trunk/net/nfc/hci/core.c @@ -33,20 +33,17 @@ /* Largest headroom needed for outgoing HCI commands */ #define HCI_CMDS_HEADROOM 1 -int nfc_hci_result_to_errno(u8 result) +static int nfc_hci_result_to_errno(u8 result) { switch (result) { case NFC_HCI_ANY_OK: return 0; - case NFC_HCI_ANY_E_REG_PAR_UNKNOWN: - return -EOPNOTSUPP; case NFC_HCI_ANY_E_TIMEOUT: return -ETIME; default: return -1; } } -EXPORT_SYMBOL(nfc_hci_result_to_errno); static void nfc_hci_msg_tx_work(struct work_struct *work) { @@ -170,7 +167,7 @@ void nfc_hci_cmd_received(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd, kfree_skb(skb); } -u32 nfc_hci_sak_to_protocol(u8 sak) +static u32 nfc_hci_sak_to_protocol(u8 sak) { switch (NFC_HCI_TYPE_A_SEL_PROT(sak)) { case NFC_HCI_TYPE_A_SEL_PROT_MIFARE: @@ -185,7 +182,6 @@ u32 nfc_hci_sak_to_protocol(u8 sak) return 0xffffffff; } } -EXPORT_SYMBOL(nfc_hci_sak_to_protocol); int nfc_hci_target_discovered(struct nfc_hci_dev *hdev, u8 gate) { @@ -288,12 +284,6 @@ void nfc_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, u8 event, struct sk_buff *skb) { int r = 0; - u8 gate = nfc_hci_pipe2gate(hdev, pipe); - - if (gate == 0xff) { - pr_err("Discarded event %x to unopened pipe %x\n", event, pipe); - goto exit; - } switch (event) { case NFC_HCI_EVT_TARGET_DISCOVERED: @@ -317,11 +307,14 @@ void nfc_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, u8 event, goto exit; } - r = nfc_hci_target_discovered(hdev, gate); + r = nfc_hci_target_discovered(hdev, + nfc_hci_pipe2gate(hdev, pipe)); break; default: if (hdev->ops->event_received) { - hdev->ops->event_received(hdev, gate, event, skb); + hdev->ops->event_received(hdev, + nfc_hci_pipe2gate(hdev, pipe), + event, skb); return; } @@ -426,10 +419,6 @@ static int hci_dev_version(struct nfc_hci_dev *hdev) r = nfc_hci_get_param(hdev, NFC_HCI_ID_MGMT_GATE, NFC_HCI_ID_MGMT_VERSION_SW, &skb); - if (r == -EOPNOTSUPP) { - pr_info("Software/Hardware info not available\n"); - return 0; - } if (r < 0) return r; diff --git a/trunk/net/nfc/llcp/commands.c b/trunk/net/nfc/llcp/commands.c index df24be48d4da..ed2d17312d61 100644 --- a/trunk/net/nfc/llcp/commands.c +++ b/trunk/net/nfc/llcp/commands.c @@ -528,23 +528,6 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock, if (local == NULL) return -ENODEV; - /* Remote is ready but has not acknowledged our frames */ - if((sock->remote_ready && - skb_queue_len(&sock->tx_pending_queue) >= sock->rw && - skb_queue_len(&sock->tx_queue) >= 2 * sock->rw)) { - pr_err("Pending queue is full %d frames\n", - skb_queue_len(&sock->tx_pending_queue)); - return -ENOBUFS; - } - - /* Remote is not ready and we've been queueing enough frames */ - if ((!sock->remote_ready && - skb_queue_len(&sock->tx_queue) >= 2 * sock->rw)) { - pr_err("Tx queue is full %d frames\n", - skb_queue_len(&sock->tx_queue)); - return -ENOBUFS; - } - msg_data = kzalloc(len, GFP_KERNEL); if (msg_data == NULL) return -ENOMEM; @@ -596,7 +579,7 @@ int nfc_llcp_send_ui_frame(struct nfc_llcp_sock *sock, u8 ssap, u8 dsap, struct sk_buff *pdu; struct nfc_llcp_local *local; size_t frag_len = 0, remaining_len; - u8 *msg_ptr, *msg_data; + u8 *msg_ptr; int err; pr_debug("Send UI frame len %zd\n", len); @@ -605,17 +588,8 @@ int nfc_llcp_send_ui_frame(struct nfc_llcp_sock *sock, u8 ssap, u8 dsap, if (local == NULL) return -ENODEV; - msg_data = kzalloc(len, GFP_KERNEL); - if (msg_data == NULL) - return -ENOMEM; - - if (memcpy_fromiovec(msg_data, msg->msg_iov, len)) { - kfree(msg_data); - return -EFAULT; - } - remaining_len = len; - msg_ptr = msg_data; + msg_ptr = (u8 *) msg->msg_iov; while (remaining_len > 0) { @@ -642,8 +616,6 @@ int nfc_llcp_send_ui_frame(struct nfc_llcp_sock *sock, u8 ssap, u8 dsap, msg_ptr += frag_len; } - kfree(msg_data); - return len; } diff --git a/trunk/net/nfc/llcp/llcp.c b/trunk/net/nfc/llcp/llcp.c index 2df87056c6df..f6804532047a 100644 --- a/trunk/net/nfc/llcp/llcp.c +++ b/trunk/net/nfc/llcp/llcp.c @@ -656,8 +656,6 @@ static void nfc_llcp_tx_work(struct work_struct *work) if (llcp_sock == NULL && nfc_llcp_ptype(skb) == LLCP_PDU_I) { nfc_llcp_send_symm(local->dev); } else { - struct sk_buff *copy_skb = NULL; - u8 ptype = nfc_llcp_ptype(skb); int ret; pr_debug("Sending pending skb\n"); @@ -665,29 +663,22 @@ static void nfc_llcp_tx_work(struct work_struct *work) DUMP_PREFIX_OFFSET, 16, 1, skb->data, skb->len, true); - if (ptype == LLCP_PDU_I) - copy_skb = skb_copy(skb, GFP_ATOMIC); - nfc_llcp_send_to_raw_sock(local, skb, NFC_LLCP_DIRECTION_TX); ret = nfc_data_exchange(local->dev, local->target_idx, skb, nfc_llcp_recv, local); - if (ret) { - kfree_skb(copy_skb); - goto out; - } - - if (ptype == LLCP_PDU_I && copy_skb) + if (!ret && nfc_llcp_ptype(skb) == LLCP_PDU_I) { + skb = skb_get(skb); skb_queue_tail(&llcp_sock->tx_pending_queue, - copy_skb); + skb); + } } } else { nfc_llcp_send_symm(local->dev); } -out: mod_timer(&local->link_timer, jiffies + msecs_to_jiffies(2 * local->remote_lto)); } @@ -1397,7 +1388,7 @@ int nfc_llcp_register_device(struct nfc_dev *ndev) local->remote_miu = LLCP_DEFAULT_MIU; local->remote_lto = LLCP_DEFAULT_LTO; - list_add(&local->list, &llcp_devices); + list_add(&llcp_devices, &local->list); return 0; } diff --git a/trunk/net/wireless/chan.c b/trunk/net/wireless/chan.c index bf2dfd54ff3b..48febd2160ba 100644 --- a/trunk/net/wireless/chan.c +++ b/trunk/net/wireless/chan.c @@ -11,264 +11,96 @@ #include "core.h" #include "rdev-ops.h" -void cfg80211_chandef_create(struct cfg80211_chan_def *chandef, - struct ieee80211_channel *chan, - enum nl80211_channel_type chan_type) +struct ieee80211_channel * +rdev_freq_to_chan(struct cfg80211_registered_device *rdev, + int freq, enum nl80211_channel_type channel_type) { - if (WARN_ON(!chan)) - return; - - chandef->chan = chan; - chandef->center_freq2 = 0; - - switch (chan_type) { - case NL80211_CHAN_NO_HT: - chandef->width = NL80211_CHAN_WIDTH_20_NOHT; - chandef->center_freq1 = chan->center_freq; - break; - case NL80211_CHAN_HT20: - chandef->width = NL80211_CHAN_WIDTH_20; - chandef->center_freq1 = chan->center_freq; - break; - case NL80211_CHAN_HT40PLUS: - chandef->width = NL80211_CHAN_WIDTH_40; - chandef->center_freq1 = chan->center_freq + 10; - break; - case NL80211_CHAN_HT40MINUS: - chandef->width = NL80211_CHAN_WIDTH_40; - chandef->center_freq1 = chan->center_freq - 10; - break; - default: - WARN_ON(1); - } -} -EXPORT_SYMBOL(cfg80211_chandef_create); + struct ieee80211_channel *chan; + struct ieee80211_sta_ht_cap *ht_cap; -bool cfg80211_chan_def_valid(const struct cfg80211_chan_def *chandef) -{ - u32 control_freq; + chan = ieee80211_get_channel(&rdev->wiphy, freq); - if (!chandef->chan) - return false; - - control_freq = chandef->chan->center_freq; - - switch (chandef->width) { - case NL80211_CHAN_WIDTH_20: - case NL80211_CHAN_WIDTH_20_NOHT: - if (chandef->center_freq1 != control_freq) - return false; - if (chandef->center_freq2) - return false; - break; - case NL80211_CHAN_WIDTH_40: - if (chandef->center_freq1 != control_freq + 10 && - chandef->center_freq1 != control_freq - 10) - return false; - if (chandef->center_freq2) - return false; - break; - case NL80211_CHAN_WIDTH_80P80: - if (chandef->center_freq1 != control_freq + 30 && - chandef->center_freq1 != control_freq + 10 && - chandef->center_freq1 != control_freq - 10 && - chandef->center_freq1 != control_freq - 30) - return false; - if (!chandef->center_freq2) - return false; - break; - case NL80211_CHAN_WIDTH_80: - if (chandef->center_freq1 != control_freq + 30 && - chandef->center_freq1 != control_freq + 10 && - chandef->center_freq1 != control_freq - 10 && - chandef->center_freq1 != control_freq - 30) - return false; - if (chandef->center_freq2) - return false; - break; - case NL80211_CHAN_WIDTH_160: - if (chandef->center_freq1 != control_freq + 70 && - chandef->center_freq1 != control_freq + 50 && - chandef->center_freq1 != control_freq + 30 && - chandef->center_freq1 != control_freq + 10 && - chandef->center_freq1 != control_freq - 10 && - chandef->center_freq1 != control_freq - 30 && - chandef->center_freq1 != control_freq - 50 && - chandef->center_freq1 != control_freq - 70) - return false; - if (chandef->center_freq2) - return false; - break; - default: - return false; - } - - return true; -} - -static void chandef_primary_freqs(const struct cfg80211_chan_def *c, - int *pri40, int *pri80) -{ - int tmp; - - switch (c->width) { - case NL80211_CHAN_WIDTH_40: - *pri40 = c->center_freq1; - *pri80 = 0; - break; - case NL80211_CHAN_WIDTH_80: - case NL80211_CHAN_WIDTH_80P80: - *pri80 = c->center_freq1; - /* n_P20 */ - tmp = (30 + c->chan->center_freq - c->center_freq1)/20; - /* n_P40 */ - tmp /= 2; - /* freq_P40 */ - *pri40 = c->center_freq1 - 20 + 40 * tmp; - break; - case NL80211_CHAN_WIDTH_160: - /* n_P20 */ - tmp = (70 + c->chan->center_freq - c->center_freq1)/20; - /* n_P40 */ - tmp /= 2; - /* freq_P40 */ - *pri40 = c->center_freq1 - 60 + 40 * tmp; - /* n_P80 */ - tmp /= 2; - *pri80 = c->center_freq1 - 40 + 80 * tmp; - break; - default: - WARN_ON_ONCE(1); - } -} - -const struct cfg80211_chan_def * -cfg80211_chandef_compatible(const struct cfg80211_chan_def *c1, - const struct cfg80211_chan_def *c2) -{ - u32 c1_pri40, c1_pri80, c2_pri40, c2_pri80; - - /* If they are identical, return */ - if (cfg80211_chandef_identical(c1, c2)) - return c1; - - /* otherwise, must have same control channel */ - if (c1->chan != c2->chan) + /* Primary channel not allowed */ + if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) return NULL; - /* - * If they have the same width, but aren't identical, - * then they can't be compatible. - */ - if (c1->width == c2->width) + if (channel_type == NL80211_CHAN_HT40MINUS && + chan->flags & IEEE80211_CHAN_NO_HT40MINUS) return NULL; - - if (c1->width == NL80211_CHAN_WIDTH_20_NOHT || - c1->width == NL80211_CHAN_WIDTH_20) - return c2; - - if (c2->width == NL80211_CHAN_WIDTH_20_NOHT || - c2->width == NL80211_CHAN_WIDTH_20) - return c1; - - chandef_primary_freqs(c1, &c1_pri40, &c1_pri80); - chandef_primary_freqs(c2, &c2_pri40, &c2_pri80); - - if (c1_pri40 != c2_pri40) - return NULL; - - WARN_ON(!c1_pri80 && !c2_pri80); - if (c1_pri80 && c2_pri80 && c1_pri80 != c2_pri80) + else if (channel_type == NL80211_CHAN_HT40PLUS && + chan->flags & IEEE80211_CHAN_NO_HT40PLUS) return NULL; - if (c1->width > c2->width) - return c1; - return c2; -} -EXPORT_SYMBOL(cfg80211_chandef_compatible); + ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap; -bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, - u32 center_freq, u32 bandwidth, - u32 prohibited_flags) -{ - struct ieee80211_channel *c; - u32 freq; + if (channel_type != NL80211_CHAN_NO_HT) { + if (!ht_cap->ht_supported) + return NULL; - for (freq = center_freq - bandwidth/2 + 10; - freq <= center_freq + bandwidth/2 - 10; - freq += 20) { - c = ieee80211_get_channel(wiphy, freq); - if (!c || c->flags & prohibited_flags) - return false; + if (channel_type != NL80211_CHAN_HT20 && + (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) || + ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT)) + return NULL; } - return true; + return chan; } -static bool cfg80211_check_beacon_chans(struct wiphy *wiphy, - u32 center_freq, u32 bw) +bool cfg80211_can_beacon_sec_chan(struct wiphy *wiphy, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type) { - return cfg80211_secondary_chans_ok(wiphy, center_freq, bw, - IEEE80211_CHAN_DISABLED | - IEEE80211_CHAN_PASSIVE_SCAN | - IEEE80211_CHAN_NO_IBSS | - IEEE80211_CHAN_RADAR); -} + struct ieee80211_channel *sec_chan; + int diff; -bool cfg80211_reg_can_beacon(struct wiphy *wiphy, - struct cfg80211_chan_def *chandef) -{ - u32 width; - bool res; + trace_cfg80211_can_beacon_sec_chan(wiphy, chan, channel_type); - trace_cfg80211_reg_can_beacon(wiphy, chandef); + switch (channel_type) { + case NL80211_CHAN_HT40PLUS: + diff = 20; + break; + case NL80211_CHAN_HT40MINUS: + diff = -20; + break; + default: + trace_cfg80211_return_bool(true); + return true; + } - if (WARN_ON(!cfg80211_chan_def_valid(chandef))) { + sec_chan = ieee80211_get_channel(wiphy, chan->center_freq + diff); + if (!sec_chan) { trace_cfg80211_return_bool(false); return false; } - switch (chandef->width) { - case NL80211_CHAN_WIDTH_20_NOHT: - case NL80211_CHAN_WIDTH_20: - width = 20; - break; - case NL80211_CHAN_WIDTH_40: - width = 40; - break; - case NL80211_CHAN_WIDTH_80: - case NL80211_CHAN_WIDTH_80P80: - width = 80; - break; - case NL80211_CHAN_WIDTH_160: - width = 160; - break; - default: - WARN_ON_ONCE(1); + /* we'll need a DFS capability later */ + if (sec_chan->flags & (IEEE80211_CHAN_DISABLED | + IEEE80211_CHAN_PASSIVE_SCAN | + IEEE80211_CHAN_NO_IBSS | + IEEE80211_CHAN_RADAR)) { trace_cfg80211_return_bool(false); return false; } - - res = cfg80211_check_beacon_chans(wiphy, chandef->center_freq1, width); - - if (res && chandef->center_freq2) - res = cfg80211_check_beacon_chans(wiphy, chandef->center_freq2, - width); - - trace_cfg80211_return_bool(res); - return res; + trace_cfg80211_return_bool(true); + return true; } -EXPORT_SYMBOL(cfg80211_reg_can_beacon); +EXPORT_SYMBOL(cfg80211_can_beacon_sec_chan); int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev, - struct cfg80211_chan_def *chandef) + int freq, enum nl80211_channel_type chantype) { + struct ieee80211_channel *chan; + if (!rdev->ops->set_monitor_channel) return -EOPNOTSUPP; if (!cfg80211_has_monitors_only(rdev)) return -EBUSY; - return rdev_set_monitor_channel(rdev, chandef); + chan = rdev_freq_to_chan(rdev, freq, chantype); + if (!chan) + return -EINVAL; + + return rdev_set_monitor_channel(rdev, chan, chantype); } void diff --git a/trunk/net/wireless/core.h b/trunk/net/wireless/core.h index a0c8decf6a47..e53831c876bb 100644 --- a/trunk/net/wireless/core.h +++ b/trunk/net/wireless/core.h @@ -309,9 +309,9 @@ int cfg80211_join_mesh(struct cfg80211_registered_device *rdev, const struct mesh_config *conf); int cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, struct net_device *dev); -int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev, - struct wireless_dev *wdev, - struct cfg80211_chan_def *chandef); +int cfg80211_set_mesh_freq(struct cfg80211_registered_device *rdev, + struct wireless_dev *wdev, int freq, + enum nl80211_channel_type channel_type); /* AP */ int cfg80211_stop_ap(struct cfg80211_registered_device *rdev, @@ -378,8 +378,10 @@ void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev); int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, struct wireless_dev *wdev, struct ieee80211_channel *chan, bool offchan, - unsigned int wait, const u8 *buf, size_t len, - bool no_cck, bool dont_wait_for_ack, u64 *cookie); + enum nl80211_channel_type channel_type, + bool channel_type_valid, unsigned int wait, + const u8 *buf, size_t len, bool no_cck, + bool dont_wait_for_ack, u64 *cookie); void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa, const struct ieee80211_ht_cap *ht_capa_mask); @@ -470,8 +472,11 @@ cfg80211_get_chan_state(struct wireless_dev *wdev, struct ieee80211_channel **chan, enum cfg80211_chan_mode *chanmode); +struct ieee80211_channel * +rdev_freq_to_chan(struct cfg80211_registered_device *rdev, + int freq, enum nl80211_channel_type channel_type); int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev, - struct cfg80211_chan_def *chandef); + int freq, enum nl80211_channel_type chantype); int ieee80211_get_ratemask(struct ieee80211_supported_band *sband, const u8 *rates, unsigned int n_rates, @@ -483,12 +488,6 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, enum nl80211_iftype iftype, int num); -bool cfg80211_chan_def_valid(const struct cfg80211_chan_def *chandef); - -bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, - u32 center_freq, u32 bandwidth, - u32 prohibited_flags); - #define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10 #ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS diff --git a/trunk/net/wireless/ibss.c b/trunk/net/wireless/ibss.c index 9b9551e4a6f9..27941d5db72b 100644 --- a/trunk/net/wireless/ibss.c +++ b/trunk/net/wireless/ibss.c @@ -100,9 +100,9 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, * 11a for maximum compatibility. */ struct ieee80211_supported_band *sband = - rdev->wiphy.bands[params->chandef.chan->band]; + rdev->wiphy.bands[params->channel->band]; int j; - u32 flag = params->chandef.chan->band == IEEE80211_BAND_5GHZ ? + u32 flag = params->channel->band == IEEE80211_BAND_5GHZ ? IEEE80211_RATE_MANDATORY_A : IEEE80211_RATE_MANDATORY_B; @@ -118,11 +118,11 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, wdev->ibss_fixed = params->channel_fixed; #ifdef CONFIG_CFG80211_WEXT - wdev->wext.ibss.chandef = params->chandef; + wdev->wext.ibss.channel = params->channel; #endif wdev->sme_state = CFG80211_SME_CONNECTING; - err = cfg80211_can_use_chan(rdev, wdev, params->chandef.chan, + err = cfg80211_can_use_chan(rdev, wdev, params->channel, params->channel_fixed ? CHAN_MODE_SHARED : CHAN_MODE_EXCLUSIVE); @@ -251,9 +251,7 @@ int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev, wdev->wext.ibss.beacon_interval = 100; /* try to find an IBSS channel if none requested ... */ - if (!wdev->wext.ibss.chandef.chan) { - wdev->wext.ibss.chandef.width = NL80211_CHAN_WIDTH_20_NOHT; - + if (!wdev->wext.ibss.channel) { for (band = 0; band < IEEE80211_NUM_BANDS; band++) { struct ieee80211_supported_band *sband; struct ieee80211_channel *chan; @@ -268,15 +266,15 @@ int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev, continue; if (chan->flags & IEEE80211_CHAN_DISABLED) continue; - wdev->wext.ibss.chandef.chan = chan; + wdev->wext.ibss.channel = chan; break; } - if (wdev->wext.ibss.chandef.chan) + if (wdev->wext.ibss.channel) break; } - if (!wdev->wext.ibss.chandef.chan) + if (!wdev->wext.ibss.channel) return -EINVAL; } @@ -338,7 +336,7 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev, return -EINVAL; } - if (wdev->wext.ibss.chandef.chan == chan) + if (wdev->wext.ibss.channel == chan) return 0; wdev_lock(wdev); @@ -351,8 +349,7 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev, return err; if (chan) { - wdev->wext.ibss.chandef.chan = chan; - wdev->wext.ibss.chandef.width = NL80211_CHAN_WIDTH_20_NOHT; + wdev->wext.ibss.channel = chan; wdev->wext.ibss.channel_fixed = true; } else { /* cfg80211_ibss_wext_join will pick one if needed */ @@ -382,8 +379,8 @@ int cfg80211_ibss_wext_giwfreq(struct net_device *dev, wdev_lock(wdev); if (wdev->current_bss) chan = wdev->current_bss->pub.channel; - else if (wdev->wext.ibss.chandef.chan) - chan = wdev->wext.ibss.chandef.chan; + else if (wdev->wext.ibss.channel) + chan = wdev->wext.ibss.channel; wdev_unlock(wdev); if (chan) { diff --git a/trunk/net/wireless/mesh.c b/trunk/net/wireless/mesh.c index 3ee5a7282283..966cfc4cd79d 100644 --- a/trunk/net/wireless/mesh.c +++ b/trunk/net/wireless/mesh.c @@ -73,6 +73,8 @@ const struct mesh_config default_mesh_config = { const struct mesh_setup default_mesh_setup = { /* cfg80211_join_mesh() will pick a channel if needed */ + .channel = NULL, + .channel_type = NL80211_CHAN_NO_HT, .sync_method = IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET, .path_sel_proto = IEEE80211_PATH_PROTOCOL_HWMP, .path_metric = IEEE80211_PATH_METRIC_AIRTIME, @@ -109,12 +111,13 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, if (!rdev->ops->join_mesh) return -EOPNOTSUPP; - if (!setup->chandef.chan) { + if (!setup->channel) { /* if no channel explicitly given, use preset channel */ - setup->chandef = wdev->preset_chandef; + setup->channel = wdev->preset_chan; + setup->channel_type = wdev->preset_chantype; } - if (!setup->chandef.chan) { + if (!setup->channel) { /* if we don't have that either, use the first usable channel */ enum ieee80211_band band; @@ -134,25 +137,26 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, IEEE80211_CHAN_DISABLED | IEEE80211_CHAN_RADAR)) continue; - setup->chandef.chan = chan; + setup->channel = chan; break; } - if (setup->chandef.chan) + if (setup->channel) break; } /* no usable channel ... */ - if (!setup->chandef.chan) + if (!setup->channel) return -EINVAL; - setup->chandef.width = NL80211_CHAN_WIDTH_20_NOHT;; + setup->channel_type = NL80211_CHAN_NO_HT; } - if (!cfg80211_reg_can_beacon(&rdev->wiphy, &setup->chandef)) + if (!cfg80211_can_beacon_sec_chan(&rdev->wiphy, setup->channel, + setup->channel_type)) return -EINVAL; - err = cfg80211_can_use_chan(rdev, wdev, setup->chandef.chan, + err = cfg80211_can_use_chan(rdev, wdev, setup->channel, CHAN_MODE_SHARED); if (err) return err; @@ -161,7 +165,7 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, if (!err) { memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len); wdev->mesh_id_len = setup->mesh_id_len; - wdev->channel = setup->chandef.chan; + wdev->channel = setup->channel; } return err; @@ -184,12 +188,20 @@ int cfg80211_join_mesh(struct cfg80211_registered_device *rdev, return err; } -int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev, - struct wireless_dev *wdev, - struct cfg80211_chan_def *chandef) +int cfg80211_set_mesh_freq(struct cfg80211_registered_device *rdev, + struct wireless_dev *wdev, int freq, + enum nl80211_channel_type channel_type) { + struct ieee80211_channel *channel; int err; + channel = rdev_freq_to_chan(rdev, freq, channel_type); + if (!channel || !cfg80211_can_beacon_sec_chan(&rdev->wiphy, + channel, + channel_type)) { + return -EINVAL; + } + /* * Workaround for libertas (only!), it puts the interface * into mesh mode but doesn't implement join_mesh. Instead, @@ -198,21 +210,21 @@ int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev, * compatible with 802.11 mesh. */ if (rdev->ops->libertas_set_mesh_channel) { - if (chandef->width != NL80211_CHAN_WIDTH_20_NOHT) + if (channel_type != NL80211_CHAN_NO_HT) return -EINVAL; if (!netif_running(wdev->netdev)) return -ENETDOWN; - err = cfg80211_can_use_chan(rdev, wdev, chandef->chan, + err = cfg80211_can_use_chan(rdev, wdev, channel, CHAN_MODE_SHARED); if (err) return err; err = rdev_libertas_set_mesh_channel(rdev, wdev->netdev, - chandef->chan); + channel); if (!err) - wdev->channel = chandef->chan; + wdev->channel = channel; return err; } @@ -220,7 +232,8 @@ int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev, if (wdev->mesh_id_len) return -EBUSY; - wdev->preset_chandef = *chandef; + wdev->preset_chan = channel; + wdev->preset_chantype = channel_type; return 0; } diff --git a/trunk/net/wireless/mlme.c b/trunk/net/wireless/mlme.c index 5e8123ee63fd..4bfd14f7c592 100644 --- a/trunk/net/wireless/mlme.c +++ b/trunk/net/wireless/mlme.c @@ -579,25 +579,31 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie, struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, unsigned int duration, gfp_t gfp) { struct wiphy *wiphy = wdev->wiphy; struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); - trace_cfg80211_ready_on_channel(wdev, cookie, chan, duration); - nl80211_send_remain_on_channel(rdev, wdev, cookie, chan, duration, gfp); + trace_cfg80211_ready_on_channel(wdev, cookie, chan, channel_type, + duration); + nl80211_send_remain_on_channel(rdev, wdev, cookie, chan, channel_type, + duration, gfp); } EXPORT_SYMBOL(cfg80211_ready_on_channel); void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie, struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, gfp_t gfp) { struct wiphy *wiphy = wdev->wiphy; struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); - trace_cfg80211_ready_on_channel_expired(wdev, cookie, chan); - nl80211_send_remain_on_channel_cancel(rdev, wdev, cookie, chan, gfp); + trace_cfg80211_ready_on_channel_expired(wdev, cookie, chan, + channel_type); + nl80211_send_remain_on_channel_cancel(rdev, wdev, cookie, chan, + channel_type, gfp); } EXPORT_SYMBOL(cfg80211_remain_on_channel_expired); @@ -752,8 +758,10 @@ void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev) int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, struct wireless_dev *wdev, struct ieee80211_channel *chan, bool offchan, - unsigned int wait, const u8 *buf, size_t len, - bool no_cck, bool dont_wait_for_ack, u64 *cookie) + enum nl80211_channel_type channel_type, + bool channel_type_valid, unsigned int wait, + const u8 *buf, size_t len, bool no_cck, + bool dont_wait_for_ack, u64 *cookie) { const struct ieee80211_mgmt *mgmt; u16 stype; @@ -847,6 +855,7 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, /* Transmit the Action frame as requested by user space */ return rdev_mgmt_tx(rdev, wdev, chan, offchan, + channel_type, channel_type_valid, wait, buf, len, no_cck, dont_wait_for_ack, cookie); } @@ -988,14 +997,15 @@ void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index, } EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify); -void cfg80211_ch_switch_notify(struct net_device *dev, - struct cfg80211_chan_def *chandef) +void cfg80211_ch_switch_notify(struct net_device *dev, int freq, + enum nl80211_channel_type type) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct wiphy *wiphy = wdev->wiphy; struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); + struct ieee80211_channel *chan; - trace_cfg80211_ch_switch_notify(dev, chandef); + trace_cfg80211_ch_switch_notify(dev, freq, type); wdev_lock(wdev); @@ -1003,8 +1013,12 @@ void cfg80211_ch_switch_notify(struct net_device *dev, wdev->iftype != NL80211_IFTYPE_P2P_GO)) goto out; - wdev->channel = chandef->chan; - nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL); + chan = rdev_freq_to_chan(rdev, freq, type); + if (WARN_ON(!chan)) + goto out; + + wdev->channel = chan; + nl80211_ch_switch_notify(rdev, dev, freq, type, GFP_KERNEL); out: wdev_unlock(wdev); return; diff --git a/trunk/net/wireless/nl80211.c b/trunk/net/wireless/nl80211.c index d038fa45ecd1..c18b2fc9d492 100644 --- a/trunk/net/wireless/nl80211.c +++ b/trunk/net/wireless/nl80211.c @@ -223,13 +223,8 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING, .len = 20-1 }, [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED }, - [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 }, [NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 }, - [NL80211_ATTR_CHANNEL_WIDTH] = { .type = NLA_U32 }, - [NL80211_ATTR_CENTER_FREQ1] = { .type = NLA_U32 }, - [NL80211_ATTR_CENTER_FREQ2] = { .type = NLA_U32 }, - [NL80211_ATTR_WIPHY_RETRY_SHORT] = { .type = NLA_U8 }, [NL80211_ATTR_WIPHY_RETRY_LONG] = { .type = NLA_U8 }, [NL80211_ATTR_WIPHY_FRAG_THRESHOLD] = { .type = NLA_U32 }, @@ -1365,139 +1360,51 @@ static bool nl80211_can_set_dev_channel(struct wireless_dev *wdev) wdev->iftype == NL80211_IFTYPE_P2P_GO; } -static int nl80211_parse_chandef(struct cfg80211_registered_device *rdev, - struct genl_info *info, - struct cfg80211_chan_def *chandef) +static bool nl80211_valid_channel_type(struct genl_info *info, + enum nl80211_channel_type *channel_type) { - struct ieee80211_sta_ht_cap *ht_cap; - struct ieee80211_sta_vht_cap *vht_cap; - u32 control_freq, width; - - if (!info->attrs[NL80211_ATTR_WIPHY_FREQ]) - return -EINVAL; - - control_freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); + enum nl80211_channel_type tmp; - chandef->chan = ieee80211_get_channel(&rdev->wiphy, control_freq); - chandef->width = NL80211_CHAN_WIDTH_20_NOHT; - chandef->center_freq1 = control_freq; - chandef->center_freq2 = 0; - - /* Primary channel not allowed */ - if (!chandef->chan || chandef->chan->flags & IEEE80211_CHAN_DISABLED) - return -EINVAL; - - if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { - enum nl80211_channel_type chantype; - - chantype = nla_get_u32( - info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]); - - switch (chantype) { - case NL80211_CHAN_NO_HT: - case NL80211_CHAN_HT20: - case NL80211_CHAN_HT40PLUS: - case NL80211_CHAN_HT40MINUS: - cfg80211_chandef_create(chandef, chandef->chan, - chantype); - break; - default: - return -EINVAL; - } - } else if (info->attrs[NL80211_ATTR_CHANNEL_WIDTH]) { - chandef->width = - nla_get_u32(info->attrs[NL80211_ATTR_CHANNEL_WIDTH]); - if (info->attrs[NL80211_ATTR_CENTER_FREQ1]) - chandef->center_freq1 = - nla_get_u32( - info->attrs[NL80211_ATTR_CENTER_FREQ1]); - if (info->attrs[NL80211_ATTR_CENTER_FREQ2]) - chandef->center_freq2 = - nla_get_u32( - info->attrs[NL80211_ATTR_CENTER_FREQ2]); - } - - ht_cap = &rdev->wiphy.bands[chandef->chan->band]->ht_cap; - vht_cap = &rdev->wiphy.bands[chandef->chan->band]->vht_cap; - - if (!cfg80211_chan_def_valid(chandef)) - return -EINVAL; - - switch (chandef->width) { - case NL80211_CHAN_WIDTH_20: - if (!ht_cap->ht_supported) - return -EINVAL; - case NL80211_CHAN_WIDTH_20_NOHT: - width = 20; - break; - case NL80211_CHAN_WIDTH_40: - width = 40; - /* quick early regulatory check */ - if (chandef->center_freq1 < control_freq && - chandef->chan->flags & IEEE80211_CHAN_NO_HT40MINUS) - return -EINVAL; - if (chandef->center_freq1 > control_freq && - chandef->chan->flags & IEEE80211_CHAN_NO_HT40PLUS) - return -EINVAL; - if (!ht_cap->ht_supported) - return -EINVAL; - if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) || - ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT) - return -EINVAL; - break; - case NL80211_CHAN_WIDTH_80: - width = 80; - if (!vht_cap->vht_supported) - return -EINVAL; - break; - case NL80211_CHAN_WIDTH_80P80: - width = 80; - if (!vht_cap->vht_supported) - return -EINVAL; - if (!(vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)) - return -EINVAL; - break; - case NL80211_CHAN_WIDTH_160: - width = 160; - if (!vht_cap->vht_supported) - return -EINVAL; - if (!(vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ)) - return -EINVAL; - break; - default: - return -EINVAL; - } + if (!info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) + return false; - if (!cfg80211_secondary_chans_ok(&rdev->wiphy, chandef->center_freq1, - width, IEEE80211_CHAN_DISABLED)) - return -EINVAL; - if (chandef->center_freq2 && - !cfg80211_secondary_chans_ok(&rdev->wiphy, chandef->center_freq2, - width, IEEE80211_CHAN_DISABLED)) - return -EINVAL; + tmp = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]); + if (tmp != NL80211_CHAN_NO_HT && + tmp != NL80211_CHAN_HT20 && + tmp != NL80211_CHAN_HT40PLUS && + tmp != NL80211_CHAN_HT40MINUS) + return false; - /* TODO: missing regulatory check on bandwidth */ + if (channel_type) + *channel_type = tmp; - return 0; + return true; } static int __nl80211_set_channel(struct cfg80211_registered_device *rdev, struct wireless_dev *wdev, struct genl_info *info) { - struct cfg80211_chan_def chandef; + struct ieee80211_channel *channel; + enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; + u32 freq; int result; enum nl80211_iftype iftype = NL80211_IFTYPE_MONITOR; if (wdev) iftype = wdev->iftype; + if (!info->attrs[NL80211_ATTR_WIPHY_FREQ]) + return -EINVAL; + if (!nl80211_can_set_dev_channel(wdev)) return -EOPNOTSUPP; - result = nl80211_parse_chandef(rdev, info, &chandef); - if (result) - return result; + if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE] && + !nl80211_valid_channel_type(info, &channel_type)) + return -EINVAL; + + freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); mutex_lock(&rdev->devlist_mtx); switch (iftype) { @@ -1507,18 +1414,22 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev, result = -EBUSY; break; } - if (!cfg80211_reg_can_beacon(&rdev->wiphy, &chandef)) { + channel = rdev_freq_to_chan(rdev, freq, channel_type); + if (!channel || !cfg80211_can_beacon_sec_chan(&rdev->wiphy, + channel, + channel_type)) { result = -EINVAL; break; } - wdev->preset_chandef = chandef; + wdev->preset_chan = channel; + wdev->preset_chantype = channel_type; result = 0; break; case NL80211_IFTYPE_MESH_POINT: - result = cfg80211_set_mesh_channel(rdev, wdev, &chandef); + result = cfg80211_set_mesh_freq(rdev, wdev, freq, channel_type); break; case NL80211_IFTYPE_MONITOR: - result = cfg80211_set_monitor_channel(rdev, &chandef); + result = cfg80211_set_monitor_channel(rdev, freq, channel_type); break; default: result = -EINVAL; @@ -1838,35 +1749,6 @@ static inline u64 wdev_id(struct wireless_dev *wdev) ((u64)wiphy_to_dev(wdev->wiphy)->wiphy_idx << 32); } -static int nl80211_send_chandef(struct sk_buff *msg, - struct cfg80211_chan_def *chandef) -{ - WARN_ON(!cfg80211_chan_def_valid(chandef)); - - if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, - chandef->chan->center_freq)) - return -ENOBUFS; - switch (chandef->width) { - case NL80211_CHAN_WIDTH_20_NOHT: - case NL80211_CHAN_WIDTH_20: - case NL80211_CHAN_WIDTH_40: - if (nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, - cfg80211_get_chandef_type(chandef))) - return -ENOBUFS; - break; - default: - break; - } - if (nla_put_u32(msg, NL80211_ATTR_CHANNEL_WIDTH, chandef->width)) - return -ENOBUFS; - if (nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ1, chandef->center_freq1)) - return -ENOBUFS; - if (chandef->center_freq2 && - nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ2, chandef->center_freq2)) - return -ENOBUFS; - return 0; -} - static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags, struct cfg80211_registered_device *rdev, struct wireless_dev *wdev) @@ -1893,14 +1775,16 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flag goto nla_put_failure; if (rdev->ops->get_channel) { - int ret; - struct cfg80211_chan_def chandef; - - ret = rdev_get_channel(rdev, wdev, &chandef); - if (ret == 0) { - if (nl80211_send_chandef(msg, &chandef)) - goto nla_put_failure; - } + struct ieee80211_channel *chan; + enum nl80211_channel_type channel_type; + + chan = rdev_get_channel(rdev, wdev, &channel_type); + if (chan && + (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, + chan->center_freq) || + nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, + channel_type))) + goto nla_put_failure; } if (wdev->ssid_len) { @@ -2608,10 +2492,11 @@ static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev, wdev->iftype != NL80211_IFTYPE_P2P_GO) continue; - if (!wdev->preset_chandef.chan) + if (!wdev->preset_chan) continue; - params->chandef = wdev->preset_chandef; + params->channel = wdev->preset_chan; + params->channel_type = wdev->preset_chantype; ret = true; break; } @@ -2733,19 +2618,30 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) } if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { - err = nl80211_parse_chandef(rdev, info, ¶ms.chandef); - if (err) - return err; - } else if (wdev->preset_chandef.chan) { - params.chandef = wdev->preset_chandef; + enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; + + if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE] && + !nl80211_valid_channel_type(info, &channel_type)) + return -EINVAL; + + params.channel = rdev_freq_to_chan(rdev, + nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]), + channel_type); + if (!params.channel) + return -EINVAL; + params.channel_type = channel_type; + } else if (wdev->preset_chan) { + params.channel = wdev->preset_chan; + params.channel_type = wdev->preset_chantype; } else if (!nl80211_get_ap_channel(rdev, ¶ms)) return -EINVAL; - if (!cfg80211_reg_can_beacon(&rdev->wiphy, ¶ms.chandef)) + if (!cfg80211_can_beacon_sec_chan(&rdev->wiphy, params.channel, + params.channel_type)) return -EINVAL; mutex_lock(&rdev->devlist_mtx); - err = cfg80211_can_use_chan(rdev, wdev, params.chandef.chan, + err = cfg80211_can_use_chan(rdev, wdev, params.channel, CHAN_MODE_SHARED); mutex_unlock(&rdev->devlist_mtx); @@ -2754,9 +2650,10 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) err = rdev_start_ap(rdev, dev, ¶ms); if (!err) { - wdev->preset_chandef = params.chandef; + wdev->preset_chan = params.channel; + wdev->preset_chantype = params.channel_type; wdev->beacon_interval = params.beacon_interval; - wdev->channel = params.chandef.chan; + wdev->channel = params.channel; wdev->ssid_len = params.ssid_len; memcpy(wdev->ssid, params.ssid, wdev->ssid_len); } @@ -2890,52 +2787,29 @@ static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, rate = nla_nest_start(msg, attr); if (!rate) - return false; + goto nla_put_failure; /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */ bitrate = cfg80211_calculate_bitrate(info); /* report 16-bit bitrate only if we can */ bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0; - if (bitrate > 0 && - nla_put_u32(msg, NL80211_RATE_INFO_BITRATE32, bitrate)) - return false; - if (bitrate_compat > 0 && - nla_put_u16(msg, NL80211_RATE_INFO_BITRATE, bitrate_compat)) - return false; - - if (info->flags & RATE_INFO_FLAGS_MCS) { - if (nla_put_u8(msg, NL80211_RATE_INFO_MCS, info->mcs)) - return false; - if (info->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH && - nla_put_flag(msg, NL80211_RATE_INFO_40_MHZ_WIDTH)) - return false; - if (info->flags & RATE_INFO_FLAGS_SHORT_GI && - nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI)) - return false; - } else if (info->flags & RATE_INFO_FLAGS_VHT_MCS) { - if (nla_put_u8(msg, NL80211_RATE_INFO_VHT_MCS, info->mcs)) - return false; - if (nla_put_u8(msg, NL80211_RATE_INFO_VHT_NSS, info->nss)) - return false; - if (info->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH && - nla_put_flag(msg, NL80211_RATE_INFO_40_MHZ_WIDTH)) - return false; - if (info->flags & RATE_INFO_FLAGS_80_MHZ_WIDTH && - nla_put_flag(msg, NL80211_RATE_INFO_80_MHZ_WIDTH)) - return false; - if (info->flags & RATE_INFO_FLAGS_80P80_MHZ_WIDTH && - nla_put_flag(msg, NL80211_RATE_INFO_80P80_MHZ_WIDTH)) - return false; - if (info->flags & RATE_INFO_FLAGS_160_MHZ_WIDTH && - nla_put_flag(msg, NL80211_RATE_INFO_160_MHZ_WIDTH)) - return false; - if (info->flags & RATE_INFO_FLAGS_SHORT_GI && - nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI)) - return false; - } + if ((bitrate > 0 && + nla_put_u32(msg, NL80211_RATE_INFO_BITRATE32, bitrate)) || + (bitrate_compat > 0 && + nla_put_u16(msg, NL80211_RATE_INFO_BITRATE, bitrate_compat)) || + ((info->flags & RATE_INFO_FLAGS_MCS) && + nla_put_u8(msg, NL80211_RATE_INFO_MCS, info->mcs)) || + ((info->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) && + nla_put_flag(msg, NL80211_RATE_INFO_40_MHZ_WIDTH)) || + ((info->flags & RATE_INFO_FLAGS_SHORT_GI) && + nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI))) + goto nla_put_failure; nla_nest_end(msg, rate); return true; + +nla_put_failure: + return false; } static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq, @@ -5456,7 +5330,8 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) return -EINVAL; - if (!info->attrs[NL80211_ATTR_SSID] || + if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] || + !info->attrs[NL80211_ATTR_SSID] || !nla_len(info->attrs[NL80211_ATTR_SSID])) return -EINVAL; @@ -5491,17 +5366,35 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); } - err = nl80211_parse_chandef(rdev, info, &ibss.chandef); - if (err) - return err; + if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { + enum nl80211_channel_type channel_type; + + if (!nl80211_valid_channel_type(info, &channel_type)) + return -EINVAL; + + if (channel_type != NL80211_CHAN_NO_HT && + !(wiphy->features & NL80211_FEATURE_HT_IBSS)) + return -EINVAL; - if (!cfg80211_reg_can_beacon(&rdev->wiphy, &ibss.chandef)) + ibss.channel_type = channel_type; + } else { + ibss.channel_type = NL80211_CHAN_NO_HT; + } + + ibss.channel = rdev_freq_to_chan(rdev, + nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]), + ibss.channel_type); + if (!ibss.channel || + ibss.channel->flags & IEEE80211_CHAN_NO_IBSS || + ibss.channel->flags & IEEE80211_CHAN_DISABLED) return -EINVAL; - if (ibss.chandef.width > NL80211_CHAN_WIDTH_40) + /* Both channels should be able to initiate communication */ + if ((ibss.channel_type == NL80211_CHAN_HT40PLUS || + ibss.channel_type == NL80211_CHAN_HT40MINUS) && + !cfg80211_can_beacon_sec_chan(&rdev->wiphy, ibss.channel, + ibss.channel_type)) return -EINVAL; - if (ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT && - !(rdev->wiphy.features & NL80211_FEATURE_HT_IBSS)) ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED]; ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY]; @@ -5512,7 +5405,7 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) int n_rates = nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); struct ieee80211_supported_band *sband = - wiphy->bands[ibss.chandef.chan->band]; + wiphy->bands[ibss.channel->band]; err = ieee80211_get_ratemask(sband, rates, n_rates, &ibss.basic_rates); @@ -5534,8 +5427,7 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) if (IS_ERR(connkeys)) return PTR_ERR(connkeys); - if ((ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT) && - no_ht) { + if ((ibss.channel_type != NL80211_CHAN_NO_HT) && no_ht) { kfree(connkeys); return -EINVAL; } @@ -6056,11 +5948,12 @@ static int nl80211_remain_on_channel(struct sk_buff *skb, { struct cfg80211_registered_device *rdev = info->user_ptr[0]; struct wireless_dev *wdev = info->user_ptr[1]; - struct cfg80211_chan_def chandef; + struct ieee80211_channel *chan; struct sk_buff *msg; void *hdr; u64 cookie; - u32 duration; + enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; + u32 freq, duration; int err; if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] || @@ -6081,9 +5974,14 @@ static int nl80211_remain_on_channel(struct sk_buff *skb, duration > rdev->wiphy.max_remain_on_channel_duration) return -EINVAL; - err = nl80211_parse_chandef(rdev, info, &chandef); - if (err) - return err; + if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE] && + !nl80211_valid_channel_type(info, &channel_type)) + return -EINVAL; + + freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); + chan = rdev_freq_to_chan(rdev, freq, channel_type); + if (chan == NULL) + return -EINVAL; msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) @@ -6097,8 +5995,8 @@ static int nl80211_remain_on_channel(struct sk_buff *skb, goto free_msg; } - err = rdev_remain_on_channel(rdev, wdev, chandef.chan, - duration, &cookie); + err = rdev_remain_on_channel(rdev, wdev, chan, channel_type, duration, + &cookie); if (err) goto free_msg; @@ -6317,7 +6215,10 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) { struct cfg80211_registered_device *rdev = info->user_ptr[0]; struct wireless_dev *wdev = info->user_ptr[1]; - struct cfg80211_chan_def chandef; + struct ieee80211_channel *chan; + enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; + bool channel_type_valid = false; + u32 freq; int err; void *hdr = NULL; u64 cookie; @@ -6327,7 +6228,8 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) dont_wait_for_ack = info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK]; - if (!info->attrs[NL80211_ATTR_FRAME]) + if (!info->attrs[NL80211_ATTR_FRAME] || + !info->attrs[NL80211_ATTR_WIPHY_FREQ]) return -EINVAL; if (!rdev->ops->mgmt_tx) @@ -6362,6 +6264,12 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) } + if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { + if (!nl80211_valid_channel_type(info, &channel_type)) + return -EINVAL; + channel_type_valid = true; + } + offchan = info->attrs[NL80211_ATTR_OFFCHANNEL_TX_OK]; if (offchan && !(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX)) @@ -6369,9 +6277,10 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) no_cck = nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]); - err = nl80211_parse_chandef(rdev, info, &chandef); - if (err) - return err; + freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); + chan = rdev_freq_to_chan(rdev, freq, channel_type); + if (chan == NULL) + return -EINVAL; if (!dont_wait_for_ack) { msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); @@ -6387,7 +6296,8 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) } } - err = cfg80211_mlme_mgmt_tx(rdev, wdev, chandef.chan, offchan, wait, + err = cfg80211_mlme_mgmt_tx(rdev, wdev, chan, offchan, channel_type, + channel_type_valid, wait, nla_data(info->attrs[NL80211_ATTR_FRAME]), nla_len(info->attrs[NL80211_ATTR_FRAME]), no_cck, dont_wait_for_ack, &cookie); @@ -6651,12 +6561,21 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info) } if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { - err = nl80211_parse_chandef(rdev, info, &setup.chandef); - if (err) - return err; + enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; + + if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE] && + !nl80211_valid_channel_type(info, &channel_type)) + return -EINVAL; + + setup.channel = rdev_freq_to_chan(rdev, + nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]), + channel_type); + if (!setup.channel) + return -EINVAL; + setup.channel_type = channel_type; } else { /* cfg80211_join_mesh() will sort it out */ - setup.chandef.chan = NULL; + setup.channel = NULL; } return cfg80211_join_mesh(rdev, dev, &setup, &cfg); @@ -8476,6 +8395,7 @@ static void nl80211_send_remain_on_chan_event( int cmd, struct cfg80211_registered_device *rdev, struct wireless_dev *wdev, u64 cookie, struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, unsigned int duration, gfp_t gfp) { struct sk_buff *msg; @@ -8496,8 +8416,7 @@ static void nl80211_send_remain_on_chan_event( wdev->netdev->ifindex)) || nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)) || nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, chan->center_freq) || - nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, - NL80211_CHAN_NO_HT) || + nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, channel_type) || nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie)) goto nla_put_failure; @@ -8519,20 +8438,23 @@ static void nl80211_send_remain_on_chan_event( void nl80211_send_remain_on_channel(struct cfg80211_registered_device *rdev, struct wireless_dev *wdev, u64 cookie, struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, unsigned int duration, gfp_t gfp) { nl80211_send_remain_on_chan_event(NL80211_CMD_REMAIN_ON_CHANNEL, rdev, wdev, cookie, chan, - duration, gfp); + channel_type, duration, gfp); } void nl80211_send_remain_on_channel_cancel( struct cfg80211_registered_device *rdev, struct wireless_dev *wdev, - u64 cookie, struct ieee80211_channel *chan, gfp_t gfp) + u64 cookie, struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, gfp_t gfp) { nl80211_send_remain_on_chan_event(NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL, - rdev, wdev, cookie, chan, 0, gfp); + rdev, wdev, cookie, chan, + channel_type, 0, gfp); } void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, @@ -8888,8 +8810,8 @@ void nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev, } void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev, - struct net_device *netdev, - struct cfg80211_chan_def *chandef, gfp_t gfp) + struct net_device *netdev, int freq, + enum nl80211_channel_type type, gfp_t gfp) { struct sk_buff *msg; void *hdr; @@ -8904,10 +8826,9 @@ void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev, return; } - if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex)) - goto nla_put_failure; - - if (nl80211_send_chandef(msg, chandef)) + if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || + nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq) || + nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, type)) goto nla_put_failure; genlmsg_end(msg, hdr); @@ -9106,53 +9027,6 @@ void cfg80211_report_obss_beacon(struct wiphy *wiphy, } EXPORT_SYMBOL(cfg80211_report_obss_beacon); -void cfg80211_tdls_oper_request(struct net_device *dev, const u8 *peer, - enum nl80211_tdls_operation oper, - u16 reason_code, gfp_t gfp) -{ - struct wireless_dev *wdev = dev->ieee80211_ptr; - struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); - struct sk_buff *msg; - void *hdr; - int err; - - trace_cfg80211_tdls_oper_request(wdev->wiphy, dev, peer, oper, - reason_code); - - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); - if (!msg) - return; - - hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_TDLS_OPER); - if (!hdr) { - nlmsg_free(msg); - return; - } - - if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || - nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || - nla_put_u8(msg, NL80211_ATTR_TDLS_OPERATION, oper) || - nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer) || - (reason_code > 0 && - nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason_code))) - goto nla_put_failure; - - err = genlmsg_end(msg, hdr); - if (err < 0) { - nlmsg_free(msg); - return; - } - - genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, - nl80211_mlme_mcgrp.id, gfp); - return; - - nla_put_failure: - genlmsg_cancel(msg, hdr); - nlmsg_free(msg); -} -EXPORT_SYMBOL(cfg80211_tdls_oper_request); - static int nl80211_netlink_notify(struct notifier_block * nb, unsigned long state, void *_notify) diff --git a/trunk/net/wireless/nl80211.h b/trunk/net/wireless/nl80211.h index 2acba8477e9d..f6153516068c 100644 --- a/trunk/net/wireless/nl80211.h +++ b/trunk/net/wireless/nl80211.h @@ -76,11 +76,13 @@ void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev, void nl80211_send_remain_on_channel(struct cfg80211_registered_device *rdev, struct wireless_dev *wdev, u64 cookie, struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, unsigned int duration, gfp_t gfp); void nl80211_send_remain_on_channel_cancel( struct cfg80211_registered_device *rdev, struct wireless_dev *wdev, - u64 cookie, struct ieee80211_channel *chan, gfp_t gfp); + u64 cookie, struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, gfp_t gfp); void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, struct net_device *dev, const u8 *mac_addr, @@ -127,8 +129,8 @@ void nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev, const u8 *bssid, bool preauth, gfp_t gfp); void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev, - struct net_device *dev, - struct cfg80211_chan_def *chandef, gfp_t gfp); + struct net_device *dev, int freq, + enum nl80211_channel_type type, gfp_t gfp); bool nl80211_unexpected_frame(struct net_device *dev, const u8 *addr, gfp_t gfp); diff --git a/trunk/net/wireless/rdev-ops.h b/trunk/net/wireless/rdev-ops.h index 6c0c8191f837..6e5fa659068d 100644 --- a/trunk/net/wireless/rdev-ops.h +++ b/trunk/net/wireless/rdev-ops.h @@ -359,11 +359,12 @@ rdev_libertas_set_mesh_channel(struct cfg80211_registered_device *rdev, static inline int rdev_set_monitor_channel(struct cfg80211_registered_device *rdev, - struct cfg80211_chan_def *chandef) + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type) { int ret; - trace_rdev_set_monitor_channel(&rdev->wiphy, chandef); - ret = rdev->ops->set_monitor_channel(&rdev->wiphy, chandef); + trace_rdev_set_monitor_channel(&rdev->wiphy, chan, channel_type); + ret = rdev->ops->set_monitor_channel(&rdev->wiphy, chan, channel_type); trace_rdev_return_int(&rdev->wiphy, ret); return ret; } @@ -599,12 +600,14 @@ static inline int rdev_remain_on_channel(struct cfg80211_registered_device *rdev, struct wireless_dev *wdev, struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, unsigned int duration, u64 *cookie) { int ret; - trace_rdev_remain_on_channel(&rdev->wiphy, wdev, chan, duration); + trace_rdev_remain_on_channel(&rdev->wiphy, wdev, chan, channel_type, + duration); ret = rdev->ops->remain_on_channel(&rdev->wiphy, wdev, chan, - duration, cookie); + channel_type, duration, cookie); trace_rdev_return_int_cookie(&rdev->wiphy, ret, *cookie); return ret; } @@ -623,15 +626,17 @@ rdev_cancel_remain_on_channel(struct cfg80211_registered_device *rdev, static inline int rdev_mgmt_tx(struct cfg80211_registered_device *rdev, struct wireless_dev *wdev, struct ieee80211_channel *chan, bool offchan, - unsigned int wait, const u8 *buf, size_t len, - bool no_cck, bool dont_wait_for_ack, u64 *cookie) + enum nl80211_channel_type channel_type, + bool channel_type_valid, unsigned int wait, + const u8 *buf, size_t len, bool no_cck, + bool dont_wait_for_ack, u64 *cookie) { int ret; - trace_rdev_mgmt_tx(&rdev->wiphy, wdev, chan, offchan, - wait, no_cck, dont_wait_for_ack); + trace_rdev_mgmt_tx(&rdev->wiphy, wdev, chan, offchan, channel_type, + channel_type_valid, wait, no_cck, dont_wait_for_ack); ret = rdev->ops->mgmt_tx(&rdev->wiphy, wdev, chan, offchan, - wait, buf, len, no_cck, - dont_wait_for_ack, cookie); + channel_type, channel_type_valid, wait, buf, + len, no_cck, dont_wait_for_ack, cookie); trace_rdev_return_int_cookie(&rdev->wiphy, ret, *cookie); return ret; } @@ -843,17 +848,14 @@ static inline void rdev_get_et_strings(struct cfg80211_registered_device *rdev, trace_rdev_return_void(&rdev->wiphy); } -static inline int -rdev_get_channel(struct cfg80211_registered_device *rdev, - struct wireless_dev *wdev, - struct cfg80211_chan_def *chandef) +static inline struct ieee80211_channel +*rdev_get_channel(struct cfg80211_registered_device *rdev, + struct wireless_dev *wdev, enum nl80211_channel_type *type) { - int ret; - + struct ieee80211_channel *ret; trace_rdev_get_channel(&rdev->wiphy, wdev); - ret = rdev->ops->get_channel(&rdev->wiphy, wdev, chandef); - trace_rdev_return_chandef(&rdev->wiphy, ret, chandef); - + ret = rdev->ops->get_channel(&rdev->wiphy, wdev, type); + trace_rdev_return_channel(&rdev->wiphy, ret, *type); return ret; } diff --git a/trunk/net/wireless/reg.c b/trunk/net/wireless/reg.c index b75756b05af7..bcc7d7ee5a51 100644 --- a/trunk/net/wireless/reg.c +++ b/trunk/net/wireless/reg.c @@ -141,8 +141,9 @@ static const struct ieee80211_regdomain world_regdom = { .reg_rules = { /* IEEE 802.11b/g, channels 1..11 */ REG_RULE(2412-10, 2462+10, 40, 6, 20, 0), - /* IEEE 802.11b/g, channels 12..13. */ - REG_RULE(2467-10, 2472+10, 40, 6, 20, + /* IEEE 802.11b/g, channels 12..13. No HT40 + * channel fits here. */ + REG_RULE(2467-10, 2472+10, 20, 6, 20, NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS), /* IEEE 802.11 channel 14 - Only JP enables diff --git a/trunk/net/wireless/scan.c b/trunk/net/wireless/scan.c index 9596015975d2..7f97a087f452 100644 --- a/trunk/net/wireless/scan.c +++ b/trunk/net/wireless/scan.c @@ -771,38 +771,6 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, return found; } -static struct ieee80211_channel * -cfg80211_get_bss_channel(struct wiphy *wiphy, const u8 *ie, size_t ielen, - struct ieee80211_channel *channel) -{ - const u8 *tmp; - u32 freq; - int channel_number = -1; - - tmp = cfg80211_find_ie(WLAN_EID_DS_PARAMS, ie, ielen); - if (tmp && tmp[1] == 1) { - channel_number = tmp[2]; - } else { - tmp = cfg80211_find_ie(WLAN_EID_HT_OPERATION, ie, ielen); - if (tmp && tmp[1] >= sizeof(struct ieee80211_ht_operation)) { - struct ieee80211_ht_operation *htop = (void *)(tmp + 2); - - channel_number = htop->primary_chan; - } - } - - if (channel_number < 0) - return channel; - - freq = ieee80211_channel_to_frequency(channel_number, channel->band); - channel = ieee80211_get_channel(wiphy, freq); - if (!channel) - return NULL; - if (channel->flags & IEEE80211_CHAN_DISABLED) - return NULL; - return channel; -} - struct cfg80211_bss* cfg80211_inform_bss(struct wiphy *wiphy, struct ieee80211_channel *channel, @@ -822,10 +790,6 @@ cfg80211_inform_bss(struct wiphy *wiphy, (signal < 0 || signal > 100))) return NULL; - channel = cfg80211_get_bss_channel(wiphy, ie, ielen, channel); - if (!channel) - return NULL; - res = kzalloc(sizeof(*res) + privsz + ielen, gfp); if (!res) return NULL; @@ -875,13 +839,11 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy, s32 signal, gfp_t gfp) { struct cfg80211_internal_bss *res; + size_t ielen = len - offsetof(struct ieee80211_mgmt, u.probe_resp.variable); size_t privsz; - BUILD_BUG_ON(offsetof(struct ieee80211_mgmt, u.probe_resp.variable) != - offsetof(struct ieee80211_mgmt, u.beacon.variable)); - trace_cfg80211_inform_bss_frame(wiphy, channel, mgmt, len, signal); if (WARN_ON(!mgmt)) @@ -899,11 +861,6 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy, privsz = wiphy->bss_priv_size; - channel = cfg80211_get_bss_channel(wiphy, mgmt->u.beacon.variable, - ielen, channel); - if (!channel) - return NULL; - res = kzalloc(sizeof(*res) + privsz + ielen, gfp); if (!res) return NULL; diff --git a/trunk/net/wireless/trace.h b/trunk/net/wireless/trace.h index 2134576f426e..8e03c6382a8a 100644 --- a/trunk/net/wireless/trace.h +++ b/trunk/net/wireless/trace.h @@ -20,26 +20,29 @@ #define MAC_PR_FMT "%pM" #define MAC_PR_ARG(entry_mac) (__entry->entry_mac) -#define MAXNAME 32 -#define WIPHY_ENTRY __array(char, wiphy_name, 32) -#define WIPHY_ASSIGN strlcpy(__entry->wiphy_name, wiphy_name(wiphy), MAXNAME) -#define WIPHY_PR_FMT "%s" -#define WIPHY_PR_ARG __entry->wiphy_name - -#define WDEV_ENTRY __field(u32, id) -#define WDEV_ASSIGN (__entry->id) = (wdev ? wdev->identifier : 0) -#define WDEV_PR_FMT "wdev(%u)" -#define WDEV_PR_ARG (__entry->id) - -#define NETDEV_ENTRY __array(char, name, IFNAMSIZ) \ - __field(int, ifindex) +#define WIPHY_ENTRY MAC_ENTRY(wiphy_mac) +#define WIPHY_ASSIGN MAC_ASSIGN(wiphy_mac, wiphy->perm_addr) +#define WIPHY_PR_FMT "wiphy " MAC_PR_FMT +#define WIPHY_PR_ARG MAC_PR_ARG(wiphy_mac) + +#define WDEV_ENTRY __field(u32, id) +#define WDEV_ASSIGN (__entry->id) = (wdev ? wdev->identifier : 0) +#define WDEV_PR_FMT ", wdev id: %u" +#define WDEV_PR_ARG (__entry->id) + +#define NETDEV_ENTRY __array(char, name, IFNAMSIZ) \ + MAC_ENTRY(netdev_addr) \ + __field(int, ifindex) #define NETDEV_ASSIGN \ do { \ memcpy(__entry->name, netdev->name, IFNAMSIZ); \ + MAC_ASSIGN(netdev_addr, netdev->dev_addr); \ (__entry->ifindex) = (netdev->ifindex); \ } while (0) -#define NETDEV_PR_FMT "netdev:%s(%d)" -#define NETDEV_PR_ARG __entry->name, __entry->ifindex +#define NETDEV_PR_FMT ", netdev - name: %s, addr: " MAC_PR_FMT \ + ", intf index: %d" +#define NETDEV_PR_ARG (__entry->name), MAC_PR_ARG(netdev_addr), \ + (__entry->ifindex) #define MESH_CFG_ENTRY __field(u16, dot11MeshRetryTimeout) \ __field(u16, dot11MeshConfirmTimeout) \ @@ -120,37 +123,9 @@ __entry->center_freq = 0; \ } \ } while (0) -#define CHAN_PR_FMT "band: %d, freq: %u" +#define CHAN_PR_FMT ", band: %d, freq: %u" #define CHAN_PR_ARG __entry->band, __entry->center_freq -#define CHAN_DEF_ENTRY __field(enum ieee80211_band, band) \ - __field(u32, control_freq) \ - __field(u32, width) \ - __field(u32, center_freq1) \ - __field(u32, center_freq2) -#define CHAN_DEF_ASSIGN(chandef) \ - do { \ - if ((chandef) && (chandef)->chan) { \ - __entry->band = (chandef)->chan->band; \ - __entry->control_freq = \ - (chandef)->chan->center_freq; \ - __entry->width = (chandef)->width; \ - __entry->center_freq1 = (chandef)->center_freq1;\ - __entry->center_freq2 = (chandef)->center_freq2;\ - } else { \ - __entry->band = 0; \ - __entry->control_freq = 0; \ - __entry->width = 0; \ - __entry->center_freq1 = 0; \ - __entry->center_freq2 = 0; \ - } \ - } while (0) -#define CHAN_DEF_PR_FMT \ - "band: %d, control freq: %u, width: %d, cf1: %u, cf2: %u" -#define CHAN_DEF_PR_ARG __entry->band, __entry->control_freq, \ - __entry->width, __entry->center_freq1, \ - __entry->center_freq2 - #define SINFO_ENTRY __field(int, generation) \ __field(u32, connected_time) \ __field(u32, inactive_time) \ @@ -338,7 +313,7 @@ DECLARE_EVENT_CLASS(wiphy_wdev_evt, WIPHY_ASSIGN; WDEV_ASSIGN; ), - TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT, WIPHY_PR_ARG, WDEV_PR_ARG) + TP_printk(WIPHY_PR_FMT WDEV_PR_FMT, WIPHY_PR_ARG, WDEV_PR_ARG) ); DEFINE_EVENT(wiphy_wdev_evt, rdev_return_wdev, @@ -365,7 +340,7 @@ TRACE_EVENT(rdev_change_virtual_intf, NETDEV_ASSIGN; __entry->type = type; ), - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", type: %d", + TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", type: %d", WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->type) ); @@ -387,7 +362,7 @@ DECLARE_EVENT_CLASS(key_handle, __entry->key_index = key_index; __entry->pairwise = pairwise; ), - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", key_index: %u, pairwise: %s, mac addr: " MAC_PR_FMT, + TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", key_index: %u, pairwise: %s, mac addr: " MAC_PR_FMT, WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->key_index, BOOL_TO_STR(__entry->pairwise), MAC_PR_ARG(mac_addr)) ); @@ -428,7 +403,7 @@ TRACE_EVENT(rdev_set_default_key, __entry->unicast = unicast; __entry->multicast = multicast; ), - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", key index: %u, unicast: %s, multicast: %s", + TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", key index: %u, unicast: %s, multicast: %s", WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->key_index, BOOL_TO_STR(__entry->unicast), BOOL_TO_STR(__entry->multicast)) @@ -447,7 +422,7 @@ TRACE_EVENT(rdev_set_default_mgmt_key, NETDEV_ASSIGN; __entry->key_index = key_index; ), - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", key index: %u", + TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", key index: %u", WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->key_index) ); @@ -458,7 +433,7 @@ TRACE_EVENT(rdev_start_ap, TP_STRUCT__entry( WIPHY_ENTRY NETDEV_ENTRY - CHAN_DEF_ENTRY + CHAN_ENTRY __field(int, beacon_interval) __field(int, dtim_period) __array(char, ssid, IEEE80211_MAX_SSID_LEN + 1) @@ -471,7 +446,7 @@ TRACE_EVENT(rdev_start_ap, TP_fast_assign( WIPHY_ASSIGN; NETDEV_ASSIGN; - CHAN_DEF_ASSIGN(&settings->chandef); + CHAN_ASSIGN(settings->channel); __entry->beacon_interval = settings->beacon_interval; __entry->dtim_period = settings->dtim_period; __entry->hidden_ssid = settings->hidden_ssid; @@ -482,11 +457,11 @@ TRACE_EVENT(rdev_start_ap, memset(__entry->ssid, 0, IEEE80211_MAX_SSID_LEN + 1); memcpy(__entry->ssid, settings->ssid, settings->ssid_len); ), - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", AP settings - ssid: %s, " - CHAN_DEF_PR_FMT ", beacon interval: %d, dtim period: %d, " + TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", AP settings - ssid: %s, " + CHAN_PR_FMT ", beacon interval: %d, dtim period: %d, " "hidden ssid: %d, wpa versions: %u, privacy: %s, " "auth type: %d, inactivity timeout: %d", - WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->ssid, CHAN_DEF_PR_ARG, + WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->ssid, CHAN_PR_ARG, __entry->beacon_interval, __entry->dtim_period, __entry->hidden_ssid, __entry->wpa_ver, BOOL_TO_STR(__entry->privacy), __entry->auth_type, @@ -535,7 +510,7 @@ TRACE_EVENT(rdev_change_beacon, info->probe_resp, info->probe_resp_len); } ), - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT, WIPHY_PR_ARG, NETDEV_PR_ARG) + TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT, WIPHY_PR_ARG, NETDEV_PR_ARG) ); DECLARE_EVENT_CLASS(wiphy_netdev_evt, @@ -549,7 +524,7 @@ DECLARE_EVENT_CLASS(wiphy_netdev_evt, WIPHY_ASSIGN; NETDEV_ASSIGN; ), - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT, WIPHY_PR_ARG, NETDEV_PR_ARG) + TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT, WIPHY_PR_ARG, NETDEV_PR_ARG) ); DEFINE_EVENT(wiphy_netdev_evt, rdev_stop_ap, @@ -627,7 +602,7 @@ DECLARE_EVENT_CLASS(station_add_change, memcpy(__entry->ht_capa, params->ht_capa, sizeof(struct ieee80211_ht_cap)); ), - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", station mac: " MAC_PR_FMT + TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", station mac: " MAC_PR_FMT ", station flags mask: %u, station flags set: %u, " "station modify mask: %u, listen interval: %d, aid: %u, " "plink action: %u, plink state: %u, uapsd queues: %u", @@ -663,7 +638,7 @@ DECLARE_EVENT_CLASS(wiphy_netdev_mac_evt, NETDEV_ASSIGN; MAC_ASSIGN(sta_mac, mac); ), - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", mac: " MAC_PR_FMT, + TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", mac: " MAC_PR_FMT, WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(sta_mac)) ); @@ -703,7 +678,7 @@ TRACE_EVENT(rdev_dump_station, MAC_ASSIGN(sta_mac, mac); __entry->idx = idx; ), - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", station mac: " MAC_PR_FMT ", idx: %d", + TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", station mac: " MAC_PR_FMT ", idx: %d", WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(sta_mac), __entry->idx) ); @@ -741,7 +716,7 @@ DECLARE_EVENT_CLASS(mpath_evt, MAC_ASSIGN(dst, dst); MAC_ASSIGN(next_hop, next_hop); ), - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", destination: " MAC_PR_FMT ", next hop: " MAC_PR_FMT, + TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", destination: " MAC_PR_FMT ", next hop: " MAC_PR_FMT, WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(dst), MAC_PR_ARG(next_hop)) ); @@ -782,7 +757,7 @@ TRACE_EVENT(rdev_dump_mpath, MAC_ASSIGN(next_hop, next_hop); __entry->idx = idx; ), - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", index: %d, destination: " + TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", index: %d, destination: " MAC_PR_FMT ", next hop: " MAC_PR_FMT, WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->idx, MAC_PR_ARG(dst), MAC_PR_ARG(next_hop)) @@ -859,7 +834,7 @@ TRACE_EVENT(rdev_update_mesh_config, MESH_CFG_ASSIGN; __entry->mask = mask; ), - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", mask: %u", + TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", mask: %u", WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->mask) ); @@ -878,7 +853,7 @@ TRACE_EVENT(rdev_join_mesh, NETDEV_ASSIGN; MESH_CFG_ASSIGN; ), - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT, + TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT, WIPHY_PR_ARG, NETDEV_PR_ARG) ); @@ -904,7 +879,7 @@ TRACE_EVENT(rdev_change_bss, __entry->ap_isolate = params->ap_isolate; __entry->ht_opmode = params->ht_opmode; ), - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", use cts prot: %d, " + TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", use cts prot: %d, " "use short preamble: %d, use short slot time: %d, " "ap isolate: %d, ht opmode: %d", WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->use_cts_prot, @@ -934,7 +909,7 @@ TRACE_EVENT(rdev_set_txq_params, __entry->cwmax = params->cwmax; __entry->aifs = params->aifs; ), - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", ac: %d, txop: %u, cwmin: %u, cwmax: %u, aifs: %u", + TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", ac: %d, txop: %u, cwmin: %u, cwmax: %u, aifs: %u", WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->ac, __entry->txop, __entry->cwmin, __entry->cwmax, __entry->aifs) ); @@ -953,24 +928,26 @@ TRACE_EVENT(rdev_libertas_set_mesh_channel, NETDEV_ASSIGN; CHAN_ASSIGN(chan); ), - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " CHAN_PR_FMT, WIPHY_PR_ARG, + TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT CHAN_PR_FMT, WIPHY_PR_ARG, NETDEV_PR_ARG, CHAN_PR_ARG) ); TRACE_EVENT(rdev_set_monitor_channel, - TP_PROTO(struct wiphy *wiphy, - struct cfg80211_chan_def *chandef), - TP_ARGS(wiphy, chandef), + TP_PROTO(struct wiphy *wiphy, struct ieee80211_channel *chan, + enum nl80211_channel_type chan_type), + TP_ARGS(wiphy, chan, chan_type), TP_STRUCT__entry( WIPHY_ENTRY - CHAN_DEF_ENTRY + CHAN_ENTRY + __field(enum nl80211_channel_type, chan_type) ), TP_fast_assign( WIPHY_ASSIGN; - CHAN_DEF_ASSIGN(chandef); + CHAN_ASSIGN(chan); + __entry->chan_type = chan_type; ), - TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT, - WIPHY_PR_ARG, CHAN_DEF_PR_ARG) + TP_printk(WIPHY_PR_FMT CHAN_PR_FMT ", channel type : %d", + WIPHY_PR_ARG, CHAN_PR_ARG, __entry->chan_type) ); TRACE_EVENT(rdev_auth, @@ -992,7 +969,7 @@ TRACE_EVENT(rdev_auth, memset(__entry->bssid, 0, ETH_ALEN); __entry->auth_type = req->auth_type; ), - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", auth type: %d, bssid: " MAC_PR_FMT, + TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", auth type: %d, bssid: " MAC_PR_FMT, WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->auth_type, MAC_PR_ARG(bssid)) ); @@ -1020,7 +997,7 @@ TRACE_EVENT(rdev_assoc, __entry->use_mfp = req->use_mfp; __entry->flags = req->flags; ), - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: " MAC_PR_FMT + TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", bssid: " MAC_PR_FMT ", previous bssid: " MAC_PR_FMT ", use mfp: %s, flags: %u", WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid), MAC_PR_ARG(prev_bssid), BOOL_TO_STR(__entry->use_mfp), @@ -1043,7 +1020,7 @@ TRACE_EVENT(rdev_deauth, MAC_ASSIGN(bssid, req->bssid); __entry->reason_code = req->reason_code; ), - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: " MAC_PR_FMT ", reason: %u", + TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", bssid: " MAC_PR_FMT ", reason: %u", WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid), __entry->reason_code) ); @@ -1069,7 +1046,7 @@ TRACE_EVENT(rdev_disassoc, __entry->reason_code = req->reason_code; __entry->local_state_change = req->local_state_change; ), - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: " MAC_PR_FMT + TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", bssid: " MAC_PR_FMT ", reason: %u, local state change: %s", WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid), __entry->reason_code, @@ -1090,7 +1067,7 @@ TRACE_EVENT(rdev_mgmt_tx_cancel_wait, WDEV_ASSIGN; __entry->cookie = cookie; ), - TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", cookie: %llu ", + TP_printk(WIPHY_PR_FMT WDEV_PR_FMT ", cookie: %llu ", WIPHY_PR_ARG, WDEV_PR_ARG, __entry->cookie) ); @@ -1110,7 +1087,7 @@ TRACE_EVENT(rdev_set_power_mgmt, __entry->enabled = enabled; __entry->timeout = timeout; ), - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", %senabled, timeout: %d ", + TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", %senabled, timeout: %d ", WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->enabled ? "" : "not ", __entry->timeout) ); @@ -1140,7 +1117,7 @@ TRACE_EVENT(rdev_connect, __entry->wpa_versions = sme->crypto.wpa_versions; __entry->flags = sme->flags; ), - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: " MAC_PR_FMT + TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", bssid: " MAC_PR_FMT ", ssid: %s, auth type: %d, privacy: %s, wpa versions: %u, " "flags: %u", WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid), __entry->ssid, @@ -1165,7 +1142,7 @@ TRACE_EVENT(rdev_set_cqm_rssi_config, __entry->rssi_thold = rssi_thold; __entry->rssi_hyst = rssi_hyst; ), - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT + TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", rssi_thold: %d, rssi_hyst: %u ", WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->rssi_thold, __entry->rssi_hyst) @@ -1189,7 +1166,7 @@ TRACE_EVENT(rdev_set_cqm_txe_config, __entry->pkts = pkts; __entry->intvl = intvl; ), - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", rate: %u, packets: %u, interval: %u", + TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", rate: %u, packets: %u, interval: %u", WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->rate, __entry->pkts, __entry->intvl) ); @@ -1208,7 +1185,7 @@ TRACE_EVENT(rdev_disconnect, NETDEV_ASSIGN; __entry->reason_code = reason_code; ), - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", reason code: %u", WIPHY_PR_ARG, + TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", reason code: %u", WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->reason_code) ); @@ -1229,7 +1206,7 @@ TRACE_EVENT(rdev_join_ibss, memset(__entry->ssid, 0, IEEE80211_MAX_SSID_LEN + 1); memcpy(__entry->ssid, params->ssid, params->ssid_len); ), - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: " MAC_PR_FMT ", ssid: %s", + TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", bssid: " MAC_PR_FMT ", ssid: %s", WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid), __entry->ssid) ); @@ -1269,7 +1246,7 @@ TRACE_EVENT(rdev_set_tx_power, __entry->type = type; __entry->mbm = mbm; ), - TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", type: %u, mbm: %d", + TP_printk(WIPHY_PR_FMT WDEV_PR_FMT ", type: %d, mbm: %d", WIPHY_PR_ARG, WDEV_PR_ARG,__entry->type, __entry->mbm) ); @@ -1330,7 +1307,7 @@ TRACE_EVENT(rdev_set_bitrate_mask, NETDEV_ASSIGN; MAC_ASSIGN(peer, peer); ), - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", peer: " MAC_PR_FMT, + TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", peer: " MAC_PR_FMT, WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer)) ); @@ -1350,7 +1327,7 @@ TRACE_EVENT(rdev_mgmt_frame_register, __entry->frame_type = frame_type; __entry->reg = reg; ), - TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", frame_type: 0x%.2x, reg: %s ", + TP_printk(WIPHY_PR_FMT WDEV_PR_FMT ", frame_type: %u, reg: %s ", WIPHY_PR_ARG, WDEV_PR_ARG, __entry->frame_type, __entry->reg ? "true" : "false") ); @@ -1436,7 +1413,7 @@ TRACE_EVENT(rdev_sched_scan_start, WIPHY_ASSIGN; NETDEV_ASSIGN; ), - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT, + TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT, WIPHY_PR_ARG, NETDEV_PR_ARG) ); @@ -1464,7 +1441,7 @@ TRACE_EVENT(rdev_tdls_mgmt, __entry->status_code = status_code; memcpy(__get_dynamic_array(buf), buf, len); ), - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT ", action_code: %u, " + TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT MAC_PR_FMT ", action_code: %u, " "dialog_token: %u, status_code: %u, buf: %#.2x ", WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer), __entry->action_code, __entry->dialog_token, @@ -1484,7 +1461,7 @@ TRACE_EVENT(rdev_dump_survey, NETDEV_ASSIGN; __entry->idx = idx; ), - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", index: %d", + TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", index: %d", WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->idx) ); @@ -1541,7 +1518,7 @@ TRACE_EVENT(rdev_tdls_oper, MAC_ASSIGN(peer, peer); __entry->oper = oper; ), - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT ", oper: %d", + TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT MAC_PR_FMT ", oper: %d", WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer), __entry->oper) ); @@ -1559,7 +1536,7 @@ DECLARE_EVENT_CLASS(rdev_pmksa, NETDEV_ASSIGN; MAC_ASSIGN(bssid, pmksa->bssid); ), - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: " MAC_PR_FMT, + TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", bssid: " MAC_PR_FMT, WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid)) ); @@ -1577,7 +1554,7 @@ TRACE_EVENT(rdev_probe_client, NETDEV_ASSIGN; MAC_ASSIGN(peer, peer); ), - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT, + TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT MAC_PR_FMT, WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer)) ); @@ -1596,22 +1573,25 @@ DEFINE_EVENT(rdev_pmksa, rdev_del_pmksa, TRACE_EVENT(rdev_remain_on_channel, TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev, struct ieee80211_channel *chan, - unsigned int duration), - TP_ARGS(wiphy, wdev, chan, duration), + enum nl80211_channel_type channel_type, unsigned int duration), + TP_ARGS(wiphy, wdev, chan, channel_type, duration), TP_STRUCT__entry( WIPHY_ENTRY WDEV_ENTRY CHAN_ENTRY + __field(enum nl80211_channel_type, channel_type) __field(unsigned int, duration) ), TP_fast_assign( WIPHY_ASSIGN; WDEV_ASSIGN; CHAN_ASSIGN(chan); + __entry->channel_type = channel_type; __entry->duration = duration; ), - TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", " CHAN_PR_FMT ", duration: %u", - WIPHY_PR_ARG, WDEV_PR_ARG, CHAN_PR_ARG, __entry->duration) + TP_printk(WIPHY_PR_FMT WDEV_PR_FMT CHAN_PR_FMT ", channel type: %d, duration: %u", + WIPHY_PR_ARG, WDEV_PR_ARG, CHAN_PR_ARG, __entry->channel_type, + __entry->duration) ); TRACE_EVENT(rdev_return_int_cookie, @@ -1644,20 +1624,25 @@ TRACE_EVENT(rdev_cancel_remain_on_channel, WDEV_ASSIGN; __entry->cookie = cookie; ), - TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", cookie: %llu", + TP_printk(WIPHY_PR_FMT WDEV_PR_FMT ", cookie: %llu", WIPHY_PR_ARG, WDEV_PR_ARG, __entry->cookie) ); TRACE_EVENT(rdev_mgmt_tx, TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev, struct ieee80211_channel *chan, bool offchan, - unsigned int wait, bool no_cck, bool dont_wait_for_ack), - TP_ARGS(wiphy, wdev, chan, offchan, wait, no_cck, dont_wait_for_ack), + enum nl80211_channel_type channel_type, + bool channel_type_valid, unsigned int wait, bool no_cck, + bool dont_wait_for_ack), + TP_ARGS(wiphy, wdev, chan, offchan, channel_type, channel_type_valid, + wait, no_cck, dont_wait_for_ack), TP_STRUCT__entry( WIPHY_ENTRY WDEV_ENTRY CHAN_ENTRY __field(bool, offchan) + __field(enum nl80211_channel_type, channel_type) + __field(bool, channel_type_valid) __field(unsigned int, wait) __field(bool, no_cck) __field(bool, dont_wait_for_ack) @@ -1667,14 +1652,18 @@ TRACE_EVENT(rdev_mgmt_tx, WDEV_ASSIGN; CHAN_ASSIGN(chan); __entry->offchan = offchan; + __entry->channel_type = channel_type; + __entry->channel_type_valid = channel_type_valid; __entry->wait = wait; __entry->no_cck = no_cck; __entry->dont_wait_for_ack = dont_wait_for_ack; ), - TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", " CHAN_PR_FMT ", offchan: %s," - " wait: %u, no cck: %s, dont wait for ack: %s", + TP_printk(WIPHY_PR_FMT WDEV_PR_FMT CHAN_PR_FMT ", offchan: %s, " + "channel type: %d, channel type valid: %s, wait: %u, " + "no cck: %s, dont wait for ack: %s", WIPHY_PR_ARG, WDEV_PR_ARG, CHAN_PR_ARG, - BOOL_TO_STR(__entry->offchan), __entry->wait, + BOOL_TO_STR(__entry->offchan), __entry->channel_type, + BOOL_TO_STR(__entry->channel_type_valid), __entry->wait, BOOL_TO_STR(__entry->no_cck), BOOL_TO_STR(__entry->dont_wait_for_ack)) ); @@ -1693,7 +1682,7 @@ TRACE_EVENT(rdev_set_noack_map, NETDEV_ASSIGN; __entry->noack_map = noack_map; ), - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", noack_map: %u", + TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", noack_map: %u", WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->noack_map) ); @@ -1710,7 +1699,7 @@ TRACE_EVENT(rdev_get_et_sset_count, NETDEV_ASSIGN; __entry->sset = sset; ), - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", sset: %d", + TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", sset: %d", WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->sset) ); @@ -1727,7 +1716,7 @@ TRACE_EVENT(rdev_get_et_strings, NETDEV_ASSIGN; __entry->sset = sset; ), - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", sset: %u", + TP_printk(WIPHY_PR_FMT NETDEV_PR_FMT ", sset: %u", WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->sset) ); @@ -1736,25 +1725,22 @@ DEFINE_EVENT(wiphy_wdev_evt, rdev_get_channel, TP_ARGS(wiphy, wdev) ); -TRACE_EVENT(rdev_return_chandef, - TP_PROTO(struct wiphy *wiphy, int ret, - struct cfg80211_chan_def *chandef), - TP_ARGS(wiphy, ret, chandef), +TRACE_EVENT(rdev_return_channel, + TP_PROTO(struct wiphy *wiphy, struct ieee80211_channel *chan, + enum nl80211_channel_type type), + TP_ARGS(wiphy, chan, type), TP_STRUCT__entry( WIPHY_ENTRY - __field(int, ret) - CHAN_DEF_ENTRY + CHAN_ENTRY + __field(enum nl80211_channel_type, type) ), TP_fast_assign( WIPHY_ASSIGN; - if (ret == 0) - CHAN_DEF_ASSIGN(chandef); - else - CHAN_DEF_ASSIGN((struct cfg80211_chan_def *)NULL); - __entry->ret = ret; + CHAN_ASSIGN(chan); + __entry->type = type; ), - TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT ", ret: %d", - WIPHY_PR_ARG, CHAN_DEF_PR_ARG, __entry->ret) + TP_printk(WIPHY_PR_FMT CHAN_PR_FMT ", channel type: %d", + WIPHY_PR_ARG, CHAN_PR_ARG, __entry->type) ); DEFINE_EVENT(wiphy_wdev_evt, rdev_start_p2p_device, @@ -1833,7 +1819,7 @@ TRACE_EVENT(cfg80211_send_rx_assoc, MAC_ASSIGN(bssid, bss->bssid); CHAN_ASSIGN(bss->channel); ), - TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT ", " CHAN_PR_FMT, + TP_printk(NETDEV_PR_FMT MAC_PR_FMT CHAN_PR_FMT, NETDEV_PR_ARG, MAC_PR_ARG(bssid), CHAN_PR_ARG) ); @@ -1900,7 +1886,7 @@ TRACE_EVENT(cfg80211_michael_mic_failure, __entry->key_id = key_id; memcpy(__entry->tsc, tsc, 6); ), - TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT ", key type: %d, key id: %d, tsc: %pm", + TP_printk(NETDEV_PR_FMT MAC_PR_FMT ", key type: %d, key id: %d, tsc: %pm", NETDEV_PR_ARG, MAC_PR_ARG(addr), __entry->key_type, __entry->key_id, __entry->tsc) ); @@ -1908,41 +1894,47 @@ TRACE_EVENT(cfg80211_michael_mic_failure, TRACE_EVENT(cfg80211_ready_on_channel, TP_PROTO(struct wireless_dev *wdev, u64 cookie, struct ieee80211_channel *chan, - unsigned int duration), - TP_ARGS(wdev, cookie, chan, duration), + enum nl80211_channel_type channel_type, unsigned int duration), + TP_ARGS(wdev, cookie, chan, channel_type, duration), TP_STRUCT__entry( WDEV_ENTRY __field(u64, cookie) CHAN_ENTRY + __field(enum nl80211_channel_type, channel_type) __field(unsigned int, duration) ), TP_fast_assign( WDEV_ASSIGN; __entry->cookie = cookie; CHAN_ASSIGN(chan); + __entry->channel_type = channel_type; __entry->duration = duration; ), - TP_printk(WDEV_PR_FMT ", cookie: %llu, " CHAN_PR_FMT ", duration: %u", + TP_printk(WDEV_PR_FMT ", cookie: %llu, " CHAN_PR_FMT ", channel type: %d, duration: %u", WDEV_PR_ARG, __entry->cookie, CHAN_PR_ARG, - __entry->duration) + __entry->channel_type, __entry->duration) ); TRACE_EVENT(cfg80211_ready_on_channel_expired, TP_PROTO(struct wireless_dev *wdev, u64 cookie, - struct ieee80211_channel *chan), - TP_ARGS(wdev, cookie, chan), + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type), + TP_ARGS(wdev, cookie, chan, channel_type), TP_STRUCT__entry( WDEV_ENTRY __field(u64, cookie) CHAN_ENTRY + __field(enum nl80211_channel_type, channel_type) ), TP_fast_assign( WDEV_ASSIGN; __entry->cookie = cookie; CHAN_ASSIGN(chan); + __entry->channel_type = channel_type; ), - TP_printk(WDEV_PR_FMT ", cookie: %llu, " CHAN_PR_FMT, - WDEV_PR_ARG, __entry->cookie, CHAN_PR_ARG) + TP_printk(WDEV_PR_FMT ", cookie: %llu, " CHAN_PR_FMT ", channel type: %d", + WDEV_PR_ARG, __entry->cookie, CHAN_PR_ARG, + __entry->channel_type) ); TRACE_EVENT(cfg80211_new_sta, @@ -1959,7 +1951,7 @@ TRACE_EVENT(cfg80211_new_sta, MAC_ASSIGN(mac_addr, mac_addr); SINFO_ASSIGN; ), - TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT, + TP_printk(NETDEV_PR_FMT MAC_PR_FMT, NETDEV_PR_ARG, MAC_PR_ARG(mac_addr)) ); @@ -2018,35 +2010,40 @@ TRACE_EVENT(cfg80211_cqm_rssi_notify, NETDEV_PR_ARG, __entry->rssi_event) ); -TRACE_EVENT(cfg80211_reg_can_beacon, - TP_PROTO(struct wiphy *wiphy, struct cfg80211_chan_def *chandef), - TP_ARGS(wiphy, chandef), +TRACE_EVENT(cfg80211_can_beacon_sec_chan, + TP_PROTO(struct wiphy *wiphy, struct ieee80211_channel *channel, + enum nl80211_channel_type channel_type), + TP_ARGS(wiphy, channel, channel_type), TP_STRUCT__entry( WIPHY_ENTRY - CHAN_DEF_ENTRY + CHAN_ENTRY + __field(enum nl80211_channel_type, channel_type) ), TP_fast_assign( WIPHY_ASSIGN; - CHAN_DEF_ASSIGN(chandef); + CHAN_ASSIGN(channel); + __entry->channel_type = channel_type; ), - TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT, - WIPHY_PR_ARG, CHAN_DEF_PR_ARG) + TP_printk(WIPHY_PR_FMT CHAN_PR_FMT ", channel_type: %d", + WIPHY_PR_ARG, CHAN_PR_ARG, __entry->channel_type) ); TRACE_EVENT(cfg80211_ch_switch_notify, - TP_PROTO(struct net_device *netdev, - struct cfg80211_chan_def *chandef), - TP_ARGS(netdev, chandef), + TP_PROTO(struct net_device *netdev, int freq, + enum nl80211_channel_type type), + TP_ARGS(netdev, freq, type), TP_STRUCT__entry( NETDEV_ENTRY - CHAN_DEF_ENTRY + __field(int, freq) + __field(enum nl80211_channel_type, type) ), TP_fast_assign( NETDEV_ASSIGN; - CHAN_DEF_ASSIGN(chandef); + __entry->freq = freq; + __entry->type = type; ), - TP_printk(NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT, - NETDEV_PR_ARG, CHAN_DEF_PR_ARG) + TP_printk(NETDEV_PR_FMT ", freq: %d, type: %d", NETDEV_PR_ARG, + __entry->freq, __entry->type) ); DECLARE_EVENT_CLASS(cfg80211_rx_evt, @@ -2060,7 +2057,7 @@ DECLARE_EVENT_CLASS(cfg80211_rx_evt, NETDEV_ASSIGN; MAC_ASSIGN(addr, addr); ), - TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT, NETDEV_PR_ARG, MAC_PR_ARG(addr)) + TP_printk(NETDEV_PR_FMT MAC_PR_FMT, NETDEV_PR_ARG, MAC_PR_ARG(addr)) ); DEFINE_EVENT(cfg80211_rx_evt, cfg80211_ibss_joined, @@ -2094,7 +2091,7 @@ TRACE_EVENT(cfg80211_probe_status, __entry->cookie = cookie; __entry->acked = acked; ), - TP_printk(NETDEV_PR_FMT " addr:" MAC_PR_FMT ", cookie: %llu, acked: %s", + TP_printk(NETDEV_PR_FMT MAC_PR_FMT ", cookie: %llu, acked: %s", NETDEV_PR_ARG, MAC_PR_ARG(addr), __entry->cookie, BOOL_TO_STR(__entry->acked)) ); @@ -2160,29 +2157,6 @@ TRACE_EVENT(cfg80211_report_obss_beacon, WIPHY_PR_ARG, __entry->freq, __entry->sig_dbm) ); -TRACE_EVENT(cfg80211_tdls_oper_request, - TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, const u8 *peer, - enum nl80211_tdls_operation oper, u16 reason_code), - TP_ARGS(wiphy, netdev, peer, oper, reason_code), - TP_STRUCT__entry( - WIPHY_ENTRY - NETDEV_ENTRY - MAC_ENTRY(peer) - __field(enum nl80211_tdls_operation, oper) - __field(u16, reason_code) - ), - TP_fast_assign( - WIPHY_ASSIGN; - NETDEV_ASSIGN; - MAC_ASSIGN(peer, peer); - __entry->oper = oper; - __entry->reason_code = reason_code; - ), - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", peer: " MAC_PR_FMT ", oper: %d, reason_code %u", - WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer), __entry->oper, - __entry->reason_code) - ); - TRACE_EVENT(cfg80211_scan_done, TP_PROTO(struct cfg80211_scan_request *request, bool aborted), TP_ARGS(request, aborted), @@ -2244,7 +2218,7 @@ TRACE_EVENT(cfg80211_get_bss, __entry->capa_mask = capa_mask; __entry->capa_val = capa_val; ), - TP_printk(WIPHY_PR_FMT ", " CHAN_PR_FMT ", " MAC_PR_FMT ", buf: %#.2x, " + TP_printk(WIPHY_PR_FMT CHAN_PR_FMT MAC_PR_FMT ", buf: %#.2x, " "capa_mask: %d, capa_val: %u", WIPHY_PR_ARG, CHAN_PR_ARG, MAC_PR_ARG(bssid), ((u8 *)__get_dynamic_array(ssid))[0], __entry->capa_mask, __entry->capa_val) @@ -2268,7 +2242,7 @@ TRACE_EVENT(cfg80211_inform_bss_frame, memcpy(__get_dynamic_array(mgmt), mgmt, len); __entry->signal = signal; ), - TP_printk(WIPHY_PR_FMT ", " CHAN_PR_FMT "signal: %d", + TP_printk(WIPHY_PR_FMT CHAN_PR_FMT "signal: %d", WIPHY_PR_ARG, CHAN_PR_ARG, __entry->signal) ); @@ -2283,7 +2257,7 @@ DECLARE_EVENT_CLASS(cfg80211_bss_evt, MAC_ASSIGN(bssid, pub->bssid); CHAN_ASSIGN(pub->channel); ), - TP_printk(MAC_PR_FMT ", " CHAN_PR_FMT, MAC_PR_ARG(bssid), CHAN_PR_ARG) + TP_printk(MAC_PR_FMT CHAN_PR_FMT, MAC_PR_ARG(bssid), CHAN_PR_ARG) ); DEFINE_EVENT(cfg80211_bss_evt, cfg80211_return_bss, diff --git a/trunk/net/wireless/util.c b/trunk/net/wireless/util.c index 3cce6e486219..b99f01cda1f6 100644 --- a/trunk/net/wireless/util.c +++ b/trunk/net/wireless/util.c @@ -944,86 +944,14 @@ static u32 cfg80211_calculate_bitrate_60g(struct rate_info *rate) return __mcs2bitrate[rate->mcs]; } -static u32 cfg80211_calculate_bitrate_vht(struct rate_info *rate) -{ - static const u32 base[4][10] = { - { 6500000, - 13000000, - 19500000, - 26000000, - 39000000, - 52000000, - 58500000, - 65000000, - 78000000, - 0, - }, - { 13500000, - 27000000, - 40500000, - 54000000, - 81000000, - 108000000, - 121500000, - 135000000, - 162000000, - 180000000, - }, - { 29300000, - 58500000, - 87800000, - 117000000, - 175500000, - 234000000, - 263300000, - 292500000, - 351000000, - 390000000, - }, - { 58500000, - 117000000, - 175500000, - 234000000, - 351000000, - 468000000, - 526500000, - 585000000, - 702000000, - 780000000, - }, - }; - u32 bitrate; - int idx; - - if (WARN_ON_ONCE(rate->mcs > 9)) - return 0; - - idx = rate->flags & (RATE_INFO_FLAGS_160_MHZ_WIDTH | - RATE_INFO_FLAGS_80P80_MHZ_WIDTH) ? 3 : - rate->flags & RATE_INFO_FLAGS_80_MHZ_WIDTH ? 2 : - rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH ? 1 : 0; - - bitrate = base[idx][rate->mcs]; - bitrate *= rate->nss; - - if (rate->flags & RATE_INFO_FLAGS_SHORT_GI) - bitrate = (bitrate / 9) * 10; - - /* do NOT round down here */ - return (bitrate + 50000) / 100000; -} - u32 cfg80211_calculate_bitrate(struct rate_info *rate) { int modulation, streams, bitrate; - if (!(rate->flags & RATE_INFO_FLAGS_MCS) && - !(rate->flags & RATE_INFO_FLAGS_VHT_MCS)) + if (!(rate->flags & RATE_INFO_FLAGS_MCS)) return rate->legacy; if (rate->flags & RATE_INFO_FLAGS_60G) return cfg80211_calculate_bitrate_60g(rate); - if (rate->flags & RATE_INFO_FLAGS_VHT_MCS) - return cfg80211_calculate_bitrate_vht(rate); /* the formula below does only work for MCS values smaller than 32 */ if (WARN_ON_ONCE(rate->mcs >= 32)) @@ -1052,9 +980,8 @@ u32 cfg80211_calculate_bitrate(struct rate_info *rate) } EXPORT_SYMBOL(cfg80211_calculate_bitrate); -int cfg80211_get_p2p_attr(const u8 *ies, unsigned int len, - enum ieee80211_p2p_attr_id attr, - u8 *buf, unsigned int bufsize) +unsigned int cfg80211_get_p2p_attr(const u8 *ies, unsigned int len, + u8 attr, u8 *buf, unsigned int bufsize) { u8 *out = buf; u16 attr_remaining = 0; diff --git a/trunk/net/wireless/wext-compat.c b/trunk/net/wireless/wext-compat.c index f9680c9cf9b3..742ab6ec4c9d 100644 --- a/trunk/net/wireless/wext-compat.c +++ b/trunk/net/wireless/wext-compat.c @@ -784,9 +784,6 @@ static int cfg80211_wext_siwfreq(struct net_device *dev, { struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); - struct cfg80211_chan_def chandef = { - .width = NL80211_CHAN_WIDTH_20_NOHT, - }; int freq, err; switch (wdev->iftype) { @@ -800,12 +797,8 @@ static int cfg80211_wext_siwfreq(struct net_device *dev, return freq; if (freq == 0) return -EINVAL; - chandef.center_freq1 = freq; - chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq); - if (!chandef.chan) - return -EINVAL; mutex_lock(&rdev->devlist_mtx); - err = cfg80211_set_monitor_channel(rdev, &chandef); + err = cfg80211_set_monitor_channel(rdev, freq, NL80211_CHAN_NO_HT); mutex_unlock(&rdev->devlist_mtx); return err; case NL80211_IFTYPE_MESH_POINT: @@ -814,12 +807,9 @@ static int cfg80211_wext_siwfreq(struct net_device *dev, return freq; if (freq == 0) return -EINVAL; - chandef.center_freq1 = freq; - chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq); - if (!chandef.chan) - return -EINVAL; mutex_lock(&rdev->devlist_mtx); - err = cfg80211_set_mesh_channel(rdev, wdev, &chandef); + err = cfg80211_set_mesh_freq(rdev, wdev, freq, + NL80211_CHAN_NO_HT); mutex_unlock(&rdev->devlist_mtx); return err; default: @@ -833,8 +823,8 @@ static int cfg80211_wext_giwfreq(struct net_device *dev, { struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); - struct cfg80211_chan_def chandef; - int ret; + struct ieee80211_channel *chan; + enum nl80211_channel_type channel_type; switch (wdev->iftype) { case NL80211_IFTYPE_STATION: @@ -845,10 +835,10 @@ static int cfg80211_wext_giwfreq(struct net_device *dev, if (!rdev->ops->get_channel) return -EINVAL; - ret = rdev_get_channel(rdev, wdev, &chandef); - if (ret) - return ret; - freq->m = chandef.chan->center_freq; + chan = rdev_get_channel(rdev, wdev, &channel_type); + if (!chan) + return -EINVAL; + freq->m = chan->center_freq; freq->e = 6; return 0; default: diff --git a/trunk/net/wireless/wext-sme.c b/trunk/net/wireless/wext-sme.c index 873af63187c0..1f773f668d1a 100644 --- a/trunk/net/wireless/wext-sme.c +++ b/trunk/net/wireless/wext-sme.c @@ -119,16 +119,7 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev, * channel we disconnected above and reconnect below. */ if (chan && !wdev->wext.connect.ssid_len) { - struct cfg80211_chan_def chandef = { - .width = NL80211_CHAN_WIDTH_20_NOHT, - .center_freq1 = freq, - }; - - chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq); - if (chandef.chan) - err = cfg80211_set_monitor_channel(rdev, &chandef); - else - err = -EINVAL; + err = cfg80211_set_monitor_channel(rdev, freq, NL80211_CHAN_NO_HT); goto out; }