From 331d5957bc81213b8b52aba03ada4c6820dc7ed4 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 6 Mar 2013 16:46:25 +0100 Subject: [PATCH] --- yaml --- r: 368447 b: refs/heads/master c: 41effc2a6c6548f1dc6b749f09c646d931c309a4 h: refs/heads/master i: 368445: b714db006b6e639e79ccf662128803583262feb3 368443: 26b13f138be0e9dd086f99d5df3fb1b94e773790 368439: 712d04d1d230cd453f6f91b4fc8d3333dee583e2 368431: dc9e513bc52de4d70a74a8ff9aecd4c9acd50b28 368415: 42485b0c071bcc92fdac274e6a0547a77a6f88d4 368383: 7fcd104c47c8bf862ff293e193e23747c8644510 v: v3 --- [refs] | 2 +- trunk/drivers/bcma/core.c | 8 +- trunk/drivers/bcma/main.c | 5 - trunk/drivers/net/wireless/ath/ath5k/ath5k.h | 3 +- trunk/drivers/net/wireless/ath/ath5k/eeprom.c | 6 +- trunk/drivers/net/wireless/ath/ath5k/eeprom.h | 3 + trunk/drivers/net/wireless/ath/ath5k/phy.c | 20 +- trunk/drivers/net/wireless/ath/ath5k/reset.c | 4 +- .../net/wireless/ath/ath6kl/cfg80211.c | 8 +- .../net/wireless/ath/ath6kl/htc_pipe.c | 3 +- .../net/wireless/ath/ath9k/ar9003_eeprom.c | 17 - .../wireless/ath/ath9k/ar9462_2p0_initvals.h | 49 +- trunk/drivers/net/wireless/ath/ath9k/calib.c | 4 +- trunk/drivers/net/wireless/ath/ath9k/common.h | 2 +- trunk/drivers/net/wireless/ath/ath9k/debug.c | 5 - trunk/drivers/net/wireless/ath/ath9k/debug.h | 2 - trunk/drivers/net/wireless/ath/ath9k/hw.c | 188 +- trunk/drivers/net/wireless/ath/ath9k/hw.h | 1 + trunk/drivers/net/wireless/ath/carl9170/tx.c | 69 +- .../drivers/net/wireless/ath/wil6210/Makefile | 4 +- .../net/wireless/ath/wil6210/debugfs.c | 14 +- trunk/drivers/net/wireless/b43/Kconfig | 6 +- trunk/drivers/net/wireless/b43/b43.h | 6 - trunk/drivers/net/wireless/b43/main.c | 7 +- trunk/drivers/net/wireless/b43/phy_ht.c | 5 - trunk/drivers/net/wireless/brcm80211/Kconfig | 5 +- .../net/wireless/brcm80211/brcmfmac/Makefile | 3 - .../net/wireless/brcm80211/brcmfmac/dhd.h | 7 +- .../net/wireless/brcm80211/brcmfmac/dhd_bus.h | 2 +- .../net/wireless/brcm80211/brcmfmac/dhd_cdc.c | 30 +- .../wireless/brcm80211/brcmfmac/dhd_common.c | 33 - .../net/wireless/brcm80211/brcmfmac/dhd_dbg.c | 42 - .../net/wireless/brcm80211/brcmfmac/dhd_dbg.h | 34 +- .../wireless/brcm80211/brcmfmac/dhd_linux.c | 39 +- .../wireless/brcm80211/brcmfmac/dhd_proto.h | 2 +- .../wireless/brcm80211/brcmfmac/dhd_sdio.c | 28 +- .../wireless/brcm80211/brcmfmac/fwsignal.c | 382 ---- .../wireless/brcm80211/brcmfmac/fwsignal.h | 25 - .../wireless/brcm80211/brcmfmac/tracepoint.c | 22 - .../wireless/brcm80211/brcmfmac/tracepoint.h | 87 - .../net/wireless/brcm80211/brcmfmac/usb.c | 37 +- .../wireless/brcm80211/brcmfmac/wl_cfg80211.c | 6 +- .../net/wireless/brcm80211/brcmsmac/Makefile | 4 - .../net/wireless/brcm80211/brcmsmac/led.c | 126 -- .../net/wireless/brcm80211/brcmsmac/led.h | 36 - .../wireless/brcm80211/brcmsmac/mac80211_if.c | 4 - .../wireless/brcm80211/brcmsmac/mac80211_if.h | 4 - .../net/wireless/brcm80211/brcmsmac/main.c | 11 +- .../net/wireless/brcm80211/brcmutil/utils.c | 25 - .../wireless/brcm80211/include/brcmu_utils.h | 27 - trunk/drivers/net/wireless/iwlegacy/3945.h | 4 + .../drivers/net/wireless/iwlegacy/4965-mac.c | 13 +- trunk/drivers/net/wireless/iwlegacy/common.h | 4 + .../net/wireless/iwlwifi/dvm/mac80211.c | 3 +- trunk/drivers/net/wireless/iwlwifi/dvm/sta.c | 2 +- trunk/drivers/net/wireless/iwlwifi/dvm/tx.c | 11 +- .../net/wireless/iwlwifi/iwl-devtrace.h | 12 +- trunk/drivers/net/wireless/iwlwifi/iwl-drv.c | 3 +- .../net/wireless/iwlwifi/iwl-modparams.h | 2 +- .../drivers/net/wireless/iwlwifi/iwl-phy-db.c | 16 - .../drivers/net/wireless/iwlwifi/iwl-trans.h | 23 +- trunk/drivers/net/wireless/iwlwifi/mvm/d3.c | 104 +- .../drivers/net/wireless/iwlwifi/mvm/fw-api.h | 18 +- trunk/drivers/net/wireless/iwlwifi/mvm/fw.c | 133 +- .../net/wireless/iwlwifi/mvm/mac80211.c | 26 +- trunk/drivers/net/wireless/iwlwifi/mvm/mvm.h | 7 +- trunk/drivers/net/wireless/iwlwifi/mvm/ops.c | 18 +- trunk/drivers/net/wireless/iwlwifi/mvm/rx.c | 37 +- trunk/drivers/net/wireless/iwlwifi/mvm/sta.c | 14 +- trunk/drivers/net/wireless/iwlwifi/mvm/tx.c | 8 +- .../net/wireless/iwlwifi/pcie/internal.h | 35 +- trunk/drivers/net/wireless/iwlwifi/pcie/rx.c | 14 +- trunk/drivers/net/wireless/iwlwifi/pcie/tx.c | 301 +-- trunk/drivers/net/wireless/mac80211_hwsim.c | 3 +- trunk/drivers/net/wireless/mwifiex/Makefile | 1 - trunk/drivers/net/wireless/mwifiex/cfg80211.c | 157 -- trunk/drivers/net/wireless/mwifiex/cmdevt.c | 2 +- trunk/drivers/net/wireless/mwifiex/ethtool.c | 70 - trunk/drivers/net/wireless/mwifiex/fw.h | 44 +- trunk/drivers/net/wireless/mwifiex/init.c | 6 +- trunk/drivers/net/wireless/mwifiex/ioctl.h | 23 - trunk/drivers/net/wireless/mwifiex/main.h | 4 - trunk/drivers/net/wireless/mwifiex/pcie.c | 156 +- trunk/drivers/net/wireless/mwifiex/sta_cmd.c | 79 +- .../net/wireless/mwifiex/sta_cmdresp.c | 2 - .../drivers/net/wireless/mwifiex/sta_ioctl.c | 10 +- trunk/drivers/net/wireless/mwifiex/util.c | 5 +- trunk/drivers/net/wireless/mwl8k.c | 105 +- trunk/drivers/net/wireless/ray_cs.c | 6 +- trunk/drivers/net/wireless/rndis_wlan.c | 3 +- trunk/drivers/net/wireless/rt2x00/rt2x00pci.c | 4 +- trunk/drivers/net/wireless/rtlwifi/wifi.h | 3 + trunk/drivers/net/wireless/ti/wlcore/main.c | 3 +- trunk/drivers/ssb/driver_chipcommon.c | 2 +- trunk/drivers/ssb/driver_chipcommon_pmu.c | 41 +- trunk/drivers/ssb/driver_mipscore.c | 25 +- trunk/drivers/ssb/driver_pcicore.c | 15 +- trunk/drivers/ssb/embedded.c | 5 +- trunk/drivers/ssb/main.c | 51 +- trunk/drivers/ssb/pci.c | 97 +- trunk/drivers/ssb/pcmcia.c | 46 +- trunk/drivers/ssb/scan.c | 31 +- trunk/drivers/ssb/sprom.c | 4 +- trunk/drivers/ssb/ssb_private.h | 19 +- trunk/include/linux/ieee80211.h | 52 +- trunk/include/linux/ssb/ssb.h | 6 +- trunk/include/net/cfg80211.h | 126 +- trunk/include/net/mac80211.h | 29 +- trunk/include/uapi/linux/nl80211.h | 117 +- trunk/net/mac80211/cfg.c | 162 +- trunk/net/mac80211/debugfs_sta.c | 31 - trunk/net/mac80211/driver-ops.h | 7 +- trunk/net/mac80211/ht.c | 52 +- trunk/net/mac80211/ibss.c | 29 +- trunk/net/mac80211/ieee80211_i.h | 26 +- trunk/net/mac80211/iface.c | 22 +- trunk/net/mac80211/key.c | 103 +- trunk/net/mac80211/key.h | 5 +- trunk/net/mac80211/main.c | 55 +- trunk/net/mac80211/mesh.c | 59 +- trunk/net/mac80211/mesh.h | 12 + trunk/net/mac80211/mesh_plink.c | 37 +- trunk/net/mac80211/mlme.c | 110 +- trunk/net/mac80211/offchannel.c | 2 +- trunk/net/mac80211/pm.c | 117 +- trunk/net/mac80211/rc80211_minstrel.c | 204 +- trunk/net/mac80211/rc80211_minstrel.h | 31 +- trunk/net/mac80211/rc80211_minstrel_debugfs.c | 12 +- trunk/net/mac80211/rc80211_minstrel_ht.c | 79 +- trunk/net/mac80211/rc80211_minstrel_ht.h | 6 +- trunk/net/mac80211/rx.c | 61 +- trunk/net/mac80211/sta_info.c | 11 +- trunk/net/mac80211/sta_info.h | 2 + trunk/net/mac80211/trace.h | 11 +- trunk/net/mac80211/tx.c | 80 +- trunk/net/mac80211/util.c | 73 +- trunk/net/mac80211/vht.c | 212 +- trunk/net/rfkill/rfkill-regulator.c | 2 +- trunk/net/wireless/ap.c | 62 + trunk/net/wireless/core.c | 76 +- trunk/net/wireless/core.h | 22 +- trunk/net/wireless/mesh.c | 15 +- trunk/net/wireless/mlme.c | 230 ++- trunk/net/wireless/nl80211.c | 1827 ++++++----------- trunk/net/wireless/nl80211.h | 68 + trunk/net/wireless/rdev-ops.h | 20 +- trunk/net/wireless/reg.c | 6 +- trunk/net/wireless/sme.c | 26 +- trunk/net/wireless/sysfs.c | 25 +- trunk/net/wireless/trace.h | 46 - 150 files changed, 2874 insertions(+), 4784 deletions(-) delete mode 100644 trunk/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c delete mode 100644 trunk/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h delete mode 100644 trunk/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.c delete mode 100644 trunk/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h delete mode 100644 trunk/drivers/net/wireless/brcm80211/brcmsmac/led.c delete mode 100644 trunk/drivers/net/wireless/brcm80211/brcmsmac/led.h delete mode 100644 trunk/drivers/net/wireless/mwifiex/ethtool.c diff --git a/[refs] b/[refs] index ea5007df7096..593adbf28a87 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 3d5c203272b25c4391397247cdb0059a04fccddf +refs/heads/master: 41effc2a6c6548f1dc6b749f09c646d931c309a4 diff --git a/trunk/drivers/bcma/core.c b/trunk/drivers/bcma/core.c index 17b26ce7e051..03bbe104338f 100644 --- a/trunk/drivers/bcma/core.c +++ b/trunk/drivers/bcma/core.c @@ -104,13 +104,7 @@ void bcma_core_pll_ctl(struct bcma_device *core, u32 req, u32 status, bool on) if (i) bcma_err(core->bus, "PLL enable timeout\n"); } else { - /* - * Mask the PLL but don't wait for it to be disabled. PLL may be - * shared between cores and will be still up if there is another - * core using it. - */ - bcma_mask32(core, BCMA_CLKCTLST, ~req); - bcma_read32(core, BCMA_CLKCTLST); + bcma_warn(core->bus, "Disabling PLL not supported yet!\n"); } } EXPORT_SYMBOL_GPL(bcma_core_pll_ctl); diff --git a/trunk/drivers/bcma/main.c b/trunk/drivers/bcma/main.c index f72f52b4b1dd..9a6188add590 100644 --- a/trunk/drivers/bcma/main.c +++ b/trunk/drivers/bcma/main.c @@ -120,11 +120,6 @@ static int bcma_register_cores(struct bcma_bus *bus) continue; } - /* Only first GMAC core on BCM4706 is connected and working */ - if (core->id.id == BCMA_CORE_4706_MAC_GBIT && - core->core_unit > 0) - continue; - core->dev.release = bcma_release_core_dev; core->dev.bus = &bcma_bus_type; dev_set_name(&core->dev, "bcma%d:%d", bus->num, dev_id); diff --git a/trunk/drivers/net/wireless/ath/ath5k/ath5k.h b/trunk/drivers/net/wireless/ath/ath5k/ath5k.h index 2d691b8b95b9..3150def17193 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/trunk/drivers/net/wireless/ath/ath5k/ath5k.h @@ -1523,8 +1523,7 @@ int ath5k_hw_dma_stop(struct ath5k_hw *ah); /* EEPROM access functions */ int ath5k_eeprom_init(struct ath5k_hw *ah); void ath5k_eeprom_detach(struct ath5k_hw *ah); -int ath5k_eeprom_mode_from_channel(struct ath5k_hw *ah, - struct ieee80211_channel *channel); + /* Protocol Control Unit Functions */ /* Helpers */ diff --git a/trunk/drivers/net/wireless/ath/ath5k/eeprom.c b/trunk/drivers/net/wireless/ath/ath5k/eeprom.c index 94d34ee02265..b7e0258887e7 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/trunk/drivers/net/wireless/ath/ath5k/eeprom.c @@ -1779,8 +1779,7 @@ ath5k_eeprom_detach(struct ath5k_hw *ah) } int -ath5k_eeprom_mode_from_channel(struct ath5k_hw *ah, - struct ieee80211_channel *channel) +ath5k_eeprom_mode_from_channel(struct ieee80211_channel *channel) { switch (channel->hw_value) { case AR5K_MODE_11A: @@ -1790,7 +1789,6 @@ ath5k_eeprom_mode_from_channel(struct ath5k_hw *ah, case AR5K_MODE_11B: return AR5K_EEPROM_MODE_11B; default: - ATH5K_WARN(ah, "channel is not A/B/G!"); - return AR5K_EEPROM_MODE_11A; + return -1; } } diff --git a/trunk/drivers/net/wireless/ath/ath5k/eeprom.h b/trunk/drivers/net/wireless/ath/ath5k/eeprom.h index 693296ee9693..94a9bbea6874 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/eeprom.h +++ b/trunk/drivers/net/wireless/ath/ath5k/eeprom.h @@ -493,3 +493,6 @@ struct ath5k_eeprom_info { /* Antenna raw switch tables */ u32 ee_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; }; + +int +ath5k_eeprom_mode_from_channel(struct ieee80211_channel *channel); diff --git a/trunk/drivers/net/wireless/ath/ath5k/phy.c b/trunk/drivers/net/wireless/ath/ath5k/phy.c index d6bc7cb61bfb..a78afa98c650 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/phy.c +++ b/trunk/drivers/net/wireless/ath/ath5k/phy.c @@ -1612,7 +1612,11 @@ ath5k_hw_update_noise_floor(struct ath5k_hw *ah) ah->ah_cal_mask |= AR5K_CALIBRATION_NF; - ee_mode = ath5k_eeprom_mode_from_channel(ah, ah->ah_current_channel); + ee_mode = ath5k_eeprom_mode_from_channel(ah->ah_current_channel); + if (WARN_ON(ee_mode < 0)) { + ah->ah_cal_mask &= ~AR5K_CALIBRATION_NF; + return; + } /* completed NF calibration, test threshold */ nf = ath5k_hw_read_measured_noise_floor(ah); @@ -2313,7 +2317,12 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) def_ant = ah->ah_def_ant; - ee_mode = ath5k_eeprom_mode_from_channel(ah, channel); + ee_mode = ath5k_eeprom_mode_from_channel(channel); + if (ee_mode < 0) { + ATH5K_ERR(ah, + "invalid channel: %d\n", channel->center_freq); + return; + } switch (ant_mode) { case AR5K_ANTMODE_DEFAULT: @@ -3613,7 +3622,12 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, return -EINVAL; } - ee_mode = ath5k_eeprom_mode_from_channel(ah, channel); + ee_mode = ath5k_eeprom_mode_from_channel(channel); + if (ee_mode < 0) { + ATH5K_ERR(ah, + "invalid channel: %d\n", channel->center_freq); + return -EINVAL; + } /* Initialize TX power table */ switch (ah->ah_radio) { diff --git a/trunk/drivers/net/wireless/ath/ath5k/reset.c b/trunk/drivers/net/wireless/ath/ath5k/reset.c index a3399c4f13a9..e2d8b2cf19eb 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/reset.c +++ b/trunk/drivers/net/wireless/ath/ath5k/reset.c @@ -984,7 +984,9 @@ ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, if (ah->ah_version == AR5K_AR5210) return; - ee_mode = ath5k_eeprom_mode_from_channel(ah, channel); + ee_mode = ath5k_eeprom_mode_from_channel(channel); + if (WARN_ON(ee_mode < 0)) + return; /* Adjust power delta for channel 14 */ if (channel->center_freq == 2484) diff --git a/trunk/drivers/net/wireless/ath/ath6kl/cfg80211.c b/trunk/drivers/net/wireless/ath/ath6kl/cfg80211.c index 28c413f861a2..752ffc4f4166 100644 --- a/trunk/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/trunk/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -2990,15 +2990,13 @@ static int ath6kl_change_station(struct wiphy *wiphy, struct net_device *dev, { struct ath6kl *ar = ath6kl_priv(dev); struct ath6kl_vif *vif = netdev_priv(dev); - int err; if (vif->nw_type != AP_NETWORK) return -EOPNOTSUPP; - err = cfg80211_check_station_change(wiphy, params, - CFG80211_STA_AP_MLME_CLIENT); - if (err) - return err; + /* Use this only for authorizing/unauthorizing a station */ + if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED))) + return -EOPNOTSUPP; if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) return ath6kl_wmi_ap_set_mlme(ar->wmi, vif->fw_vif_idx, diff --git a/trunk/drivers/net/wireless/ath/ath6kl/htc_pipe.c b/trunk/drivers/net/wireless/ath/ath6kl/htc_pipe.c index 9adb56741bc3..281390178e3d 100644 --- a/trunk/drivers/net/wireless/ath/ath6kl/htc_pipe.c +++ b/trunk/drivers/net/wireless/ath/ath6kl/htc_pipe.c @@ -988,6 +988,8 @@ static int ath6kl_htc_pipe_rx_complete(struct ath6kl *ar, struct sk_buff *skb, htc_hdr = (struct htc_frame_hdr *) netdata; + ep = &target->endpoint[htc_hdr->eid]; + if (htc_hdr->eid >= ENDPOINT_MAX) { ath6kl_dbg(ATH6KL_DBG_HTC, "HTC Rx: invalid EndpointID=%d\n", @@ -995,7 +997,6 @@ static int ath6kl_htc_pipe_rx_complete(struct ath6kl *ar, struct sk_buff *skb, status = -EINVAL; goto free_skb; } - ep = &target->endpoint[htc_hdr->eid]; payload_len = le16_to_cpu(get_unaligned(&htc_hdr->payld_len)); diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/trunk/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index e6b92ff265fd..881e989ea470 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -3606,12 +3606,6 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) value = ar9003_hw_ant_ctrl_common_2_get(ah, is2ghz); REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value); - if ((AR_SREV_9462(ah)) && (ah->rxchainmask == 0x2)) { - value = ar9003_hw_ant_ctrl_chain_get(ah, 1, is2ghz); - REG_RMW_FIELD(ah, switch_chain_reg[0], - AR_SWITCH_TABLE_ALL, value); - } - for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { if ((ah->rxchainmask & BIT(chain)) || (ah->txchainmask & BIT(chain))) { @@ -3778,17 +3772,6 @@ static void ar9003_hw_atten_apply(struct ath_hw *ah, struct ath9k_channel *chan) AR_PHY_EXT_ATTEN_CTL_2, }; - if ((AR_SREV_9462(ah)) && (ah->rxchainmask == 0x2)) { - value = ar9003_hw_atten_chain_get(ah, 1, chan); - REG_RMW_FIELD(ah, ext_atten_reg[0], - AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, value); - - value = ar9003_hw_atten_chain_get_margin(ah, 1, chan); - REG_RMW_FIELD(ah, ext_atten_reg[0], - AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, - value); - } - /* Test value. if 0 then attenuation is unused. Don't load anything. */ for (i = 0; i < 3; i++) { if (ah->txchainmask & BIT(i)) { diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h b/trunk/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h index 999ab08c34e6..ccc42a71b436 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h @@ -37,28 +37,28 @@ static const u32 ar9462_pciephy_clkreq_enable_L1_2p0[][2] = { /* Addr allmodes */ {0x00018c00, 0x18253ede}, {0x00018c04, 0x000801d8}, - {0x00018c08, 0x0003780c}, + {0x00018c08, 0x0003580c}, }; static const u32 ar9462_2p0_baseband_postamble[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a800d}, {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a01ae}, - {0x00009824, 0x63c640de, 0x5ac640d0, 0x5ac640d0, 0x63c640da}, + {0x00009824, 0x5ac640de, 0x5ac640d0, 0x5ac640d0, 0x63c640da}, {0x00009828, 0x0796be89, 0x0696b081, 0x0696b881, 0x09143e81}, {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c}, {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4}, - {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a2}, + {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0}, {0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020}, {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000d8}, {0x00009e10, 0x92c88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec86d2e}, - {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3236605e, 0x32365a5e}, + {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3376605e, 0x32395d5e}, {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, - {0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c282}, + {0x00009e3c, 0xcf946222, 0xcf946222, 0xcfd5c782, 0xcfd5c282}, {0x00009e44, 0x62321e27, 0x62321e27, 0xfe291e27, 0xfe291e27}, {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, @@ -82,9 +82,9 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = { {0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982}, {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a3a4, 0x00000050, 0x00000050, 0x00000000, 0x00000000}, + {0x0000a3a4, 0x00000010, 0x00000010, 0x00000000, 0x00000000}, {0x0000a3a8, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa}, - {0x0000a3ac, 0xaaaaaa00, 0xaa30aa30, 0xaaaaaa00, 0xaaaaaa00}, + {0x0000a3ac, 0xaaaaaa00, 0xaaaaaa30, 0xaaaaaa00, 0xaaaaaa00}, {0x0000a41c, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce}, {0x0000a420, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce}, {0x0000a424, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce}, @@ -363,14 +363,14 @@ static const u32 ar9462_pciephy_clkreq_disable_L1_2p0[][2] = { /* Addr allmodes */ {0x00018c00, 0x18213ede}, {0x00018c04, 0x000801d8}, - {0x00018c08, 0x0003780c}, + {0x00018c08, 0x0003580c}, }; static const u32 ar9462_pciephy_pll_on_clkreq_disable_L1_2p0[][2] = { /* Addr allmodes */ {0x00018c00, 0x18212ede}, {0x00018c04, 0x000801d8}, - {0x00018c08, 0x0003780c}, + {0x00018c08, 0x0003580c}, }; static const u32 ar9462_2p0_radio_postamble_sys2ant[][5] = { @@ -775,7 +775,7 @@ static const u32 ar9462_2p0_baseband_core[][2] = { {0x00009fc0, 0x803e4788}, {0x00009fc4, 0x0001efb5}, {0x00009fcc, 0x40000014}, - {0x00009fd0, 0x0a193b93}, + {0x00009fd0, 0x01193b93}, {0x0000a20c, 0x00000000}, {0x0000a220, 0x00000000}, {0x0000a224, 0x00000000}, @@ -850,7 +850,7 @@ static const u32 ar9462_2p0_baseband_core[][2] = { {0x0000a7cc, 0x00000000}, {0x0000a7d0, 0x00000000}, {0x0000a7d4, 0x00000004}, - {0x0000a7dc, 0x00000000}, + {0x0000a7dc, 0x00000001}, {0x0000a7f0, 0x80000000}, {0x0000a8d0, 0x004b6a8e}, {0x0000a8d4, 0x00000820}, @@ -886,7 +886,7 @@ static const u32 ar9462_modes_high_ob_db_tx_gain_table_2p0[][5] = { {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x0000a410, 0x000050da, 0x000050da, 0x000050de, 0x000050de}, + {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, {0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002}, @@ -906,20 +906,20 @@ static const u32 ar9462_modes_high_ob_db_tx_gain_table_2p0[][5] = { {0x0000a53c, 0x41025e4a, 0x41025e4a, 0x34001640, 0x34001640}, {0x0000a540, 0x48025e6c, 0x48025e6c, 0x38001660, 0x38001660}, {0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3b001861, 0x3b001861}, - {0x0000a548, 0x55025eb3, 0x55025eb3, 0x3e001a81, 0x3e001a81}, - {0x0000a54c, 0x58025ef3, 0x58025ef3, 0x42001a83, 0x42001a83}, - {0x0000a550, 0x5d025ef6, 0x5d025ef6, 0x44001a84, 0x44001a84}, + {0x0000a548, 0x53025eb2, 0x53025eb2, 0x3e001a81, 0x3e001a81}, + {0x0000a54c, 0x59025eb6, 0x59025eb6, 0x42001a83, 0x42001a83}, + {0x0000a550, 0x5d025ef6, 0x5d025ef6, 0x44001c84, 0x44001c84}, {0x0000a554, 0x62025f56, 0x62025f56, 0x48001ce3, 0x48001ce3}, {0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5}, {0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9}, {0x0000a560, 0x70049f56, 0x70049f56, 0x54001ceb, 0x54001ceb}, - {0x0000a564, 0x751ffff6, 0x751ffff6, 0x56001eec, 0x56001eec}, - {0x0000a568, 0x751ffff6, 0x751ffff6, 0x58001ef0, 0x58001ef0}, - {0x0000a56c, 0x751ffff6, 0x751ffff6, 0x5a001ef4, 0x5a001ef4}, - {0x0000a570, 0x751ffff6, 0x751ffff6, 0x5c001ff6, 0x5c001ff6}, - {0x0000a574, 0x751ffff6, 0x751ffff6, 0x5c001ff6, 0x5c001ff6}, - {0x0000a578, 0x751ffff6, 0x751ffff6, 0x5c001ff6, 0x5c001ff6}, - {0x0000a57c, 0x751ffff6, 0x751ffff6, 0x5c001ff6, 0x5c001ff6}, + {0x0000a564, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, + {0x0000a568, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, + {0x0000a56c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, + {0x0000a570, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, + {0x0000a574, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, + {0x0000a578, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, + {0x0000a57c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, @@ -1053,6 +1053,7 @@ static const u32 ar9462_2p0_mac_core[][2] = { {0x00008044, 0x00000000}, {0x00008048, 0x00000000}, {0x0000804c, 0xffffffff}, + {0x00008050, 0xffffffff}, {0x00008054, 0x00000000}, {0x00008058, 0x00000000}, {0x0000805c, 0x000fc78f}, @@ -1116,9 +1117,9 @@ static const u32 ar9462_2p0_mac_core[][2] = { {0x000081f8, 0x00000000}, {0x000081fc, 0x00000000}, {0x00008240, 0x00100000}, - {0x00008244, 0x0010f400}, + {0x00008244, 0x0010f424}, {0x00008248, 0x00000800}, - {0x0000824c, 0x0001e800}, + {0x0000824c, 0x0001e848}, {0x00008250, 0x00000000}, {0x00008254, 0x00000000}, {0x00008258, 0x00000000}, diff --git a/trunk/drivers/net/wireless/ath/ath9k/calib.c b/trunk/drivers/net/wireless/ath/ath9k/calib.c index 7bdd726c7a8f..1e8508530e98 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/calib.c +++ b/trunk/drivers/net/wireless/ath/ath9k/calib.c @@ -369,6 +369,7 @@ bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan) struct ieee80211_channel *c = chan->chan; struct ath9k_hw_cal_data *caldata = ah->caldata; + chan->channelFlags &= (~CHANNEL_CW_INT); if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) { ath_dbg(common, CALIBRATE, "NF did not complete in calibration window\n"); @@ -383,6 +384,7 @@ bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan) ath_dbg(common, CALIBRATE, "noise floor failed detected; detected %d, threshold %d\n", nf, nfThresh); + chan->channelFlags |= CHANNEL_CW_INT; } if (!caldata) { @@ -408,7 +410,7 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah, int i, j; ah->caldata->channel = chan->channel; - ah->caldata->channelFlags = chan->channelFlags; + ah->caldata->channelFlags = chan->channelFlags & ~CHANNEL_CW_INT; ah->caldata->chanmode = chan->chanmode; h = ah->caldata->nfCalHist; default_nf = ath9k_hw_get_default_nf(ah, chan); diff --git a/trunk/drivers/net/wireless/ath/ath9k/common.h b/trunk/drivers/net/wireless/ath/ath9k/common.h index eca95a0c3890..5f845beeb18b 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/common.h +++ b/trunk/drivers/net/wireless/ath/ath9k/common.h @@ -40,7 +40,7 @@ x = ATH_LPF_RSSI((x), ATH_RSSI_IN((y)), ATH_RSSI_LPF_LEN); \ } while (0) #define ATH_EP_RND(x, mul) \ - (((x) + ((mul)/2)) / (mul)) + ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul)) int ath9k_cmn_padpos(__le16 frame_control); int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb); diff --git a/trunk/drivers/net/wireless/ath/ath9k/debug.c b/trunk/drivers/net/wireless/ath/ath9k/debug.c index 67a2a4b3b883..3714b971d18e 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/debug.c +++ b/trunk/drivers/net/wireless/ath/ath9k/debug.c @@ -537,7 +537,6 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf, PR("AMPDUs Completed:", a_completed); PR("AMPDUs Retried: ", a_retries); PR("AMPDUs XRetried: ", a_xretries); - PR("TXERR Filtered: ", txerr_filtered); PR("FIFO Underrun: ", fifo_underrun); PR("TXOP Exceeded: ", xtxop); PR("TXTIMER Expiry: ", timer_exp); @@ -757,8 +756,6 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, TX_STAT_INC(qnum, completed); } - if (ts->ts_status & ATH9K_TXERR_FILT) - TX_STAT_INC(qnum, txerr_filtered); if (ts->ts_status & ATH9K_TXERR_FIFO) TX_STAT_INC(qnum, fifo_underrun); if (ts->ts_status & ATH9K_TXERR_XTXOP) @@ -1912,7 +1909,6 @@ static const char ath9k_gstrings_stats[][ETH_GSTRING_LEN] = { AMKSTR(d_tx_desc_cfg_err), AMKSTR(d_tx_data_underrun), AMKSTR(d_tx_delim_underrun), - "d_rx_crc_err", "d_rx_decrypt_crc_err", "d_rx_phy_err", "d_rx_mic_err", @@ -1993,7 +1989,6 @@ void ath9k_get_et_stats(struct ieee80211_hw *hw, AWDATA(data_underrun); AWDATA(delim_underrun); - AWDATA_RX(crc_err); AWDATA_RX(decrypt_crc_err); AWDATA_RX(phy_err); AWDATA_RX(mic_err); diff --git a/trunk/drivers/net/wireless/ath/ath9k/debug.h b/trunk/drivers/net/wireless/ath/ath9k/debug.h index 794a7ec83a24..410d6d8f1aa7 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/debug.h +++ b/trunk/drivers/net/wireless/ath/ath9k/debug.h @@ -142,7 +142,6 @@ struct ath_interrupt_stats { * @a_completed: Total AMPDUs completed * @a_retries: No. of AMPDUs retried (SW) * @a_xretries: No. of AMPDUs dropped due to xretries - * @txerr_filtered: No. of frames with TXERR_FILT flag set. * @fifo_underrun: FIFO underrun occurrences Valid only for: - non-aggregate condition. @@ -169,7 +168,6 @@ struct ath_tx_stats { u32 a_completed; u32 a_retries; u32 a_xretries; - u32 txerr_filtered; u32 fifo_underrun; u32 xtxop; u32 timer_exp; diff --git a/trunk/drivers/net/wireless/ath/ath9k/hw.c b/trunk/drivers/net/wireless/ath/ath9k/hw.c index 767222f2ba5c..2a2ae403e0e5 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/hw.c +++ b/trunk/drivers/net/wireless/ath/ath9k/hw.c @@ -1667,104 +1667,6 @@ bool ath9k_hw_check_alive(struct ath_hw *ah) } EXPORT_SYMBOL(ath9k_hw_check_alive); -static void ath9k_hw_init_mfp(struct ath_hw *ah) -{ - /* Setup MFP options for CCMP */ - if (AR_SREV_9280_20_OR_LATER(ah)) { - /* Mask Retry(b11), PwrMgt(b12), MoreData(b13) to 0 in mgmt - * frames when constructing CCMP AAD. */ - REG_RMW_FIELD(ah, AR_AES_MUTE_MASK1, AR_AES_MUTE_MASK1_FC_MGMT, - 0xc7ff); - ah->sw_mgmt_crypto = false; - } else if (AR_SREV_9160_10_OR_LATER(ah)) { - /* Disable hardware crypto for management frames */ - REG_CLR_BIT(ah, AR_PCU_MISC_MODE2, - AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE); - REG_SET_BIT(ah, AR_PCU_MISC_MODE2, - AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT); - ah->sw_mgmt_crypto = true; - } else { - ah->sw_mgmt_crypto = true; - } -} - -static void ath9k_hw_reset_opmode(struct ath_hw *ah, - u32 macStaId1, u32 saveDefAntenna) -{ - struct ath_common *common = ath9k_hw_common(ah); - - ENABLE_REGWRITE_BUFFER(ah); - - REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr)); - REG_WRITE(ah, AR_STA_ID1, get_unaligned_le16(common->macaddr + 4) - | macStaId1 - | AR_STA_ID1_RTS_USE_DEF - | (ah->config.ack_6mb ? AR_STA_ID1_ACKCTS_6MB : 0) - | ah->sta_id1_defaults); - ath_hw_setbssidmask(common); - REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna); - ath9k_hw_write_associd(ah); - REG_WRITE(ah, AR_ISR, ~0); - REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR); - - REGWRITE_BUFFER_FLUSH(ah); - - ath9k_hw_set_operating_mode(ah, ah->opmode); -} - -static void ath9k_hw_init_queues(struct ath_hw *ah) -{ - int i; - - ENABLE_REGWRITE_BUFFER(ah); - - for (i = 0; i < AR_NUM_DCU; i++) - REG_WRITE(ah, AR_DQCUMASK(i), 1 << i); - - REGWRITE_BUFFER_FLUSH(ah); - - ah->intr_txqs = 0; - for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) - ath9k_hw_resettxqueue(ah, i); -} - -/* - * For big endian systems turn on swapping for descriptors - */ -static void ath9k_hw_init_desc(struct ath_hw *ah) -{ - struct ath_common *common = ath9k_hw_common(ah); - - if (AR_SREV_9100(ah)) { - u32 mask; - mask = REG_READ(ah, AR_CFG); - if (mask & (AR_CFG_SWRB | AR_CFG_SWTB | AR_CFG_SWRG)) { - ath_dbg(common, RESET, "CFG Byte Swap Set 0x%x\n", - mask); - } else { - mask = INIT_CONFIG_STATUS | AR_CFG_SWRB | AR_CFG_SWTB; - REG_WRITE(ah, AR_CFG, mask); - ath_dbg(common, RESET, "Setting CFG 0x%x\n", - REG_READ(ah, AR_CFG)); - } - } else { - if (common->bus_ops->ath_bus_type == ATH_USB) { - /* Configure AR9271 target WLAN */ - if (AR_SREV_9271(ah)) - REG_WRITE(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB); - else - REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); - } -#ifdef __BIG_ENDIAN - else if (AR_SREV_9330(ah) || AR_SREV_9340(ah) || - AR_SREV_9550(ah)) - REG_RMW(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB, 0); - else - REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); -#endif - } -} - /* * Fast channel change: * (Change synthesizer based on channel freq without resetting chip) @@ -1842,7 +1744,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, u32 saveDefAntenna; u32 macStaId1; u64 tsf = 0; - int r; + int i, r; bool start_mci_reset = false; bool save_fullsleep = ah->chip_fullsleep; @@ -1859,8 +1761,10 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, ath9k_hw_getnf(ah, ah->curchan); ah->caldata = caldata; - if (caldata && (chan->channel != caldata->channel || - chan->channelFlags != caldata->channelFlags)) { + if (caldata && + (chan->channel != caldata->channel || + (chan->channelFlags & ~CHANNEL_CW_INT) != + (caldata->channelFlags & ~CHANNEL_CW_INT))) { /* Operating channel changed, reset channel calibration data */ memset(caldata, 0, sizeof(*caldata)); ath9k_init_nfcal_hist_buffer(ah, chan); @@ -1947,7 +1851,22 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, ath9k_hw_settsf64(ah, tsf); } - ath9k_hw_init_mfp(ah); + /* Setup MFP options for CCMP */ + if (AR_SREV_9280_20_OR_LATER(ah)) { + /* Mask Retry(b11), PwrMgt(b12), MoreData(b13) to 0 in mgmt + * frames when constructing CCMP AAD. */ + REG_RMW_FIELD(ah, AR_AES_MUTE_MASK1, AR_AES_MUTE_MASK1_FC_MGMT, + 0xc7ff); + ah->sw_mgmt_crypto = false; + } else if (AR_SREV_9160_10_OR_LATER(ah)) { + /* Disable hardware crypto for management frames */ + REG_CLR_BIT(ah, AR_PCU_MISC_MODE2, + AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE); + REG_SET_BIT(ah, AR_PCU_MISC_MODE2, + AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT); + ah->sw_mgmt_crypto = true; + } else + ah->sw_mgmt_crypto = true; if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan)) ath9k_hw_set_delta_slope(ah, chan); @@ -1955,7 +1874,24 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, ath9k_hw_spur_mitigate_freq(ah, chan); ah->eep_ops->set_board_values(ah, chan); - ath9k_hw_reset_opmode(ah, macStaId1, saveDefAntenna); + ENABLE_REGWRITE_BUFFER(ah); + + REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr)); + REG_WRITE(ah, AR_STA_ID1, get_unaligned_le16(common->macaddr + 4) + | macStaId1 + | AR_STA_ID1_RTS_USE_DEF + | (ah->config. + ack_6mb ? AR_STA_ID1_ACKCTS_6MB : 0) + | ah->sta_id1_defaults); + ath_hw_setbssidmask(common); + REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna); + ath9k_hw_write_associd(ah); + REG_WRITE(ah, AR_ISR, ~0); + REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR); + + REGWRITE_BUFFER_FLUSH(ah); + + ath9k_hw_set_operating_mode(ah, ah->opmode); r = ath9k_hw_rf_set_freq(ah, chan); if (r) @@ -1963,7 +1899,17 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, ath9k_hw_set_clockrate(ah); - ath9k_hw_init_queues(ah); + ENABLE_REGWRITE_BUFFER(ah); + + for (i = 0; i < AR_NUM_DCU; i++) + REG_WRITE(ah, AR_DQCUMASK(i), 1 << i); + + REGWRITE_BUFFER_FLUSH(ah); + + ah->intr_txqs = 0; + for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) + ath9k_hw_resettxqueue(ah, i); + ath9k_hw_init_interrupt_masks(ah, ah->opmode); ath9k_hw_ani_cache_ini_regs(ah); ath9k_hw_init_qos(ah); @@ -2018,7 +1964,38 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, REGWRITE_BUFFER_FLUSH(ah); - ath9k_hw_init_desc(ah); + /* + * For big endian systems turn on swapping for descriptors + */ + if (AR_SREV_9100(ah)) { + u32 mask; + mask = REG_READ(ah, AR_CFG); + if (mask & (AR_CFG_SWRB | AR_CFG_SWTB | AR_CFG_SWRG)) { + ath_dbg(common, RESET, "CFG Byte Swap Set 0x%x\n", + mask); + } else { + mask = + INIT_CONFIG_STATUS | AR_CFG_SWRB | AR_CFG_SWTB; + REG_WRITE(ah, AR_CFG, mask); + ath_dbg(common, RESET, "Setting CFG 0x%x\n", + REG_READ(ah, AR_CFG)); + } + } else { + if (common->bus_ops->ath_bus_type == ATH_USB) { + /* Configure AR9271 target WLAN */ + if (AR_SREV_9271(ah)) + REG_WRITE(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB); + else + REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); + } +#ifdef __BIG_ENDIAN + else if (AR_SREV_9330(ah) || AR_SREV_9340(ah) || + AR_SREV_9550(ah)) + REG_RMW(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB, 0); + else + REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); +#endif + } if (ath9k_hw_btcoex_is_enabled(ah)) ath9k_hw_btcoex_enable(ah); @@ -2031,6 +2008,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, if (AR_SREV_9300_20_OR_LATER(ah)) { ar9003_hw_bb_watchdog_config(ah); + ar9003_hw_disable_phy_restart(ah); } diff --git a/trunk/drivers/net/wireless/ath/ath9k/hw.h b/trunk/drivers/net/wireless/ath/ath9k/hw.h index 30e62d92d46d..784e81ccb903 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/hw.h +++ b/trunk/drivers/net/wireless/ath/ath9k/hw.h @@ -363,6 +363,7 @@ enum ath9k_int { ATH9K_INT_NOCARD = 0xffffffff }; +#define CHANNEL_CW_INT 0x00002 #define CHANNEL_CCK 0x00020 #define CHANNEL_OFDM 0x00040 #define CHANNEL_2GHZ 0x00080 diff --git a/trunk/drivers/net/wireless/ath/carl9170/tx.c b/trunk/drivers/net/wireless/ath/carl9170/tx.c index c61cafa2665b..9c0b150d5b8e 100644 --- a/trunk/drivers/net/wireless/ath/carl9170/tx.c +++ b/trunk/drivers/net/wireless/ath/carl9170/tx.c @@ -387,7 +387,8 @@ static void carl9170_tx_status_process_ampdu(struct ar9170 *ar, u8 tid; if (!(txinfo->flags & IEEE80211_TX_CTL_AMPDU) || - txinfo->flags & IEEE80211_TX_CTL_INJECTED) + txinfo->flags & IEEE80211_TX_CTL_INJECTED || + (!(super->f.mac_control & cpu_to_le16(AR9170_TX_MAC_AGGR)))) return; rcu_read_lock(); @@ -980,6 +981,30 @@ static int carl9170_tx_prepare(struct ar9170 *ar, SET_VAL(CARL9170_TX_SUPER_AMPDU_FACTOR, txc->s.ampdu_settings, factor); + + for (i = 0; i < CARL9170_TX_MAX_RATES; i++) { + txrate = &info->control.rates[i]; + if (txrate->idx >= 0) { + txc->s.ri[i] = + CARL9170_TX_SUPER_RI_AMPDU; + + if (WARN_ON(!(txrate->flags & + IEEE80211_TX_RC_MCS))) { + /* + * Not sure if it's even possible + * to aggregate non-ht rates with + * this HW. + */ + goto err_out; + } + continue; + } + + txrate->idx = 0; + txrate->count = ar->hw->max_rate_tries; + } + + mac_tmp |= cpu_to_le16(AR9170_TX_MAC_AGGR); } /* @@ -987,31 +1012,11 @@ static int carl9170_tx_prepare(struct ar9170 *ar, * taken from mac_control. For all fallback rate, the firmware * updates the mac_control flags from the rate info field. */ - for (i = 0; i < CARL9170_TX_MAX_RATES; i++) { - __le32 phy_set; + for (i = 1; i < CARL9170_TX_MAX_RATES; i++) { txrate = &info->control.rates[i]; if (txrate->idx < 0) break; - phy_set = carl9170_tx_physet(ar, info, txrate); - if (i == 0) { - /* first rate - part of the hw's frame header */ - txc->f.phy_control = phy_set; - - if (ampdu && txrate->flags & IEEE80211_TX_RC_MCS) - mac_tmp |= cpu_to_le16(AR9170_TX_MAC_AGGR); - if (carl9170_tx_rts_check(ar, txrate, ampdu, no_ack)) - mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS); - else if (carl9170_tx_cts_check(ar, txrate)) - mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS); - - } else { - /* fallback rates are stored in the firmware's - * retry rate set array. - */ - txc->s.rr[i - 1] = phy_set; - } - SET_VAL(CARL9170_TX_SUPER_RI_TRIES, txc->s.ri[i], txrate->count); @@ -1022,13 +1027,21 @@ static int carl9170_tx_prepare(struct ar9170 *ar, txc->s.ri[i] |= (AR9170_TX_MAC_PROT_CTS << CARL9170_TX_SUPER_RI_ERP_PROT_S); - if (ampdu && (txrate->flags & IEEE80211_TX_RC_MCS)) - txc->s.ri[i] |= CARL9170_TX_SUPER_RI_AMPDU; + txc->s.rr[i - 1] = carl9170_tx_physet(ar, info, txrate); } + txrate = &info->control.rates[0]; + SET_VAL(CARL9170_TX_SUPER_RI_TRIES, txc->s.ri[0], txrate->count); + + if (carl9170_tx_rts_check(ar, txrate, ampdu, no_ack)) + mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS); + else if (carl9170_tx_cts_check(ar, txrate)) + mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS); + txc->s.len = cpu_to_le16(skb->len); txc->f.length = cpu_to_le16(len + FCS_LEN); txc->f.mac_control = mac_tmp; + txc->f.phy_control = carl9170_tx_physet(ar, info, txrate); arinfo = (void *)info->rate_driver_data; arinfo->timeout = jiffies; @@ -1368,9 +1381,9 @@ static void carl9170_tx(struct ar9170 *ar) } static bool carl9170_tx_ampdu_queue(struct ar9170 *ar, - struct ieee80211_sta *sta, struct sk_buff *skb, - struct ieee80211_tx_info *txinfo) + struct ieee80211_sta *sta, struct sk_buff *skb) { + struct _carl9170_tx_superframe *super = (void *) skb->data; struct carl9170_sta_info *sta_info; struct carl9170_sta_tid *agg; struct sk_buff *iter; @@ -1437,7 +1450,7 @@ static bool carl9170_tx_ampdu_queue(struct ar9170 *ar, err_unlock_rcu: rcu_read_unlock(); - txinfo->flags &= ~IEEE80211_TX_CTL_AMPDU; + super->f.mac_control &= ~cpu_to_le16(AR9170_TX_MAC_AGGR); carl9170_tx_status(ar, skb, false); ar->tx_dropped++; return false; @@ -1479,7 +1492,7 @@ void carl9170_op_tx(struct ieee80211_hw *hw, * sta == NULL checks are redundant in this * special case. */ - run = carl9170_tx_ampdu_queue(ar, sta, skb, info); + run = carl9170_tx_ampdu_queue(ar, sta, skb); if (run) carl9170_tx_ampdu(ar); diff --git a/trunk/drivers/net/wireless/ath/wil6210/Makefile b/trunk/drivers/net/wireless/ath/wil6210/Makefile index d288eea0a26a..9396dc9fe3c5 100644 --- a/trunk/drivers/net/wireless/ath/wil6210/Makefile +++ b/trunk/drivers/net/wireless/ath/wil6210/Makefile @@ -9,7 +9,5 @@ wil6210-objs += wmi.o wil6210-objs += interrupt.o wil6210-objs += txrx.o -ifeq (, $(findstring -W,$(EXTRA_CFLAGS))) - subdir-ccflags-y += -Werror -endif +subdir-ccflags-y += -Werror subdir-ccflags-y += -D__CHECK_ENDIAN__ diff --git a/trunk/drivers/net/wireless/ath/wil6210/debugfs.c b/trunk/drivers/net/wireless/ath/wil6210/debugfs.c index 1e709bfb63a3..65fc9683bfd8 100644 --- a/trunk/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/trunk/drivers/net/wireless/ath/wil6210/debugfs.c @@ -312,6 +312,14 @@ static const struct file_operations fops_memread = { .llseek = seq_lseek, }; +static int wil_default_open(struct inode *inode, struct file *file) +{ + if (inode->i_private) + file->private_data = inode->i_private; + + return 0; +} + static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -353,7 +361,7 @@ static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf, static const struct file_operations fops_ioblob = { .read = wil_read_file_ioblob, - .open = simple_open, + .open = wil_default_open, .llseek = default_llseek, }; @@ -388,7 +396,7 @@ static ssize_t wil_write_file_reset(struct file *file, const char __user *buf, static const struct file_operations fops_reset = { .write = wil_write_file_reset, - .open = simple_open, + .open = wil_default_open, }; /*---------Tx descriptor------------*/ @@ -518,7 +526,7 @@ static ssize_t wil_write_file_ssid(struct file *file, const char __user *buf, static const struct file_operations fops_ssid = { .read = wil_read_file_ssid, .write = wil_write_file_ssid, - .open = simple_open, + .open = wil_default_open, }; /*----------------*/ diff --git a/trunk/drivers/net/wireless/b43/Kconfig b/trunk/drivers/net/wireless/b43/Kconfig index 078e6f3477a9..287c6b670a36 100644 --- a/trunk/drivers/net/wireless/b43/Kconfig +++ b/trunk/drivers/net/wireless/b43/Kconfig @@ -131,7 +131,7 @@ config B43_PHY_LP config B43_PHY_HT bool "Support for HT-PHY (high throughput) devices" - depends on B43 && B43_BCMA + depends on B43 ---help--- Support for the HT-PHY. @@ -166,8 +166,8 @@ config B43_DEBUG Broadcom 43xx debugging. This adds additional runtime sanity checks and statistics to the driver. - These checks and statistics might be expensive and hurt the runtime - performance of your system. + These checks and statistics might me expensive and hurt runtime performance + of your system. This also adds the b43 debugfs interface. Do not enable this, unless you are debugging the driver. diff --git a/trunk/drivers/net/wireless/b43/b43.h b/trunk/drivers/net/wireless/b43/b43.h index fe4a77ee05c9..10e288d470e7 100644 --- a/trunk/drivers/net/wireless/b43/b43.h +++ b/trunk/drivers/net/wireless/b43/b43.h @@ -473,12 +473,6 @@ enum { #define B43_MACCMD_CCA 0x00000008 /* Clear channel assessment */ #define B43_MACCMD_BGNOISE 0x00000010 /* Background noise */ -/* See BCMA_CLKCTLST_EXTRESREQ and BCMA_CLKCTLST_EXTRESST */ -#define B43_BCMA_CLKCTLST_80211_PLL_REQ 0x00000100 -#define B43_BCMA_CLKCTLST_PHY_PLL_REQ 0x00000200 -#define B43_BCMA_CLKCTLST_80211_PLL_ST 0x01000000 -#define B43_BCMA_CLKCTLST_PHY_PLL_ST 0x02000000 - /* BCMA 802.11 core specific IO Control (BCMA_IOCTL) flags */ #define B43_BCMA_IOCTL_PHY_CLKEN 0x00000004 /* PHY Clock Enable */ #define B43_BCMA_IOCTL_PHY_RESET 0x00000008 /* PHY Reset */ diff --git a/trunk/drivers/net/wireless/b43/main.c b/trunk/drivers/net/wireless/b43/main.c index c4d0cc582555..05682736e466 100644 --- a/trunk/drivers/net/wireless/b43/main.c +++ b/trunk/drivers/net/wireless/b43/main.c @@ -1189,15 +1189,10 @@ static void b43_bcma_phy_reset(struct b43_wldev *dev) static void b43_bcma_wireless_core_reset(struct b43_wldev *dev, bool gmode) { - u32 req = B43_BCMA_CLKCTLST_80211_PLL_REQ | - B43_BCMA_CLKCTLST_PHY_PLL_REQ; - u32 status = B43_BCMA_CLKCTLST_80211_PLL_ST | - B43_BCMA_CLKCTLST_PHY_PLL_ST; - b43_device_enable(dev, B43_BCMA_IOCTL_PHY_CLKEN); bcma_core_set_clockmode(dev->dev->bdev, BCMA_CLKMODE_FAST); b43_bcma_phy_reset(dev); - bcma_core_pll_ctl(dev->dev->bdev, req, status, true); + bcma_core_pll_ctl(dev->dev->bdev, 0x300, 0x3000000, true); } #endif diff --git a/trunk/drivers/net/wireless/b43/phy_ht.c b/trunk/drivers/net/wireless/b43/phy_ht.c index 3719a8884c1e..7416c5e9154d 100644 --- a/trunk/drivers/net/wireless/b43/phy_ht.c +++ b/trunk/drivers/net/wireless/b43/phy_ht.c @@ -346,11 +346,6 @@ static int b43_phy_ht_op_init(struct b43_wldev *dev) u16 tmp; u16 clip_state[3]; - if (dev->dev->bus_type != B43_BUS_BCMA) { - b43err(dev->wl, "HT-PHY is supported only on BCMA bus!\n"); - return -EOPNOTSUPP; - } - b43_phy_ht_tables_init(dev); b43_phy_mask(dev, 0x0be, ~0x2); diff --git a/trunk/drivers/net/wireless/brcm80211/Kconfig b/trunk/drivers/net/wireless/brcm80211/Kconfig index 747e9317dabd..1d92d874ebb6 100644 --- a/trunk/drivers/net/wireless/brcm80211/Kconfig +++ b/trunk/drivers/net/wireless/brcm80211/Kconfig @@ -12,9 +12,8 @@ config BRCMSMAC select CORDIC ---help--- This module adds support for PCIe wireless adapters based on Broadcom - IEEE802.11n SoftMAC chipsets. It also has WLAN led support, which will - be available if you select BCMA_DRIVER_GPIO. If you choose to build a - module, the driver will be called brcmsmac.ko. + IEEE802.11n SoftMAC chipsets. If you choose to build a module, it'll + be called brcmsmac.ko. config BRCMFMAC tristate "Broadcom IEEE802.11n embedded FullMAC WLAN driver" diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/Makefile b/trunk/drivers/net/wireless/brcm80211/brcmfmac/Makefile index 598c8e2f8d2b..756e19fc2795 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/Makefile +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/Makefile @@ -26,7 +26,6 @@ brcmfmac-objs += \ wl_cfg80211.o \ fwil.o \ fweh.o \ - fwsignal.o \ p2p.o \ dhd_cdc.o \ dhd_common.o \ @@ -40,5 +39,3 @@ brcmfmac-$(CONFIG_BRCMFMAC_USB) += \ usb.o brcmfmac-$(CONFIG_BRCMDBG) += \ dhd_dbg.o -brcmfmac-$(CONFIG_BRCM_TRACING) += \ - tracepoint.o diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd.h index c7fa20846b32..ef6f23be6d32 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd.h +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd.h @@ -501,7 +501,6 @@ struct brcmf_dcmd { /* Forward decls for struct brcmf_pub (see below) */ struct brcmf_proto; /* device communication protocol info */ struct brcmf_cfg80211_dev; /* cfg80211 device info */ -struct brcmf_fws_info; /* firmware signalling info */ /* Common structure for module and instance linkage */ struct brcmf_pub { @@ -528,10 +527,6 @@ struct brcmf_pub { unsigned char proto_buf[BRCMF_DCMD_MAXLEN]; struct brcmf_fweh_info fweh; - - bool fw_signals; - struct brcmf_fws_info *fws; - spinlock_t fws_spinlock; #ifdef DEBUG struct dentry *dbgfs_dir; #endif @@ -587,7 +582,7 @@ extern int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf, uint len); /* Remove any protocol-specific data header. */ -extern int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, +extern int brcmf_proto_hdrpull(struct brcmf_pub *drvr, u8 *ifidx, struct sk_buff *rxp); extern int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked); diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h index 883ef9063e8a..ad25c3408b59 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h @@ -134,7 +134,7 @@ extern void brcmf_dev_reset(struct device *dev); /* Indication from bus module to change flow-control state */ extern void brcmf_txflowblock(struct device *dev, bool state); -/* Notify the bus has transferred the tx packet to firmware */ +/* Notify tx completion */ extern void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success); diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c index e224bcb90024..a2354d951dd7 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c @@ -28,7 +28,6 @@ #include "dhd.h" #include "dhd_proto.h" #include "dhd_bus.h" -#include "fwsignal.h" #include "dhd_dbg.h" struct brcmf_proto_cdc_dcmd { @@ -72,26 +71,13 @@ struct brcmf_proto_cdc_dcmd { ((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_IF_MASK) | \ ((idx) << BDC_FLAG2_IF_SHIFT))) -/** - * struct brcmf_proto_bdc_header - BDC header format - * - * @flags: flags contain protocol and checksum info. - * @priority: 802.1d priority and USB flow control info (bit 4:7). - * @flags2: additional flags containing dongle interface index. - * @data_offset: start of packet data. header is following by firmware signals. - */ struct brcmf_proto_bdc_header { u8 flags; - u8 priority; + u8 priority; /* 802.1d Priority, 4:7 flow control info for usb */ u8 flags2; u8 data_offset; }; -/* - * maximum length of firmware signal data between - * the BDC header and packet data in the tx path. - */ -#define BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES 12 #define RETRIES 2 /* # of retries to retrieve matching dcmd response */ #define BUS_HEADER_LEN (16+64) /* Must be atleast SDPCM_RESERVE @@ -272,7 +258,7 @@ static void pkt_set_sum_good(struct sk_buff *skb, bool x) skb->ip_summed = (x ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE); } -void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx, u8 offset, +void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx, struct sk_buff *pktbuf) { struct brcmf_proto_bdc_header *h; @@ -280,6 +266,7 @@ void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx, u8 offset, brcmf_dbg(CDC, "Enter\n"); /* Push BDC header used to convey priority for buses that don't */ + skb_push(pktbuf, BDC_HEADER_LEN); h = (struct brcmf_proto_bdc_header *)(pktbuf->data); @@ -290,11 +277,11 @@ void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx, u8 offset, h->priority = (pktbuf->priority & BDC_PRIORITY_MASK); h->flags2 = 0; - h->data_offset = offset; + h->data_offset = 0; BDC_SET_IF_IDX(h, ifidx); } -int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, +int brcmf_proto_hdrpull(struct brcmf_pub *drvr, u8 *ifidx, struct sk_buff *pktbuf) { struct brcmf_proto_bdc_header *h; @@ -341,10 +328,7 @@ int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, pktbuf->priority = h->priority & BDC_PRIORITY_MASK; skb_pull(pktbuf, BDC_HEADER_LEN); - if (do_fws) - brcmf_fws_hdrpull(drvr, *ifidx, h->data_offset << 2, pktbuf); - else - skb_pull(pktbuf, h->data_offset << 2); + skb_pull(pktbuf, h->data_offset << 2); if (pktbuf->len == 0) return -ENODATA; @@ -366,7 +350,7 @@ int brcmf_proto_attach(struct brcmf_pub *drvr) } drvr->prot = cdc; - drvr->hdrlen += BDC_HEADER_LEN + BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES; + drvr->hdrlen += BDC_HEADER_LEN; drvr->bus_if->maxctl = BRCMF_DCMD_MAXLEN + sizeof(struct brcmf_proto_cdc_dcmd) + ROUND_UP_MARGIN; return 0; diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c index be0787cab24f..4544342a0428 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c @@ -24,7 +24,6 @@ #include "dhd_proto.h" #include "dhd_dbg.h" #include "fwil.h" -#include "tracepoint.h" #define PKTFILTER_BUF_SIZE 128 #define BRCMF_ARPOL_MODE 0xb /* agent|snoop|peer_autoreply */ @@ -374,35 +373,3 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) done: return err; } - -#ifdef CONFIG_BRCM_TRACING -void __brcmf_err(const char *func, const char *fmt, ...) -{ - struct va_format vaf = { - .fmt = fmt, - }; - va_list args; - - va_start(args, fmt); - vaf.va = &args; - pr_err("%s: %pV", func, &vaf); - trace_brcmf_err(func, &vaf); - va_end(args); -} -#endif -#if defined(CONFIG_BRCM_TRACING) || defined(CONFIG_BRCMDBG) -void __brcmf_dbg(u32 level, const char *func, const char *fmt, ...) -{ - struct va_format vaf = { - .fmt = fmt, - }; - va_list args; - - va_start(args, fmt); - vaf.va = &args; - if (brcmf_msg_level & level) - pr_debug("%s %pV", func, &vaf); - trace_brcmf_dbg(level, func, &vaf); - va_end(args); -} -#endif diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c index ac792499b46a..57671eddf79d 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c @@ -22,7 +22,6 @@ #include "dhd.h" #include "dhd_bus.h" #include "dhd_dbg.h" -#include "tracepoint.h" static struct dentry *root_folder; @@ -124,44 +123,3 @@ void brcmf_debugfs_create_sdio_count(struct brcmf_pub *drvr, debugfs_create_file("counters", S_IRUGO, dentry, sdcnt, &brcmf_debugfs_sdio_counter_ops); } - -static -ssize_t brcmf_debugfs_fws_stats_read(struct file *f, char __user *data, - size_t count, loff_t *ppos) -{ - struct brcmf_fws_stats *fwstats = f->private_data; - char buf[100]; - int res; - - /* only allow read from start */ - if (*ppos > 0) - return 0; - - res = scnprintf(buf, sizeof(buf), - "header_pulls: %u\n" - "header_only_pkt: %u\n" - "tlv_parse_failed: %u\n" - "tlv_invalid_type: %u\n", - fwstats->header_pulls, - fwstats->header_only_pkt, - fwstats->tlv_parse_failed, - fwstats->tlv_invalid_type); - - return simple_read_from_buffer(data, count, ppos, buf, res); -} - -static const struct file_operations brcmf_debugfs_fws_stats_ops = { - .owner = THIS_MODULE, - .open = simple_open, - .read = brcmf_debugfs_fws_stats_read -}; - -void brcmf_debugfs_create_fws_stats(struct brcmf_pub *drvr, - struct brcmf_fws_stats *stats) -{ - struct dentry *dentry = drvr->dbgfs_dir; - - if (!IS_ERR_OR_NULL(dentry)) - debugfs_create_file("fws_stats", S_IRUGO, dentry, - stats, &brcmf_debugfs_fws_stats_ops); -} diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h index 4bc646bde16f..bc013cbe06f6 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h @@ -43,7 +43,6 @@ * debugging is not selected. When debugging the driver error * messages are as important as other tracing or even more so. */ -#ifndef CONFIG_BRCM_TRACING #ifdef CONFIG_BRCMDBG #define brcmf_err(fmt, ...) pr_err("%s: " fmt, __func__, ##__VA_ARGS__) #else @@ -53,21 +52,15 @@ pr_err("%s: " fmt, __func__, ##__VA_ARGS__); \ } while (0) #endif -#else -__printf(2, 3) -void __brcmf_err(const char *func, const char *fmt, ...); -#define brcmf_err(fmt, ...) \ - __brcmf_err(__func__, fmt, ##__VA_ARGS__) -#endif -#if defined(DEBUG) || defined(CONFIG_BRCM_TRACING) -__printf(3, 4) -void __brcmf_dbg(u32 level, const char *func, const char *fmt, ...); +#if defined(DEBUG) + #define brcmf_dbg(level, fmt, ...) \ do { \ - __brcmf_dbg(BRCMF_##level##_VAL, __func__, \ - fmt, ##__VA_ARGS__); \ + if (brcmf_msg_level & BRCMF_##level##_VAL) \ + pr_debug("%s: " fmt, __func__, ##__VA_ARGS__); \ } while (0) + #define BRCMF_DATA_ON() (brcmf_msg_level & BRCMF_DATA_VAL) #define BRCMF_CTL_ON() (brcmf_msg_level & BRCMF_CTL_VAL) #define BRCMF_HDRS_ON() (brcmf_msg_level & BRCMF_HDRS_VAL) @@ -76,7 +69,7 @@ do { \ #define BRCMF_EVENT_ON() (brcmf_msg_level & BRCMF_EVENT_VAL) #define BRCMF_FIL_ON() (brcmf_msg_level & BRCMF_FIL_VAL) -#else /* defined(DEBUG) || defined(CONFIG_BRCM_TRACING) */ +#else /* (defined DEBUG) || (defined DEBUG) */ #define brcmf_dbg(level, fmt, ...) no_printk(fmt, ##__VA_ARGS__) @@ -88,7 +81,7 @@ do { \ #define BRCMF_EVENT_ON() 0 #define BRCMF_FIL_ON() 0 -#endif /* defined(DEBUG) || defined(CONFIG_BRCM_TRACING) */ +#endif /* defined(DEBUG) */ #define brcmf_dbg_hex_dump(test, data, len, fmt, ...) \ do { \ @@ -132,13 +125,6 @@ struct brcmf_sdio_count { ulong rx_readahead_cnt; /* packets where header read-ahead was used */ }; -struct brcmf_fws_stats { - u32 tlv_parse_failed; - u32 tlv_invalid_type; - u32 header_only_pkt; - u32 header_pulls; -}; - struct brcmf_pub; #ifdef DEBUG void brcmf_debugfs_init(void); @@ -148,8 +134,6 @@ void brcmf_debugfs_detach(struct brcmf_pub *drvr); struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr); void brcmf_debugfs_create_sdio_count(struct brcmf_pub *drvr, struct brcmf_sdio_count *sdcnt); -void brcmf_debugfs_create_fws_stats(struct brcmf_pub *drvr, - struct brcmf_fws_stats *stats); #else static inline void brcmf_debugfs_init(void) { @@ -164,10 +148,6 @@ static inline int brcmf_debugfs_attach(struct brcmf_pub *drvr) static inline void brcmf_debugfs_detach(struct brcmf_pub *drvr) { } -static inline void brcmf_debugfs_create_fws_stats(struct brcmf_pub *drvr, - struct brcmf_fws_stats *stats) -{ -} #endif #endif /* _BRCMF_DBG_H_ */ diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index fa5a2af04d46..c06cea88df0d 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c @@ -30,18 +30,17 @@ #include "p2p.h" #include "wl_cfg80211.h" #include "fwil.h" -#include "fwsignal.h" MODULE_AUTHOR("Broadcom Corporation"); MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver."); +MODULE_SUPPORTED_DEVICE("Broadcom 802.11 WLAN fullmac cards"); MODULE_LICENSE("Dual BSD/GPL"); #define MAX_WAIT_FOR_8021X_TX 50 /* msecs */ /* Error bits */ int brcmf_msg_level; -module_param_named(debug, brcmf_msg_level, int, S_IRUSR | S_IWUSR); -MODULE_PARM_DESC(debug, "level of debug output"); +module_param(brcmf_msg_level, int, 0); /* P2P0 enable */ static int brcmf_p2p_enable; @@ -231,7 +230,7 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb, atomic_inc(&ifp->pend_8021x_cnt); /* If the protocol uses a data header, apply it */ - brcmf_proto_hdrpush(drvr, ifp->ifidx, 0, skb); + brcmf_proto_hdrpush(drvr, ifp->ifidx, skb); /* Use bus module to send data frame */ ret = brcmf_bus_txdata(drvr->bus_if, skb); @@ -284,7 +283,7 @@ void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list) skb_unlink(skb, skb_list); /* process and remove protocol-specific header */ - ret = brcmf_proto_hdrpull(drvr, drvr->fw_signals, &ifidx, skb); + ret = brcmf_proto_hdrpull(drvr, &ifidx, skb); ifp = drvr->iflist[ifidx]; if (ret || !ifp || !ifp->ndev) { @@ -358,29 +357,23 @@ void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success) struct brcmf_bus *bus_if = dev_get_drvdata(dev); struct brcmf_pub *drvr = bus_if->drvr; struct brcmf_if *ifp; - int res; - res = brcmf_proto_hdrpull(drvr, false, &ifidx, txp); + brcmf_proto_hdrpull(drvr, &ifidx, txp); ifp = drvr->iflist[ifidx]; if (!ifp) - goto done; + return; - if (res == 0) { - eh = (struct ethhdr *)(txp->data); - type = ntohs(eh->h_proto); + eh = (struct ethhdr *)(txp->data); + type = ntohs(eh->h_proto); - if (type == ETH_P_PAE) { - atomic_dec(&ifp->pend_8021x_cnt); - if (waitqueue_active(&ifp->pend_8021x_wait)) - wake_up(&ifp->pend_8021x_wait); - } + if (type == ETH_P_PAE) { + atomic_dec(&ifp->pend_8021x_cnt); + if (waitqueue_active(&ifp->pend_8021x_wait)) + wake_up(&ifp->pend_8021x_wait); } if (!success) ifp->stats.tx_errors++; - -done: - brcmu_pkt_buf_free_skb(txp); } static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev) @@ -880,9 +873,6 @@ int brcmf_bus_start(struct device *dev) if (ret < 0) goto fail; - drvr->fw_signals = true; - (void)brcmf_fws_init(drvr); - drvr->config = brcmf_cfg80211_attach(drvr, bus_if->dev); if (drvr->config == NULL) { ret = -ENOMEM; @@ -899,8 +889,6 @@ int brcmf_bus_start(struct device *dev) brcmf_err("failed: %d\n", ret); if (drvr->config) brcmf_cfg80211_detach(drvr->config); - if (drvr->fws) - brcmf_fws_deinit(drvr); free_netdev(ifp->ndev); drvr->iflist[0] = NULL; if (p2p_ifp) { @@ -964,9 +952,6 @@ void brcmf_detach(struct device *dev) if (drvr->prot) brcmf_proto_detach(drvr); - if (drvr->fws) - brcmf_fws_deinit(drvr); - brcmf_debugfs_detach(drvr); bus_if->drvr = NULL; kfree(drvr); diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h index ef9179883748..48fa70302192 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h @@ -33,7 +33,7 @@ extern void brcmf_proto_stop(struct brcmf_pub *drvr); /* Add any protocol-specific data header. * Caller must reserve prot_hdrlen prepend space. */ -extern void brcmf_proto_hdrpush(struct brcmf_pub *, int ifidx, u8 offset, +extern void brcmf_proto_hdrpush(struct brcmf_pub *, int ifidx, struct sk_buff *txp); /* Sets dongle media info (drv_version, mac address). */ diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index 9a2edd3f0a5c..4469321c0eb3 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c @@ -1546,7 +1546,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) struct sk_buff_head pktlist; /* needed for bus interface */ u16 pad; /* Number of pad bytes to read */ uint rxleft = 0; /* Remaining number of frames allowed */ - int ret; /* Return code from calls */ + int sdret; /* Return code from calls */ uint rxcount = 0; /* Total frames read */ struct brcmf_sdio_read *rd = &bus->cur_read, rd_new; u8 head_read = 0; @@ -1577,15 +1577,15 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) /* read header first for unknow frame length */ sdio_claim_host(bus->sdiodev->func[1]); if (!rd->len) { - ret = brcmf_sdcard_recv_buf(bus->sdiodev, + sdret = brcmf_sdcard_recv_buf(bus->sdiodev, bus->sdiodev->sbwad, SDIO_FUNC_2, F2SYNC, bus->rxhdr, BRCMF_FIRSTREAD); bus->sdcnt.f2rxhdrs++; - if (ret < 0) { + if (sdret < 0) { brcmf_err("RXHEADER FAILED: %d\n", - ret); + sdret); bus->sdcnt.rx_hdrfail++; brcmf_sdbrcm_rxfail(bus, true, true); sdio_release_host(bus->sdiodev->func[1]); @@ -1637,14 +1637,14 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) skb_pull(pkt, head_read); pkt_align(pkt, rd->len_left, BRCMF_SDALIGN); - ret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad, + sdret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad, SDIO_FUNC_2, F2SYNC, pkt); bus->sdcnt.f2rxdata++; sdio_release_host(bus->sdiodev->func[1]); - if (ret < 0) { + if (sdret < 0) { brcmf_err("read %d bytes from channel %d failed: %d\n", - rd->len, rd->channel, ret); + rd->len, rd->channel, sdret); brcmu_pkt_buf_free_skb(pkt); sdio_claim_host(bus->sdiodev->func[1]); brcmf_sdbrcm_rxfail(bus, true, @@ -1775,7 +1775,7 @@ brcmf_sdbrcm_wait_event_wakeup(struct brcmf_sdio *bus) /* Writes a HW/SW header into the packet and sends it. */ /* Assumes: (a) header space already there, (b) caller holds lock */ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt, - uint chan) + uint chan, bool free_pkt) { int ret; u8 *frame; @@ -1805,7 +1805,10 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt, pkt_align(new, pkt->len, BRCMF_SDALIGN); memcpy(new->data, pkt->data, pkt->len); - brcmu_pkt_buf_free_skb(pkt); + if (free_pkt) + brcmu_pkt_buf_free_skb(pkt); + /* free the pkt if canned one is not used */ + free_pkt = true; pkt = new; frame = (u8 *) (pkt->data); /* precondition: (frame % BRCMF_SDALIGN) == 0) */ @@ -1898,6 +1901,10 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt, /* restore pkt buffer pointer before calling tx complete routine */ skb_pull(pkt, SDPCM_HDRLEN + pad); brcmf_txcomplete(bus->sdiodev->dev, pkt, ret != 0); + + if (free_pkt) + brcmu_pkt_buf_free_skb(pkt); + return ret; } @@ -1925,7 +1932,7 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes) spin_unlock_bh(&bus->txqlock); datalen = pkt->len - SDPCM_HDRLEN; - ret = brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_DATA_CHANNEL); + ret = brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, true); /* In poll mode, need to check for other events */ if (!bus->intr && cnt) { @@ -2336,6 +2343,7 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt) if (!brcmf_c_prec_enq(bus->sdiodev->dev, &bus->txq, pkt, prec)) { skb_pull(pkt, SDPCM_HDRLEN); brcmf_txcomplete(bus->sdiodev->dev, pkt, false); + brcmu_pkt_buf_free_skb(pkt); brcmf_err("out of bus->txq !!!\n"); ret = -ENOSR; } else { diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c deleted file mode 100644 index 071d55f9cd4d..000000000000 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ /dev/null @@ -1,382 +0,0 @@ -/* - * Copyright (c) 2010 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. - */ -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include "dhd.h" -#include "dhd_dbg.h" -#include "fwil.h" -#include "fweh.h" -#include "fwsignal.h" - -/** - * DOC: Firmware Signalling - * - * Firmware can send signals to host and vice versa, which are passed in the - * data packets using TLV based header. This signalling layer is on top of the - * BDC bus protocol layer. - */ - -/* - * single definition for firmware-driver flow control tlv's. - * - * each tlv is specified by BRCMF_FWS_TLV_DEF(name, ID, length). - * A length value 0 indicates variable length tlv. - */ -#define BRCMF_FWS_TLV_DEFLIST \ - BRCMF_FWS_TLV_DEF(MAC_OPEN, 1, 1) \ - BRCMF_FWS_TLV_DEF(MAC_CLOSE, 2, 1) \ - BRCMF_FWS_TLV_DEF(MAC_REQUEST_CREDIT, 3, 2) \ - BRCMF_FWS_TLV_DEF(TXSTATUS, 4, 4) \ - BRCMF_FWS_TLV_DEF(PKTTAG, 5, 4) \ - BRCMF_FWS_TLV_DEF(MACDESC_ADD, 6, 8) \ - BRCMF_FWS_TLV_DEF(MACDESC_DEL, 7, 8) \ - BRCMF_FWS_TLV_DEF(RSSI, 8, 1) \ - BRCMF_FWS_TLV_DEF(INTERFACE_OPEN, 9, 1) \ - BRCMF_FWS_TLV_DEF(INTERFACE_CLOSE, 10, 1) \ - BRCMF_FWS_TLV_DEF(FIFO_CREDITBACK, 11, 8) \ - BRCMF_FWS_TLV_DEF(PENDING_TRAFFIC_BMP, 12, 2) \ - BRCMF_FWS_TLV_DEF(MAC_REQUEST_PACKET, 13, 3) \ - BRCMF_FWS_TLV_DEF(HOST_REORDER_RXPKTS, 14, 10) \ - BRCMF_FWS_TLV_DEF(TRANS_ID, 18, 6) \ - BRCMF_FWS_TLV_DEF(COMP_TXSTATUS, 19, 1) \ - BRCMF_FWS_TLV_DEF(FILLER, 255, 0) - -/** - * enum brcmf_fws_tlv_type - definition of tlv identifiers. - */ -#define BRCMF_FWS_TLV_DEF(name, id, len) \ - BRCMF_FWS_TYPE_ ## name = id, -enum brcmf_fws_tlv_type { - BRCMF_FWS_TLV_DEFLIST - BRCMF_FWS_TYPE_INVALID -}; -#undef BRCMF_FWS_TLV_DEF - -/** - * enum brcmf_fws_tlv_len - length values for tlvs. - */ -#define BRCMF_FWS_TLV_DEF(name, id, len) \ - BRCMF_FWS_TYPE_ ## name ## _LEN = len, -enum brcmf_fws_tlv_len { - BRCMF_FWS_TLV_DEFLIST -}; -#undef BRCMF_FWS_TLV_DEF - -#ifdef DEBUG -/** - * brcmf_fws_tlv_names - array of tlv names. - */ -#define BRCMF_FWS_TLV_DEF(name, id, len) \ - { id, #name }, -static struct { - enum brcmf_fws_tlv_type id; - const char *name; -} brcmf_fws_tlv_names[] = { - BRCMF_FWS_TLV_DEFLIST -}; -#undef BRCMF_FWS_TLV_DEF - -static const char *brcmf_fws_get_tlv_name(enum brcmf_fws_tlv_type id) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(brcmf_fws_tlv_names); i++) - if (brcmf_fws_tlv_names[i].id == id) - return brcmf_fws_tlv_names[i].name; - - return "INVALID"; -} -#else -static const char *brcmf_fws_get_tlv_name(enum brcmf_fws_tlv_type id) -{ - return "NODEBUG"; -} -#endif /* DEBUG */ - -/** - * flags used to enable tlv signalling from firmware. - */ -#define BRCMF_FWS_FLAGS_RSSI_SIGNALS 0x0001 -#define BRCMF_FWS_FLAGS_XONXOFF_SIGNALS 0x0002 -#define BRCMF_FWS_FLAGS_CREDIT_STATUS_SIGNALS 0x0004 -#define BRCMF_FWS_FLAGS_HOST_PROPTXSTATUS_ACTIVE 0x0008 -#define BRCMF_FWS_FLAGS_PSQ_GENERATIONFSM_ENABLE 0x0010 -#define BRCMF_FWS_FLAGS_PSQ_ZERO_BUFFER_ENABLE 0x0020 -#define BRCMF_FWS_FLAGS_HOST_RXREORDER_ACTIVE 0x0040 - -#define BRCMF_FWS_HANGER_MAXITEMS 1024 -#define BRCMF_FWS_HANGER_ITEM_STATE_FREE 1 -#define BRCMF_FWS_HANGER_ITEM_STATE_INUSE 2 -#define BRCMF_FWS_HANGER_ITEM_STATE_INUSE_SUPPRESSED 3 - -#define BRCMF_FWS_STATE_OPEN 1 -#define BRCMF_FWS_STATE_CLOSE 2 - -#define BRCMF_FWS_FCMODE_NONE 0 -#define BRCMF_FWS_FCMODE_IMPLIED_CREDIT 1 -#define BRCMF_FWS_FCMODE_EXPLICIT_CREDIT 2 - -#define BRCMF_FWS_MAC_DESC_TABLE_SIZE 32 -#define BRCMF_FWS_MAX_IFNUM 16 -#define BRCMF_FWS_MAC_DESC_ID_INVALID 0xff - -#define BRCMF_FWS_HOSTIF_FLOWSTATE_OFF 0 -#define BRCMF_FWS_HOSTIF_FLOWSTATE_ON 1 - -/** - * FWFC packet identifier - * - * 32-bit packet identifier used in PKTTAG tlv from host to dongle. - * - * - Generated at the host (e.g. dhd) - * - Seen as a generic sequence number by wlc except the flags field - * - * Generation : b[31] => generation number for this packet [host->fw] - * OR, current generation number [fw->host] - * Flags : b[30:27] => command, status flags - * FIFO-AC : b[26:24] => AC-FIFO id - * h-slot : b[23:8] => hanger-slot - * freerun : b[7:0] => A free running counter - */ -#define BRCMF_FWS_PKTTAG_GENERATION_MASK 0x80000000 -#define BRCMF_FWS_PKTTAG_GENERATION_SHIFT 31 -#define BRCMF_FWS_PKTTAG_FLAGS_MASK 0x78000000 -#define BRCMF_FWS_PKTTAG_FLAGS_SHIFT 27 -#define BRCMF_FWS_PKTTAG_FIFO_MASK 0x07000000 -#define BRCMF_FWS_PKTTAG_FIFO_SHIFT 24 -#define BRCMF_FWS_PKTTAG_HSLOT_MASK 0x00ffff00 -#define BRCMF_FWS_PKTTAG_HSLOT_SHIFT 8 -#define BRCMF_FWS_PKTTAG_FREERUN_MASK 0x000000ff -#define BRCMF_FWS_PKTTAG_FREERUN_SHIFT 0 - -#define brcmf_fws_pkttag_set_field(var, field, value) \ - brcmu_maskset32((var), BRCMF_FWS_PKTTAG_ ## field ## _MASK, \ - BRCMF_FWS_PKTTAG_ ## field ## _SHIFT, (value)) -#define brcmf_fws_pkttag_get_field(var, field) \ - brcmu_maskget32((var), BRCMF_FWS_PKTTAG_ ## field ## _MASK, \ - BRCMF_FWS_PKTTAG_ ## field ## _SHIFT) - -struct brcmf_fws_info { - struct brcmf_pub *drvr; - struct brcmf_fws_stats stats; -}; - -static int brcmf_fws_rssi_indicate(struct brcmf_fws_info *fws, s8 rssi) -{ - brcmf_dbg(CTL, "rssi %d\n", rssi); - return 0; -} - -static int brcmf_fws_dbg_seqnum_check(struct brcmf_fws_info *fws, u8 *data) -{ - __le32 timestamp; - - memcpy(×tamp, &data[2], sizeof(timestamp)); - brcmf_dbg(INFO, "received: seq %d, timestamp %d\n", data[1], - le32_to_cpu(timestamp)); - return 0; -} - -/* using macro so sparse checking does not complain - * about locking imbalance. - */ -#define brcmf_fws_lock(drvr, flags) \ -do { \ - flags = 0; \ - spin_lock_irqsave(&((drvr)->fws_spinlock), (flags)); \ -} while (0) - -/* using macro so sparse checking does not complain - * about locking imbalance. - */ -#define brcmf_fws_unlock(drvr, flags) \ - spin_unlock_irqrestore(&((drvr)->fws_spinlock), (flags)) - -int brcmf_fws_init(struct brcmf_pub *drvr) -{ - u32 tlv; - int rc; - - /* enable rssi signals */ - tlv = drvr->fw_signals ? BRCMF_FWS_FLAGS_RSSI_SIGNALS : 0; - - spin_lock_init(&drvr->fws_spinlock); - - drvr->fws = kzalloc(sizeof(*(drvr->fws)), GFP_KERNEL); - if (!drvr->fws) { - rc = -ENOMEM; - goto fail; - } - - /* enable proptxtstatus signaling by default */ - rc = brcmf_fil_iovar_int_set(drvr->iflist[0], "tlv", tlv); - if (rc < 0) { - brcmf_err("failed to set bdcv2 tlv signaling\n"); - goto fail; - } - /* set linkage back */ - drvr->fws->drvr = drvr; - - /* create debugfs file for statistics */ - brcmf_debugfs_create_fws_stats(drvr, &drvr->fws->stats); - - /* TODO: remove upon feature delivery */ - brcmf_err("%s bdcv2 tlv signaling [%x]\n", - drvr->fw_signals ? "enabled" : "disabled", tlv); - return 0; - -fail: - /* disable flow control entirely */ - drvr->fw_signals = false; - brcmf_fws_deinit(drvr); - return rc; -} - -void brcmf_fws_deinit(struct brcmf_pub *drvr) -{ - /* free top structure */ - kfree(drvr->fws); - drvr->fws = NULL; -} - -int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len, - struct sk_buff *skb) -{ - struct brcmf_fws_info *fws = drvr->fws; - ulong flags; - u8 *signal_data; - s16 data_len; - u8 type; - u8 len; - u8 *data; - - brcmf_dbg(TRACE, "enter: ifidx %d, skblen %u, sig %d\n", - ifidx, skb->len, signal_len); - - WARN_ON(signal_len > skb->len); - - /* if flow control disabled, skip to packet data and leave */ - if (!signal_len || !drvr->fw_signals) { - skb_pull(skb, signal_len); - return 0; - } - - /* lock during tlv parsing */ - brcmf_fws_lock(drvr, flags); - - fws->stats.header_pulls++; - data_len = signal_len; - signal_data = skb->data; - - while (data_len > 0) { - /* extract tlv info */ - type = signal_data[0]; - - /* FILLER type is actually not a TLV, but - * a single byte that can be skipped. - */ - if (type == BRCMF_FWS_TYPE_FILLER) { - signal_data += 1; - data_len -= 1; - continue; - } - len = signal_data[1]; - data = signal_data + 2; - - /* abort parsing when length invalid */ - if (data_len < len + 2) - break; - - brcmf_dbg(INFO, "tlv type=%d (%s), len=%d\n", type, - brcmf_fws_get_tlv_name(type), len); - switch (type) { - case BRCMF_FWS_TYPE_MAC_OPEN: - case BRCMF_FWS_TYPE_MAC_CLOSE: - WARN_ON(len != BRCMF_FWS_TYPE_MAC_OPEN_LEN); - break; - case BRCMF_FWS_TYPE_MAC_REQUEST_CREDIT: - WARN_ON(len != BRCMF_FWS_TYPE_MAC_REQUEST_CREDIT_LEN); - break; - case BRCMF_FWS_TYPE_TXSTATUS: - WARN_ON(len != BRCMF_FWS_TYPE_TXSTATUS_LEN); - break; - case BRCMF_FWS_TYPE_PKTTAG: - WARN_ON(len != BRCMF_FWS_TYPE_PKTTAG_LEN); - break; - case BRCMF_FWS_TYPE_MACDESC_ADD: - case BRCMF_FWS_TYPE_MACDESC_DEL: - WARN_ON(len != BRCMF_FWS_TYPE_MACDESC_ADD_LEN); - break; - case BRCMF_FWS_TYPE_RSSI: - WARN_ON(len != BRCMF_FWS_TYPE_RSSI_LEN); - brcmf_fws_rssi_indicate(fws, *(s8 *)data); - break; - case BRCMF_FWS_TYPE_INTERFACE_OPEN: - case BRCMF_FWS_TYPE_INTERFACE_CLOSE: - WARN_ON(len != BRCMF_FWS_TYPE_INTERFACE_OPEN_LEN); - break; - case BRCMF_FWS_TYPE_FIFO_CREDITBACK: - WARN_ON(len != BRCMF_FWS_TYPE_FIFO_CREDITBACK_LEN); - break; - case BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP: - WARN_ON(len != BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN); - break; - case BRCMF_FWS_TYPE_MAC_REQUEST_PACKET: - WARN_ON(len != BRCMF_FWS_TYPE_MAC_REQUEST_PACKET_LEN); - break; - case BRCMF_FWS_TYPE_HOST_REORDER_RXPKTS: - WARN_ON(len != BRCMF_FWS_TYPE_HOST_REORDER_RXPKTS_LEN); - break; - case BRCMF_FWS_TYPE_TRANS_ID: - WARN_ON(len != BRCMF_FWS_TYPE_TRANS_ID_LEN); - brcmf_fws_dbg_seqnum_check(fws, data); - break; - case BRCMF_FWS_TYPE_COMP_TXSTATUS: - WARN_ON(len != BRCMF_FWS_TYPE_COMP_TXSTATUS_LEN); - break; - default: - fws->stats.tlv_invalid_type++; - break; - } - - signal_data += len + 2; - data_len -= len + 2; - } - - if (data_len != 0) - fws->stats.tlv_parse_failed++; - - /* signalling processing result does - * not affect the actual ethernet packet. - */ - skb_pull(skb, signal_len); - - /* this may be a signal-only packet - */ - if (skb->len == 0) - fws->stats.header_only_pkt++; - - brcmf_fws_unlock(drvr, flags); - return 0; -} diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h b/trunk/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h deleted file mode 100644 index e728eea72bb4..000000000000 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h +++ /dev/null @@ -1,25 +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 FWSIGNAL_H_ -#define FWSIGNAL_H_ - -int brcmf_fws_init(struct brcmf_pub *drvr); -void brcmf_fws_deinit(struct brcmf_pub *drvr); -int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len, - struct sk_buff *skb); -#endif /* FWSIGNAL_H_ */ diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.c deleted file mode 100644 index b505db48c60d..000000000000 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.c +++ /dev/null @@ -1,22 +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. - */ - -#include /* bug in tracepoint.h, it should include this */ - -#ifndef __CHECKER__ -#define CREATE_TRACE_POINTS -#include "tracepoint.h" -#endif diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h b/trunk/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h deleted file mode 100644 index 35efc7a67644..000000000000 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2013 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. - */ -#if !defined(BRCMF_TRACEPOINT_H_) || defined(TRACE_HEADER_MULTI_READ) -#define BRCMF_TRACEPOINT_H_ - -#include -#include - -#ifndef CONFIG_BRCM_TRACING - -#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 /* CONFIG_BRCM_TRACING */ - -#undef TRACE_SYSTEM -#define TRACE_SYSTEM brcmfmac - -#define MAX_MSG_LEN 100 - -TRACE_EVENT(brcmf_err, - TP_PROTO(const char *func, struct va_format *vaf), - TP_ARGS(func, vaf), - TP_STRUCT__entry( - __string(func, func) - __dynamic_array(char, msg, MAX_MSG_LEN) - ), - TP_fast_assign( - __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)) -); - -TRACE_EVENT(brcmf_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)) -); - -#ifdef CONFIG_BRCM_TRACING - -#undef TRACE_INCLUDE_PATH -#define TRACE_INCLUDE_PATH . -#undef TRACE_INCLUDE_FILE -#define TRACE_INCLUDE_FILE tracepoint - -#include - -#endif /* CONFIG_BRCM_TRACING */ - -#endif /* BRCMF_TRACEPOINT_H_ */ diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/usb.c index 01aed7ad6bec..42289e9ea886 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/usb.c @@ -112,6 +112,11 @@ struct brcmf_usbdev_info { static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo, struct brcmf_usbreq *req); +MODULE_AUTHOR("Broadcom Corporation"); +MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN fullmac usb driver."); +MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN fullmac usb cards"); +MODULE_LICENSE("Dual BSD/GPL"); + static struct brcmf_usbdev *brcmf_usb_get_buspub(struct device *dev) { struct brcmf_bus *bus_if = dev_get_drvdata(dev); @@ -417,6 +422,8 @@ static void brcmf_usb_tx_complete(struct urb *urb) brcmf_usb_del_fromq(devinfo, req); brcmf_txcomplete(devinfo->dev, req->skb, urb->status == 0); + + brcmu_pkt_buf_free_skb(req->skb); req->skb = NULL; brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req, &devinfo->tx_freecount); if (devinfo->tx_freecount > devinfo->tx_high_watermark && @@ -570,17 +577,15 @@ static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb) int ret; brcmf_dbg(USB, "Enter, skb=%p\n", skb); - if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP) { - ret = -EIO; - goto fail; - } + if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP) + return -EIO; req = brcmf_usb_deq(devinfo, &devinfo->tx_freeq, &devinfo->tx_freecount); if (!req) { + brcmu_pkt_buf_free_skb(skb); brcmf_err("no req to send\n"); - ret = -ENOMEM; - goto fail; + return -ENOMEM; } req->skb = skb; @@ -593,21 +598,18 @@ static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb) if (ret) { brcmf_err("brcmf_usb_tx usb_submit_urb FAILED\n"); brcmf_usb_del_fromq(devinfo, req); + brcmu_pkt_buf_free_skb(req->skb); req->skb = NULL; brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req, - &devinfo->tx_freecount); - goto fail; - } - - if (devinfo->tx_freecount < devinfo->tx_low_watermark && - !devinfo->tx_flowblock) { - brcmf_txflowblock(dev, true); - devinfo->tx_flowblock = true; + &devinfo->tx_freecount); + } else { + if (devinfo->tx_freecount < devinfo->tx_low_watermark && + !devinfo->tx_flowblock) { + brcmf_txflowblock(dev, true); + devinfo->tx_flowblock = true; + } } - return 0; -fail: - brcmf_txcomplete(dev, skb, false); return ret; } @@ -1483,7 +1485,6 @@ static struct usb_device_id brcmf_usb_devid_table[] = { { USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_BCMFW) }, { } }; - MODULE_DEVICE_TABLE(usb, brcmf_usb_devid_table); MODULE_FIRMWARE(BRCMF_USB_43143_FW_NAME); MODULE_FIRMWARE(BRCMF_USB_43236_FW_NAME); diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 804473fc5c5e..2af9c0f0798d 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -3052,16 +3052,16 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy, int i; int ret = 0; - brcmf_dbg(SCAN, "Enter n_match_sets:%d n_ssids:%d\n", + brcmf_dbg(SCAN, "Enter n_match_sets:%d n_ssids:%d\n", request->n_match_sets, request->n_ssids); if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { brcmf_err("Scanning already: status (%lu)\n", cfg->scan_status); return -EAGAIN; } - if (!request->n_ssids || !request->n_match_sets) { + if (!request || !request->n_ssids || !request->n_match_sets) { brcmf_err("Invalid sched scan req!! n_ssids:%d\n", - request->n_ssids); + request ? request->n_ssids : 0); return -EINVAL; } diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/Makefile b/trunk/drivers/net/wireless/brcm80211/brcmsmac/Makefile index cba19d839b77..d3d4151c3eda 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/Makefile +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/Makefile @@ -43,10 +43,6 @@ BRCMSMAC_OFILES := \ brcms_trace_events.o \ debug.o -ifdef CONFIG_BCMA_DRIVER_GPIO -BRCMSMAC_OFILES += led.o -endif - MODULEPFX := brcmsmac obj-$(CONFIG_BRCMSMAC) += $(MODULEPFX).o diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/led.c b/trunk/drivers/net/wireless/brcm80211/brcmsmac/led.c deleted file mode 100644 index 74b17cecb189..000000000000 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/led.c +++ /dev/null @@ -1,126 +0,0 @@ -#include -#include -#include - -#include "mac80211_if.h" -#include "pub.h" -#include "main.h" -#include "led.h" - - /* number of leds */ -#define BRCMS_LED_NO 4 - /* behavior mask */ -#define BRCMS_LED_BEH_MASK 0x7f - /* activelow (polarity) bit */ -#define BRCMS_LED_AL_MASK 0x80 - /* radio enabled */ -#define BRCMS_LED_RADIO 3 - -static void brcms_radio_led_ctrl(struct brcms_info *wl, bool state) -{ - if (wl->radio_led.gpio == -1) - return; - - if (wl->radio_led.active_low) - state = !state; - - if (state) - gpio_set_value(wl->radio_led.gpio, 1); - else - gpio_set_value(wl->radio_led.gpio, 0); -} - - -/* Callback from the LED subsystem. */ -static void brcms_led_brightness_set(struct led_classdev *led_dev, - enum led_brightness brightness) -{ - struct brcms_info *wl = container_of(led_dev, - struct brcms_info, led_dev); - brcms_radio_led_ctrl(wl, brightness); -} - -void brcms_led_unregister(struct brcms_info *wl) -{ - if (wl->led_dev.dev) - led_classdev_unregister(&wl->led_dev); - if (wl->radio_led.gpio != -1) - gpio_free(wl->radio_led.gpio); -} - -int brcms_led_register(struct brcms_info *wl) -{ - int i, err; - struct brcms_led *radio_led = &wl->radio_led; - /* get CC core */ - struct bcma_drv_cc *cc_drv = &wl->wlc->hw->d11core->bus->drv_cc; - struct gpio_chip *bcma_gpio = &cc_drv->gpio; - struct ssb_sprom *sprom = &wl->wlc->hw->d11core->bus->sprom; - u8 *leds[] = { &sprom->gpio0, - &sprom->gpio1, - &sprom->gpio2, - &sprom->gpio3 }; - unsigned gpio = -1; - bool active_low = false; - - /* none by default */ - radio_led->gpio = -1; - radio_led->active_low = false; - - if (!bcma_gpio || !gpio_is_valid(bcma_gpio->base)) - return -ENODEV; - - /* find radio enabled LED */ - for (i = 0; i < BRCMS_LED_NO; i++) { - u8 led = *leds[i]; - if ((led & BRCMS_LED_BEH_MASK) == BRCMS_LED_RADIO) { - gpio = bcma_gpio->base + i; - if (led & BRCMS_LED_AL_MASK) - active_low = true; - break; - } - } - - if (gpio == -1 || !gpio_is_valid(gpio)) - return -ENODEV; - - /* request and configure LED gpio */ - err = gpio_request_one(gpio, - active_low ? GPIOF_OUT_INIT_HIGH - : GPIOF_OUT_INIT_LOW, - "radio on"); - if (err) { - wiphy_err(wl->wiphy, "requesting led gpio %d failed (err: %d)\n", - gpio, err); - return err; - } - err = gpio_direction_output(gpio, 1); - if (err) { - wiphy_err(wl->wiphy, "cannot set led gpio %d to output (err: %d)\n", - gpio, err); - return err; - } - - snprintf(wl->radio_led.name, sizeof(wl->radio_led.name), - "brcmsmac-%s:radio", wiphy_name(wl->wiphy)); - - wl->led_dev.name = wl->radio_led.name; - wl->led_dev.default_trigger = - ieee80211_get_radio_led_name(wl->pub->ieee_hw); - wl->led_dev.brightness_set = brcms_led_brightness_set; - err = led_classdev_register(wiphy_dev(wl->wiphy), &wl->led_dev); - - if (err) { - wiphy_err(wl->wiphy, "cannot register led device: %s (err: %d)\n", - wl->radio_led.name, err); - return err; - } - - wiphy_info(wl->wiphy, "registered radio enabled led device: %s gpio: %d\n", - wl->radio_led.name, - gpio); - radio_led->gpio = gpio; - radio_led->active_low = active_low; - - return 0; -} diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/led.h b/trunk/drivers/net/wireless/brcm80211/brcmsmac/led.h deleted file mode 100644 index 17a0b1f5dbcf..000000000000 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/led.h +++ /dev/null @@ -1,36 +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 _BRCM_LED_H_ -#define _BRCM_LED_H_ -struct brcms_led { - char name[32]; - unsigned gpio; - bool active_low; -}; - -#ifdef CONFIG_BCMA_DRIVER_GPIO -void brcms_led_unregister(struct brcms_info *wl); -int brcms_led_register(struct brcms_info *wl); -#else -static inline void brcms_led_unregister(struct brcms_info *wl) {}; -static inline int brcms_led_register(struct brcms_info *wl) -{ - return -ENOTSUPP; -}; -#endif - -#endif /* _BRCM_LED_H_ */ diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/trunk/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index c70cf7b654cd..c6451c61407a 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c @@ -34,7 +34,6 @@ #include "mac80211_if.h" #include "main.h" #include "debug.h" -#include "led.h" #define N_TX_QUEUES 4 /* #tx queues on mac80211<->driver interface */ #define BRCMS_FLUSH_TIMEOUT 500 /* msec */ @@ -905,7 +904,6 @@ static void brcms_remove(struct bcma_device *pdev) struct brcms_info *wl = hw->priv; if (wl->wlc) { - brcms_led_unregister(wl); wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false); wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy); ieee80211_unregister_hw(hw); @@ -1153,8 +1151,6 @@ static int brcms_bcma_probe(struct bcma_device *pdev) pr_err("%s: brcms_attach failed!\n", __func__); return -ENODEV; } - brcms_led_register(wl); - return 0; } diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h b/trunk/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h index 4090032e81a2..947ccacf43e6 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h @@ -20,10 +20,8 @@ #include #include #include -#include #include "ucode_loader.h" -#include "led.h" /* * Starting index for 5G rates in the * legacy rate table. @@ -83,8 +81,6 @@ struct brcms_info { struct wiphy *wiphy; struct brcms_ucode ucode; bool mute_tx; - struct brcms_led radio_led; - struct led_classdev led_dev; }; /* misc callbacks */ diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/main.c b/trunk/drivers/net/wireless/brcm80211/brcmsmac/main.c index 0c8e998bfb1e..8ef02dca8f8c 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/main.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/main.c @@ -7810,14 +7810,9 @@ void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx) /* read the ucode version if we have not yet done so */ if (wlc->ucode_rev == 0) { - u16 rev; - u16 patch; - - rev = brcms_b_read_shm(wlc->hw, M_BOM_REV_MAJOR); - patch = brcms_b_read_shm(wlc->hw, M_BOM_REV_MINOR); - wlc->ucode_rev = (rev << NBITS(u16)) | patch; - snprintf(wlc->wiphy->fw_version, - sizeof(wlc->wiphy->fw_version), "%u.%u", rev, patch); + wlc->ucode_rev = + brcms_b_read_shm(wlc->hw, M_BOM_REV_MAJOR) << NBITS(u16); + wlc->ucode_rev |= brcms_b_read_shm(wlc->hw, M_BOM_REV_MINOR); } /* ..now really unleash hell (allow the MAC out of suspend) */ diff --git a/trunk/drivers/net/wireless/brcm80211/brcmutil/utils.c b/trunk/drivers/net/wireless/brcm80211/brcmutil/utils.c index bf5e50fc21ba..3e6405e06ac0 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmutil/utils.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmutil/utils.c @@ -116,31 +116,6 @@ struct sk_buff *brcmu_pktq_pdeq(struct pktq *pq, int prec) } EXPORT_SYMBOL(brcmu_pktq_pdeq); -/* - * precedence based dequeue with match function. Passing a NULL pointer - * for the match function parameter is considered to be a wildcard so - * any packet on the queue is returned. In that case it is no different - * from brcmu_pktq_pdeq() above. - */ -struct sk_buff *brcmu_pktq_pdeq_match(struct pktq *pq, int prec, - bool (*match_fn)(struct sk_buff *skb, - void *arg), void *arg) -{ - struct sk_buff_head *q; - struct sk_buff *p, *next; - - q = &pq->q[prec].skblist; - skb_queue_walk_safe(q, p, next) { - if (match_fn == NULL || match_fn(p, arg)) { - skb_unlink(p, q); - pq->len--; - return p; - } - } - return NULL; -} -EXPORT_SYMBOL(brcmu_pktq_pdeq_match); - struct sk_buff *brcmu_pktq_pdeq_tail(struct pktq *pq, int prec) { struct sk_buff_head *q; diff --git a/trunk/drivers/net/wireless/brcm80211/include/brcmu_utils.h b/trunk/drivers/net/wireless/brcm80211/include/brcmu_utils.h index 898cacb8d01d..477b92ad3d62 100644 --- a/trunk/drivers/net/wireless/brcm80211/include/brcmu_utils.h +++ b/trunk/drivers/net/wireless/brcm80211/include/brcmu_utils.h @@ -120,10 +120,6 @@ extern struct sk_buff *brcmu_pktq_penq_head(struct pktq *pq, int prec, struct sk_buff *p); extern struct sk_buff *brcmu_pktq_pdeq(struct pktq *pq, int prec); extern struct sk_buff *brcmu_pktq_pdeq_tail(struct pktq *pq, int prec); -extern struct sk_buff *brcmu_pktq_pdeq_match(struct pktq *pq, int prec, - bool (*match_fn)(struct sk_buff *p, - void *arg), - void *arg); /* packet primitives */ extern struct sk_buff *brcmu_pkt_buf_get_skb(uint len); @@ -177,29 +173,6 @@ extern void brcmu_pktq_flush(struct pktq *pq, bool dir, /* ip address */ struct ipv4_addr; -/* - * bitfield macros using masking and shift - * - * remark: the mask parameter should be a shifted mask. - */ -static inline void brcmu_maskset32(u32 *var, u32 mask, u8 shift, u32 value) -{ - value = (value << shift) & mask; - *var = (*var & ~mask) | value; -} -static inline u32 brcmu_maskget32(u32 var, u32 mask, u8 shift) -{ - return (var & mask) >> shift; -} -static inline void brcmu_maskset16(u16 *var, u16 mask, u8 shift, u16 value) -{ - value = (value << shift) & mask; - *var = (*var & ~mask) | value; -} -static inline u16 brcmu_maskget16(u16 var, u16 mask, u8 shift) -{ - return (var & mask) >> shift; -} /* externs */ /* format/print */ diff --git a/trunk/drivers/net/wireless/iwlegacy/3945.h b/trunk/drivers/net/wireless/iwlegacy/3945.h index 9a8703def0ba..1d45075e0d5b 100644 --- a/trunk/drivers/net/wireless/iwlegacy/3945.h +++ b/trunk/drivers/net/wireless/iwlegacy/3945.h @@ -150,6 +150,10 @@ struct il3945_frame { struct list_head list; }; +#define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4) +#define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ) +#define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4) + #define SUP_RATE_11A_MAX_NUM_CHANNELS 8 #define SUP_RATE_11B_MAX_NUM_CHANNELS 4 #define SUP_RATE_11G_MAX_NUM_CHANNELS 12 diff --git a/trunk/drivers/net/wireless/iwlegacy/4965-mac.c b/trunk/drivers/net/wireless/iwlegacy/4965-mac.c index c092fcbbe965..7941eb3a0166 100644 --- a/trunk/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/trunk/drivers/net/wireless/iwlegacy/4965-mac.c @@ -2258,7 +2258,7 @@ il4965_tx_agg_start(struct il_priv *il, struct ieee80211_vif *vif, spin_lock_irqsave(&il->sta_lock, flags); tid_data = &il->stations[sta_id].tid[tid]; - *ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number); + *ssn = SEQ_TO_SN(tid_data->seq_number); tid_data->agg.txq_id = txq_id; il_set_swq_id(&il->txq[txq_id], il4965_get_ac_from_tid(tid), txq_id); spin_unlock_irqrestore(&il->sta_lock, flags); @@ -2408,7 +2408,7 @@ il4965_txq_check_empty(struct il_priv *il, int sta_id, u8 tid, int txq_id) /* aggregated HW queue */ if (txq_id == tid_data->agg.txq_id && q->read_ptr == q->write_ptr) { - u16 ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number); + u16 ssn = SEQ_TO_SN(tid_data->seq_number); int tx_fifo = il4965_get_fifo_from_tid(tid); D_HT("HW queue empty: continue DELBA flow\n"); il4965_txq_agg_disable(il, txq_id, ssn, tx_fifo); @@ -2627,8 +2627,7 @@ il4965_get_ra_sta_id(struct il_priv *il, struct ieee80211_hdr *hdr) static inline u32 il4965_get_scd_ssn(struct il4965_tx_resp *tx_resp) { - return le32_to_cpup(&tx_resp->u.status + - tx_resp->frame_count) & IEEE80211_MAX_SN; + return le32_to_cpup(&tx_resp->u.status + tx_resp->frame_count) & MAX_SN; } static inline u32 @@ -2718,15 +2717,15 @@ il4965_tx_status_reply_tx(struct il_priv *il, struct il_ht_agg *agg, hdr = (struct ieee80211_hdr *) skb->data; sc = le16_to_cpu(hdr->seq_ctrl); - if (idx != (IEEE80211_SEQ_TO_SN(sc) & 0xff)) { + if (idx != (SEQ_TO_SN(sc) & 0xff)) { IL_ERR("BUG_ON idx doesn't match seq control" " idx=%d, seq_idx=%d, seq=%d\n", idx, - IEEE80211_SEQ_TO_SN(sc), hdr->seq_ctrl); + SEQ_TO_SN(sc), hdr->seq_ctrl); return -1; } D_TX_REPLY("AGG Frame i=%d idx %d seq=%d\n", i, idx, - IEEE80211_SEQ_TO_SN(sc)); + SEQ_TO_SN(sc)); sh = idx - start; if (sh > 64) { diff --git a/trunk/drivers/net/wireless/iwlegacy/common.h b/trunk/drivers/net/wireless/iwlegacy/common.h index 73bd3ef316c8..96f2025d936e 100644 --- a/trunk/drivers/net/wireless/iwlegacy/common.h +++ b/trunk/drivers/net/wireless/iwlegacy/common.h @@ -541,6 +541,10 @@ struct il_frame { struct list_head list; }; +#define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4) +#define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ) +#define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4) + enum { CMD_SYNC = 0, CMD_SIZE_NORMAL = 0, diff --git a/trunk/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/trunk/drivers/net/wireless/iwlwifi/dvm/mac80211.c index c7cd2dffa5cd..323e4a33fcac 100644 --- a/trunk/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/trunk/drivers/net/wireless/iwlwifi/dvm/mac80211.c @@ -1137,8 +1137,7 @@ 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, - int duration, - enum ieee80211_roc_type type) + int duration) { struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN]; diff --git a/trunk/drivers/net/wireless/iwlwifi/dvm/sta.c b/trunk/drivers/net/wireless/iwlwifi/dvm/sta.c index 94ef33838bc6..b775769f8322 100644 --- a/trunk/drivers/net/wireless/iwlwifi/dvm/sta.c +++ b/trunk/drivers/net/wireless/iwlwifi/dvm/sta.c @@ -151,7 +151,7 @@ int iwl_send_add_sta(struct iwl_priv *priv, sta_id, sta->sta.addr, flags & CMD_ASYNC ? "a" : ""); if (!(flags & CMD_ASYNC)) { - cmd.flags |= CMD_WANT_SKB | CMD_WANT_HCMD; + cmd.flags |= CMD_WANT_SKB; might_sleep(); } diff --git a/trunk/drivers/net/wireless/iwlwifi/dvm/tx.c b/trunk/drivers/net/wireless/iwlwifi/dvm/tx.c index d499a0366fa6..6aec2df3bb27 100644 --- a/trunk/drivers/net/wireless/iwlwifi/dvm/tx.c +++ b/trunk/drivers/net/wireless/iwlwifi/dvm/tx.c @@ -418,8 +418,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, " Tx flags = 0x%08x, agg.state = %d", info->flags, tid_data->agg.state); IWL_ERR(priv, "sta_id = %d, tid = %d seq_num = %d", - sta_id, tid, - IEEE80211_SEQ_TO_SN(tid_data->seq_number)); + sta_id, tid, SEQ_TO_SN(tid_data->seq_number)); goto drop_unlock_sta; } @@ -570,7 +569,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, return 0; } - tid_data->agg.ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number); + tid_data->agg.ssn = SEQ_TO_SN(tid_data->seq_number); /* There are still packets for this RA / TID in the HW */ if (!test_bit(txq_id, priv->agg_q_alloc)) { @@ -652,7 +651,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, spin_lock_bh(&priv->sta_lock); tid_data = &priv->tid_data[sta_id][tid]; - tid_data->agg.ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number); + tid_data->agg.ssn = SEQ_TO_SN(tid_data->seq_number); tid_data->agg.txq_id = txq_id; *ssn = tid_data->agg.ssn; @@ -912,7 +911,7 @@ static void iwlagn_count_agg_tx_err_status(struct iwl_priv *priv, u16 status) static inline u32 iwlagn_get_scd_ssn(struct iwlagn_tx_resp *tx_resp) { return le32_to_cpup((__le32 *)&tx_resp->status + - tx_resp->frame_count) & IEEE80211_MAX_SN; + tx_resp->frame_count) & MAX_SN; } static void iwl_rx_reply_tx_agg(struct iwl_priv *priv, @@ -1149,7 +1148,7 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, if (tx_resp->frame_count == 1) { u16 next_reclaimed = le16_to_cpu(tx_resp->seq_ctl); - next_reclaimed = IEEE80211_SEQ_TO_SN(next_reclaimed + 0x10); + next_reclaimed = SEQ_TO_SN(next_reclaimed + 0x10); if (is_agg) { /* If this is an aggregation queue, we can rely on the diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/trunk/drivers/net/wireless/iwlwifi/iwl-devtrace.h index 9a0f45ec9e01..81aa91fab5aa 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-devtrace.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-devtrace.h @@ -349,25 +349,23 @@ TRACE_EVENT(iwlwifi_dev_rx_data, TRACE_EVENT(iwlwifi_dev_hcmd, TP_PROTO(const struct device *dev, struct iwl_host_cmd *cmd, u16 total_size, - const void *hdr, size_t hdr_len), - TP_ARGS(dev, cmd, total_size, hdr, hdr_len), + struct iwl_cmd_header *hdr), + TP_ARGS(dev, cmd, total_size, hdr), TP_STRUCT__entry( DEV_ENTRY __dynamic_array(u8, hcmd, total_size) __field(u32, flags) ), TP_fast_assign( - int i, offset = hdr_len; + int i, offset = sizeof(*hdr); DEV_ASSIGN; __entry->flags = cmd->flags; - memcpy(__get_dynamic_array(hcmd), hdr, hdr_len); + memcpy(__get_dynamic_array(hcmd), hdr, sizeof(*hdr)); - for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { + for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) { if (!cmd->len[i]) continue; - if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY)) - continue; memcpy((u8 *)__get_dynamic_array(hcmd) + offset, cmd->data[i], cmd->len[i]); offset += cmd->len[i]; diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-drv.c b/trunk/drivers/net/wireless/iwlwifi/iwl-drv.c index 6f228bb2b844..fbfd2d137117 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-drv.c @@ -1102,7 +1102,6 @@ void iwl_drv_stop(struct iwl_drv *drv) /* shared module parameters */ struct iwl_mod_params iwlwifi_mod_params = { - .amsdu_size_8K = 1, .restart_fw = 1, .plcp_check = true, .bt_coex_active = true, @@ -1207,7 +1206,7 @@ MODULE_PARM_DESC(11n_disable, "disable 11n functionality, bitmap: 1: full, 2: agg TX, 4: agg RX"); module_param_named(amsdu_size_8K, iwlwifi_mod_params.amsdu_size_8K, int, S_IRUGO); -MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size"); +MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size (default 0)"); module_param_named(fw_restart, iwlwifi_mod_params.restart_fw, int, S_IRUGO); MODULE_PARM_DESC(fw_restart, "restart firmware in case of error"); diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-modparams.h b/trunk/drivers/net/wireless/iwlwifi/iwl-modparams.h index e5e3a79eae2f..2c2a729092f5 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-modparams.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-modparams.h @@ -91,7 +91,7 @@ enum iwl_power_level { * @sw_crypto: using hardware encryption, default = 0 * @disable_11n: disable 11n capabilities, default = 0, * use IWL_DISABLE_HT_* constants - * @amsdu_size_8K: enable 8K amsdu size, default = 1 + * @amsdu_size_8K: enable 8K amsdu size, default = 0 * @restart_fw: restart firmware, default = 1 * @plcp_check: enable plcp health check, default = true * @wd_disable: enable stuck queue check, default = 0 diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-phy-db.c b/trunk/drivers/net/wireless/iwlwifi/iwl-phy-db.c index 14fc8d39fc28..3392011a8768 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-phy-db.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-phy-db.c @@ -136,12 +136,6 @@ struct iwl_calib_res_notif_phy_db { u8 data[]; } __packed; -#define IWL_PHY_DB_STATIC_PIC cpu_to_le32(0x21436587) -static inline void iwl_phy_db_test_pic(__le32 pic) -{ - WARN_ON(IWL_PHY_DB_STATIC_PIC != pic); -} - struct iwl_phy_db *iwl_phy_db_init(struct iwl_trans *trans) { struct iwl_phy_db *phy_db = kzalloc(sizeof(struct iwl_phy_db), @@ -260,11 +254,6 @@ int iwl_phy_db_set_section(struct iwl_phy_db *phy_db, struct iwl_rx_packet *pkt, (size - CHANNEL_NUM_SIZE) / phy_db->channel_num; } - /* Test PIC */ - if (type != IWL_PHY_DB_CFG) - iwl_phy_db_test_pic(*(((__le32 *)phy_db_notif->data) + - (size / sizeof(__le32)) - 1)); - IWL_DEBUG_INFO(phy_db->trans, "%s(%d): [PHYDB]SET: Type %d , Size: %d\n", __func__, __LINE__, type, size); @@ -372,11 +361,6 @@ int iwl_phy_db_get_section_data(struct iwl_phy_db *phy_db, *size = entry->size; } - /* Test PIC */ - if (type != IWL_PHY_DB_CFG) - iwl_phy_db_test_pic(*(((__le32 *)*data) + - (*size / sizeof(__le32)) - 1)); - IWL_DEBUG_INFO(phy_db->trans, "%s(%d): [PHYDB] GET: Type %d , Size: %d\n", __func__, __LINE__, type, *size); diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-trans.h b/trunk/drivers/net/wireless/iwlwifi/iwl-trans.h index 00bdc5b00af3..0cac2b7af78b 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -114,6 +114,9 @@ * completely agnostic to these differences. * The transport does provide helper functionnality (i.e. SYNC / ASYNC mode), */ +#define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4) +#define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ) +#define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4) #define SEQ_TO_QUEUE(s) (((s) >> 8) & 0x1f) #define QUEUE_TO_SEQ(q) (((q) & 0x1f) << 8) #define SEQ_TO_INDEX(s) ((s) & 0xff) @@ -183,19 +186,13 @@ struct iwl_rx_packet { * @CMD_ASYNC: Return right away and don't want for the response * @CMD_WANT_SKB: valid only with CMD_SYNC. The caller needs the buffer of the * response. The caller needs to call iwl_free_resp when done. - * @CMD_WANT_HCMD: The caller needs to get the HCMD that was sent in the - * response handler. Chunks flagged by %IWL_HCMD_DFL_NOCOPY won't be - * copied. The pointer passed to the response handler is in the transport - * ownership and don't need to be freed by the op_mode. This also means - * that the pointer is invalidated after the op_mode's handler returns. * @CMD_ON_DEMAND: This command is sent by the test mode pipe. */ enum CMD_MODE { CMD_SYNC = 0, CMD_ASYNC = BIT(0), CMD_WANT_SKB = BIT(1), - CMD_WANT_HCMD = BIT(2), - CMD_ON_DEMAND = BIT(3), + CMD_ON_DEMAND = BIT(2), }; #define DEF_CMD_PAYLOAD_SIZE 320 @@ -214,7 +211,11 @@ struct iwl_device_cmd { #define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_device_cmd)) -#define IWL_MAX_CMD_TFDS 2 +/* + * number of transfer buffers (fragments) per transmit frame descriptor; + * this is just the driver's idea, the hardware supports 20 + */ +#define IWL_MAX_CMD_TBS_PER_TFD 2 /** * struct iwl_hcmd_dataflag - flag for each one of the chunks of the command @@ -251,15 +252,15 @@ enum iwl_hcmd_dataflag { * @id: id of the host command */ struct iwl_host_cmd { - const void *data[IWL_MAX_CMD_TFDS]; + const void *data[IWL_MAX_CMD_TBS_PER_TFD]; struct iwl_rx_packet *resp_pkt; unsigned long _rx_page_addr; u32 _rx_page_order; int handler_status; u32 flags; - u16 len[IWL_MAX_CMD_TFDS]; - u8 dataflags[IWL_MAX_CMD_TFDS]; + u16 len[IWL_MAX_CMD_TBS_PER_TFD]; + u8 dataflags[IWL_MAX_CMD_TBS_PER_TFD]; u8 id; }; diff --git a/trunk/drivers/net/wireless/iwlwifi/mvm/d3.c b/trunk/drivers/net/wireless/iwlwifi/mvm/d3.c index c64d864799cd..994c8c263dc0 100644 --- a/trunk/drivers/net/wireless/iwlwifi/mvm/d3.c +++ b/trunk/drivers/net/wireless/iwlwifi/mvm/d3.c @@ -61,6 +61,7 @@ * *****************************************************************************/ +#include #include #include #include "iwl-modparams.h" @@ -192,6 +193,11 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw, sizeof(wkc), &wkc); data->error = ret != 0; + mvm->ptk_ivlen = key->iv_len; + mvm->ptk_icvlen = key->icv_len; + mvm->gtk_ivlen = key->iv_len; + mvm->gtk_icvlen = key->icv_len; + /* don't upload key again */ goto out_unlock; } @@ -304,9 +310,13 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw, */ if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { key->hw_key_idx = 0; + mvm->ptk_ivlen = key->iv_len; + mvm->ptk_icvlen = key->icv_len; } else { data->gtk_key_idx++; key->hw_key_idx = data->gtk_key_idx; + mvm->gtk_ivlen = key->iv_len; + mvm->gtk_icvlen = key->icv_len; } ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, true); @@ -649,6 +659,11 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) /* We reprogram keys and shouldn't allocate new key indices */ memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table)); + mvm->ptk_ivlen = 0; + mvm->ptk_icvlen = 0; + mvm->ptk_ivlen = 0; + mvm->ptk_icvlen = 0; + /* * The D3 firmware still hardcodes the AP station ID for the * BSS we're associated with as 0. As a result, we have to move @@ -783,7 +798,6 @@ static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, struct iwl_wowlan_status *status; u32 reasons; int ret, len; - bool pkt8023 = false; struct sk_buff *pkt = NULL; iwl_trans_read_mem_bytes(mvm->trans, base, @@ -824,7 +838,8 @@ static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, status = (void *)cmd.resp_pkt->data; if (len - sizeof(struct iwl_cmd_header) != - sizeof(*status) + le32_to_cpu(status->wake_packet_bufsize)) { + sizeof(*status) + + ALIGN(le32_to_cpu(status->wake_packet_bufsize), 4)) { IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); goto out; } @@ -836,61 +851,96 @@ static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, goto report; } - if (reasons & IWL_WOWLAN_WAKEUP_BY_MAGIC_PACKET) { + if (reasons & IWL_WOWLAN_WAKEUP_BY_MAGIC_PACKET) wakeup.magic_pkt = true; - pkt8023 = true; - } - if (reasons & IWL_WOWLAN_WAKEUP_BY_PATTERN) { + if (reasons & IWL_WOWLAN_WAKEUP_BY_PATTERN) wakeup.pattern_idx = le16_to_cpu(status->pattern_number); - pkt8023 = true; - } if (reasons & (IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_MISSED_BEACON | IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_DEAUTH)) wakeup.disconnect = true; - if (reasons & IWL_WOWLAN_WAKEUP_BY_GTK_REKEY_FAILURE) { + if (reasons & IWL_WOWLAN_WAKEUP_BY_GTK_REKEY_FAILURE) wakeup.gtk_rekey_failure = true; - pkt8023 = true; - } - if (reasons & IWL_WOWLAN_WAKEUP_BY_RFKILL_DEASSERTED) { + if (reasons & IWL_WOWLAN_WAKEUP_BY_RFKILL_DEASSERTED) wakeup.rfkill_release = true; - pkt8023 = true; - } - if (reasons & IWL_WOWLAN_WAKEUP_BY_EAPOL_REQUEST) { + if (reasons & IWL_WOWLAN_WAKEUP_BY_EAPOL_REQUEST) wakeup.eap_identity_req = true; - pkt8023 = true; - } - if (reasons & IWL_WOWLAN_WAKEUP_BY_FOUR_WAY_HANDSHAKE) { + if (reasons & IWL_WOWLAN_WAKEUP_BY_FOUR_WAY_HANDSHAKE) wakeup.four_way_handshake = true; - pkt8023 = true; - } if (status->wake_packet_bufsize) { - u32 pktsize = le32_to_cpu(status->wake_packet_bufsize); - u32 pktlen = le32_to_cpu(status->wake_packet_length); + int pktsize = le32_to_cpu(status->wake_packet_bufsize); + int pktlen = le32_to_cpu(status->wake_packet_length); + const u8 *pktdata = status->wake_packet; + struct ieee80211_hdr *hdr = (void *)pktdata; + int truncated = pktlen - pktsize; + + /* this would be a firmware bug */ + if (WARN_ON_ONCE(truncated < 0)) + truncated = 0; + + if (ieee80211_is_data(hdr->frame_control)) { + int hdrlen = ieee80211_hdrlen(hdr->frame_control); + int ivlen = 0, icvlen = 4; /* also FCS */ - if (pkt8023) { pkt = alloc_skb(pktsize, GFP_KERNEL); if (!pkt) goto report; - memcpy(skb_put(pkt, pktsize), status->wake_packet, - pktsize); + + memcpy(skb_put(pkt, hdrlen), pktdata, hdrlen); + pktdata += hdrlen; + pktsize -= hdrlen; + + if (ieee80211_has_protected(hdr->frame_control)) { + if (is_multicast_ether_addr(hdr->addr1)) { + ivlen = mvm->gtk_ivlen; + icvlen += mvm->gtk_icvlen; + } else { + ivlen = mvm->ptk_ivlen; + icvlen += mvm->ptk_icvlen; + } + } + + /* if truncated, FCS/ICV is (partially) gone */ + if (truncated >= icvlen) { + icvlen = 0; + truncated -= icvlen; + } else { + icvlen -= truncated; + truncated = 0; + } + + pktsize -= ivlen + icvlen; + pktdata += ivlen; + + memcpy(skb_put(pkt, pktsize), pktdata, pktsize); + if (ieee80211_data_to_8023(pkt, vif->addr, vif->type)) goto report; wakeup.packet = pkt->data; wakeup.packet_present_len = pkt->len; - wakeup.packet_len = pkt->len - (pktlen - pktsize); + wakeup.packet_len = pkt->len - truncated; wakeup.packet_80211 = false; } else { + int fcslen = 4; + + if (truncated >= 4) { + truncated -= 4; + fcslen = 0; + } else { + fcslen -= truncated; + truncated = 0; + } + pktsize -= fcslen; wakeup.packet = status->wake_packet; wakeup.packet_present_len = pktsize; - wakeup.packet_len = pktlen; + wakeup.packet_len = pktlen - truncated; wakeup.packet_80211 = true; } } diff --git a/trunk/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/trunk/drivers/net/wireless/iwlwifi/mvm/fw-api.h index 23eebda848b0..2adb61f103f4 100644 --- a/trunk/drivers/net/wireless/iwlwifi/mvm/fw-api.h +++ b/trunk/drivers/net/wireless/iwlwifi/mvm/fw-api.h @@ -762,18 +762,20 @@ struct iwl_phy_context_cmd { #define IWL_RX_INFO_PHY_CNT 8 #define IWL_RX_INFO_AGC_IDX 1 #define IWL_RX_INFO_RSSI_AB_IDX 2 -#define IWL_RX_INFO_RSSI_C_IDX 3 -#define IWL_OFDM_AGC_DB_MSK 0xfe00 -#define IWL_OFDM_AGC_DB_POS 9 +#define IWL_OFDM_AGC_A_MSK 0x0000007f +#define IWL_OFDM_AGC_A_POS 0 +#define IWL_OFDM_AGC_B_MSK 0x00003f80 +#define IWL_OFDM_AGC_B_POS 7 +#define IWL_OFDM_AGC_CODE_MSK 0x3fe00000 +#define IWL_OFDM_AGC_CODE_POS 20 #define IWL_OFDM_RSSI_INBAND_A_MSK 0x00ff -#define IWL_OFDM_RSSI_ALLBAND_A_MSK 0xff00 #define IWL_OFDM_RSSI_A_POS 0 +#define IWL_OFDM_RSSI_ALLBAND_A_MSK 0xff00 +#define IWL_OFDM_RSSI_ALLBAND_A_POS 8 #define IWL_OFDM_RSSI_INBAND_B_MSK 0xff0000 -#define IWL_OFDM_RSSI_ALLBAND_B_MSK 0xff000000 #define IWL_OFDM_RSSI_B_POS 16 -#define IWL_OFDM_RSSI_INBAND_C_MSK 0x00ff -#define IWL_OFDM_RSSI_ALLBAND_C_MSK 0xff00 -#define IWL_OFDM_RSSI_C_POS 0 +#define IWL_OFDM_RSSI_ALLBAND_B_MSK 0xff000000 +#define IWL_OFDM_RSSI_ALLBAND_B_POS 24 /** * struct iwl_rx_phy_info - phy info diff --git a/trunk/drivers/net/wireless/iwlwifi/mvm/fw.c b/trunk/drivers/net/wireless/iwlwifi/mvm/fw.c index d3d959db03a9..500f818dba04 100644 --- a/trunk/drivers/net/wireless/iwlwifi/mvm/fw.c +++ b/trunk/drivers/net/wireless/iwlwifi/mvm/fw.c @@ -79,17 +79,8 @@ #define UCODE_VALID_OK cpu_to_le32(0x1) /* Default calibration values for WkP - set to INIT image w/o running */ -static const u8 wkp_calib_values_bb_filter[] = { 0xbf, 0x00, 0x5f, 0x00, 0x2f, - 0x00, 0x18, 0x00 }; -static const u8 wkp_calib_values_rx_dc[] = { 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f }; -static const u8 wkp_calib_values_tx_lo[] = { 0x00, 0x00, 0x00, 0x00 }; -static const u8 wkp_calib_values_tx_iq[] = { 0xff, 0x00, 0xff, 0x00, 0x00, - 0x00 }; -static const u8 wkp_calib_values_rx_iq[] = { 0xff, 0x00, 0x00, 0x00 }; static const u8 wkp_calib_values_rx_iq_skew[] = { 0x00, 0x00, 0x01, 0x00 }; static const u8 wkp_calib_values_tx_iq_skew[] = { 0x01, 0x00, 0x00, 0x00 }; -static const u8 wkp_calib_values_xtal[] = { 0xd2, 0xd2 }; struct iwl_calib_default_data { u16 size; @@ -99,12 +90,7 @@ struct iwl_calib_default_data { #define CALIB_SIZE_N_DATA(_buf) {.size = sizeof(_buf), .data = &_buf} static const struct iwl_calib_default_data wkp_calib_default_data[12] = { - [5] = CALIB_SIZE_N_DATA(wkp_calib_values_rx_dc), - [6] = CALIB_SIZE_N_DATA(wkp_calib_values_bb_filter), - [7] = CALIB_SIZE_N_DATA(wkp_calib_values_tx_lo), - [8] = CALIB_SIZE_N_DATA(wkp_calib_values_tx_iq), [9] = CALIB_SIZE_N_DATA(wkp_calib_values_tx_iq_skew), - [10] = CALIB_SIZE_N_DATA(wkp_calib_values_rx_iq), [11] = CALIB_SIZE_N_DATA(wkp_calib_values_rx_iq_skew), }; @@ -241,20 +227,6 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, return 0; } -#define IWL_HW_REV_ID_RAINBOW 0x2 -#define IWL_PROJ_TYPE_LHP 0x5 - -static u32 iwl_mvm_build_phy_cfg(struct iwl_mvm *mvm) -{ - struct iwl_nvm_data *data = mvm->nvm_data; - /* Temp calls to static definitions, will be changed to CSR calls */ - u8 hw_rev_id = IWL_HW_REV_ID_RAINBOW; - u8 project_type = IWL_PROJ_TYPE_LHP; - - return data->radio_cfg_dash | (data->radio_cfg_step << 2) | - (hw_rev_id << 4) | ((project_type & 0x7f) << 6) | - (data->valid_tx_ant << 16) | (data->valid_rx_ant << 20); -} static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm) { @@ -262,7 +234,7 @@ static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm) enum iwl_ucode_type ucode_type = mvm->cur_ucode; /* Set parameters */ - phy_cfg_cmd.phy_cfg = cpu_to_le32(iwl_mvm_build_phy_cfg(mvm)); + phy_cfg_cmd.phy_cfg = cpu_to_le32(mvm->fw->phy_config); phy_cfg_cmd.calib_control.event_trigger = mvm->fw->default_calib[ucode_type].event_trigger; phy_cfg_cmd.calib_control.flow_trigger = @@ -275,103 +247,6 @@ static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm) sizeof(phy_cfg_cmd), &phy_cfg_cmd); } -/* Starting with the new PHY DB implementation - New calibs are enabled */ -/* Value - 0x405e7 */ -#define IWL_CALIB_DEFAULT_FLOW_INIT (IWL_CALIB_CFG_XTAL_IDX |\ - IWL_CALIB_CFG_TEMPERATURE_IDX |\ - IWL_CALIB_CFG_VOLTAGE_READ_IDX |\ - IWL_CALIB_CFG_DC_IDX |\ - IWL_CALIB_CFG_BB_FILTER_IDX |\ - IWL_CALIB_CFG_LO_LEAKAGE_IDX |\ - IWL_CALIB_CFG_TX_IQ_IDX |\ - IWL_CALIB_CFG_RX_IQ_IDX |\ - IWL_CALIB_CFG_AGC_IDX) - -#define IWL_CALIB_DEFAULT_EVENT_INIT 0x0 - -/* Value 0x41567 */ -#define IWL_CALIB_DEFAULT_FLOW_RUN (IWL_CALIB_CFG_XTAL_IDX |\ - IWL_CALIB_CFG_TEMPERATURE_IDX |\ - IWL_CALIB_CFG_VOLTAGE_READ_IDX |\ - IWL_CALIB_CFG_BB_FILTER_IDX |\ - IWL_CALIB_CFG_DC_IDX |\ - IWL_CALIB_CFG_TX_IQ_IDX |\ - IWL_CALIB_CFG_RX_IQ_IDX |\ - IWL_CALIB_CFG_SENSITIVITY_IDX |\ - IWL_CALIB_CFG_AGC_IDX) - -#define IWL_CALIB_DEFAULT_EVENT_RUN (IWL_CALIB_CFG_XTAL_IDX |\ - IWL_CALIB_CFG_TEMPERATURE_IDX |\ - IWL_CALIB_CFG_VOLTAGE_READ_IDX |\ - IWL_CALIB_CFG_TX_PWR_IDX |\ - IWL_CALIB_CFG_DC_IDX |\ - IWL_CALIB_CFG_TX_IQ_IDX |\ - IWL_CALIB_CFG_SENSITIVITY_IDX) - -/* - * Sets the calibrations trigger values that will be sent to the FW for runtime - * and init calibrations. - * The ones given in the FW TLV are not correct. - */ -static void iwl_set_default_calib_trigger(struct iwl_mvm *mvm) -{ - struct iwl_tlv_calib_ctrl default_calib; - - /* - * WkP FW TLV calib bits are wrong, overwrite them. - * This defines the dynamic calibrations which are implemented in the - * uCode both for init(flow) calculation and event driven calibs. - */ - - /* Init Image */ - default_calib.event_trigger = cpu_to_le32(IWL_CALIB_DEFAULT_EVENT_INIT); - default_calib.flow_trigger = cpu_to_le32(IWL_CALIB_DEFAULT_FLOW_INIT); - - if (default_calib.event_trigger != - mvm->fw->default_calib[IWL_UCODE_INIT].event_trigger) - IWL_ERR(mvm, - "Updating the event calib for INIT image: 0x%x -> 0x%x\n", - mvm->fw->default_calib[IWL_UCODE_INIT].event_trigger, - default_calib.event_trigger); - if (default_calib.flow_trigger != - mvm->fw->default_calib[IWL_UCODE_INIT].flow_trigger) - IWL_ERR(mvm, - "Updating the flow calib for INIT image: 0x%x -> 0x%x\n", - mvm->fw->default_calib[IWL_UCODE_INIT].flow_trigger, - default_calib.flow_trigger); - - memcpy((void *)&mvm->fw->default_calib[IWL_UCODE_INIT], - &default_calib, sizeof(struct iwl_tlv_calib_ctrl)); - IWL_ERR(mvm, - "Setting uCode init calibrations event 0x%x, trigger 0x%x\n", - default_calib.event_trigger, - default_calib.flow_trigger); - - /* Run time image */ - default_calib.event_trigger = cpu_to_le32(IWL_CALIB_DEFAULT_EVENT_RUN); - default_calib.flow_trigger = cpu_to_le32(IWL_CALIB_DEFAULT_FLOW_RUN); - - if (default_calib.event_trigger != - mvm->fw->default_calib[IWL_UCODE_REGULAR].event_trigger) - IWL_ERR(mvm, - "Updating the event calib for RT image: 0x%x -> 0x%x\n", - mvm->fw->default_calib[IWL_UCODE_REGULAR].event_trigger, - default_calib.event_trigger); - if (default_calib.flow_trigger != - mvm->fw->default_calib[IWL_UCODE_REGULAR].flow_trigger) - IWL_ERR(mvm, - "Updating the flow calib for RT image: 0x%x -> 0x%x\n", - mvm->fw->default_calib[IWL_UCODE_REGULAR].flow_trigger, - default_calib.flow_trigger); - - memcpy((void *)&mvm->fw->default_calib[IWL_UCODE_REGULAR], - &default_calib, sizeof(struct iwl_tlv_calib_ctrl)); - IWL_ERR(mvm, - "Setting uCode runtime calibs event 0x%x, trigger 0x%x\n", - default_calib.event_trigger, - default_calib.flow_trigger); -} - static int iwl_set_default_calibrations(struct iwl_mvm *mvm) { u8 cmd_raw[16]; /* holds the variable size commands */ @@ -446,8 +321,10 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) ret = iwl_nvm_check_version(mvm->nvm_data, mvm->trans); WARN_ON(ret); - /* Override the calibrations from TLV and the const of fw */ - iwl_set_default_calib_trigger(mvm); + /* Send TX valid antennas before triggering calibrations */ + ret = iwl_send_tx_ant_cfg(mvm, mvm->nvm_data->valid_tx_ant); + if (ret) + goto error; /* WkP doesn't have all calibrations, need to set default values */ if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) { diff --git a/trunk/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/trunk/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 23460f4a4c75..7e169b085afe 100644 --- a/trunk/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/trunk/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -557,11 +557,9 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, return ret; } -static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) +static void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm, + struct ieee80211_vif *vif) { - struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); u32 tfd_msk = 0, ac; for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) @@ -594,12 +592,21 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw, */ flush_work(&mvm->sta_drained_wk); } +} + +static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + + iwl_mvm_prepare_mac_removal(mvm, vif); mutex_lock(&mvm->mutex); /* * For AP/GO interface, the tear down of the resources allocated to the - * interface should be handled as part of the bss_info_changed flow. + * interface is be handled as part of the stop_ap flow. */ if (vif->type == NL80211_IFTYPE_AP) { iwl_mvm_dealloc_int_sta(mvm, &mvmvif->bcast_sta); @@ -763,6 +770,8 @@ static void iwl_mvm_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif) struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + iwl_mvm_prepare_mac_removal(mvm, vif); + mutex_lock(&mvm->mutex); mvmvif->ap_active = false; @@ -1081,8 +1090,7 @@ static void iwl_mvm_mac_update_tkip_key(struct ieee80211_hw *hw, static int iwl_mvm_roc(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_channel *channel, - int duration, - enum ieee80211_roc_type type) + int duration) { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct cfg80211_chan_def chandef; @@ -1093,8 +1101,8 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw, return -EINVAL; } - IWL_DEBUG_MAC80211(mvm, "enter (%d, %d, %d)\n", channel->hw_value, - duration, type); + IWL_DEBUG_MAC80211(mvm, "enter (%d, %d)\n", channel->hw_value, + duration); mutex_lock(&mvm->mutex); diff --git a/trunk/drivers/net/wireless/iwlwifi/mvm/mvm.h b/trunk/drivers/net/wireless/iwlwifi/mvm/mvm.h index 4e339ccfa800..bdae700c769e 100644 --- a/trunk/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/trunk/drivers/net/wireless/iwlwifi/mvm/mvm.h @@ -80,7 +80,8 @@ #define IWL_INVALID_MAC80211_QUEUE 0xff #define IWL_MVM_MAX_ADDRESSES 2 -#define IWL_RSSI_OFFSET 44 +/* RSSI offset for WkP */ +#define IWL_RSSI_OFFSET 50 enum iwl_mvm_tx_fifo { IWL_MVM_TX_FIFO_BK = 0, @@ -327,6 +328,10 @@ struct iwl_mvm { struct led_classdev led; struct ieee80211_vif *p2p_device_vif; + +#ifdef CONFIG_PM_SLEEP + int gtk_ivlen, gtk_icvlen, ptk_ivlen, ptk_icvlen; +#endif }; /* Extract MVM priv from op_mode and _hw */ diff --git a/trunk/drivers/net/wireless/iwlwifi/mvm/ops.c b/trunk/drivers/net/wireless/iwlwifi/mvm/ops.c index aa59adf87db3..d0f9c1e0475e 100644 --- a/trunk/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/trunk/drivers/net/wireless/iwlwifi/mvm/ops.c @@ -624,12 +624,8 @@ static void iwl_mvm_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb) ieee80211_free_txskb(mvm->hw, skb); } -static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode) +static void iwl_mvm_nic_restart(struct iwl_mvm *mvm) { - struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); - - iwl_mvm_dump_nic_error_log(mvm); - iwl_abort_notification_waits(&mvm->notif_wait); /* @@ -663,9 +659,21 @@ static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode) } } +static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode) +{ + struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); + + iwl_mvm_dump_nic_error_log(mvm); + + iwl_mvm_nic_restart(mvm); +} + static void iwl_mvm_cmd_queue_full(struct iwl_op_mode *op_mode) { + struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); + WARN_ON(1); + iwl_mvm_nic_restart(mvm); } static const struct iwl_op_mode_ops iwl_mvm_ops = { diff --git a/trunk/drivers/net/wireless/iwlwifi/mvm/rx.c b/trunk/drivers/net/wireless/iwlwifi/mvm/rx.c index 3f40ab05bbd8..b0b190d0ec23 100644 --- a/trunk/drivers/net/wireless/iwlwifi/mvm/rx.c +++ b/trunk/drivers/net/wireless/iwlwifi/mvm/rx.c @@ -131,33 +131,42 @@ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm, static int iwl_mvm_calc_rssi(struct iwl_mvm *mvm, struct iwl_rx_phy_info *phy_info) { - u32 rssi_a, rssi_b, rssi_c, max_rssi, agc_db; + int rssi_a, rssi_b, rssi_a_dbm, rssi_b_dbm, max_rssi_dbm; + int rssi_all_band_a, rssi_all_band_b; + u32 agc_a, agc_b, max_agc; u32 val; - /* Find max rssi among 3 possible receivers. + /* Find max rssi among 2 possible receivers. * These values are measured by the Digital Signal Processor (DSP). * They should stay fairly constant even as the signal strength varies, * if the radio's Automatic Gain Control (AGC) is working right. * AGC value (see below) will provide the "interesting" info. */ + val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_AGC_IDX]); + agc_a = (val & IWL_OFDM_AGC_A_MSK) >> IWL_OFDM_AGC_A_POS; + agc_b = (val & IWL_OFDM_AGC_B_MSK) >> IWL_OFDM_AGC_B_POS; + max_agc = max_t(u32, agc_a, agc_b); + val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_RSSI_AB_IDX]); rssi_a = (val & IWL_OFDM_RSSI_INBAND_A_MSK) >> IWL_OFDM_RSSI_A_POS; rssi_b = (val & IWL_OFDM_RSSI_INBAND_B_MSK) >> IWL_OFDM_RSSI_B_POS; - val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_RSSI_C_IDX]); - rssi_c = (val & IWL_OFDM_RSSI_INBAND_C_MSK) >> IWL_OFDM_RSSI_C_POS; - - val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_AGC_IDX]); - agc_db = (val & IWL_OFDM_AGC_DB_MSK) >> IWL_OFDM_AGC_DB_POS; + rssi_all_band_a = (val & IWL_OFDM_RSSI_ALLBAND_A_MSK) >> + IWL_OFDM_RSSI_ALLBAND_A_POS; + rssi_all_band_b = (val & IWL_OFDM_RSSI_ALLBAND_B_MSK) >> + IWL_OFDM_RSSI_ALLBAND_B_POS; - max_rssi = max_t(u32, rssi_a, rssi_b); - max_rssi = max_t(u32, max_rssi, rssi_c); + /* + * dBm = rssi dB - agc dB - constant. + * Higher AGC (higher radio gain) means lower signal. + */ + rssi_a_dbm = rssi_a - IWL_RSSI_OFFSET - agc_a; + rssi_b_dbm = rssi_b - IWL_RSSI_OFFSET - agc_b; + max_rssi_dbm = max_t(int, rssi_a_dbm, rssi_b_dbm); - IWL_DEBUG_STATS(mvm, "Rssi In A %d B %d C %d Max %d AGC dB %d\n", - rssi_a, rssi_b, rssi_c, max_rssi, agc_db); + IWL_DEBUG_STATS(mvm, "Rssi In A %d B %d Max %d AGCA %d AGCB %d\n", + rssi_a_dbm, rssi_b_dbm, max_rssi_dbm, agc_a, agc_b); - /* dBm = max_rssi dB - agc dB - constant. - * Higher AGC (higher radio gain) means lower signal. */ - return max_rssi - agc_db - IWL_RSSI_OFFSET; + return max_rssi_dbm; } /* diff --git a/trunk/drivers/net/wireless/iwlwifi/mvm/sta.c b/trunk/drivers/net/wireless/iwlwifi/mvm/sta.c index 52aecf20d0df..274f44e2ef60 100644 --- a/trunk/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/trunk/drivers/net/wireless/iwlwifi/mvm/sta.c @@ -686,7 +686,7 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, spin_lock_bh(&mvmsta->lock); tid_data = &mvmsta->tid_data[tid]; - tid_data->ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number); + tid_data->ssn = SEQ_TO_SN(tid_data->seq_number); tid_data->txq_id = txq_id; *ssn = tid_data->ssn; @@ -770,6 +770,16 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif, u16 txq_id; int err; + + /* + * If mac80211 is cleaning its state, then say that we finished since + * our state has been cleared anyway. + */ + if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) { + ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); + return 0; + } + spin_lock_bh(&mvmsta->lock); txq_id = tid_data->txq_id; @@ -779,7 +789,7 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif, switch (tid_data->state) { case IWL_AGG_ON: - tid_data->ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number); + tid_data->ssn = SEQ_TO_SN(tid_data->seq_number); IWL_DEBUG_TX_QUEUES(mvm, "ssn = %d, next_recl = %d\n", diff --git a/trunk/drivers/net/wireless/iwlwifi/mvm/tx.c b/trunk/drivers/net/wireless/iwlwifi/mvm/tx.c index 56df249b215e..6645efe5c03e 100644 --- a/trunk/drivers/net/wireless/iwlwifi/mvm/tx.c +++ b/trunk/drivers/net/wireless/iwlwifi/mvm/tx.c @@ -607,12 +607,8 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, /* Single frame failure in an AMPDU queue => send BAR */ if (txq_id >= IWL_FIRST_AMPDU_QUEUE && - !(info->flags & IEEE80211_TX_STAT_ACK)) { - /* there must be only one skb in the skb_list */ - WARN_ON_ONCE(skb_freed > 1 || - !skb_queue_empty(&skbs)); + !(info->flags & IEEE80211_TX_STAT_ACK)) info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; - } /* W/A FW bug: seq_ctl is wrong when the queue is flushed */ if (status == TX_STATUS_FAIL_FIFO_FLUSHED) { @@ -641,7 +637,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, next_reclaimed = ssn; } else { /* The next packet to be reclaimed is the one after this one */ - next_reclaimed = IEEE80211_SEQ_TO_SN(seq_ctl + 0x10); + next_reclaimed = SEQ_TO_SN(seq_ctl + 0x10); } IWL_DEBUG_TX_REPLY(mvm, diff --git a/trunk/drivers/net/wireless/iwlwifi/pcie/internal.h b/trunk/drivers/net/wireless/iwlwifi/pcie/internal.h index aa2a39a637dd..148843e7f34f 100644 --- a/trunk/drivers/net/wireless/iwlwifi/pcie/internal.h +++ b/trunk/drivers/net/wireless/iwlwifi/pcie/internal.h @@ -137,10 +137,6 @@ static inline int iwl_queue_dec_wrap(int index, int n_bd) struct iwl_cmd_meta { /* only for SYNC commands, iff the reply skb is wanted */ struct iwl_host_cmd *source; - - DEFINE_DMA_UNMAP_ADDR(mapping); - DEFINE_DMA_UNMAP_LEN(len); - u32 flags; }; @@ -182,19 +178,39 @@ struct iwl_queue { #define TFD_TX_CMD_SLOTS 256 #define TFD_CMD_SLOTS 32 +/* + * The FH will write back to the first TB only, so we need + * to copy some data into the buffer regardless of whether + * it should be mapped or not. This indicates how big the + * first TB must be to include the scratch buffer. Since + * the scratch is 4 bytes at offset 12, it's 16 now. If we + * make it bigger then allocations will be bigger and copy + * slower, so that's probably not useful. + */ +#define IWL_HCMD_SCRATCHBUF_SIZE 16 + struct iwl_pcie_txq_entry { struct iwl_device_cmd *cmd; - struct iwl_device_cmd *copy_cmd; struct sk_buff *skb; /* buffer to free after command completes */ const void *free_buf; struct iwl_cmd_meta meta; }; +struct iwl_pcie_txq_scratch_buf { + struct iwl_cmd_header hdr; + u8 buf[8]; + __le32 scratch; +}; + /** * struct iwl_txq - Tx Queue for DMA * @q: generic Rx/Tx queue descriptor * @tfds: transmit frame descriptors (DMA memory) + * @scratchbufs: start of command headers, including scratch buffers, for + * the writeback -- this is DMA memory and an array holding one buffer + * for each command on the queue + * @scratchbufs_dma: DMA address for the scratchbufs start * @entries: transmit entries (driver state) * @lock: queue lock * @stuck_timer: timer that fires if queue gets stuck @@ -208,6 +224,8 @@ struct iwl_pcie_txq_entry { struct iwl_txq { struct iwl_queue q; struct iwl_tfd *tfds; + struct iwl_pcie_txq_scratch_buf *scratchbufs; + dma_addr_t scratchbufs_dma; struct iwl_pcie_txq_entry *entries; spinlock_t lock; struct timer_list stuck_timer; @@ -216,6 +234,13 @@ struct iwl_txq { u8 active; }; +static inline dma_addr_t +iwl_pcie_get_scratchbuf_dma(struct iwl_txq *txq, int idx) +{ + return txq->scratchbufs_dma + + sizeof(struct iwl_pcie_txq_scratch_buf) * idx; +} + /** * struct iwl_trans_pcie - PCIe transport specific data * @rxq: all the RX queue data diff --git a/trunk/drivers/net/wireless/iwlwifi/pcie/rx.c b/trunk/drivers/net/wireless/iwlwifi/pcie/rx.c index b0ae06d2456f..567e67ad1f61 100644 --- a/trunk/drivers/net/wireless/iwlwifi/pcie/rx.c +++ b/trunk/drivers/net/wireless/iwlwifi/pcie/rx.c @@ -637,22 +637,14 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans, index = SEQ_TO_INDEX(sequence); cmd_index = get_cmd_index(&txq->q, index); - if (reclaim) { - struct iwl_pcie_txq_entry *ent; - ent = &txq->entries[cmd_index]; - cmd = ent->copy_cmd; - WARN_ON_ONCE(!cmd && ent->meta.flags & CMD_WANT_HCMD); - } else { + if (reclaim) + cmd = txq->entries[cmd_index].cmd; + else cmd = NULL; - } err = iwl_op_mode_rx(trans->op_mode, &rxcb, cmd); if (reclaim) { - /* The original command isn't needed any more */ - kfree(txq->entries[cmd_index].copy_cmd); - txq->entries[cmd_index].copy_cmd = NULL; - /* nor is the duplicated part of the command */ kfree(txq->entries[cmd_index].free_buf); txq->entries[cmd_index].free_buf = NULL; } diff --git a/trunk/drivers/net/wireless/iwlwifi/pcie/tx.c b/trunk/drivers/net/wireless/iwlwifi/pcie/tx.c index ad7441dfa6fb..8595c16f74de 100644 --- a/trunk/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/trunk/drivers/net/wireless/iwlwifi/pcie/tx.c @@ -191,12 +191,9 @@ static void iwl_pcie_txq_stuck_timer(unsigned long data) } 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; + i = iwl_queue_inc_wrap(i, q->n_bd)) IWL_ERR(trans, "scratch %d = 0x%08x\n", i, - get_unaligned_le32(&tx_cmd->scratch)); - } + le32_to_cpu(txq->scratchbufs[i].scratch)); iwl_op_mode_nic_error(trans->op_mode); } @@ -367,8 +364,8 @@ static inline u8 iwl_pcie_tfd_get_num_tbs(struct iwl_tfd *tfd) } 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) + struct iwl_cmd_meta *meta, + struct iwl_tfd *tfd) { int i; int num_tbs; @@ -382,17 +379,12 @@ static void iwl_pcie_tfd_unmap(struct iwl_trans *trans, return; } - /* Unmap tx_cmd */ - if (num_tbs) - dma_unmap_single(trans->dev, - dma_unmap_addr(meta, mapping), - dma_unmap_len(meta, len), - DMA_BIDIRECTIONAL); + /* first TB is never freed - it's the scratchbuf data */ - /* 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); + iwl_pcie_tfd_tb_get_len(tfd, i), + DMA_TO_DEVICE); tfd->num_tbs = 0; } @@ -406,8 +398,7 @@ 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) +static void iwl_pcie_txq_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq) { struct iwl_tfd *tfd_tmp = txq->tfds; @@ -418,8 +409,7 @@ 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_pcie_tfd_unmap(trans, &txq->entries[idx].meta, &tfd_tmp[rd_ptr]); /* free SKB */ if (txq->entries) { @@ -479,6 +469,7 @@ static int iwl_pcie_txq_alloc(struct iwl_trans *trans, { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); size_t tfd_sz = sizeof(struct iwl_tfd) * TFD_QUEUE_SIZE_MAX; + size_t scratchbuf_sz; int i; if (WARN_ON(txq->entries || txq->tfds)) @@ -514,9 +505,25 @@ static int iwl_pcie_txq_alloc(struct iwl_trans *trans, IWL_ERR(trans, "dma_alloc_coherent(%zd) failed\n", tfd_sz); goto error; } + + BUILD_BUG_ON(IWL_HCMD_SCRATCHBUF_SIZE != sizeof(*txq->scratchbufs)); + BUILD_BUG_ON(offsetof(struct iwl_pcie_txq_scratch_buf, scratch) != + sizeof(struct iwl_cmd_header) + + offsetof(struct iwl_tx_cmd, scratch)); + + scratchbuf_sz = sizeof(*txq->scratchbufs) * slots_num; + + txq->scratchbufs = dma_alloc_coherent(trans->dev, scratchbuf_sz, + &txq->scratchbufs_dma, + GFP_KERNEL); + if (!txq->scratchbufs) + goto err_free_tfds; + txq->q.id = txq_id; return 0; +err_free_tfds: + dma_free_coherent(trans->dev, tfd_sz, txq->tfds, txq->q.dma_addr); error: if (txq->entries && txq_id == trans_pcie->cmd_queue) for (i = 0; i < slots_num; i++) @@ -565,22 +572,13 @@ 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); + iwl_pcie_txq_free_tfd(trans, txq); q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); } spin_unlock_bh(&txq->lock); @@ -610,7 +608,6 @@ static void iwl_pcie_txq_free(struct iwl_trans *trans, int txq_id) 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); } @@ -619,6 +616,10 @@ static void iwl_pcie_txq_free(struct iwl_trans *trans, int txq_id) dma_free_coherent(dev, sizeof(struct iwl_tfd) * txq->q.n_bd, txq->tfds, txq->q.dma_addr); txq->q.dma_addr = 0; + + dma_free_coherent(dev, + sizeof(*txq->scratchbufs) * txq->q.n_window, + txq->scratchbufs, txq->scratchbufs_dma); } kfree(txq->entries); @@ -962,7 +963,7 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn, iwl_pcie_txq_inval_byte_cnt_tbl(trans, txq); - iwl_pcie_txq_free_tfd(trans, txq, DMA_TO_DEVICE); + iwl_pcie_txq_free_tfd(trans, txq); } iwl_pcie_txq_progress(trans_pcie, txq); @@ -1152,20 +1153,37 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, void *dup_buf = NULL; dma_addr_t phys_addr; int idx; - u16 copy_size, cmd_size; + u16 copy_size, cmd_size, scratch_size; bool had_nocopy = false; int i; u32 cmd_pos; + const u8 *cmddata[IWL_MAX_CMD_TBS_PER_TFD]; + u16 cmdlen[IWL_MAX_CMD_TBS_PER_TFD]; copy_size = sizeof(out_cmd->hdr); cmd_size = sizeof(out_cmd->hdr); /* need one for the header if the first is NOCOPY */ - BUILD_BUG_ON(IWL_MAX_CMD_TFDS > IWL_NUM_OF_TBS - 1); + BUILD_BUG_ON(IWL_MAX_CMD_TBS_PER_TFD > IWL_NUM_OF_TBS - 1); + + for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) { + cmddata[i] = cmd->data[i]; + cmdlen[i] = cmd->len[i]; - for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { if (!cmd->len[i]) continue; + + /* need at least IWL_HCMD_SCRATCHBUF_SIZE copied */ + if (copy_size < IWL_HCMD_SCRATCHBUF_SIZE) { + int copy = IWL_HCMD_SCRATCHBUF_SIZE - copy_size; + + if (copy > cmdlen[i]) + copy = cmdlen[i]; + cmdlen[i] -= copy; + cmddata[i] += copy; + copy_size += copy; + } + if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY) { had_nocopy = true; if (WARN_ON(cmd->dataflags[i] & IWL_HCMD_DFL_DUP)) { @@ -1185,7 +1203,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, goto free_dup_buf; } - dup_buf = kmemdup(cmd->data[i], cmd->len[i], + dup_buf = kmemdup(cmddata[i], cmdlen[i], GFP_ATOMIC); if (!dup_buf) return -ENOMEM; @@ -1195,7 +1213,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, idx = -EINVAL; goto free_dup_buf; } - copy_size += cmd->len[i]; + copy_size += cmdlen[i]; } cmd_size += cmd->len[i]; } @@ -1242,30 +1260,30 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, /* and copy the data that needs to be copied */ cmd_pos = offsetof(struct iwl_device_cmd, payload); - for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { - if (!cmd->len[i]) + copy_size = sizeof(out_cmd->hdr); + for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) { + int copy = 0; + + if (!cmd->len) continue; - if (cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY | - IWL_HCMD_DFL_DUP)) - break; - memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], cmd->len[i]); - cmd_pos += cmd->len[i]; - } - WARN_ON_ONCE(txq->entries[idx].copy_cmd); + /* need at least IWL_HCMD_SCRATCHBUF_SIZE copied */ + if (copy_size < IWL_HCMD_SCRATCHBUF_SIZE) { + copy = IWL_HCMD_SCRATCHBUF_SIZE - copy_size; - /* - * since out_cmd will be the source address of the FH, it will write - * the retry count there. So when the user needs to receivce the HCMD - * that corresponds to the response in the response handler, it needs - * to set CMD_WANT_HCMD. - */ - if (cmd->flags & CMD_WANT_HCMD) { - txq->entries[idx].copy_cmd = - kmemdup(out_cmd, cmd_pos, GFP_ATOMIC); - if (unlikely(!txq->entries[idx].copy_cmd)) { - idx = -ENOMEM; - goto out; + if (copy > cmd->len[i]) + copy = cmd->len[i]; + } + + /* copy everything if not nocopy/dup */ + if (!(cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY | + IWL_HCMD_DFL_DUP))) + copy = cmd->len[i]; + + if (copy) { + memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], copy); + cmd_pos += copy; + copy_size += copy; } } @@ -1275,22 +1293,35 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence), cmd_size, q->write_ptr, idx, trans_pcie->cmd_queue); - phys_addr = dma_map_single(trans->dev, &out_cmd->hdr, copy_size, - DMA_BIDIRECTIONAL); - if (unlikely(dma_mapping_error(trans->dev, phys_addr))) { - idx = -ENOMEM; - goto out; - } - - dma_unmap_addr_set(out_meta, mapping, phys_addr); - dma_unmap_len_set(out_meta, len, copy_size); + /* start the TFD with the scratchbuf */ + scratch_size = min_t(int, copy_size, IWL_HCMD_SCRATCHBUF_SIZE); + memcpy(&txq->scratchbufs[q->write_ptr], &out_cmd->hdr, scratch_size); + iwl_pcie_txq_build_tfd(trans, txq, + iwl_pcie_get_scratchbuf_dma(txq, q->write_ptr), + scratch_size, 1); + + /* map first command fragment, if any remains */ + if (copy_size > scratch_size) { + phys_addr = dma_map_single(trans->dev, + ((u8 *)&out_cmd->hdr) + scratch_size, + copy_size - scratch_size, + DMA_TO_DEVICE); + if (dma_mapping_error(trans->dev, phys_addr)) { + iwl_pcie_tfd_unmap(trans, out_meta, + &txq->tfds[q->write_ptr]); + idx = -ENOMEM; + goto out; + } - iwl_pcie_txq_build_tfd(trans, txq, phys_addr, copy_size, 1); + iwl_pcie_txq_build_tfd(trans, txq, phys_addr, + copy_size - scratch_size, 0); + } - for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { - const void *data = cmd->data[i]; + /* map the remaining (adjusted) nocopy/dup fragments */ + for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) { + const void *data = cmddata[i]; - if (!cmd->len[i]) + if (!cmdlen[i]) continue; if (!(cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY | IWL_HCMD_DFL_DUP))) @@ -1298,16 +1329,15 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, if (cmd->dataflags[i] & IWL_HCMD_DFL_DUP) data = dup_buf; phys_addr = dma_map_single(trans->dev, (void *)data, - cmd->len[i], DMA_BIDIRECTIONAL); + cmdlen[i], DMA_TO_DEVICE); if (dma_mapping_error(trans->dev, phys_addr)) { iwl_pcie_tfd_unmap(trans, out_meta, - &txq->tfds[q->write_ptr], - DMA_BIDIRECTIONAL); + &txq->tfds[q->write_ptr]); idx = -ENOMEM; goto out; } - iwl_pcie_txq_build_tfd(trans, txq, phys_addr, cmd->len[i], 0); + iwl_pcie_txq_build_tfd(trans, txq, phys_addr, cmdlen[i], 0); } out_meta->flags = cmd->flags; @@ -1317,8 +1347,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, txq->need_update = 1; - trace_iwlwifi_dev_hcmd(trans->dev, cmd, cmd_size, - &out_cmd->hdr, copy_size); + trace_iwlwifi_dev_hcmd(trans->dev, cmd, cmd_size, &out_cmd->hdr); /* start timer if queue currently empty */ if (q->read_ptr == q->write_ptr && trans_pcie->wd_timeout) @@ -1377,7 +1406,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_pcie_tfd_unmap(trans, meta, &txq->tfds[index]); /* Input error checking is done when commands are added to queue. */ if (meta->flags & CMD_WANT_SKB) { @@ -1556,10 +1585,9 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, 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; + dma_addr_t tb0_phys, tb1_phys, scratch_phys; + void *tb1_addr; + u16 len, tb1_len, tb2_len; u8 wait_write_ptr = 0; __le16 fc = hdr->frame_control; u8 hdr_len = ieee80211_hdrlen(fc); @@ -1581,7 +1609,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, * Check here that the packets are in the right place on the ring. */ #ifdef CONFIG_IWLWIFI_DEBUG - wifi_seq = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); + 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", @@ -1597,85 +1625,80 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) | INDEX_TO_SEQ(q->write_ptr))); + tb0_phys = iwl_pcie_get_scratchbuf_dma(txq, q->write_ptr); + scratch_phys = tb0_phys + sizeof(struct iwl_cmd_header) + + offsetof(struct iwl_tx_cmd, scratch); + + tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys); + tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys); + /* 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. + * The second TB (tb1) points to the remainder of the TX command + * and the 802.11 header - dword aligned size + * (This calculation modifies the TX command, so do it before the + * setup of the first TB) */ - len = sizeof(struct iwl_tx_cmd) + - sizeof(struct iwl_cmd_header) + hdr_len; - firstlen = (len + 3) & ~3; + len = sizeof(struct iwl_tx_cmd) + sizeof(struct iwl_cmd_header) + + hdr_len - IWL_HCMD_SCRATCHBUF_SIZE; + tb1_len = (len + 3) & ~3; /* Tell NIC about any 2-byte padding after MAC header */ - if (firstlen != len) + if (tb1_len != 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); + /* The first TB points to the scratchbuf data - min_copy bytes */ + memcpy(&txq->scratchbufs[q->write_ptr], &dev_cmd->hdr, + IWL_HCMD_SCRATCHBUF_SIZE); + iwl_pcie_txq_build_tfd(trans, txq, tb0_phys, + IWL_HCMD_SCRATCHBUF_SIZE, 1); - if (!ieee80211_has_morefrags(fc)) { - txq->need_update = 1; - } else { - wait_write_ptr = 1; - txq->need_update = 0; - } + /* there must be data left over for TB1 or this code must be changed */ + BUILD_BUG_ON(sizeof(struct iwl_tx_cmd) < IWL_HCMD_SCRATCHBUF_SIZE); + + /* map the data for TB1 */ + tb1_addr = ((u8 *)&dev_cmd->hdr) + IWL_HCMD_SCRATCHBUF_SIZE; + tb1_phys = dma_map_single(trans->dev, tb1_addr, tb1_len, DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(trans->dev, tb1_phys))) + goto out_err; + iwl_pcie_txq_build_tfd(trans, txq, tb1_phys, tb1_len, 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); + /* + * Set up TFD's third entry to point directly to remainder + * of skb, if any (802.11 null frames have no payload). + */ + tb2_len = skb->len - hdr_len; + if (tb2_len > 0) { + dma_addr_t tb2_phys = dma_map_single(trans->dev, + skb->data + hdr_len, + tb2_len, DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(trans->dev, tb2_phys))) { + iwl_pcie_tfd_unmap(trans, out_meta, + &txq->tfds[q->write_ptr]); goto out_err; } + iwl_pcie_txq_build_tfd(trans, txq, tb2_phys, tb2_len, 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); - - /* 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); - /* 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)); - 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); + &dev_cmd->hdr, IWL_HCMD_SCRATCHBUF_SIZE + tb1_len, + skb->data + hdr_len, tb2_len); trace_iwlwifi_dev_tx_data(trans->dev, skb, - skb->data + hdr_len, secondlen); + skb->data + hdr_len, tb2_len); + + if (!ieee80211_has_morefrags(fc)) { + txq->need_update = 1; + } else { + wait_write_ptr = 1; + txq->need_update = 0; + } /* start timer if queue currently empty */ if (txq->need_update && q->read_ptr == q->write_ptr && diff --git a/trunk/drivers/net/wireless/mac80211_hwsim.c b/trunk/drivers/net/wireless/mac80211_hwsim.c index 7490c4fc7177..cffdf4fbf161 100644 --- a/trunk/drivers/net/wireless/mac80211_hwsim.c +++ b/trunk/drivers/net/wireless/mac80211_hwsim.c @@ -1535,8 +1535,7 @@ 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, - int duration, - enum ieee80211_roc_type type) + int duration) { struct mac80211_hwsim_data *hwsim = hw->priv; diff --git a/trunk/drivers/net/wireless/mwifiex/Makefile b/trunk/drivers/net/wireless/mwifiex/Makefile index ecf28464367f..97b245cbafd8 100644 --- a/trunk/drivers/net/wireless/mwifiex/Makefile +++ b/trunk/drivers/net/wireless/mwifiex/Makefile @@ -39,7 +39,6 @@ mwifiex-y += sta_tx.o mwifiex-y += sta_rx.o mwifiex-y += uap_txrx.o mwifiex-y += cfg80211.o -mwifiex-y += ethtool.o mwifiex-$(CONFIG_DEBUG_FS) += debugfs.o obj-$(CONFIG_MWIFIEX) += mwifiex.o diff --git a/trunk/drivers/net/wireless/mwifiex/cfg80211.c b/trunk/drivers/net/wireless/mwifiex/cfg80211.c index df30107225f8..a44023a7bd57 100644 --- a/trunk/drivers/net/wireless/mwifiex/cfg80211.c +++ b/trunk/drivers/net/wireless/mwifiex/cfg80211.c @@ -2235,7 +2235,6 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, dev->flags |= IFF_BROADCAST | IFF_MULTICAST; dev->watchdog_timeo = MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT; dev->hard_header_len += MWIFIEX_MIN_DATA_HEADER_LEN; - dev->ethtool_ops = &mwifiex_ethtool_ops; mdev_priv = netdev_priv(dev); *((unsigned long *) mdev_priv) = (unsigned long) priv; @@ -2294,149 +2293,6 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) } EXPORT_SYMBOL_GPL(mwifiex_del_virtual_intf); -#ifdef CONFIG_PM -static bool -mwifiex_is_pattern_supported(struct cfg80211_wowlan_trig_pkt_pattern *pat, - s8 *byte_seq) -{ - int j, k, valid_byte_cnt = 0; - bool dont_care_byte = false; - - for (j = 0; j < DIV_ROUND_UP(pat->pattern_len, 8); j++) { - for (k = 0; k < 8; k++) { - if (pat->mask[j] & 1 << k) { - memcpy(byte_seq + valid_byte_cnt, - &pat->pattern[j * 8 + k], 1); - valid_byte_cnt++; - if (dont_care_byte) - return false; - } else { - if (valid_byte_cnt) - dont_care_byte = true; - } - - if (valid_byte_cnt > MAX_BYTESEQ) - return false; - } - } - - byte_seq[MAX_BYTESEQ] = valid_byte_cnt; - - return true; -} - -static int mwifiex_cfg80211_suspend(struct wiphy *wiphy, - struct cfg80211_wowlan *wowlan) -{ - struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); - struct mwifiex_ds_mef_cfg mef_cfg; - struct mwifiex_mef_entry *mef_entry; - int i, filt_num = 0, ret; - bool first_pat = true; - u8 byte_seq[MAX_BYTESEQ + 1]; - const u8 ipv4_mc_mac[] = {0x33, 0x33}; - const u8 ipv6_mc_mac[] = {0x01, 0x00, 0x5e}; - struct mwifiex_private *priv = - mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA); - - if (!wowlan) { - dev_warn(adapter->dev, "None of the WOWLAN triggers enabled\n"); - return 0; - } - - if (!priv->media_connected) { - dev_warn(adapter->dev, - "Can not configure WOWLAN in disconnected state\n"); - return 0; - } - - memset(&mef_cfg, 0, sizeof(mef_cfg)); - mef_cfg.num_entries = 1; - mef_entry = kzalloc(sizeof(*mef_entry), GFP_KERNEL); - mef_cfg.mef_entry = mef_entry; - mef_entry->mode = MEF_MODE_HOST_SLEEP; - mef_entry->action = MEF_ACTION_ALLOW_AND_WAKEUP_HOST; - - for (i = 0; i < wowlan->n_patterns; i++) { - memset(byte_seq, 0, sizeof(byte_seq)); - if (!mwifiex_is_pattern_supported(&wowlan->patterns[i], - byte_seq)) { - wiphy_err(wiphy, "Pattern not supported\n"); - kfree(mef_entry); - return -EOPNOTSUPP; - } - - if (!wowlan->patterns[i].pkt_offset) { - if (!(byte_seq[0] & 0x01) && - (byte_seq[MAX_BYTESEQ] == 1)) { - mef_cfg.criteria |= MWIFIEX_CRITERIA_UNICAST; - continue; - } else if (is_broadcast_ether_addr(byte_seq)) { - mef_cfg.criteria |= MWIFIEX_CRITERIA_BROADCAST; - continue; - } else if ((!memcmp(byte_seq, ipv4_mc_mac, 2) && - (byte_seq[MAX_BYTESEQ] == 2)) || - (!memcmp(byte_seq, ipv6_mc_mac, 3) && - (byte_seq[MAX_BYTESEQ] == 3))) { - mef_cfg.criteria |= MWIFIEX_CRITERIA_MULTICAST; - continue; - } - } - - mef_entry->filter[filt_num].repeat = 1; - mef_entry->filter[filt_num].offset = - wowlan->patterns[i].pkt_offset; - memcpy(mef_entry->filter[filt_num].byte_seq, byte_seq, - sizeof(byte_seq)); - mef_entry->filter[filt_num].filt_type = TYPE_EQ; - - if (first_pat) - first_pat = false; - else - mef_entry->filter[filt_num].filt_action = TYPE_AND; - - filt_num++; - } - - if (wowlan->magic_pkt) { - mef_cfg.criteria |= MWIFIEX_CRITERIA_UNICAST; - mef_entry->filter[filt_num].repeat = 16; - memcpy(mef_entry->filter[filt_num].byte_seq, priv->curr_addr, - ETH_ALEN); - mef_entry->filter[filt_num].byte_seq[MAX_BYTESEQ] = ETH_ALEN; - mef_entry->filter[filt_num].offset = 14; - mef_entry->filter[filt_num].filt_type = TYPE_EQ; - if (filt_num) - mef_entry->filter[filt_num].filt_action = TYPE_OR; - } - - if (!mef_cfg.criteria) - mef_cfg.criteria = MWIFIEX_CRITERIA_BROADCAST | - MWIFIEX_CRITERIA_UNICAST | - MWIFIEX_CRITERIA_MULTICAST; - - ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_MEF_CFG, - HostCmd_ACT_GEN_SET, 0, - &mef_cfg); - - kfree(mef_entry); - return ret; -} - -static int mwifiex_cfg80211_resume(struct wiphy *wiphy) -{ - return 0; -} - -static void mwifiex_cfg80211_set_wakeup(struct wiphy *wiphy, - bool enabled) -{ - struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); - - device_set_wakeup_enable(adapter->dev, enabled); -} -#endif - /* station cfg80211 operations */ static struct cfg80211_ops mwifiex_cfg80211_ops = { .add_virtual_intf = mwifiex_add_virtual_intf, @@ -2465,11 +2321,6 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { .change_beacon = mwifiex_cfg80211_change_beacon, .set_cqm_rssi_config = mwifiex_cfg80211_set_cqm_rssi_config, .set_antenna = mwifiex_cfg80211_set_antenna, -#ifdef CONFIG_PM - .suspend = mwifiex_cfg80211_suspend, - .resume = mwifiex_cfg80211_resume, - .set_wakeup = mwifiex_cfg80211_set_wakeup, -#endif }; /* @@ -2528,14 +2379,6 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) wiphy_apply_custom_regulatory(wiphy, &mwifiex_world_regdom_custom); -#ifdef CONFIG_PM - wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT; - wiphy->wowlan.n_patterns = MWIFIEX_MAX_FILTERS; - wiphy->wowlan.pattern_min_len = 1; - wiphy->wowlan.pattern_max_len = MWIFIEX_MAX_PATTERN_LEN; - wiphy->wowlan.max_pkt_offset = MWIFIEX_MAX_OFFSET_LEN; -#endif - wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P; diff --git a/trunk/drivers/net/wireless/mwifiex/cmdevt.c b/trunk/drivers/net/wireless/mwifiex/cmdevt.c index d19a88c47a4d..20a6c5555873 100644 --- a/trunk/drivers/net/wireless/mwifiex/cmdevt.c +++ b/trunk/drivers/net/wireless/mwifiex/cmdevt.c @@ -1139,7 +1139,7 @@ int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv, phs_cfg->params.hs_config.gpio, phs_cfg->params.hs_config.gap); } - if (conditions != HS_CFG_CANCEL) { + if (conditions != HOST_SLEEP_CFG_CANCEL) { adapter->is_hs_configured = true; if (adapter->iface_type == MWIFIEX_USB || adapter->iface_type == MWIFIEX_PCIE) diff --git a/trunk/drivers/net/wireless/mwifiex/ethtool.c b/trunk/drivers/net/wireless/mwifiex/ethtool.c deleted file mode 100644 index bfb39908b2c6..000000000000 --- a/trunk/drivers/net/wireless/mwifiex/ethtool.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Marvell Wireless LAN device driver: ethtool - * - * Copyright (C) 2013, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "main.h" - -static void mwifiex_ethtool_get_wol(struct net_device *dev, - struct ethtool_wolinfo *wol) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - u32 conditions = le32_to_cpu(priv->adapter->hs_cfg.conditions); - - wol->supported = WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY; - - if (conditions == HS_CFG_COND_DEF) - return; - - if (conditions & HS_CFG_COND_UNICAST_DATA) - wol->wolopts |= WAKE_UCAST; - if (conditions & HS_CFG_COND_MULTICAST_DATA) - wol->wolopts |= WAKE_MCAST; - if (conditions & HS_CFG_COND_BROADCAST_DATA) - wol->wolopts |= WAKE_BCAST; - if (conditions & HS_CFG_COND_MAC_EVENT) - wol->wolopts |= WAKE_PHY; -} - -static int mwifiex_ethtool_set_wol(struct net_device *dev, - struct ethtool_wolinfo *wol) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - u32 conditions = 0; - - if (wol->wolopts & ~(WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY)) - return -EOPNOTSUPP; - - if (wol->wolopts & WAKE_UCAST) - conditions |= HS_CFG_COND_UNICAST_DATA; - if (wol->wolopts & WAKE_MCAST) - conditions |= HS_CFG_COND_MULTICAST_DATA; - if (wol->wolopts & WAKE_BCAST) - conditions |= HS_CFG_COND_BROADCAST_DATA; - if (wol->wolopts & WAKE_PHY) - conditions |= HS_CFG_COND_MAC_EVENT; - if (wol->wolopts == 0) - conditions |= HS_CFG_COND_DEF; - priv->adapter->hs_cfg.conditions = cpu_to_le32(conditions); - - return 0; -} - -const struct ethtool_ops mwifiex_ethtool_ops = { - .get_wol = mwifiex_ethtool_get_wol, - .set_wol = mwifiex_ethtool_set_wol, -}; diff --git a/trunk/drivers/net/wireless/mwifiex/fw.h b/trunk/drivers/net/wireless/mwifiex/fw.h index 6d6e5ae71eaa..25acb0682c56 100644 --- a/trunk/drivers/net/wireless/mwifiex/fw.h +++ b/trunk/drivers/net/wireless/mwifiex/fw.h @@ -300,7 +300,6 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { #define HostCmd_CMD_802_11_TX_RATE_QUERY 0x007f #define HostCmd_CMD_802_11_IBSS_COALESCING_STATUS 0x0083 #define HostCmd_CMD_VERSION_EXT 0x0097 -#define HostCmd_CMD_MEF_CFG 0x009a #define HostCmd_CMD_RSSI_INFO 0x00a4 #define HostCmd_CMD_FUNC_INIT 0x00a9 #define HostCmd_CMD_FUNC_SHUTDOWN 0x00aa @@ -377,14 +376,10 @@ enum P2P_MODES { #define HostCmd_SCAN_RADIO_TYPE_BG 0 #define HostCmd_SCAN_RADIO_TYPE_A 1 -#define HS_CFG_CANCEL 0xffffffff -#define HS_CFG_COND_DEF 0x00000000 -#define HS_CFG_GPIO_DEF 0xff -#define HS_CFG_GAP_DEF 0 -#define HS_CFG_COND_BROADCAST_DATA 0x00000001 -#define HS_CFG_COND_UNICAST_DATA 0x00000002 -#define HS_CFG_COND_MAC_EVENT 0x00000004 -#define HS_CFG_COND_MULTICAST_DATA 0x00000008 +#define HOST_SLEEP_CFG_CANCEL 0xffffffff +#define HOST_SLEEP_CFG_COND_DEF 0x00000000 +#define HOST_SLEEP_CFG_GPIO_DEF 0xff +#define HOST_SLEEP_CFG_GAP_DEF 0 #define MWIFIEX_TIMEOUT_FOR_AP_RESP 0xfffc #define MWIFIEX_STATUS_CODE_AUTH_TIMEOUT 2 @@ -474,23 +469,6 @@ enum P2P_MODES { #define EVENT_GET_BSS_TYPE(event_cause) \ (((event_cause) >> 24) & 0x00ff) -#define MWIFIEX_MAX_PATTERN_LEN 20 -#define MWIFIEX_MAX_OFFSET_LEN 50 -#define STACK_NBYTES 100 -#define TYPE_DNUM 1 -#define TYPE_BYTESEQ 2 -#define MAX_OPERAND 0x40 -#define TYPE_EQ (MAX_OPERAND+1) -#define TYPE_EQ_DNUM (MAX_OPERAND+2) -#define TYPE_EQ_BIT (MAX_OPERAND+3) -#define TYPE_AND (MAX_OPERAND+4) -#define TYPE_OR (MAX_OPERAND+5) -#define MEF_MODE_HOST_SLEEP 1 -#define MEF_ACTION_ALLOW_AND_WAKEUP_HOST 3 -#define MWIFIEX_CRITERIA_BROADCAST BIT(0) -#define MWIFIEX_CRITERIA_UNICAST BIT(1) -#define MWIFIEX_CRITERIA_MULTICAST BIT(3) - struct mwifiex_ie_types_header { __le16 type; __le16 len; @@ -1521,19 +1499,6 @@ struct host_cmd_ds_802_11_ibss_status { __le16 use_g_rate_protect; } __packed; -struct mwifiex_fw_mef_entry { - u8 mode; - u8 action; - __le16 exprsize; - u8 expr[0]; -} __packed; - -struct host_cmd_ds_mef_cfg { - __le32 criteria; - __le16 num_entries; - struct mwifiex_fw_mef_entry mef_entry[0]; -} __packed; - #define CONNECTION_TYPE_INFRA 0 #define CONNECTION_TYPE_ADHOC 1 #define CONNECTION_TYPE_AP 2 @@ -1638,7 +1603,6 @@ struct host_cmd_ds_command { struct host_cmd_ds_remain_on_chan roc_cfg; struct host_cmd_ds_p2p_mode_cfg mode_cfg; struct host_cmd_ds_802_11_ibss_status ibss_coalescing; - struct host_cmd_ds_mef_cfg mef_cfg; struct host_cmd_ds_mac_reg_access mac_reg; struct host_cmd_ds_bbp_reg_access bbp_reg; struct host_cmd_ds_rf_reg_access rf_reg; diff --git a/trunk/drivers/net/wireless/mwifiex/init.c b/trunk/drivers/net/wireless/mwifiex/init.c index cab3434d0d52..e38aa9b3663d 100644 --- a/trunk/drivers/net/wireless/mwifiex/init.c +++ b/trunk/drivers/net/wireless/mwifiex/init.c @@ -318,9 +318,9 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter) adapter->curr_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; adapter->is_hs_configured = false; - adapter->hs_cfg.conditions = cpu_to_le32(HS_CFG_COND_DEF); - adapter->hs_cfg.gpio = HS_CFG_GPIO_DEF; - adapter->hs_cfg.gap = HS_CFG_GAP_DEF; + adapter->hs_cfg.conditions = cpu_to_le32(HOST_SLEEP_CFG_COND_DEF); + adapter->hs_cfg.gpio = HOST_SLEEP_CFG_GPIO_DEF; + adapter->hs_cfg.gap = HOST_SLEEP_CFG_GAP_DEF; adapter->hs_activated = false; memset(adapter->event_body, 0, sizeof(adapter->event_body)); diff --git a/trunk/drivers/net/wireless/mwifiex/ioctl.h b/trunk/drivers/net/wireless/mwifiex/ioctl.h index 91d522c746ed..d85e6eb1f58a 100644 --- a/trunk/drivers/net/wireless/mwifiex/ioctl.h +++ b/trunk/drivers/net/wireless/mwifiex/ioctl.h @@ -354,29 +354,6 @@ struct mwifiex_ds_misc_subsc_evt { struct subsc_evt_cfg bcn_h_rssi_cfg; }; -#define MAX_BYTESEQ 6 /* non-adjustable */ -#define MWIFIEX_MAX_FILTERS 10 - -struct mwifiex_mef_filter { - u16 repeat; - u16 offset; - s8 byte_seq[MAX_BYTESEQ + 1]; - u8 filt_type; - u8 filt_action; -}; - -struct mwifiex_mef_entry { - u8 mode; - u8 action; - struct mwifiex_mef_filter filter[MWIFIEX_MAX_FILTERS]; -}; - -struct mwifiex_ds_mef_cfg { - u32 criteria; - u16 num_entries; - struct mwifiex_mef_entry *mef_entry; -}; - #define MWIFIEX_MAX_VSIE_LEN (256) #define MWIFIEX_MAX_VSIE_NUM (8) #define MWIFIEX_VSIE_MASK_CLEAR 0x00 diff --git a/trunk/drivers/net/wireless/mwifiex/main.h b/trunk/drivers/net/wireless/mwifiex/main.h index 560cf7312d08..553adfb0aa81 100644 --- a/trunk/drivers/net/wireless/mwifiex/main.h +++ b/trunk/drivers/net/wireless/mwifiex/main.h @@ -1098,15 +1098,11 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev); void mwifiex_set_sys_config_invalid_data(struct mwifiex_uap_bss_param *config); -int mwifiex_add_wowlan_magic_pkt_filter(struct mwifiex_adapter *adapter); - int mwifiex_set_mgmt_ies(struct mwifiex_private *priv, struct cfg80211_beacon_data *data); int mwifiex_del_mgmt_ies(struct mwifiex_private *priv); u8 *mwifiex_11d_code_2_region(u8 code); -extern const struct ethtool_ops mwifiex_ethtool_ops; - #ifdef CONFIG_DEBUG_FS void mwifiex_debugfs_init(void); void mwifiex_debugfs_remove(void); diff --git a/trunk/drivers/net/wireless/mwifiex/pcie.c b/trunk/drivers/net/wireless/mwifiex/pcie.c index b813a27ee613..35c79722c361 100644 --- a/trunk/drivers/net/wireless/mwifiex/pcie.c +++ b/trunk/drivers/net/wireless/mwifiex/pcie.c @@ -36,6 +36,8 @@ static u8 user_rmmod; static struct mwifiex_if_ops pcie_ops; static struct semaphore add_remove_card_sem; +static int mwifiex_pcie_enable_host_int(struct mwifiex_adapter *adapter); +static int mwifiex_pcie_resume(struct pci_dev *pdev); static int mwifiex_map_pci_memory(struct mwifiex_adapter *adapter, struct sk_buff *skb, @@ -76,82 +78,6 @@ static bool mwifiex_pcie_ok_to_access_hw(struct mwifiex_adapter *adapter) return false; } -#ifdef CONFIG_PM -/* - * Kernel needs to suspend all functions separately. Therefore all - * registered functions must have drivers with suspend and resume - * methods. Failing that the kernel simply removes the whole card. - * - * If already not suspended, this function allocates and sends a host - * sleep activate request to the firmware and turns off the traffic. - */ -static int mwifiex_pcie_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct mwifiex_adapter *adapter; - struct pcie_service_card *card; - int hs_actived; - - if (pdev) { - card = (struct pcie_service_card *) pci_get_drvdata(pdev); - if (!card || !card->adapter) { - pr_err("Card or adapter structure is not valid\n"); - return 0; - } - } else { - pr_err("PCIE device is not specified\n"); - return 0; - } - - adapter = card->adapter; - - hs_actived = mwifiex_enable_hs(adapter); - - /* Indicate device suspended */ - adapter->is_suspended = true; - - return 0; -} - -/* - * Kernel needs to suspend all functions separately. Therefore all - * registered functions must have drivers with suspend and resume - * methods. Failing that the kernel simply removes the whole card. - * - * If already not resumed, this function turns on the traffic and - * sends a host sleep cancel request to the firmware. - */ -static int mwifiex_pcie_resume(struct pci_dev *pdev) -{ - struct mwifiex_adapter *adapter; - struct pcie_service_card *card; - - if (pdev) { - card = (struct pcie_service_card *) pci_get_drvdata(pdev); - if (!card || !card->adapter) { - pr_err("Card or adapter structure is not valid\n"); - return 0; - } - } else { - pr_err("PCIE device is not specified\n"); - return 0; - } - - adapter = card->adapter; - - if (!adapter->is_suspended) { - dev_warn(adapter->dev, "Device already resumed\n"); - return 0; - } - - adapter->is_suspended = false; - - mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA), - MWIFIEX_ASYNC_CMD); - - return 0; -} -#endif - /* * This function probes an mwifiex device and registers it. It allocates * the card structure, enables PCIE function number and initiates the @@ -233,6 +159,80 @@ static void mwifiex_pcie_remove(struct pci_dev *pdev) kfree(card); } +/* + * Kernel needs to suspend all functions separately. Therefore all + * registered functions must have drivers with suspend and resume + * methods. Failing that the kernel simply removes the whole card. + * + * If already not suspended, this function allocates and sends a host + * sleep activate request to the firmware and turns off the traffic. + */ +static int mwifiex_pcie_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct mwifiex_adapter *adapter; + struct pcie_service_card *card; + int hs_actived; + + if (pdev) { + card = (struct pcie_service_card *) pci_get_drvdata(pdev); + if (!card || !card->adapter) { + pr_err("Card or adapter structure is not valid\n"); + return 0; + } + } else { + pr_err("PCIE device is not specified\n"); + return 0; + } + + adapter = card->adapter; + + hs_actived = mwifiex_enable_hs(adapter); + + /* Indicate device suspended */ + adapter->is_suspended = true; + + return 0; +} + +/* + * Kernel needs to suspend all functions separately. Therefore all + * registered functions must have drivers with suspend and resume + * methods. Failing that the kernel simply removes the whole card. + * + * If already not resumed, this function turns on the traffic and + * sends a host sleep cancel request to the firmware. + */ +static int mwifiex_pcie_resume(struct pci_dev *pdev) +{ + struct mwifiex_adapter *adapter; + struct pcie_service_card *card; + + if (pdev) { + card = (struct pcie_service_card *) pci_get_drvdata(pdev); + if (!card || !card->adapter) { + pr_err("Card or adapter structure is not valid\n"); + return 0; + } + } else { + pr_err("PCIE device is not specified\n"); + return 0; + } + + adapter = card->adapter; + + if (!adapter->is_suspended) { + dev_warn(adapter->dev, "Device already resumed\n"); + return 0; + } + + adapter->is_suspended = false; + + mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA), + MWIFIEX_ASYNC_CMD); + + return 0; +} + static DEFINE_PCI_DEVICE_TABLE(mwifiex_ids) = { { PCIE_VENDOR_ID_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8766P, @@ -1030,8 +1030,8 @@ mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb, u32 wrindx, num_tx_buffs, rx_val; int ret; dma_addr_t buf_pa; - struct mwifiex_pcie_buf_desc *desc = NULL; - struct mwifiex_pfu_buf_desc *desc2 = NULL; + struct mwifiex_pcie_buf_desc *desc; + struct mwifiex_pfu_buf_desc *desc2; __le16 *tmp; if (!(skb->data && skb->len)) { diff --git a/trunk/drivers/net/wireless/mwifiex/sta_cmd.c b/trunk/drivers/net/wireless/mwifiex/sta_cmd.c index a2ae690a0a67..c55c5bb93134 100644 --- a/trunk/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/trunk/drivers/net/wireless/mwifiex/sta_cmd.c @@ -334,7 +334,7 @@ mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv, cmd->command = cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH); if (!hs_activate && - (hscfg_param->conditions != cpu_to_le32(HS_CFG_CANCEL)) && + (hscfg_param->conditions != cpu_to_le32(HOST_SLEEP_CFG_CANCEL)) && ((adapter->arp_filter_size > 0) && (adapter->arp_filter_size <= ARP_FILTER_MAX_BUF_SIZE))) { dev_dbg(adapter->dev, @@ -1059,80 +1059,6 @@ mwifiex_cmd_802_11_subsc_evt(struct mwifiex_private *priv, return 0; } -static int -mwifiex_cmd_append_rpn_expression(struct mwifiex_private *priv, - struct mwifiex_mef_entry *mef_entry, - u8 **buffer) -{ - struct mwifiex_mef_filter *filter = mef_entry->filter; - int i, byte_len; - u8 *stack_ptr = *buffer; - - for (i = 0; i < MWIFIEX_MAX_FILTERS; i++) { - filter = &mef_entry->filter[i]; - if (!filter->filt_type) - break; - *(__le32 *)stack_ptr = cpu_to_le32((u32)filter->repeat); - stack_ptr += 4; - *stack_ptr = TYPE_DNUM; - stack_ptr += 1; - - byte_len = filter->byte_seq[MAX_BYTESEQ]; - memcpy(stack_ptr, filter->byte_seq, byte_len); - stack_ptr += byte_len; - *stack_ptr = byte_len; - stack_ptr += 1; - *stack_ptr = TYPE_BYTESEQ; - stack_ptr += 1; - - *(__le32 *)stack_ptr = cpu_to_le32((u32)filter->offset); - stack_ptr += 4; - *stack_ptr = TYPE_DNUM; - stack_ptr += 1; - - *stack_ptr = filter->filt_type; - stack_ptr += 1; - - if (filter->filt_action) { - *stack_ptr = filter->filt_action; - stack_ptr += 1; - } - - if (stack_ptr - *buffer > STACK_NBYTES) - return -1; - } - - *buffer = stack_ptr; - return 0; -} - -static int -mwifiex_cmd_mef_cfg(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - struct mwifiex_ds_mef_cfg *mef) -{ - struct host_cmd_ds_mef_cfg *mef_cfg = &cmd->params.mef_cfg; - u8 *pos = (u8 *)mef_cfg; - - cmd->command = cpu_to_le16(HostCmd_CMD_MEF_CFG); - - mef_cfg->criteria = cpu_to_le32(mef->criteria); - mef_cfg->num_entries = cpu_to_le16(mef->num_entries); - pos += sizeof(*mef_cfg); - mef_cfg->mef_entry->mode = mef->mef_entry->mode; - mef_cfg->mef_entry->action = mef->mef_entry->action; - pos += sizeof(*(mef_cfg->mef_entry)); - - if (mwifiex_cmd_append_rpn_expression(priv, mef->mef_entry, &pos)) - return -1; - - mef_cfg->mef_entry->exprsize = - cpu_to_le16(pos - mef_cfg->mef_entry->expr); - cmd->size = cpu_to_le16((u16) (pos - (u8 *)mef_cfg) + S_DS_GEN); - - return 0; -} - /* * This function prepares the commands before sending them to the firmware. * @@ -1347,9 +1273,6 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, case HostCmd_CMD_802_11_SUBSCRIBE_EVENT: ret = mwifiex_cmd_802_11_subsc_evt(priv, cmd_ptr, data_buf); break; - case HostCmd_CMD_MEF_CFG: - ret = mwifiex_cmd_mef_cfg(priv, cmd_ptr, data_buf); - break; default: dev_err(priv->adapter->dev, "PREP_CMD: unknown cmd- %#x\n", cmd_no); diff --git a/trunk/drivers/net/wireless/mwifiex/sta_cmdresp.c b/trunk/drivers/net/wireless/mwifiex/sta_cmdresp.c index 80b9f2238001..4669f8d9389f 100644 --- a/trunk/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/trunk/drivers/net/wireless/mwifiex/sta_cmdresp.c @@ -976,8 +976,6 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, case HostCmd_CMD_UAP_BSS_STOP: priv->bss_started = 0; break; - case HostCmd_CMD_MEF_CFG: - break; default: dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n", resp->command); diff --git a/trunk/drivers/net/wireless/mwifiex/sta_ioctl.c b/trunk/drivers/net/wireless/mwifiex/sta_ioctl.c index 76d31deb7b1b..9f33c92c90f5 100644 --- a/trunk/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/trunk/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -388,7 +388,7 @@ static int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action, break; } if (hs_cfg->is_invoke_hostcmd) { - if (hs_cfg->conditions == HS_CFG_CANCEL) { + if (hs_cfg->conditions == HOST_SLEEP_CFG_CANCEL) { if (!adapter->is_hs_configured) /* Already cancelled */ break; @@ -403,8 +403,8 @@ static int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action, adapter->hs_cfg.gpio = (u8)hs_cfg->gpio; if (hs_cfg->gap) adapter->hs_cfg.gap = (u8)hs_cfg->gap; - } else if (adapter->hs_cfg.conditions == - cpu_to_le32(HS_CFG_CANCEL)) { + } else if (adapter->hs_cfg.conditions + == cpu_to_le32(HOST_SLEEP_CFG_CANCEL)) { /* Return failure if no parameters for HS enable */ status = -1; @@ -420,7 +420,7 @@ static int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action, HostCmd_CMD_802_11_HS_CFG_ENH, HostCmd_ACT_GEN_SET, 0, &adapter->hs_cfg); - if (hs_cfg->conditions == HS_CFG_CANCEL) + if (hs_cfg->conditions == HOST_SLEEP_CFG_CANCEL) /* Restore previous condition */ adapter->hs_cfg.conditions = cpu_to_le32(prev_cond); @@ -454,7 +454,7 @@ int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type) { struct mwifiex_ds_hs_cfg hscfg; - hscfg.conditions = HS_CFG_CANCEL; + hscfg.conditions = HOST_SLEEP_CFG_CANCEL; hscfg.is_invoke_hostcmd = true; return mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET, diff --git a/trunk/drivers/net/wireless/mwifiex/util.c b/trunk/drivers/net/wireless/mwifiex/util.c index 54667e65ca47..21553976b550 100644 --- a/trunk/drivers/net/wireless/mwifiex/util.c +++ b/trunk/drivers/net/wireless/mwifiex/util.c @@ -195,7 +195,7 @@ int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb) skb->protocol = eth_type_trans(skb, priv->netdev); skb->ip_summed = CHECKSUM_NONE; - /* This is required only in case of 11n and USB/PCIE as we alloc + /* This is required only in case of 11n and USB as we alloc * a buffer of 4K only if its 11N (to be able to receive 4K * AMSDU packets). In case of SD we allocate buffers based * on the size of packet and hence this is not needed. @@ -212,8 +212,7 @@ int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb) * fragments. Currently we fail the Filesndl-ht.scr script * for UDP, hence this fix */ - if ((priv->adapter->iface_type == MWIFIEX_USB || - priv->adapter->iface_type == MWIFIEX_PCIE) && + if ((priv->adapter->iface_type == MWIFIEX_USB) && (skb->truesize > MWIFIEX_RX_DATA_BUF_SIZE)) skb->truesize += (skb->len - MWIFIEX_RX_DATA_BUF_SIZE); diff --git a/trunk/drivers/net/wireless/mwl8k.c b/trunk/drivers/net/wireless/mwl8k.c index aaaf10d48f7d..091d9a64080a 100644 --- a/trunk/drivers/net/wireless/mwl8k.c +++ b/trunk/drivers/net/wireless/mwl8k.c @@ -284,7 +284,6 @@ struct mwl8k_priv { unsigned fw_state; char *fw_pref; char *fw_alt; - bool is_8764; struct completion firmware_loading_complete; /* bitmap of running BSSes */ @@ -601,18 +600,13 @@ mwl8k_send_fw_load_cmd(struct mwl8k_priv *priv, void *data, int length) loops = 1000; do { u32 int_code; - if (priv->is_8764) { - int_code = ioread32(regs + - MWL8K_HIU_H2A_INTERRUPT_STATUS); - if (int_code == 0) - break; - } else { - int_code = ioread32(regs + MWL8K_HIU_INT_CODE); - if (int_code == MWL8K_INT_CODE_CMD_FINISHED) { - iowrite32(0, regs + MWL8K_HIU_INT_CODE); - break; - } + + int_code = ioread32(regs + MWL8K_HIU_INT_CODE); + if (int_code == MWL8K_INT_CODE_CMD_FINISHED) { + iowrite32(0, regs + MWL8K_HIU_INT_CODE); + break; } + cond_resched(); udelay(1); } while (--loops); @@ -730,7 +724,7 @@ static int mwl8k_load_firmware(struct ieee80211_hw *hw) int rc; int loops; - if (!memcmp(fw->data, "\x01\x00\x00\x00", 4) && !priv->is_8764) { + if (!memcmp(fw->data, "\x01\x00\x00\x00", 4)) { const struct firmware *helper = priv->fw_helper; if (helper == NULL) { @@ -749,10 +743,7 @@ static int mwl8k_load_firmware(struct ieee80211_hw *hw) rc = mwl8k_feed_fw_image(priv, fw->data, fw->size); } else { - if (priv->is_8764) - rc = mwl8k_feed_fw_image(priv, fw->data, fw->size); - else - rc = mwl8k_load_fw_image(priv, fw->data, fw->size); + rc = mwl8k_load_fw_image(priv, fw->data, fw->size); } if (rc) { @@ -917,9 +908,9 @@ static void mwl8k_encapsulate_tx_frame(struct mwl8k_priv *priv, } /* - * Packet reception for 88w8366/88w8764 AP firmware. + * Packet reception for 88w8366 AP firmware. */ -struct mwl8k_rxd_ap { +struct mwl8k_rxd_8366_ap { __le16 pkt_len; __u8 sq2; __u8 rate; @@ -937,30 +928,30 @@ struct mwl8k_rxd_ap { __u8 rx_ctrl; } __packed; -#define MWL8K_AP_RATE_INFO_MCS_FORMAT 0x80 -#define MWL8K_AP_RATE_INFO_40MHZ 0x40 -#define MWL8K_AP_RATE_INFO_RATEID(x) ((x) & 0x3f) +#define MWL8K_8366_AP_RATE_INFO_MCS_FORMAT 0x80 +#define MWL8K_8366_AP_RATE_INFO_40MHZ 0x40 +#define MWL8K_8366_AP_RATE_INFO_RATEID(x) ((x) & 0x3f) -#define MWL8K_AP_RX_CTRL_OWNED_BY_HOST 0x80 +#define MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST 0x80 -/* 8366/8764 AP rx_status bits */ -#define MWL8K_AP_RXSTAT_DECRYPT_ERR_MASK 0x80 -#define MWL8K_AP_RXSTAT_GENERAL_DECRYPT_ERR 0xFF -#define MWL8K_AP_RXSTAT_TKIP_DECRYPT_MIC_ERR 0x02 -#define MWL8K_AP_RXSTAT_WEP_DECRYPT_ICV_ERR 0x04 -#define MWL8K_AP_RXSTAT_TKIP_DECRYPT_ICV_ERR 0x08 +/* 8366 AP rx_status bits */ +#define MWL8K_8366_AP_RXSTAT_DECRYPT_ERR_MASK 0x80 +#define MWL8K_8366_AP_RXSTAT_GENERAL_DECRYPT_ERR 0xFF +#define MWL8K_8366_AP_RXSTAT_TKIP_DECRYPT_MIC_ERR 0x02 +#define MWL8K_8366_AP_RXSTAT_WEP_DECRYPT_ICV_ERR 0x04 +#define MWL8K_8366_AP_RXSTAT_TKIP_DECRYPT_ICV_ERR 0x08 -static void mwl8k_rxd_ap_init(void *_rxd, dma_addr_t next_dma_addr) +static void mwl8k_rxd_8366_ap_init(void *_rxd, dma_addr_t next_dma_addr) { - struct mwl8k_rxd_ap *rxd = _rxd; + struct mwl8k_rxd_8366_ap *rxd = _rxd; rxd->next_rxd_phys_addr = cpu_to_le32(next_dma_addr); - rxd->rx_ctrl = MWL8K_AP_RX_CTRL_OWNED_BY_HOST; + rxd->rx_ctrl = MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST; } -static void mwl8k_rxd_ap_refill(void *_rxd, dma_addr_t addr, int len) +static void mwl8k_rxd_8366_ap_refill(void *_rxd, dma_addr_t addr, int len) { - struct mwl8k_rxd_ap *rxd = _rxd; + struct mwl8k_rxd_8366_ap *rxd = _rxd; rxd->pkt_len = cpu_to_le16(len); rxd->pkt_phys_addr = cpu_to_le32(addr); @@ -969,12 +960,12 @@ static void mwl8k_rxd_ap_refill(void *_rxd, dma_addr_t addr, int len) } static int -mwl8k_rxd_ap_process(void *_rxd, struct ieee80211_rx_status *status, - __le16 *qos, s8 *noise) +mwl8k_rxd_8366_ap_process(void *_rxd, struct ieee80211_rx_status *status, + __le16 *qos, s8 *noise) { - struct mwl8k_rxd_ap *rxd = _rxd; + struct mwl8k_rxd_8366_ap *rxd = _rxd; - if (!(rxd->rx_ctrl & MWL8K_AP_RX_CTRL_OWNED_BY_HOST)) + if (!(rxd->rx_ctrl & MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST)) return -1; rmb(); @@ -983,11 +974,11 @@ mwl8k_rxd_ap_process(void *_rxd, struct ieee80211_rx_status *status, status->signal = -rxd->rssi; *noise = -rxd->noise_floor; - if (rxd->rate & MWL8K_AP_RATE_INFO_MCS_FORMAT) { + if (rxd->rate & MWL8K_8366_AP_RATE_INFO_MCS_FORMAT) { status->flag |= RX_FLAG_HT; - if (rxd->rate & MWL8K_AP_RATE_INFO_40MHZ) + if (rxd->rate & MWL8K_8366_AP_RATE_INFO_40MHZ) status->flag |= RX_FLAG_40MHZ; - status->rate_idx = MWL8K_AP_RATE_INFO_RATEID(rxd->rate); + status->rate_idx = MWL8K_8366_AP_RATE_INFO_RATEID(rxd->rate); } else { int i; @@ -1011,19 +1002,19 @@ mwl8k_rxd_ap_process(void *_rxd, struct ieee80211_rx_status *status, *qos = rxd->qos_control; - if ((rxd->rx_status != MWL8K_AP_RXSTAT_GENERAL_DECRYPT_ERR) && - (rxd->rx_status & MWL8K_AP_RXSTAT_DECRYPT_ERR_MASK) && - (rxd->rx_status & MWL8K_AP_RXSTAT_TKIP_DECRYPT_MIC_ERR)) + if ((rxd->rx_status != MWL8K_8366_AP_RXSTAT_GENERAL_DECRYPT_ERR) && + (rxd->rx_status & MWL8K_8366_AP_RXSTAT_DECRYPT_ERR_MASK) && + (rxd->rx_status & MWL8K_8366_AP_RXSTAT_TKIP_DECRYPT_MIC_ERR)) status->flag |= RX_FLAG_MMIC_ERROR; return le16_to_cpu(rxd->pkt_len); } -static struct rxd_ops rxd_ap_ops = { - .rxd_size = sizeof(struct mwl8k_rxd_ap), - .rxd_init = mwl8k_rxd_ap_init, - .rxd_refill = mwl8k_rxd_ap_refill, - .rxd_process = mwl8k_rxd_ap_process, +static struct rxd_ops rxd_8366_ap_ops = { + .rxd_size = sizeof(struct mwl8k_rxd_8366_ap), + .rxd_init = mwl8k_rxd_8366_ap_init, + .rxd_refill = mwl8k_rxd_8366_ap_refill, + .rxd_process = mwl8k_rxd_8366_ap_process, }; /* @@ -5438,17 +5429,12 @@ enum { MWL8363 = 0, MWL8687, MWL8366, - MWL8764, }; #define MWL8K_8366_AP_FW_API 3 #define _MWL8K_8366_AP_FW(api) "mwl8k/fmimage_8366_ap-" #api ".fw" #define MWL8K_8366_AP_FW(api) _MWL8K_8366_AP_FW(api) -#define MWL8K_8764_AP_FW_API 1 -#define _MWL8K_8764_AP_FW(api) "mwl8k/fmimage_8764_ap-" #api ".fw" -#define MWL8K_8764_AP_FW(api) _MWL8K_8764_AP_FW(api) - static struct mwl8k_device_info mwl8k_info_tbl[] = { [MWL8363] = { .part_name = "88w8363", @@ -5466,13 +5452,7 @@ static struct mwl8k_device_info mwl8k_info_tbl[] = { .fw_image_sta = "mwl8k/fmimage_8366.fw", .fw_image_ap = MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API), .fw_api_ap = MWL8K_8366_AP_FW_API, - .ap_rxd_ops = &rxd_ap_ops, - }, - [MWL8764] = { - .part_name = "88w8764", - .fw_image_ap = MWL8K_8764_AP_FW(MWL8K_8764_AP_FW_API), - .fw_api_ap = MWL8K_8764_AP_FW_API, - .ap_rxd_ops = &rxd_ap_ops, + .ap_rxd_ops = &rxd_8366_ap_ops, }, }; @@ -5494,7 +5474,6 @@ static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = { { PCI_VDEVICE(MARVELL, 0x2a41), .driver_data = MWL8366, }, { PCI_VDEVICE(MARVELL, 0x2a42), .driver_data = MWL8366, }, { PCI_VDEVICE(MARVELL, 0x2a43), .driver_data = MWL8366, }, - { PCI_VDEVICE(MARVELL, 0x2b36), .driver_data = MWL8764, }, { }, }; MODULE_DEVICE_TABLE(pci, mwl8k_pci_id_table); @@ -6016,8 +5995,6 @@ static int mwl8k_probe(struct pci_dev *pdev, priv->pdev = pdev; priv->device_info = &mwl8k_info_tbl[id->driver_data]; - if (id->driver_data == MWL8764) - priv->is_8764 = true; priv->sram = pci_iomap(pdev, 0, 0x10000); if (priv->sram == NULL) { diff --git a/trunk/drivers/net/wireless/ray_cs.c b/trunk/drivers/net/wireless/ray_cs.c index 4775b5d172d5..3109c0db66e1 100644 --- a/trunk/drivers/net/wireless/ray_cs.c +++ b/trunk/drivers/net/wireless/ray_cs.c @@ -144,7 +144,7 @@ static int psm; static char *essid; /* Default to encapsulation unless translation requested */ -static bool translate = 1; +static int translate = 1; static int country = USA; @@ -178,7 +178,7 @@ module_param(hop_dwell, int, 0); module_param(beacon_period, int, 0); module_param(psm, int, 0); module_param(essid, charp, 0); -module_param(translate, bool, 0); +module_param(translate, int, 0); module_param(country, int, 0); module_param(sniffer, int, 0); module_param(bc, int, 0); @@ -1353,7 +1353,7 @@ static int ray_get_range(struct net_device *dev, struct iw_request_info *info, static int ray_set_framing(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { - translate = !!*(extra); /* Set framing mode */ + translate = *(extra); /* Set framing mode */ return 0; } diff --git a/trunk/drivers/net/wireless/rndis_wlan.c b/trunk/drivers/net/wireless/rndis_wlan.c index 5f66b4eac298..525fd7521dff 100644 --- a/trunk/drivers/net/wireless/rndis_wlan.c +++ b/trunk/drivers/net/wireless/rndis_wlan.c @@ -2839,7 +2839,8 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev) } else if (priv->infra_mode == NDIS_80211_INFRA_ADHOC) cfg80211_ibss_joined(usbdev->net, bssid, GFP_KERNEL); - kfree(info); + if (info != NULL) + kfree(info); priv->connected = true; memcpy(priv->bssid, bssid, ETH_ALEN); diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00pci.c b/trunk/drivers/net/wireless/rt2x00/rt2x00pci.c index b1c673ecada1..a0c8caef3b0a 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -52,8 +52,8 @@ int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev, udelay(REGISTER_BUSY_DELAY); } - printk_once(KERN_ERR "%s() Indirect register access failed: " - "offset=0x%.08x, value=0x%.08x\n", __func__, offset, *reg); + ERROR(rt2x00dev, "Indirect register access failed: " + "offset=0x%.08x, value=0x%.08x\n", offset, *reg); *reg = ~0; return 0; diff --git a/trunk/drivers/net/wireless/rtlwifi/wifi.h b/trunk/drivers/net/wireless/rtlwifi/wifi.h index c3eff32acf6c..f13258a8d995 100644 --- a/trunk/drivers/net/wireless/rtlwifi/wifi.h +++ b/trunk/drivers/net/wireless/rtlwifi/wifi.h @@ -2127,6 +2127,9 @@ value to host byte ordering.*/ #define WLAN_FC_GET_TYPE(fc) (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) #define WLAN_FC_GET_STYPE(fc) (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) #define WLAN_FC_MORE_DATA(fc) (le16_to_cpu(fc) & IEEE80211_FCTL_MOREDATA) +#define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4) +#define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ) +#define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4) #define RT_RF_OFF_LEVL_ASPM BIT(0) /*PCI ASPM */ #define RT_RF_OFF_LEVL_CLK_REQ BIT(1) /*PCI clock request */ diff --git a/trunk/drivers/net/wireless/ti/wlcore/main.c b/trunk/drivers/net/wireless/ti/wlcore/main.c index d7e306333f6c..2c2ff3e1f849 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/main.c +++ b/trunk/drivers/net/wireless/ti/wlcore/main.c @@ -4956,8 +4956,7 @@ static void wlcore_op_flush(struct ieee80211_hw *hw, bool drop) static int wlcore_op_remain_on_channel(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_channel *chan, - int duration, - enum ieee80211_roc_type type) + int duration) { struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); struct wl1271 *wl = hw->priv; diff --git a/trunk/drivers/ssb/driver_chipcommon.c b/trunk/drivers/ssb/driver_chipcommon.c index 7cb7d2c8fd86..71098a7b5fed 100644 --- a/trunk/drivers/ssb/driver_chipcommon.c +++ b/trunk/drivers/ssb/driver_chipcommon.c @@ -354,7 +354,7 @@ void ssb_chipcommon_init(struct ssb_chipcommon *cc) if (cc->dev->id.revision >= 11) cc->status = chipco_read32(cc, SSB_CHIPCO_CHIPSTAT); - ssb_dbg("chipcommon status is 0x%x\n", cc->status); + ssb_dprintk(KERN_INFO PFX "chipcommon status is 0x%x\n", cc->status); if (cc->dev->id.revision >= 20) { chipco_write32(cc, SSB_CHIPCO_GPIOPULLUP, 0); diff --git a/trunk/drivers/ssb/driver_chipcommon_pmu.c b/trunk/drivers/ssb/driver_chipcommon_pmu.c index 791da2c0d8f6..4c0f6d883dd3 100644 --- a/trunk/drivers/ssb/driver_chipcommon_pmu.c +++ b/trunk/drivers/ssb/driver_chipcommon_pmu.c @@ -110,8 +110,8 @@ static void ssb_pmu0_pllinit_r0(struct ssb_chipcommon *cc, return; } - ssb_info("Programming PLL to %u.%03u MHz\n", - crystalfreq / 1000, crystalfreq % 1000); + ssb_printk(KERN_INFO PFX "Programming PLL to %u.%03u MHz\n", + (crystalfreq / 1000), (crystalfreq % 1000)); /* First turn the PLL off. */ switch (bus->chip_id) { @@ -138,7 +138,7 @@ static void ssb_pmu0_pllinit_r0(struct ssb_chipcommon *cc, } tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST); if (tmp & SSB_CHIPCO_CLKCTLST_HAVEHT) - ssb_emerg("Failed to turn the PLL off!\n"); + ssb_printk(KERN_EMERG PFX "Failed to turn the PLL off!\n"); /* Set PDIV in PLL control 0. */ pllctl = ssb_chipco_pll_read(cc, SSB_PMU0_PLLCTL0); @@ -249,8 +249,8 @@ static void ssb_pmu1_pllinit_r0(struct ssb_chipcommon *cc, return; } - ssb_info("Programming PLL to %u.%03u MHz\n", - crystalfreq / 1000, crystalfreq % 1000); + ssb_printk(KERN_INFO PFX "Programming PLL to %u.%03u MHz\n", + (crystalfreq / 1000), (crystalfreq % 1000)); /* First turn the PLL off. */ switch (bus->chip_id) { @@ -275,7 +275,7 @@ static void ssb_pmu1_pllinit_r0(struct ssb_chipcommon *cc, } tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST); if (tmp & SSB_CHIPCO_CLKCTLST_HAVEHT) - ssb_emerg("Failed to turn the PLL off!\n"); + ssb_printk(KERN_EMERG PFX "Failed to turn the PLL off!\n"); /* Set p1div and p2div. */ pllctl = ssb_chipco_pll_read(cc, SSB_PMU1_PLLCTL0); @@ -349,8 +349,9 @@ static void ssb_pmu_pll_init(struct ssb_chipcommon *cc) case 43222: break; default: - ssb_err("ERROR: PLL init unknown for device %04X\n", - bus->chip_id); + ssb_printk(KERN_ERR PFX + "ERROR: PLL init unknown for device %04X\n", + bus->chip_id); } } @@ -471,8 +472,9 @@ static void ssb_pmu_resources_init(struct ssb_chipcommon *cc) max_msk = 0xFFFFF; break; default: - ssb_err("ERROR: PMU resource config unknown for device %04X\n", - bus->chip_id); + ssb_printk(KERN_ERR PFX + "ERROR: PMU resource config unknown for device %04X\n", + bus->chip_id); } if (updown_tab) { @@ -524,8 +526,8 @@ void ssb_pmu_init(struct ssb_chipcommon *cc) pmucap = chipco_read32(cc, SSB_CHIPCO_PMU_CAP); cc->pmu.rev = (pmucap & SSB_CHIPCO_PMU_CAP_REVISION); - ssb_dbg("Found rev %u PMU (capabilities 0x%08X)\n", - cc->pmu.rev, pmucap); + ssb_dprintk(KERN_DEBUG PFX "Found rev %u PMU (capabilities 0x%08X)\n", + cc->pmu.rev, pmucap); if (cc->pmu.rev == 1) chipco_mask32(cc, SSB_CHIPCO_PMU_CTL, @@ -636,8 +638,9 @@ u32 ssb_pmu_get_alp_clock(struct ssb_chipcommon *cc) case 0x5354: ssb_pmu_get_alp_clock_clk0(cc); default: - ssb_err("ERROR: PMU alp clock unknown for device %04X\n", - bus->chip_id); + ssb_printk(KERN_ERR PFX + "ERROR: PMU alp clock unknown for device %04X\n", + bus->chip_id); return 0; } } @@ -651,8 +654,9 @@ u32 ssb_pmu_get_cpu_clock(struct ssb_chipcommon *cc) /* 5354 chip uses a non programmable PLL of frequency 240MHz */ return 240000000; default: - ssb_err("ERROR: PMU cpu clock unknown for device %04X\n", - bus->chip_id); + ssb_printk(KERN_ERR PFX + "ERROR: PMU cpu clock unknown for device %04X\n", + bus->chip_id); return 0; } } @@ -665,8 +669,9 @@ u32 ssb_pmu_get_controlclock(struct ssb_chipcommon *cc) case 0x5354: return 120000000; default: - ssb_err("ERROR: PMU controlclock unknown for device %04X\n", - bus->chip_id); + ssb_printk(KERN_ERR PFX + "ERROR: PMU controlclock unknown for device %04X\n", + bus->chip_id); return 0; } } diff --git a/trunk/drivers/ssb/driver_mipscore.c b/trunk/drivers/ssb/driver_mipscore.c index fa385a368a56..33b37dac40bd 100644 --- a/trunk/drivers/ssb/driver_mipscore.c +++ b/trunk/drivers/ssb/driver_mipscore.c @@ -167,22 +167,21 @@ static void set_irq(struct ssb_device *dev, unsigned int irq) irqflag |= (ipsflag & ~ipsflag_irq_mask[irq]); ssb_write32(mdev, SSB_IPSFLAG, irqflag); } - ssb_dbg("set_irq: core 0x%04x, irq %d => %d\n", - dev->id.coreid, oldirq+2, irq+2); + ssb_dprintk(KERN_INFO PFX + "set_irq: core 0x%04x, irq %d => %d\n", + dev->id.coreid, oldirq+2, irq+2); } static void print_irq(struct ssb_device *dev, unsigned int irq) { + int i; static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"}; - ssb_dbg("core 0x%04x, irq : %s%s %s%s %s%s %s%s %s%s %s%s %s%s\n", - dev->id.coreid, - irq_name[0], irq == 0 ? "*" : " ", - irq_name[1], irq == 1 ? "*" : " ", - irq_name[2], irq == 2 ? "*" : " ", - irq_name[3], irq == 3 ? "*" : " ", - irq_name[4], irq == 4 ? "*" : " ", - irq_name[5], irq == 5 ? "*" : " ", - irq_name[6], irq == 6 ? "*" : " "); + ssb_dprintk(KERN_INFO PFX + "core 0x%04x, irq :", dev->id.coreid); + for (i = 0; i <= 6; i++) { + ssb_dprintk(" %s%s", irq_name[i], i==irq?"*":" "); + } + ssb_dprintk("\n"); } static void dump_irq(struct ssb_bus *bus) @@ -287,7 +286,7 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore) if (!mcore->dev) return; /* We don't have a MIPS core */ - ssb_dbg("Initializing MIPS core...\n"); + ssb_dprintk(KERN_INFO PFX "Initializing MIPS core...\n"); bus = mcore->dev->bus; hz = ssb_clockspeed(bus); @@ -335,7 +334,7 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore) break; } } - ssb_dbg("after irq reconfiguration\n"); + ssb_dprintk(KERN_INFO PFX "after irq reconfiguration\n"); dump_irq(bus); ssb_mips_serial_init(mcore); diff --git a/trunk/drivers/ssb/driver_pcicore.c b/trunk/drivers/ssb/driver_pcicore.c index d75b72ba2672..59801d23d7ec 100644 --- a/trunk/drivers/ssb/driver_pcicore.c +++ b/trunk/drivers/ssb/driver_pcicore.c @@ -263,7 +263,8 @@ int ssb_pcicore_plat_dev_init(struct pci_dev *d) return -ENODEV; } - ssb_info("PCI: Fixing up device %s\n", pci_name(d)); + ssb_printk(KERN_INFO "PCI: Fixing up device %s\n", + pci_name(d)); /* Fix up interrupt lines */ d->irq = ssb_mips_irq(extpci_core->dev) + 2; @@ -284,12 +285,12 @@ static void ssb_pcicore_fixup_pcibridge(struct pci_dev *dev) if (dev->bus->number != 0 || PCI_SLOT(dev->devfn) != 0) return; - ssb_info("PCI: Fixing up bridge %s\n", pci_name(dev)); + ssb_printk(KERN_INFO "PCI: Fixing up bridge %s\n", pci_name(dev)); /* Enable PCI bridge bus mastering and memory space */ pci_set_master(dev); if (pcibios_enable_device(dev, ~0) < 0) { - ssb_err("PCI: SSB bridge enable failed\n"); + ssb_printk(KERN_ERR "PCI: SSB bridge enable failed\n"); return; } @@ -298,8 +299,8 @@ static void ssb_pcicore_fixup_pcibridge(struct pci_dev *dev) /* Make sure our latency is high enough to handle the devices behind us */ lat = 168; - ssb_info("PCI: Fixing latency timer of device %s to %u\n", - pci_name(dev), lat); + ssb_printk(KERN_INFO "PCI: Fixing latency timer of device %s to %u\n", + pci_name(dev), lat); pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); } DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, ssb_pcicore_fixup_pcibridge); @@ -322,7 +323,7 @@ static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc) return; extpci_core = pc; - ssb_dbg("PCIcore in host mode found\n"); + ssb_dprintk(KERN_INFO PFX "PCIcore in host mode found\n"); /* Reset devices on the external PCI bus */ val = SSB_PCICORE_CTL_RST_OE; val |= SSB_PCICORE_CTL_CLK_OE; @@ -337,7 +338,7 @@ static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc) udelay(1); /* Assertion time demanded by the PCI standard */ if (pc->dev->bus->has_cardbus_slot) { - ssb_dbg("CardBus slot detected\n"); + ssb_dprintk(KERN_INFO PFX "CardBus slot detected\n"); pc->cardbusmode = 1; /* GPIO 1 resets the bridge */ ssb_gpio_out(pc->dev->bus, 1, 1); diff --git a/trunk/drivers/ssb/embedded.c b/trunk/drivers/ssb/embedded.c index 55e101115038..bb18d76f9f2c 100644 --- a/trunk/drivers/ssb/embedded.c +++ b/trunk/drivers/ssb/embedded.c @@ -57,8 +57,9 @@ int ssb_watchdog_register(struct ssb_bus *bus) bus->busnumber, &wdt, sizeof(wdt)); if (IS_ERR(pdev)) { - ssb_dbg("can not register watchdog device, err: %li\n", - PTR_ERR(pdev)); + ssb_dprintk(KERN_INFO PFX + "can not register watchdog device, err: %li\n", + PTR_ERR(pdev)); return PTR_ERR(pdev); } diff --git a/trunk/drivers/ssb/main.c b/trunk/drivers/ssb/main.c index 812775a4bfb6..3b645b8a261f 100644 --- a/trunk/drivers/ssb/main.c +++ b/trunk/drivers/ssb/main.c @@ -275,8 +275,8 @@ int ssb_devices_thaw(struct ssb_freeze_context *ctx) err = sdrv->probe(sdev, &sdev->id); if (err) { - ssb_err("Failed to thaw device %s\n", - dev_name(sdev->dev)); + ssb_printk(KERN_ERR PFX "Failed to thaw device %s\n", + dev_name(sdev->dev)); result = err; } ssb_device_put(sdev); @@ -447,9 +447,10 @@ void ssb_bus_unregister(struct ssb_bus *bus) err = ssb_gpio_unregister(bus); if (err == -EBUSY) - ssb_dbg("Some GPIOs are still in use\n"); + ssb_dprintk(KERN_ERR PFX "Some GPIOs are still in use.\n"); else if (err) - ssb_dbg("Can not unregister GPIO driver: %i\n", err); + ssb_dprintk(KERN_ERR PFX + "Can not unregister GPIO driver: %i\n", err); ssb_buses_lock(); ssb_devices_unregister(bus); @@ -496,7 +497,8 @@ static int ssb_devices_register(struct ssb_bus *bus) devwrap = kzalloc(sizeof(*devwrap), GFP_KERNEL); if (!devwrap) { - ssb_err("Could not allocate device\n"); + ssb_printk(KERN_ERR PFX + "Could not allocate device\n"); err = -ENOMEM; goto error; } @@ -535,7 +537,9 @@ static int ssb_devices_register(struct ssb_bus *bus) sdev->dev = dev; err = device_register(dev); if (err) { - ssb_err("Could not register %s\n", dev_name(dev)); + ssb_printk(KERN_ERR PFX + "Could not register %s\n", + dev_name(dev)); /* Set dev to NULL to not unregister * dev on error unwinding. */ sdev->dev = NULL; @@ -821,9 +825,10 @@ static int ssb_bus_register(struct ssb_bus *bus, ssb_mipscore_init(&bus->mipscore); err = ssb_gpio_init(bus); if (err == -ENOTSUPP) - ssb_dbg("GPIO driver not activated\n"); + ssb_dprintk(KERN_DEBUG PFX "GPIO driver not activated\n"); else if (err) - ssb_dbg("Error registering GPIO driver: %i\n", err); + ssb_dprintk(KERN_ERR PFX + "Error registering GPIO driver: %i\n", err); err = ssb_fetch_invariants(bus, get_invariants); if (err) { ssb_bus_may_powerdown(bus); @@ -873,11 +878,11 @@ int ssb_bus_pcibus_register(struct ssb_bus *bus, struct pci_dev *host_pci) err = ssb_bus_register(bus, ssb_pci_get_invariants, 0); if (!err) { - ssb_info("Sonics Silicon Backplane found on PCI device %s\n", - dev_name(&host_pci->dev)); + ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane found on " + "PCI device %s\n", dev_name(&host_pci->dev)); } else { - ssb_err("Failed to register PCI version of SSB with error %d\n", - err); + ssb_printk(KERN_ERR PFX "Failed to register PCI version" + " of SSB with error %d\n", err); } return err; @@ -898,8 +903,8 @@ int ssb_bus_pcmciabus_register(struct ssb_bus *bus, err = ssb_bus_register(bus, ssb_pcmcia_get_invariants, baseaddr); if (!err) { - ssb_info("Sonics Silicon Backplane found on PCMCIA device %s\n", - pcmcia_dev->devname); + ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane found on " + "PCMCIA device %s\n", pcmcia_dev->devname); } return err; @@ -920,8 +925,8 @@ int ssb_bus_sdiobus_register(struct ssb_bus *bus, struct sdio_func *func, err = ssb_bus_register(bus, ssb_sdio_get_invariants, ~0); if (!err) { - ssb_info("Sonics Silicon Backplane found on SDIO device %s\n", - sdio_func_id(func)); + ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane found on " + "SDIO device %s\n", sdio_func_id(func)); } return err; @@ -939,8 +944,8 @@ int ssb_bus_ssbbus_register(struct ssb_bus *bus, unsigned long baseaddr, err = ssb_bus_register(bus, get_invariants, baseaddr); if (!err) { - ssb_info("Sonics Silicon Backplane found at address 0x%08lX\n", - baseaddr); + ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane found at " + "address 0x%08lX\n", baseaddr); } return err; @@ -1334,7 +1339,7 @@ int ssb_bus_may_powerdown(struct ssb_bus *bus) #endif return err; error: - ssb_err("Bus powerdown failed\n"); + ssb_printk(KERN_ERR PFX "Bus powerdown failed\n"); goto out; } EXPORT_SYMBOL(ssb_bus_may_powerdown); @@ -1357,7 +1362,7 @@ int ssb_bus_powerup(struct ssb_bus *bus, bool dynamic_pctl) return 0; error: - ssb_err("Bus powerup failed\n"); + ssb_printk(KERN_ERR PFX "Bus powerup failed\n"); return err; } EXPORT_SYMBOL(ssb_bus_powerup); @@ -1465,13 +1470,15 @@ static int __init ssb_modinit(void) err = b43_pci_ssb_bridge_init(); if (err) { - ssb_err("Broadcom 43xx PCI-SSB-bridge initialization failed\n"); + ssb_printk(KERN_ERR "Broadcom 43xx PCI-SSB-bridge " + "initialization failed\n"); /* don't fail SSB init because of this */ err = 0; } err = ssb_gige_init(); if (err) { - ssb_err("SSB Broadcom Gigabit Ethernet driver initialization failed\n"); + ssb_printk(KERN_ERR "SSB Broadcom Gigabit Ethernet " + "driver initialization failed\n"); /* don't fail SSB init because of this */ err = 0; } diff --git a/trunk/drivers/ssb/pci.c b/trunk/drivers/ssb/pci.c index 6d6e7b926aa5..e9d94968f394 100644 --- a/trunk/drivers/ssb/pci.c +++ b/trunk/drivers/ssb/pci.c @@ -56,7 +56,7 @@ int ssb_pci_switch_coreidx(struct ssb_bus *bus, u8 coreidx) } return 0; error: - ssb_err("Failed to switch to core %u\n", coreidx); + ssb_printk(KERN_ERR PFX "Failed to switch to core %u\n", coreidx); return -ENODEV; } @@ -67,9 +67,10 @@ int ssb_pci_switch_core(struct ssb_bus *bus, unsigned long flags; #if SSB_VERBOSE_PCICORESWITCH_DEBUG - ssb_info("Switching to %s core, index %d\n", - ssb_core_name(dev->id.coreid), - dev->core_index); + ssb_printk(KERN_INFO PFX + "Switching to %s core, index %d\n", + ssb_core_name(dev->id.coreid), + dev->core_index); #endif spin_lock_irqsave(&bus->bar_lock, flags); @@ -230,15 +231,6 @@ static inline u8 ssb_crc8(u8 crc, u8 data) return t[crc ^ data]; } -static void sprom_get_mac(char *mac, const u16 *in) -{ - int i; - for (i = 0; i < 3; i++) { - *mac++ = in[i]; - *mac++ = in[i] >> 8; - } -} - static u8 ssb_sprom_crc(const u16 *sprom, u16 size) { int word; @@ -286,7 +278,7 @@ static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom) u32 spromctl; u16 size = bus->sprom_size; - ssb_notice("Writing SPROM. Do NOT turn off the power! Please stand by...\n"); + ssb_printk(KERN_NOTICE PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n"); err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl); if (err) goto err_ctlreg; @@ -294,17 +286,17 @@ static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom) err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl); if (err) goto err_ctlreg; - ssb_notice("[ 0%%"); + ssb_printk(KERN_NOTICE PFX "[ 0%%"); msleep(500); for (i = 0; i < size; i++) { if (i == size / 4) - ssb_cont("25%%"); + ssb_printk("25%%"); else if (i == size / 2) - ssb_cont("50%%"); + ssb_printk("50%%"); else if (i == (size * 3) / 4) - ssb_cont("75%%"); + ssb_printk("75%%"); else if (i % 2) - ssb_cont("."); + ssb_printk("."); writew(sprom[i], bus->mmio + bus->sprom_offset + (i * 2)); mmiowb(); msleep(20); @@ -317,12 +309,12 @@ static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom) if (err) goto err_ctlreg; msleep(500); - ssb_cont("100%% ]\n"); - ssb_notice("SPROM written\n"); + ssb_printk("100%% ]\n"); + ssb_printk(KERN_NOTICE PFX "SPROM written.\n"); return 0; err_ctlreg: - ssb_err("Could not access SPROM control register.\n"); + ssb_printk(KERN_ERR PFX "Could not access SPROM control register.\n"); return err; } @@ -349,6 +341,8 @@ static s8 r123_extract_antgain(u8 sprom_revision, const u16 *in, static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) { + int i; + u16 v; u16 loc[3]; if (out->revision == 3) /* rev 3 moved MAC */ @@ -358,10 +352,19 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) loc[1] = SSB_SPROM1_ET0MAC; loc[2] = SSB_SPROM1_ET1MAC; } - sprom_get_mac(out->il0mac, &in[SPOFF(loc[0])]); + for (i = 0; i < 3; i++) { + v = in[SPOFF(loc[0]) + i]; + *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v); + } if (out->revision < 3) { /* only rev 1-2 have et0, et1 */ - sprom_get_mac(out->et0mac, &in[SPOFF(loc[1])]); - sprom_get_mac(out->et1mac, &in[SPOFF(loc[2])]); + for (i = 0; i < 3; i++) { + v = in[SPOFF(loc[1]) + i]; + *(((__be16 *)out->et0mac) + i) = cpu_to_be16(v); + } + for (i = 0; i < 3; i++) { + v = in[SPOFF(loc[2]) + i]; + *(((__be16 *)out->et1mac) + i) = cpu_to_be16(v); + } } SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0); SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A, @@ -451,15 +454,19 @@ static void sprom_extract_r458(struct ssb_sprom *out, const u16 *in) static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in) { + int i; + u16 v; u16 il0mac_offset; if (out->revision == 4) il0mac_offset = SSB_SPROM4_IL0MAC; else il0mac_offset = SSB_SPROM5_IL0MAC; - - sprom_get_mac(out->il0mac, &in[SPOFF(il0mac_offset)]); - + /* extract the MAC address */ + for (i = 0; i < 3; i++) { + v = in[SPOFF(il0mac_offset) + i]; + *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v); + } SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0); SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A, SSB_SPROM4_ETHPHY_ET1A_SHIFT); @@ -523,7 +530,7 @@ static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in) static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in) { int i; - u16 o; + u16 v, o; u16 pwr_info_offset[] = { SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1, SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3 @@ -532,8 +539,10 @@ static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in) ARRAY_SIZE(out->core_pwr_info)); /* extract the MAC address */ - sprom_get_mac(out->il0mac, &in[SPOFF(SSB_SPROM8_IL0MAC)]); - + for (i = 0; i < 3; i++) { + v = in[SPOFF(SSB_SPROM8_IL0MAC) + i]; + *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v); + } SPEX(board_rev, SSB_SPROM8_BOARDREV, 0xFFFF, 0); SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8); SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0); @@ -734,7 +743,7 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out, memset(out, 0, sizeof(*out)); out->revision = in[size - 1] & 0x00FF; - ssb_dbg("SPROM revision %d detected\n", out->revision); + ssb_dprintk(KERN_DEBUG PFX "SPROM revision %d detected.\n", out->revision); memset(out->et0mac, 0xFF, 6); /* preset et0 and et1 mac */ memset(out->et1mac, 0xFF, 6); @@ -743,7 +752,7 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out, * number stored in the SPROM. * Always extract r1. */ out->revision = 1; - ssb_dbg("SPROM treated as revision %d\n", out->revision); + ssb_dprintk(KERN_DEBUG PFX "SPROM treated as revision %d\n", out->revision); } switch (out->revision) { @@ -760,8 +769,9 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out, sprom_extract_r8(out, in); break; default: - ssb_warn("Unsupported SPROM revision %d detected. Will extract v1\n", - out->revision); + ssb_printk(KERN_WARNING PFX "Unsupported SPROM" + " revision %d detected. Will extract" + " v1\n", out->revision); out->revision = 1; sprom_extract_r123(out, in); } @@ -781,7 +791,7 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus, u16 *buf; if (!ssb_is_sprom_available(bus)) { - ssb_err("No SPROM available!\n"); + ssb_printk(KERN_ERR PFX "No SPROM available!\n"); return -ENODEV; } if (bus->chipco.dev) { /* can be unavailable! */ @@ -800,7 +810,7 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus, } else { bus->sprom_offset = SSB_SPROM_BASE1; } - ssb_dbg("SPROM offset is 0x%x\n", bus->sprom_offset); + ssb_dprintk(KERN_INFO PFX "SPROM offset is 0x%x\n", bus->sprom_offset); buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL); if (!buf) @@ -825,15 +835,18 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus, * available for this device in some other storage */ err = ssb_fill_sprom_with_fallback(bus, sprom); if (err) { - ssb_warn("WARNING: Using fallback SPROM failed (err %d)\n", - err); + ssb_printk(KERN_WARNING PFX "WARNING: Using" + " fallback SPROM failed (err %d)\n", + err); } else { - ssb_dbg("Using SPROM revision %d provided by platform\n", - sprom->revision); + ssb_dprintk(KERN_DEBUG PFX "Using SPROM" + " revision %d provided by" + " platform.\n", sprom->revision); err = 0; goto out_free; } - ssb_warn("WARNING: Invalid SPROM CRC (corrupt SPROM)\n"); + ssb_printk(KERN_WARNING PFX "WARNING: Invalid" + " SPROM CRC (corrupt SPROM)\n"); } } err = sprom_extract(bus, sprom, buf, bus->sprom_size); diff --git a/trunk/drivers/ssb/pcmcia.c b/trunk/drivers/ssb/pcmcia.c index b413e0187087..fbafed5b729b 100644 --- a/trunk/drivers/ssb/pcmcia.c +++ b/trunk/drivers/ssb/pcmcia.c @@ -143,7 +143,7 @@ int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus, return 0; error: - ssb_err("Failed to switch to core %u\n", coreidx); + ssb_printk(KERN_ERR PFX "Failed to switch to core %u\n", coreidx); return err; } @@ -153,9 +153,10 @@ int ssb_pcmcia_switch_core(struct ssb_bus *bus, int err; #if SSB_VERBOSE_PCMCIACORESWITCH_DEBUG - ssb_info("Switching to %s core, index %d\n", - ssb_core_name(dev->id.coreid), - dev->core_index); + ssb_printk(KERN_INFO PFX + "Switching to %s core, index %d\n", + ssb_core_name(dev->id.coreid), + dev->core_index); #endif err = ssb_pcmcia_switch_coreidx(bus, dev->core_index); @@ -191,7 +192,7 @@ int ssb_pcmcia_switch_segment(struct ssb_bus *bus, u8 seg) return 0; error: - ssb_err("Failed to switch pcmcia segment\n"); + ssb_printk(KERN_ERR PFX "Failed to switch pcmcia segment\n"); return err; } @@ -548,39 +549,44 @@ static int ssb_pcmcia_sprom_write_all(struct ssb_bus *bus, const u16 *sprom) bool failed = 0; size_t size = SSB_PCMCIA_SPROM_SIZE; - ssb_notice("Writing SPROM. Do NOT turn off the power! Please stand by...\n"); + ssb_printk(KERN_NOTICE PFX + "Writing SPROM. Do NOT turn off the power! " + "Please stand by...\n"); err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEEN); if (err) { - ssb_notice("Could not enable SPROM write access\n"); + ssb_printk(KERN_NOTICE PFX + "Could not enable SPROM write access.\n"); return -EBUSY; } - ssb_notice("[ 0%%"); + ssb_printk(KERN_NOTICE PFX "[ 0%%"); msleep(500); for (i = 0; i < size; i++) { if (i == size / 4) - ssb_cont("25%%"); + ssb_printk("25%%"); else if (i == size / 2) - ssb_cont("50%%"); + ssb_printk("50%%"); else if (i == (size * 3) / 4) - ssb_cont("75%%"); + ssb_printk("75%%"); else if (i % 2) - ssb_cont("."); + ssb_printk("."); err = ssb_pcmcia_sprom_write(bus, i, sprom[i]); if (err) { - ssb_notice("Failed to write to SPROM\n"); + ssb_printk(KERN_NOTICE PFX + "Failed to write to SPROM.\n"); failed = 1; break; } } err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEDIS); if (err) { - ssb_notice("Could not disable SPROM write access\n"); + ssb_printk(KERN_NOTICE PFX + "Could not disable SPROM write access.\n"); failed = 1; } msleep(500); if (!failed) { - ssb_cont("100%% ]\n"); - ssb_notice("SPROM written\n"); + ssb_printk("100%% ]\n"); + ssb_printk(KERN_NOTICE PFX "SPROM written.\n"); } return failed ? -EBUSY : 0; @@ -694,7 +700,7 @@ static int ssb_pcmcia_do_get_invariants(struct pcmcia_device *p_dev, return -ENOSPC; /* continue with next entry */ error: - ssb_err( + ssb_printk(KERN_ERR PFX "PCMCIA: Failed to fetch device invariants: %s\n", error_description); return -ENODEV; @@ -716,7 +722,7 @@ int ssb_pcmcia_get_invariants(struct ssb_bus *bus, res = pcmcia_loop_tuple(bus->host_pcmcia, CISTPL_FUNCE, ssb_pcmcia_get_mac, sprom); if (res != 0) { - ssb_err( + ssb_printk(KERN_ERR PFX "PCMCIA: Failed to fetch MAC address\n"); return -ENODEV; } @@ -727,7 +733,7 @@ int ssb_pcmcia_get_invariants(struct ssb_bus *bus, if ((res == 0) || (res == -ENOSPC)) return 0; - ssb_err( + ssb_printk(KERN_ERR PFX "PCMCIA: Failed to fetch device invariants\n"); return -ENODEV; } @@ -837,6 +843,6 @@ int ssb_pcmcia_init(struct ssb_bus *bus) return 0; error: - ssb_err("Failed to initialize PCMCIA host device\n"); + ssb_printk(KERN_ERR PFX "Failed to initialize PCMCIA host device\n"); return err; } diff --git a/trunk/drivers/ssb/scan.c b/trunk/drivers/ssb/scan.c index b9429df583eb..ab4627cf1114 100644 --- a/trunk/drivers/ssb/scan.c +++ b/trunk/drivers/ssb/scan.c @@ -125,7 +125,8 @@ static u16 pcidev_to_chipid(struct pci_dev *pci_dev) chipid_fallback = 0x4401; break; default: - ssb_err("PCI-ID not in fallback list\n"); + ssb_printk(KERN_ERR PFX + "PCI-ID not in fallback list\n"); } return chipid_fallback; @@ -151,7 +152,8 @@ static u8 chipid_to_nrcores(u16 chipid) case 0x4704: return 9; default: - ssb_err("CHIPID not in nrcores fallback list\n"); + ssb_printk(KERN_ERR PFX + "CHIPID not in nrcores fallback list\n"); } return 1; @@ -318,13 +320,15 @@ int ssb_bus_scan(struct ssb_bus *bus, bus->chip_package = 0; } } - ssb_info("Found chip with id 0x%04X, rev 0x%02X and package 0x%02X\n", - bus->chip_id, bus->chip_rev, bus->chip_package); + ssb_printk(KERN_INFO PFX "Found chip with id 0x%04X, rev 0x%02X and " + "package 0x%02X\n", bus->chip_id, bus->chip_rev, + bus->chip_package); if (!bus->nr_devices) bus->nr_devices = chipid_to_nrcores(bus->chip_id); if (bus->nr_devices > ARRAY_SIZE(bus->devices)) { - ssb_err("More than %d ssb cores found (%d)\n", - SSB_MAX_NR_CORES, bus->nr_devices); + ssb_printk(KERN_ERR PFX + "More than %d ssb cores found (%d)\n", + SSB_MAX_NR_CORES, bus->nr_devices); goto err_unmap; } if (bus->bustype == SSB_BUSTYPE_SSB) { @@ -366,7 +370,8 @@ int ssb_bus_scan(struct ssb_bus *bus, nr_80211_cores++; if (nr_80211_cores > 1) { if (!we_support_multiple_80211_cores(bus)) { - ssb_dbg("Ignoring additional 802.11 core\n"); + ssb_dprintk(KERN_INFO PFX "Ignoring additional " + "802.11 core\n"); continue; } } @@ -374,7 +379,8 @@ int ssb_bus_scan(struct ssb_bus *bus, case SSB_DEV_EXTIF: #ifdef CONFIG_SSB_DRIVER_EXTIF if (bus->extif.dev) { - ssb_warn("WARNING: Multiple EXTIFs found\n"); + ssb_printk(KERN_WARNING PFX + "WARNING: Multiple EXTIFs found\n"); break; } bus->extif.dev = dev; @@ -382,7 +388,8 @@ int ssb_bus_scan(struct ssb_bus *bus, break; case SSB_DEV_CHIPCOMMON: if (bus->chipco.dev) { - ssb_warn("WARNING: Multiple ChipCommon found\n"); + ssb_printk(KERN_WARNING PFX + "WARNING: Multiple ChipCommon found\n"); break; } bus->chipco.dev = dev; @@ -391,7 +398,8 @@ int ssb_bus_scan(struct ssb_bus *bus, case SSB_DEV_MIPS_3302: #ifdef CONFIG_SSB_DRIVER_MIPS if (bus->mipscore.dev) { - ssb_warn("WARNING: Multiple MIPS cores found\n"); + ssb_printk(KERN_WARNING PFX + "WARNING: Multiple MIPS cores found\n"); break; } bus->mipscore.dev = dev; @@ -412,7 +420,8 @@ int ssb_bus_scan(struct ssb_bus *bus, } } if (bus->pcicore.dev) { - ssb_warn("WARNING: Multiple PCI(E) cores found\n"); + ssb_printk(KERN_WARNING PFX + "WARNING: Multiple PCI(E) cores found\n"); break; } bus->pcicore.dev = dev; diff --git a/trunk/drivers/ssb/sprom.c b/trunk/drivers/ssb/sprom.c index a3b23644b0fb..80d366fcf8d3 100644 --- a/trunk/drivers/ssb/sprom.c +++ b/trunk/drivers/ssb/sprom.c @@ -127,13 +127,13 @@ ssize_t ssb_attr_sprom_store(struct ssb_bus *bus, goto out_kfree; err = ssb_devices_freeze(bus, &freeze); if (err) { - ssb_err("SPROM write: Could not freeze all devices\n"); + ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze all devices\n"); goto out_unlock; } res = sprom_write(bus, sprom); err = ssb_devices_thaw(&freeze); if (err) - ssb_err("SPROM write: Could not thaw all devices\n"); + ssb_printk(KERN_ERR PFX "SPROM write: Could not thaw all devices\n"); out_unlock: mutex_unlock(&bus->sprom_mutex); out_kfree: diff --git a/trunk/drivers/ssb/ssb_private.h b/trunk/drivers/ssb/ssb_private.h index 4671f17f09af..466171b77f68 100644 --- a/trunk/drivers/ssb/ssb_private.h +++ b/trunk/drivers/ssb/ssb_private.h @@ -9,27 +9,16 @@ #define PFX "ssb: " #ifdef CONFIG_SSB_SILENT -# define ssb_printk(fmt, ...) \ - do { if (0) printk(fmt, ##__VA_ARGS__); } while (0) +# define ssb_printk(fmt, x...) do { /* nothing */ } while (0) #else -# define ssb_printk(fmt, ...) \ - printk(fmt, ##__VA_ARGS__) +# define ssb_printk printk #endif /* CONFIG_SSB_SILENT */ -#define ssb_emerg(fmt, ...) ssb_printk(KERN_EMERG PFX fmt, ##__VA_ARGS__) -#define ssb_err(fmt, ...) ssb_printk(KERN_ERR PFX fmt, ##__VA_ARGS__) -#define ssb_warn(fmt, ...) ssb_printk(KERN_WARNING PFX fmt, ##__VA_ARGS__) -#define ssb_notice(fmt, ...) ssb_printk(KERN_NOTICE PFX fmt, ##__VA_ARGS__) -#define ssb_info(fmt, ...) ssb_printk(KERN_INFO PFX fmt, ##__VA_ARGS__) -#define ssb_cont(fmt, ...) ssb_printk(KERN_CONT fmt, ##__VA_ARGS__) - /* dprintk: Debugging printk; vanishes for non-debug compilation */ #ifdef CONFIG_SSB_DEBUG -# define ssb_dbg(fmt, ...) \ - ssb_printk(KERN_DEBUG PFX fmt, ##__VA_ARGS__) +# define ssb_dprintk(fmt, x...) ssb_printk(fmt , ##x) #else -# define ssb_dbg(fmt, ...) \ - do { if (0) printk(KERN_DEBUG PFX fmt, ##__VA_ARGS__); } while (0) +# define ssb_dprintk(fmt, x...) do { /* nothing */ } while (0) #endif #ifdef CONFIG_SSB_DEBUG diff --git a/trunk/include/linux/ieee80211.h b/trunk/include/linux/ieee80211.h index 4cf0c9e4dd99..7e24fe0cfbcd 100644 --- a/trunk/include/linux/ieee80211.h +++ b/trunk/include/linux/ieee80211.h @@ -113,34 +113,6 @@ #define IEEE80211_CTL_EXT_SSW_FBACK 0x9000 #define IEEE80211_CTL_EXT_SSW_ACK 0xa000 - -#define IEEE80211_SN_MASK ((IEEE80211_SCTL_SEQ) >> 4) -#define IEEE80211_MAX_SN IEEE80211_SN_MASK -#define IEEE80211_SN_MODULO (IEEE80211_MAX_SN + 1) - -static inline int ieee80211_sn_less(u16 sn1, u16 sn2) -{ - return ((sn1 - sn2) & IEEE80211_SN_MASK) > (IEEE80211_SN_MODULO >> 1); -} - -static inline u16 ieee80211_sn_add(u16 sn1, u16 sn2) -{ - return (sn1 + sn2) & IEEE80211_SN_MASK; -} - -static inline u16 ieee80211_sn_inc(u16 sn) -{ - return ieee80211_sn_add(sn, 1); -} - -static inline u16 ieee80211_sn_sub(u16 sn1, u16 sn2) -{ - return (sn1 - sn2) & IEEE80211_SN_MASK; -} - -#define IEEE80211_SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4) -#define IEEE80211_SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ) - /* miscellaneous IEEE 802.11 constants */ #define IEEE80211_MAX_FRAG_THRESHOLD 2352 #define IEEE80211_MAX_RTS_THRESHOLD 2353 @@ -213,7 +185,7 @@ struct ieee80211_hdr { u8 addr3[6]; __le16 seq_ctrl; u8 addr4[6]; -} __packed __aligned(2); +} __packed; struct ieee80211_hdr_3addr { __le16 frame_control; @@ -222,7 +194,7 @@ struct ieee80211_hdr_3addr { u8 addr2[6]; u8 addr3[6]; __le16 seq_ctrl; -} __packed __aligned(2); +} __packed; struct ieee80211_qos_hdr { __le16 frame_control; @@ -232,7 +204,7 @@ struct ieee80211_qos_hdr { u8 addr3[6]; __le16 seq_ctrl; __le16 qos_ctrl; -} __packed __aligned(2); +} __packed; /** * ieee80211_has_tods - check if IEEE80211_FCTL_TODS is set @@ -609,7 +581,7 @@ struct ieee80211s_hdr { __le32 seqnum; u8 eaddr1[6]; u8 eaddr2[6]; -} __packed __aligned(2); +} __packed; /* Mesh flags */ #define MESH_FLAGS_AE_A4 0x1 @@ -903,7 +875,7 @@ struct ieee80211_mgmt { } u; } __packed action; } u; -} __packed __aligned(2); +} __packed; /* Supported Rates value encodings in 802.11n-2009 7.3.2.2 */ #define BSS_MEMBERSHIP_SELECTOR_HT_PHY 127 @@ -934,20 +906,20 @@ struct ieee80211_rts { __le16 duration; u8 ra[6]; u8 ta[6]; -} __packed __aligned(2); +} __packed; struct ieee80211_cts { __le16 frame_control; __le16 duration; u8 ra[6]; -} __packed __aligned(2); +} __packed; struct ieee80211_pspoll { __le16 frame_control; __le16 aid; u8 bssid[6]; u8 ta[6]; -} __packed __aligned(2); +} __packed; /* TDLS */ @@ -1318,6 +1290,11 @@ struct ieee80211_vht_operation { } __packed; +#define IEEE80211_VHT_MCS_ZERO_TO_SEVEN_SUPPORT 0 +#define IEEE80211_VHT_MCS_ZERO_TO_EIGHT_SUPPORT 1 +#define IEEE80211_VHT_MCS_ZERO_TO_NINE_SUPPORT 2 +#define IEEE80211_VHT_MCS_NOT_SUPPORTED 3 + /* 802.11ac VHT Capabilities */ #define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 0x00000000 #define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 0x00000001 @@ -1333,11 +1310,10 @@ struct ieee80211_vht_operation { #define IEEE80211_VHT_CAP_RXSTBC_2 0x00000200 #define IEEE80211_VHT_CAP_RXSTBC_3 0x00000300 #define IEEE80211_VHT_CAP_RXSTBC_4 0x00000400 -#define IEEE80211_VHT_CAP_RXSTBC_MASK 0x00000700 #define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE 0x00000800 #define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE 0x00001000 #define IEEE80211_VHT_CAP_BEAMFORMER_ANTENNAS_MAX 0x00006000 -#define IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MAX 0x00030000 +#define IEEE80211_VHT_CAP_SOUNDING_DIMENTION_MAX 0x00030000 #define IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE 0x00080000 #define IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE 0x00100000 #define IEEE80211_VHT_CAP_VHT_TXOP_PS 0x00200000 diff --git a/trunk/include/linux/ssb/ssb.h b/trunk/include/linux/ssb/ssb.h index 8b1322296fed..22958d68ecfe 100644 --- a/trunk/include/linux/ssb/ssb.h +++ b/trunk/include/linux/ssb/ssb.h @@ -26,9 +26,9 @@ struct ssb_sprom_core_pwr_info { struct ssb_sprom { u8 revision; - u8 il0mac[6] __aligned(sizeof(u16)); /* MAC address for 802.11b/g */ - u8 et0mac[6] __aligned(sizeof(u16)); /* MAC address for Ethernet */ - u8 et1mac[6] __aligned(sizeof(u16)); /* MAC address for 802.11a */ + u8 il0mac[6]; /* MAC address for 802.11b/g */ + u8 et0mac[6]; /* MAC address for Ethernet */ + u8 et1mac[6]; /* MAC address for 802.11a */ u8 et0phyaddr; /* MII address for enet0 */ u8 et1phyaddr; /* MII address for enet1 */ u8 et0mdcport; /* MDIO for enet0 */ diff --git a/trunk/include/net/cfg80211.h b/trunk/include/net/cfg80211.h index bdba9b619064..d581c6de5d64 100644 --- a/trunk/include/net/cfg80211.h +++ b/trunk/include/net/cfg80211.h @@ -610,11 +610,23 @@ struct cfg80211_ap_settings { bool radar_required; }; +/** + * enum plink_action - actions to perform in mesh peers + * + * @PLINK_ACTION_INVALID: action 0 is reserved + * @PLINK_ACTION_OPEN: start mesh peer link establishment + * @PLINK_ACTION_BLOCK: block traffic from this mesh peer + */ +enum plink_actions { + PLINK_ACTION_INVALID, + PLINK_ACTION_OPEN, + PLINK_ACTION_BLOCK, +}; + /** * enum station_parameters_apply_mask - station parameter values to apply * @STATION_PARAM_APPLY_UAPSD: apply new uAPSD parameters (uapsd_queues, max_sp) * @STATION_PARAM_APPLY_CAPABILITY: apply new capability - * @STATION_PARAM_APPLY_PLINK_STATE: apply new plink state * * Not all station parameters have in-band "no change" signalling, * for those that don't these flags will are used. @@ -622,7 +634,6 @@ struct cfg80211_ap_settings { enum station_parameters_apply_mask { STATION_PARAM_APPLY_UAPSD = BIT(0), STATION_PARAM_APPLY_CAPABILITY = BIT(1), - STATION_PARAM_APPLY_PLINK_STATE = BIT(2), }; /** @@ -658,7 +669,7 @@ enum station_parameters_apply_mask { * @ext_capab_len: number of extended capabilities */ struct station_parameters { - const u8 *supported_rates; + u8 *supported_rates; struct net_device *vlan; u32 sta_flags_mask, sta_flags_set; u32 sta_modify_mask; @@ -667,59 +678,16 @@ struct station_parameters { u8 supported_rates_len; u8 plink_action; u8 plink_state; - const struct ieee80211_ht_cap *ht_capa; - const struct ieee80211_vht_cap *vht_capa; + struct ieee80211_ht_cap *ht_capa; + struct ieee80211_vht_cap *vht_capa; u8 uapsd_queues; u8 max_sp; enum nl80211_mesh_power_mode local_pm; u16 capability; - const u8 *ext_capab; + u8 *ext_capab; u8 ext_capab_len; }; -/** - * enum cfg80211_station_type - the type of station being modified - * @CFG80211_STA_AP_CLIENT: client of an AP interface - * @CFG80211_STA_AP_MLME_CLIENT: client of an AP interface that has - * the AP MLME in the device - * @CFG80211_STA_AP_STA: AP station on managed interface - * @CFG80211_STA_IBSS: IBSS station - * @CFG80211_STA_TDLS_PEER_SETUP: TDLS peer on managed interface (dummy entry - * while TDLS setup is in progress, it moves out of this state when - * being marked authorized; use this only if TDLS with external setup is - * supported/used) - * @CFG80211_STA_TDLS_PEER_ACTIVE: TDLS peer on managed interface (active - * entry that is operating, has been marked authorized by userspace) - * @CFG80211_STA_MESH_PEER_KERNEL: peer on mesh interface (kernel managed) - * @CFG80211_STA_MESH_PEER_USER: peer on mesh interface (user managed) - */ -enum cfg80211_station_type { - CFG80211_STA_AP_CLIENT, - CFG80211_STA_AP_MLME_CLIENT, - CFG80211_STA_AP_STA, - CFG80211_STA_IBSS, - CFG80211_STA_TDLS_PEER_SETUP, - CFG80211_STA_TDLS_PEER_ACTIVE, - CFG80211_STA_MESH_PEER_KERNEL, - CFG80211_STA_MESH_PEER_USER, -}; - -/** - * cfg80211_check_station_change - validate parameter changes - * @wiphy: the wiphy this operates on - * @params: the new parameters for a station - * @statype: the type of station being modified - * - * Utility function for the @change_station driver method. Call this function - * with the appropriate station type looking up the station (and checking that - * it exists). It will verify whether the station change is acceptable, and if - * not will return an error code. Note that it may modify the parameters for - * backward compatibility reasons, so don't use them before calling this. - */ -int cfg80211_check_station_change(struct wiphy *wiphy, - struct station_parameters *params, - enum cfg80211_station_type statype); - /** * enum station_info_flags - station information flags * @@ -1151,7 +1119,6 @@ struct mesh_config { * @ie_len: length of vendor information elements * @is_authenticated: this mesh requires authentication * @is_secure: this mesh uses security - * @user_mpm: userspace handles all MPM functions * @dtim_period: DTIM period to use * @beacon_interval: beacon interval to use * @mcast_rate: multicat rate for Mesh Node [6Mbps is the default for 802.11a] @@ -1169,7 +1136,6 @@ struct mesh_setup { u8 ie_len; bool is_authenticated; bool is_secure; - bool user_mpm; u8 dtim_period; u16 beacon_interval; int mcast_rate[IEEE80211_NUM_BANDS]; @@ -1432,11 +1398,9 @@ struct cfg80211_auth_request { * enum cfg80211_assoc_req_flags - Over-ride default behaviour in association. * * @ASSOC_REQ_DISABLE_HT: Disable HT (802.11n) - * @ASSOC_REQ_DISABLE_VHT: Disable VHT */ enum cfg80211_assoc_req_flags { ASSOC_REQ_DISABLE_HT = BIT(0), - ASSOC_REQ_DISABLE_VHT = BIT(1), }; /** @@ -1458,8 +1422,6 @@ enum cfg80211_assoc_req_flags { * @ht_capa: HT Capabilities over-rides. Values set in ht_capa_mask * will be used in ht_capa. Un-supported values will be ignored. * @ht_capa_mask: The bits of ht_capa which are to be used. - * @vht_capa: VHT capability override - * @vht_capa_mask: VHT capability mask indicating which fields to use */ struct cfg80211_assoc_request { struct cfg80211_bss *bss; @@ -1470,7 +1432,6 @@ struct cfg80211_assoc_request { u32 flags; struct ieee80211_ht_cap ht_capa; struct ieee80211_ht_cap ht_capa_mask; - struct ieee80211_vht_cap vht_capa, vht_capa_mask; }; /** @@ -1581,8 +1542,6 @@ struct cfg80211_ibss_params { * @ht_capa: HT Capabilities over-rides. Values set in ht_capa_mask * will be used in ht_capa. Un-supported values will be ignored. * @ht_capa_mask: The bits of ht_capa which are to be used. - * @vht_capa: VHT Capability overrides - * @vht_capa_mask: The bits of vht_capa which are to be used. */ struct cfg80211_connect_params { struct ieee80211_channel *channel; @@ -1601,8 +1560,6 @@ struct cfg80211_connect_params { int bg_scan_period; struct ieee80211_ht_cap ht_capa; struct ieee80211_ht_cap ht_capa_mask; - struct ieee80211_vht_cap vht_capa; - struct ieee80211_vht_cap vht_capa_mask; }; /** @@ -1764,21 +1721,6 @@ struct cfg80211_gtk_rekey_data { u8 replay_ctr[NL80211_REPLAY_CTR_LEN]; }; -/** - * struct cfg80211_update_ft_ies_params - FT IE Information - * - * This structure provides information needed to update the fast transition IE - * - * @md: The Mobility Domain ID, 2 Octet value - * @ie: Fast Transition IEs - * @ie_len: Length of ft_ie in octets - */ -struct cfg80211_update_ft_ies_params { - u16 md; - const u8 *ie; - size_t ie_len; -}; - /** * struct cfg80211_ops - backend description for wireless configuration * @@ -1839,8 +1781,9 @@ struct cfg80211_update_ft_ies_params { * @change_station: Modify a given station. Note that flags changes are not much * validated in cfg80211, in particular the auth/assoc/authorized flags * might come to the driver in invalid combinations -- make sure to check - * them, also against the existing state! Drivers must call - * cfg80211_check_station_change() to validate the information. + * them, also against the existing state! Also, supported_rates changes are + * not checked in station mode -- drivers need to reject (or ignore) them + * for anything but TDLS peers. * @get_station: get station information for the station identified by @mac * @dump_station: dump station callback -- resume dump at index @idx * @@ -2225,8 +2168,6 @@ struct cfg80211_ops { int (*start_radar_detection)(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_chan_def *chandef); - int (*update_ft_ies)(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_update_ft_ies_params *ftie); }; /* @@ -2544,8 +2485,6 @@ struct wiphy_wowlan_support { * @ap_sme_capa: AP SME capabilities, flags from &enum nl80211_ap_sme_features. * @ht_capa_mod_mask: Specify what ht_cap values can be over-ridden. * If null, then none can be over-ridden. - * @vht_capa_mod_mask: Specify what VHT capabilities can be over-ridden. - * If null, then none can be over-ridden. * * @max_acl_mac_addrs: Maximum number of MAC addresses that the device * supports for ACL. @@ -2654,7 +2593,6 @@ struct wiphy { struct dentry *debugfsdir; const struct ieee80211_ht_cap *ht_capa_mod_mask; - const struct ieee80211_vht_cap *vht_capa_mod_mask; #ifdef CONFIG_NET_NS /* the network namespace this phy lives in currently */ @@ -4063,30 +4001,6 @@ u32 cfg80211_calculate_bitrate(struct rate_info *rate); */ void cfg80211_unregister_wdev(struct wireless_dev *wdev); -/** - * struct cfg80211_ft_event - FT Information Elements - * @ies: FT IEs - * @ies_len: length of the FT IE in bytes - * @target_ap: target AP's MAC address - * @ric_ies: RIC IE - * @ric_ies_len: length of the RIC IE in bytes - */ -struct cfg80211_ft_event_params { - const u8 *ies; - size_t ies_len; - const u8 *target_ap; - const u8 *ric_ies; - size_t ric_ies_len; -}; - -/** - * cfg80211_ft_event - notify userspace about FT IE and RIC IE - * @netdev: network device - * @ft_event: IE information - */ -void cfg80211_ft_event(struct net_device *netdev, - struct cfg80211_ft_event_params *ft_event); - /** * cfg80211_get_p2p_attr - find and copy a P2P attribute from IE buffer * @ies: the input IE buffer diff --git a/trunk/include/net/mac80211.h b/trunk/include/net/mac80211.h index cdd7cea1fd4c..f7eba1300d82 100644 --- a/trunk/include/net/mac80211.h +++ b/trunk/include/net/mac80211.h @@ -1101,6 +1101,8 @@ static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif) * These flags are used for communication about keys between the driver * and mac80211, with the @flags parameter of &struct ieee80211_key_conf. * + * @IEEE80211_KEY_FLAG_WMM_STA: Set by mac80211, this flag indicates + * that the STA this key will be used with could be using QoS. * @IEEE80211_KEY_FLAG_GENERATE_IV: This flag should be set by the * driver to indicate that it requires IV generation for this * particular key. @@ -1125,6 +1127,7 @@ static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif) * %IEEE80211_KEY_FLAG_SW_MGMT_TX flag to encrypt such frames in SW. */ enum ieee80211_key_flags { + IEEE80211_KEY_FLAG_WMM_STA = 1<<0, IEEE80211_KEY_FLAG_GENERATE_IV = 1<<1, IEEE80211_KEY_FLAG_GENERATE_MMIC= 1<<2, IEEE80211_KEY_FLAG_PAIRWISE = 1<<3, @@ -1228,8 +1231,9 @@ enum ieee80211_sta_rx_bandwidth { * @addr: MAC address * @aid: AID we assigned to the station if we're an AP * @supp_rates: Bitmap of supported rates (per band) - * @ht_cap: HT capabilities of this STA; restricted to our own capabilities - * @vht_cap: VHT capabilities of this STA; restricted to our own capabilities + * @ht_cap: HT capabilities of this STA; restricted to our own TX capabilities + * @vht_cap: VHT capabilities of this STA; Not restricting any capabilities + * of remote STA. Taking as is. * @wme: indicates whether the STA supports WME. Only valid during AP-mode. * @drv_priv: data area for driver use, will always be aligned to * sizeof(void *), size is determined in hw information. @@ -2130,24 +2134,6 @@ enum ieee80211_rate_control_changed { IEEE80211_RC_NSS_CHANGED = BIT(3), }; -/** - * enum ieee80211_roc_type - remain on channel type - * - * With the support for multi channel contexts and multi channel operations, - * remain on channel operations might be limited/deferred/aborted by other - * flows/operations which have higher priority (and vise versa). - * Specifying the ROC type can be used by devices to prioritize the ROC - * operations compared to other operations/flows. - * - * @IEEE80211_ROC_TYPE_NORMAL: There are no special requirements for this ROC. - * @IEEE80211_ROC_TYPE_MGMT_TX: The remain on channel request is required - * for sending managment frames offchannel. - */ -enum ieee80211_roc_type { - IEEE80211_ROC_TYPE_NORMAL = 0, - IEEE80211_ROC_TYPE_MGMT_TX, -}; - /** * struct ieee80211_ops - callbacks from mac80211 to the driver * @@ -2701,8 +2687,7 @@ struct ieee80211_ops { int (*remain_on_channel)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_channel *chan, - int duration, - enum ieee80211_roc_type type); + int duration); int (*cancel_remain_on_channel)(struct ieee80211_hw *hw); int (*set_ringparam)(struct ieee80211_hw *hw, u32 tx, u32 rx); void (*get_ringparam)(struct ieee80211_hw *hw, diff --git a/trunk/include/uapi/linux/nl80211.h b/trunk/include/uapi/linux/nl80211.h index 79da8710448e..c46bb016f4e4 100644 --- a/trunk/include/uapi/linux/nl80211.h +++ b/trunk/include/uapi/linux/nl80211.h @@ -36,21 +36,7 @@ * The station is still assumed to belong to the AP interface it was added * to. * - * Station handling varies per interface type and depending on the driver's - * capabilities. - * - * For drivers supporting TDLS with external setup (WIPHY_FLAG_SUPPORTS_TDLS - * and WIPHY_FLAG_TDLS_EXTERNAL_SETUP), the station lifetime is as follows: - * - a setup station entry is added, not yet authorized, without any rate - * or capability information, this just exists to avoid race conditions - * - when the TDLS setup is done, a single NL80211_CMD_SET_STATION is valid - * to add rate and capability information to the station and at the same - * time mark it authorized. - * - %NL80211_TDLS_ENABLE_LINK is then used - * - after this, the only valid operation is to remove it by tearing down - * the TDLS link (%NL80211_TDLS_DISABLE_LINK) - * - * TODO: need more info for other interface types + * TODO: need more info? */ /** @@ -513,11 +499,9 @@ * @NL80211_CMD_NEW_PEER_CANDIDATE: Notification on the reception of a * beacon or probe response from a compatible mesh peer. This is only * sent while no station information (sta_info) exists for the new peer - * candidate and when @NL80211_MESH_SETUP_USERSPACE_AUTH, - * @NL80211_MESH_SETUP_USERSPACE_AMPE, or - * @NL80211_MESH_SETUP_USERSPACE_MPM is set. On reception of this - * notification, userspace may decide to create a new station - * (@NL80211_CMD_NEW_STATION). To stop this notification from + * candidate and when @NL80211_MESH_SETUP_USERSPACE_AUTH is set. On + * reception of this notification, userspace may decide to create a new + * station (@NL80211_CMD_NEW_STATION). To stop this notification from * reoccurring, the userspace authentication daemon may want to create the * new station with the AUTHENTICATED flag unset and maybe change it later * depending on the authentication result. @@ -627,18 +611,6 @@ * %NL80211_ATTR_RADAR_EVENT is used to inform about the type of the * event. * - * @NL80211_CMD_GET_PROTOCOL_FEATURES: Get global nl80211 protocol features, - * i.e. features for the nl80211 protocol rather than device features. - * Returns the features in the %NL80211_ATTR_PROTOCOL_FEATURES bitmap. - * - * @NL80211_CMD_UPDATE_FT_IES: Pass down the most up-to-date Fast Transition - * Information Element to the WLAN driver - * - * @NL80211_CMD_FT_EVENT: Send a Fast transition event from the WLAN driver - * to the supplicant. This will carry the target AP's MAC address along - * with the relevant Information Elements. This event is used to report - * received FT IEs (MDIE, FTIE, RSN IE, TIE, RICIE). - * * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use */ @@ -793,11 +765,6 @@ enum nl80211_commands { NL80211_CMD_RADAR_DETECT, - NL80211_CMD_GET_PROTOCOL_FEATURES, - - NL80211_CMD_UPDATE_FT_IES, - NL80211_CMD_FT_EVENT, - /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ @@ -917,8 +884,7 @@ enum nl80211_commands { * consisting of a nested array. * * @NL80211_ATTR_MESH_ID: mesh id (1-32 bytes). - * @NL80211_ATTR_STA_PLINK_ACTION: action to perform on the mesh peer link - * (see &enum nl80211_plink_action). + * @NL80211_ATTR_STA_PLINK_ACTION: action to perform on the mesh peer link. * @NL80211_ATTR_MPATH_NEXT_HOP: MAC address of the next hop for a mesh path. * @NL80211_ATTR_MPATH_INFO: information about a mesh_path, part of mesh path * info given for %NL80211_CMD_GET_MPATH, nested attribute described at @@ -1201,10 +1167,10 @@ enum nl80211_commands { * @NL80211_ATTR_SUPPORT_MESH_AUTH: Currently, this means the underlying driver * allows auth frames in a mesh to be passed to userspace for processing via * the @NL80211_MESH_SETUP_USERSPACE_AUTH flag. - * @NL80211_ATTR_STA_PLINK_STATE: The state of a mesh peer link as defined in - * &enum nl80211_plink_state. Used when userspace is driving the peer link - * management state machine. @NL80211_MESH_SETUP_USERSPACE_AMPE or - * @NL80211_MESH_SETUP_USERSPACE_MPM must be enabled. + * @NL80211_ATTR_STA_PLINK_STATE: The state of a mesh peer link as + * defined in &enum nl80211_plink_state. Used when userspace is + * driving the peer link management state machine. + * @NL80211_MESH_SETUP_USERSPACE_AMPE must be enabled. * * @NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED: indicates, as part of the wiphy * capabilities, the supported WoWLAN triggers @@ -1402,18 +1368,6 @@ enum nl80211_commands { * advertised to the driver, e.g., to enable TDLS off channel operations * and PU-APSD. * - * @NL80211_ATTR_PROTOCOL_FEATURES: global nl80211 feature flags, see - * &enum nl80211_protocol_features, the attribute is a u32. - * - * @NL80211_ATTR_SPLIT_WIPHY_DUMP: flag attribute, userspace supports - * receiving the data for a single wiphy split across multiple - * messages, given with wiphy dump message - * - * @NL80211_ATTR_MDID: Mobility Domain Identifier - * - * @NL80211_ATTR_IE_RIC: Resource Information Container Information - * Element - * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */ @@ -1700,15 +1654,6 @@ enum nl80211_attrs { NL80211_ATTR_STA_CAPABILITY, NL80211_ATTR_STA_EXT_CAPABILITY, - NL80211_ATTR_PROTOCOL_FEATURES, - NL80211_ATTR_SPLIT_WIPHY_DUMP, - - NL80211_ATTR_DISABLE_VHT, - NL80211_ATTR_VHT_CAPABILITY_MASK, - - NL80211_ATTR_MDID, - NL80211_ATTR_IE_RIC, - /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -2467,10 +2412,8 @@ enum nl80211_mesh_power_mode { * @NL80211_MESHCONF_TTL: specifies the value of TTL field set at a source mesh * point. * - * @NL80211_MESHCONF_AUTO_OPEN_PLINKS: whether we should automatically open - * peer links when we detect compatible mesh peers. Disabled if - * @NL80211_MESH_SETUP_USERSPACE_MPM or @NL80211_MESH_SETUP_USERSPACE_AMPE are - * set. + * @NL80211_MESHCONF_AUTO_OPEN_PLINKS: whether we should automatically + * open peer links when we detect compatible mesh peers. * * @NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES: the number of action frames * containing a PREQ that an MP can send to a particular destination (path @@ -2616,9 +2559,6 @@ enum nl80211_meshconf_params { * vendor specific synchronization method or disable it to use the default * neighbor offset synchronization * - * @NL80211_MESH_SETUP_USERSPACE_MPM: Enable this option if userspace will - * implement an MPM which handles peer allocation and state. - * * @NL80211_MESH_SETUP_ATTR_MAX: highest possible mesh setup attribute number * * @__NL80211_MESH_SETUP_ATTR_AFTER_LAST: Internal use @@ -2631,7 +2571,6 @@ enum nl80211_mesh_setup_params { NL80211_MESH_SETUP_USERSPACE_AUTH, NL80211_MESH_SETUP_USERSPACE_AMPE, NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC, - NL80211_MESH_SETUP_USERSPACE_MPM, /* keep last */ __NL80211_MESH_SETUP_ATTR_AFTER_LAST, @@ -3368,23 +3307,6 @@ enum nl80211_plink_state { MAX_NL80211_PLINK_STATES = NUM_NL80211_PLINK_STATES - 1 }; -/** - * enum nl80211_plink_action - actions to perform in mesh peers - * - * @NL80211_PLINK_ACTION_NO_ACTION: perform no action - * @NL80211_PLINK_ACTION_OPEN: start mesh peer link establishment - * @NL80211_PLINK_ACTION_BLOCK: block traffic from this mesh peer - * @NUM_NL80211_PLINK_ACTIONS: number of possible actions - */ -enum plink_actions { - NL80211_PLINK_ACTION_NO_ACTION, - NL80211_PLINK_ACTION_OPEN, - NL80211_PLINK_ACTION_BLOCK, - - NUM_NL80211_PLINK_ACTIONS, -}; - - #define NL80211_KCK_LEN 16 #define NL80211_KEK_LEN 16 #define NL80211_REPLAY_CTR_LEN 8 @@ -3534,10 +3456,6 @@ enum nl80211_ap_sme_features { * stations the authenticated/associated bits have to be set in the mask. * @NL80211_FEATURE_ADVERTISE_CHAN_LIMITS: cfg80211 advertises channel limits * (HT40, VHT 80/160 MHz) if this flag is set - * @NL80211_FEATURE_USERSPACE_MPM: This driver supports a userspace Mesh - * Peering Management entity which may be implemented by registering for - * beacons or NL80211_CMD_NEW_PEER_CANDIDATE events. The mesh beacon is - * still generated by the driver. */ enum nl80211_feature_flags { NL80211_FEATURE_SK_TX_STATUS = 1 << 0, @@ -3556,7 +3474,6 @@ enum nl80211_feature_flags { /* bit 13 is reserved */ NL80211_FEATURE_ADVERTISE_CHAN_LIMITS = 1 << 14, NL80211_FEATURE_FULL_AP_CLIENT_STATE = 1 << 15, - NL80211_FEATURE_USERSPACE_MPM = 1 << 16, }; /** @@ -3670,16 +3587,4 @@ enum nl80211_dfs_state { NL80211_DFS_AVAILABLE, }; -/** - * enum enum nl80211_protocol_features - nl80211 protocol features - * @NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP: nl80211 supports splitting - * wiphy dumps (if requested by the application with the attribute - * %NL80211_ATTR_SPLIT_WIPHY_DUMP. Also supported is filtering the - * wiphy dump by %NL80211_ATTR_WIPHY, %NL80211_ATTR_IFINDEX or - * %NL80211_ATTR_WDEV. - */ -enum nl80211_protocol_features { - NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP = 1 << 0, -}; - #endif /* __LINUX_NL80211_H */ diff --git a/trunk/net/mac80211/cfg.c b/trunk/net/mac80211/cfg.c index 1d1ddabd89ca..09d96a8f6c2c 100644 --- a/trunk/net/mac80211/cfg.c +++ b/trunk/net/mac80211/cfg.c @@ -254,7 +254,7 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, goto out_unlock; } - __ieee80211_key_free(key, true); + __ieee80211_key_free(key); ret = 0; out_unlock: @@ -1035,12 +1035,9 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) sta_info_flush_defer(vlan); sta_info_flush_defer(sdata); rcu_barrier(); - list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) { + list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) sta_info_flush_cleanup(vlan); - ieee80211_free_keys(vlan); - } sta_info_flush_cleanup(sdata); - ieee80211_free_keys(sdata); sdata->vif.bss_conf.enable_beacon = false; clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state); @@ -1180,18 +1177,6 @@ static int sta_apply_parameters(struct ieee80211_local *local, mask |= BIT(NL80211_STA_FLAG_ASSOCIATED); if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) set |= BIT(NL80211_STA_FLAG_ASSOCIATED); - } else if (test_sta_flag(sta, WLAN_STA_TDLS_PEER)) { - /* - * TDLS -- everything follows authorized, but - * only becoming authorized is possible, not - * going back - */ - if (set & BIT(NL80211_STA_FLAG_AUTHORIZED)) { - set |= BIT(NL80211_STA_FLAG_AUTHENTICATED) | - BIT(NL80211_STA_FLAG_ASSOCIATED); - mask |= BIT(NL80211_STA_FLAG_AUTHENTICATED) | - BIT(NL80211_STA_FLAG_ASSOCIATED); - } } ret = sta_apply_auth_flags(local, sta, mask, set); @@ -1276,8 +1261,7 @@ static int sta_apply_parameters(struct ieee80211_local *local, if (ieee80211_vif_is_mesh(&sdata->vif)) { #ifdef CONFIG_MAC80211_MESH u32 changed = 0; - - if (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE) { + if (sdata->u.mesh.security & IEEE80211_MESH_SEC_SECURED) { switch (params->plink_state) { case NL80211_PLINK_ESTAB: if (sta->plink_state != NL80211_PLINK_ESTAB) @@ -1308,18 +1292,15 @@ static int sta_apply_parameters(struct ieee80211_local *local, /* nothing */ break; } - } - - switch (params->plink_action) { - case NL80211_PLINK_ACTION_NO_ACTION: - /* nothing */ - break; - case NL80211_PLINK_ACTION_OPEN: - changed |= mesh_plink_open(sta); - break; - case NL80211_PLINK_ACTION_BLOCK: - changed |= mesh_plink_block(sta); - break; + } else { + switch (params->plink_action) { + case PLINK_ACTION_OPEN: + changed |= mesh_plink_open(sta); + break; + case PLINK_ACTION_BLOCK: + changed |= mesh_plink_block(sta); + break; + } } if (params->local_pm) @@ -1365,10 +1346,8 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, * defaults -- if userspace wants something else we'll * change it accordingly in sta_apply_parameters() */ - if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) { - sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); - sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); - } + sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); + sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); err = sta_apply_parameters(local, sta, params); if (err) { @@ -1377,8 +1356,8 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, } /* - * for TDLS, rate control should be initialized only when - * rates are known and station is marked authorized + * for TDLS, rate control should be initialized only when supported + * rates are known. */ if (!test_sta_flag(sta, WLAN_STA_TDLS_PEER)) rate_control_rate_init(sta); @@ -1415,67 +1394,50 @@ static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, } static int ieee80211_change_station(struct wiphy *wiphy, - struct net_device *dev, u8 *mac, + struct net_device *dev, + u8 *mac, struct station_parameters *params) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = wiphy_priv(wiphy); struct sta_info *sta; struct ieee80211_sub_if_data *vlansdata; - enum cfg80211_station_type statype; int err; mutex_lock(&local->sta_mtx); sta = sta_info_get_bss(sdata, mac); if (!sta) { - err = -ENOENT; - goto out_err; + mutex_unlock(&local->sta_mtx); + return -ENOENT; } - switch (sdata->vif.type) { - case NL80211_IFTYPE_MESH_POINT: - if (sdata->u.mesh.user_mpm) - statype = CFG80211_STA_MESH_PEER_USER; - else - statype = CFG80211_STA_MESH_PEER_KERNEL; - break; - case NL80211_IFTYPE_ADHOC: - statype = CFG80211_STA_IBSS; - break; - case NL80211_IFTYPE_STATION: - if (!test_sta_flag(sta, WLAN_STA_TDLS_PEER)) { - statype = CFG80211_STA_AP_STA; - break; - } - if (test_sta_flag(sta, WLAN_STA_AUTHORIZED)) - statype = CFG80211_STA_TDLS_PEER_ACTIVE; - else - statype = CFG80211_STA_TDLS_PEER_SETUP; - break; - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_AP_VLAN: - statype = CFG80211_STA_AP_CLIENT; - break; - default: - err = -EOPNOTSUPP; - goto out_err; + /* in station mode, some updates are only valid with TDLS */ + if (sdata->vif.type == NL80211_IFTYPE_STATION && + (params->supported_rates || params->ht_capa || params->vht_capa || + params->sta_modify_mask || + (params->sta_flags_mask & BIT(NL80211_STA_FLAG_WME))) && + !test_sta_flag(sta, WLAN_STA_TDLS_PEER)) { + mutex_unlock(&local->sta_mtx); + return -EINVAL; } - err = cfg80211_check_station_change(wiphy, params, statype); - if (err) - goto out_err; - if (params->vlan && params->vlan != sta->sdata->dev) { bool prev_4addr = false; bool new_4addr = false; vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); + if (vlansdata->vif.type != NL80211_IFTYPE_AP_VLAN && + vlansdata->vif.type != NL80211_IFTYPE_AP) { + mutex_unlock(&local->sta_mtx); + return -EINVAL; + } + if (params->vlan->ieee80211_ptr->use_4addr) { if (vlansdata->u.vlan.sta) { - err = -EBUSY; - goto out_err; + mutex_unlock(&local->sta_mtx); + return -EBUSY; } rcu_assign_pointer(vlansdata->u.vlan.sta, sta); @@ -1502,12 +1464,12 @@ static int ieee80211_change_station(struct wiphy *wiphy, } err = sta_apply_parameters(local, sta, params); - if (err) - goto out_err; + if (err) { + mutex_unlock(&local->sta_mtx); + return err; + } - /* When peer becomes authorized, init rate control as well */ - if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) && - test_sta_flag(sta, WLAN_STA_AUTHORIZED)) + if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) && params->supported_rates) rate_control_rate_init(sta); mutex_unlock(&local->sta_mtx); @@ -1517,11 +1479,7 @@ static int ieee80211_change_station(struct wiphy *wiphy, ieee80211_recalc_ps(local, -1); ieee80211_recalc_ps_vif(sdata); } - return 0; -out_err: - mutex_unlock(&local->sta_mtx); - return err; } #ifdef CONFIG_MAC80211_MESH @@ -1729,7 +1687,6 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh, ifmsh->mesh_sp_id = setup->sync_method; ifmsh->mesh_pp_id = setup->path_sel_proto; ifmsh->mesh_pm_id = setup->path_metric; - ifmsh->user_mpm = setup->user_mpm; ifmsh->security = IEEE80211_MESH_SEC_NONE; if (setup->is_authenticated) ifmsh->security |= IEEE80211_MESH_SEC_AUTHED; @@ -1773,11 +1730,8 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy, conf->dot11MeshTTL = nconf->dot11MeshTTL; if (_chg_mesh_attr(NL80211_MESHCONF_ELEMENT_TTL, mask)) conf->element_ttl = nconf->element_ttl; - if (_chg_mesh_attr(NL80211_MESHCONF_AUTO_OPEN_PLINKS, mask)) { - if (ifmsh->user_mpm) - return -EBUSY; + if (_chg_mesh_attr(NL80211_MESHCONF_AUTO_OPEN_PLINKS, mask)) conf->auto_open_plinks = nconf->auto_open_plinks; - } if (_chg_mesh_attr(NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR, mask)) conf->dot11MeshNbrOffsetMaxNeighbor = nconf->dot11MeshNbrOffsetMaxNeighbor; @@ -2417,8 +2371,7 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata, struct ieee80211_channel *channel, unsigned int duration, u64 *cookie, - struct sk_buff *txskb, - enum ieee80211_roc_type type) + struct sk_buff *txskb) { struct ieee80211_roc_work *roc, *tmp; bool queued = false; @@ -2437,7 +2390,6 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, roc->duration = duration; roc->req_duration = duration; roc->frame = txskb; - roc->type = type; roc->mgmt_tx_cookie = (unsigned long)txskb; roc->sdata = sdata; INIT_DELAYED_WORK(&roc->work, ieee80211_sw_roc_work); @@ -2468,7 +2420,7 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, if (!duration) duration = 10; - ret = drv_remain_on_channel(local, sdata, channel, duration, type); + ret = drv_remain_on_channel(local, sdata, channel, duration); if (ret) { kfree(roc); return ret; @@ -2487,13 +2439,10 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, * * If it hasn't started yet, just increase the duration * and add the new one to the list of dependents. - * If the type of the new ROC has higher priority, modify the - * type of the previous one to match that of the new one. */ if (!tmp->started) { list_add_tail(&roc->list, &tmp->dependents); tmp->duration = max(tmp->duration, roc->duration); - tmp->type = max(tmp->type, roc->type); queued = true; break; } @@ -2505,18 +2454,16 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, /* * In the offloaded ROC case, if it hasn't begun, add * this new one to the dependent list to be handled - * when the master one begins. If it has begun, + * when the the master one begins. If it has begun, * check that there's still a minimum time left and * if so, start this one, transmitting the frame, but - * add it to the list directly after this one with + * add it to the list directly after this one with a * a reduced time so we'll ask the driver to execute * it right after finishing the previous one, in the * hope that it'll also be executed right afterwards, * effectively extending the old one. * If there's no minimum time left, just add it to the * normal list. - * TODO: the ROC type is ignored here, assuming that it - * is better to immediately use the current ROC. */ if (!tmp->hw_begun) { list_add_tail(&roc->list, &tmp->dependents); @@ -2610,8 +2557,7 @@ static int ieee80211_remain_on_channel(struct wiphy *wiphy, mutex_lock(&local->mtx); ret = ieee80211_start_roc_work(local, sdata, chan, - duration, cookie, NULL, - IEEE80211_ROC_TYPE_NORMAL); + duration, cookie, NULL); mutex_unlock(&local->mtx); return ret; @@ -2844,8 +2790,7 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, /* This will handle all kinds of coalescing and immediate TX */ ret = ieee80211_start_roc_work(local, sdata, chan, - wait, cookie, skb, - IEEE80211_ROC_TYPE_MGMT_TX); + wait, cookie, skb); if (ret) kfree_skb(skb); out_unlock: @@ -3340,7 +3285,6 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy, struct cfg80211_chan_def *chandef) { struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); - struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_chanctx_conf *chanctx_conf; int ret = -ENODATA; @@ -3349,16 +3293,6 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy, if (chanctx_conf) { *chandef = chanctx_conf->def; ret = 0; - } else if (local->open_count > 0 && - local->open_count == local->monitors && - sdata->vif.type == NL80211_IFTYPE_MONITOR) { - if (local->use_chanctx) - *chandef = local->monitor_chandef; - else - cfg80211_chandef_create(chandef, - local->_oper_channel, - local->_oper_channel_type); - ret = 0; } rcu_read_unlock(); diff --git a/trunk/net/mac80211/debugfs_sta.c b/trunk/net/mac80211/debugfs_sta.c index 4f841fe559df..c7591f73dbc3 100644 --- a/trunk/net/mac80211/debugfs_sta.c +++ b/trunk/net/mac80211/debugfs_sta.c @@ -325,36 +325,6 @@ static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf, } STA_OPS(ht_capa); -static ssize_t sta_vht_capa_read(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) -{ - char buf[128], *p = buf; - struct sta_info *sta = file->private_data; - struct ieee80211_sta_vht_cap *vhtc = &sta->sta.vht_cap; - - p += scnprintf(p, sizeof(buf) + buf - p, "VHT %ssupported\n", - vhtc->vht_supported ? "" : "not "); - if (vhtc->vht_supported) { - p += scnprintf(p, sizeof(buf)+buf-p, "cap: %#.8x\n", vhtc->cap); - - p += scnprintf(p, sizeof(buf)+buf-p, "RX MCS: %.4x\n", - le16_to_cpu(vhtc->vht_mcs.rx_mcs_map)); - if (vhtc->vht_mcs.rx_highest) - p += scnprintf(p, sizeof(buf)+buf-p, - "MCS RX highest: %d Mbps\n", - le16_to_cpu(vhtc->vht_mcs.rx_highest)); - p += scnprintf(p, sizeof(buf)+buf-p, "TX MCS: %.4x\n", - le16_to_cpu(vhtc->vht_mcs.tx_mcs_map)); - if (vhtc->vht_mcs.tx_highest) - p += scnprintf(p, sizeof(buf)+buf-p, - "MCS TX highest: %d Mbps\n", - le16_to_cpu(vhtc->vht_mcs.tx_highest)); - } - - return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf); -} -STA_OPS(vht_capa); - static ssize_t sta_current_tx_rate_read(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) { @@ -435,7 +405,6 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta) DEBUGFS_ADD(dev); DEBUGFS_ADD(last_signal); DEBUGFS_ADD(ht_capa); - DEBUGFS_ADD(vht_capa); DEBUGFS_ADD(last_ack_signal); DEBUGFS_ADD(current_tx_rate); DEBUGFS_ADD(last_rx_rate); diff --git a/trunk/net/mac80211/driver-ops.h b/trunk/net/mac80211/driver-ops.h index 832acea4a5cb..ee56d0779d8b 100644 --- a/trunk/net/mac80211/driver-ops.h +++ b/trunk/net/mac80211/driver-ops.h @@ -787,16 +787,15 @@ 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, - unsigned int duration, - enum ieee80211_roc_type type) + unsigned int duration) { int ret; might_sleep(); - trace_drv_remain_on_channel(local, sdata, chan, duration, type); + trace_drv_remain_on_channel(local, sdata, chan, duration); ret = local->ops->remain_on_channel(&local->hw, &sdata->vif, - chan, duration, type); + chan, duration); trace_drv_return_int(local, ret); return ret; diff --git a/trunk/net/mac80211/ht.c b/trunk/net/mac80211/ht.c index af8cee06e4f3..0db25d4bb223 100644 --- a/trunk/net/mac80211/ht.c +++ b/trunk/net/mac80211/ht.c @@ -40,6 +40,13 @@ void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata, if (!ht_cap->ht_supported) return; + if (sdata->vif.type != NL80211_IFTYPE_STATION) { + /* AP interfaces call this code when adding new stations, + * so just silently ignore non station interfaces. + */ + return; + } + /* NOTE: If you add more over-rides here, update register_hw * ht_capa_mod_msk logic in main.c as well. * And, if this method can ever change ht_cap.ht_supported, fix @@ -90,7 +97,7 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata, const struct ieee80211_ht_cap *ht_cap_ie, struct sta_info *sta) { - struct ieee80211_sta_ht_cap ht_cap, own_cap; + struct ieee80211_sta_ht_cap ht_cap; u8 ampdu_info, tx_mcs_set_cap; int i, max_tx_streams; bool changed; @@ -104,18 +111,6 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata, ht_cap.ht_supported = true; - own_cap = sband->ht_cap; - - /* - * If user has specified capability over-rides, take care - * of that if the station we're setting up is the AP that - * we advertised a restricted capability set to. Override - * our own capabilities and then use those below. - */ - if (sdata->vif.type == NL80211_IFTYPE_STATION && - !test_sta_flag(sta, WLAN_STA_TDLS_PEER)) - ieee80211_apply_htcap_overrides(sdata, &own_cap); - /* * The bits listed in this expression should be * the same for the peer and us, if the station @@ -123,20 +118,21 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata, * we mask them out. */ ht_cap.cap = le16_to_cpu(ht_cap_ie->cap_info) & - (own_cap.cap | ~(IEEE80211_HT_CAP_LDPC_CODING | - IEEE80211_HT_CAP_SUP_WIDTH_20_40 | - IEEE80211_HT_CAP_GRN_FLD | - IEEE80211_HT_CAP_SGI_20 | - IEEE80211_HT_CAP_SGI_40 | - IEEE80211_HT_CAP_DSSSCCK40)); + (sband->ht_cap.cap | + ~(IEEE80211_HT_CAP_LDPC_CODING | + IEEE80211_HT_CAP_SUP_WIDTH_20_40 | + IEEE80211_HT_CAP_GRN_FLD | + IEEE80211_HT_CAP_SGI_20 | + IEEE80211_HT_CAP_SGI_40 | + IEEE80211_HT_CAP_DSSSCCK40)); /* * The STBC bits are asymmetric -- if we don't have * TX then mask out the peer's RX and vice versa. */ - if (!(own_cap.cap & IEEE80211_HT_CAP_TX_STBC)) + if (!(sband->ht_cap.cap & IEEE80211_HT_CAP_TX_STBC)) ht_cap.cap &= ~IEEE80211_HT_CAP_RX_STBC; - if (!(own_cap.cap & IEEE80211_HT_CAP_RX_STBC)) + if (!(sband->ht_cap.cap & IEEE80211_HT_CAP_RX_STBC)) ht_cap.cap &= ~IEEE80211_HT_CAP_TX_STBC; ampdu_info = ht_cap_ie->ampdu_params_info; @@ -146,7 +142,7 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata, (ampdu_info & IEEE80211_HT_AMPDU_PARM_DENSITY) >> 2; /* own MCS TX capabilities */ - tx_mcs_set_cap = own_cap.mcs.tx_params; + tx_mcs_set_cap = sband->ht_cap.mcs.tx_params; /* Copy peer MCS TX capabilities, the driver might need them. */ ht_cap.mcs.tx_params = ht_cap_ie->mcs.tx_params; @@ -172,20 +168,26 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata, */ for (i = 0; i < max_tx_streams; i++) ht_cap.mcs.rx_mask[i] = - own_cap.mcs.rx_mask[i] & ht_cap_ie->mcs.rx_mask[i]; + sband->ht_cap.mcs.rx_mask[i] & ht_cap_ie->mcs.rx_mask[i]; if (tx_mcs_set_cap & IEEE80211_HT_MCS_TX_UNEQUAL_MODULATION) for (i = IEEE80211_HT_MCS_UNEQUAL_MODULATION_START_BYTE; i < IEEE80211_HT_MCS_MASK_LEN; i++) ht_cap.mcs.rx_mask[i] = - own_cap.mcs.rx_mask[i] & + sband->ht_cap.mcs.rx_mask[i] & ht_cap_ie->mcs.rx_mask[i]; /* handle MCS rate 32 too */ - if (own_cap.mcs.rx_mask[32/8] & ht_cap_ie->mcs.rx_mask[32/8] & 1) + if (sband->ht_cap.mcs.rx_mask[32/8] & ht_cap_ie->mcs.rx_mask[32/8] & 1) ht_cap.mcs.rx_mask[32/8] |= 1; apply: + /* + * If user has specified capability over-rides, take care + * of that here. + */ + ieee80211_apply_htcap_overrides(sdata, &ht_cap); + changed = memcmp(&sta->sta.ht_cap, &ht_cap, sizeof(ht_cap)); memcpy(&sta->sta.ht_cap, &ht_cap, sizeof(ht_cap)); diff --git a/trunk/net/mac80211/ibss.c b/trunk/net/mac80211/ibss.c index 539d4a11b47b..40b71dfcc79d 100644 --- a/trunk/net/mac80211/ibss.c +++ b/trunk/net/mac80211/ibss.c @@ -985,9 +985,36 @@ static void ieee80211_ibss_timer(unsigned long data) { struct ieee80211_sub_if_data *sdata = (struct ieee80211_sub_if_data *) data; + struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; + struct ieee80211_local *local = sdata->local; - ieee80211_queue_work(&sdata->local->hw, &sdata->work); + if (local->quiescing) { + ifibss->timer_running = true; + return; + } + + ieee80211_queue_work(&local->hw, &sdata->work); +} + +#ifdef CONFIG_PM +void ieee80211_ibss_quiesce(struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; + + if (del_timer_sync(&ifibss->timer)) + ifibss->timer_running = true; +} + +void ieee80211_ibss_restart(struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; + + if (ifibss->timer_running) { + add_timer(&ifibss->timer); + ifibss->timer_running = false; + } } +#endif void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata) { diff --git a/trunk/net/mac80211/ieee80211_i.h b/trunk/net/mac80211/ieee80211_i.h index f4433f081e77..388580a1bada 100644 --- a/trunk/net/mac80211/ieee80211_i.h +++ b/trunk/net/mac80211/ieee80211_i.h @@ -315,7 +315,6 @@ struct ieee80211_roc_work { u32 duration, req_duration; struct sk_buff *frame; u64 cookie, mgmt_tx_cookie; - enum ieee80211_roc_type type; }; /* flags used in struct ieee80211_if_managed.flags */ @@ -401,6 +400,7 @@ struct ieee80211_if_managed { u16 aid; + unsigned long timers_running; /* used for quiesce/restart */ bool powersave; /* powersave requested for this iface */ bool broken_ap; /* AP is broken -- turn off powersave */ u8 dtim_period; @@ -479,8 +479,6 @@ struct ieee80211_if_managed { struct ieee80211_ht_cap ht_capa; /* configured ht-cap over-rides */ struct ieee80211_ht_cap ht_capa_mask; /* Valid parts of ht_capa */ - struct ieee80211_vht_cap vht_capa; /* configured VHT overrides */ - struct ieee80211_vht_cap vht_capa_mask; /* Valid parts of vht_capa */ }; struct ieee80211_if_ibss { @@ -492,6 +490,8 @@ struct ieee80211_if_ibss { u32 basic_rates; + bool timer_running; + bool fixed_bssid; bool fixed_channel; bool privacy; @@ -543,6 +543,8 @@ struct ieee80211_if_mesh { struct timer_list mesh_path_timer; struct timer_list mesh_path_root_timer; + unsigned long timers_running; + unsigned long wrkq_flags; u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN]; @@ -588,7 +590,6 @@ struct ieee80211_if_mesh { IEEE80211_MESH_SEC_AUTHED = 0x1, IEEE80211_MESH_SEC_SECURED = 0x2, } security; - bool user_mpm; /* Extensible Synchronization Framework */ const struct ieee80211_mesh_sync_ops *sync_ops; s64 sync_offset_clockdrift_max; @@ -681,8 +682,6 @@ struct ieee80211_sub_if_data { /* count for keys needing tailroom space allocation */ int crypto_tx_tailroom_needed_cnt; - int crypto_tx_tailroom_pending_dec; - struct delayed_work dec_tailroom_needed_wk; struct net_device *dev; struct ieee80211_local *local; @@ -766,6 +765,10 @@ struct ieee80211_sub_if_data { } debugfs; #endif +#ifdef CONFIG_PM + struct ieee80211_bss_conf suspend_bss_conf; +#endif + /* must be last, dynamically sized area in this! */ struct ieee80211_vif vif; }; @@ -1133,6 +1136,11 @@ struct ieee80211_local { struct ieee80211_sub_if_data __rcu *p2p_sdata; + /* dummy netdev for use w/ NAPI */ + struct net_device napi_dev; + + struct napi_struct napi; + /* virtual monitor interface */ struct ieee80211_sub_if_data __rcu *monitor_sdata; struct cfg80211_chan_def monitor_chandef; @@ -1275,6 +1283,8 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, const struct ieee80211_channel_sw_ie *sw_elem, struct ieee80211_bss *bss, u64 timestamp); +void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata); +void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata); void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata); void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); @@ -1292,6 +1302,8 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata, int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, struct cfg80211_ibss_params *params); int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata); +void ieee80211_ibss_quiesce(struct ieee80211_sub_if_data *sdata); +void ieee80211_ibss_restart(struct ieee80211_sub_if_data *sdata); void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata); void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); @@ -1429,8 +1441,6 @@ void ieee80211_sta_set_rx_nss(struct sta_info *sta); void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, struct sta_info *sta, u8 opmode, enum ieee80211_band band, bool nss_only); -void ieee80211_apply_vhtcap_overrides(struct ieee80211_sub_if_data *sdata, - struct ieee80211_sta_vht_cap *vht_cap); /* Spectrum management */ void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, diff --git a/trunk/net/mac80211/iface.c b/trunk/net/mac80211/iface.c index d85282f64405..2c059e54e885 100644 --- a/trunk/net/mac80211/iface.c +++ b/trunk/net/mac80211/iface.c @@ -107,7 +107,7 @@ void ieee80211_recalc_idle(struct ieee80211_local *local) lockdep_assert_held(&local->mtx); - active = !list_empty(&local->chanctx_list) || local->monitors; + active = !list_empty(&local->chanctx_list); if (!local->ops->remain_on_channel) { list_for_each_entry(roc, &local->roc_list, list) { @@ -485,6 +485,8 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) res = drv_start(local); if (res) goto err_del_bss; + if (local->ops->napi_poll) + napi_enable(&local->napi); /* we're brought up, everything changes */ hw_reconf_flags = ~0; ieee80211_led_radio(local, true); @@ -539,9 +541,6 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) ieee80211_adjust_monitor_flags(sdata, 1); ieee80211_configure_filter(local); - mutex_lock(&local->mtx); - ieee80211_recalc_idle(local); - mutex_unlock(&local->mtx); netif_carrier_on(dev); break; @@ -813,9 +812,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, ieee80211_adjust_monitor_flags(sdata, -1); ieee80211_configure_filter(local); - mutex_lock(&local->mtx); - ieee80211_recalc_idle(local); - mutex_unlock(&local->mtx); break; case NL80211_IFTYPE_P2P_DEVICE: /* relies on synchronize_rcu() below */ @@ -836,16 +832,14 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, rcu_barrier(); sta_info_flush_cleanup(sdata); + skb_queue_purge(&sdata->skb_queue); + /* * Free all remaining keys, there shouldn't be any, - * except maybe in WDS mode? + * except maybe group keys in AP more or WDS? */ ieee80211_free_keys(sdata); - /* fall through */ - case NL80211_IFTYPE_AP: - skb_queue_purge(&sdata->skb_queue); - drv_remove_interface_debugfs(local, sdata); if (going_down) @@ -857,6 +851,8 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, ieee80211_recalc_ps(local, -1); if (local->open_count == 0) { + if (local->ops->napi_poll) + napi_disable(&local->napi); ieee80211_clear_tx_pending(local); ieee80211_stop_device(local); @@ -1545,8 +1541,6 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, INIT_WORK(&sdata->cleanup_stations_wk, ieee80211_cleanup_sdata_stas_wk); INIT_DELAYED_WORK(&sdata->dfs_cac_timer_work, ieee80211_dfs_cac_timer_work); - INIT_DELAYED_WORK(&sdata->dec_tailroom_needed_wk, - ieee80211_delayed_tailroom_dec); for (i = 0; i < IEEE80211_NUM_BANDS; i++) { struct ieee80211_supported_band *sband; diff --git a/trunk/net/mac80211/key.c b/trunk/net/mac80211/key.c index 99e9f6ae6a54..ef252eb58c36 100644 --- a/trunk/net/mac80211/key.c +++ b/trunk/net/mac80211/key.c @@ -397,8 +397,7 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, return key; } -static void __ieee80211_key_destroy(struct ieee80211_key *key, - bool delay_tailroom) +static void __ieee80211_key_destroy(struct ieee80211_key *key) { if (!key) return; @@ -417,18 +416,8 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key, if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC) ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm); if (key->local) { - struct ieee80211_sub_if_data *sdata = key->sdata; - ieee80211_debugfs_key_remove(key); - - if (delay_tailroom) { - /* see ieee80211_delayed_tailroom_dec */ - sdata->crypto_tx_tailroom_pending_dec++; - schedule_delayed_work(&sdata->dec_tailroom_needed_wk, - HZ/2); - } else { - sdata->crypto_tx_tailroom_needed_cnt--; - } + key->sdata->crypto_tx_tailroom_needed_cnt--; } kfree(key); @@ -451,6 +440,32 @@ int ieee80211_key_link(struct ieee80211_key *key, key->sdata = sdata; key->sta = sta; + if (sta) { + /* + * some hardware cannot handle TKIP with QoS, so + * we indicate whether QoS could be in use. + */ + if (test_sta_flag(sta, WLAN_STA_WME)) + key->conf.flags |= IEEE80211_KEY_FLAG_WMM_STA; + } else { + if (sdata->vif.type == NL80211_IFTYPE_STATION) { + struct sta_info *ap; + + /* + * We're getting a sta pointer in, so must be under + * appropriate locking for sta_info_get(). + */ + + /* same here, the AP could be using QoS */ + ap = sta_info_get(key->sdata, key->sdata->u.mgd.bssid); + if (ap) { + if (test_sta_flag(ap, WLAN_STA_WME)) + key->conf.flags |= + IEEE80211_KEY_FLAG_WMM_STA; + } + } + } + mutex_lock(&sdata->local->key_mtx); if (sta && pairwise) @@ -463,7 +478,7 @@ int ieee80211_key_link(struct ieee80211_key *key, increment_tailroom_need_count(sdata); __ieee80211_key_replace(sdata, sta, pairwise, old_key, key); - __ieee80211_key_destroy(old_key, true); + __ieee80211_key_destroy(old_key); ieee80211_debugfs_key_add(key); @@ -474,7 +489,7 @@ int ieee80211_key_link(struct ieee80211_key *key, return ret; } -void __ieee80211_key_free(struct ieee80211_key *key, bool delay_tailroom) +void __ieee80211_key_free(struct ieee80211_key *key) { if (!key) return; @@ -486,14 +501,14 @@ void __ieee80211_key_free(struct ieee80211_key *key, bool delay_tailroom) __ieee80211_key_replace(key->sdata, key->sta, key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE, key, NULL); - __ieee80211_key_destroy(key, delay_tailroom); + __ieee80211_key_destroy(key); } void ieee80211_key_free(struct ieee80211_local *local, struct ieee80211_key *key) { mutex_lock(&local->key_mtx); - __ieee80211_key_free(key, true); + __ieee80211_key_free(key); mutex_unlock(&local->key_mtx); } @@ -551,61 +566,37 @@ void ieee80211_iter_keys(struct ieee80211_hw *hw, } EXPORT_SYMBOL(ieee80211_iter_keys); -void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata) +void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata) { - struct ieee80211_key *key, *tmp; + struct ieee80211_key *key; - cancel_delayed_work_sync(&sdata->dec_tailroom_needed_wk); + ASSERT_RTNL(); mutex_lock(&sdata->local->key_mtx); - sdata->crypto_tx_tailroom_needed_cnt -= - sdata->crypto_tx_tailroom_pending_dec; - sdata->crypto_tx_tailroom_pending_dec = 0; - - ieee80211_debugfs_key_remove_mgmt_default(sdata); - - list_for_each_entry_safe(key, tmp, &sdata->key_list, list) - __ieee80211_key_free(key, false); - - ieee80211_debugfs_key_update_default(sdata); - - WARN_ON_ONCE(sdata->crypto_tx_tailroom_needed_cnt || - sdata->crypto_tx_tailroom_pending_dec); + list_for_each_entry(key, &sdata->key_list, list) + ieee80211_key_disable_hw_accel(key); mutex_unlock(&sdata->local->key_mtx); } -void ieee80211_delayed_tailroom_dec(struct work_struct *wk) +void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata) { - struct ieee80211_sub_if_data *sdata; + struct ieee80211_key *key, *tmp; - sdata = container_of(wk, struct ieee80211_sub_if_data, - dec_tailroom_needed_wk.work); + mutex_lock(&sdata->local->key_mtx); - /* - * The reason for the delayed tailroom needed decrementing is to - * make roaming faster: during roaming, all keys are first deleted - * and then new keys are installed. The first new key causes the - * crypto_tx_tailroom_needed_cnt to go from 0 to 1, which invokes - * the cost of synchronize_net() (which can be slow). Avoid this - * by deferring the crypto_tx_tailroom_needed_cnt decrementing on - * key removal for a while, so if we roam the value is larger than - * zero and no 0->1 transition happens. - * - * The cost is that if the AP switching was from an AP with keys - * to one without, we still allocate tailroom while it would no - * longer be needed. However, in the typical (fast) roaming case - * within an ESS this usually won't happen. - */ + ieee80211_debugfs_key_remove_mgmt_default(sdata); + + list_for_each_entry_safe(key, tmp, &sdata->key_list, list) + __ieee80211_key_free(key); + + ieee80211_debugfs_key_update_default(sdata); - mutex_lock(&sdata->local->key_mtx); - sdata->crypto_tx_tailroom_needed_cnt -= - sdata->crypto_tx_tailroom_pending_dec; - sdata->crypto_tx_tailroom_pending_dec = 0; mutex_unlock(&sdata->local->key_mtx); } + void ieee80211_gtk_rekey_notify(struct ieee80211_vif *vif, const u8 *bssid, const u8 *replay_ctr, gfp_t gfp) { diff --git a/trunk/net/mac80211/key.h b/trunk/net/mac80211/key.h index 2a682d81cee9..382dc44ed330 100644 --- a/trunk/net/mac80211/key.h +++ b/trunk/net/mac80211/key.h @@ -134,7 +134,7 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, int __must_check ieee80211_key_link(struct ieee80211_key *key, struct ieee80211_sub_if_data *sdata, struct sta_info *sta); -void __ieee80211_key_free(struct ieee80211_key *key, bool delay_tailroom); +void __ieee80211_key_free(struct ieee80211_key *key); void ieee80211_key_free(struct ieee80211_local *local, struct ieee80211_key *key); void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx, @@ -143,10 +143,9 @@ void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, int idx); void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata); void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata); +void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata); #define key_mtx_dereference(local, ref) \ rcu_dereference_protected(ref, lockdep_is_held(&((local)->key_mtx))) -void ieee80211_delayed_tailroom_dec(struct work_struct *wk); - #endif /* IEEE80211_KEY_H */ diff --git a/trunk/net/mac80211/main.c b/trunk/net/mac80211/main.c index 5a53aa5ede80..1a8591b77a13 100644 --- a/trunk/net/mac80211/main.c +++ b/trunk/net/mac80211/main.c @@ -399,6 +399,30 @@ static int ieee80211_ifa6_changed(struct notifier_block *nb, } #endif +static int ieee80211_napi_poll(struct napi_struct *napi, int budget) +{ + struct ieee80211_local *local = + container_of(napi, struct ieee80211_local, napi); + + return local->ops->napi_poll(&local->hw, budget); +} + +void ieee80211_napi_schedule(struct ieee80211_hw *hw) +{ + struct ieee80211_local *local = hw_to_local(hw); + + napi_schedule(&local->napi); +} +EXPORT_SYMBOL(ieee80211_napi_schedule); + +void ieee80211_napi_complete(struct ieee80211_hw *hw) +{ + struct ieee80211_local *local = hw_to_local(hw); + + napi_complete(&local->napi); +} +EXPORT_SYMBOL(ieee80211_napi_complete); + /* There isn't a lot of sense in it, but you can transmit anything you like */ static const struct ieee80211_txrx_stypes ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { @@ -477,27 +501,6 @@ static const struct ieee80211_ht_cap mac80211_ht_capa_mod_mask = { }, }; -static const struct ieee80211_vht_cap mac80211_vht_capa_mod_mask = { - .vht_cap_info = - cpu_to_le32(IEEE80211_VHT_CAP_RXLDPC | - IEEE80211_VHT_CAP_SHORT_GI_80 | - IEEE80211_VHT_CAP_SHORT_GI_160 | - IEEE80211_VHT_CAP_RXSTBC_1 | - IEEE80211_VHT_CAP_RXSTBC_2 | - IEEE80211_VHT_CAP_RXSTBC_3 | - IEEE80211_VHT_CAP_RXSTBC_4 | - IEEE80211_VHT_CAP_TXSTBC | - IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE | - IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | - IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN | - IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN | - IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK), - .supp_mcs = { - .rx_mcs_map = cpu_to_le16(~0), - .tx_mcs_map = cpu_to_le16(~0), - }, -}; - static const u8 extended_capabilities[] = { 0, 0, 0, 0, 0, 0, 0, WLAN_EXT_CAPA8_OPMODE_NOTIF, @@ -569,8 +572,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, wiphy->features |= NL80211_FEATURE_SK_TX_STATUS | NL80211_FEATURE_SAE | NL80211_FEATURE_HT_IBSS | - NL80211_FEATURE_VIF_TXPOWER | - NL80211_FEATURE_USERSPACE_MPM; + NL80211_FEATURE_VIF_TXPOWER; if (!ops->hw_scan) wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN | @@ -607,7 +609,6 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH; local->user_power_level = IEEE80211_UNSET_POWER_LEVEL; wiphy->ht_capa_mod_mask = &mac80211_ht_capa_mod_mask; - wiphy->vht_capa_mod_mask = &mac80211_vht_capa_mod_mask; INIT_LIST_HEAD(&local->interfaces); @@ -663,6 +664,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, skb_queue_head_init(&local->skb_queue); skb_queue_head_init(&local->skb_queue_unreliable); + /* init dummy netdev for use w/ NAPI */ + init_dummy_netdev(&local->napi_dev); + ieee80211_led_names(local); ieee80211_roc_setup(local); @@ -1017,6 +1021,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) goto fail_ifa6; #endif + netif_napi_add(&local->napi_dev, &local->napi, ieee80211_napi_poll, + local->hw.napi_weight); + return 0; #if IS_ENABLED(CONFIG_IPV6) diff --git a/trunk/net/mac80211/mesh.c b/trunk/net/mac80211/mesh.c index 5ac017f3fcd2..29ce2aa87e7b 100644 --- a/trunk/net/mac80211/mesh.c +++ b/trunk/net/mac80211/mesh.c @@ -13,6 +13,10 @@ #include "ieee80211_i.h" #include "mesh.h" +#define TMR_RUNNING_HK 0 +#define TMR_RUNNING_MP 1 +#define TMR_RUNNING_MPR 2 + static int mesh_allocated; static struct kmem_cache *rm_cache; @@ -46,6 +50,11 @@ static void ieee80211_mesh_housekeeping_timer(unsigned long data) set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags); + if (local->quiescing) { + set_bit(TMR_RUNNING_HK, &ifmsh->timers_running); + return; + } + ieee80211_queue_work(&local->hw, &sdata->work); } @@ -156,7 +165,7 @@ void mesh_sta_cleanup(struct sta_info *sta) * an update. */ changed = mesh_accept_plinks_update(sdata); - if (!sdata->u.mesh.user_mpm) { + if (sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) { changed |= mesh_plink_deactivate(sta); del_timer_sync(&sta->plink_timer); } @@ -470,8 +479,15 @@ static void ieee80211_mesh_path_timer(unsigned long data) { struct ieee80211_sub_if_data *sdata = (struct ieee80211_sub_if_data *) data; + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; + struct ieee80211_local *local = sdata->local; + + if (local->quiescing) { + set_bit(TMR_RUNNING_MP, &ifmsh->timers_running); + return; + } - ieee80211_queue_work(&sdata->local->hw, &sdata->work); + ieee80211_queue_work(&local->hw, &sdata->work); } static void ieee80211_mesh_path_root_timer(unsigned long data) @@ -479,10 +495,16 @@ static void ieee80211_mesh_path_root_timer(unsigned long data) struct ieee80211_sub_if_data *sdata = (struct ieee80211_sub_if_data *) data; struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; + struct ieee80211_local *local = sdata->local; set_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags); - ieee80211_queue_work(&sdata->local->hw, &sdata->work); + if (local->quiescing) { + set_bit(TMR_RUNNING_MPR, &ifmsh->timers_running); + return; + } + + ieee80211_queue_work(&local->hw, &sdata->work); } void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh) @@ -600,6 +622,35 @@ static void ieee80211_mesh_rootpath(struct ieee80211_sub_if_data *sdata) round_jiffies(TU_TO_EXP_TIME(interval))); } +#ifdef CONFIG_PM +void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; + + /* use atomic bitops in case all timers fire at the same time */ + + if (del_timer_sync(&ifmsh->housekeeping_timer)) + set_bit(TMR_RUNNING_HK, &ifmsh->timers_running); + if (del_timer_sync(&ifmsh->mesh_path_timer)) + set_bit(TMR_RUNNING_MP, &ifmsh->timers_running); + if (del_timer_sync(&ifmsh->mesh_path_root_timer)) + set_bit(TMR_RUNNING_MPR, &ifmsh->timers_running); +} + +void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; + + if (test_and_clear_bit(TMR_RUNNING_HK, &ifmsh->timers_running)) + add_timer(&ifmsh->housekeeping_timer); + if (test_and_clear_bit(TMR_RUNNING_MP, &ifmsh->timers_running)) + add_timer(&ifmsh->mesh_path_timer); + if (test_and_clear_bit(TMR_RUNNING_MPR, &ifmsh->timers_running)) + add_timer(&ifmsh->mesh_path_root_timer); + ieee80211_mesh_root_setup(ifmsh); +} +#endif + static int ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh) { @@ -820,6 +871,8 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) local->fif_other_bss--; atomic_dec(&local->iff_allmultis); ieee80211_configure_filter(local); + + sdata->u.mesh.timers_running = 0; } static void diff --git a/trunk/net/mac80211/mesh.h b/trunk/net/mac80211/mesh.h index 6ffabbe99c46..336c88a16687 100644 --- a/trunk/net/mac80211/mesh.h +++ b/trunk/net/mac80211/mesh.h @@ -313,6 +313,8 @@ void mesh_path_timer(unsigned long data); void mesh_path_flush_by_nexthop(struct sta_info *sta); void mesh_path_discard_frame(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); +void mesh_path_quiesce(struct ieee80211_sub_if_data *sdata); +void mesh_path_restart(struct ieee80211_sub_if_data *sdata); void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata); bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt); @@ -357,12 +359,22 @@ static inline bool mesh_path_sel_is_hwmp(struct ieee80211_sub_if_data *sdata) void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local); +void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata); +void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata); +void mesh_plink_quiesce(struct sta_info *sta); +void mesh_plink_restart(struct sta_info *sta); void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata); void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata); void ieee80211s_stop(void); #else static inline void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) {} +static inline void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata) +{} +static inline void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata) +{} +static inline void mesh_plink_quiesce(struct sta_info *sta) {} +static inline void mesh_plink_restart(struct sta_info *sta) {} static inline bool mesh_path_sel_is_hwmp(struct ieee80211_sub_if_data *sdata) { return false; } static inline void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata) diff --git a/trunk/net/mac80211/mesh_plink.c b/trunk/net/mac80211/mesh_plink.c index 937e06fe8f2a..07d396d57079 100644 --- a/trunk/net/mac80211/mesh_plink.c +++ b/trunk/net/mac80211/mesh_plink.c @@ -420,6 +420,7 @@ __mesh_sta_info_alloc(struct ieee80211_sub_if_data *sdata, u8 *hw_addr) return NULL; sta->plink_state = NL80211_PLINK_LISTEN; + init_timer(&sta->plink_timer); sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); @@ -436,9 +437,8 @@ mesh_sta_info_alloc(struct ieee80211_sub_if_data *sdata, u8 *addr, { struct sta_info *sta = NULL; - /* Userspace handles station allocation */ - if (sdata->u.mesh.user_mpm || - sdata->u.mesh.security & IEEE80211_MESH_SEC_AUTHED) + /* Userspace handles peer allocation when security is enabled */ + if (sdata->u.mesh.security & IEEE80211_MESH_SEC_AUTHED) cfg80211_notify_new_peer_candidate(sdata->dev, addr, elems->ie_start, elems->total_len, @@ -534,8 +534,10 @@ static void mesh_plink_timer(unsigned long data) */ sta = (struct sta_info *) data; - if (sta->sdata->local->quiescing) + if (sta->sdata->local->quiescing) { + sta->plink_timer_was_running = true; return; + } spin_lock_bh(&sta->lock); if (sta->ignore_plink_timer) { @@ -596,6 +598,29 @@ static void mesh_plink_timer(unsigned long data) } } +#ifdef CONFIG_PM +void mesh_plink_quiesce(struct sta_info *sta) +{ + if (!ieee80211_vif_is_mesh(&sta->sdata->vif)) + return; + + /* no kernel mesh sta timers have been initialized */ + if (sta->sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE) + return; + + if (del_timer_sync(&sta->plink_timer)) + sta->plink_timer_was_running = true; +} + +void mesh_plink_restart(struct sta_info *sta) +{ + if (sta->plink_timer_was_running) { + add_timer(&sta->plink_timer); + sta->plink_timer_was_running = false; + } +} +#endif + static inline void mesh_plink_timer_set(struct sta_info *sta, int timeout) { sta->plink_timer.expires = jiffies + (HZ * timeout / 1000); @@ -670,10 +695,6 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, if (len < IEEE80211_MIN_ACTION_SIZE + 3) return; - if (sdata->u.mesh.user_mpm) - /* userspace must register for these */ - return; - if (is_multicast_ether_addr(mgmt->da)) { mpl_dbg(sdata, "Mesh plink: ignore frame from multicast address\n"); diff --git a/trunk/net/mac80211/mlme.c b/trunk/net/mac80211/mlme.c index fdc06e381c10..9f6464f3e05f 100644 --- a/trunk/net/mac80211/mlme.c +++ b/trunk/net/mac80211/mlme.c @@ -87,6 +87,9 @@ MODULE_PARM_DESC(probe_wait_ms, */ #define IEEE80211_SIGNAL_AVE_MIN_COUNT 4 +#define TMR_RUNNING_TIMER 0 +#define TMR_RUNNING_CHANSW 1 + /* * All cfg80211 functions have to be called outside a locked * section so that they can acquire a lock themselves... This @@ -606,7 +609,6 @@ static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata, BUILD_BUG_ON(sizeof(vht_cap) != sizeof(sband->vht_cap)); memcpy(&vht_cap, &sband->vht_cap, sizeof(vht_cap)); - ieee80211_apply_vhtcap_overrides(sdata, &vht_cap); /* determine capability flags */ cap = vht_cap.cap; @@ -645,9 +647,6 @@ static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata, our_mcs = (le16_to_cpu(vht_cap.vht_mcs.rx_mcs_map) & mask) >> shift; - if (our_mcs == IEEE80211_VHT_MCS_NOT_SUPPORTED) - continue; - switch (ap_mcs) { default: if (our_mcs <= ap_mcs) @@ -1036,8 +1035,14 @@ static void ieee80211_chswitch_timer(unsigned long data) { struct ieee80211_sub_if_data *sdata = (struct ieee80211_sub_if_data *) data; + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; - ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.chswitch_work); + if (sdata->local->quiescing) { + set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running); + return; + } + + ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work); } void @@ -1794,11 +1799,9 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, sdata->vif.bss_conf.p2p_ctwindow = 0; sdata->vif.bss_conf.p2p_oppps = false; - /* on the next assoc, re-program HT/VHT parameters */ + /* on the next assoc, re-program HT parameters */ memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa)); memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask)); - memset(&ifmgd->vht_capa, 0, sizeof(ifmgd->vht_capa)); - memset(&ifmgd->vht_capa_mask, 0, sizeof(ifmgd->vht_capa_mask)); sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL; @@ -1824,6 +1827,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, del_timer_sync(&sdata->u.mgd.timer); del_timer_sync(&sdata->u.mgd.chswitch_timer); + sdata->u.mgd.timers_running = 0; + sdata->vif.bss_conf.dtim_period = 0; ifmgd->flags = 0; @@ -3132,8 +3137,15 @@ static void ieee80211_sta_timer(unsigned long data) { struct ieee80211_sub_if_data *sdata = (struct ieee80211_sub_if_data *) data; + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + struct ieee80211_local *local = sdata->local; + + if (local->quiescing) { + set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running); + return; + } - ieee80211_queue_work(&sdata->local->hw, &sdata->work); + ieee80211_queue_work(&local->hw, &sdata->work); } static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata, @@ -3485,6 +3497,68 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) } } +#ifdef CONFIG_PM +void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + + /* + * we need to use atomic bitops for the running bits + * only because both timers might fire at the same + * time -- the code here is properly synchronised. + */ + + cancel_work_sync(&ifmgd->request_smps_work); + + cancel_work_sync(&ifmgd->monitor_work); + cancel_work_sync(&ifmgd->beacon_connection_loss_work); + cancel_work_sync(&ifmgd->csa_connection_drop_work); + if (del_timer_sync(&ifmgd->timer)) + set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running); + + cancel_work_sync(&ifmgd->chswitch_work); + if (del_timer_sync(&ifmgd->chswitch_timer)) + set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running); + + /* these will just be re-established on connection */ + del_timer_sync(&ifmgd->conn_mon_timer); + del_timer_sync(&ifmgd->bcn_mon_timer); +} + +void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + + mutex_lock(&ifmgd->mtx); + if (!ifmgd->associated) { + mutex_unlock(&ifmgd->mtx); + return; + } + + if (sdata->flags & IEEE80211_SDATA_DISCONNECT_RESUME) { + sdata->flags &= ~IEEE80211_SDATA_DISCONNECT_RESUME; + mlme_dbg(sdata, "driver requested disconnect after resume\n"); + ieee80211_sta_connection_lost(sdata, + ifmgd->associated->bssid, + WLAN_REASON_UNSPECIFIED, + true); + mutex_unlock(&ifmgd->mtx); + return; + } + mutex_unlock(&ifmgd->mtx); + + if (test_and_clear_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running)) + add_timer(&ifmgd->timer); + if (test_and_clear_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running)) + add_timer(&ifmgd->chswitch_timer); + ieee80211_sta_reset_beacon_monitor(sdata); + + mutex_lock(&sdata->local->mtx); + ieee80211_restart_sta_timer(sdata); + mutex_unlock(&sdata->local->mtx); +} +#endif + /* interface setup */ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) { @@ -3990,9 +4064,6 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; } - if (req->flags & ASSOC_REQ_DISABLE_VHT) - ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; - /* Also disable HT if we don't support it or the AP doesn't use WMM */ sband = local->hw.wiphy->bands[req->bss->channel->band]; if (!sband->ht_cap.ht_supported || @@ -4016,10 +4087,6 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, memcpy(&ifmgd->ht_capa_mask, &req->ht_capa_mask, sizeof(ifmgd->ht_capa_mask)); - memcpy(&ifmgd->vht_capa, &req->vht_capa, sizeof(ifmgd->vht_capa)); - memcpy(&ifmgd->vht_capa_mask, &req->vht_capa_mask, - sizeof(ifmgd->vht_capa_mask)); - if (req->ie && req->ie_len) { memcpy(assoc_data->ie, req->ie, req->ie_len); assoc_data->ie_len = req->ie_len; @@ -4248,17 +4315,6 @@ void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; - /* - * Make sure some work items will not run after this, - * they will not do anything but might not have been - * cancelled when disconnecting. - */ - cancel_work_sync(&ifmgd->monitor_work); - cancel_work_sync(&ifmgd->beacon_connection_loss_work); - cancel_work_sync(&ifmgd->request_smps_work); - cancel_work_sync(&ifmgd->csa_connection_drop_work); - cancel_work_sync(&ifmgd->chswitch_work); - mutex_lock(&ifmgd->mtx); if (ifmgd->assoc_data) ieee80211_destroy_assoc_data(sdata, false); diff --git a/trunk/net/mac80211/offchannel.c b/trunk/net/mac80211/offchannel.c index db547fceaeb9..cc79b4a2e821 100644 --- a/trunk/net/mac80211/offchannel.c +++ b/trunk/net/mac80211/offchannel.c @@ -277,7 +277,7 @@ void ieee80211_start_next_roc(struct ieee80211_local *local) duration = 10; ret = drv_remain_on_channel(local, roc->sdata, roc->chan, - duration, roc->type); + duration); roc->started = true; diff --git a/trunk/net/mac80211/pm.c b/trunk/net/mac80211/pm.c index b471a67f224d..d0275f34bf70 100644 --- a/trunk/net/mac80211/pm.c +++ b/trunk/net/mac80211/pm.c @@ -6,11 +6,32 @@ #include "driver-ops.h" #include "led.h" +/* return value indicates whether the driver should be further notified */ +static void ieee80211_quiesce(struct ieee80211_sub_if_data *sdata) +{ + switch (sdata->vif.type) { + case NL80211_IFTYPE_STATION: + ieee80211_sta_quiesce(sdata); + break; + case NL80211_IFTYPE_ADHOC: + ieee80211_ibss_quiesce(sdata); + break; + case NL80211_IFTYPE_MESH_POINT: + ieee80211_mesh_quiesce(sdata); + break; + default: + break; + } + + cancel_work_sync(&sdata->work); +} + 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; @@ -72,12 +93,19 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) return err; } else if (err > 0) { WARN_ON(err != 1); - return err; + local->wowlan = false; } else { + list_for_each_entry(sdata, &local->interfaces, list) + if (ieee80211_sdata_running(sdata)) + ieee80211_quiesce(sdata); goto suspend; } } + /* disable keys */ + list_for_each_entry(sdata, &local->interfaces, list) + ieee80211_disable_keys(sdata); + /* tear down aggregation sessions and remove STAs */ mutex_lock(&local->sta_mtx); list_for_each_entry(sta, &local->sta_list, list) { @@ -89,25 +117,100 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) WARN_ON(drv_sta_state(local, sta->sdata, sta, state, state - 1)); } + + mesh_plink_quiesce(sta); } mutex_unlock(&local->sta_mtx); /* remove all interfaces */ list_for_each_entry(sdata, &local->interfaces, list) { + static u8 zero_addr[ETH_ALEN] = {}; + u32 changed = 0; + if (!ieee80211_sdata_running(sdata)) continue; + + switch (sdata->vif.type) { + case NL80211_IFTYPE_AP_VLAN: + case NL80211_IFTYPE_MONITOR: + /* skip these */ + continue; + case NL80211_IFTYPE_STATION: + if (sdata->vif.bss_conf.assoc) + changed = BSS_CHANGED_ASSOC | + BSS_CHANGED_BSSID | + BSS_CHANGED_IDLE; + break; + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_MESH_POINT: + if (sdata->vif.bss_conf.enable_beacon) + changed = BSS_CHANGED_BEACON_ENABLED; + break; + default: + break; + } + + ieee80211_quiesce(sdata); + + sdata->suspend_bss_conf = sdata->vif.bss_conf; + memset(&sdata->vif.bss_conf, 0, sizeof(sdata->vif.bss_conf)); + sdata->vif.bss_conf.idle = true; + if (sdata->suspend_bss_conf.bssid) + sdata->vif.bss_conf.bssid = zero_addr; + + /* disable beaconing or remove association */ + ieee80211_bss_info_change_notify(sdata, changed); + + if (sdata->vif.type == NL80211_IFTYPE_AP && + 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); + } drv_remove_interface(local, sdata); } sdata = rtnl_dereference(local->monitor_sdata); - if (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); + } + drv_remove_interface(local, sdata); + } - /* - * We disconnected on all interfaces before suspend, all channel - * contexts should be released. - */ - WARN_ON(!list_empty(&local->chanctx_list)); + 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/rc80211_minstrel.c b/trunk/net/mac80211/rc80211_minstrel.c index 1c36c9b4fa4a..eea45a2c7c35 100644 --- a/trunk/net/mac80211/rc80211_minstrel.c +++ b/trunk/net/mac80211/rc80211_minstrel.c @@ -55,6 +55,7 @@ #include "rate.h" #include "rc80211_minstrel.h" +#define SAMPLE_COLUMNS 10 #define SAMPLE_TBL(_mi, _idx, _col) \ _mi->sample_table[(_idx * SAMPLE_COLUMNS) + _col] @@ -69,31 +70,16 @@ rix_to_ndx(struct minstrel_sta_info *mi, int rix) return i; } -/* find & sort topmost throughput rates */ -static inline void -minstrel_sort_best_tp_rates(struct minstrel_sta_info *mi, int i, u8 *tp_list) -{ - int j = MAX_THR_RATES; - - while (j > 0 && mi->r[i].cur_tp > mi->r[tp_list[j - 1]].cur_tp) - j--; - if (j < MAX_THR_RATES - 1) - memmove(&tp_list[j + 1], &tp_list[j], MAX_THR_RATES - (j + 1)); - if (j < MAX_THR_RATES) - tp_list[j] = i; -} - static void minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) { - u8 tmp_tp_rate[MAX_THR_RATES]; - u8 tmp_prob_rate = 0; + u32 max_tp = 0, index_max_tp = 0, index_max_tp2 = 0; + u32 max_prob = 0, index_max_prob = 0; u32 usecs; + u32 p; int i; - for (i=0; i < MAX_THR_RATES; i++) - tmp_tp_rate[i] = 0; - + mi->stats_update = jiffies; for (i = 0; i < mi->n_rates; i++) { struct minstrel_rate *mr = &mi->r[i]; @@ -101,32 +87,27 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) if (!usecs) usecs = 1000000; - if (unlikely(mr->attempts > 0)) { - mr->sample_skipped = 0; - mr->cur_prob = MINSTREL_FRAC(mr->success, mr->attempts); + /* To avoid rounding issues, probabilities scale from 0 (0%) + * to 18000 (100%) */ + if (mr->attempts) { + p = (mr->success * 18000) / mr->attempts; mr->succ_hist += mr->success; mr->att_hist += mr->attempts; - mr->probability = minstrel_ewma(mr->probability, - mr->cur_prob, - EWMA_LEVEL); - } else - mr->sample_skipped++; + mr->cur_prob = p; + p = ((p * (100 - mp->ewma_level)) + (mr->probability * + mp->ewma_level)) / 100; + mr->probability = p; + mr->cur_tp = p * (1000000 / usecs); + } mr->last_success = mr->success; mr->last_attempts = mr->attempts; mr->success = 0; mr->attempts = 0; - /* Update throughput per rate, reset thr. below 10% success */ - if (mr->probability < MINSTREL_FRAC(10, 100)) - mr->cur_tp = 0; - else - mr->cur_tp = mr->probability * (1000000 / usecs); - /* Sample less often below the 10% chance of success. * Sample less often above the 95% chance of success. */ - if (mr->probability > MINSTREL_FRAC(95, 100) || - mr->probability < MINSTREL_FRAC(10, 100)) { + if ((mr->probability > 17100) || (mr->probability < 1800)) { mr->adjusted_retry_count = mr->retry_count >> 1; if (mr->adjusted_retry_count > 2) mr->adjusted_retry_count = 2; @@ -137,30 +118,35 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) } if (!mr->adjusted_retry_count) mr->adjusted_retry_count = 2; + } - minstrel_sort_best_tp_rates(mi, i, tmp_tp_rate); - - /* To determine the most robust rate (max_prob_rate) used at - * 3rd mmr stage we distinct between two cases: - * (1) if any success probabilitiy >= 95%, out of those rates - * choose the maximum throughput rate as max_prob_rate - * (2) if all success probabilities < 95%, the rate with - * highest success probability is choosen as max_prob_rate */ - if (mr->probability >= MINSTREL_FRAC(95,100)) { - if (mr->cur_tp >= mi->r[tmp_prob_rate].cur_tp) - tmp_prob_rate = i; - } else { - if (mr->probability >= mi->r[tmp_prob_rate].probability) - tmp_prob_rate = i; + for (i = 0; i < mi->n_rates; i++) { + struct minstrel_rate *mr = &mi->r[i]; + if (max_tp < mr->cur_tp) { + index_max_tp = i; + max_tp = mr->cur_tp; + } + if (max_prob < mr->probability) { + index_max_prob = i; + max_prob = mr->probability; } } - /* Assign the new rate set */ - memcpy(mi->max_tp_rate, tmp_tp_rate, sizeof(mi->max_tp_rate)); - mi->max_prob_rate = tmp_prob_rate; + max_tp = 0; + for (i = 0; i < mi->n_rates; i++) { + struct minstrel_rate *mr = &mi->r[i]; - /* Reset update timer */ - mi->stats_update = jiffies; + if (i == index_max_tp) + continue; + + if (max_tp < mr->cur_tp) { + index_max_tp2 = i; + max_tp = mr->cur_tp; + } + } + mi->max_tp_rate = index_max_tp; + mi->max_tp_rate2 = index_max_tp2; + mi->max_prob_rate = index_max_prob; } static void @@ -221,10 +207,10 @@ static int minstrel_get_next_sample(struct minstrel_sta_info *mi) { unsigned int sample_ndx; - sample_ndx = SAMPLE_TBL(mi, mi->sample_row, mi->sample_column); - mi->sample_row++; - if ((int) mi->sample_row >= mi->n_rates) { - mi->sample_row = 0; + sample_ndx = SAMPLE_TBL(mi, mi->sample_idx, mi->sample_column); + mi->sample_idx++; + if ((int) mi->sample_idx > (mi->n_rates - 2)) { + mi->sample_idx = 0; mi->sample_column++; if (mi->sample_column >= SAMPLE_COLUMNS) mi->sample_column = 0; @@ -242,37 +228,31 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta, struct minstrel_priv *mp = priv; struct ieee80211_tx_rate *ar = info->control.rates; unsigned int ndx, sample_ndx = 0; - bool mrr_capable; - bool indirect_rate_sampling = false; - bool rate_sampling = false; + bool mrr; + bool sample_slower = false; + bool sample = false; int i, delta; int mrr_ndx[3]; - int sampling_ratio; + int sample_rate; - /* management/no-ack frames do not use rate control */ if (rate_control_send_low(sta, priv_sta, txrc)) return; - /* check multi-rate-retry capabilities & adjust lookaround_rate */ - mrr_capable = mp->has_mrr && - !txrc->rts && - !txrc->bss_conf->use_cts_prot; - if (mrr_capable) - sampling_ratio = mp->lookaround_rate_mrr; - else - sampling_ratio = mp->lookaround_rate; + mrr = mp->has_mrr && !txrc->rts && !txrc->bss_conf->use_cts_prot; - /* init rateindex [ndx] with max throughput rate */ - ndx = mi->max_tp_rate[0]; + ndx = mi->max_tp_rate; - /* increase sum packet counter */ - mi->packet_count++; + if (mrr) + sample_rate = mp->lookaround_rate_mrr; + else + sample_rate = mp->lookaround_rate; - delta = (mi->packet_count * sampling_ratio / 100) - + mi->packet_count++; + delta = (mi->packet_count * sample_rate / 100) - (mi->sample_count + mi->sample_deferred / 2); /* delta > 0: sampling required */ - if ((delta > 0) && (mrr_capable || !mi->prev_sample)) { + if ((delta > 0) && (mrr || !mi->prev_sample)) { struct minstrel_rate *msr; if (mi->packet_count >= 10000) { mi->sample_deferred = 0; @@ -291,28 +271,21 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta, mi->sample_count += (delta - mi->n_rates * 2); } - /* get next random rate sample */ sample_ndx = minstrel_get_next_sample(mi); msr = &mi->r[sample_ndx]; - rate_sampling = true; - - /* Decide if direct ( 1st mrr stage) or indirect (2nd mrr stage) - * rate sampling method should be used. - * Respect such rates that are not sampled for 20 interations. - */ - if (mrr_capable && - msr->perfect_tx_time > mi->r[ndx].perfect_tx_time && - msr->sample_skipped < 20) - indirect_rate_sampling = true; - - if (!indirect_rate_sampling) { + sample = true; + sample_slower = mrr && (msr->perfect_tx_time > + mi->r[ndx].perfect_tx_time); + + if (!sample_slower) { if (msr->sample_limit != 0) { ndx = sample_ndx; mi->sample_count++; if (msr->sample_limit > 0) msr->sample_limit--; - } else - rate_sampling = false; + } else { + sample = false; + } } else { /* Only use IEEE80211_TX_CTL_RATE_CTRL_PROBE to mark * packets that have the sampling rate deferred to the @@ -324,39 +297,34 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta, mi->sample_deferred++; } } - mi->prev_sample = rate_sampling; + mi->prev_sample = sample; /* If we're not using MRR and the sampling rate already * has a probability of >95%, we shouldn't be attempting * to use it, as this only wastes precious airtime */ - if (!mrr_capable && rate_sampling && - (mi->r[ndx].probability > MINSTREL_FRAC(95, 100))) - ndx = mi->max_tp_rate[0]; + if (!mrr && sample && (mi->r[ndx].probability > 17100)) + ndx = mi->max_tp_rate; - /* mrr setup for 1st stage */ ar[0].idx = mi->r[ndx].rix; ar[0].count = minstrel_get_retry_count(&mi->r[ndx], info); - /* non mrr setup for 2nd stage */ - if (!mrr_capable) { - if (!rate_sampling) + if (!mrr) { + if (!sample) ar[0].count = mp->max_retry; ar[1].idx = mi->lowest_rix; ar[1].count = mp->max_retry; return; } - /* mrr setup for 2nd stage */ - if (rate_sampling) { - if (indirect_rate_sampling) + /* MRR setup */ + if (sample) { + if (sample_slower) mrr_ndx[0] = sample_ndx; else - mrr_ndx[0] = mi->max_tp_rate[0]; + mrr_ndx[0] = mi->max_tp_rate; } else { - mrr_ndx[0] = mi->max_tp_rate[1]; + mrr_ndx[0] = mi->max_tp_rate2; } - - /* mrr setup for 3rd & 4th stage */ mrr_ndx[1] = mi->max_prob_rate; mrr_ndx[2] = 0; for (i = 1; i < 4; i++) { @@ -383,21 +351,26 @@ static void init_sample_table(struct minstrel_sta_info *mi) { unsigned int i, col, new_idx; + unsigned int n_srates = mi->n_rates - 1; u8 rnd[8]; mi->sample_column = 0; - mi->sample_row = 0; - memset(mi->sample_table, 0xff, SAMPLE_COLUMNS * mi->n_rates); + mi->sample_idx = 0; + memset(mi->sample_table, 0, SAMPLE_COLUMNS * mi->n_rates); for (col = 0; col < SAMPLE_COLUMNS; col++) { - for (i = 0; i < mi->n_rates; i++) { + for (i = 0; i < n_srates; i++) { get_random_bytes(rnd, sizeof(rnd)); - new_idx = (i + rnd[i & 7]) % mi->n_rates; + new_idx = (i + rnd[i & 7]) % n_srates; - while (SAMPLE_TBL(mi, new_idx, col) != 0xff) - new_idx = (new_idx + 1) % mi->n_rates; + while (SAMPLE_TBL(mi, new_idx, col) != 0) + new_idx = (new_idx + 1) % n_srates; - SAMPLE_TBL(mi, new_idx, col) = i; + /* Don't sample the slowest rate (i.e. slowest base + * rate). We must presume that the slowest rate works + * fine, or else other management frames will also be + * failing and the link will break */ + SAMPLE_TBL(mi, new_idx, col) = i + 1; } } } @@ -569,6 +542,9 @@ minstrel_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) mp->lookaround_rate = 5; mp->lookaround_rate_mrr = 10; + /* moving average weight for EWMA */ + mp->ewma_level = 75; + /* maximum time that the hw is allowed to stay in one MRR segment */ mp->segment_size = 6000; diff --git a/trunk/net/mac80211/rc80211_minstrel.h b/trunk/net/mac80211/rc80211_minstrel.h index 85ebf42cb46d..5ecf757817f2 100644 --- a/trunk/net/mac80211/rc80211_minstrel.h +++ b/trunk/net/mac80211/rc80211_minstrel.h @@ -9,28 +9,6 @@ #ifndef __RC_MINSTREL_H #define __RC_MINSTREL_H -#define EWMA_LEVEL 75 /* ewma weighting factor [%] */ -#define SAMPLE_COLUMNS 10 /* number of columns in sample table */ - - -/* scaled fraction values */ -#define MINSTREL_SCALE 16 -#define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / div) -#define MINSTREL_TRUNC(val) ((val) >> MINSTREL_SCALE) - -/* number of highest throughput rates to consider*/ -#define MAX_THR_RATES 4 - -/* - * Perform EWMA (Exponentially Weighted Moving Average) calculation - */ -static inline int -minstrel_ewma(int old, int new, int weight) -{ - return (new * (100 - weight) + old * weight) / 100; -} - - struct minstrel_rate { int bitrate; int rix; @@ -48,7 +26,6 @@ struct minstrel_rate { u32 attempts; u32 last_attempts; u32 last_success; - u8 sample_skipped; /* parts per thousand */ u32 cur_prob; @@ -68,13 +45,14 @@ struct minstrel_sta_info { unsigned int lowest_rix; - u8 max_tp_rate[MAX_THR_RATES]; - u8 max_prob_rate; + unsigned int max_tp_rate; + unsigned int max_tp_rate2; + unsigned int max_prob_rate; unsigned int packet_count; unsigned int sample_count; int sample_deferred; - unsigned int sample_row; + unsigned int sample_idx; unsigned int sample_column; int n_rates; @@ -95,6 +73,7 @@ struct minstrel_priv { unsigned int cw_min; unsigned int cw_max; unsigned int max_retry; + unsigned int ewma_level; unsigned int segment_size; unsigned int update_interval; unsigned int lookaround_rate; diff --git a/trunk/net/mac80211/rc80211_minstrel_debugfs.c b/trunk/net/mac80211/rc80211_minstrel_debugfs.c index d1048348d399..d5a56226e675 100644 --- a/trunk/net/mac80211/rc80211_minstrel_debugfs.c +++ b/trunk/net/mac80211/rc80211_minstrel_debugfs.c @@ -73,17 +73,15 @@ minstrel_stats_open(struct inode *inode, struct file *file) for (i = 0; i < mi->n_rates; i++) { struct minstrel_rate *mr = &mi->r[i]; - *(p++) = (i == mi->max_tp_rate[0]) ? 'A' : ' '; - *(p++) = (i == mi->max_tp_rate[1]) ? 'B' : ' '; - *(p++) = (i == mi->max_tp_rate[2]) ? 'C' : ' '; - *(p++) = (i == mi->max_tp_rate[3]) ? 'D' : ' '; + *(p++) = (i == mi->max_tp_rate) ? 'T' : ' '; + *(p++) = (i == mi->max_tp_rate2) ? 't' : ' '; *(p++) = (i == mi->max_prob_rate) ? 'P' : ' '; p += sprintf(p, "%3u%s", mr->bitrate / 2, (mr->bitrate & 1 ? ".5" : " ")); - tp = MINSTREL_TRUNC(mr->cur_tp / 10); - prob = MINSTREL_TRUNC(mr->cur_prob * 1000); - eprob = MINSTREL_TRUNC(mr->probability * 1000); + tp = mr->cur_tp / ((18000 << 10) / 96); + prob = mr->cur_prob / 18; + eprob = mr->probability / 18; p += sprintf(p, " %6u.%1u %6u.%1u %6u.%1u " "%3u(%3u) %8llu %8llu\n", diff --git a/trunk/net/mac80211/rc80211_minstrel_ht.c b/trunk/net/mac80211/rc80211_minstrel_ht.c index 749552bdcfe1..3af141c69712 100644 --- a/trunk/net/mac80211/rc80211_minstrel_ht.c +++ b/trunk/net/mac80211/rc80211_minstrel_ht.c @@ -17,6 +17,8 @@ #include "rc80211_minstrel_ht.h" #define AVG_PKT_SIZE 1200 +#define SAMPLE_COLUMNS 10 +#define EWMA_LEVEL 75 /* Number of bits for an average sized packet */ #define MCS_NBITS (AVG_PKT_SIZE << 3) @@ -24,11 +26,11 @@ /* Number of symbols for a packet with (bps) bits per symbol */ #define MCS_NSYMS(bps) ((MCS_NBITS + (bps) - 1) / (bps)) -/* Transmission time (nanoseconds) for a packet containing (syms) symbols */ +/* Transmission time for a packet containing (syms) symbols */ #define MCS_SYMBOL_TIME(sgi, syms) \ (sgi ? \ - ((syms) * 18000 + 4000) / 5 : /* syms * 3.6 us */ \ - ((syms) * 1000) << 2 /* syms * 4 us */ \ + ((syms) * 18 + 4) / 5 : /* syms * 3.6 us */ \ + (syms) << 2 /* syms * 4 us */ \ ) /* Transmit duration for the raw data part of an average sized packet */ @@ -62,9 +64,9 @@ } #define CCK_DURATION(_bitrate, _short, _len) \ - (1000 * (10 /* SIFS */ + \ + (10 /* SIFS */ + \ (_short ? 72 + 24 : 144 + 48 ) + \ - (8 * (_len + 4) * 10) / (_bitrate))) + (8 * (_len + 4) * 10) / (_bitrate)) #define CCK_ACK_DURATION(_bitrate, _short) \ (CCK_DURATION((_bitrate > 10 ? 20 : 10), false, 60) + \ @@ -126,6 +128,15 @@ const struct mcs_group minstrel_mcs_groups[] = { static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES]; +/* + * Perform EWMA (Exponentially Weighted Moving Average) calculation + */ +static int +minstrel_ewma(int old, int new, int weight) +{ + return (new * (100 - weight) + old * weight) / 100; +} + /* * Look up an MCS group index based on mac80211 rate information */ @@ -200,8 +211,7 @@ static void minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int group, int rate) { struct minstrel_rate_stats *mr; - unsigned int nsecs = 0; - unsigned int tp; + unsigned int usecs = 0; mr = &mi->groups[group].rates[rate]; @@ -211,12 +221,10 @@ minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int group, int rate) } if (group != MINSTREL_CCK_GROUP) - nsecs = 1000 * mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len); + usecs = mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len); - nsecs += minstrel_mcs_groups[group].duration[rate]; - tp = 1000000 * ((mr->probability * 1000) / nsecs); - - mr->cur_tp = MINSTREL_TRUNC(tp); + usecs += minstrel_mcs_groups[group].duration[rate]; + mr->cur_tp = MINSTREL_TRUNC((1000000 / usecs) * mr->probability); } /* @@ -300,8 +308,8 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) } } - /* try to sample all available rates during each interval */ - mi->sample_count *= 8; + /* try to sample up to half of the available rates during each interval */ + mi->sample_count *= 4; cur_prob = 0; cur_prob_tp = 0; @@ -312,13 +320,20 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) if (!mg->supported) continue; + mr = minstrel_get_ratestats(mi, mg->max_prob_rate); + if (cur_prob_tp < mr->cur_tp && + minstrel_mcs_groups[group].streams == 1) { + mi->max_prob_rate = mg->max_prob_rate; + cur_prob = mr->cur_prob; + cur_prob_tp = mr->cur_tp; + } + mr = minstrel_get_ratestats(mi, mg->max_tp_rate); if (cur_tp < mr->cur_tp) { mi->max_tp_rate2 = mi->max_tp_rate; cur_tp2 = cur_tp; mi->max_tp_rate = mg->max_tp_rate; cur_tp = mr->cur_tp; - mi->max_prob_streams = minstrel_mcs_groups[group].streams - 1; } mr = minstrel_get_ratestats(mi, mg->max_tp_rate2); @@ -328,23 +343,6 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) } } - if (mi->max_prob_streams < 1) - mi->max_prob_streams = 1; - - for (group = 0; group < ARRAY_SIZE(minstrel_mcs_groups); group++) { - mg = &mi->groups[group]; - if (!mg->supported) - continue; - mr = minstrel_get_ratestats(mi, mg->max_prob_rate); - if (cur_prob_tp < mr->cur_tp && - minstrel_mcs_groups[group].streams <= mi->max_prob_streams) { - mi->max_prob_rate = mg->max_prob_rate; - cur_prob = mr->cur_prob; - cur_prob_tp = mr->cur_tp; - } - } - - mi->stats_update = jiffies; } @@ -469,7 +467,7 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband, if (!mi->sample_wait && !mi->sample_tries && mi->sample_count > 0) { mi->sample_wait = 16 + 2 * MINSTREL_TRUNC(mi->avg_ampdu_len); - mi->sample_tries = 1; + mi->sample_tries = 2; mi->sample_count--; } @@ -538,7 +536,7 @@ minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, mr->retry_updated = true; group = &minstrel_mcs_groups[index / MCS_GROUP_RATES]; - tx_time_data = group->duration[index % MCS_GROUP_RATES] * ampdu_len / 1000; + tx_time_data = group->duration[index % MCS_GROUP_RATES] * ampdu_len; /* Contention time for first 2 tries */ ctime = (t_slot * cw) >> 1; @@ -618,7 +616,6 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) { struct minstrel_rate_stats *mr; struct minstrel_mcs_group_data *mg; - unsigned int sample_dur, sample_group; int sample_idx = 0; if (mi->sample_wait > 0) { @@ -629,11 +626,11 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) if (!mi->sample_tries) return -1; + mi->sample_tries--; mg = &mi->groups[mi->sample_group]; sample_idx = sample_table[mg->column][mg->index]; mr = &mg->rates[sample_idx]; - sample_group = mi->sample_group; - sample_idx += sample_group * MCS_GROUP_RATES; + sample_idx += mi->sample_group * MCS_GROUP_RATES; minstrel_next_sample_idx(mi); /* @@ -654,18 +651,14 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) * Make sure that lower rates get sampled only occasionally, * if the link is working perfectly. */ - sample_dur = minstrel_get_duration(sample_idx); - if (sample_dur >= minstrel_get_duration(mi->max_tp_rate2) && - (mi->max_prob_streams < - minstrel_mcs_groups[sample_group].streams || - sample_dur >= minstrel_get_duration(mi->max_prob_rate))) { + if (minstrel_get_duration(sample_idx) > + minstrel_get_duration(mi->max_tp_rate)) { if (mr->sample_skipped < 20) return -1; if (mi->sample_slow++ > 2) return -1; } - mi->sample_tries--; return sample_idx; } diff --git a/trunk/net/mac80211/rc80211_minstrel_ht.h b/trunk/net/mac80211/rc80211_minstrel_ht.h index 9b16e9de9923..302dbd52180d 100644 --- a/trunk/net/mac80211/rc80211_minstrel_ht.h +++ b/trunk/net/mac80211/rc80211_minstrel_ht.h @@ -16,6 +16,11 @@ #define MINSTREL_MAX_STREAMS 3 #define MINSTREL_STREAM_GROUPS 4 +/* scaled fraction values */ +#define MINSTREL_SCALE 16 +#define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / div) +#define MINSTREL_TRUNC(val) ((val) >> MINSTREL_SCALE) + #define MCS_GROUP_RATES 8 struct mcs_group { @@ -80,7 +85,6 @@ struct minstrel_ht_sta { /* best probability rate */ unsigned int max_prob_rate; - unsigned int max_prob_streams; /* time of last status update */ unsigned long stats_update; diff --git a/trunk/net/mac80211/rx.c b/trunk/net/mac80211/rx.c index 5b4492af4e85..bb73ed2d20b9 100644 --- a/trunk/net/mac80211/rx.c +++ b/trunk/net/mac80211/rx.c @@ -648,6 +648,24 @@ static ieee80211_rx_result ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) return RX_CONTINUE; } +#define SEQ_MODULO 0x1000 +#define SEQ_MASK 0xfff + +static inline int seq_less(u16 sq1, u16 sq2) +{ + return ((sq1 - sq2) & SEQ_MASK) > (SEQ_MODULO >> 1); +} + +static inline u16 seq_inc(u16 sq) +{ + return (sq + 1) & SEQ_MASK; +} + +static inline u16 seq_sub(u16 sq1, u16 sq2) +{ + return (sq1 - sq2) & SEQ_MASK; +} + static void ieee80211_release_reorder_frame(struct ieee80211_sub_if_data *sdata, struct tid_ampdu_rx *tid_agg_rx, int index, @@ -669,7 +687,7 @@ static void ieee80211_release_reorder_frame(struct ieee80211_sub_if_data *sdata, __skb_queue_tail(frames, skb); no_frame: - tid_agg_rx->head_seq_num = ieee80211_sn_inc(tid_agg_rx->head_seq_num); + tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); } static void ieee80211_release_reorder_frames(struct ieee80211_sub_if_data *sdata, @@ -681,9 +699,8 @@ static void ieee80211_release_reorder_frames(struct ieee80211_sub_if_data *sdata lockdep_assert_held(&tid_agg_rx->reorder_lock); - while (ieee80211_sn_less(tid_agg_rx->head_seq_num, head_seq_num)) { - index = ieee80211_sn_sub(tid_agg_rx->head_seq_num, - tid_agg_rx->ssn) % + while (seq_less(tid_agg_rx->head_seq_num, head_seq_num)) { + index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % tid_agg_rx->buf_size; ieee80211_release_reorder_frame(sdata, tid_agg_rx, index, frames); @@ -710,8 +727,8 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata, lockdep_assert_held(&tid_agg_rx->reorder_lock); /* release the buffer until next missing frame */ - index = ieee80211_sn_sub(tid_agg_rx->head_seq_num, - tid_agg_rx->ssn) % tid_agg_rx->buf_size; + index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % + tid_agg_rx->buf_size; if (!tid_agg_rx->reorder_buf[index] && tid_agg_rx->stored_mpdu_num) { /* @@ -739,22 +756,19 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata, * Increment the head seq# also for the skipped slots. */ tid_agg_rx->head_seq_num = - (tid_agg_rx->head_seq_num + - skipped) & IEEE80211_SN_MASK; + (tid_agg_rx->head_seq_num + skipped) & SEQ_MASK; skipped = 0; } } else while (tid_agg_rx->reorder_buf[index]) { ieee80211_release_reorder_frame(sdata, tid_agg_rx, index, frames); - index = ieee80211_sn_sub(tid_agg_rx->head_seq_num, - tid_agg_rx->ssn) % + index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % tid_agg_rx->buf_size; } if (tid_agg_rx->stored_mpdu_num) { - j = index = ieee80211_sn_sub(tid_agg_rx->head_seq_num, - tid_agg_rx->ssn) % - tid_agg_rx->buf_size; + j = index = seq_sub(tid_agg_rx->head_seq_num, + tid_agg_rx->ssn) % tid_agg_rx->buf_size; for (; j != (index - 1) % tid_agg_rx->buf_size; j = (j + 1) % tid_agg_rx->buf_size) { @@ -795,7 +809,7 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata head_seq_num = tid_agg_rx->head_seq_num; /* frame with out of date sequence number */ - if (ieee80211_sn_less(mpdu_seq_num, head_seq_num)) { + if (seq_less(mpdu_seq_num, head_seq_num)) { dev_kfree_skb(skb); goto out; } @@ -804,9 +818,8 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata * If frame the sequence number exceeds our buffering window * size release some previous frames to make room for this one. */ - if (!ieee80211_sn_less(mpdu_seq_num, head_seq_num + buf_size)) { - head_seq_num = ieee80211_sn_inc( - ieee80211_sn_sub(mpdu_seq_num, buf_size)); + if (!seq_less(mpdu_seq_num, head_seq_num + buf_size)) { + head_seq_num = seq_inc(seq_sub(mpdu_seq_num, buf_size)); /* release stored frames up to new head to stack */ ieee80211_release_reorder_frames(sdata, tid_agg_rx, head_seq_num, frames); @@ -814,8 +827,7 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata /* Now the new frame is always in the range of the reordering buffer */ - index = ieee80211_sn_sub(mpdu_seq_num, - tid_agg_rx->ssn) % tid_agg_rx->buf_size; + index = seq_sub(mpdu_seq_num, tid_agg_rx->ssn) % tid_agg_rx->buf_size; /* check if we already stored this frame */ if (tid_agg_rx->reorder_buf[index]) { @@ -831,8 +843,7 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata */ if (mpdu_seq_num == tid_agg_rx->head_seq_num && tid_agg_rx->stored_mpdu_num == 0) { - tid_agg_rx->head_seq_num = - ieee80211_sn_inc(tid_agg_rx->head_seq_num); + tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); ret = false; goto out; } @@ -1883,10 +1894,8 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) * 'align' will only take the values 0 or 2 here * since all frames are required to be aligned * to 2-byte boundaries when being passed to - * mac80211; the code here works just as well if - * that isn't true, but mac80211 assumes it can - * access fields as 2-byte aligned (e.g. for - * compare_ether_addr) + * mac80211. That also explains the __skb_push() + * below. */ align = ((unsigned long)(skb->data + sizeof(struct ethhdr))) & 3; if (align) { @@ -2543,7 +2552,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) case WLAN_SP_MESH_PEERING_CONFIRM: if (!ieee80211_vif_is_mesh(&sdata->vif)) goto invalid; - if (sdata->u.mesh.user_mpm) + if (sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE) /* userspace handles this frame */ break; goto queue; diff --git a/trunk/net/mac80211/sta_info.c b/trunk/net/mac80211/sta_info.c index 3644ad79688a..a79ce820cb50 100644 --- a/trunk/net/mac80211/sta_info.c +++ b/trunk/net/mac80211/sta_info.c @@ -342,11 +342,6 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, INIT_WORK(&sta->drv_unblock_wk, sta_unblock); INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work); mutex_init(&sta->ampdu_mlme.mtx); -#ifdef CONFIG_MAC80211_MESH - if (ieee80211_vif_is_mesh(&sdata->vif) && - !sdata->u.mesh.user_mpm) - init_timer(&sta->plink_timer); -#endif memcpy(sta->sta.addr, addr, ETH_ALEN); sta->local = local; @@ -799,11 +794,9 @@ int __must_check __sta_info_destroy(struct sta_info *sta) mutex_lock(&local->key_mtx); for (i = 0; i < NUM_DEFAULT_KEYS; i++) - __ieee80211_key_free(key_mtx_dereference(local, sta->gtk[i]), - true); + __ieee80211_key_free(key_mtx_dereference(local, sta->gtk[i])); if (sta->ptk) - __ieee80211_key_free(key_mtx_dereference(local, sta->ptk), - true); + __ieee80211_key_free(key_mtx_dereference(local, sta->ptk)); mutex_unlock(&local->key_mtx); sta->dead = true; diff --git a/trunk/net/mac80211/sta_info.h b/trunk/net/mac80211/sta_info.h index e5868c32d1a3..4947341a2a82 100644 --- a/trunk/net/mac80211/sta_info.h +++ b/trunk/net/mac80211/sta_info.h @@ -281,6 +281,7 @@ struct sta_ampdu_mlme { * @plink_state: peer link state * @plink_timeout: timeout of peer link * @plink_timer: peer link watch timer + * @plink_timer_was_running: used by suspend/resume to restore timers * @t_offset: timing offset relative to this host * @t_offset_setpoint: reference timing offset of this sta to be used when * calculating clockdrift @@ -378,6 +379,7 @@ struct sta_info { __le16 reason; u8 plink_retries; bool ignore_plink_timer; + bool plink_timer_was_running; enum nl80211_plink_state plink_state; u32 plink_timeout; struct timer_list plink_timer; diff --git a/trunk/net/mac80211/trace.h b/trunk/net/mac80211/trace.h index e7db2b804e0c..3d7cd2a0582f 100644 --- a/trunk/net/mac80211/trace.h +++ b/trunk/net/mac80211/trace.h @@ -1042,17 +1042,15 @@ 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, - enum ieee80211_roc_type type), + unsigned int duration), - TP_ARGS(local, sdata, chan, duration, type), + TP_ARGS(local, sdata, chan, duration), TP_STRUCT__entry( LOCAL_ENTRY VIF_ENTRY __field(int, center_freq) __field(unsigned int, duration) - __field(u32, type) ), TP_fast_assign( @@ -1060,13 +1058,12 @@ TRACE_EVENT(drv_remain_on_channel, VIF_ASSIGN; __entry->center_freq = chan->center_freq; __entry->duration = duration; - __entry->type = type; ), TP_printk( - LOCAL_PR_FMT VIF_PR_FMT " freq:%dMHz duration:%dms type=%d", + LOCAL_PR_FMT VIF_PR_FMT " freq:%dMHz duration:%dms", LOCAL_PR_ARG, VIF_PR_ARG, - __entry->center_freq, __entry->duration, __entry->type + __entry->center_freq, __entry->duration ) ); diff --git a/trunk/net/mac80211/tx.c b/trunk/net/mac80211/tx.c index 8914d2d2881a..de8548bf0a7f 100644 --- a/trunk/net/mac80211/tx.c +++ b/trunk/net/mac80211/tx.c @@ -1231,40 +1231,34 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local, if (local->queue_stop_reasons[q] || (!txpending && !skb_queue_empty(&local->pending[q]))) { if (unlikely(info->flags & - IEEE80211_TX_INTFL_OFFCHAN_TX_OK)) { - if (local->queue_stop_reasons[q] & - ~BIT(IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL)) { - /* - * Drop off-channel frames if queues - * are stopped for any reason other - * than off-channel operation. Never - * queue them. - */ - spin_unlock_irqrestore( - &local->queue_stop_reason_lock, - flags); - ieee80211_purge_tx_queue(&local->hw, - skbs); - return true; - } - } else { - + IEEE80211_TX_INTFL_OFFCHAN_TX_OK && + local->queue_stop_reasons[q] & + ~BIT(IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL))) { /* - * Since queue is stopped, queue up frames for - * later transmission from the tx-pending - * tasklet when the queue is woken again. + * Drop off-channel frames if queues are stopped + * for any reason other than off-channel + * operation. Never queue them. */ - if (txpending) - skb_queue_splice_init(skbs, - &local->pending[q]); - else - skb_queue_splice_tail_init(skbs, - &local->pending[q]); - - spin_unlock_irqrestore(&local->queue_stop_reason_lock, - flags); - return false; + spin_unlock_irqrestore( + &local->queue_stop_reason_lock, flags); + ieee80211_purge_tx_queue(&local->hw, skbs); + return true; } + + /* + * Since queue is stopped, queue up frames for later + * transmission from the tx-pending tasklet when the + * queue is woken again. + */ + if (txpending) + skb_queue_splice_init(skbs, &local->pending[q]); + else + skb_queue_splice_tail_init(skbs, + &local->pending[q]); + + spin_unlock_irqrestore(&local->queue_stop_reason_lock, + flags); + return false; } spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); @@ -1850,24 +1844,9 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, } if (!is_multicast_ether_addr(skb->data)) { - struct sta_info *next_hop; - bool mpp_lookup = true; - mpath = mesh_path_lookup(sdata, skb->data); - if (mpath) { - mpp_lookup = false; - next_hop = rcu_dereference(mpath->next_hop); - if (!next_hop || - !(mpath->flags & (MESH_PATH_ACTIVE | - MESH_PATH_RESOLVING))) - mpp_lookup = true; - } - - if (mpp_lookup) + if (!mpath) mppath = mpp_path_lookup(sdata, skb->data); - - if (mppath && mpath) - mesh_path_del(mpath->sdata, mpath->dst); } /* @@ -2371,9 +2350,9 @@ static int ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata, if (local->tim_in_locked_section) { __ieee80211_beacon_add_tim(sdata, ps, skb); } else { - spin_lock_bh(&local->tim_lock); + spin_lock(&local->tim_lock); __ieee80211_beacon_add_tim(sdata, ps, skb); - spin_unlock_bh(&local->tim_lock); + spin_unlock(&local->tim_lock); } return 0; @@ -2745,8 +2724,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, cpu_to_le16(IEEE80211_FCTL_MOREDATA); } - if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) - sdata = IEEE80211_DEV_TO_SUB_IF(skb->dev); + sdata = IEEE80211_DEV_TO_SUB_IF(skb->dev); if (!ieee80211_tx_prepare(sdata, &tx, skb)) break; dev_kfree_skb_any(skb); diff --git a/trunk/net/mac80211/util.c b/trunk/net/mac80211/util.c index b7a856e3281b..0f38f43ac62e 100644 --- a/trunk/net/mac80211/util.c +++ b/trunk/net/mac80211/util.c @@ -1357,25 +1357,6 @@ void ieee80211_stop_device(struct ieee80211_local *local) drv_stop(local); } -static void ieee80211_assign_chanctx(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata) -{ - struct ieee80211_chanctx_conf *conf; - struct ieee80211_chanctx *ctx; - - if (!local->use_chanctx) - return; - - 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_assign_vif_chanctx(local, sdata, ctx); - } - mutex_unlock(&local->chanctx_mtx); -} - int ieee80211_reconfig(struct ieee80211_local *local) { struct ieee80211_hw *hw = &local->hw; @@ -1464,14 +1445,36 @@ int ieee80211_reconfig(struct ieee80211_local *local) } list_for_each_entry(sdata, &local->interfaces, list) { + struct ieee80211_chanctx_conf *ctx_conf; + if (!ieee80211_sdata_running(sdata)) continue; - ieee80211_assign_chanctx(local, sdata); + + 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); } sdata = rtnl_dereference(local->monitor_sdata); - if (sdata && ieee80211_sdata_running(sdata)) - ieee80211_assign_chanctx(local, 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); @@ -1531,6 +1534,11 @@ int ieee80211_reconfig(struct ieee80211_local *local) BSS_CHANGED_IDLE | BSS_CHANGED_TXPOWER; +#ifdef CONFIG_PM + if (local->resuming && !reconfig_due_to_wowlan) + sdata->vif.bss_conf = sdata->suspend_bss_conf; +#endif + switch (sdata->vif.type) { case NL80211_IFTYPE_STATION: changed |= BSS_CHANGED_ASSOC | @@ -1670,7 +1678,28 @@ int ieee80211_reconfig(struct ieee80211_local *local) mb(); local->resuming = false; + list_for_each_entry(sdata, &local->interfaces, list) { + switch(sdata->vif.type) { + case NL80211_IFTYPE_STATION: + ieee80211_sta_restart(sdata); + break; + case NL80211_IFTYPE_ADHOC: + ieee80211_ibss_restart(sdata); + break; + case NL80211_IFTYPE_MESH_POINT: + ieee80211_mesh_restart(sdata); + break; + default: + break; + } + } + mod_timer(&local->sta_cleanup, jiffies + 1); + + mutex_lock(&local->sta_mtx); + list_for_each_entry(sta, &local->sta_list, list) + mesh_plink_restart(sta); + mutex_unlock(&local->sta_mtx); #else WARN_ON(1); #endif diff --git a/trunk/net/mac80211/vht.c b/trunk/net/mac80211/vht.c index 171344d4eb7c..a2c2258bc84e 100644 --- a/trunk/net/mac80211/vht.c +++ b/trunk/net/mac80211/vht.c @@ -13,104 +13,6 @@ #include "rate.h" -static void __check_vhtcap_disable(struct ieee80211_sub_if_data *sdata, - struct ieee80211_sta_vht_cap *vht_cap, - u32 flag) -{ - __le32 le_flag = cpu_to_le32(flag); - - if (sdata->u.mgd.vht_capa_mask.vht_cap_info & le_flag && - !(sdata->u.mgd.vht_capa.vht_cap_info & le_flag)) - vht_cap->cap &= ~flag; -} - -void ieee80211_apply_vhtcap_overrides(struct ieee80211_sub_if_data *sdata, - struct ieee80211_sta_vht_cap *vht_cap) -{ - int i; - u16 rxmcs_mask, rxmcs_cap, rxmcs_n, txmcs_mask, txmcs_cap, txmcs_n; - - if (!vht_cap->vht_supported) - return; - - if (sdata->vif.type != NL80211_IFTYPE_STATION) - return; - - __check_vhtcap_disable(sdata, vht_cap, - IEEE80211_VHT_CAP_RXLDPC); - __check_vhtcap_disable(sdata, vht_cap, - IEEE80211_VHT_CAP_SHORT_GI_80); - __check_vhtcap_disable(sdata, vht_cap, - IEEE80211_VHT_CAP_SHORT_GI_160); - __check_vhtcap_disable(sdata, vht_cap, - IEEE80211_VHT_CAP_TXSTBC); - __check_vhtcap_disable(sdata, vht_cap, - IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE); - __check_vhtcap_disable(sdata, vht_cap, - IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE); - __check_vhtcap_disable(sdata, vht_cap, - IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN); - __check_vhtcap_disable(sdata, vht_cap, - IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN); - - /* Allow user to decrease AMPDU length exponent */ - if (sdata->u.mgd.vht_capa_mask.vht_cap_info & - cpu_to_le32(IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK)) { - u32 cap, n; - - n = le32_to_cpu(sdata->u.mgd.vht_capa.vht_cap_info) & - IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; - n >>= IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT; - cap = vht_cap->cap & IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; - cap >>= IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT; - - if (n < cap) { - vht_cap->cap &= - ~IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; - vht_cap->cap |= - n << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT; - } - } - - /* Allow the user to decrease MCSes */ - rxmcs_mask = - le16_to_cpu(sdata->u.mgd.vht_capa_mask.supp_mcs.rx_mcs_map); - rxmcs_n = le16_to_cpu(sdata->u.mgd.vht_capa.supp_mcs.rx_mcs_map); - rxmcs_n &= rxmcs_mask; - rxmcs_cap = le16_to_cpu(vht_cap->vht_mcs.rx_mcs_map); - - txmcs_mask = - le16_to_cpu(sdata->u.mgd.vht_capa_mask.supp_mcs.tx_mcs_map); - txmcs_n = le16_to_cpu(sdata->u.mgd.vht_capa.supp_mcs.tx_mcs_map); - txmcs_n &= txmcs_mask; - txmcs_cap = le16_to_cpu(vht_cap->vht_mcs.tx_mcs_map); - for (i = 0; i < 8; i++) { - u8 m, n, c; - - m = (rxmcs_mask >> 2*i) & IEEE80211_VHT_MCS_NOT_SUPPORTED; - n = (rxmcs_n >> 2*i) & IEEE80211_VHT_MCS_NOT_SUPPORTED; - c = (rxmcs_cap >> 2*i) & IEEE80211_VHT_MCS_NOT_SUPPORTED; - - if (m && ((c != IEEE80211_VHT_MCS_NOT_SUPPORTED && n < c) || - n == IEEE80211_VHT_MCS_NOT_SUPPORTED)) { - rxmcs_cap &= ~(3 << 2*i); - rxmcs_cap |= (rxmcs_n & (3 << 2*i)); - } - - m = (txmcs_mask >> 2*i) & IEEE80211_VHT_MCS_NOT_SUPPORTED; - n = (txmcs_n >> 2*i) & IEEE80211_VHT_MCS_NOT_SUPPORTED; - c = (txmcs_cap >> 2*i) & IEEE80211_VHT_MCS_NOT_SUPPORTED; - - if (m && ((c != IEEE80211_VHT_MCS_NOT_SUPPORTED && n < c) || - n == IEEE80211_VHT_MCS_NOT_SUPPORTED)) { - txmcs_cap &= ~(3 << 2*i); - txmcs_cap |= (txmcs_n & (3 << 2*i)); - } - } - vht_cap->vht_mcs.rx_mcs_map = cpu_to_le16(rxmcs_cap); - vht_cap->vht_mcs.tx_mcs_map = cpu_to_le16(txmcs_cap); -} - void ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, struct ieee80211_supported_band *sband, @@ -118,8 +20,6 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, struct sta_info *sta) { struct ieee80211_sta_vht_cap *vht_cap = &sta->sta.vht_cap; - struct ieee80211_sta_vht_cap own_cap; - u32 cap_info, i; memset(vht_cap, 0, sizeof(*vht_cap)); @@ -135,122 +35,12 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, vht_cap->vht_supported = true; - own_cap = sband->vht_cap; - /* - * If user has specified capability overrides, take care - * of that if the station we're setting up is the AP that - * we advertised a restricted capability set to. Override - * our own capabilities and then use those below. - */ - if (sdata->vif.type == NL80211_IFTYPE_STATION && - !test_sta_flag(sta, WLAN_STA_TDLS_PEER)) - ieee80211_apply_vhtcap_overrides(sdata, &own_cap); - - /* take some capabilities as-is */ - cap_info = le32_to_cpu(vht_cap_ie->vht_cap_info); - vht_cap->cap = cap_info; - vht_cap->cap &= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 | - IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 | - IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | - IEEE80211_VHT_CAP_RXLDPC | - IEEE80211_VHT_CAP_VHT_TXOP_PS | - IEEE80211_VHT_CAP_HTC_VHT | - IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK | - IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB | - IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB | - IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN | - IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN; - - /* and some based on our own capabilities */ - switch (own_cap.cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) { - case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ: - vht_cap->cap |= cap_info & - IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ; - break; - case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ: - vht_cap->cap |= cap_info & - IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK; - break; - default: - /* nothing */ - break; - } - - /* symmetric capabilities */ - vht_cap->cap |= cap_info & own_cap.cap & - (IEEE80211_VHT_CAP_SHORT_GI_80 | - IEEE80211_VHT_CAP_SHORT_GI_160); - - /* remaining ones */ - if (own_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE) { - vht_cap->cap |= cap_info & - (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE | - IEEE80211_VHT_CAP_BEAMFORMER_ANTENNAS_MAX | - IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MAX); - } - - if (own_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE) - vht_cap->cap |= cap_info & - IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE; - - if (own_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) - vht_cap->cap |= cap_info & - IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE; - - if (own_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE) - vht_cap->cap |= cap_info & - IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE; - - if (own_cap.cap & IEEE80211_VHT_CAP_TXSTBC) - vht_cap->cap |= cap_info & IEEE80211_VHT_CAP_RXSTBC_MASK; - - if (own_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK) - vht_cap->cap |= cap_info & IEEE80211_VHT_CAP_TXSTBC; + vht_cap->cap = le32_to_cpu(vht_cap_ie->vht_cap_info); /* Copy peer MCS info, the driver might need them. */ memcpy(&vht_cap->vht_mcs, &vht_cap_ie->supp_mcs, sizeof(struct ieee80211_vht_mcs_info)); - /* but also restrict MCSes */ - for (i = 0; i < 8; i++) { - u16 own_rx, own_tx, peer_rx, peer_tx; - - own_rx = le16_to_cpu(own_cap.vht_mcs.rx_mcs_map); - own_rx = (own_rx >> i * 2) & IEEE80211_VHT_MCS_NOT_SUPPORTED; - - own_tx = le16_to_cpu(own_cap.vht_mcs.tx_mcs_map); - own_tx = (own_tx >> i * 2) & IEEE80211_VHT_MCS_NOT_SUPPORTED; - - peer_rx = le16_to_cpu(vht_cap->vht_mcs.rx_mcs_map); - peer_rx = (peer_rx >> i * 2) & IEEE80211_VHT_MCS_NOT_SUPPORTED; - - peer_tx = le16_to_cpu(vht_cap->vht_mcs.tx_mcs_map); - peer_tx = (peer_tx >> i * 2) & IEEE80211_VHT_MCS_NOT_SUPPORTED; - - if (peer_tx != IEEE80211_VHT_MCS_NOT_SUPPORTED) { - if (own_rx == IEEE80211_VHT_MCS_NOT_SUPPORTED) - peer_tx = IEEE80211_VHT_MCS_NOT_SUPPORTED; - else if (own_rx < peer_tx) - peer_tx = own_rx; - } - - if (peer_rx != IEEE80211_VHT_MCS_NOT_SUPPORTED) { - if (own_tx == IEEE80211_VHT_MCS_NOT_SUPPORTED) - peer_rx = IEEE80211_VHT_MCS_NOT_SUPPORTED; - else if (own_tx < peer_rx) - peer_rx = own_tx; - } - - vht_cap->vht_mcs.rx_mcs_map &= - ~cpu_to_le16(IEEE80211_VHT_MCS_NOT_SUPPORTED << i * 2); - vht_cap->vht_mcs.rx_mcs_map |= cpu_to_le16(peer_rx << i * 2); - - vht_cap->vht_mcs.tx_mcs_map &= - ~cpu_to_le16(IEEE80211_VHT_MCS_NOT_SUPPORTED << i * 2); - vht_cap->vht_mcs.tx_mcs_map |= cpu_to_le16(peer_tx << i * 2); - } - - /* finally set up the bandwidth */ switch (vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) { case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ: case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ: diff --git a/trunk/net/rfkill/rfkill-regulator.c b/trunk/net/rfkill/rfkill-regulator.c index d11ac79246e4..4b5ab21ecb24 100644 --- a/trunk/net/rfkill/rfkill-regulator.c +++ b/trunk/net/rfkill/rfkill-regulator.c @@ -51,7 +51,7 @@ static int rfkill_regulator_set_block(void *data, bool blocked) return 0; } -static struct rfkill_ops rfkill_regulator_ops = { +struct rfkill_ops rfkill_regulator_ops = { .set_block = rfkill_regulator_set_block, }; diff --git a/trunk/net/wireless/ap.c b/trunk/net/wireless/ap.c index 324e8d851dc4..a4a14e8f55cc 100644 --- a/trunk/net/wireless/ap.c +++ b/trunk/net/wireless/ap.c @@ -46,3 +46,65 @@ int cfg80211_stop_ap(struct cfg80211_registered_device *rdev, return err; } + +void cfg80211_ch_switch_notify(struct net_device *dev, + struct cfg80211_chan_def *chandef) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct wiphy *wiphy = wdev->wiphy; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); + + trace_cfg80211_ch_switch_notify(dev, chandef); + + wdev_lock(wdev); + + if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && + wdev->iftype != NL80211_IFTYPE_P2P_GO)) + goto out; + + wdev->channel = chandef->chan; + nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL); +out: + wdev_unlock(wdev); + return; +} +EXPORT_SYMBOL(cfg80211_ch_switch_notify); + +bool cfg80211_rx_spurious_frame(struct net_device *dev, + const u8 *addr, gfp_t gfp) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + bool ret; + + trace_cfg80211_rx_spurious_frame(dev, addr); + + if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && + wdev->iftype != NL80211_IFTYPE_P2P_GO)) { + trace_cfg80211_return_bool(false); + return false; + } + ret = nl80211_unexpected_frame(dev, addr, gfp); + trace_cfg80211_return_bool(ret); + return ret; +} +EXPORT_SYMBOL(cfg80211_rx_spurious_frame); + +bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev, + const u8 *addr, gfp_t gfp) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + bool ret; + + trace_cfg80211_rx_unexpected_4addr_frame(dev, addr); + + if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && + wdev->iftype != NL80211_IFTYPE_P2P_GO && + wdev->iftype != NL80211_IFTYPE_AP_VLAN)) { + trace_cfg80211_return_bool(false); + return false; + } + ret = nl80211_unexpected_4addr_frame(dev, addr, gfp); + trace_cfg80211_return_bool(ret); + return ret; +} +EXPORT_SYMBOL(cfg80211_rx_unexpected_4addr_frame); diff --git a/trunk/net/wireless/core.c b/trunk/net/wireless/core.c index f382cae983ba..5ffff039b017 100644 --- a/trunk/net/wireless/core.c +++ b/trunk/net/wireless/core.c @@ -367,7 +367,8 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) rdev->wiphy.rts_threshold = (u32) -1; rdev->wiphy.coverage_class = 0; - rdev->wiphy.features = NL80211_FEATURE_SCAN_FLUSH; + rdev->wiphy.features = NL80211_FEATURE_SCAN_FLUSH | + NL80211_FEATURE_ADVERTISE_CHAN_LIMITS; return &rdev->wiphy; } @@ -814,46 +815,6 @@ void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, rdev->num_running_monitor_ifaces += num; } -void cfg80211_leave(struct cfg80211_registered_device *rdev, - struct wireless_dev *wdev) -{ - struct net_device *dev = wdev->netdev; - - switch (wdev->iftype) { - case NL80211_IFTYPE_ADHOC: - cfg80211_leave_ibss(rdev, dev, true); - break; - case NL80211_IFTYPE_P2P_CLIENT: - case NL80211_IFTYPE_STATION: - mutex_lock(&rdev->sched_scan_mtx); - __cfg80211_stop_sched_scan(rdev, false); - mutex_unlock(&rdev->sched_scan_mtx); - - wdev_lock(wdev); -#ifdef CONFIG_CFG80211_WEXT - kfree(wdev->wext.ie); - wdev->wext.ie = NULL; - wdev->wext.ie_len = 0; - wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; -#endif - __cfg80211_disconnect(rdev, dev, - WLAN_REASON_DEAUTH_LEAVING, true); - cfg80211_mlme_down(rdev, dev); - wdev_unlock(wdev); - break; - case NL80211_IFTYPE_MESH_POINT: - cfg80211_leave_mesh(rdev, dev); - break; - case NL80211_IFTYPE_AP: - cfg80211_stop_ap(rdev, dev); - break; - default: - break; - } - - wdev->beacon_interval = 0; -} - static int cfg80211_netdev_notifier_call(struct notifier_block *nb, unsigned long state, void *ndev) @@ -922,7 +883,38 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, dev->priv_flags |= IFF_DONT_BRIDGE; break; case NETDEV_GOING_DOWN: - cfg80211_leave(rdev, wdev); + switch (wdev->iftype) { + case NL80211_IFTYPE_ADHOC: + cfg80211_leave_ibss(rdev, dev, true); + break; + case NL80211_IFTYPE_P2P_CLIENT: + case NL80211_IFTYPE_STATION: + mutex_lock(&rdev->sched_scan_mtx); + __cfg80211_stop_sched_scan(rdev, false); + mutex_unlock(&rdev->sched_scan_mtx); + + wdev_lock(wdev); +#ifdef CONFIG_CFG80211_WEXT + kfree(wdev->wext.ie); + wdev->wext.ie = NULL; + wdev->wext.ie_len = 0; + wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; +#endif + __cfg80211_disconnect(rdev, dev, + WLAN_REASON_DEAUTH_LEAVING, true); + cfg80211_mlme_down(rdev, dev); + wdev_unlock(wdev); + break; + case NL80211_IFTYPE_MESH_POINT: + cfg80211_leave_mesh(rdev, dev); + break; + case NL80211_IFTYPE_AP: + cfg80211_stop_ap(rdev, dev); + break; + default: + break; + } + wdev->beacon_interval = 0; break; case NETDEV_DOWN: cfg80211_update_iface_num(rdev, wdev->iftype, -1); diff --git a/trunk/net/wireless/core.h b/trunk/net/wireless/core.h index d5d06fdea961..3aec0e429d8a 100644 --- a/trunk/net/wireless/core.h +++ b/trunk/net/wireless/core.h @@ -330,15 +330,20 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, struct net_device *dev, struct ieee80211_channel *chan, - const u8 *bssid, + const u8 *bssid, const u8 *prev_bssid, const u8 *ssid, int ssid_len, - struct cfg80211_assoc_request *req); + const u8 *ie, int ie_len, bool use_mfp, + struct cfg80211_crypto_settings *crypt, + u32 assoc_flags, struct ieee80211_ht_cap *ht_capa, + struct ieee80211_ht_cap *ht_capa_mask); int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, - struct net_device *dev, - struct ieee80211_channel *chan, - const u8 *bssid, + struct net_device *dev, struct ieee80211_channel *chan, + const u8 *bssid, const u8 *prev_bssid, const u8 *ssid, int ssid_len, - struct cfg80211_assoc_request *req); + const u8 *ie, int ie_len, bool use_mfp, + struct cfg80211_crypto_settings *crypt, + u32 assoc_flags, struct ieee80211_ht_cap *ht_capa, + struct ieee80211_ht_cap *ht_capa_mask); int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, struct net_device *dev, const u8 *bssid, const u8 *ie, int ie_len, u16 reason, @@ -370,8 +375,6 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, 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); -void cfg80211_oper_and_vht_capa(struct ieee80211_vht_cap *vht_capa, - const struct ieee80211_vht_cap *vht_capa_mask); /* SME */ int __cfg80211_connect(struct cfg80211_registered_device *rdev, @@ -500,9 +503,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); -void cfg80211_leave(struct cfg80211_registered_device *rdev, - struct wireless_dev *wdev); - #define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10 #ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS diff --git a/trunk/net/wireless/mesh.c b/trunk/net/wireless/mesh.c index 0bb93f3061a4..55957a284f6c 100644 --- a/trunk/net/wireless/mesh.c +++ b/trunk/net/wireless/mesh.c @@ -85,7 +85,6 @@ const struct mesh_setup default_mesh_setup = { .ie = NULL, .ie_len = 0, .is_secure = false, - .user_mpm = false, .beacon_interval = MESH_DEFAULT_BEACON_INTERVAL, .dtim_period = MESH_DEFAULT_DTIM_PERIOD, }; @@ -234,6 +233,20 @@ int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev, return 0; } +void cfg80211_notify_new_peer_candidate(struct net_device *dev, + const u8 *macaddr, const u8* ie, u8 ie_len, gfp_t gfp) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + + trace_cfg80211_notify_new_peer_candidate(dev, macaddr); + if (WARN_ON(wdev->iftype != NL80211_IFTYPE_MESH_POINT)) + return; + + nl80211_send_new_peer_candidate(wiphy_to_dev(wdev->wiphy), dev, + macaddr, ie, ie_len, gfp); +} +EXPORT_SYMBOL(cfg80211_notify_new_peer_candidate); + static int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, struct net_device *dev) { diff --git a/trunk/net/wireless/mlme.c b/trunk/net/wireless/mlme.c index 390198bf4b36..caddca35d686 100644 --- a/trunk/net/wireless/mlme.c +++ b/trunk/net/wireless/mlme.c @@ -187,6 +187,30 @@ void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len) } EXPORT_SYMBOL(cfg80211_send_disassoc); +void cfg80211_send_unprot_deauth(struct net_device *dev, const u8 *buf, + size_t len) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct wiphy *wiphy = wdev->wiphy; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); + + trace_cfg80211_send_unprot_deauth(dev); + nl80211_send_unprot_deauth(rdev, dev, buf, len, GFP_ATOMIC); +} +EXPORT_SYMBOL(cfg80211_send_unprot_deauth); + +void cfg80211_send_unprot_disassoc(struct net_device *dev, const u8 *buf, + size_t len) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct wiphy *wiphy = wdev->wiphy; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); + + trace_cfg80211_send_unprot_disassoc(dev); + nl80211_send_unprot_disassoc(rdev, dev, buf, len, GFP_ATOMIC); +} +EXPORT_SYMBOL(cfg80211_send_unprot_disassoc); + void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr) { struct wireless_dev *wdev = dev->ieee80211_ptr; @@ -343,38 +367,27 @@ void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa, p1[i] &= p2[i]; } -/* Do a logical ht_capa &= ht_capa_mask. */ -void cfg80211_oper_and_vht_capa(struct ieee80211_vht_cap *vht_capa, - const struct ieee80211_vht_cap *vht_capa_mask) -{ - int i; - u8 *p1, *p2; - if (!vht_capa_mask) { - memset(vht_capa, 0, sizeof(*vht_capa)); - return; - } - - p1 = (u8*)(vht_capa); - p2 = (u8*)(vht_capa_mask); - for (i = 0; i < sizeof(*vht_capa); i++) - p1[i] &= p2[i]; -} - int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, struct net_device *dev, struct ieee80211_channel *chan, - const u8 *bssid, + const u8 *bssid, const u8 *prev_bssid, const u8 *ssid, int ssid_len, - struct cfg80211_assoc_request *req) + const u8 *ie, int ie_len, bool use_mfp, + struct cfg80211_crypto_settings *crypt, + u32 assoc_flags, struct ieee80211_ht_cap *ht_capa, + struct ieee80211_ht_cap *ht_capa_mask) { struct wireless_dev *wdev = dev->ieee80211_ptr; + struct cfg80211_assoc_request req; int err; bool was_connected = false; ASSERT_WDEV_LOCK(wdev); - if (wdev->current_bss && req->prev_bssid && - ether_addr_equal(wdev->current_bss->pub.bssid, req->prev_bssid)) { + memset(&req, 0, sizeof(req)); + + if (wdev->current_bss && prev_bssid && + ether_addr_equal(wdev->current_bss->pub.bssid, prev_bssid)) { /* * Trying to reassociate: Allow this to proceed and let the old * association to be dropped when the new one is completed. @@ -386,30 +399,40 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, } else if (wdev->current_bss) return -EALREADY; - cfg80211_oper_and_ht_capa(&req->ht_capa_mask, + req.ie = ie; + req.ie_len = ie_len; + memcpy(&req.crypto, crypt, sizeof(req.crypto)); + req.use_mfp = use_mfp; + req.prev_bssid = prev_bssid; + req.flags = assoc_flags; + if (ht_capa) + memcpy(&req.ht_capa, ht_capa, sizeof(req.ht_capa)); + if (ht_capa_mask) + memcpy(&req.ht_capa_mask, ht_capa_mask, + sizeof(req.ht_capa_mask)); + cfg80211_oper_and_ht_capa(&req.ht_capa_mask, rdev->wiphy.ht_capa_mod_mask); - cfg80211_oper_and_vht_capa(&req->vht_capa_mask, - rdev->wiphy.vht_capa_mod_mask); - req->bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len, - WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); - if (!req->bss) { + req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len, + WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); + if (!req.bss) { if (was_connected) wdev->sme_state = CFG80211_SME_CONNECTED; return -ENOENT; } - err = cfg80211_can_use_chan(rdev, wdev, chan, CHAN_MODE_SHARED); + err = cfg80211_can_use_chan(rdev, wdev, req.bss->channel, + CHAN_MODE_SHARED); if (err) goto out; - err = rdev_assoc(rdev, dev, req); + err = rdev_assoc(rdev, dev, &req); out: if (err) { if (was_connected) wdev->sme_state = CFG80211_SME_CONNECTED; - cfg80211_put_bss(&rdev->wiphy, req->bss); + cfg80211_put_bss(&rdev->wiphy, req.bss); } return err; @@ -418,17 +441,21 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, struct net_device *dev, struct ieee80211_channel *chan, - const u8 *bssid, + const u8 *bssid, const u8 *prev_bssid, const u8 *ssid, int ssid_len, - struct cfg80211_assoc_request *req) + const u8 *ie, int ie_len, bool use_mfp, + struct cfg80211_crypto_settings *crypt, + u32 assoc_flags, struct ieee80211_ht_cap *ht_capa, + struct ieee80211_ht_cap *ht_capa_mask) { struct wireless_dev *wdev = dev->ieee80211_ptr; int err; mutex_lock(&rdev->devlist_mtx); wdev_lock(wdev); - err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid, - ssid, ssid_len, req); + err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid, + ssid, ssid_len, ie, ie_len, use_mfp, crypt, + assoc_flags, ht_capa, ht_capa_mask); wdev_unlock(wdev); mutex_unlock(&rdev->devlist_mtx); @@ -550,6 +577,62 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, } } +void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie, + struct ieee80211_channel *chan, + 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); +} +EXPORT_SYMBOL(cfg80211_ready_on_channel); + +void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie, + struct ieee80211_channel *chan, + 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); +} +EXPORT_SYMBOL(cfg80211_remain_on_channel_expired); + +void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr, + struct station_info *sinfo, gfp_t gfp) +{ + struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); + + trace_cfg80211_new_sta(dev, mac_addr, sinfo); + nl80211_send_sta_event(rdev, dev, mac_addr, sinfo, gfp); +} +EXPORT_SYMBOL(cfg80211_new_sta); + +void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp) +{ + struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); + + trace_cfg80211_del_sta(dev, mac_addr); + nl80211_send_sta_del_event(rdev, dev, mac_addr, gfp); +} +EXPORT_SYMBOL(cfg80211_del_sta); + +void cfg80211_conn_failed(struct net_device *dev, const u8 *mac_addr, + enum nl80211_connect_failed_reason reason, + gfp_t gfp) +{ + struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); + + nl80211_send_conn_failed_event(rdev, dev, mac_addr, reason, gfp); +} +EXPORT_SYMBOL(cfg80211_conn_failed); + struct cfg80211_mgmt_registration { struct list_head list; @@ -826,6 +909,85 @@ bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_mbm, } EXPORT_SYMBOL(cfg80211_rx_mgmt); +void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie, + const u8 *buf, size_t len, bool ack, gfp_t gfp) +{ + struct wiphy *wiphy = wdev->wiphy; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); + + trace_cfg80211_mgmt_tx_status(wdev, cookie, ack); + + /* Indicate TX status of the Action frame to user space */ + nl80211_send_mgmt_tx_status(rdev, wdev, cookie, buf, len, ack, gfp); +} +EXPORT_SYMBOL(cfg80211_mgmt_tx_status); + +void cfg80211_cqm_rssi_notify(struct net_device *dev, + enum nl80211_cqm_rssi_threshold_event rssi_event, + gfp_t gfp) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct wiphy *wiphy = wdev->wiphy; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); + + trace_cfg80211_cqm_rssi_notify(dev, rssi_event); + + /* Indicate roaming trigger event to user space */ + nl80211_send_cqm_rssi_notify(rdev, dev, rssi_event, gfp); +} +EXPORT_SYMBOL(cfg80211_cqm_rssi_notify); + +void cfg80211_cqm_pktloss_notify(struct net_device *dev, + const u8 *peer, u32 num_packets, gfp_t gfp) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct wiphy *wiphy = wdev->wiphy; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); + + trace_cfg80211_cqm_pktloss_notify(dev, peer, num_packets); + + /* Indicate roaming trigger event to user space */ + nl80211_send_cqm_pktloss_notify(rdev, dev, peer, num_packets, gfp); +} +EXPORT_SYMBOL(cfg80211_cqm_pktloss_notify); + +void cfg80211_cqm_txe_notify(struct net_device *dev, + const u8 *peer, u32 num_packets, + u32 rate, u32 intvl, gfp_t gfp) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct wiphy *wiphy = wdev->wiphy; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); + + nl80211_send_cqm_txe_notify(rdev, dev, peer, num_packets, + rate, intvl, gfp); +} +EXPORT_SYMBOL(cfg80211_cqm_txe_notify); + +void cfg80211_gtk_rekey_notify(struct net_device *dev, const u8 *bssid, + const u8 *replay_ctr, gfp_t gfp) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct wiphy *wiphy = wdev->wiphy; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); + + trace_cfg80211_gtk_rekey_notify(dev, bssid); + nl80211_gtk_rekey_notify(rdev, dev, bssid, replay_ctr, gfp); +} +EXPORT_SYMBOL(cfg80211_gtk_rekey_notify); + +void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index, + const u8 *bssid, bool preauth, gfp_t gfp) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct wiphy *wiphy = wdev->wiphy; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); + + trace_cfg80211_pmksa_candidate_notify(dev, index, bssid, preauth); + nl80211_pmksa_candidate_notify(rdev, dev, index, bssid, preauth, gfp); +} +EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify); + void cfg80211_dfs_channels_update_work(struct work_struct *work) { struct delayed_work *delayed_work; diff --git a/trunk/net/wireless/nl80211.c b/trunk/net/wireless/nl80211.c index f924d45af1b8..35545ccc30fd 100644 --- a/trunk/net/wireless/nl80211.c +++ b/trunk/net/wireless/nl80211.c @@ -370,14 +370,6 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { [NL80211_ATTR_MAC_ADDRS] = { .type = NLA_NESTED }, [NL80211_ATTR_STA_CAPABILITY] = { .type = NLA_U16 }, [NL80211_ATTR_STA_EXT_CAPABILITY] = { .type = NLA_BINARY, }, - [NL80211_ATTR_SPLIT_WIPHY_DUMP] = { .type = NLA_FLAG, }, - [NL80211_ATTR_DISABLE_VHT] = { .type = NLA_FLAG }, - [NL80211_ATTR_VHT_CAPABILITY_MASK] = { - .len = NL80211_VHT_CAPABILITY_LEN, - }, - [NL80211_ATTR_MDID] = { .type = NLA_U16 }, - [NL80211_ATTR_IE_RIC] = { .type = NLA_BINARY, - .len = IEEE80211_MAX_DATA_LEN }, }; /* policy for the key attributes */ @@ -547,8 +539,7 @@ static inline void *nl80211hdr_put(struct sk_buff *skb, u32 portid, u32 seq, } static int nl80211_msg_put_channel(struct sk_buff *msg, - struct ieee80211_channel *chan, - bool large) + struct ieee80211_channel *chan) { if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_FREQ, chan->center_freq)) @@ -564,36 +555,27 @@ static int nl80211_msg_put_channel(struct sk_buff *msg, nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IBSS)) goto nla_put_failure; if (chan->flags & IEEE80211_CHAN_RADAR) { + u32 time = elapsed_jiffies_msecs(chan->dfs_state_entered); if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR)) goto nla_put_failure; - if (large) { - u32 time; - - time = elapsed_jiffies_msecs(chan->dfs_state_entered); - - if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_STATE, - chan->dfs_state)) - goto nla_put_failure; - if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_TIME, - time)) - goto nla_put_failure; - } - } - - if (large) { - if ((chan->flags & IEEE80211_CHAN_NO_HT40MINUS) && - nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_MINUS)) - goto nla_put_failure; - if ((chan->flags & IEEE80211_CHAN_NO_HT40PLUS) && - nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_PLUS)) - goto nla_put_failure; - if ((chan->flags & IEEE80211_CHAN_NO_80MHZ) && - nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_80MHZ)) + if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_STATE, + chan->dfs_state)) goto nla_put_failure; - if ((chan->flags & IEEE80211_CHAN_NO_160MHZ) && - nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_160MHZ)) + if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_TIME, time)) goto nla_put_failure; } + if ((chan->flags & IEEE80211_CHAN_NO_HT40MINUS) && + nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_MINUS)) + goto nla_put_failure; + if ((chan->flags & IEEE80211_CHAN_NO_HT40PLUS) && + nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_PLUS)) + goto nla_put_failure; + if ((chan->flags & IEEE80211_CHAN_NO_80MHZ) && + nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_80MHZ)) + goto nla_put_failure; + if ((chan->flags & IEEE80211_CHAN_NO_160MHZ) && + nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_160MHZ)) + goto nla_put_failure; if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER, DBM_TO_MBM(chan->max_power))) @@ -869,8 +851,7 @@ static int nl80211_put_iftypes(struct sk_buff *msg, u32 attr, u16 ifmodes) } static int nl80211_put_iface_combinations(struct wiphy *wiphy, - struct sk_buff *msg, - bool large) + struct sk_buff *msg) { struct nlattr *nl_combis; int i, j; @@ -919,8 +900,7 @@ static int nl80211_put_iface_combinations(struct wiphy *wiphy, nla_put_u32(msg, NL80211_IFACE_COMB_MAXNUM, c->max_interfaces)) goto nla_put_failure; - if (large && - nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS, + if (nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS, c->radar_detect_widths)) goto nla_put_failure; @@ -974,571 +954,426 @@ static int nl80211_send_wowlan_tcp_caps(struct cfg80211_registered_device *rdev, nla_nest_end(msg, nl_tcp); return 0; } +#endif -static int nl80211_send_wowlan(struct sk_buff *msg, - struct cfg80211_registered_device *dev, - bool large) +static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flags, + struct cfg80211_registered_device *dev) { - struct nlattr *nl_wowlan; - - if (!dev->wiphy.wowlan.flags && !dev->wiphy.wowlan.n_patterns) - return 0; + void *hdr; + struct nlattr *nl_bands, *nl_band; + struct nlattr *nl_freqs, *nl_freq; + struct nlattr *nl_rates, *nl_rate; + struct nlattr *nl_cmds; + enum ieee80211_band band; + struct ieee80211_channel *chan; + struct ieee80211_rate *rate; + int i; + const struct ieee80211_txrx_stypes *mgmt_stypes = + dev->wiphy.mgmt_stypes; - nl_wowlan = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED); - if (!nl_wowlan) - return -ENOBUFS; + hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_WIPHY); + if (!hdr) + return -1; - if (((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_ANY) && - nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) || - ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_DISCONNECT) && - nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) || - ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_MAGIC_PKT) && - nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) || - ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY) && - nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED)) || - ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) && - nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) || - ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ) && - nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) || - ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_4WAY_HANDSHAKE) && - nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) || - ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_RFKILL_RELEASE) && - nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE))) - return -ENOBUFS; + if (nla_put_u32(msg, NL80211_ATTR_WIPHY, dev->wiphy_idx) || + nla_put_string(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy)) || + nla_put_u32(msg, NL80211_ATTR_GENERATION, + cfg80211_rdev_list_generation) || + nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT, + dev->wiphy.retry_short) || + nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_LONG, + dev->wiphy.retry_long) || + nla_put_u32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD, + dev->wiphy.frag_threshold) || + nla_put_u32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD, + dev->wiphy.rts_threshold) || + nla_put_u8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS, + dev->wiphy.coverage_class) || + nla_put_u8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS, + dev->wiphy.max_scan_ssids) || + nla_put_u8(msg, NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS, + dev->wiphy.max_sched_scan_ssids) || + nla_put_u16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN, + dev->wiphy.max_scan_ie_len) || + nla_put_u16(msg, NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN, + dev->wiphy.max_sched_scan_ie_len) || + nla_put_u8(msg, NL80211_ATTR_MAX_MATCH_SETS, + dev->wiphy.max_match_sets)) + goto nla_put_failure; - if (dev->wiphy.wowlan.n_patterns) { - struct nl80211_wowlan_pattern_support pat = { - .max_patterns = dev->wiphy.wowlan.n_patterns, - .min_pattern_len = dev->wiphy.wowlan.pattern_min_len, - .max_pattern_len = dev->wiphy.wowlan.pattern_max_len, - .max_pkt_offset = dev->wiphy.wowlan.max_pkt_offset, - }; + if ((dev->wiphy.flags & WIPHY_FLAG_IBSS_RSN) && + nla_put_flag(msg, NL80211_ATTR_SUPPORT_IBSS_RSN)) + goto nla_put_failure; + if ((dev->wiphy.flags & WIPHY_FLAG_MESH_AUTH) && + nla_put_flag(msg, NL80211_ATTR_SUPPORT_MESH_AUTH)) + goto nla_put_failure; + if ((dev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) && + nla_put_flag(msg, NL80211_ATTR_SUPPORT_AP_UAPSD)) + goto nla_put_failure; + if ((dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_FW_ROAM) && + nla_put_flag(msg, NL80211_ATTR_ROAM_SUPPORT)) + goto nla_put_failure; + if ((dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) && + nla_put_flag(msg, NL80211_ATTR_TDLS_SUPPORT)) + goto nla_put_failure; + if ((dev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) && + nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP)) + goto nla_put_failure; - if (nla_put(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN, - sizeof(pat), &pat)) - return -ENOBUFS; - } + if (nla_put(msg, NL80211_ATTR_CIPHER_SUITES, + sizeof(u32) * dev->wiphy.n_cipher_suites, + dev->wiphy.cipher_suites)) + goto nla_put_failure; - if (large && nl80211_send_wowlan_tcp_caps(dev, msg)) - return -ENOBUFS; + if (nla_put_u8(msg, NL80211_ATTR_MAX_NUM_PMKIDS, + dev->wiphy.max_num_pmkids)) + goto nla_put_failure; - nla_nest_end(msg, nl_wowlan); + if ((dev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) && + nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE)) + goto nla_put_failure; - return 0; -} -#endif + if (nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX, + dev->wiphy.available_antennas_tx) || + nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX, + dev->wiphy.available_antennas_rx)) + goto nla_put_failure; -static int nl80211_send_band_rateinfo(struct sk_buff *msg, - struct ieee80211_supported_band *sband) -{ - struct nlattr *nl_rates, *nl_rate; - struct ieee80211_rate *rate; - int i; + if ((dev->wiphy.flags & WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD) && + nla_put_u32(msg, NL80211_ATTR_PROBE_RESP_OFFLOAD, + dev->wiphy.probe_resp_offload)) + goto nla_put_failure; - /* add HT info */ - if (sband->ht_cap.ht_supported && - (nla_put(msg, NL80211_BAND_ATTR_HT_MCS_SET, - sizeof(sband->ht_cap.mcs), - &sband->ht_cap.mcs) || - nla_put_u16(msg, NL80211_BAND_ATTR_HT_CAPA, - sband->ht_cap.cap) || - nla_put_u8(msg, NL80211_BAND_ATTR_HT_AMPDU_FACTOR, - sband->ht_cap.ampdu_factor) || - nla_put_u8(msg, NL80211_BAND_ATTR_HT_AMPDU_DENSITY, - sband->ht_cap.ampdu_density))) - return -ENOBUFS; + if ((dev->wiphy.available_antennas_tx || + dev->wiphy.available_antennas_rx) && dev->ops->get_antenna) { + u32 tx_ant = 0, rx_ant = 0; + int res; + res = rdev_get_antenna(dev, &tx_ant, &rx_ant); + if (!res) { + if (nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_TX, + tx_ant) || + nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_RX, + rx_ant)) + goto nla_put_failure; + } + } - /* add VHT info */ - if (sband->vht_cap.vht_supported && - (nla_put(msg, NL80211_BAND_ATTR_VHT_MCS_SET, - sizeof(sband->vht_cap.vht_mcs), - &sband->vht_cap.vht_mcs) || - nla_put_u32(msg, NL80211_BAND_ATTR_VHT_CAPA, - sband->vht_cap.cap))) - return -ENOBUFS; + if (nl80211_put_iftypes(msg, NL80211_ATTR_SUPPORTED_IFTYPES, + dev->wiphy.interface_modes)) + goto nla_put_failure; - /* add bitrates */ - nl_rates = nla_nest_start(msg, NL80211_BAND_ATTR_RATES); - if (!nl_rates) - return -ENOBUFS; + nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS); + if (!nl_bands) + goto nla_put_failure; - for (i = 0; i < sband->n_bitrates; i++) { - nl_rate = nla_nest_start(msg, i); - if (!nl_rate) - return -ENOBUFS; + for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + if (!dev->wiphy.bands[band]) + continue; - rate = &sband->bitrates[i]; - if (nla_put_u32(msg, NL80211_BITRATE_ATTR_RATE, - rate->bitrate)) - return -ENOBUFS; - if ((rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) && - nla_put_flag(msg, - NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE)) - return -ENOBUFS; + nl_band = nla_nest_start(msg, band); + if (!nl_band) + goto nla_put_failure; - nla_nest_end(msg, nl_rate); - } + /* add HT info */ + if (dev->wiphy.bands[band]->ht_cap.ht_supported && + (nla_put(msg, NL80211_BAND_ATTR_HT_MCS_SET, + sizeof(dev->wiphy.bands[band]->ht_cap.mcs), + &dev->wiphy.bands[band]->ht_cap.mcs) || + nla_put_u16(msg, NL80211_BAND_ATTR_HT_CAPA, + dev->wiphy.bands[band]->ht_cap.cap) || + nla_put_u8(msg, NL80211_BAND_ATTR_HT_AMPDU_FACTOR, + dev->wiphy.bands[band]->ht_cap.ampdu_factor) || + nla_put_u8(msg, NL80211_BAND_ATTR_HT_AMPDU_DENSITY, + dev->wiphy.bands[band]->ht_cap.ampdu_density))) + goto nla_put_failure; - nla_nest_end(msg, nl_rates); + /* add VHT info */ + if (dev->wiphy.bands[band]->vht_cap.vht_supported && + (nla_put(msg, NL80211_BAND_ATTR_VHT_MCS_SET, + sizeof(dev->wiphy.bands[band]->vht_cap.vht_mcs), + &dev->wiphy.bands[band]->vht_cap.vht_mcs) || + nla_put_u32(msg, NL80211_BAND_ATTR_VHT_CAPA, + dev->wiphy.bands[band]->vht_cap.cap))) + goto nla_put_failure; - return 0; -} + /* add frequencies */ + nl_freqs = nla_nest_start(msg, NL80211_BAND_ATTR_FREQS); + if (!nl_freqs) + goto nla_put_failure; -static int -nl80211_send_mgmt_stypes(struct sk_buff *msg, - const struct ieee80211_txrx_stypes *mgmt_stypes) -{ - u16 stypes; - struct nlattr *nl_ftypes, *nl_ifs; - enum nl80211_iftype ift; - int i; + for (i = 0; i < dev->wiphy.bands[band]->n_channels; i++) { + nl_freq = nla_nest_start(msg, i); + if (!nl_freq) + goto nla_put_failure; - if (!mgmt_stypes) - return 0; + chan = &dev->wiphy.bands[band]->channels[i]; - nl_ifs = nla_nest_start(msg, NL80211_ATTR_TX_FRAME_TYPES); - if (!nl_ifs) - return -ENOBUFS; + if (nl80211_msg_put_channel(msg, chan)) + goto nla_put_failure; - for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) { - nl_ftypes = nla_nest_start(msg, ift); - if (!nl_ftypes) - return -ENOBUFS; - i = 0; - stypes = mgmt_stypes[ift].tx; - while (stypes) { - if ((stypes & 1) && - nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE, - (i << 4) | IEEE80211_FTYPE_MGMT)) - return -ENOBUFS; - stypes >>= 1; - i++; + nla_nest_end(msg, nl_freq); } - nla_nest_end(msg, nl_ftypes); - } - nla_nest_end(msg, nl_ifs); + nla_nest_end(msg, nl_freqs); - nl_ifs = nla_nest_start(msg, NL80211_ATTR_RX_FRAME_TYPES); - if (!nl_ifs) - return -ENOBUFS; + /* add bitrates */ + nl_rates = nla_nest_start(msg, NL80211_BAND_ATTR_RATES); + if (!nl_rates) + goto nla_put_failure; - for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) { - nl_ftypes = nla_nest_start(msg, ift); - if (!nl_ftypes) - return -ENOBUFS; - i = 0; - stypes = mgmt_stypes[ift].rx; - while (stypes) { - if ((stypes & 1) && - nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE, - (i << 4) | IEEE80211_FTYPE_MGMT)) - return -ENOBUFS; - stypes >>= 1; - i++; - } - nla_nest_end(msg, nl_ftypes); - } - nla_nest_end(msg, nl_ifs); + for (i = 0; i < dev->wiphy.bands[band]->n_bitrates; i++) { + nl_rate = nla_nest_start(msg, i); + if (!nl_rate) + goto nla_put_failure; - return 0; -} + rate = &dev->wiphy.bands[band]->bitrates[i]; + if (nla_put_u32(msg, NL80211_BITRATE_ATTR_RATE, + rate->bitrate)) + goto nla_put_failure; + if ((rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) && + nla_put_flag(msg, + NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE)) + goto nla_put_failure; -static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, - struct sk_buff *msg, u32 portid, u32 seq, - int flags, bool split, long *split_start, - long *band_start, long *chan_start) -{ - void *hdr; - struct nlattr *nl_bands, *nl_band; - struct nlattr *nl_freqs, *nl_freq; - struct nlattr *nl_cmds; - enum ieee80211_band band; - struct ieee80211_channel *chan; - int i; - const struct ieee80211_txrx_stypes *mgmt_stypes = - dev->wiphy.mgmt_stypes; - long start = 0, start_chan = 0, start_band = 0; - u32 features; + nla_nest_end(msg, nl_rate); + } - hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_WIPHY); - if (!hdr) - return -ENOBUFS; + nla_nest_end(msg, nl_rates); - /* allow always using the variables */ - if (!split) { - split_start = &start; - band_start = &start_band; - chan_start = &start_chan; + nla_nest_end(msg, nl_band); } + nla_nest_end(msg, nl_bands); - if (nla_put_u32(msg, NL80211_ATTR_WIPHY, dev->wiphy_idx) || - nla_put_string(msg, NL80211_ATTR_WIPHY_NAME, - wiphy_name(&dev->wiphy)) || - nla_put_u32(msg, NL80211_ATTR_GENERATION, - cfg80211_rdev_list_generation)) - goto nla_put_failure; - - switch (*split_start) { - case 0: - if (nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT, - dev->wiphy.retry_short) || - nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_LONG, - dev->wiphy.retry_long) || - nla_put_u32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD, - dev->wiphy.frag_threshold) || - nla_put_u32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD, - dev->wiphy.rts_threshold) || - nla_put_u8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS, - dev->wiphy.coverage_class) || - nla_put_u8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS, - dev->wiphy.max_scan_ssids) || - nla_put_u8(msg, NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS, - dev->wiphy.max_sched_scan_ssids) || - nla_put_u16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN, - dev->wiphy.max_scan_ie_len) || - nla_put_u16(msg, NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN, - dev->wiphy.max_sched_scan_ie_len) || - nla_put_u8(msg, NL80211_ATTR_MAX_MATCH_SETS, - dev->wiphy.max_match_sets)) - goto nla_put_failure; + nl_cmds = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_COMMANDS); + if (!nl_cmds) + goto nla_put_failure; - if ((dev->wiphy.flags & WIPHY_FLAG_IBSS_RSN) && - nla_put_flag(msg, NL80211_ATTR_SUPPORT_IBSS_RSN)) - goto nla_put_failure; - if ((dev->wiphy.flags & WIPHY_FLAG_MESH_AUTH) && - nla_put_flag(msg, NL80211_ATTR_SUPPORT_MESH_AUTH)) - goto nla_put_failure; - if ((dev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) && - nla_put_flag(msg, NL80211_ATTR_SUPPORT_AP_UAPSD)) - goto nla_put_failure; - if ((dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_FW_ROAM) && - nla_put_flag(msg, NL80211_ATTR_ROAM_SUPPORT)) - goto nla_put_failure; - if ((dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) && - nla_put_flag(msg, NL80211_ATTR_TDLS_SUPPORT)) + i = 0; +#define CMD(op, n) \ + do { \ + if (dev->ops->op) { \ + i++; \ + if (nla_put_u32(msg, i, NL80211_CMD_ ## n)) \ + goto nla_put_failure; \ + } \ + } while (0) + + CMD(add_virtual_intf, NEW_INTERFACE); + CMD(change_virtual_intf, SET_INTERFACE); + CMD(add_key, NEW_KEY); + CMD(start_ap, START_AP); + CMD(add_station, NEW_STATION); + CMD(add_mpath, NEW_MPATH); + CMD(update_mesh_config, SET_MESH_CONFIG); + CMD(change_bss, SET_BSS); + CMD(auth, AUTHENTICATE); + CMD(assoc, ASSOCIATE); + CMD(deauth, DEAUTHENTICATE); + CMD(disassoc, DISASSOCIATE); + CMD(join_ibss, JOIN_IBSS); + CMD(join_mesh, JOIN_MESH); + CMD(set_pmksa, SET_PMKSA); + CMD(del_pmksa, DEL_PMKSA); + CMD(flush_pmksa, FLUSH_PMKSA); + if (dev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL) + CMD(remain_on_channel, REMAIN_ON_CHANNEL); + CMD(set_bitrate_mask, SET_TX_BITRATE_MASK); + CMD(mgmt_tx, FRAME); + CMD(mgmt_tx_cancel_wait, FRAME_WAIT_CANCEL); + if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) { + i++; + if (nla_put_u32(msg, i, NL80211_CMD_SET_WIPHY_NETNS)) goto nla_put_failure; - if ((dev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) && - nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP)) + } + if (dev->ops->set_monitor_channel || dev->ops->start_ap || + dev->ops->join_mesh) { + i++; + if (nla_put_u32(msg, i, NL80211_CMD_SET_CHANNEL)) goto nla_put_failure; - - (*split_start)++; - if (split) - break; - case 1: - if (nla_put(msg, NL80211_ATTR_CIPHER_SUITES, - sizeof(u32) * dev->wiphy.n_cipher_suites, - dev->wiphy.cipher_suites)) + } + CMD(set_wds_peer, SET_WDS_PEER); + if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) { + CMD(tdls_mgmt, TDLS_MGMT); + CMD(tdls_oper, TDLS_OPER); + } + if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) + CMD(sched_scan_start, START_SCHED_SCAN); + CMD(probe_client, PROBE_CLIENT); + CMD(set_noack_map, SET_NOACK_MAP); + if (dev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS) { + i++; + if (nla_put_u32(msg, i, NL80211_CMD_REGISTER_BEACONS)) goto nla_put_failure; + } + CMD(start_p2p_device, START_P2P_DEVICE); + CMD(set_mcast_rate, SET_MCAST_RATE); - if (nla_put_u8(msg, NL80211_ATTR_MAX_NUM_PMKIDS, - dev->wiphy.max_num_pmkids)) - goto nla_put_failure; +#ifdef CONFIG_NL80211_TESTMODE + CMD(testmode_cmd, TESTMODE); +#endif - if ((dev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) && - nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE)) - goto nla_put_failure; +#undef CMD - if (nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX, - dev->wiphy.available_antennas_tx) || - nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX, - dev->wiphy.available_antennas_rx)) + if (dev->ops->connect || dev->ops->auth) { + i++; + if (nla_put_u32(msg, i, NL80211_CMD_CONNECT)) goto nla_put_failure; + } - if ((dev->wiphy.flags & WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD) && - nla_put_u32(msg, NL80211_ATTR_PROBE_RESP_OFFLOAD, - dev->wiphy.probe_resp_offload)) + if (dev->ops->disconnect || dev->ops->deauth) { + i++; + if (nla_put_u32(msg, i, NL80211_CMD_DISCONNECT)) goto nla_put_failure; + } - if ((dev->wiphy.available_antennas_tx || - dev->wiphy.available_antennas_rx) && - dev->ops->get_antenna) { - u32 tx_ant = 0, rx_ant = 0; - int res; - res = rdev_get_antenna(dev, &tx_ant, &rx_ant); - if (!res) { - if (nla_put_u32(msg, - NL80211_ATTR_WIPHY_ANTENNA_TX, - tx_ant) || - nla_put_u32(msg, - NL80211_ATTR_WIPHY_ANTENNA_RX, - rx_ant)) - goto nla_put_failure; - } - } + nla_nest_end(msg, nl_cmds); - (*split_start)++; - if (split) - break; - case 2: - if (nl80211_put_iftypes(msg, NL80211_ATTR_SUPPORTED_IFTYPES, - dev->wiphy.interface_modes)) - goto nla_put_failure; - (*split_start)++; - if (split) - break; - case 3: - nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS); - if (!nl_bands) - goto nla_put_failure; + if (dev->ops->remain_on_channel && + (dev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL) && + nla_put_u32(msg, NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION, + dev->wiphy.max_remain_on_channel_duration)) + goto nla_put_failure; - for (band = *band_start; band < IEEE80211_NUM_BANDS; band++) { - struct ieee80211_supported_band *sband; + if ((dev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX) && + nla_put_flag(msg, NL80211_ATTR_OFFCHANNEL_TX_OK)) + goto nla_put_failure; - sband = dev->wiphy.bands[band]; + if (mgmt_stypes) { + u16 stypes; + struct nlattr *nl_ftypes, *nl_ifs; + enum nl80211_iftype ift; - if (!sband) - continue; + nl_ifs = nla_nest_start(msg, NL80211_ATTR_TX_FRAME_TYPES); + if (!nl_ifs) + goto nla_put_failure; - nl_band = nla_nest_start(msg, band); - if (!nl_band) + for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) { + nl_ftypes = nla_nest_start(msg, ift); + if (!nl_ftypes) goto nla_put_failure; - - switch (*chan_start) { - case 0: - if (nl80211_send_band_rateinfo(msg, sband)) - goto nla_put_failure; - (*chan_start)++; - if (split) - break; - default: - /* add frequencies */ - nl_freqs = nla_nest_start( - msg, NL80211_BAND_ATTR_FREQS); - if (!nl_freqs) + i = 0; + stypes = mgmt_stypes[ift].tx; + while (stypes) { + if ((stypes & 1) && + nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE, + (i << 4) | IEEE80211_FTYPE_MGMT)) goto nla_put_failure; - - for (i = *chan_start - 1; - i < sband->n_channels; - i++) { - nl_freq = nla_nest_start(msg, i); - if (!nl_freq) - goto nla_put_failure; - - chan = &sband->channels[i]; - - if (nl80211_msg_put_channel(msg, chan, - split)) - goto nla_put_failure; - - nla_nest_end(msg, nl_freq); - if (split) - break; - } - if (i < sband->n_channels) - *chan_start = i + 2; - else - *chan_start = 0; - nla_nest_end(msg, nl_freqs); - } - - nla_nest_end(msg, nl_band); - - if (split) { - /* start again here */ - if (*chan_start) - band--; - break; + stypes >>= 1; + i++; } + nla_nest_end(msg, nl_ftypes); } - nla_nest_end(msg, nl_bands); - if (band < IEEE80211_NUM_BANDS) - *band_start = band + 1; - else - *band_start = 0; + nla_nest_end(msg, nl_ifs); - /* if bands & channels are done, continue outside */ - if (*band_start == 0 && *chan_start == 0) - (*split_start)++; - if (split) - break; - case 4: - nl_cmds = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_COMMANDS); - if (!nl_cmds) + nl_ifs = nla_nest_start(msg, NL80211_ATTR_RX_FRAME_TYPES); + if (!nl_ifs) goto nla_put_failure; - i = 0; -#define CMD(op, n) \ - do { \ - if (dev->ops->op) { \ - i++; \ - if (nla_put_u32(msg, i, NL80211_CMD_ ## n)) \ - goto nla_put_failure; \ - } \ - } while (0) - - CMD(add_virtual_intf, NEW_INTERFACE); - CMD(change_virtual_intf, SET_INTERFACE); - CMD(add_key, NEW_KEY); - CMD(start_ap, START_AP); - CMD(add_station, NEW_STATION); - CMD(add_mpath, NEW_MPATH); - CMD(update_mesh_config, SET_MESH_CONFIG); - CMD(change_bss, SET_BSS); - CMD(auth, AUTHENTICATE); - CMD(assoc, ASSOCIATE); - CMD(deauth, DEAUTHENTICATE); - CMD(disassoc, DISASSOCIATE); - CMD(join_ibss, JOIN_IBSS); - CMD(join_mesh, JOIN_MESH); - CMD(set_pmksa, SET_PMKSA); - CMD(del_pmksa, DEL_PMKSA); - CMD(flush_pmksa, FLUSH_PMKSA); - if (dev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL) - CMD(remain_on_channel, REMAIN_ON_CHANNEL); - CMD(set_bitrate_mask, SET_TX_BITRATE_MASK); - CMD(mgmt_tx, FRAME); - CMD(mgmt_tx_cancel_wait, FRAME_WAIT_CANCEL); - if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) { - i++; - if (nla_put_u32(msg, i, NL80211_CMD_SET_WIPHY_NETNS)) - goto nla_put_failure; - } - if (dev->ops->set_monitor_channel || dev->ops->start_ap || - dev->ops->join_mesh) { - i++; - if (nla_put_u32(msg, i, NL80211_CMD_SET_CHANNEL)) - goto nla_put_failure; - } - CMD(set_wds_peer, SET_WDS_PEER); - if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) { - CMD(tdls_mgmt, TDLS_MGMT); - CMD(tdls_oper, TDLS_OPER); - } - if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) - CMD(sched_scan_start, START_SCHED_SCAN); - CMD(probe_client, PROBE_CLIENT); - CMD(set_noack_map, SET_NOACK_MAP); - if (dev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS) { - i++; - if (nla_put_u32(msg, i, NL80211_CMD_REGISTER_BEACONS)) + for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) { + nl_ftypes = nla_nest_start(msg, ift); + if (!nl_ftypes) goto nla_put_failure; + i = 0; + stypes = mgmt_stypes[ift].rx; + while (stypes) { + if ((stypes & 1) && + nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE, + (i << 4) | IEEE80211_FTYPE_MGMT)) + goto nla_put_failure; + stypes >>= 1; + i++; + } + nla_nest_end(msg, nl_ftypes); } - CMD(start_p2p_device, START_P2P_DEVICE); - CMD(set_mcast_rate, SET_MCAST_RATE); - -#ifdef CONFIG_NL80211_TESTMODE - CMD(testmode_cmd, TESTMODE); -#endif + nla_nest_end(msg, nl_ifs); + } -#undef CMD +#ifdef CONFIG_PM + if (dev->wiphy.wowlan.flags || dev->wiphy.wowlan.n_patterns) { + struct nlattr *nl_wowlan; - if (dev->ops->connect || dev->ops->auth) { - i++; - if (nla_put_u32(msg, i, NL80211_CMD_CONNECT)) - goto nla_put_failure; - } + nl_wowlan = nla_nest_start(msg, + NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED); + if (!nl_wowlan) + goto nla_put_failure; - if (dev->ops->disconnect || dev->ops->deauth) { - i++; - if (nla_put_u32(msg, i, NL80211_CMD_DISCONNECT)) + if (((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_ANY) && + nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) || + ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_DISCONNECT) && + nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) || + ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_MAGIC_PKT) && + nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) || + ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY) && + nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED)) || + ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) && + nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) || + ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ) && + nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) || + ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_4WAY_HANDSHAKE) && + nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) || + ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_RFKILL_RELEASE) && + nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE))) + goto nla_put_failure; + if (dev->wiphy.wowlan.n_patterns) { + struct nl80211_wowlan_pattern_support pat = { + .max_patterns = dev->wiphy.wowlan.n_patterns, + .min_pattern_len = + dev->wiphy.wowlan.pattern_min_len, + .max_pattern_len = + dev->wiphy.wowlan.pattern_max_len, + .max_pkt_offset = + dev->wiphy.wowlan.max_pkt_offset, + }; + if (nla_put(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN, + sizeof(pat), &pat)) goto nla_put_failure; } - nla_nest_end(msg, nl_cmds); - (*split_start)++; - if (split) - break; - case 5: - if (dev->ops->remain_on_channel && - (dev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL) && - nla_put_u32(msg, - NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION, - dev->wiphy.max_remain_on_channel_duration)) + if (nl80211_send_wowlan_tcp_caps(dev, msg)) goto nla_put_failure; - if ((dev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX) && - nla_put_flag(msg, NL80211_ATTR_OFFCHANNEL_TX_OK)) - goto nla_put_failure; - - if (nl80211_send_mgmt_stypes(msg, mgmt_stypes)) - goto nla_put_failure; - (*split_start)++; - if (split) - break; - case 6: -#ifdef CONFIG_PM - if (nl80211_send_wowlan(msg, dev, split)) - goto nla_put_failure; - (*split_start)++; - if (split) - break; -#else - (*split_start)++; + nla_nest_end(msg, nl_wowlan); + } #endif - case 7: - if (nl80211_put_iftypes(msg, NL80211_ATTR_SOFTWARE_IFTYPES, - dev->wiphy.software_iftypes)) - goto nla_put_failure; - if (nl80211_put_iface_combinations(&dev->wiphy, msg, split)) - goto nla_put_failure; + if (nl80211_put_iftypes(msg, NL80211_ATTR_SOFTWARE_IFTYPES, + dev->wiphy.software_iftypes)) + goto nla_put_failure; - (*split_start)++; - if (split) - break; - case 8: - if ((dev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME) && - nla_put_u32(msg, NL80211_ATTR_DEVICE_AP_SME, - dev->wiphy.ap_sme_capa)) - goto nla_put_failure; + if (nl80211_put_iface_combinations(&dev->wiphy, msg)) + goto nla_put_failure; - features = dev->wiphy.features; - /* - * We can only add the per-channel limit information if the - * dump is split, otherwise it makes it too big. Therefore - * only advertise it in that case. - */ - if (split) - features |= NL80211_FEATURE_ADVERTISE_CHAN_LIMITS; - if (nla_put_u32(msg, NL80211_ATTR_FEATURE_FLAGS, features)) - goto nla_put_failure; + if ((dev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME) && + nla_put_u32(msg, NL80211_ATTR_DEVICE_AP_SME, + dev->wiphy.ap_sme_capa)) + goto nla_put_failure; - if (dev->wiphy.ht_capa_mod_mask && - nla_put(msg, NL80211_ATTR_HT_CAPABILITY_MASK, - sizeof(*dev->wiphy.ht_capa_mod_mask), - dev->wiphy.ht_capa_mod_mask)) - goto nla_put_failure; + if (nla_put_u32(msg, NL80211_ATTR_FEATURE_FLAGS, + dev->wiphy.features)) + goto nla_put_failure; - if (dev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME && - dev->wiphy.max_acl_mac_addrs && - nla_put_u32(msg, NL80211_ATTR_MAC_ACL_MAX, - dev->wiphy.max_acl_mac_addrs)) - goto nla_put_failure; + if (dev->wiphy.ht_capa_mod_mask && + nla_put(msg, NL80211_ATTR_HT_CAPABILITY_MASK, + sizeof(*dev->wiphy.ht_capa_mod_mask), + dev->wiphy.ht_capa_mod_mask)) + goto nla_put_failure; - /* - * Any information below this point is only available to - * applications that can deal with it being split. This - * helps ensure that newly added capabilities don't break - * older tools by overrunning their buffers. - * - * We still increment split_start so that in the split - * case we'll continue with more data in the next round, - * but break unconditionally so unsplit data stops here. - */ - (*split_start)++; - break; - case 9: - if (dev->wiphy.extended_capabilities && - (nla_put(msg, NL80211_ATTR_EXT_CAPA, - dev->wiphy.extended_capabilities_len, - dev->wiphy.extended_capabilities) || - nla_put(msg, NL80211_ATTR_EXT_CAPA_MASK, - dev->wiphy.extended_capabilities_len, - dev->wiphy.extended_capabilities_mask))) - goto nla_put_failure; + if (dev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME && + dev->wiphy.max_acl_mac_addrs && + nla_put_u32(msg, NL80211_ATTR_MAC_ACL_MAX, + dev->wiphy.max_acl_mac_addrs)) + goto nla_put_failure; - if (dev->wiphy.vht_capa_mod_mask && - nla_put(msg, NL80211_ATTR_VHT_CAPABILITY_MASK, - sizeof(*dev->wiphy.vht_capa_mod_mask), - dev->wiphy.vht_capa_mod_mask)) - goto nla_put_failure; + if (dev->wiphy.extended_capabilities && + (nla_put(msg, NL80211_ATTR_EXT_CAPA, + dev->wiphy.extended_capabilities_len, + dev->wiphy.extended_capabilities) || + nla_put(msg, NL80211_ATTR_EXT_CAPA_MASK, + dev->wiphy.extended_capabilities_len, + dev->wiphy.extended_capabilities_mask))) + goto nla_put_failure; - /* done */ - *split_start = 0; - break; - } return genlmsg_end(msg, hdr); nla_put_failure: @@ -1548,83 +1383,22 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) { - int idx = 0, ret; + int idx = 0; int start = cb->args[0]; struct cfg80211_registered_device *dev; - s64 filter_wiphy = -1; - bool split = false; - struct nlattr **tb = nl80211_fam.attrbuf; - int res; mutex_lock(&cfg80211_mutex); - res = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, - tb, nl80211_fam.maxattr, nl80211_policy); - if (res == 0) { - split = tb[NL80211_ATTR_SPLIT_WIPHY_DUMP]; - if (tb[NL80211_ATTR_WIPHY]) - filter_wiphy = nla_get_u32(tb[NL80211_ATTR_WIPHY]); - if (tb[NL80211_ATTR_WDEV]) - filter_wiphy = nla_get_u64(tb[NL80211_ATTR_WDEV]) >> 32; - if (tb[NL80211_ATTR_IFINDEX]) { - struct net_device *netdev; - int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]); - - netdev = dev_get_by_index(sock_net(skb->sk), ifidx); - if (!netdev) { - mutex_unlock(&cfg80211_mutex); - return -ENODEV; - } - if (netdev->ieee80211_ptr) { - dev = wiphy_to_dev( - netdev->ieee80211_ptr->wiphy); - filter_wiphy = dev->wiphy_idx; - } - dev_put(netdev); - } - } - list_for_each_entry(dev, &cfg80211_rdev_list, list) { if (!net_eq(wiphy_net(&dev->wiphy), sock_net(skb->sk))) continue; if (++idx <= start) continue; - if (filter_wiphy != -1 && dev->wiphy_idx != filter_wiphy) - continue; - /* attempt to fit multiple wiphy data chunks into the skb */ - do { - ret = nl80211_send_wiphy(dev, skb, - NETLINK_CB(cb->skb).portid, - cb->nlh->nlmsg_seq, - NLM_F_MULTI, - split, &cb->args[1], - &cb->args[2], - &cb->args[3]); - if (ret < 0) { - /* - * If sending the wiphy data didn't fit (ENOBUFS - * or EMSGSIZE returned), this SKB is still - * empty (so it's not too big because another - * wiphy dataset is already in the skb) and - * we've not tried to adjust the dump allocation - * yet ... then adjust the alloc size to be - * bigger, and return 1 but with the empty skb. - * This results in an empty message being RX'ed - * in userspace, but that is ignored. - * - * We can then retry with the larger buffer. - */ - if ((ret == -ENOBUFS || ret == -EMSGSIZE) && - !skb->len && - cb->min_dump_alloc < 4096) { - cb->min_dump_alloc = 4096; - mutex_unlock(&cfg80211_mutex); - return 1; - } - idx--; - break; - } - } while (cb->args[1] > 0); - break; + if (nl80211_send_wiphy(skb, NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq, NLM_F_MULTI, + dev) < 0) { + idx--; + break; + } } mutex_unlock(&cfg80211_mutex); @@ -1638,12 +1412,11 @@ static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info) struct sk_buff *msg; struct cfg80211_registered_device *dev = info->user_ptr[0]; - msg = nlmsg_new(4096, GFP_KERNEL); + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) return -ENOMEM; - if (nl80211_send_wiphy(dev, msg, info->snd_portid, info->snd_seq, 0, - false, NULL, NULL, NULL) < 0) { + if (nl80211_send_wiphy(msg, info->snd_portid, info->snd_seq, 0, dev) < 0) { nlmsg_free(msg); return -ENOBUFS; } @@ -3250,7 +3023,6 @@ static int parse_station_flags(struct genl_info *info, sta_flags = nla_data(nla); params->sta_flags_mask = sta_flags->mask; params->sta_flags_set = sta_flags->set; - params->sta_flags_set &= params->sta_flags_mask; if ((params->sta_flags_mask | params->sta_flags_set) & BIT(__NL80211_STA_FLAG_INVALID)) return -EINVAL; @@ -3604,136 +3376,6 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info) return genlmsg_reply(msg, info); } -int cfg80211_check_station_change(struct wiphy *wiphy, - struct station_parameters *params, - enum cfg80211_station_type statype) -{ - if (params->listen_interval != -1) - return -EINVAL; - if (params->aid) - return -EINVAL; - - /* When you run into this, adjust the code below for the new flag */ - BUILD_BUG_ON(NL80211_STA_FLAG_MAX != 7); - - switch (statype) { - case CFG80211_STA_MESH_PEER_KERNEL: - case CFG80211_STA_MESH_PEER_USER: - /* - * No ignoring the TDLS flag here -- the userspace mesh - * code doesn't have the bug of including TDLS in the - * mask everywhere. - */ - if (params->sta_flags_mask & - ~(BIT(NL80211_STA_FLAG_AUTHENTICATED) | - BIT(NL80211_STA_FLAG_MFP) | - BIT(NL80211_STA_FLAG_AUTHORIZED))) - return -EINVAL; - break; - case CFG80211_STA_TDLS_PEER_SETUP: - case CFG80211_STA_TDLS_PEER_ACTIVE: - if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) - return -EINVAL; - /* ignore since it can't change */ - params->sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER); - break; - default: - /* disallow mesh-specific things */ - if (params->plink_action != NL80211_PLINK_ACTION_NO_ACTION) - return -EINVAL; - if (params->local_pm) - return -EINVAL; - if (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE) - return -EINVAL; - } - - if (statype != CFG80211_STA_TDLS_PEER_SETUP && - statype != CFG80211_STA_TDLS_PEER_ACTIVE) { - /* TDLS can't be set, ... */ - if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) - return -EINVAL; - /* - * ... but don't bother the driver with it. This works around - * a hostapd/wpa_supplicant issue -- it always includes the - * TLDS_PEER flag in the mask even for AP mode. - */ - params->sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER); - } - - if (statype != CFG80211_STA_TDLS_PEER_SETUP) { - /* reject other things that can't change */ - if (params->sta_modify_mask & STATION_PARAM_APPLY_UAPSD) - return -EINVAL; - if (params->sta_modify_mask & STATION_PARAM_APPLY_CAPABILITY) - return -EINVAL; - if (params->supported_rates) - return -EINVAL; - if (params->ext_capab || params->ht_capa || params->vht_capa) - return -EINVAL; - } - - if (statype != CFG80211_STA_AP_CLIENT) { - if (params->vlan) - return -EINVAL; - } - - switch (statype) { - case CFG80211_STA_AP_MLME_CLIENT: - /* Use this only for authorizing/unauthorizing a station */ - if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED))) - return -EOPNOTSUPP; - break; - case CFG80211_STA_AP_CLIENT: - /* accept only the listed bits */ - if (params->sta_flags_mask & - ~(BIT(NL80211_STA_FLAG_AUTHORIZED) | - BIT(NL80211_STA_FLAG_AUTHENTICATED) | - BIT(NL80211_STA_FLAG_ASSOCIATED) | - BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) | - BIT(NL80211_STA_FLAG_WME) | - BIT(NL80211_STA_FLAG_MFP))) - return -EINVAL; - - /* but authenticated/associated only if driver handles it */ - if (!(wiphy->features & NL80211_FEATURE_FULL_AP_CLIENT_STATE) && - params->sta_flags_mask & - (BIT(NL80211_STA_FLAG_AUTHENTICATED) | - BIT(NL80211_STA_FLAG_ASSOCIATED))) - return -EINVAL; - break; - case CFG80211_STA_IBSS: - case CFG80211_STA_AP_STA: - /* reject any changes other than AUTHORIZED */ - if (params->sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED)) - return -EINVAL; - break; - case CFG80211_STA_TDLS_PEER_SETUP: - /* reject any changes other than AUTHORIZED or WME */ - if (params->sta_flags_mask & ~(BIT(NL80211_STA_FLAG_AUTHORIZED) | - BIT(NL80211_STA_FLAG_WME))) - return -EINVAL; - /* force (at least) rates when authorizing */ - if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED) && - !params->supported_rates) - return -EINVAL; - break; - case CFG80211_STA_TDLS_PEER_ACTIVE: - /* reject any changes */ - return -EINVAL; - case CFG80211_STA_MESH_PEER_KERNEL: - if (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE) - return -EINVAL; - break; - case CFG80211_STA_MESH_PEER_USER: - if (params->plink_action != NL80211_PLINK_ACTION_NO_ACTION) - return -EINVAL; - break; - } - - return 0; -} -EXPORT_SYMBOL(cfg80211_check_station_change); - /* * Get vlan interface making sure it is running and on the right wiphy. */ @@ -3756,13 +3398,6 @@ static struct net_device *get_vlan(struct genl_info *info, goto error; } - if (v->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && - v->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && - v->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) { - ret = -EINVAL; - goto error; - } - if (!netif_running(v)) { ret = -ENETDOWN; goto error; @@ -3780,13 +3415,21 @@ nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] __read_mostly = { [NL80211_STA_WME_MAX_SP] = { .type = NLA_U8 }, }; -static int nl80211_parse_sta_wme(struct genl_info *info, - struct station_parameters *params) +static int nl80211_set_station_tdls(struct genl_info *info, + struct station_parameters *params) { struct nlattr *tb[NL80211_STA_WME_MAX + 1]; struct nlattr *nla; int err; + /* Dummy STA entry gets updated once the peer capabilities are known */ + if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) + params->ht_capa = + nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); + if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) + params->vht_capa = + nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]); + /* parse WME attributes if present */ if (!info->attrs[NL80211_ATTR_STA_WME]) return 0; @@ -3814,34 +3457,18 @@ static int nl80211_parse_sta_wme(struct genl_info *info, return 0; } -static int nl80211_set_station_tdls(struct genl_info *info, - struct station_parameters *params) -{ - /* Dummy STA entry gets updated once the peer capabilities are known */ - if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) - params->ht_capa = - nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); - if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) - params->vht_capa = - nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]); - - return nl80211_parse_sta_wme(info, params); -} - static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) { struct cfg80211_registered_device *rdev = info->user_ptr[0]; + int err; struct net_device *dev = info->user_ptr[1]; struct station_parameters params; - u8 *mac_addr; - int err; + u8 *mac_addr = NULL; memset(¶ms, 0, sizeof(params)); params.listen_interval = -1; - - if (!rdev->ops->change_station) - return -EOPNOTSUPP; + params.plink_state = -1; if (info->attrs[NL80211_ATTR_STA_AID]) return -EINVAL; @@ -3874,23 +3501,19 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]) return -EINVAL; + if (!rdev->ops->change_station) + return -EOPNOTSUPP; + if (parse_station_flags(info, dev->ieee80211_ptr->iftype, ¶ms)) return -EINVAL; - if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) { + if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) params.plink_action = - nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]); - if (params.plink_action >= NUM_NL80211_PLINK_ACTIONS) - return -EINVAL; - } + nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]); - if (info->attrs[NL80211_ATTR_STA_PLINK_STATE]) { + if (info->attrs[NL80211_ATTR_STA_PLINK_STATE]) params.plink_state = - nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]); - if (params.plink_state >= NUM_NL80211_PLINK_STATES) - return -EINVAL; - params.sta_modify_mask |= STATION_PARAM_APPLY_PLINK_STATE; - } + nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]); if (info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE]) { enum nl80211_mesh_power_mode pm = nla_get_u32( @@ -3900,36 +3523,130 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) pm > NL80211_MESH_POWER_MAX) return -EINVAL; - params.local_pm = pm; - } - - /* Include parameters for TDLS peer (will check later) */ - err = nl80211_set_station_tdls(info, ¶ms); - if (err) - return err; + params.local_pm = pm; + } + + switch (dev->ieee80211_ptr->iftype) { + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_AP_VLAN: + case NL80211_IFTYPE_P2P_GO: + /* disallow mesh-specific things */ + if (params.plink_action) + return -EINVAL; + if (params.local_pm) + return -EINVAL; + + /* TDLS can't be set, ... */ + if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) + return -EINVAL; + /* + * ... but don't bother the driver with it. This works around + * a hostapd/wpa_supplicant issue -- it always includes the + * TLDS_PEER flag in the mask even for AP mode. + */ + params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER); + + /* accept only the listed bits */ + if (params.sta_flags_mask & + ~(BIT(NL80211_STA_FLAG_AUTHORIZED) | + BIT(NL80211_STA_FLAG_AUTHENTICATED) | + BIT(NL80211_STA_FLAG_ASSOCIATED) | + BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) | + BIT(NL80211_STA_FLAG_WME) | + BIT(NL80211_STA_FLAG_MFP))) + return -EINVAL; + + /* but authenticated/associated only if driver handles it */ + if (!(rdev->wiphy.features & + NL80211_FEATURE_FULL_AP_CLIENT_STATE) && + params.sta_flags_mask & + (BIT(NL80211_STA_FLAG_AUTHENTICATED) | + BIT(NL80211_STA_FLAG_ASSOCIATED))) + return -EINVAL; - params.vlan = get_vlan(info, rdev); - if (IS_ERR(params.vlan)) - return PTR_ERR(params.vlan); + /* reject other things that can't change */ + if (params.supported_rates) + return -EINVAL; + if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) + return -EINVAL; + if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]) + return -EINVAL; + if (info->attrs[NL80211_ATTR_HT_CAPABILITY] || + info->attrs[NL80211_ATTR_VHT_CAPABILITY]) + return -EINVAL; - switch (dev->ieee80211_ptr->iftype) { - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_AP_VLAN: - case NL80211_IFTYPE_P2P_GO: + /* must be last in here for error handling */ + params.vlan = get_vlan(info, rdev); + if (IS_ERR(params.vlan)) + return PTR_ERR(params.vlan); + break; case NL80211_IFTYPE_P2P_CLIENT: case NL80211_IFTYPE_STATION: + /* + * Don't allow userspace to change the TDLS_PEER flag, + * but silently ignore attempts to change it since we + * don't have state here to verify that it doesn't try + * to change the flag. + */ + params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER); + /* Include parameters for TDLS peer (driver will check) */ + err = nl80211_set_station_tdls(info, ¶ms); + if (err) + return err; + /* disallow things sta doesn't support */ + if (params.plink_action) + return -EINVAL; + if (params.local_pm) + return -EINVAL; + /* reject any changes other than AUTHORIZED or WME (for TDLS) */ + if (params.sta_flags_mask & ~(BIT(NL80211_STA_FLAG_AUTHORIZED) | + BIT(NL80211_STA_FLAG_WME))) + return -EINVAL; + break; case NL80211_IFTYPE_ADHOC: + /* disallow things sta doesn't support */ + if (params.plink_action) + return -EINVAL; + if (params.local_pm) + return -EINVAL; + if (info->attrs[NL80211_ATTR_HT_CAPABILITY] || + info->attrs[NL80211_ATTR_VHT_CAPABILITY]) + return -EINVAL; + /* reject any changes other than AUTHORIZED */ + if (params.sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED)) + return -EINVAL; + break; case NL80211_IFTYPE_MESH_POINT: + /* disallow things mesh doesn't support */ + if (params.vlan) + return -EINVAL; + if (params.supported_rates) + return -EINVAL; + if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) + return -EINVAL; + if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]) + return -EINVAL; + if (info->attrs[NL80211_ATTR_HT_CAPABILITY] || + info->attrs[NL80211_ATTR_VHT_CAPABILITY]) + return -EINVAL; + /* + * No special handling for TDLS here -- the userspace + * mesh code doesn't have this bug. + */ + if (params.sta_flags_mask & + ~(BIT(NL80211_STA_FLAG_AUTHENTICATED) | + BIT(NL80211_STA_FLAG_MFP) | + BIT(NL80211_STA_FLAG_AUTHORIZED))) + return -EINVAL; break; default: - err = -EOPNOTSUPP; - goto out_put_vlan; + return -EOPNOTSUPP; } - /* driver will call cfg80211_check_station_change() */ + /* be aware of params.vlan when changing code here */ + err = rdev_change_station(rdev, dev, mac_addr, ¶ms); - out_put_vlan: if (params.vlan) dev_put(params.vlan); @@ -3946,9 +3663,6 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) memset(¶ms, 0, sizeof(params)); - if (!rdev->ops->add_station) - return -EOPNOTSUPP; - if (!info->attrs[NL80211_ATTR_MAC]) return -EINVAL; @@ -3994,32 +3708,50 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) params.vht_capa = nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]); - if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) { + if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) params.plink_action = - nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]); - if (params.plink_action >= NUM_NL80211_PLINK_ACTIONS) - return -EINVAL; - } + nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]); - err = nl80211_parse_sta_wme(info, ¶ms); - if (err) - return err; + if (!rdev->ops->add_station) + return -EOPNOTSUPP; if (parse_station_flags(info, dev->ieee80211_ptr->iftype, ¶ms)) return -EINVAL; - /* When you run into this, adjust the code below for the new flag */ - BUILD_BUG_ON(NL80211_STA_FLAG_MAX != 7); - switch (dev->ieee80211_ptr->iftype) { case NL80211_IFTYPE_AP: case NL80211_IFTYPE_AP_VLAN: case NL80211_IFTYPE_P2P_GO: - /* ignore WME attributes if iface/sta is not capable */ - if (!(rdev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) || - !(params.sta_flags_set & BIT(NL80211_STA_FLAG_WME))) - params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD; + /* parse WME attributes if sta is WME capable */ + if ((rdev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) && + (params.sta_flags_set & BIT(NL80211_STA_FLAG_WME)) && + info->attrs[NL80211_ATTR_STA_WME]) { + struct nlattr *tb[NL80211_STA_WME_MAX + 1]; + struct nlattr *nla; + + nla = info->attrs[NL80211_ATTR_STA_WME]; + err = nla_parse_nested(tb, NL80211_STA_WME_MAX, nla, + nl80211_sta_wme_policy); + if (err) + return err; + + if (tb[NL80211_STA_WME_UAPSD_QUEUES]) + params.uapsd_queues = + nla_get_u8(tb[NL80211_STA_WME_UAPSD_QUEUES]); + if (params.uapsd_queues & + ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK) + return -EINVAL; + + if (tb[NL80211_STA_WME_MAX_SP]) + params.max_sp = + nla_get_u8(tb[NL80211_STA_WME_MAX_SP]); + if (params.max_sp & + ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK) + return -EINVAL; + + params.sta_modify_mask |= STATION_PARAM_APPLY_UAPSD; + } /* TDLS peers cannot be added */ if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) return -EINVAL; @@ -4040,9 +3772,6 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) return PTR_ERR(params.vlan); break; case NL80211_IFTYPE_MESH_POINT: - /* ignore uAPSD data */ - params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD; - /* associated is disallowed */ if (params.sta_flags_mask & BIT(NL80211_STA_FLAG_ASSOCIATED)) return -EINVAL; @@ -4051,14 +3780,8 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) return -EINVAL; break; case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_P2P_CLIENT: - /* ignore uAPSD data */ - params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD; - - /* these are disallowed */ - if (params.sta_flags_mask & - (BIT(NL80211_STA_FLAG_ASSOCIATED) | - BIT(NL80211_STA_FLAG_AUTHENTICATED))) + /* associated is disallowed */ + if (params.sta_flags_mask & BIT(NL80211_STA_FLAG_ASSOCIATED)) return -EINVAL; /* Only TDLS peers can be added */ if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) @@ -4069,11 +3792,6 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) /* ... with external setup is supported */ if (!(rdev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP)) return -EOPNOTSUPP; - /* - * Older wpa_supplicant versions always mark the TDLS peer - * as authorized, but it shouldn't yet be. - */ - params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_AUTHORIZED); break; default: return -EOPNOTSUPP; @@ -4618,7 +4336,6 @@ static const struct nla_policy [NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL] = { .type = NLA_U8 }, [NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC] = { .type = NLA_U8 }, [NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG }, - [NL80211_MESH_SETUP_USERSPACE_MPM] = { .type = NLA_FLAG }, [NL80211_MESH_SETUP_IE] = { .type = NLA_BINARY, .len = IEEE80211_MAX_DATA_LEN }, [NL80211_MESH_SETUP_USERSPACE_AMPE] = { .type = NLA_FLAG }, @@ -4757,7 +4474,6 @@ do { \ static int nl80211_parse_mesh_setup(struct genl_info *info, struct mesh_setup *setup) { - struct cfg80211_registered_device *rdev = info->user_ptr[0]; struct nlattr *tb[NL80211_MESH_SETUP_ATTR_MAX + 1]; if (!info->attrs[NL80211_ATTR_MESH_SETUP]) @@ -4794,14 +4510,8 @@ static int nl80211_parse_mesh_setup(struct genl_info *info, setup->ie = nla_data(ieattr); setup->ie_len = nla_len(ieattr); } - if (tb[NL80211_MESH_SETUP_USERSPACE_MPM] && - !(rdev->wiphy.features & NL80211_FEATURE_USERSPACE_MPM)) - return -EINVAL; - setup->user_mpm = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_MPM]); setup->is_authenticated = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AUTH]); setup->is_secure = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AMPE]); - if (setup->is_secure) - setup->user_mpm = true; return 0; } @@ -5996,10 +5706,14 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) { struct cfg80211_registered_device *rdev = info->user_ptr[0]; struct net_device *dev = info->user_ptr[1]; + struct cfg80211_crypto_settings crypto; struct ieee80211_channel *chan; - struct cfg80211_assoc_request req = {}; - const u8 *bssid, *ssid; - int err, ssid_len = 0; + const u8 *bssid, *ssid, *ie = NULL, *prev_bssid = NULL; + int err, ssid_len, ie_len = 0; + bool use_mfp = false; + u32 flags = 0; + struct ieee80211_ht_cap *ht_capa = NULL; + struct ieee80211_ht_cap *ht_capa_mask = NULL; if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) return -EINVAL; @@ -6027,58 +5741,41 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]); if (info->attrs[NL80211_ATTR_IE]) { - req.ie = nla_data(info->attrs[NL80211_ATTR_IE]); - req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); + ie = nla_data(info->attrs[NL80211_ATTR_IE]); + ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); } if (info->attrs[NL80211_ATTR_USE_MFP]) { enum nl80211_mfp mfp = nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]); if (mfp == NL80211_MFP_REQUIRED) - req.use_mfp = true; + use_mfp = true; else if (mfp != NL80211_MFP_NO) return -EINVAL; } if (info->attrs[NL80211_ATTR_PREV_BSSID]) - req.prev_bssid = nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]); + prev_bssid = nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]); if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT])) - req.flags |= ASSOC_REQ_DISABLE_HT; + flags |= ASSOC_REQ_DISABLE_HT; if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]) - memcpy(&req.ht_capa_mask, - nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]), - sizeof(req.ht_capa_mask)); + ht_capa_mask = + nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]); if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) { - if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]) + if (!ht_capa_mask) return -EINVAL; - memcpy(&req.ht_capa, - nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]), - sizeof(req.ht_capa)); - } - - if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_VHT])) - req.flags |= ASSOC_REQ_DISABLE_VHT; - - if (info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]) - memcpy(&req.vht_capa_mask, - nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]), - sizeof(req.vht_capa_mask)); - - if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) { - if (!info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]) - return -EINVAL; - memcpy(&req.vht_capa, - nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]), - sizeof(req.vht_capa)); + ht_capa = nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); } - err = nl80211_crypto_settings(rdev, info, &req.crypto, 1); + err = nl80211_crypto_settings(rdev, info, &crypto, 1); if (!err) - err = cfg80211_mlme_assoc(rdev, dev, chan, bssid, - ssid, ssid_len, &req); + err = cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid, + ssid, ssid_len, ie, ie_len, use_mfp, + &crypto, flags, ht_capa, + ht_capa_mask); return err; } @@ -6658,24 +6355,6 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) sizeof(connect.ht_capa)); } - if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_VHT])) - connect.flags |= ASSOC_REQ_DISABLE_VHT; - - if (info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]) - memcpy(&connect.vht_capa_mask, - nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]), - sizeof(connect.vht_capa_mask)); - - if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) { - if (!info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]) { - kfree(connkeys); - return -EINVAL; - } - memcpy(&connect.vht_capa, - nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]), - sizeof(connect.vht_capa)); - } - err = cfg80211_connect(rdev, dev, &connect, connkeys); if (err) kfree(connkeys); @@ -7449,9 +7128,6 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info) return err; } - if (setup.user_mpm) - cfg.auto_open_plinks = false; - if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { err = nl80211_parse_chandef(rdev, info, &setup.chandef); if (err) @@ -7651,8 +7327,7 @@ static int nl80211_parse_wowlan_tcp(struct cfg80211_registered_device *rdev, return -EINVAL; if (nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]) > - rdev->wiphy.wowlan.tcp->data_interval_max || - nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]) == 0) + rdev->wiphy.wowlan.tcp->data_interval_max) return -EINVAL; wake_size = nla_len(tb[NL80211_WOWLAN_TCP_WAKE_PAYLOAD]); @@ -8148,54 +7823,6 @@ static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info) return 0; } -static int nl80211_get_protocol_features(struct sk_buff *skb, - struct genl_info *info) -{ - void *hdr; - struct sk_buff *msg; - - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); - if (!msg) - return -ENOMEM; - - hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0, - NL80211_CMD_GET_PROTOCOL_FEATURES); - if (!hdr) - goto nla_put_failure; - - if (nla_put_u32(msg, NL80211_ATTR_PROTOCOL_FEATURES, - NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP)) - goto nla_put_failure; - - genlmsg_end(msg, hdr); - return genlmsg_reply(msg, info); - - nla_put_failure: - kfree_skb(msg); - return -ENOBUFS; -} - -static int nl80211_update_ft_ies(struct sk_buff *skb, struct genl_info *info) -{ - struct cfg80211_registered_device *rdev = info->user_ptr[0]; - struct cfg80211_update_ft_ies_params ft_params; - struct net_device *dev = info->user_ptr[1]; - - if (!rdev->ops->update_ft_ies) - return -EOPNOTSUPP; - - if (!info->attrs[NL80211_ATTR_MDID] || - !is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) - return -EINVAL; - - memset(&ft_params, 0, sizeof(ft_params)); - ft_params.md = nla_get_u16(info->attrs[NL80211_ATTR_MDID]); - ft_params.ie = nla_data(info->attrs[NL80211_ATTR_IE]); - ft_params.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); - - return rdev_update_ft_ies(rdev, dev, &ft_params); -} - #define NL80211_FLAG_NEED_WIPHY 0x01 #define NL80211_FLAG_NEED_NETDEV 0x02 #define NL80211_FLAG_NEED_RTNL 0x04 @@ -8872,19 +8499,6 @@ static struct genl_ops nl80211_ops[] = { .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | NL80211_FLAG_NEED_RTNL, }, - { - .cmd = NL80211_CMD_GET_PROTOCOL_FEATURES, - .doit = nl80211_get_protocol_features, - .policy = nl80211_policy, - }, - { - .cmd = NL80211_CMD_UPDATE_FT_IES, - .doit = nl80211_update_ft_ies, - .policy = nl80211_policy, - .flags = GENL_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | - NL80211_FLAG_NEED_RTNL, - }, }; static struct genl_multicast_group nl80211_mlme_mcgrp = { @@ -8912,8 +8526,7 @@ void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev) if (!msg) return; - if (nl80211_send_wiphy(rdev, msg, 0, 0, 0, - false, NULL, NULL, NULL) < 0) { + if (nl80211_send_wiphy(msg, 0, 0, 0, rdev) < 0) { nlmsg_free(msg); return; } @@ -9237,31 +8850,21 @@ void nl80211_send_disassoc(struct cfg80211_registered_device *rdev, NL80211_CMD_DISASSOCIATE, gfp); } -void cfg80211_send_unprot_deauth(struct net_device *dev, const u8 *buf, - size_t len) +void nl80211_send_unprot_deauth(struct cfg80211_registered_device *rdev, + struct net_device *netdev, const u8 *buf, + size_t len, gfp_t gfp) { - struct wireless_dev *wdev = dev->ieee80211_ptr; - struct wiphy *wiphy = wdev->wiphy; - struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); - - trace_cfg80211_send_unprot_deauth(dev); - nl80211_send_mlme_event(rdev, dev, buf, len, - NL80211_CMD_UNPROT_DEAUTHENTICATE, GFP_ATOMIC); + nl80211_send_mlme_event(rdev, netdev, buf, len, + NL80211_CMD_UNPROT_DEAUTHENTICATE, gfp); } -EXPORT_SYMBOL(cfg80211_send_unprot_deauth); -void cfg80211_send_unprot_disassoc(struct net_device *dev, const u8 *buf, - size_t len) +void nl80211_send_unprot_disassoc(struct cfg80211_registered_device *rdev, + struct net_device *netdev, const u8 *buf, + size_t len, gfp_t gfp) { - struct wireless_dev *wdev = dev->ieee80211_ptr; - struct wiphy *wiphy = wdev->wiphy; - struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); - - trace_cfg80211_send_unprot_disassoc(dev); - nl80211_send_mlme_event(rdev, dev, buf, len, - NL80211_CMD_UNPROT_DISASSOCIATE, GFP_ATOMIC); + nl80211_send_mlme_event(rdev, netdev, buf, len, + NL80211_CMD_UNPROT_DISASSOCIATE, gfp); } -EXPORT_SYMBOL(cfg80211_send_unprot_disassoc); static void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev, struct net_device *netdev, int cmd, @@ -9464,19 +9067,14 @@ void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev, nlmsg_free(msg); } -void cfg80211_notify_new_peer_candidate(struct net_device *dev, const u8 *addr, - const u8* ie, u8 ie_len, gfp_t gfp) +void nl80211_send_new_peer_candidate(struct cfg80211_registered_device *rdev, + struct net_device *netdev, + const u8 *macaddr, const u8* ie, u8 ie_len, + 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; - if (WARN_ON(wdev->iftype != NL80211_IFTYPE_MESH_POINT)) - return; - - trace_cfg80211_notify_new_peer_candidate(dev, addr); - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); if (!msg) return; @@ -9488,8 +9086,8 @@ void cfg80211_notify_new_peer_candidate(struct net_device *dev, const u8 *addr, } if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || - nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || - nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) || + nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || + nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, macaddr) || (ie_len && ie && nla_put(msg, NL80211_ATTR_IE, ie_len , ie))) goto nla_put_failure; @@ -9504,7 +9102,6 @@ void cfg80211_notify_new_peer_candidate(struct net_device *dev, const u8 *addr, genlmsg_cancel(msg, hdr); nlmsg_free(msg); } -EXPORT_SYMBOL(cfg80211_notify_new_peer_candidate); void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev, struct net_device *netdev, const u8 *addr, @@ -9573,7 +9170,7 @@ void nl80211_send_beacon_hint_event(struct wiphy *wiphy, nl_freq = nla_nest_start(msg, NL80211_ATTR_FREQ_BEFORE); if (!nl_freq) goto nla_put_failure; - if (nl80211_msg_put_channel(msg, channel_before, false)) + if (nl80211_msg_put_channel(msg, channel_before)) goto nla_put_failure; nla_nest_end(msg, nl_freq); @@ -9581,7 +9178,7 @@ void nl80211_send_beacon_hint_event(struct wiphy *wiphy, nl_freq = nla_nest_start(msg, NL80211_ATTR_FREQ_AFTER); if (!nl_freq) goto nla_put_failure; - if (nl80211_msg_put_channel(msg, channel_after, false)) + if (nl80211_msg_put_channel(msg, channel_after)) goto nla_put_failure; nla_nest_end(msg, nl_freq); @@ -9643,42 +9240,31 @@ static void nl80211_send_remain_on_chan_event( nlmsg_free(msg); } -void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie, - struct ieee80211_channel *chan, - unsigned int duration, gfp_t gfp) +void nl80211_send_remain_on_channel(struct cfg80211_registered_device *rdev, + struct wireless_dev *wdev, u64 cookie, + struct ieee80211_channel *chan, + 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_chan_event(NL80211_CMD_REMAIN_ON_CHANNEL, rdev, wdev, cookie, chan, duration, gfp); } -EXPORT_SYMBOL(cfg80211_ready_on_channel); -void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie, - struct ieee80211_channel *chan, - 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) { - 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_chan_event(NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL, rdev, wdev, cookie, chan, 0, gfp); } -EXPORT_SYMBOL(cfg80211_remain_on_channel_expired); -void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr, - struct station_info *sinfo, gfp_t gfp) +void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, + struct net_device *dev, const u8 *mac_addr, + struct station_info *sinfo, gfp_t gfp) { - struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; - struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); struct sk_buff *msg; - trace_cfg80211_new_sta(dev, mac_addr, sinfo); - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); if (!msg) return; @@ -9692,17 +9278,14 @@ void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr, genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, nl80211_mlme_mcgrp.id, gfp); } -EXPORT_SYMBOL(cfg80211_new_sta); -void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp) +void nl80211_send_sta_del_event(struct cfg80211_registered_device *rdev, + struct net_device *dev, const u8 *mac_addr, + gfp_t gfp) { - struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; - struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); struct sk_buff *msg; void *hdr; - trace_cfg80211_del_sta(dev, mac_addr); - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); if (!msg) return; @@ -9727,14 +9310,12 @@ void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp) genlmsg_cancel(msg, hdr); nlmsg_free(msg); } -EXPORT_SYMBOL(cfg80211_del_sta); -void cfg80211_conn_failed(struct net_device *dev, const u8 *mac_addr, - enum nl80211_connect_failed_reason reason, - gfp_t gfp) +void nl80211_send_conn_failed_event(struct cfg80211_registered_device *rdev, + struct net_device *dev, const u8 *mac_addr, + enum nl80211_connect_failed_reason reason, + gfp_t gfp) { - struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; - struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); struct sk_buff *msg; void *hdr; @@ -9763,7 +9344,6 @@ void cfg80211_conn_failed(struct net_device *dev, const u8 *mac_addr, genlmsg_cancel(msg, hdr); nlmsg_free(msg); } -EXPORT_SYMBOL(cfg80211_conn_failed); static bool __nl80211_unexpected_frame(struct net_device *dev, u8 cmd, const u8 *addr, gfp_t gfp) @@ -9808,47 +9388,19 @@ static bool __nl80211_unexpected_frame(struct net_device *dev, u8 cmd, return true; } -bool cfg80211_rx_spurious_frame(struct net_device *dev, - const u8 *addr, gfp_t gfp) +bool nl80211_unexpected_frame(struct net_device *dev, const u8 *addr, gfp_t gfp) { - struct wireless_dev *wdev = dev->ieee80211_ptr; - bool ret; - - trace_cfg80211_rx_spurious_frame(dev, addr); - - if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && - wdev->iftype != NL80211_IFTYPE_P2P_GO)) { - trace_cfg80211_return_bool(false); - return false; - } - ret = __nl80211_unexpected_frame(dev, NL80211_CMD_UNEXPECTED_FRAME, - addr, gfp); - trace_cfg80211_return_bool(ret); - return ret; + return __nl80211_unexpected_frame(dev, NL80211_CMD_UNEXPECTED_FRAME, + addr, gfp); } -EXPORT_SYMBOL(cfg80211_rx_spurious_frame); -bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev, - const u8 *addr, gfp_t gfp) +bool nl80211_unexpected_4addr_frame(struct net_device *dev, + const u8 *addr, gfp_t gfp) { - struct wireless_dev *wdev = dev->ieee80211_ptr; - bool ret; - - trace_cfg80211_rx_unexpected_4addr_frame(dev, addr); - - if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && - wdev->iftype != NL80211_IFTYPE_P2P_GO && - wdev->iftype != NL80211_IFTYPE_AP_VLAN)) { - trace_cfg80211_return_bool(false); - return false; - } - ret = __nl80211_unexpected_frame(dev, - NL80211_CMD_UNEXPECTED_4ADDR_FRAME, - addr, gfp); - trace_cfg80211_return_bool(ret); - return ret; + return __nl80211_unexpected_frame(dev, + NL80211_CMD_UNEXPECTED_4ADDR_FRAME, + addr, gfp); } -EXPORT_SYMBOL(cfg80211_rx_unexpected_4addr_frame); int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, struct wireless_dev *wdev, u32 nlportid, @@ -9888,17 +9440,15 @@ int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, return -ENOBUFS; } -void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie, - const u8 *buf, size_t len, bool ack, gfp_t gfp) +void nl80211_send_mgmt_tx_status(struct cfg80211_registered_device *rdev, + struct wireless_dev *wdev, u64 cookie, + const u8 *buf, size_t len, bool ack, + gfp_t gfp) { - struct wiphy *wiphy = wdev->wiphy; - struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); struct net_device *netdev = wdev->netdev; struct sk_buff *msg; void *hdr; - trace_cfg80211_mgmt_tx_status(wdev, cookie, ack); - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); if (!msg) return; @@ -9926,21 +9476,17 @@ void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie, genlmsg_cancel(msg, hdr); nlmsg_free(msg); } -EXPORT_SYMBOL(cfg80211_mgmt_tx_status); -void cfg80211_cqm_rssi_notify(struct net_device *dev, - enum nl80211_cqm_rssi_threshold_event rssi_event, - gfp_t gfp) +void +nl80211_send_cqm_rssi_notify(struct cfg80211_registered_device *rdev, + struct net_device *netdev, + enum nl80211_cqm_rssi_threshold_event rssi_event, + gfp_t gfp) { - struct wireless_dev *wdev = dev->ieee80211_ptr; - struct wiphy *wiphy = wdev->wiphy; - struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); struct sk_buff *msg; struct nlattr *pinfoattr; void *hdr; - trace_cfg80211_cqm_rssi_notify(dev, rssi_event); - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); if (!msg) return; @@ -9952,7 +9498,7 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev, } if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || - nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex)) + nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex)) goto nla_put_failure; pinfoattr = nla_nest_start(msg, NL80211_ATTR_CQM); @@ -9975,11 +9521,10 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev, genlmsg_cancel(msg, hdr); nlmsg_free(msg); } -EXPORT_SYMBOL(cfg80211_cqm_rssi_notify); -static void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev, - struct net_device *netdev, const u8 *bssid, - const u8 *replay_ctr, gfp_t gfp) +void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev, + struct net_device *netdev, const u8 *bssid, + const u8 *replay_ctr, gfp_t gfp) { struct sk_buff *msg; struct nlattr *rekey_attr; @@ -10021,22 +9566,9 @@ static void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev, nlmsg_free(msg); } -void cfg80211_gtk_rekey_notify(struct net_device *dev, const u8 *bssid, - const u8 *replay_ctr, gfp_t gfp) -{ - struct wireless_dev *wdev = dev->ieee80211_ptr; - struct wiphy *wiphy = wdev->wiphy; - struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); - - trace_cfg80211_gtk_rekey_notify(dev, bssid); - nl80211_gtk_rekey_notify(rdev, dev, bssid, replay_ctr, gfp); -} -EXPORT_SYMBOL(cfg80211_gtk_rekey_notify); - -static void -nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev, - struct net_device *netdev, int index, - const u8 *bssid, bool preauth, gfp_t gfp) +void nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev, + struct net_device *netdev, int index, + const u8 *bssid, bool preauth, gfp_t gfp) { struct sk_buff *msg; struct nlattr *attr; @@ -10079,22 +9611,9 @@ nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev, nlmsg_free(msg); } -void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index, - const u8 *bssid, bool preauth, gfp_t gfp) -{ - struct wireless_dev *wdev = dev->ieee80211_ptr; - struct wiphy *wiphy = wdev->wiphy; - struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); - - trace_cfg80211_pmksa_candidate_notify(dev, index, bssid, preauth); - nl80211_pmksa_candidate_notify(rdev, dev, index, bssid, preauth, gfp); -} -EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify); - -static void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev, - struct net_device *netdev, - struct cfg80211_chan_def *chandef, - gfp_t gfp) +void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev, + struct net_device *netdev, + struct cfg80211_chan_def *chandef, gfp_t gfp) { struct sk_buff *msg; void *hdr; @@ -10126,36 +9645,11 @@ static void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev, nlmsg_free(msg); } -void cfg80211_ch_switch_notify(struct net_device *dev, - struct cfg80211_chan_def *chandef) -{ - struct wireless_dev *wdev = dev->ieee80211_ptr; - struct wiphy *wiphy = wdev->wiphy; - struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); - - trace_cfg80211_ch_switch_notify(dev, chandef); - - wdev_lock(wdev); - - if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && - wdev->iftype != NL80211_IFTYPE_P2P_GO)) - goto out; - - wdev->channel = chandef->chan; - nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL); -out: - wdev_unlock(wdev); - return; -} -EXPORT_SYMBOL(cfg80211_ch_switch_notify); - -void cfg80211_cqm_txe_notify(struct net_device *dev, - const u8 *peer, u32 num_packets, - u32 rate, u32 intvl, gfp_t gfp) +void +nl80211_send_cqm_txe_notify(struct cfg80211_registered_device *rdev, + struct net_device *netdev, const u8 *peer, + u32 num_packets, u32 rate, u32 intvl, gfp_t gfp) { - struct wireless_dev *wdev = dev->ieee80211_ptr; - struct wiphy *wiphy = wdev->wiphy; - struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); struct sk_buff *msg; struct nlattr *pinfoattr; void *hdr; @@ -10171,7 +9665,7 @@ void cfg80211_cqm_txe_notify(struct net_device *dev, } if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || - nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || + nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer)) goto nla_put_failure; @@ -10200,7 +9694,6 @@ void cfg80211_cqm_txe_notify(struct net_device *dev, genlmsg_cancel(msg, hdr); nlmsg_free(msg); } -EXPORT_SYMBOL(cfg80211_cqm_txe_notify); void nl80211_radar_notify(struct cfg80211_registered_device *rdev, @@ -10253,18 +9746,15 @@ nl80211_radar_notify(struct cfg80211_registered_device *rdev, nlmsg_free(msg); } -void cfg80211_cqm_pktloss_notify(struct net_device *dev, - const u8 *peer, u32 num_packets, gfp_t gfp) +void +nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev, + struct net_device *netdev, const u8 *peer, + u32 num_packets, gfp_t gfp) { - struct wireless_dev *wdev = dev->ieee80211_ptr; - struct wiphy *wiphy = wdev->wiphy; - struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); struct sk_buff *msg; struct nlattr *pinfoattr; void *hdr; - trace_cfg80211_cqm_pktloss_notify(dev, peer, num_packets); - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); if (!msg) return; @@ -10276,7 +9766,7 @@ void cfg80211_cqm_pktloss_notify(struct net_device *dev, } if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || - nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || + nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer)) goto nla_put_failure; @@ -10299,7 +9789,6 @@ void cfg80211_cqm_pktloss_notify(struct net_device *dev, genlmsg_cancel(msg, hdr); nlmsg_free(msg); } -EXPORT_SYMBOL(cfg80211_cqm_pktloss_notify); void cfg80211_probe_status(struct net_device *dev, const u8 *addr, u64 cookie, bool acked, gfp_t gfp) @@ -10586,50 +10075,6 @@ static struct notifier_block nl80211_netlink_notifier = { .notifier_call = nl80211_netlink_notify, }; -void cfg80211_ft_event(struct net_device *netdev, - struct cfg80211_ft_event_params *ft_event) -{ - struct wiphy *wiphy = netdev->ieee80211_ptr->wiphy; - struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); - struct sk_buff *msg; - void *hdr; - int err; - - trace_cfg80211_ft_event(wiphy, netdev, ft_event); - - if (!ft_event->target_ap) - return; - - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); - if (!msg) - return; - - hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FT_EVENT); - if (!hdr) { - nlmsg_free(msg); - return; - } - - nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); - nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); - nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, ft_event->target_ap); - if (ft_event->ies) - nla_put(msg, NL80211_ATTR_IE, ft_event->ies_len, ft_event->ies); - if (ft_event->ric_ies) - nla_put(msg, NL80211_ATTR_IE_RIC, ft_event->ric_ies_len, - ft_event->ric_ies); - - 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_KERNEL); -} -EXPORT_SYMBOL(cfg80211_ft_event); - /* initialisation/exit functions */ int nl80211_init(void) diff --git a/trunk/net/wireless/nl80211.h b/trunk/net/wireless/nl80211.h index a4073e808c13..b061da4919e1 100644 --- a/trunk/net/wireless/nl80211.h +++ b/trunk/net/wireless/nl80211.h @@ -29,6 +29,12 @@ void nl80211_send_deauth(struct cfg80211_registered_device *rdev, void nl80211_send_disassoc(struct cfg80211_registered_device *rdev, struct net_device *netdev, const u8 *buf, size_t len, gfp_t gfp); +void nl80211_send_unprot_deauth(struct cfg80211_registered_device *rdev, + struct net_device *netdev, + const u8 *buf, size_t len, gfp_t gfp); +void nl80211_send_unprot_disassoc(struct cfg80211_registered_device *rdev, + struct net_device *netdev, + const u8 *buf, size_t len, gfp_t gfp); void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev, struct net_device *netdev, const u8 *addr, gfp_t gfp); @@ -48,6 +54,10 @@ void nl80211_send_disconnected(struct cfg80211_registered_device *rdev, struct net_device *netdev, u16 reason, const u8 *ie, size_t ie_len, bool from_ap); +void nl80211_send_new_peer_candidate(struct cfg80211_registered_device *rdev, + struct net_device *netdev, + const u8 *macaddr, const u8* ie, u8 ie_len, + gfp_t gfp); void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev, struct net_device *netdev, const u8 *addr, @@ -63,10 +73,41 @@ void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev, struct net_device *netdev, const u8 *bssid, gfp_t gfp); +void nl80211_send_remain_on_channel(struct cfg80211_registered_device *rdev, + struct wireless_dev *wdev, u64 cookie, + struct ieee80211_channel *chan, + 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); + +void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, + struct net_device *dev, const u8 *mac_addr, + struct station_info *sinfo, gfp_t gfp); +void nl80211_send_sta_del_event(struct cfg80211_registered_device *rdev, + struct net_device *dev, const u8 *mac_addr, + gfp_t gfp); + +void nl80211_send_conn_failed_event(struct cfg80211_registered_device *rdev, + struct net_device *dev, const u8 *mac_addr, + enum nl80211_connect_failed_reason reason, + gfp_t gfp); + int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, struct wireless_dev *wdev, u32 nlpid, int freq, int sig_dbm, const u8 *buf, size_t len, gfp_t gfp); +void nl80211_send_mgmt_tx_status(struct cfg80211_registered_device *rdev, + struct wireless_dev *wdev, u64 cookie, + const u8 *buf, size_t len, bool ack, + gfp_t gfp); + +void +nl80211_send_cqm_rssi_notify(struct cfg80211_registered_device *rdev, + struct net_device *netdev, + enum nl80211_cqm_rssi_threshold_event rssi_event, + gfp_t gfp); void nl80211_radar_notify(struct cfg80211_registered_device *rdev, @@ -74,4 +115,31 @@ nl80211_radar_notify(struct cfg80211_registered_device *rdev, enum nl80211_radar_event event, struct net_device *netdev, gfp_t gfp); +void +nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev, + struct net_device *netdev, const u8 *peer, + u32 num_packets, gfp_t gfp); + +void +nl80211_send_cqm_txe_notify(struct cfg80211_registered_device *rdev, + struct net_device *netdev, const u8 *peer, + u32 num_packets, u32 rate, u32 intvl, gfp_t gfp); + +void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev, + struct net_device *netdev, const u8 *bssid, + const u8 *replay_ctr, gfp_t gfp); + +void nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev, + struct net_device *netdev, int index, + 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); + +bool nl80211_unexpected_frame(struct net_device *dev, + const u8 *addr, gfp_t gfp); +bool nl80211_unexpected_4addr_frame(struct net_device *dev, + const u8 *addr, gfp_t gfp); + #endif /* __NET_WIRELESS_NL80211_H */ diff --git a/trunk/net/wireless/rdev-ops.h b/trunk/net/wireless/rdev-ops.h index d77e1c1d3a0e..422d38291d66 100644 --- a/trunk/net/wireless/rdev-ops.h +++ b/trunk/net/wireless/rdev-ops.h @@ -6,12 +6,11 @@ #include "core.h" #include "trace.h" -static inline int rdev_suspend(struct cfg80211_registered_device *rdev, - struct cfg80211_wowlan *wowlan) +static inline int rdev_suspend(struct cfg80211_registered_device *rdev) { int ret; - trace_rdev_suspend(&rdev->wiphy, wowlan); - ret = rdev->ops->suspend(&rdev->wiphy, wowlan); + trace_rdev_suspend(&rdev->wiphy, rdev->wowlan); + ret = rdev->ops->suspend(&rdev->wiphy, rdev->wowlan); trace_rdev_return_int(&rdev->wiphy, ret); return ret; } @@ -888,17 +887,4 @@ static inline int rdev_set_mac_acl(struct cfg80211_registered_device *rdev, trace_rdev_return_int(&rdev->wiphy, ret); return ret; } - -static inline int rdev_update_ft_ies(struct cfg80211_registered_device *rdev, - struct net_device *dev, - struct cfg80211_update_ft_ies_params *ftie) -{ - int ret; - - trace_rdev_update_ft_ies(&rdev->wiphy, dev, ftie); - ret = rdev->ops->update_ft_ies(&rdev->wiphy, dev, ftie); - trace_rdev_return_int(&rdev->wiphy, ret); - return ret; -} - #endif /* __CFG80211_RDEV_OPS */ diff --git a/trunk/net/wireless/reg.c b/trunk/net/wireless/reg.c index e6df52dc8c69..98532c00242d 100644 --- a/trunk/net/wireless/reg.c +++ b/trunk/net/wireless/reg.c @@ -184,14 +184,14 @@ static const struct ieee80211_regdomain world_regdom = { NL80211_RRF_NO_IBSS | NL80211_RRF_NO_OFDM), /* IEEE 802.11a, channel 36..48 */ - REG_RULE(5180-10, 5240+10, 80, 6, 20, + REG_RULE(5180-10, 5240+10, 40, 6, 20, NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS), - /* NB: 5260 MHz - 5700 MHz requires DFS */ + /* NB: 5260 MHz - 5700 MHz requies DFS */ /* IEEE 802.11a, channel 149..165 */ - REG_RULE(5745-10, 5825+10, 80, 6, 20, + REG_RULE(5745-10, 5825+10, 40, 6, 20, NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS), diff --git a/trunk/net/wireless/sme.c b/trunk/net/wireless/sme.c index bad4c4b5e4eb..f432bd3755b1 100644 --- a/trunk/net/wireless/sme.c +++ b/trunk/net/wireless/sme.c @@ -159,7 +159,7 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev) { struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); struct cfg80211_connect_params *params; - struct cfg80211_assoc_request req = {}; + const u8 *prev_bssid = NULL; int err; ASSERT_WDEV_LOCK(wdev); @@ -186,20 +186,16 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev) BUG_ON(!rdev->ops->assoc); wdev->conn->state = CFG80211_CONN_ASSOCIATING; if (wdev->conn->prev_bssid_valid) - req.prev_bssid = wdev->conn->prev_bssid; - req.ie = params->ie; - req.ie_len = params->ie_len; - req.use_mfp = params->mfp != NL80211_MFP_NO; - req.crypto = params->crypto; - req.flags = params->flags; - req.ht_capa = params->ht_capa; - req.ht_capa_mask = params->ht_capa_mask; - req.vht_capa = params->vht_capa; - req.vht_capa_mask = params->vht_capa_mask; - - err = __cfg80211_mlme_assoc(rdev, wdev->netdev, params->channel, - params->bssid, params->ssid, - params->ssid_len, &req); + prev_bssid = wdev->conn->prev_bssid; + err = __cfg80211_mlme_assoc(rdev, wdev->netdev, + params->channel, params->bssid, + prev_bssid, + params->ssid, params->ssid_len, + params->ie, params->ie_len, + params->mfp != NL80211_MFP_NO, + ¶ms->crypto, + params->flags, ¶ms->ht_capa, + ¶ms->ht_capa_mask); if (err) __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, NULL, 0, diff --git a/trunk/net/wireless/sysfs.c b/trunk/net/wireless/sysfs.c index 8f28b9f798d8..238ee49b3868 100644 --- a/trunk/net/wireless/sysfs.c +++ b/trunk/net/wireless/sysfs.c @@ -83,14 +83,6 @@ static int wiphy_uevent(struct device *dev, struct kobj_uevent_env *env) return 0; } -static void cfg80211_leave_all(struct cfg80211_registered_device *rdev) -{ - struct wireless_dev *wdev; - - list_for_each_entry(wdev, &rdev->wdev_list, list) - cfg80211_leave(rdev, wdev); -} - static int wiphy_suspend(struct device *dev, pm_message_t state) { struct cfg80211_registered_device *rdev = dev_to_rdev(dev); @@ -98,19 +90,12 @@ static int wiphy_suspend(struct device *dev, pm_message_t state) rdev->suspend_at = get_seconds(); - rtnl_lock(); - if (rdev->wiphy.registered) { - if (!rdev->wowlan) - cfg80211_leave_all(rdev); - if (rdev->ops->suspend) - ret = rdev_suspend(rdev, rdev->wowlan); - if (ret == 1) { - /* Driver refuse to configure wowlan */ - cfg80211_leave_all(rdev); - ret = rdev_suspend(rdev, NULL); - } + if (rdev->ops->suspend) { + rtnl_lock(); + if (rdev->wiphy.registered) + ret = rdev_suspend(rdev); + rtnl_unlock(); } - rtnl_unlock(); return ret; } diff --git a/trunk/net/wireless/trace.h b/trunk/net/wireless/trace.h index ccadef2106ac..b7a531380e19 100644 --- a/trunk/net/wireless/trace.h +++ b/trunk/net/wireless/trace.h @@ -1785,26 +1785,6 @@ TRACE_EVENT(rdev_set_mac_acl, WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->acl_policy) ); -TRACE_EVENT(rdev_update_ft_ies, - TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, - struct cfg80211_update_ft_ies_params *ftie), - TP_ARGS(wiphy, netdev, ftie), - TP_STRUCT__entry( - WIPHY_ENTRY - NETDEV_ENTRY - __field(u16, md) - __dynamic_array(u8, ie, ftie->ie_len) - ), - TP_fast_assign( - WIPHY_ASSIGN; - NETDEV_ASSIGN; - __entry->md = ftie->md; - memcpy(__get_dynamic_array(ie), ftie->ie, ftie->ie_len); - ), - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", md: 0x%x", - WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->md) -); - /************************************************************* * cfg80211 exported functions traces * *************************************************************/ @@ -2433,32 +2413,6 @@ TRACE_EVENT(cfg80211_report_wowlan_wakeup, TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT, WIPHY_PR_ARG, WDEV_PR_ARG) ); -TRACE_EVENT(cfg80211_ft_event, - TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, - struct cfg80211_ft_event_params *ft_event), - TP_ARGS(wiphy, netdev, ft_event), - TP_STRUCT__entry( - WIPHY_ENTRY - NETDEV_ENTRY - __dynamic_array(u8, ies, ft_event->ies_len) - MAC_ENTRY(target_ap) - __dynamic_array(u8, ric_ies, ft_event->ric_ies_len) - ), - TP_fast_assign( - WIPHY_ASSIGN; - NETDEV_ASSIGN; - if (ft_event->ies) - memcpy(__get_dynamic_array(ies), ft_event->ies, - ft_event->ies_len); - MAC_ASSIGN(target_ap, ft_event->target_ap); - if (ft_event->ric_ies) - memcpy(__get_dynamic_array(ric_ies), ft_event->ric_ies, - ft_event->ric_ies_len); - ), - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", target_ap: " MAC_PR_FMT, - WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(target_ap)) -); - #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */ #undef TRACE_INCLUDE_PATH