diff options
author | John W. Linville <linville@tuxdriver.com> | 2013-03-20 15:24:57 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-03-20 15:24:57 -0400 |
commit | 5470b462c3f0c6fa980c320968a165bd0f34ca8d (patch) | |
tree | eb20de947bec8133d27f97f7af8ae4cf35def663 | |
parent | 4c1d8d0617a39c8325a7c2fd80ac14bf40fd8cc6 (diff) | |
parent | 0d4e67174b03e3dcfe75ce7ec488770a5d443bf4 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
263 files changed, 9520 insertions, 3400 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index fb89be1281c6..86c084321387 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -8500,7 +8500,7 @@ F: drivers/usb/gadget/*uvc*.c | |||
8500 | F: drivers/usb/gadget/webcam.c | 8500 | F: drivers/usb/gadget/webcam.c |
8501 | 8501 | ||
8502 | USB WIRELESS RNDIS DRIVER (rndis_wlan) | 8502 | USB WIRELESS RNDIS DRIVER (rndis_wlan) |
8503 | M: Jussi Kivilinna <jussi.kivilinna@mbnet.fi> | 8503 | M: Jussi Kivilinna <jussi.kivilinna@iki.fi> |
8504 | L: linux-wireless@vger.kernel.org | 8504 | L: linux-wireless@vger.kernel.org |
8505 | S: Maintained | 8505 | S: Maintained |
8506 | F: drivers/net/wireless/rndis_wlan.c | 8506 | F: drivers/net/wireless/rndis_wlan.c |
diff --git a/drivers/bcma/core.c b/drivers/bcma/core.c index 03bbe104338f..17b26ce7e051 100644 --- a/drivers/bcma/core.c +++ b/drivers/bcma/core.c | |||
@@ -104,7 +104,13 @@ void bcma_core_pll_ctl(struct bcma_device *core, u32 req, u32 status, bool on) | |||
104 | if (i) | 104 | if (i) |
105 | bcma_err(core->bus, "PLL enable timeout\n"); | 105 | bcma_err(core->bus, "PLL enable timeout\n"); |
106 | } else { | 106 | } else { |
107 | bcma_warn(core->bus, "Disabling PLL not supported yet!\n"); | 107 | /* |
108 | * Mask the PLL but don't wait for it to be disabled. PLL may be | ||
109 | * shared between cores and will be still up if there is another | ||
110 | * core using it. | ||
111 | */ | ||
112 | bcma_mask32(core, BCMA_CLKCTLST, ~req); | ||
113 | bcma_read32(core, BCMA_CLKCTLST); | ||
108 | } | 114 | } |
109 | } | 115 | } |
110 | EXPORT_SYMBOL_GPL(bcma_core_pll_ctl); | 116 | EXPORT_SYMBOL_GPL(bcma_core_pll_ctl); |
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index 9a6188add590..f72f52b4b1dd 100644 --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c | |||
@@ -120,6 +120,11 @@ static int bcma_register_cores(struct bcma_bus *bus) | |||
120 | continue; | 120 | continue; |
121 | } | 121 | } |
122 | 122 | ||
123 | /* Only first GMAC core on BCM4706 is connected and working */ | ||
124 | if (core->id.id == BCMA_CORE_4706_MAC_GBIT && | ||
125 | core->core_unit > 0) | ||
126 | continue; | ||
127 | |||
123 | core->dev.release = bcma_release_core_dev; | 128 | core->dev.release = bcma_release_core_dev; |
124 | core->dev.bus = &bcma_bus_type; | 129 | core->dev.bus = &bcma_bus_type; |
125 | dev_set_name(&core->dev, "bcma%d:%d", bus->num, dev_id); | 130 | dev_set_name(&core->dev, "bcma%d:%d", bus->num, dev_id); |
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 3150def17193..2d691b8b95b9 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h | |||
@@ -1523,7 +1523,8 @@ int ath5k_hw_dma_stop(struct ath5k_hw *ah); | |||
1523 | /* EEPROM access functions */ | 1523 | /* EEPROM access functions */ |
1524 | int ath5k_eeprom_init(struct ath5k_hw *ah); | 1524 | int ath5k_eeprom_init(struct ath5k_hw *ah); |
1525 | void ath5k_eeprom_detach(struct ath5k_hw *ah); | 1525 | void ath5k_eeprom_detach(struct ath5k_hw *ah); |
1526 | 1526 | int ath5k_eeprom_mode_from_channel(struct ath5k_hw *ah, | |
1527 | struct ieee80211_channel *channel); | ||
1527 | 1528 | ||
1528 | /* Protocol Control Unit Functions */ | 1529 | /* Protocol Control Unit Functions */ |
1529 | /* Helpers */ | 1530 | /* Helpers */ |
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index b7e0258887e7..94d34ee02265 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c | |||
@@ -1779,7 +1779,8 @@ ath5k_eeprom_detach(struct ath5k_hw *ah) | |||
1779 | } | 1779 | } |
1780 | 1780 | ||
1781 | int | 1781 | int |
1782 | ath5k_eeprom_mode_from_channel(struct ieee80211_channel *channel) | 1782 | ath5k_eeprom_mode_from_channel(struct ath5k_hw *ah, |
1783 | struct ieee80211_channel *channel) | ||
1783 | { | 1784 | { |
1784 | switch (channel->hw_value) { | 1785 | switch (channel->hw_value) { |
1785 | case AR5K_MODE_11A: | 1786 | case AR5K_MODE_11A: |
@@ -1789,6 +1790,7 @@ ath5k_eeprom_mode_from_channel(struct ieee80211_channel *channel) | |||
1789 | case AR5K_MODE_11B: | 1790 | case AR5K_MODE_11B: |
1790 | return AR5K_EEPROM_MODE_11B; | 1791 | return AR5K_EEPROM_MODE_11B; |
1791 | default: | 1792 | default: |
1792 | return -1; | 1793 | ATH5K_WARN(ah, "channel is not A/B/G!"); |
1794 | return AR5K_EEPROM_MODE_11A; | ||
1793 | } | 1795 | } |
1794 | } | 1796 | } |
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.h b/drivers/net/wireless/ath/ath5k/eeprom.h index 94a9bbea6874..693296ee9693 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.h +++ b/drivers/net/wireless/ath/ath5k/eeprom.h | |||
@@ -493,6 +493,3 @@ struct ath5k_eeprom_info { | |||
493 | /* Antenna raw switch tables */ | 493 | /* Antenna raw switch tables */ |
494 | u32 ee_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; | 494 | u32 ee_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; |
495 | }; | 495 | }; |
496 | |||
497 | int | ||
498 | ath5k_eeprom_mode_from_channel(struct ieee80211_channel *channel); | ||
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index a78afa98c650..d6bc7cb61bfb 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c | |||
@@ -1612,11 +1612,7 @@ ath5k_hw_update_noise_floor(struct ath5k_hw *ah) | |||
1612 | 1612 | ||
1613 | ah->ah_cal_mask |= AR5K_CALIBRATION_NF; | 1613 | ah->ah_cal_mask |= AR5K_CALIBRATION_NF; |
1614 | 1614 | ||
1615 | ee_mode = ath5k_eeprom_mode_from_channel(ah->ah_current_channel); | 1615 | ee_mode = ath5k_eeprom_mode_from_channel(ah, ah->ah_current_channel); |
1616 | if (WARN_ON(ee_mode < 0)) { | ||
1617 | ah->ah_cal_mask &= ~AR5K_CALIBRATION_NF; | ||
1618 | return; | ||
1619 | } | ||
1620 | 1616 | ||
1621 | /* completed NF calibration, test threshold */ | 1617 | /* completed NF calibration, test threshold */ |
1622 | nf = ath5k_hw_read_measured_noise_floor(ah); | 1618 | nf = ath5k_hw_read_measured_noise_floor(ah); |
@@ -2317,12 +2313,7 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) | |||
2317 | 2313 | ||
2318 | def_ant = ah->ah_def_ant; | 2314 | def_ant = ah->ah_def_ant; |
2319 | 2315 | ||
2320 | ee_mode = ath5k_eeprom_mode_from_channel(channel); | 2316 | ee_mode = ath5k_eeprom_mode_from_channel(ah, channel); |
2321 | if (ee_mode < 0) { | ||
2322 | ATH5K_ERR(ah, | ||
2323 | "invalid channel: %d\n", channel->center_freq); | ||
2324 | return; | ||
2325 | } | ||
2326 | 2317 | ||
2327 | switch (ant_mode) { | 2318 | switch (ant_mode) { |
2328 | case AR5K_ANTMODE_DEFAULT: | 2319 | case AR5K_ANTMODE_DEFAULT: |
@@ -3622,12 +3613,7 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
3622 | return -EINVAL; | 3613 | return -EINVAL; |
3623 | } | 3614 | } |
3624 | 3615 | ||
3625 | ee_mode = ath5k_eeprom_mode_from_channel(channel); | 3616 | ee_mode = ath5k_eeprom_mode_from_channel(ah, channel); |
3626 | if (ee_mode < 0) { | ||
3627 | ATH5K_ERR(ah, | ||
3628 | "invalid channel: %d\n", channel->center_freq); | ||
3629 | return -EINVAL; | ||
3630 | } | ||
3631 | 3617 | ||
3632 | /* Initialize TX power table */ | 3618 | /* Initialize TX power table */ |
3633 | switch (ah->ah_radio) { | 3619 | switch (ah->ah_radio) { |
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index e2d8b2cf19eb..a3399c4f13a9 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c | |||
@@ -984,9 +984,7 @@ ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, | |||
984 | if (ah->ah_version == AR5K_AR5210) | 984 | if (ah->ah_version == AR5K_AR5210) |
985 | return; | 985 | return; |
986 | 986 | ||
987 | ee_mode = ath5k_eeprom_mode_from_channel(channel); | 987 | ee_mode = ath5k_eeprom_mode_from_channel(ah, channel); |
988 | if (WARN_ON(ee_mode < 0)) | ||
989 | return; | ||
990 | 988 | ||
991 | /* Adjust power delta for channel 14 */ | 989 | /* Adjust power delta for channel 14 */ |
992 | if (channel->center_freq == 2484) | 990 | if (channel->center_freq == 2484) |
diff --git a/drivers/net/wireless/ath/ath6kl/Kconfig b/drivers/net/wireless/ath/ath6kl/Kconfig index 630c83db056e..e39e5860a2e9 100644 --- a/drivers/net/wireless/ath/ath6kl/Kconfig +++ b/drivers/net/wireless/ath/ath6kl/Kconfig | |||
@@ -30,6 +30,15 @@ config ATH6KL_DEBUG | |||
30 | ---help--- | 30 | ---help--- |
31 | Enables debug support | 31 | Enables debug support |
32 | 32 | ||
33 | config ATH6KL_TRACING | ||
34 | bool "Atheros ath6kl tracing support" | ||
35 | depends on ATH6KL | ||
36 | depends on EVENT_TRACING | ||
37 | ---help--- | ||
38 | Select this to ath6kl use tracing infrastructure. | ||
39 | |||
40 | If unsure, say Y to make it easier to debug problems. | ||
41 | |||
33 | config ATH6KL_REGDOMAIN | 42 | config ATH6KL_REGDOMAIN |
34 | bool "Atheros ath6kl regdomain support" | 43 | bool "Atheros ath6kl regdomain support" |
35 | depends on ATH6KL | 44 | depends on ATH6KL |
diff --git a/drivers/net/wireless/ath/ath6kl/Makefile b/drivers/net/wireless/ath/ath6kl/Makefile index cab0ec0d5380..dc2b3b46781e 100644 --- a/drivers/net/wireless/ath/ath6kl/Makefile +++ b/drivers/net/wireless/ath/ath6kl/Makefile | |||
@@ -35,10 +35,15 @@ ath6kl_core-y += txrx.o | |||
35 | ath6kl_core-y += wmi.o | 35 | ath6kl_core-y += wmi.o |
36 | ath6kl_core-y += core.o | 36 | ath6kl_core-y += core.o |
37 | ath6kl_core-y += recovery.o | 37 | ath6kl_core-y += recovery.o |
38 | |||
38 | ath6kl_core-$(CONFIG_NL80211_TESTMODE) += testmode.o | 39 | ath6kl_core-$(CONFIG_NL80211_TESTMODE) += testmode.o |
40 | ath6kl_core-$(CONFIG_ATH6KL_TRACING) += trace.o | ||
39 | 41 | ||
40 | obj-$(CONFIG_ATH6KL_SDIO) += ath6kl_sdio.o | 42 | obj-$(CONFIG_ATH6KL_SDIO) += ath6kl_sdio.o |
41 | ath6kl_sdio-y += sdio.o | 43 | ath6kl_sdio-y += sdio.o |
42 | 44 | ||
43 | obj-$(CONFIG_ATH6KL_USB) += ath6kl_usb.o | 45 | obj-$(CONFIG_ATH6KL_USB) += ath6kl_usb.o |
44 | ath6kl_usb-y += usb.o | 46 | ath6kl_usb-y += usb.o |
47 | |||
48 | # for tracing framework to find trace.h | ||
49 | CFLAGS_trace.o := -I$(src) | ||
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 752ffc4f4166..5c9736a94e54 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c | |||
@@ -402,7 +402,7 @@ static bool ath6kl_is_valid_iftype(struct ath6kl *ar, enum nl80211_iftype type, | |||
402 | if (type == NL80211_IFTYPE_STATION || | 402 | if (type == NL80211_IFTYPE_STATION || |
403 | type == NL80211_IFTYPE_AP || type == NL80211_IFTYPE_ADHOC) { | 403 | type == NL80211_IFTYPE_AP || type == NL80211_IFTYPE_ADHOC) { |
404 | for (i = 0; i < ar->vif_max; i++) { | 404 | for (i = 0; i < ar->vif_max; i++) { |
405 | if ((ar->avail_idx_map >> i) & BIT(0)) { | 405 | if ((ar->avail_idx_map) & BIT(i)) { |
406 | *if_idx = i; | 406 | *if_idx = i; |
407 | return true; | 407 | return true; |
408 | } | 408 | } |
@@ -412,7 +412,7 @@ static bool ath6kl_is_valid_iftype(struct ath6kl *ar, enum nl80211_iftype type, | |||
412 | if (type == NL80211_IFTYPE_P2P_CLIENT || | 412 | if (type == NL80211_IFTYPE_P2P_CLIENT || |
413 | type == NL80211_IFTYPE_P2P_GO) { | 413 | type == NL80211_IFTYPE_P2P_GO) { |
414 | for (i = ar->max_norm_iface; i < ar->vif_max; i++) { | 414 | for (i = ar->max_norm_iface; i < ar->vif_max; i++) { |
415 | if ((ar->avail_idx_map >> i) & BIT(0)) { | 415 | if ((ar->avail_idx_map) & BIT(i)) { |
416 | *if_idx = i; | 416 | *if_idx = i; |
417 | return true; | 417 | return true; |
418 | } | 418 | } |
@@ -1535,7 +1535,9 @@ static int ath6kl_cfg80211_del_iface(struct wiphy *wiphy, | |||
1535 | 1535 | ||
1536 | ath6kl_cfg80211_vif_stop(vif, test_bit(WMI_READY, &ar->flag)); | 1536 | ath6kl_cfg80211_vif_stop(vif, test_bit(WMI_READY, &ar->flag)); |
1537 | 1537 | ||
1538 | rtnl_lock(); | ||
1538 | ath6kl_cfg80211_vif_cleanup(vif); | 1539 | ath6kl_cfg80211_vif_cleanup(vif); |
1540 | rtnl_unlock(); | ||
1539 | 1541 | ||
1540 | return 0; | 1542 | return 0; |
1541 | } | 1543 | } |
@@ -2990,13 +2992,15 @@ static int ath6kl_change_station(struct wiphy *wiphy, struct net_device *dev, | |||
2990 | { | 2992 | { |
2991 | struct ath6kl *ar = ath6kl_priv(dev); | 2993 | struct ath6kl *ar = ath6kl_priv(dev); |
2992 | struct ath6kl_vif *vif = netdev_priv(dev); | 2994 | struct ath6kl_vif *vif = netdev_priv(dev); |
2995 | int err; | ||
2993 | 2996 | ||
2994 | if (vif->nw_type != AP_NETWORK) | 2997 | if (vif->nw_type != AP_NETWORK) |
2995 | return -EOPNOTSUPP; | 2998 | return -EOPNOTSUPP; |
2996 | 2999 | ||
2997 | /* Use this only for authorizing/unauthorizing a station */ | 3000 | err = cfg80211_check_station_change(wiphy, params, |
2998 | if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED))) | 3001 | CFG80211_STA_AP_MLME_CLIENT); |
2999 | return -EOPNOTSUPP; | 3002 | if (err) |
3003 | return err; | ||
3000 | 3004 | ||
3001 | if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) | 3005 | if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) |
3002 | return ath6kl_wmi_ap_set_mlme(ar->wmi, vif->fw_vif_idx, | 3006 | return ath6kl_wmi_ap_set_mlme(ar->wmi, vif->fw_vif_idx, |
@@ -3659,7 +3663,6 @@ struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, const char *name, | |||
3659 | vif->sme_state = SME_DISCONNECTED; | 3663 | vif->sme_state = SME_DISCONNECTED; |
3660 | set_bit(WLAN_ENABLED, &vif->flags); | 3664 | set_bit(WLAN_ENABLED, &vif->flags); |
3661 | ar->wlan_pwr_state = WLAN_POWER_STATE_ON; | 3665 | ar->wlan_pwr_state = WLAN_POWER_STATE_ON; |
3662 | set_bit(NETDEV_REGISTERED, &vif->flags); | ||
3663 | 3666 | ||
3664 | if (type == NL80211_IFTYPE_ADHOC) | 3667 | if (type == NL80211_IFTYPE_ADHOC) |
3665 | ar->ibss_if_active = true; | 3668 | ar->ibss_if_active = true; |
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index 61b2f98b4e77..26b0f92424e1 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h | |||
@@ -560,7 +560,6 @@ enum ath6kl_vif_state { | |||
560 | WMM_ENABLED, | 560 | WMM_ENABLED, |
561 | NETQ_STOPPED, | 561 | NETQ_STOPPED, |
562 | DTIM_EXPIRED, | 562 | DTIM_EXPIRED, |
563 | NETDEV_REGISTERED, | ||
564 | CLEAR_BSSFILTER_ON_BEACON, | 563 | CLEAR_BSSFILTER_ON_BEACON, |
565 | DTIM_PERIOD_AVAIL, | 564 | DTIM_PERIOD_AVAIL, |
566 | WLAN_ENABLED, | 565 | WLAN_ENABLED, |
@@ -936,8 +935,6 @@ void aggr_recv_addba_req_evt(struct ath6kl_vif *vif, u8 tid, u16 seq_no, | |||
936 | u8 win_sz); | 935 | u8 win_sz); |
937 | void ath6kl_wakeup_event(void *dev); | 936 | void ath6kl_wakeup_event(void *dev); |
938 | 937 | ||
939 | void ath6kl_reset_device(struct ath6kl *ar, u32 target_type, | ||
940 | bool wait_fot_compltn, bool cold_reset); | ||
941 | void ath6kl_init_control_info(struct ath6kl_vif *vif); | 938 | void ath6kl_init_control_info(struct ath6kl_vif *vif); |
942 | struct ath6kl_vif *ath6kl_vif_first(struct ath6kl *ar); | 939 | struct ath6kl_vif *ath6kl_vif_first(struct ath6kl *ar); |
943 | void ath6kl_cfg80211_vif_stop(struct ath6kl_vif *vif, bool wmi_ready); | 940 | void ath6kl_cfg80211_vif_stop(struct ath6kl_vif *vif, bool wmi_ready); |
diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c index 15cfe30e54fd..fe38b836cb26 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.c +++ b/drivers/net/wireless/ath/ath6kl/debug.c | |||
@@ -56,6 +56,60 @@ int ath6kl_printk(const char *level, const char *fmt, ...) | |||
56 | } | 56 | } |
57 | EXPORT_SYMBOL(ath6kl_printk); | 57 | EXPORT_SYMBOL(ath6kl_printk); |
58 | 58 | ||
59 | int ath6kl_info(const char *fmt, ...) | ||
60 | { | ||
61 | struct va_format vaf = { | ||
62 | .fmt = fmt, | ||
63 | }; | ||
64 | va_list args; | ||
65 | int ret; | ||
66 | |||
67 | va_start(args, fmt); | ||
68 | vaf.va = &args; | ||
69 | ret = ath6kl_printk(KERN_INFO, "%pV", &vaf); | ||
70 | trace_ath6kl_log_info(&vaf); | ||
71 | va_end(args); | ||
72 | |||
73 | return ret; | ||
74 | } | ||
75 | EXPORT_SYMBOL(ath6kl_info); | ||
76 | |||
77 | int ath6kl_err(const char *fmt, ...) | ||
78 | { | ||
79 | struct va_format vaf = { | ||
80 | .fmt = fmt, | ||
81 | }; | ||
82 | va_list args; | ||
83 | int ret; | ||
84 | |||
85 | va_start(args, fmt); | ||
86 | vaf.va = &args; | ||
87 | ret = ath6kl_printk(KERN_ERR, "%pV", &vaf); | ||
88 | trace_ath6kl_log_err(&vaf); | ||
89 | va_end(args); | ||
90 | |||
91 | return ret; | ||
92 | } | ||
93 | EXPORT_SYMBOL(ath6kl_err); | ||
94 | |||
95 | int ath6kl_warn(const char *fmt, ...) | ||
96 | { | ||
97 | struct va_format vaf = { | ||
98 | .fmt = fmt, | ||
99 | }; | ||
100 | va_list args; | ||
101 | int ret; | ||
102 | |||
103 | va_start(args, fmt); | ||
104 | vaf.va = &args; | ||
105 | ret = ath6kl_printk(KERN_WARNING, "%pV", &vaf); | ||
106 | trace_ath6kl_log_warn(&vaf); | ||
107 | va_end(args); | ||
108 | |||
109 | return ret; | ||
110 | } | ||
111 | EXPORT_SYMBOL(ath6kl_warn); | ||
112 | |||
59 | #ifdef CONFIG_ATH6KL_DEBUG | 113 | #ifdef CONFIG_ATH6KL_DEBUG |
60 | 114 | ||
61 | void ath6kl_dbg(enum ATH6K_DEBUG_MASK mask, const char *fmt, ...) | 115 | void ath6kl_dbg(enum ATH6K_DEBUG_MASK mask, const char *fmt, ...) |
@@ -63,15 +117,15 @@ void ath6kl_dbg(enum ATH6K_DEBUG_MASK mask, const char *fmt, ...) | |||
63 | struct va_format vaf; | 117 | struct va_format vaf; |
64 | va_list args; | 118 | va_list args; |
65 | 119 | ||
66 | if (!(debug_mask & mask)) | ||
67 | return; | ||
68 | |||
69 | va_start(args, fmt); | 120 | va_start(args, fmt); |
70 | 121 | ||
71 | vaf.fmt = fmt; | 122 | vaf.fmt = fmt; |
72 | vaf.va = &args; | 123 | vaf.va = &args; |
73 | 124 | ||
74 | ath6kl_printk(KERN_DEBUG, "%pV", &vaf); | 125 | if (debug_mask & mask) |
126 | ath6kl_printk(KERN_DEBUG, "%pV", &vaf); | ||
127 | |||
128 | trace_ath6kl_log_dbg(mask, &vaf); | ||
75 | 129 | ||
76 | va_end(args); | 130 | va_end(args); |
77 | } | 131 | } |
@@ -87,6 +141,10 @@ void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask, | |||
87 | 141 | ||
88 | print_hex_dump_bytes(prefix, DUMP_PREFIX_OFFSET, buf, len); | 142 | print_hex_dump_bytes(prefix, DUMP_PREFIX_OFFSET, buf, len); |
89 | } | 143 | } |
144 | |||
145 | /* tracing code doesn't like null strings :/ */ | ||
146 | trace_ath6kl_log_dbg_dump(msg ? msg : "", prefix ? prefix : "", | ||
147 | buf, len); | ||
90 | } | 148 | } |
91 | EXPORT_SYMBOL(ath6kl_dbg_dump); | 149 | EXPORT_SYMBOL(ath6kl_dbg_dump); |
92 | 150 | ||
@@ -1752,8 +1810,10 @@ int ath6kl_debug_init_fs(struct ath6kl *ar) | |||
1752 | debugfs_create_file("tgt_stats", S_IRUSR, ar->debugfs_phy, ar, | 1810 | debugfs_create_file("tgt_stats", S_IRUSR, ar->debugfs_phy, ar, |
1753 | &fops_tgt_stats); | 1811 | &fops_tgt_stats); |
1754 | 1812 | ||
1755 | debugfs_create_file("credit_dist_stats", S_IRUSR, ar->debugfs_phy, ar, | 1813 | if (ar->hif_type == ATH6KL_HIF_TYPE_SDIO) |
1756 | &fops_credit_dist_stats); | 1814 | debugfs_create_file("credit_dist_stats", S_IRUSR, |
1815 | ar->debugfs_phy, ar, | ||
1816 | &fops_credit_dist_stats); | ||
1757 | 1817 | ||
1758 | debugfs_create_file("endpoint_stats", S_IRUSR | S_IWUSR, | 1818 | debugfs_create_file("endpoint_stats", S_IRUSR | S_IWUSR, |
1759 | ar->debugfs_phy, ar, &fops_endpoint_stats); | 1819 | ar->debugfs_phy, ar, &fops_endpoint_stats); |
diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h index f97cd4ead543..74369de00fb5 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.h +++ b/drivers/net/wireless/ath/ath6kl/debug.h | |||
@@ -19,6 +19,7 @@ | |||
19 | #define DEBUG_H | 19 | #define DEBUG_H |
20 | 20 | ||
21 | #include "hif.h" | 21 | #include "hif.h" |
22 | #include "trace.h" | ||
22 | 23 | ||
23 | enum ATH6K_DEBUG_MASK { | 24 | enum ATH6K_DEBUG_MASK { |
24 | ATH6KL_DBG_CREDIT = BIT(0), | 25 | ATH6KL_DBG_CREDIT = BIT(0), |
@@ -51,13 +52,9 @@ enum ATH6K_DEBUG_MASK { | |||
51 | extern unsigned int debug_mask; | 52 | extern unsigned int debug_mask; |
52 | extern __printf(2, 3) | 53 | extern __printf(2, 3) |
53 | int ath6kl_printk(const char *level, const char *fmt, ...); | 54 | int ath6kl_printk(const char *level, const char *fmt, ...); |
54 | 55 | extern __printf(1, 2) int ath6kl_info(const char *fmt, ...); | |
55 | #define ath6kl_info(fmt, ...) \ | 56 | extern __printf(1, 2) int ath6kl_err(const char *fmt, ...); |
56 | ath6kl_printk(KERN_INFO, fmt, ##__VA_ARGS__) | 57 | extern __printf(1, 2) int ath6kl_warn(const char *fmt, ...); |
57 | #define ath6kl_err(fmt, ...) \ | ||
58 | ath6kl_printk(KERN_ERR, fmt, ##__VA_ARGS__) | ||
59 | #define ath6kl_warn(fmt, ...) \ | ||
60 | ath6kl_printk(KERN_WARNING, fmt, ##__VA_ARGS__) | ||
61 | 58 | ||
62 | enum ath6kl_war { | 59 | enum ath6kl_war { |
63 | ATH6KL_WAR_INVALID_RATE, | 60 | ATH6KL_WAR_INVALID_RATE, |
diff --git a/drivers/net/wireless/ath/ath6kl/hif.c b/drivers/net/wireless/ath/ath6kl/hif.c index a6b614421fa4..fea7709b5dda 100644 --- a/drivers/net/wireless/ath/ath6kl/hif.c +++ b/drivers/net/wireless/ath/ath6kl/hif.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include "target.h" | 22 | #include "target.h" |
23 | #include "hif-ops.h" | 23 | #include "hif-ops.h" |
24 | #include "debug.h" | 24 | #include "debug.h" |
25 | #include "trace.h" | ||
25 | 26 | ||
26 | #define MAILBOX_FOR_BLOCK_SIZE 1 | 27 | #define MAILBOX_FOR_BLOCK_SIZE 1 |
27 | 28 | ||
@@ -436,6 +437,8 @@ static int proc_pending_irqs(struct ath6kl_device *dev, bool *done) | |||
436 | 437 | ||
437 | ath6kl_dump_registers(dev, &dev->irq_proc_reg, | 438 | ath6kl_dump_registers(dev, &dev->irq_proc_reg, |
438 | &dev->irq_en_reg); | 439 | &dev->irq_en_reg); |
440 | trace_ath6kl_sdio_irq(&dev->irq_en_reg, | ||
441 | sizeof(dev->irq_en_reg)); | ||
439 | 442 | ||
440 | /* Update only those registers that are enabled */ | 443 | /* Update only those registers that are enabled */ |
441 | host_int_status = dev->irq_proc_reg.host_int_status & | 444 | host_int_status = dev->irq_proc_reg.host_int_status & |
diff --git a/drivers/net/wireless/ath/ath6kl/htc_mbox.c b/drivers/net/wireless/ath/ath6kl/htc_mbox.c index fbb78dfe078f..65e5b719093d 100644 --- a/drivers/net/wireless/ath/ath6kl/htc_mbox.c +++ b/drivers/net/wireless/ath/ath6kl/htc_mbox.c | |||
@@ -19,6 +19,8 @@ | |||
19 | #include "hif.h" | 19 | #include "hif.h" |
20 | #include "debug.h" | 20 | #include "debug.h" |
21 | #include "hif-ops.h" | 21 | #include "hif-ops.h" |
22 | #include "trace.h" | ||
23 | |||
22 | #include <asm/unaligned.h> | 24 | #include <asm/unaligned.h> |
23 | 25 | ||
24 | #define CALC_TXRX_PADDED_LEN(dev, len) (__ALIGN_MASK((len), (dev)->block_mask)) | 26 | #define CALC_TXRX_PADDED_LEN(dev, len) (__ALIGN_MASK((len), (dev)->block_mask)) |
@@ -537,6 +539,8 @@ static int ath6kl_htc_tx_issue(struct htc_target *target, | |||
537 | packet->buf, padded_len, | 539 | packet->buf, padded_len, |
538 | HIF_WR_ASYNC_BLOCK_INC, packet); | 540 | HIF_WR_ASYNC_BLOCK_INC, packet); |
539 | 541 | ||
542 | trace_ath6kl_htc_tx(status, packet->endpoint, packet->buf, send_len); | ||
543 | |||
540 | return status; | 544 | return status; |
541 | } | 545 | } |
542 | 546 | ||
@@ -757,7 +761,8 @@ static void ath6kl_htc_tx_bundle(struct htc_endpoint *endpoint, | |||
757 | { | 761 | { |
758 | struct htc_target *target = endpoint->target; | 762 | struct htc_target *target = endpoint->target; |
759 | struct hif_scatter_req *scat_req = NULL; | 763 | struct hif_scatter_req *scat_req = NULL; |
760 | int n_scat, n_sent_bundle = 0, tot_pkts_bundle = 0; | 764 | int n_scat, n_sent_bundle = 0, tot_pkts_bundle = 0, i; |
765 | struct htc_packet *packet; | ||
761 | int status; | 766 | int status; |
762 | u32 txb_mask; | 767 | u32 txb_mask; |
763 | u8 ac = WMM_NUM_AC; | 768 | u8 ac = WMM_NUM_AC; |
@@ -832,6 +837,13 @@ static void ath6kl_htc_tx_bundle(struct htc_endpoint *endpoint, | |||
832 | ath6kl_dbg(ATH6KL_DBG_HTC, | 837 | ath6kl_dbg(ATH6KL_DBG_HTC, |
833 | "htc tx scatter bytes %d entries %d\n", | 838 | "htc tx scatter bytes %d entries %d\n", |
834 | scat_req->len, scat_req->scat_entries); | 839 | scat_req->len, scat_req->scat_entries); |
840 | |||
841 | for (i = 0; i < scat_req->scat_entries; i++) { | ||
842 | packet = scat_req->scat_list[i].packet; | ||
843 | trace_ath6kl_htc_tx(packet->status, packet->endpoint, | ||
844 | packet->buf, packet->act_len); | ||
845 | } | ||
846 | |||
835 | ath6kl_hif_submit_scat_req(target->dev, scat_req, false); | 847 | ath6kl_hif_submit_scat_req(target->dev, scat_req, false); |
836 | 848 | ||
837 | if (status) | 849 | if (status) |
@@ -1903,6 +1915,7 @@ static void ath6kl_htc_rx_complete(struct htc_endpoint *endpoint, | |||
1903 | ath6kl_dbg(ATH6KL_DBG_HTC, | 1915 | ath6kl_dbg(ATH6KL_DBG_HTC, |
1904 | "htc rx complete ep %d packet 0x%p\n", | 1916 | "htc rx complete ep %d packet 0x%p\n", |
1905 | endpoint->eid, packet); | 1917 | endpoint->eid, packet); |
1918 | |||
1906 | endpoint->ep_cb.rx(endpoint->target, packet); | 1919 | endpoint->ep_cb.rx(endpoint->target, packet); |
1907 | } | 1920 | } |
1908 | 1921 | ||
@@ -2011,6 +2024,9 @@ static int ath6kl_htc_rx_process_packets(struct htc_target *target, | |||
2011 | list_for_each_entry_safe(packet, tmp_pkt, comp_pktq, list) { | 2024 | list_for_each_entry_safe(packet, tmp_pkt, comp_pktq, list) { |
2012 | ep = &target->endpoint[packet->endpoint]; | 2025 | ep = &target->endpoint[packet->endpoint]; |
2013 | 2026 | ||
2027 | trace_ath6kl_htc_rx(packet->status, packet->endpoint, | ||
2028 | packet->buf, packet->act_len); | ||
2029 | |||
2014 | /* process header for each of the recv packet */ | 2030 | /* process header for each of the recv packet */ |
2015 | status = ath6kl_htc_rx_process_hdr(target, packet, lk_ahds, | 2031 | status = ath6kl_htc_rx_process_hdr(target, packet, lk_ahds, |
2016 | n_lk_ahd); | 2032 | n_lk_ahd); |
@@ -2291,6 +2307,9 @@ static struct htc_packet *htc_wait_for_ctrl_msg(struct htc_target *target) | |||
2291 | if (ath6kl_htc_rx_packet(target, packet, packet->act_len)) | 2307 | if (ath6kl_htc_rx_packet(target, packet, packet->act_len)) |
2292 | goto fail_ctrl_rx; | 2308 | goto fail_ctrl_rx; |
2293 | 2309 | ||
2310 | trace_ath6kl_htc_rx(packet->status, packet->endpoint, | ||
2311 | packet->buf, packet->act_len); | ||
2312 | |||
2294 | /* process receive header */ | 2313 | /* process receive header */ |
2295 | packet->status = ath6kl_htc_rx_process_hdr(target, packet, NULL, NULL); | 2314 | packet->status = ath6kl_htc_rx_process_hdr(target, packet, NULL, NULL); |
2296 | 2315 | ||
diff --git a/drivers/net/wireless/ath/ath6kl/htc_pipe.c b/drivers/net/wireless/ath/ath6kl/htc_pipe.c index 281390178e3d..67aa924ed8b3 100644 --- a/drivers/net/wireless/ath/ath6kl/htc_pipe.c +++ b/drivers/net/wireless/ath/ath6kl/htc_pipe.c | |||
@@ -988,8 +988,6 @@ static int ath6kl_htc_pipe_rx_complete(struct ath6kl *ar, struct sk_buff *skb, | |||
988 | 988 | ||
989 | htc_hdr = (struct htc_frame_hdr *) netdata; | 989 | htc_hdr = (struct htc_frame_hdr *) netdata; |
990 | 990 | ||
991 | ep = &target->endpoint[htc_hdr->eid]; | ||
992 | |||
993 | if (htc_hdr->eid >= ENDPOINT_MAX) { | 991 | if (htc_hdr->eid >= ENDPOINT_MAX) { |
994 | ath6kl_dbg(ATH6KL_DBG_HTC, | 992 | ath6kl_dbg(ATH6KL_DBG_HTC, |
995 | "HTC Rx: invalid EndpointID=%d\n", | 993 | "HTC Rx: invalid EndpointID=%d\n", |
@@ -997,6 +995,7 @@ static int ath6kl_htc_pipe_rx_complete(struct ath6kl *ar, struct sk_buff *skb, | |||
997 | status = -EINVAL; | 995 | status = -EINVAL; |
998 | goto free_skb; | 996 | goto free_skb; |
999 | } | 997 | } |
998 | ep = &target->endpoint[htc_hdr->eid]; | ||
1000 | 999 | ||
1001 | payload_len = le16_to_cpu(get_unaligned(&htc_hdr->payld_len)); | 1000 | payload_len = le16_to_cpu(get_unaligned(&htc_hdr->payld_len)); |
1002 | 1001 | ||
@@ -1168,8 +1167,8 @@ static int htc_wait_recv_ctrl_message(struct htc_target *target) | |||
1168 | } | 1167 | } |
1169 | 1168 | ||
1170 | if (count <= 0) { | 1169 | if (count <= 0) { |
1171 | ath6kl_dbg(ATH6KL_DBG_HTC, "%s: Timeout!\n", __func__); | 1170 | ath6kl_warn("htc pipe control receive timeout!\n"); |
1172 | return -ECOMM; | 1171 | return -ETIMEDOUT; |
1173 | } | 1172 | } |
1174 | 1173 | ||
1175 | return 0; | 1174 | return 0; |
@@ -1582,16 +1581,16 @@ static int ath6kl_htc_pipe_wait_target(struct htc_target *target) | |||
1582 | return status; | 1581 | return status; |
1583 | 1582 | ||
1584 | if (target->pipe.ctrl_response_len < sizeof(*ready_msg)) { | 1583 | if (target->pipe.ctrl_response_len < sizeof(*ready_msg)) { |
1585 | ath6kl_dbg(ATH6KL_DBG_HTC, "invalid htc ready msg len:%d!\n", | 1584 | ath6kl_warn("invalid htc pipe ready msg len: %d\n", |
1586 | target->pipe.ctrl_response_len); | 1585 | target->pipe.ctrl_response_len); |
1587 | return -ECOMM; | 1586 | return -ECOMM; |
1588 | } | 1587 | } |
1589 | 1588 | ||
1590 | ready_msg = (struct htc_ready_ext_msg *) target->pipe.ctrl_response_buf; | 1589 | ready_msg = (struct htc_ready_ext_msg *) target->pipe.ctrl_response_buf; |
1591 | 1590 | ||
1592 | if (ready_msg->ver2_0_info.msg_id != cpu_to_le16(HTC_MSG_READY_ID)) { | 1591 | if (ready_msg->ver2_0_info.msg_id != cpu_to_le16(HTC_MSG_READY_ID)) { |
1593 | ath6kl_dbg(ATH6KL_DBG_HTC, "invalid htc ready msg : 0x%X !\n", | 1592 | ath6kl_warn("invalid htc pipe ready msg: 0x%x\n", |
1594 | ready_msg->ver2_0_info.msg_id); | 1593 | ready_msg->ver2_0_info.msg_id); |
1595 | return -ECOMM; | 1594 | return -ECOMM; |
1596 | } | 1595 | } |
1597 | 1596 | ||
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 5d434cf88f35..40ffee6184fd 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c | |||
@@ -201,8 +201,8 @@ struct sk_buff *ath6kl_buf_alloc(int size) | |||
201 | u16 reserved; | 201 | u16 reserved; |
202 | 202 | ||
203 | /* Add chacheline space at front and back of buffer */ | 203 | /* Add chacheline space at front and back of buffer */ |
204 | reserved = (2 * L1_CACHE_BYTES) + ATH6KL_DATA_OFFSET + | 204 | reserved = roundup((2 * L1_CACHE_BYTES) + ATH6KL_DATA_OFFSET + |
205 | sizeof(struct htc_packet) + ATH6KL_HTC_ALIGN_BYTES; | 205 | sizeof(struct htc_packet) + ATH6KL_HTC_ALIGN_BYTES, 4); |
206 | skb = dev_alloc_skb(size + reserved); | 206 | skb = dev_alloc_skb(size + reserved); |
207 | 207 | ||
208 | if (skb) | 208 | if (skb) |
@@ -1549,10 +1549,89 @@ static const char *ath6kl_init_get_hif_name(enum ath6kl_hif_type type) | |||
1549 | return NULL; | 1549 | return NULL; |
1550 | } | 1550 | } |
1551 | 1551 | ||
1552 | |||
1553 | static const struct fw_capa_str_map { | ||
1554 | int id; | ||
1555 | const char *name; | ||
1556 | } fw_capa_map[] = { | ||
1557 | { ATH6KL_FW_CAPABILITY_HOST_P2P, "host-p2p" }, | ||
1558 | { ATH6KL_FW_CAPABILITY_SCHED_SCAN, "sched-scan" }, | ||
1559 | { ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX, "sta-p2pdev-duplex" }, | ||
1560 | { ATH6KL_FW_CAPABILITY_INACTIVITY_TIMEOUT, "inactivity-timeout" }, | ||
1561 | { ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE, "rsn-cap-override" }, | ||
1562 | { ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER, "wow-mc-filter" }, | ||
1563 | { ATH6KL_FW_CAPABILITY_BMISS_ENHANCE, "bmiss-enhance" }, | ||
1564 | { ATH6KL_FW_CAPABILITY_SCHED_SCAN_MATCH_LIST, "sscan-match-list" }, | ||
1565 | { ATH6KL_FW_CAPABILITY_RSSI_SCAN_THOLD, "rssi-scan-thold" }, | ||
1566 | { ATH6KL_FW_CAPABILITY_CUSTOM_MAC_ADDR, "custom-mac-addr" }, | ||
1567 | { ATH6KL_FW_CAPABILITY_TX_ERR_NOTIFY, "tx-err-notify" }, | ||
1568 | { ATH6KL_FW_CAPABILITY_REGDOMAIN, "regdomain" }, | ||
1569 | { ATH6KL_FW_CAPABILITY_SCHED_SCAN_V2, "sched-scan-v2" }, | ||
1570 | { ATH6KL_FW_CAPABILITY_HEART_BEAT_POLL, "hb-poll" }, | ||
1571 | }; | ||
1572 | |||
1573 | static const char *ath6kl_init_get_fw_capa_name(unsigned int id) | ||
1574 | { | ||
1575 | int i; | ||
1576 | |||
1577 | for (i = 0; i < ARRAY_SIZE(fw_capa_map); i++) { | ||
1578 | if (fw_capa_map[i].id == id) | ||
1579 | return fw_capa_map[i].name; | ||
1580 | } | ||
1581 | |||
1582 | return "<unknown>"; | ||
1583 | } | ||
1584 | |||
1585 | static void ath6kl_init_get_fwcaps(struct ath6kl *ar, char *buf, size_t buf_len) | ||
1586 | { | ||
1587 | u8 *data = (u8 *) ar->fw_capabilities; | ||
1588 | size_t trunc_len, len = 0; | ||
1589 | int i, index, bit; | ||
1590 | char *trunc = "..."; | ||
1591 | |||
1592 | for (i = 0; i < ATH6KL_FW_CAPABILITY_MAX; i++) { | ||
1593 | index = i / 8; | ||
1594 | bit = i % 8; | ||
1595 | |||
1596 | if (index >= sizeof(ar->fw_capabilities) * 4) | ||
1597 | break; | ||
1598 | |||
1599 | if (buf_len - len < 4) { | ||
1600 | ath6kl_warn("firmware capability buffer too small!\n"); | ||
1601 | |||
1602 | /* add "..." to the end of string */ | ||
1603 | trunc_len = strlen(trunc) + 1; | ||
1604 | strncpy(buf + buf_len - trunc_len, trunc, trunc_len); | ||
1605 | |||
1606 | return; | ||
1607 | } | ||
1608 | |||
1609 | if (data[index] & (1 << bit)) { | ||
1610 | len += scnprintf(buf + len, buf_len - len, "%s,", | ||
1611 | ath6kl_init_get_fw_capa_name(i)); | ||
1612 | } | ||
1613 | } | ||
1614 | |||
1615 | /* overwrite the last comma */ | ||
1616 | if (len > 0) | ||
1617 | len--; | ||
1618 | |||
1619 | buf[len] = '\0'; | ||
1620 | } | ||
1621 | |||
1622 | static int ath6kl_init_hw_reset(struct ath6kl *ar) | ||
1623 | { | ||
1624 | ath6kl_dbg(ATH6KL_DBG_BOOT, "cold resetting the device"); | ||
1625 | |||
1626 | return ath6kl_diag_write32(ar, RESET_CONTROL_ADDRESS, | ||
1627 | cpu_to_le32(RESET_CONTROL_COLD_RST)); | ||
1628 | } | ||
1629 | |||
1552 | static int __ath6kl_init_hw_start(struct ath6kl *ar) | 1630 | static int __ath6kl_init_hw_start(struct ath6kl *ar) |
1553 | { | 1631 | { |
1554 | long timeleft; | 1632 | long timeleft; |
1555 | int ret, i; | 1633 | int ret, i; |
1634 | char buf[200]; | ||
1556 | 1635 | ||
1557 | ath6kl_dbg(ATH6KL_DBG_BOOT, "hw start\n"); | 1636 | ath6kl_dbg(ATH6KL_DBG_BOOT, "hw start\n"); |
1558 | 1637 | ||
@@ -1569,24 +1648,35 @@ static int __ath6kl_init_hw_start(struct ath6kl *ar) | |||
1569 | goto err_power_off; | 1648 | goto err_power_off; |
1570 | 1649 | ||
1571 | /* Do we need to finish the BMI phase */ | 1650 | /* Do we need to finish the BMI phase */ |
1572 | /* FIXME: return error from ath6kl_bmi_done() */ | 1651 | ret = ath6kl_bmi_done(ar); |
1573 | if (ath6kl_bmi_done(ar)) { | 1652 | if (ret) |
1574 | ret = -EIO; | ||
1575 | goto err_power_off; | 1653 | goto err_power_off; |
1576 | } | ||
1577 | 1654 | ||
1578 | /* | 1655 | /* |
1579 | * The reason we have to wait for the target here is that the | 1656 | * The reason we have to wait for the target here is that the |
1580 | * driver layer has to init BMI in order to set the host block | 1657 | * driver layer has to init BMI in order to set the host block |
1581 | * size. | 1658 | * size. |
1582 | */ | 1659 | */ |
1583 | if (ath6kl_htc_wait_target(ar->htc_target)) { | 1660 | ret = ath6kl_htc_wait_target(ar->htc_target); |
1584 | ret = -EIO; | 1661 | |
1662 | if (ret == -ETIMEDOUT) { | ||
1663 | /* | ||
1664 | * Most likely USB target is in odd state after reboot and | ||
1665 | * needs a reset. A cold reset makes the whole device | ||
1666 | * disappear from USB bus and initialisation starts from | ||
1667 | * beginning. | ||
1668 | */ | ||
1669 | ath6kl_warn("htc wait target timed out, resetting device\n"); | ||
1670 | ath6kl_init_hw_reset(ar); | ||
1671 | goto err_power_off; | ||
1672 | } else if (ret) { | ||
1673 | ath6kl_err("htc wait target failed: %d\n", ret); | ||
1585 | goto err_power_off; | 1674 | goto err_power_off; |
1586 | } | 1675 | } |
1587 | 1676 | ||
1588 | if (ath6kl_init_service_ep(ar)) { | 1677 | ret = ath6kl_init_service_ep(ar); |
1589 | ret = -EIO; | 1678 | if (ret) { |
1679 | ath6kl_err("Endpoint service initilisation failed: %d\n", ret); | ||
1590 | goto err_cleanup_scatter; | 1680 | goto err_cleanup_scatter; |
1591 | } | 1681 | } |
1592 | 1682 | ||
@@ -1617,6 +1707,8 @@ static int __ath6kl_init_hw_start(struct ath6kl *ar) | |||
1617 | ar->wiphy->fw_version, | 1707 | ar->wiphy->fw_version, |
1618 | ar->fw_api, | 1708 | ar->fw_api, |
1619 | test_bit(TESTMODE, &ar->flag) ? " testmode" : ""); | 1709 | test_bit(TESTMODE, &ar->flag) ? " testmode" : ""); |
1710 | ath6kl_init_get_fwcaps(ar, buf, sizeof(buf)); | ||
1711 | ath6kl_info("firmware supports: %s\n", buf); | ||
1620 | } | 1712 | } |
1621 | 1713 | ||
1622 | if (ar->version.abi_ver != ATH6KL_ABI_VERSION) { | 1714 | if (ar->version.abi_ver != ATH6KL_ABI_VERSION) { |
@@ -1765,9 +1857,7 @@ void ath6kl_stop_txrx(struct ath6kl *ar) | |||
1765 | * Try to reset the device if we can. The driver may have been | 1857 | * Try to reset the device if we can. The driver may have been |
1766 | * configure NOT to reset the target during a debug session. | 1858 | * configure NOT to reset the target during a debug session. |
1767 | */ | 1859 | */ |
1768 | ath6kl_dbg(ATH6KL_DBG_TRC, | 1860 | ath6kl_init_hw_reset(ar); |
1769 | "attempting to reset target on instance destroy\n"); | ||
1770 | ath6kl_reset_device(ar, ar->target_type, true, true); | ||
1771 | 1861 | ||
1772 | up(&ar->sem); | 1862 | up(&ar->sem); |
1773 | } | 1863 | } |
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index bd50b6b7b492..d4fcfcad57d0 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c | |||
@@ -345,39 +345,6 @@ out: | |||
345 | return ret; | 345 | return ret; |
346 | } | 346 | } |
347 | 347 | ||
348 | /* FIXME: move to a better place, target.h? */ | ||
349 | #define AR6003_RESET_CONTROL_ADDRESS 0x00004000 | ||
350 | #define AR6004_RESET_CONTROL_ADDRESS 0x00004000 | ||
351 | |||
352 | void ath6kl_reset_device(struct ath6kl *ar, u32 target_type, | ||
353 | bool wait_fot_compltn, bool cold_reset) | ||
354 | { | ||
355 | int status = 0; | ||
356 | u32 address; | ||
357 | __le32 data; | ||
358 | |||
359 | if (target_type != TARGET_TYPE_AR6003 && | ||
360 | target_type != TARGET_TYPE_AR6004) | ||
361 | return; | ||
362 | |||
363 | data = cold_reset ? cpu_to_le32(RESET_CONTROL_COLD_RST) : | ||
364 | cpu_to_le32(RESET_CONTROL_MBOX_RST); | ||
365 | |||
366 | switch (target_type) { | ||
367 | case TARGET_TYPE_AR6003: | ||
368 | address = AR6003_RESET_CONTROL_ADDRESS; | ||
369 | break; | ||
370 | case TARGET_TYPE_AR6004: | ||
371 | address = AR6004_RESET_CONTROL_ADDRESS; | ||
372 | break; | ||
373 | } | ||
374 | |||
375 | status = ath6kl_diag_write32(ar, address, data); | ||
376 | |||
377 | if (status) | ||
378 | ath6kl_err("failed to reset target\n"); | ||
379 | } | ||
380 | |||
381 | static void ath6kl_install_static_wep_keys(struct ath6kl_vif *vif) | 348 | static void ath6kl_install_static_wep_keys(struct ath6kl_vif *vif) |
382 | { | 349 | { |
383 | u8 index; | 350 | u8 index; |
@@ -1327,9 +1294,11 @@ void init_netdev(struct net_device *dev) | |||
1327 | dev->watchdog_timeo = ATH6KL_TX_TIMEOUT; | 1294 | dev->watchdog_timeo = ATH6KL_TX_TIMEOUT; |
1328 | 1295 | ||
1329 | dev->needed_headroom = ETH_HLEN; | 1296 | dev->needed_headroom = ETH_HLEN; |
1330 | dev->needed_headroom += sizeof(struct ath6kl_llc_snap_hdr) + | 1297 | dev->needed_headroom += roundup(sizeof(struct ath6kl_llc_snap_hdr) + |
1331 | sizeof(struct wmi_data_hdr) + HTC_HDR_LENGTH | 1298 | sizeof(struct wmi_data_hdr) + |
1332 | + WMI_MAX_TX_META_SZ + ATH6KL_HTC_ALIGN_BYTES; | 1299 | HTC_HDR_LENGTH + |
1300 | WMI_MAX_TX_META_SZ + | ||
1301 | ATH6KL_HTC_ALIGN_BYTES, 4); | ||
1333 | 1302 | ||
1334 | dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM; | 1303 | dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM; |
1335 | 1304 | ||
diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c index d111980d44c0..fb141454c6d2 100644 --- a/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/drivers/net/wireless/ath/ath6kl/sdio.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include "target.h" | 28 | #include "target.h" |
29 | #include "debug.h" | 29 | #include "debug.h" |
30 | #include "cfg80211.h" | 30 | #include "cfg80211.h" |
31 | #include "trace.h" | ||
31 | 32 | ||
32 | struct ath6kl_sdio { | 33 | struct ath6kl_sdio { |
33 | struct sdio_func *func; | 34 | struct sdio_func *func; |
@@ -179,6 +180,8 @@ static int ath6kl_sdio_io(struct sdio_func *func, u32 request, u32 addr, | |||
179 | request & HIF_FIXED_ADDRESS ? " (fixed)" : "", buf, len); | 180 | request & HIF_FIXED_ADDRESS ? " (fixed)" : "", buf, len); |
180 | ath6kl_dbg_dump(ATH6KL_DBG_SDIO_DUMP, NULL, "sdio ", buf, len); | 181 | ath6kl_dbg_dump(ATH6KL_DBG_SDIO_DUMP, NULL, "sdio ", buf, len); |
181 | 182 | ||
183 | trace_ath6kl_sdio(addr, request, buf, len); | ||
184 | |||
182 | return ret; | 185 | return ret; |
183 | } | 186 | } |
184 | 187 | ||
@@ -309,6 +312,13 @@ static int ath6kl_sdio_scat_rw(struct ath6kl_sdio *ar_sdio, | |||
309 | sdio_claim_host(ar_sdio->func); | 312 | sdio_claim_host(ar_sdio->func); |
310 | 313 | ||
311 | mmc_set_data_timeout(&data, ar_sdio->func->card); | 314 | mmc_set_data_timeout(&data, ar_sdio->func->card); |
315 | |||
316 | trace_ath6kl_sdio_scat(scat_req->addr, | ||
317 | scat_req->req, | ||
318 | scat_req->len, | ||
319 | scat_req->scat_entries, | ||
320 | scat_req->scat_list); | ||
321 | |||
312 | /* synchronous call to process request */ | 322 | /* synchronous call to process request */ |
313 | mmc_wait_for_req(ar_sdio->func->card->host, &mmc_req); | 323 | mmc_wait_for_req(ar_sdio->func->card->host, &mmc_req); |
314 | 324 | ||
@@ -1123,10 +1133,12 @@ static int ath6kl_sdio_bmi_write(struct ath6kl *ar, u8 *buf, u32 len) | |||
1123 | 1133 | ||
1124 | ret = ath6kl_sdio_read_write_sync(ar, addr, buf, len, | 1134 | ret = ath6kl_sdio_read_write_sync(ar, addr, buf, len, |
1125 | HIF_WR_SYNC_BYTE_INC); | 1135 | HIF_WR_SYNC_BYTE_INC); |
1126 | if (ret) | 1136 | if (ret) { |
1127 | ath6kl_err("unable to send the bmi data to the device\n"); | 1137 | ath6kl_err("unable to send the bmi data to the device\n"); |
1138 | return ret; | ||
1139 | } | ||
1128 | 1140 | ||
1129 | return ret; | 1141 | return 0; |
1130 | } | 1142 | } |
1131 | 1143 | ||
1132 | static int ath6kl_sdio_bmi_read(struct ath6kl *ar, u8 *buf, u32 len) | 1144 | static int ath6kl_sdio_bmi_read(struct ath6kl *ar, u8 *buf, u32 len) |
diff --git a/drivers/net/wireless/ath/ath6kl/target.h b/drivers/net/wireless/ath/ath6kl/target.h index a98c12ba70c1..a580a629a0da 100644 --- a/drivers/net/wireless/ath/ath6kl/target.h +++ b/drivers/net/wireless/ath/ath6kl/target.h | |||
@@ -25,7 +25,7 @@ | |||
25 | #define AR6004_BOARD_DATA_SZ 6144 | 25 | #define AR6004_BOARD_DATA_SZ 6144 |
26 | #define AR6004_BOARD_EXT_DATA_SZ 0 | 26 | #define AR6004_BOARD_EXT_DATA_SZ 0 |
27 | 27 | ||
28 | #define RESET_CONTROL_ADDRESS 0x00000000 | 28 | #define RESET_CONTROL_ADDRESS 0x00004000 |
29 | #define RESET_CONTROL_COLD_RST 0x00000100 | 29 | #define RESET_CONTROL_COLD_RST 0x00000100 |
30 | #define RESET_CONTROL_MBOX_RST 0x00000004 | 30 | #define RESET_CONTROL_MBOX_RST 0x00000004 |
31 | 31 | ||
diff --git a/drivers/net/wireless/ath/ath6kl/trace.c b/drivers/net/wireless/ath/ath6kl/trace.c new file mode 100644 index 000000000000..e7d64b1285cb --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/trace.c | |||
@@ -0,0 +1,23 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Qualcomm Atheros, Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include <linux/module.h> | ||
18 | |||
19 | #define CREATE_TRACE_POINTS | ||
20 | #include "trace.h" | ||
21 | |||
22 | EXPORT_TRACEPOINT_SYMBOL(ath6kl_sdio); | ||
23 | EXPORT_TRACEPOINT_SYMBOL(ath6kl_sdio_scat); | ||
diff --git a/drivers/net/wireless/ath/ath6kl/trace.h b/drivers/net/wireless/ath/ath6kl/trace.h new file mode 100644 index 000000000000..1a1ea7881b4d --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/trace.h | |||
@@ -0,0 +1,332 @@ | |||
1 | #if !defined(_ATH6KL_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) | ||
2 | |||
3 | #include <net/cfg80211.h> | ||
4 | #include <linux/skbuff.h> | ||
5 | #include <linux/tracepoint.h> | ||
6 | #include "wmi.h" | ||
7 | #include "hif.h" | ||
8 | |||
9 | #if !defined(_ATH6KL_TRACE_H) | ||
10 | static inline unsigned int ath6kl_get_wmi_id(void *buf, size_t buf_len) | ||
11 | { | ||
12 | struct wmi_cmd_hdr *hdr = buf; | ||
13 | |||
14 | if (buf_len < sizeof(*hdr)) | ||
15 | return 0; | ||
16 | |||
17 | return le16_to_cpu(hdr->cmd_id); | ||
18 | } | ||
19 | #endif /* __ATH6KL_TRACE_H */ | ||
20 | |||
21 | #define _ATH6KL_TRACE_H | ||
22 | |||
23 | /* create empty functions when tracing is disabled */ | ||
24 | #if !defined(CONFIG_ATH6KL_TRACING) | ||
25 | #undef TRACE_EVENT | ||
26 | #define TRACE_EVENT(name, proto, ...) \ | ||
27 | static inline void trace_ ## name(proto) {} | ||
28 | #undef DECLARE_EVENT_CLASS | ||
29 | #define DECLARE_EVENT_CLASS(...) | ||
30 | #undef DEFINE_EVENT | ||
31 | #define DEFINE_EVENT(evt_class, name, proto, ...) \ | ||
32 | static inline void trace_ ## name(proto) {} | ||
33 | #endif /* !CONFIG_ATH6KL_TRACING || __CHECKER__ */ | ||
34 | |||
35 | #undef TRACE_SYSTEM | ||
36 | #define TRACE_SYSTEM ath6kl | ||
37 | |||
38 | TRACE_EVENT(ath6kl_wmi_cmd, | ||
39 | TP_PROTO(void *buf, size_t buf_len), | ||
40 | |||
41 | TP_ARGS(buf, buf_len), | ||
42 | |||
43 | TP_STRUCT__entry( | ||
44 | __field(unsigned int, id) | ||
45 | __field(size_t, buf_len) | ||
46 | __dynamic_array(u8, buf, buf_len) | ||
47 | ), | ||
48 | |||
49 | TP_fast_assign( | ||
50 | __entry->id = ath6kl_get_wmi_id(buf, buf_len); | ||
51 | __entry->buf_len = buf_len; | ||
52 | memcpy(__get_dynamic_array(buf), buf, buf_len); | ||
53 | ), | ||
54 | |||
55 | TP_printk( | ||
56 | "id %d len %zd", | ||
57 | __entry->id, __entry->buf_len | ||
58 | ) | ||
59 | ); | ||
60 | |||
61 | TRACE_EVENT(ath6kl_wmi_event, | ||
62 | TP_PROTO(void *buf, size_t buf_len), | ||
63 | |||
64 | TP_ARGS(buf, buf_len), | ||
65 | |||
66 | TP_STRUCT__entry( | ||
67 | __field(unsigned int, id) | ||
68 | __field(size_t, buf_len) | ||
69 | __dynamic_array(u8, buf, buf_len) | ||
70 | ), | ||
71 | |||
72 | TP_fast_assign( | ||
73 | __entry->id = ath6kl_get_wmi_id(buf, buf_len); | ||
74 | __entry->buf_len = buf_len; | ||
75 | memcpy(__get_dynamic_array(buf), buf, buf_len); | ||
76 | ), | ||
77 | |||
78 | TP_printk( | ||
79 | "id %d len %zd", | ||
80 | __entry->id, __entry->buf_len | ||
81 | ) | ||
82 | ); | ||
83 | |||
84 | TRACE_EVENT(ath6kl_sdio, | ||
85 | TP_PROTO(unsigned int addr, int flags, | ||
86 | void *buf, size_t buf_len), | ||
87 | |||
88 | TP_ARGS(addr, flags, buf, buf_len), | ||
89 | |||
90 | TP_STRUCT__entry( | ||
91 | __field(unsigned int, tx) | ||
92 | __field(unsigned int, addr) | ||
93 | __field(int, flags) | ||
94 | __field(size_t, buf_len) | ||
95 | __dynamic_array(u8, buf, buf_len) | ||
96 | ), | ||
97 | |||
98 | TP_fast_assign( | ||
99 | __entry->addr = addr; | ||
100 | __entry->flags = flags; | ||
101 | __entry->buf_len = buf_len; | ||
102 | memcpy(__get_dynamic_array(buf), buf, buf_len); | ||
103 | |||
104 | if (flags & HIF_WRITE) | ||
105 | __entry->tx = 1; | ||
106 | else | ||
107 | __entry->tx = 0; | ||
108 | ), | ||
109 | |||
110 | TP_printk( | ||
111 | "%s addr 0x%x flags 0x%x len %zd\n", | ||
112 | __entry->tx ? "tx" : "rx", | ||
113 | __entry->addr, | ||
114 | __entry->flags, | ||
115 | __entry->buf_len | ||
116 | ) | ||
117 | ); | ||
118 | |||
119 | TRACE_EVENT(ath6kl_sdio_scat, | ||
120 | TP_PROTO(unsigned int addr, int flags, unsigned int total_len, | ||
121 | unsigned int entries, struct hif_scatter_item *list), | ||
122 | |||
123 | TP_ARGS(addr, flags, total_len, entries, list), | ||
124 | |||
125 | TP_STRUCT__entry( | ||
126 | __field(unsigned int, tx) | ||
127 | __field(unsigned int, addr) | ||
128 | __field(int, flags) | ||
129 | __field(unsigned int, entries) | ||
130 | __field(size_t, total_len) | ||
131 | __dynamic_array(unsigned int, len_array, entries) | ||
132 | __dynamic_array(u8, data, total_len) | ||
133 | ), | ||
134 | |||
135 | TP_fast_assign( | ||
136 | unsigned int *len_array; | ||
137 | int i, offset = 0; | ||
138 | size_t len; | ||
139 | |||
140 | __entry->addr = addr; | ||
141 | __entry->flags = flags; | ||
142 | __entry->entries = entries; | ||
143 | __entry->total_len = total_len; | ||
144 | |||
145 | if (flags & HIF_WRITE) | ||
146 | __entry->tx = 1; | ||
147 | else | ||
148 | __entry->tx = 0; | ||
149 | |||
150 | len_array = __get_dynamic_array(len_array); | ||
151 | |||
152 | for (i = 0; i < entries; i++) { | ||
153 | len = list[i].len; | ||
154 | |||
155 | memcpy((u8 *) __get_dynamic_array(data) + offset, | ||
156 | list[i].buf, len); | ||
157 | |||
158 | len_array[i] = len; | ||
159 | offset += len; | ||
160 | } | ||
161 | ), | ||
162 | |||
163 | TP_printk( | ||
164 | "%s addr 0x%x flags 0x%x entries %d total_len %zd\n", | ||
165 | __entry->tx ? "tx" : "rx", | ||
166 | __entry->addr, | ||
167 | __entry->flags, | ||
168 | __entry->entries, | ||
169 | __entry->total_len | ||
170 | ) | ||
171 | ); | ||
172 | |||
173 | TRACE_EVENT(ath6kl_sdio_irq, | ||
174 | TP_PROTO(void *buf, size_t buf_len), | ||
175 | |||
176 | TP_ARGS(buf, buf_len), | ||
177 | |||
178 | TP_STRUCT__entry( | ||
179 | __field(size_t, buf_len) | ||
180 | __dynamic_array(u8, buf, buf_len) | ||
181 | ), | ||
182 | |||
183 | TP_fast_assign( | ||
184 | __entry->buf_len = buf_len; | ||
185 | memcpy(__get_dynamic_array(buf), buf, buf_len); | ||
186 | ), | ||
187 | |||
188 | TP_printk( | ||
189 | "irq len %zd\n", __entry->buf_len | ||
190 | ) | ||
191 | ); | ||
192 | |||
193 | TRACE_EVENT(ath6kl_htc_rx, | ||
194 | TP_PROTO(int status, int endpoint, void *buf, | ||
195 | size_t buf_len), | ||
196 | |||
197 | TP_ARGS(status, endpoint, buf, buf_len), | ||
198 | |||
199 | TP_STRUCT__entry( | ||
200 | __field(int, status) | ||
201 | __field(int, endpoint) | ||
202 | __field(size_t, buf_len) | ||
203 | __dynamic_array(u8, buf, buf_len) | ||
204 | ), | ||
205 | |||
206 | TP_fast_assign( | ||
207 | __entry->status = status; | ||
208 | __entry->endpoint = endpoint; | ||
209 | __entry->buf_len = buf_len; | ||
210 | memcpy(__get_dynamic_array(buf), buf, buf_len); | ||
211 | ), | ||
212 | |||
213 | TP_printk( | ||
214 | "status %d endpoint %d len %zd\n", | ||
215 | __entry->status, | ||
216 | __entry->endpoint, | ||
217 | __entry->buf_len | ||
218 | ) | ||
219 | ); | ||
220 | |||
221 | TRACE_EVENT(ath6kl_htc_tx, | ||
222 | TP_PROTO(int status, int endpoint, void *buf, | ||
223 | size_t buf_len), | ||
224 | |||
225 | TP_ARGS(status, endpoint, buf, buf_len), | ||
226 | |||
227 | TP_STRUCT__entry( | ||
228 | __field(int, status) | ||
229 | __field(int, endpoint) | ||
230 | __field(size_t, buf_len) | ||
231 | __dynamic_array(u8, buf, buf_len) | ||
232 | ), | ||
233 | |||
234 | TP_fast_assign( | ||
235 | __entry->status = status; | ||
236 | __entry->endpoint = endpoint; | ||
237 | __entry->buf_len = buf_len; | ||
238 | memcpy(__get_dynamic_array(buf), buf, buf_len); | ||
239 | ), | ||
240 | |||
241 | TP_printk( | ||
242 | "status %d endpoint %d len %zd\n", | ||
243 | __entry->status, | ||
244 | __entry->endpoint, | ||
245 | __entry->buf_len | ||
246 | ) | ||
247 | ); | ||
248 | |||
249 | #define ATH6KL_MSG_MAX 200 | ||
250 | |||
251 | DECLARE_EVENT_CLASS(ath6kl_log_event, | ||
252 | TP_PROTO(struct va_format *vaf), | ||
253 | TP_ARGS(vaf), | ||
254 | TP_STRUCT__entry( | ||
255 | __dynamic_array(char, msg, ATH6KL_MSG_MAX) | ||
256 | ), | ||
257 | TP_fast_assign( | ||
258 | WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg), | ||
259 | ATH6KL_MSG_MAX, | ||
260 | vaf->fmt, | ||
261 | *vaf->va) >= ATH6KL_MSG_MAX); | ||
262 | ), | ||
263 | TP_printk("%s", __get_str(msg)) | ||
264 | ); | ||
265 | |||
266 | DEFINE_EVENT(ath6kl_log_event, ath6kl_log_err, | ||
267 | TP_PROTO(struct va_format *vaf), | ||
268 | TP_ARGS(vaf) | ||
269 | ); | ||
270 | |||
271 | DEFINE_EVENT(ath6kl_log_event, ath6kl_log_warn, | ||
272 | TP_PROTO(struct va_format *vaf), | ||
273 | TP_ARGS(vaf) | ||
274 | ); | ||
275 | |||
276 | DEFINE_EVENT(ath6kl_log_event, ath6kl_log_info, | ||
277 | TP_PROTO(struct va_format *vaf), | ||
278 | TP_ARGS(vaf) | ||
279 | ); | ||
280 | |||
281 | TRACE_EVENT(ath6kl_log_dbg, | ||
282 | TP_PROTO(unsigned int level, struct va_format *vaf), | ||
283 | TP_ARGS(level, vaf), | ||
284 | TP_STRUCT__entry( | ||
285 | __field(unsigned int, level) | ||
286 | __dynamic_array(char, msg, ATH6KL_MSG_MAX) | ||
287 | ), | ||
288 | TP_fast_assign( | ||
289 | __entry->level = level; | ||
290 | WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg), | ||
291 | ATH6KL_MSG_MAX, | ||
292 | vaf->fmt, | ||
293 | *vaf->va) >= ATH6KL_MSG_MAX); | ||
294 | ), | ||
295 | TP_printk("%s", __get_str(msg)) | ||
296 | ); | ||
297 | |||
298 | TRACE_EVENT(ath6kl_log_dbg_dump, | ||
299 | TP_PROTO(const char *msg, const char *prefix, | ||
300 | const void *buf, size_t buf_len), | ||
301 | |||
302 | TP_ARGS(msg, prefix, buf, buf_len), | ||
303 | |||
304 | TP_STRUCT__entry( | ||
305 | __string(msg, msg) | ||
306 | __string(prefix, prefix) | ||
307 | __field(size_t, buf_len) | ||
308 | __dynamic_array(u8, buf, buf_len) | ||
309 | ), | ||
310 | |||
311 | TP_fast_assign( | ||
312 | __assign_str(msg, msg); | ||
313 | __assign_str(prefix, prefix); | ||
314 | __entry->buf_len = buf_len; | ||
315 | memcpy(__get_dynamic_array(buf), buf, buf_len); | ||
316 | ), | ||
317 | |||
318 | TP_printk( | ||
319 | "%s/%s\n", __get_str(prefix), __get_str(msg) | ||
320 | ) | ||
321 | ); | ||
322 | |||
323 | #endif /* _ ATH6KL_TRACE_H || TRACE_HEADER_MULTI_READ*/ | ||
324 | |||
325 | /* we don't want to use include/trace/events */ | ||
326 | #undef TRACE_INCLUDE_PATH | ||
327 | #define TRACE_INCLUDE_PATH . | ||
328 | #undef TRACE_INCLUDE_FILE | ||
329 | #define TRACE_INCLUDE_FILE trace | ||
330 | |||
331 | /* This part must be outside protection */ | ||
332 | #include <trace/define_trace.h> | ||
diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c index 78b369286579..ebb24045a8ae 100644 --- a/drivers/net/wireless/ath/ath6kl/txrx.c +++ b/drivers/net/wireless/ath/ath6kl/txrx.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include "core.h" | 20 | #include "core.h" |
21 | #include "debug.h" | 21 | #include "debug.h" |
22 | #include "htc-ops.h" | 22 | #include "htc-ops.h" |
23 | #include "trace.h" | ||
23 | 24 | ||
24 | /* | 25 | /* |
25 | * tid - tid_mux0..tid_mux3 | 26 | * tid - tid_mux0..tid_mux3 |
@@ -288,6 +289,8 @@ int ath6kl_control_tx(void *devt, struct sk_buff *skb, | |||
288 | int status = 0; | 289 | int status = 0; |
289 | struct ath6kl_cookie *cookie = NULL; | 290 | struct ath6kl_cookie *cookie = NULL; |
290 | 291 | ||
292 | trace_ath6kl_wmi_cmd(skb->data, skb->len); | ||
293 | |||
291 | if (WARN_ON_ONCE(ar->state == ATH6KL_STATE_WOW)) { | 294 | if (WARN_ON_ONCE(ar->state == ATH6KL_STATE_WOW)) { |
292 | dev_kfree_skb(skb); | 295 | dev_kfree_skb(skb); |
293 | return -EACCES; | 296 | return -EACCES; |
@@ -1324,7 +1327,7 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) | |||
1324 | __func__, ar, ept, skb, packet->buf, | 1327 | __func__, ar, ept, skb, packet->buf, |
1325 | packet->act_len, status); | 1328 | packet->act_len, status); |
1326 | 1329 | ||
1327 | if (status || !(skb->data + HTC_HDR_LENGTH)) { | 1330 | if (status || packet->act_len < HTC_HDR_LENGTH) { |
1328 | dev_kfree_skb(skb); | 1331 | dev_kfree_skb(skb); |
1329 | return; | 1332 | return; |
1330 | } | 1333 | } |
diff --git a/drivers/net/wireless/ath/ath6kl/usb.c b/drivers/net/wireless/ath/ath6kl/usb.c index 5fcd342762de..bed0d337712d 100644 --- a/drivers/net/wireless/ath/ath6kl/usb.c +++ b/drivers/net/wireless/ath/ath6kl/usb.c | |||
@@ -856,11 +856,9 @@ static int ath6kl_usb_submit_ctrl_out(struct ath6kl_usb *ar_usb, | |||
856 | int ret; | 856 | int ret; |
857 | 857 | ||
858 | if (size > 0) { | 858 | if (size > 0) { |
859 | buf = kmalloc(size, GFP_KERNEL); | 859 | buf = kmemdup(data, size, GFP_KERNEL); |
860 | if (buf == NULL) | 860 | if (buf == NULL) |
861 | return -ENOMEM; | 861 | return -ENOMEM; |
862 | |||
863 | memcpy(buf, data, size); | ||
864 | } | 862 | } |
865 | 863 | ||
866 | /* note: if successful returns number of bytes transfered */ | 864 | /* note: if successful returns number of bytes transfered */ |
@@ -872,8 +870,9 @@ static int ath6kl_usb_submit_ctrl_out(struct ath6kl_usb *ar_usb, | |||
872 | size, 1000); | 870 | size, 1000); |
873 | 871 | ||
874 | if (ret < 0) { | 872 | if (ret < 0) { |
875 | ath6kl_dbg(ATH6KL_DBG_USB, "%s failed,result = %d\n", | 873 | ath6kl_warn("Failed to submit usb control message: %d\n", ret); |
876 | __func__, ret); | 874 | kfree(buf); |
875 | return ret; | ||
877 | } | 876 | } |
878 | 877 | ||
879 | kfree(buf); | 878 | kfree(buf); |
@@ -903,8 +902,9 @@ static int ath6kl_usb_submit_ctrl_in(struct ath6kl_usb *ar_usb, | |||
903 | size, 2 * HZ); | 902 | size, 2 * HZ); |
904 | 903 | ||
905 | if (ret < 0) { | 904 | if (ret < 0) { |
906 | ath6kl_dbg(ATH6KL_DBG_USB, "%s failed,result = %d\n", | 905 | ath6kl_warn("Failed to read usb control message: %d\n", ret); |
907 | __func__, ret); | 906 | kfree(buf); |
907 | return ret; | ||
908 | } | 908 | } |
909 | 909 | ||
910 | memcpy((u8 *) data, buf, size); | 910 | memcpy((u8 *) data, buf, size); |
@@ -961,8 +961,10 @@ static int ath6kl_usb_diag_read32(struct ath6kl *ar, u32 address, u32 *data) | |||
961 | ATH6KL_USB_CONTROL_REQ_DIAG_RESP, | 961 | ATH6KL_USB_CONTROL_REQ_DIAG_RESP, |
962 | ar_usb->diag_resp_buffer, &resp_len); | 962 | ar_usb->diag_resp_buffer, &resp_len); |
963 | 963 | ||
964 | if (ret) | 964 | if (ret) { |
965 | ath6kl_warn("diag read32 failed: %d\n", ret); | ||
965 | return ret; | 966 | return ret; |
967 | } | ||
966 | 968 | ||
967 | resp = (struct ath6kl_usb_ctrl_diag_resp_read *) | 969 | resp = (struct ath6kl_usb_ctrl_diag_resp_read *) |
968 | ar_usb->diag_resp_buffer; | 970 | ar_usb->diag_resp_buffer; |
@@ -976,6 +978,7 @@ static int ath6kl_usb_diag_write32(struct ath6kl *ar, u32 address, __le32 data) | |||
976 | { | 978 | { |
977 | struct ath6kl_usb *ar_usb = ar->hif_priv; | 979 | struct ath6kl_usb *ar_usb = ar->hif_priv; |
978 | struct ath6kl_usb_ctrl_diag_cmd_write *cmd; | 980 | struct ath6kl_usb_ctrl_diag_cmd_write *cmd; |
981 | int ret; | ||
979 | 982 | ||
980 | cmd = (struct ath6kl_usb_ctrl_diag_cmd_write *) ar_usb->diag_cmd_buffer; | 983 | cmd = (struct ath6kl_usb_ctrl_diag_cmd_write *) ar_usb->diag_cmd_buffer; |
981 | 984 | ||
@@ -984,12 +987,17 @@ static int ath6kl_usb_diag_write32(struct ath6kl *ar, u32 address, __le32 data) | |||
984 | cmd->address = cpu_to_le32(address); | 987 | cmd->address = cpu_to_le32(address); |
985 | cmd->value = data; | 988 | cmd->value = data; |
986 | 989 | ||
987 | return ath6kl_usb_ctrl_msg_exchange(ar_usb, | 990 | ret = ath6kl_usb_ctrl_msg_exchange(ar_usb, |
988 | ATH6KL_USB_CONTROL_REQ_DIAG_CMD, | 991 | ATH6KL_USB_CONTROL_REQ_DIAG_CMD, |
989 | (u8 *) cmd, | 992 | (u8 *) cmd, |
990 | sizeof(*cmd), | 993 | sizeof(*cmd), |
991 | 0, NULL, NULL); | 994 | 0, NULL, NULL); |
995 | if (ret) { | ||
996 | ath6kl_warn("diag_write32 failed: %d\n", ret); | ||
997 | return ret; | ||
998 | } | ||
992 | 999 | ||
1000 | return 0; | ||
993 | } | 1001 | } |
994 | 1002 | ||
995 | static int ath6kl_usb_bmi_read(struct ath6kl *ar, u8 *buf, u32 len) | 1003 | static int ath6kl_usb_bmi_read(struct ath6kl *ar, u8 *buf, u32 len) |
@@ -1001,7 +1009,7 @@ static int ath6kl_usb_bmi_read(struct ath6kl *ar, u8 *buf, u32 len) | |||
1001 | ret = ath6kl_usb_submit_ctrl_in(ar_usb, | 1009 | ret = ath6kl_usb_submit_ctrl_in(ar_usb, |
1002 | ATH6KL_USB_CONTROL_REQ_RECV_BMI_RESP, | 1010 | ATH6KL_USB_CONTROL_REQ_RECV_BMI_RESP, |
1003 | 0, 0, buf, len); | 1011 | 0, 0, buf, len); |
1004 | if (ret != 0) { | 1012 | if (ret) { |
1005 | ath6kl_err("Unable to read the bmi data from the device: %d\n", | 1013 | ath6kl_err("Unable to read the bmi data from the device: %d\n", |
1006 | ret); | 1014 | ret); |
1007 | return ret; | 1015 | return ret; |
@@ -1019,7 +1027,7 @@ static int ath6kl_usb_bmi_write(struct ath6kl *ar, u8 *buf, u32 len) | |||
1019 | ret = ath6kl_usb_submit_ctrl_out(ar_usb, | 1027 | ret = ath6kl_usb_submit_ctrl_out(ar_usb, |
1020 | ATH6KL_USB_CONTROL_REQ_SEND_BMI_CMD, | 1028 | ATH6KL_USB_CONTROL_REQ_SEND_BMI_CMD, |
1021 | 0, 0, buf, len); | 1029 | 0, 0, buf, len); |
1022 | if (ret != 0) { | 1030 | if (ret) { |
1023 | ath6kl_err("unable to send the bmi data to the device: %d\n", | 1031 | ath6kl_err("unable to send the bmi data to the device: %d\n", |
1024 | ret); | 1032 | ret); |
1025 | return ret; | 1033 | return ret; |
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index d76b5bd81a0d..87aefb4c4c23 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include "core.h" | 20 | #include "core.h" |
21 | #include "debug.h" | 21 | #include "debug.h" |
22 | #include "testmode.h" | 22 | #include "testmode.h" |
23 | #include "trace.h" | ||
23 | #include "../regd.h" | 24 | #include "../regd.h" |
24 | #include "../regd_common.h" | 25 | #include "../regd_common.h" |
25 | 26 | ||
@@ -2028,6 +2029,9 @@ int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx, | |||
2028 | if (!sband) | 2029 | if (!sband) |
2029 | continue; | 2030 | continue; |
2030 | 2031 | ||
2032 | if (WARN_ON(band >= ATH6KL_NUM_BANDS)) | ||
2033 | break; | ||
2034 | |||
2031 | ratemask = rates[band]; | 2035 | ratemask = rates[band]; |
2032 | supp_rates = sc->supp_rates[band].rates; | 2036 | supp_rates = sc->supp_rates[band].rates; |
2033 | num_rates = 0; | 2037 | num_rates = 0; |
@@ -4086,6 +4090,8 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb) | |||
4086 | return -EINVAL; | 4090 | return -EINVAL; |
4087 | } | 4091 | } |
4088 | 4092 | ||
4093 | trace_ath6kl_wmi_event(skb->data, skb->len); | ||
4094 | |||
4089 | return ath6kl_wmi_proc_events(wmi, skb); | 4095 | return ath6kl_wmi_proc_events(wmi, skb); |
4090 | } | 4096 | } |
4091 | 4097 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 881e989ea470..e6b92ff265fd 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | |||
@@ -3606,6 +3606,12 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) | |||
3606 | value = ar9003_hw_ant_ctrl_common_2_get(ah, is2ghz); | 3606 | value = ar9003_hw_ant_ctrl_common_2_get(ah, is2ghz); |
3607 | REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value); | 3607 | REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value); |
3608 | 3608 | ||
3609 | if ((AR_SREV_9462(ah)) && (ah->rxchainmask == 0x2)) { | ||
3610 | value = ar9003_hw_ant_ctrl_chain_get(ah, 1, is2ghz); | ||
3611 | REG_RMW_FIELD(ah, switch_chain_reg[0], | ||
3612 | AR_SWITCH_TABLE_ALL, value); | ||
3613 | } | ||
3614 | |||
3609 | for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { | 3615 | for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { |
3610 | if ((ah->rxchainmask & BIT(chain)) || | 3616 | if ((ah->rxchainmask & BIT(chain)) || |
3611 | (ah->txchainmask & BIT(chain))) { | 3617 | (ah->txchainmask & BIT(chain))) { |
@@ -3772,6 +3778,17 @@ static void ar9003_hw_atten_apply(struct ath_hw *ah, struct ath9k_channel *chan) | |||
3772 | AR_PHY_EXT_ATTEN_CTL_2, | 3778 | AR_PHY_EXT_ATTEN_CTL_2, |
3773 | }; | 3779 | }; |
3774 | 3780 | ||
3781 | if ((AR_SREV_9462(ah)) && (ah->rxchainmask == 0x2)) { | ||
3782 | value = ar9003_hw_atten_chain_get(ah, 1, chan); | ||
3783 | REG_RMW_FIELD(ah, ext_atten_reg[0], | ||
3784 | AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, value); | ||
3785 | |||
3786 | value = ar9003_hw_atten_chain_get_margin(ah, 1, chan); | ||
3787 | REG_RMW_FIELD(ah, ext_atten_reg[0], | ||
3788 | AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, | ||
3789 | value); | ||
3790 | } | ||
3791 | |||
3775 | /* Test value. if 0 then attenuation is unused. Don't load anything. */ | 3792 | /* Test value. if 0 then attenuation is unused. Don't load anything. */ |
3776 | for (i = 0; i < 3; i++) { | 3793 | for (i = 0; i < 3; i++) { |
3777 | if (ah->txchainmask & BIT(i)) { | 3794 | if (ah->txchainmask & BIT(i)) { |
diff --git a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h index ccc42a71b436..999ab08c34e6 100644 --- a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h | |||
@@ -37,28 +37,28 @@ static const u32 ar9462_pciephy_clkreq_enable_L1_2p0[][2] = { | |||
37 | /* Addr allmodes */ | 37 | /* Addr allmodes */ |
38 | {0x00018c00, 0x18253ede}, | 38 | {0x00018c00, 0x18253ede}, |
39 | {0x00018c04, 0x000801d8}, | 39 | {0x00018c04, 0x000801d8}, |
40 | {0x00018c08, 0x0003580c}, | 40 | {0x00018c08, 0x0003780c}, |
41 | }; | 41 | }; |
42 | 42 | ||
43 | static const u32 ar9462_2p0_baseband_postamble[][5] = { | 43 | static const u32 ar9462_2p0_baseband_postamble[][5] = { |
44 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 44 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
45 | {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a800d}, | 45 | {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a800d}, |
46 | {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a01ae}, | 46 | {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a01ae}, |
47 | {0x00009824, 0x5ac640de, 0x5ac640d0, 0x5ac640d0, 0x63c640da}, | 47 | {0x00009824, 0x63c640de, 0x5ac640d0, 0x5ac640d0, 0x63c640da}, |
48 | {0x00009828, 0x0796be89, 0x0696b081, 0x0696b881, 0x09143e81}, | 48 | {0x00009828, 0x0796be89, 0x0696b081, 0x0696b881, 0x09143e81}, |
49 | {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, | 49 | {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, |
50 | {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c}, | 50 | {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c}, |
51 | {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4}, | 51 | {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4}, |
52 | {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0}, | 52 | {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a2}, |
53 | {0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020}, | 53 | {0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020}, |
54 | {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000d8}, | 54 | {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000d8}, |
55 | {0x00009e10, 0x92c88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec86d2e}, | 55 | {0x00009e10, 0x92c88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec86d2e}, |
56 | {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3376605e, 0x32395d5e}, | 56 | {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3236605e, 0x32365a5e}, |
57 | {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 57 | {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
58 | {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, | 58 | {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, |
59 | {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, | 59 | {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, |
60 | {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, | 60 | {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, |
61 | {0x00009e3c, 0xcf946222, 0xcf946222, 0xcfd5c782, 0xcfd5c282}, | 61 | {0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c282}, |
62 | {0x00009e44, 0x62321e27, 0x62321e27, 0xfe291e27, 0xfe291e27}, | 62 | {0x00009e44, 0x62321e27, 0x62321e27, 0xfe291e27, 0xfe291e27}, |
63 | {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, | 63 | {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, |
64 | {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, | 64 | {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, |
@@ -82,9 +82,9 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = { | |||
82 | {0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982}, | 82 | {0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982}, |
83 | {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, | 83 | {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, |
84 | {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 84 | {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
85 | {0x0000a3a4, 0x00000010, 0x00000010, 0x00000000, 0x00000000}, | 85 | {0x0000a3a4, 0x00000050, 0x00000050, 0x00000000, 0x00000000}, |
86 | {0x0000a3a8, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa}, | 86 | {0x0000a3a8, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa}, |
87 | {0x0000a3ac, 0xaaaaaa00, 0xaaaaaa30, 0xaaaaaa00, 0xaaaaaa00}, | 87 | {0x0000a3ac, 0xaaaaaa00, 0xaa30aa30, 0xaaaaaa00, 0xaaaaaa00}, |
88 | {0x0000a41c, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce}, | 88 | {0x0000a41c, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce}, |
89 | {0x0000a420, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce}, | 89 | {0x0000a420, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce}, |
90 | {0x0000a424, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce}, | 90 | {0x0000a424, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce}, |
@@ -363,14 +363,14 @@ static const u32 ar9462_pciephy_clkreq_disable_L1_2p0[][2] = { | |||
363 | /* Addr allmodes */ | 363 | /* Addr allmodes */ |
364 | {0x00018c00, 0x18213ede}, | 364 | {0x00018c00, 0x18213ede}, |
365 | {0x00018c04, 0x000801d8}, | 365 | {0x00018c04, 0x000801d8}, |
366 | {0x00018c08, 0x0003580c}, | 366 | {0x00018c08, 0x0003780c}, |
367 | }; | 367 | }; |
368 | 368 | ||
369 | static const u32 ar9462_pciephy_pll_on_clkreq_disable_L1_2p0[][2] = { | 369 | static const u32 ar9462_pciephy_pll_on_clkreq_disable_L1_2p0[][2] = { |
370 | /* Addr allmodes */ | 370 | /* Addr allmodes */ |
371 | {0x00018c00, 0x18212ede}, | 371 | {0x00018c00, 0x18212ede}, |
372 | {0x00018c04, 0x000801d8}, | 372 | {0x00018c04, 0x000801d8}, |
373 | {0x00018c08, 0x0003580c}, | 373 | {0x00018c08, 0x0003780c}, |
374 | }; | 374 | }; |
375 | 375 | ||
376 | static const u32 ar9462_2p0_radio_postamble_sys2ant[][5] = { | 376 | static const u32 ar9462_2p0_radio_postamble_sys2ant[][5] = { |
@@ -775,7 +775,7 @@ static const u32 ar9462_2p0_baseband_core[][2] = { | |||
775 | {0x00009fc0, 0x803e4788}, | 775 | {0x00009fc0, 0x803e4788}, |
776 | {0x00009fc4, 0x0001efb5}, | 776 | {0x00009fc4, 0x0001efb5}, |
777 | {0x00009fcc, 0x40000014}, | 777 | {0x00009fcc, 0x40000014}, |
778 | {0x00009fd0, 0x01193b93}, | 778 | {0x00009fd0, 0x0a193b93}, |
779 | {0x0000a20c, 0x00000000}, | 779 | {0x0000a20c, 0x00000000}, |
780 | {0x0000a220, 0x00000000}, | 780 | {0x0000a220, 0x00000000}, |
781 | {0x0000a224, 0x00000000}, | 781 | {0x0000a224, 0x00000000}, |
@@ -850,7 +850,7 @@ static const u32 ar9462_2p0_baseband_core[][2] = { | |||
850 | {0x0000a7cc, 0x00000000}, | 850 | {0x0000a7cc, 0x00000000}, |
851 | {0x0000a7d0, 0x00000000}, | 851 | {0x0000a7d0, 0x00000000}, |
852 | {0x0000a7d4, 0x00000004}, | 852 | {0x0000a7d4, 0x00000004}, |
853 | {0x0000a7dc, 0x00000001}, | 853 | {0x0000a7dc, 0x00000000}, |
854 | {0x0000a7f0, 0x80000000}, | 854 | {0x0000a7f0, 0x80000000}, |
855 | {0x0000a8d0, 0x004b6a8e}, | 855 | {0x0000a8d0, 0x004b6a8e}, |
856 | {0x0000a8d4, 0x00000820}, | 856 | {0x0000a8d4, 0x00000820}, |
@@ -886,7 +886,7 @@ static const u32 ar9462_modes_high_ob_db_tx_gain_table_2p0[][5] = { | |||
886 | {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, | 886 | {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, |
887 | {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, | 887 | {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, |
888 | {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, | 888 | {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, |
889 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, | 889 | {0x0000a410, 0x000050da, 0x000050da, 0x000050de, 0x000050de}, |
890 | {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 890 | {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
891 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, | 891 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, |
892 | {0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002}, | 892 | {0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002}, |
@@ -906,20 +906,20 @@ static const u32 ar9462_modes_high_ob_db_tx_gain_table_2p0[][5] = { | |||
906 | {0x0000a53c, 0x41025e4a, 0x41025e4a, 0x34001640, 0x34001640}, | 906 | {0x0000a53c, 0x41025e4a, 0x41025e4a, 0x34001640, 0x34001640}, |
907 | {0x0000a540, 0x48025e6c, 0x48025e6c, 0x38001660, 0x38001660}, | 907 | {0x0000a540, 0x48025e6c, 0x48025e6c, 0x38001660, 0x38001660}, |
908 | {0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3b001861, 0x3b001861}, | 908 | {0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3b001861, 0x3b001861}, |
909 | {0x0000a548, 0x53025eb2, 0x53025eb2, 0x3e001a81, 0x3e001a81}, | 909 | {0x0000a548, 0x55025eb3, 0x55025eb3, 0x3e001a81, 0x3e001a81}, |
910 | {0x0000a54c, 0x59025eb6, 0x59025eb6, 0x42001a83, 0x42001a83}, | 910 | {0x0000a54c, 0x58025ef3, 0x58025ef3, 0x42001a83, 0x42001a83}, |
911 | {0x0000a550, 0x5d025ef6, 0x5d025ef6, 0x44001c84, 0x44001c84}, | 911 | {0x0000a550, 0x5d025ef6, 0x5d025ef6, 0x44001a84, 0x44001a84}, |
912 | {0x0000a554, 0x62025f56, 0x62025f56, 0x48001ce3, 0x48001ce3}, | 912 | {0x0000a554, 0x62025f56, 0x62025f56, 0x48001ce3, 0x48001ce3}, |
913 | {0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5}, | 913 | {0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5}, |
914 | {0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9}, | 914 | {0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9}, |
915 | {0x0000a560, 0x70049f56, 0x70049f56, 0x54001ceb, 0x54001ceb}, | 915 | {0x0000a560, 0x70049f56, 0x70049f56, 0x54001ceb, 0x54001ceb}, |
916 | {0x0000a564, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 916 | {0x0000a564, 0x751ffff6, 0x751ffff6, 0x56001eec, 0x56001eec}, |
917 | {0x0000a568, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 917 | {0x0000a568, 0x751ffff6, 0x751ffff6, 0x58001ef0, 0x58001ef0}, |
918 | {0x0000a56c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 918 | {0x0000a56c, 0x751ffff6, 0x751ffff6, 0x5a001ef4, 0x5a001ef4}, |
919 | {0x0000a570, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 919 | {0x0000a570, 0x751ffff6, 0x751ffff6, 0x5c001ff6, 0x5c001ff6}, |
920 | {0x0000a574, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 920 | {0x0000a574, 0x751ffff6, 0x751ffff6, 0x5c001ff6, 0x5c001ff6}, |
921 | {0x0000a578, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 921 | {0x0000a578, 0x751ffff6, 0x751ffff6, 0x5c001ff6, 0x5c001ff6}, |
922 | {0x0000a57c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 922 | {0x0000a57c, 0x751ffff6, 0x751ffff6, 0x5c001ff6, 0x5c001ff6}, |
923 | {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 923 | {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
924 | {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 924 | {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
925 | {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 925 | {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
@@ -1053,7 +1053,6 @@ static const u32 ar9462_2p0_mac_core[][2] = { | |||
1053 | {0x00008044, 0x00000000}, | 1053 | {0x00008044, 0x00000000}, |
1054 | {0x00008048, 0x00000000}, | 1054 | {0x00008048, 0x00000000}, |
1055 | {0x0000804c, 0xffffffff}, | 1055 | {0x0000804c, 0xffffffff}, |
1056 | {0x00008050, 0xffffffff}, | ||
1057 | {0x00008054, 0x00000000}, | 1056 | {0x00008054, 0x00000000}, |
1058 | {0x00008058, 0x00000000}, | 1057 | {0x00008058, 0x00000000}, |
1059 | {0x0000805c, 0x000fc78f}, | 1058 | {0x0000805c, 0x000fc78f}, |
@@ -1117,9 +1116,9 @@ static const u32 ar9462_2p0_mac_core[][2] = { | |||
1117 | {0x000081f8, 0x00000000}, | 1116 | {0x000081f8, 0x00000000}, |
1118 | {0x000081fc, 0x00000000}, | 1117 | {0x000081fc, 0x00000000}, |
1119 | {0x00008240, 0x00100000}, | 1118 | {0x00008240, 0x00100000}, |
1120 | {0x00008244, 0x0010f424}, | 1119 | {0x00008244, 0x0010f400}, |
1121 | {0x00008248, 0x00000800}, | 1120 | {0x00008248, 0x00000800}, |
1122 | {0x0000824c, 0x0001e848}, | 1121 | {0x0000824c, 0x0001e800}, |
1123 | {0x00008250, 0x00000000}, | 1122 | {0x00008250, 0x00000000}, |
1124 | {0x00008254, 0x00000000}, | 1123 | {0x00008254, 0x00000000}, |
1125 | {0x00008258, 0x00000000}, | 1124 | {0x00008258, 0x00000000}, |
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 1e8508530e98..7bdd726c7a8f 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c | |||
@@ -369,7 +369,6 @@ bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
369 | struct ieee80211_channel *c = chan->chan; | 369 | struct ieee80211_channel *c = chan->chan; |
370 | struct ath9k_hw_cal_data *caldata = ah->caldata; | 370 | struct ath9k_hw_cal_data *caldata = ah->caldata; |
371 | 371 | ||
372 | chan->channelFlags &= (~CHANNEL_CW_INT); | ||
373 | if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) { | 372 | if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) { |
374 | ath_dbg(common, CALIBRATE, | 373 | ath_dbg(common, CALIBRATE, |
375 | "NF did not complete in calibration window\n"); | 374 | "NF did not complete in calibration window\n"); |
@@ -384,7 +383,6 @@ bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
384 | ath_dbg(common, CALIBRATE, | 383 | ath_dbg(common, CALIBRATE, |
385 | "noise floor failed detected; detected %d, threshold %d\n", | 384 | "noise floor failed detected; detected %d, threshold %d\n", |
386 | nf, nfThresh); | 385 | nf, nfThresh); |
387 | chan->channelFlags |= CHANNEL_CW_INT; | ||
388 | } | 386 | } |
389 | 387 | ||
390 | if (!caldata) { | 388 | if (!caldata) { |
@@ -410,7 +408,7 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah, | |||
410 | int i, j; | 408 | int i, j; |
411 | 409 | ||
412 | ah->caldata->channel = chan->channel; | 410 | ah->caldata->channel = chan->channel; |
413 | ah->caldata->channelFlags = chan->channelFlags & ~CHANNEL_CW_INT; | 411 | ah->caldata->channelFlags = chan->channelFlags; |
414 | ah->caldata->chanmode = chan->chanmode; | 412 | ah->caldata->chanmode = chan->chanmode; |
415 | h = ah->caldata->nfCalHist; | 413 | h = ah->caldata->nfCalHist; |
416 | default_nf = ath9k_hw_get_default_nf(ah, chan); | 414 | default_nf = ath9k_hw_get_default_nf(ah, chan); |
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index 050ca4a4850d..6102476a65de 100644 --- a/drivers/net/wireless/ath/ath9k/common.h +++ b/drivers/net/wireless/ath/ath9k/common.h | |||
@@ -40,7 +40,7 @@ | |||
40 | x = ATH_LPF_RSSI((x), ATH_RSSI_IN((y)), ATH_RSSI_LPF_LEN); \ | 40 | x = ATH_LPF_RSSI((x), ATH_RSSI_IN((y)), ATH_RSSI_LPF_LEN); \ |
41 | } while (0) | 41 | } while (0) |
42 | #define ATH_EP_RND(x, mul) \ | 42 | #define ATH_EP_RND(x, mul) \ |
43 | ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul)) | 43 | (((x) + ((mul)/2)) / (mul)) |
44 | 44 | ||
45 | int ath9k_cmn_padpos(__le16 frame_control); | 45 | int ath9k_cmn_padpos(__le16 frame_control); |
46 | int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb); | 46 | int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb); |
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 3714b971d18e..67a2a4b3b883 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
@@ -537,6 +537,7 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf, | |||
537 | PR("AMPDUs Completed:", a_completed); | 537 | PR("AMPDUs Completed:", a_completed); |
538 | PR("AMPDUs Retried: ", a_retries); | 538 | PR("AMPDUs Retried: ", a_retries); |
539 | PR("AMPDUs XRetried: ", a_xretries); | 539 | PR("AMPDUs XRetried: ", a_xretries); |
540 | PR("TXERR Filtered: ", txerr_filtered); | ||
540 | PR("FIFO Underrun: ", fifo_underrun); | 541 | PR("FIFO Underrun: ", fifo_underrun); |
541 | PR("TXOP Exceeded: ", xtxop); | 542 | PR("TXOP Exceeded: ", xtxop); |
542 | PR("TXTIMER Expiry: ", timer_exp); | 543 | PR("TXTIMER Expiry: ", timer_exp); |
@@ -756,6 +757,8 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, | |||
756 | TX_STAT_INC(qnum, completed); | 757 | TX_STAT_INC(qnum, completed); |
757 | } | 758 | } |
758 | 759 | ||
760 | if (ts->ts_status & ATH9K_TXERR_FILT) | ||
761 | TX_STAT_INC(qnum, txerr_filtered); | ||
759 | if (ts->ts_status & ATH9K_TXERR_FIFO) | 762 | if (ts->ts_status & ATH9K_TXERR_FIFO) |
760 | TX_STAT_INC(qnum, fifo_underrun); | 763 | TX_STAT_INC(qnum, fifo_underrun); |
761 | if (ts->ts_status & ATH9K_TXERR_XTXOP) | 764 | if (ts->ts_status & ATH9K_TXERR_XTXOP) |
@@ -1909,6 +1912,7 @@ static const char ath9k_gstrings_stats[][ETH_GSTRING_LEN] = { | |||
1909 | AMKSTR(d_tx_desc_cfg_err), | 1912 | AMKSTR(d_tx_desc_cfg_err), |
1910 | AMKSTR(d_tx_data_underrun), | 1913 | AMKSTR(d_tx_data_underrun), |
1911 | AMKSTR(d_tx_delim_underrun), | 1914 | AMKSTR(d_tx_delim_underrun), |
1915 | "d_rx_crc_err", | ||
1912 | "d_rx_decrypt_crc_err", | 1916 | "d_rx_decrypt_crc_err", |
1913 | "d_rx_phy_err", | 1917 | "d_rx_phy_err", |
1914 | "d_rx_mic_err", | 1918 | "d_rx_mic_err", |
@@ -1989,6 +1993,7 @@ void ath9k_get_et_stats(struct ieee80211_hw *hw, | |||
1989 | AWDATA(data_underrun); | 1993 | AWDATA(data_underrun); |
1990 | AWDATA(delim_underrun); | 1994 | AWDATA(delim_underrun); |
1991 | 1995 | ||
1996 | AWDATA_RX(crc_err); | ||
1992 | AWDATA_RX(decrypt_crc_err); | 1997 | AWDATA_RX(decrypt_crc_err); |
1993 | AWDATA_RX(phy_err); | 1998 | AWDATA_RX(phy_err); |
1994 | AWDATA_RX(mic_err); | 1999 | AWDATA_RX(mic_err); |
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 410d6d8f1aa7..794a7ec83a24 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h | |||
@@ -142,6 +142,7 @@ struct ath_interrupt_stats { | |||
142 | * @a_completed: Total AMPDUs completed | 142 | * @a_completed: Total AMPDUs completed |
143 | * @a_retries: No. of AMPDUs retried (SW) | 143 | * @a_retries: No. of AMPDUs retried (SW) |
144 | * @a_xretries: No. of AMPDUs dropped due to xretries | 144 | * @a_xretries: No. of AMPDUs dropped due to xretries |
145 | * @txerr_filtered: No. of frames with TXERR_FILT flag set. | ||
145 | * @fifo_underrun: FIFO underrun occurrences | 146 | * @fifo_underrun: FIFO underrun occurrences |
146 | Valid only for: | 147 | Valid only for: |
147 | - non-aggregate condition. | 148 | - non-aggregate condition. |
@@ -168,6 +169,7 @@ struct ath_tx_stats { | |||
168 | u32 a_completed; | 169 | u32 a_completed; |
169 | u32 a_retries; | 170 | u32 a_retries; |
170 | u32 a_xretries; | 171 | u32 a_xretries; |
172 | u32 txerr_filtered; | ||
171 | u32 fifo_underrun; | 173 | u32 fifo_underrun; |
172 | u32 xtxop; | 174 | u32 xtxop; |
173 | u32 timer_exp; | 175 | u32 timer_exp; |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 07e25260c31d..4fa2bb167050 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -1669,6 +1669,104 @@ bool ath9k_hw_check_alive(struct ath_hw *ah) | |||
1669 | } | 1669 | } |
1670 | EXPORT_SYMBOL(ath9k_hw_check_alive); | 1670 | EXPORT_SYMBOL(ath9k_hw_check_alive); |
1671 | 1671 | ||
1672 | static void ath9k_hw_init_mfp(struct ath_hw *ah) | ||
1673 | { | ||
1674 | /* Setup MFP options for CCMP */ | ||
1675 | if (AR_SREV_9280_20_OR_LATER(ah)) { | ||
1676 | /* Mask Retry(b11), PwrMgt(b12), MoreData(b13) to 0 in mgmt | ||
1677 | * frames when constructing CCMP AAD. */ | ||
1678 | REG_RMW_FIELD(ah, AR_AES_MUTE_MASK1, AR_AES_MUTE_MASK1_FC_MGMT, | ||
1679 | 0xc7ff); | ||
1680 | ah->sw_mgmt_crypto = false; | ||
1681 | } else if (AR_SREV_9160_10_OR_LATER(ah)) { | ||
1682 | /* Disable hardware crypto for management frames */ | ||
1683 | REG_CLR_BIT(ah, AR_PCU_MISC_MODE2, | ||
1684 | AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE); | ||
1685 | REG_SET_BIT(ah, AR_PCU_MISC_MODE2, | ||
1686 | AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT); | ||
1687 | ah->sw_mgmt_crypto = true; | ||
1688 | } else { | ||
1689 | ah->sw_mgmt_crypto = true; | ||
1690 | } | ||
1691 | } | ||
1692 | |||
1693 | static void ath9k_hw_reset_opmode(struct ath_hw *ah, | ||
1694 | u32 macStaId1, u32 saveDefAntenna) | ||
1695 | { | ||
1696 | struct ath_common *common = ath9k_hw_common(ah); | ||
1697 | |||
1698 | ENABLE_REGWRITE_BUFFER(ah); | ||
1699 | |||
1700 | REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr)); | ||
1701 | REG_WRITE(ah, AR_STA_ID1, get_unaligned_le16(common->macaddr + 4) | ||
1702 | | macStaId1 | ||
1703 | | AR_STA_ID1_RTS_USE_DEF | ||
1704 | | (ah->config.ack_6mb ? AR_STA_ID1_ACKCTS_6MB : 0) | ||
1705 | | ah->sta_id1_defaults); | ||
1706 | ath_hw_setbssidmask(common); | ||
1707 | REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna); | ||
1708 | ath9k_hw_write_associd(ah); | ||
1709 | REG_WRITE(ah, AR_ISR, ~0); | ||
1710 | REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR); | ||
1711 | |||
1712 | REGWRITE_BUFFER_FLUSH(ah); | ||
1713 | |||
1714 | ath9k_hw_set_operating_mode(ah, ah->opmode); | ||
1715 | } | ||
1716 | |||
1717 | static void ath9k_hw_init_queues(struct ath_hw *ah) | ||
1718 | { | ||
1719 | int i; | ||
1720 | |||
1721 | ENABLE_REGWRITE_BUFFER(ah); | ||
1722 | |||
1723 | for (i = 0; i < AR_NUM_DCU; i++) | ||
1724 | REG_WRITE(ah, AR_DQCUMASK(i), 1 << i); | ||
1725 | |||
1726 | REGWRITE_BUFFER_FLUSH(ah); | ||
1727 | |||
1728 | ah->intr_txqs = 0; | ||
1729 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) | ||
1730 | ath9k_hw_resettxqueue(ah, i); | ||
1731 | } | ||
1732 | |||
1733 | /* | ||
1734 | * For big endian systems turn on swapping for descriptors | ||
1735 | */ | ||
1736 | static void ath9k_hw_init_desc(struct ath_hw *ah) | ||
1737 | { | ||
1738 | struct ath_common *common = ath9k_hw_common(ah); | ||
1739 | |||
1740 | if (AR_SREV_9100(ah)) { | ||
1741 | u32 mask; | ||
1742 | mask = REG_READ(ah, AR_CFG); | ||
1743 | if (mask & (AR_CFG_SWRB | AR_CFG_SWTB | AR_CFG_SWRG)) { | ||
1744 | ath_dbg(common, RESET, "CFG Byte Swap Set 0x%x\n", | ||
1745 | mask); | ||
1746 | } else { | ||
1747 | mask = INIT_CONFIG_STATUS | AR_CFG_SWRB | AR_CFG_SWTB; | ||
1748 | REG_WRITE(ah, AR_CFG, mask); | ||
1749 | ath_dbg(common, RESET, "Setting CFG 0x%x\n", | ||
1750 | REG_READ(ah, AR_CFG)); | ||
1751 | } | ||
1752 | } else { | ||
1753 | if (common->bus_ops->ath_bus_type == ATH_USB) { | ||
1754 | /* Configure AR9271 target WLAN */ | ||
1755 | if (AR_SREV_9271(ah)) | ||
1756 | REG_WRITE(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB); | ||
1757 | else | ||
1758 | REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); | ||
1759 | } | ||
1760 | #ifdef __BIG_ENDIAN | ||
1761 | else if (AR_SREV_9330(ah) || AR_SREV_9340(ah) || | ||
1762 | AR_SREV_9550(ah)) | ||
1763 | REG_RMW(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB, 0); | ||
1764 | else | ||
1765 | REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); | ||
1766 | #endif | ||
1767 | } | ||
1768 | } | ||
1769 | |||
1672 | /* | 1770 | /* |
1673 | * Fast channel change: | 1771 | * Fast channel change: |
1674 | * (Change synthesizer based on channel freq without resetting chip) | 1772 | * (Change synthesizer based on channel freq without resetting chip) |
@@ -1746,7 +1844,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1746 | u32 saveDefAntenna; | 1844 | u32 saveDefAntenna; |
1747 | u32 macStaId1; | 1845 | u32 macStaId1; |
1748 | u64 tsf = 0; | 1846 | u64 tsf = 0; |
1749 | int i, r; | 1847 | int r; |
1750 | bool start_mci_reset = false; | 1848 | bool start_mci_reset = false; |
1751 | bool save_fullsleep = ah->chip_fullsleep; | 1849 | bool save_fullsleep = ah->chip_fullsleep; |
1752 | 1850 | ||
@@ -1763,10 +1861,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1763 | ath9k_hw_getnf(ah, ah->curchan); | 1861 | ath9k_hw_getnf(ah, ah->curchan); |
1764 | 1862 | ||
1765 | ah->caldata = caldata; | 1863 | ah->caldata = caldata; |
1766 | if (caldata && | 1864 | if (caldata && (chan->channel != caldata->channel || |
1767 | (chan->channel != caldata->channel || | 1865 | chan->channelFlags != caldata->channelFlags)) { |
1768 | (chan->channelFlags & ~CHANNEL_CW_INT) != | ||
1769 | (caldata->channelFlags & ~CHANNEL_CW_INT))) { | ||
1770 | /* Operating channel changed, reset channel calibration data */ | 1866 | /* Operating channel changed, reset channel calibration data */ |
1771 | memset(caldata, 0, sizeof(*caldata)); | 1867 | memset(caldata, 0, sizeof(*caldata)); |
1772 | ath9k_init_nfcal_hist_buffer(ah, chan); | 1868 | ath9k_init_nfcal_hist_buffer(ah, chan); |
@@ -1853,22 +1949,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1853 | ath9k_hw_settsf64(ah, tsf); | 1949 | ath9k_hw_settsf64(ah, tsf); |
1854 | } | 1950 | } |
1855 | 1951 | ||
1856 | /* Setup MFP options for CCMP */ | 1952 | ath9k_hw_init_mfp(ah); |
1857 | if (AR_SREV_9280_20_OR_LATER(ah)) { | ||
1858 | /* Mask Retry(b11), PwrMgt(b12), MoreData(b13) to 0 in mgmt | ||
1859 | * frames when constructing CCMP AAD. */ | ||
1860 | REG_RMW_FIELD(ah, AR_AES_MUTE_MASK1, AR_AES_MUTE_MASK1_FC_MGMT, | ||
1861 | 0xc7ff); | ||
1862 | ah->sw_mgmt_crypto = false; | ||
1863 | } else if (AR_SREV_9160_10_OR_LATER(ah)) { | ||
1864 | /* Disable hardware crypto for management frames */ | ||
1865 | REG_CLR_BIT(ah, AR_PCU_MISC_MODE2, | ||
1866 | AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE); | ||
1867 | REG_SET_BIT(ah, AR_PCU_MISC_MODE2, | ||
1868 | AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT); | ||
1869 | ah->sw_mgmt_crypto = true; | ||
1870 | } else | ||
1871 | ah->sw_mgmt_crypto = true; | ||
1872 | 1953 | ||
1873 | if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan)) | 1954 | if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan)) |
1874 | ath9k_hw_set_delta_slope(ah, chan); | 1955 | ath9k_hw_set_delta_slope(ah, chan); |
@@ -1876,24 +1957,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1876 | ath9k_hw_spur_mitigate_freq(ah, chan); | 1957 | ath9k_hw_spur_mitigate_freq(ah, chan); |
1877 | ah->eep_ops->set_board_values(ah, chan); | 1958 | ah->eep_ops->set_board_values(ah, chan); |
1878 | 1959 | ||
1879 | ENABLE_REGWRITE_BUFFER(ah); | 1960 | ath9k_hw_reset_opmode(ah, macStaId1, saveDefAntenna); |
1880 | |||
1881 | REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr)); | ||
1882 | REG_WRITE(ah, AR_STA_ID1, get_unaligned_le16(common->macaddr + 4) | ||
1883 | | macStaId1 | ||
1884 | | AR_STA_ID1_RTS_USE_DEF | ||
1885 | | (ah->config. | ||
1886 | ack_6mb ? AR_STA_ID1_ACKCTS_6MB : 0) | ||
1887 | | ah->sta_id1_defaults); | ||
1888 | ath_hw_setbssidmask(common); | ||
1889 | REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna); | ||
1890 | ath9k_hw_write_associd(ah); | ||
1891 | REG_WRITE(ah, AR_ISR, ~0); | ||
1892 | REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR); | ||
1893 | |||
1894 | REGWRITE_BUFFER_FLUSH(ah); | ||
1895 | |||
1896 | ath9k_hw_set_operating_mode(ah, ah->opmode); | ||
1897 | 1961 | ||
1898 | r = ath9k_hw_rf_set_freq(ah, chan); | 1962 | r = ath9k_hw_rf_set_freq(ah, chan); |
1899 | if (r) | 1963 | if (r) |
@@ -1901,17 +1965,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1901 | 1965 | ||
1902 | ath9k_hw_set_clockrate(ah); | 1966 | ath9k_hw_set_clockrate(ah); |
1903 | 1967 | ||
1904 | ENABLE_REGWRITE_BUFFER(ah); | 1968 | ath9k_hw_init_queues(ah); |
1905 | |||
1906 | for (i = 0; i < AR_NUM_DCU; i++) | ||
1907 | REG_WRITE(ah, AR_DQCUMASK(i), 1 << i); | ||
1908 | |||
1909 | REGWRITE_BUFFER_FLUSH(ah); | ||
1910 | |||
1911 | ah->intr_txqs = 0; | ||
1912 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) | ||
1913 | ath9k_hw_resettxqueue(ah, i); | ||
1914 | |||
1915 | ath9k_hw_init_interrupt_masks(ah, ah->opmode); | 1969 | ath9k_hw_init_interrupt_masks(ah, ah->opmode); |
1916 | ath9k_hw_ani_cache_ini_regs(ah); | 1970 | ath9k_hw_ani_cache_ini_regs(ah); |
1917 | ath9k_hw_init_qos(ah); | 1971 | ath9k_hw_init_qos(ah); |
@@ -1966,38 +2020,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1966 | 2020 | ||
1967 | REGWRITE_BUFFER_FLUSH(ah); | 2021 | REGWRITE_BUFFER_FLUSH(ah); |
1968 | 2022 | ||
1969 | /* | 2023 | ath9k_hw_init_desc(ah); |
1970 | * For big endian systems turn on swapping for descriptors | ||
1971 | */ | ||
1972 | if (AR_SREV_9100(ah)) { | ||
1973 | u32 mask; | ||
1974 | mask = REG_READ(ah, AR_CFG); | ||
1975 | if (mask & (AR_CFG_SWRB | AR_CFG_SWTB | AR_CFG_SWRG)) { | ||
1976 | ath_dbg(common, RESET, "CFG Byte Swap Set 0x%x\n", | ||
1977 | mask); | ||
1978 | } else { | ||
1979 | mask = | ||
1980 | INIT_CONFIG_STATUS | AR_CFG_SWRB | AR_CFG_SWTB; | ||
1981 | REG_WRITE(ah, AR_CFG, mask); | ||
1982 | ath_dbg(common, RESET, "Setting CFG 0x%x\n", | ||
1983 | REG_READ(ah, AR_CFG)); | ||
1984 | } | ||
1985 | } else { | ||
1986 | if (common->bus_ops->ath_bus_type == ATH_USB) { | ||
1987 | /* Configure AR9271 target WLAN */ | ||
1988 | if (AR_SREV_9271(ah)) | ||
1989 | REG_WRITE(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB); | ||
1990 | else | ||
1991 | REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); | ||
1992 | } | ||
1993 | #ifdef __BIG_ENDIAN | ||
1994 | else if (AR_SREV_9330(ah) || AR_SREV_9340(ah) || | ||
1995 | AR_SREV_9550(ah)) | ||
1996 | REG_RMW(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB, 0); | ||
1997 | else | ||
1998 | REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); | ||
1999 | #endif | ||
2000 | } | ||
2001 | 2024 | ||
2002 | if (ath9k_hw_btcoex_is_enabled(ah)) | 2025 | if (ath9k_hw_btcoex_is_enabled(ah)) |
2003 | ath9k_hw_btcoex_enable(ah); | 2026 | ath9k_hw_btcoex_enable(ah); |
@@ -2010,7 +2033,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
2010 | 2033 | ||
2011 | if (AR_SREV_9300_20_OR_LATER(ah)) { | 2034 | if (AR_SREV_9300_20_OR_LATER(ah)) { |
2012 | ar9003_hw_bb_watchdog_config(ah); | 2035 | ar9003_hw_bb_watchdog_config(ah); |
2013 | |||
2014 | ar9003_hw_disable_phy_restart(ah); | 2036 | ar9003_hw_disable_phy_restart(ah); |
2015 | } | 2037 | } |
2016 | 2038 | ||
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 784e81ccb903..30e62d92d46d 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -363,7 +363,6 @@ enum ath9k_int { | |||
363 | ATH9K_INT_NOCARD = 0xffffffff | 363 | ATH9K_INT_NOCARD = 0xffffffff |
364 | }; | 364 | }; |
365 | 365 | ||
366 | #define CHANNEL_CW_INT 0x00002 | ||
367 | #define CHANNEL_CCK 0x00020 | 366 | #define CHANNEL_CCK 0x00020 |
368 | #define CHANNEL_OFDM 0x00040 | 367 | #define CHANNEL_OFDM 0x00040 |
369 | #define CHANNEL_2GHZ 0x00080 | 368 | #define CHANNEL_2GHZ 0x00080 |
diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c index 9c0b150d5b8e..c61cafa2665b 100644 --- a/drivers/net/wireless/ath/carl9170/tx.c +++ b/drivers/net/wireless/ath/carl9170/tx.c | |||
@@ -387,8 +387,7 @@ static void carl9170_tx_status_process_ampdu(struct ar9170 *ar, | |||
387 | u8 tid; | 387 | u8 tid; |
388 | 388 | ||
389 | if (!(txinfo->flags & IEEE80211_TX_CTL_AMPDU) || | 389 | if (!(txinfo->flags & IEEE80211_TX_CTL_AMPDU) || |
390 | txinfo->flags & IEEE80211_TX_CTL_INJECTED || | 390 | txinfo->flags & IEEE80211_TX_CTL_INJECTED) |
391 | (!(super->f.mac_control & cpu_to_le16(AR9170_TX_MAC_AGGR)))) | ||
392 | return; | 391 | return; |
393 | 392 | ||
394 | rcu_read_lock(); | 393 | rcu_read_lock(); |
@@ -981,30 +980,6 @@ static int carl9170_tx_prepare(struct ar9170 *ar, | |||
981 | 980 | ||
982 | SET_VAL(CARL9170_TX_SUPER_AMPDU_FACTOR, | 981 | SET_VAL(CARL9170_TX_SUPER_AMPDU_FACTOR, |
983 | txc->s.ampdu_settings, factor); | 982 | txc->s.ampdu_settings, factor); |
984 | |||
985 | for (i = 0; i < CARL9170_TX_MAX_RATES; i++) { | ||
986 | txrate = &info->control.rates[i]; | ||
987 | if (txrate->idx >= 0) { | ||
988 | txc->s.ri[i] = | ||
989 | CARL9170_TX_SUPER_RI_AMPDU; | ||
990 | |||
991 | if (WARN_ON(!(txrate->flags & | ||
992 | IEEE80211_TX_RC_MCS))) { | ||
993 | /* | ||
994 | * Not sure if it's even possible | ||
995 | * to aggregate non-ht rates with | ||
996 | * this HW. | ||
997 | */ | ||
998 | goto err_out; | ||
999 | } | ||
1000 | continue; | ||
1001 | } | ||
1002 | |||
1003 | txrate->idx = 0; | ||
1004 | txrate->count = ar->hw->max_rate_tries; | ||
1005 | } | ||
1006 | |||
1007 | mac_tmp |= cpu_to_le16(AR9170_TX_MAC_AGGR); | ||
1008 | } | 983 | } |
1009 | 984 | ||
1010 | /* | 985 | /* |
@@ -1012,11 +987,31 @@ static int carl9170_tx_prepare(struct ar9170 *ar, | |||
1012 | * taken from mac_control. For all fallback rate, the firmware | 987 | * taken from mac_control. For all fallback rate, the firmware |
1013 | * updates the mac_control flags from the rate info field. | 988 | * updates the mac_control flags from the rate info field. |
1014 | */ | 989 | */ |
1015 | for (i = 1; i < CARL9170_TX_MAX_RATES; i++) { | 990 | for (i = 0; i < CARL9170_TX_MAX_RATES; i++) { |
991 | __le32 phy_set; | ||
1016 | txrate = &info->control.rates[i]; | 992 | txrate = &info->control.rates[i]; |
1017 | if (txrate->idx < 0) | 993 | if (txrate->idx < 0) |
1018 | break; | 994 | break; |
1019 | 995 | ||
996 | phy_set = carl9170_tx_physet(ar, info, txrate); | ||
997 | if (i == 0) { | ||
998 | /* first rate - part of the hw's frame header */ | ||
999 | txc->f.phy_control = phy_set; | ||
1000 | |||
1001 | if (ampdu && txrate->flags & IEEE80211_TX_RC_MCS) | ||
1002 | mac_tmp |= cpu_to_le16(AR9170_TX_MAC_AGGR); | ||
1003 | if (carl9170_tx_rts_check(ar, txrate, ampdu, no_ack)) | ||
1004 | mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS); | ||
1005 | else if (carl9170_tx_cts_check(ar, txrate)) | ||
1006 | mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS); | ||
1007 | |||
1008 | } else { | ||
1009 | /* fallback rates are stored in the firmware's | ||
1010 | * retry rate set array. | ||
1011 | */ | ||
1012 | txc->s.rr[i - 1] = phy_set; | ||
1013 | } | ||
1014 | |||
1020 | SET_VAL(CARL9170_TX_SUPER_RI_TRIES, txc->s.ri[i], | 1015 | SET_VAL(CARL9170_TX_SUPER_RI_TRIES, txc->s.ri[i], |
1021 | txrate->count); | 1016 | txrate->count); |
1022 | 1017 | ||
@@ -1027,21 +1022,13 @@ static int carl9170_tx_prepare(struct ar9170 *ar, | |||
1027 | txc->s.ri[i] |= (AR9170_TX_MAC_PROT_CTS << | 1022 | txc->s.ri[i] |= (AR9170_TX_MAC_PROT_CTS << |
1028 | CARL9170_TX_SUPER_RI_ERP_PROT_S); | 1023 | CARL9170_TX_SUPER_RI_ERP_PROT_S); |
1029 | 1024 | ||
1030 | txc->s.rr[i - 1] = carl9170_tx_physet(ar, info, txrate); | 1025 | if (ampdu && (txrate->flags & IEEE80211_TX_RC_MCS)) |
1026 | txc->s.ri[i] |= CARL9170_TX_SUPER_RI_AMPDU; | ||
1031 | } | 1027 | } |
1032 | 1028 | ||
1033 | txrate = &info->control.rates[0]; | ||
1034 | SET_VAL(CARL9170_TX_SUPER_RI_TRIES, txc->s.ri[0], txrate->count); | ||
1035 | |||
1036 | if (carl9170_tx_rts_check(ar, txrate, ampdu, no_ack)) | ||
1037 | mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS); | ||
1038 | else if (carl9170_tx_cts_check(ar, txrate)) | ||
1039 | mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS); | ||
1040 | |||
1041 | txc->s.len = cpu_to_le16(skb->len); | 1029 | txc->s.len = cpu_to_le16(skb->len); |
1042 | txc->f.length = cpu_to_le16(len + FCS_LEN); | 1030 | txc->f.length = cpu_to_le16(len + FCS_LEN); |
1043 | txc->f.mac_control = mac_tmp; | 1031 | txc->f.mac_control = mac_tmp; |
1044 | txc->f.phy_control = carl9170_tx_physet(ar, info, txrate); | ||
1045 | 1032 | ||
1046 | arinfo = (void *)info->rate_driver_data; | 1033 | arinfo = (void *)info->rate_driver_data; |
1047 | arinfo->timeout = jiffies; | 1034 | arinfo->timeout = jiffies; |
@@ -1381,9 +1368,9 @@ static void carl9170_tx(struct ar9170 *ar) | |||
1381 | } | 1368 | } |
1382 | 1369 | ||
1383 | static bool carl9170_tx_ampdu_queue(struct ar9170 *ar, | 1370 | static bool carl9170_tx_ampdu_queue(struct ar9170 *ar, |
1384 | struct ieee80211_sta *sta, struct sk_buff *skb) | 1371 | struct ieee80211_sta *sta, struct sk_buff *skb, |
1372 | struct ieee80211_tx_info *txinfo) | ||
1385 | { | 1373 | { |
1386 | struct _carl9170_tx_superframe *super = (void *) skb->data; | ||
1387 | struct carl9170_sta_info *sta_info; | 1374 | struct carl9170_sta_info *sta_info; |
1388 | struct carl9170_sta_tid *agg; | 1375 | struct carl9170_sta_tid *agg; |
1389 | struct sk_buff *iter; | 1376 | struct sk_buff *iter; |
@@ -1450,7 +1437,7 @@ err_unlock: | |||
1450 | 1437 | ||
1451 | err_unlock_rcu: | 1438 | err_unlock_rcu: |
1452 | rcu_read_unlock(); | 1439 | rcu_read_unlock(); |
1453 | super->f.mac_control &= ~cpu_to_le16(AR9170_TX_MAC_AGGR); | 1440 | txinfo->flags &= ~IEEE80211_TX_CTL_AMPDU; |
1454 | carl9170_tx_status(ar, skb, false); | 1441 | carl9170_tx_status(ar, skb, false); |
1455 | ar->tx_dropped++; | 1442 | ar->tx_dropped++; |
1456 | return false; | 1443 | return false; |
@@ -1492,7 +1479,7 @@ void carl9170_op_tx(struct ieee80211_hw *hw, | |||
1492 | * sta == NULL checks are redundant in this | 1479 | * sta == NULL checks are redundant in this |
1493 | * special case. | 1480 | * special case. |
1494 | */ | 1481 | */ |
1495 | run = carl9170_tx_ampdu_queue(ar, sta, skb); | 1482 | run = carl9170_tx_ampdu_queue(ar, sta, skb, info); |
1496 | if (run) | 1483 | if (run) |
1497 | carl9170_tx_ampdu(ar); | 1484 | carl9170_tx_ampdu(ar); |
1498 | 1485 | ||
diff --git a/drivers/net/wireless/ath/wil6210/Makefile b/drivers/net/wireless/ath/wil6210/Makefile index 9396dc9fe3c5..d288eea0a26a 100644 --- a/drivers/net/wireless/ath/wil6210/Makefile +++ b/drivers/net/wireless/ath/wil6210/Makefile | |||
@@ -9,5 +9,7 @@ wil6210-objs += wmi.o | |||
9 | wil6210-objs += interrupt.o | 9 | wil6210-objs += interrupt.o |
10 | wil6210-objs += txrx.o | 10 | wil6210-objs += txrx.o |
11 | 11 | ||
12 | subdir-ccflags-y += -Werror | 12 | ifeq (, $(findstring -W,$(EXTRA_CFLAGS))) |
13 | subdir-ccflags-y += -Werror | ||
14 | endif | ||
13 | subdir-ccflags-y += -D__CHECK_ENDIAN__ | 15 | subdir-ccflags-y += -D__CHECK_ENDIAN__ |
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 9ecc1968262c..c5d4a87abaaf 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c | |||
@@ -14,16 +14,6 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/netdevice.h> | ||
19 | #include <linux/sched.h> | ||
20 | #include <linux/etherdevice.h> | ||
21 | #include <linux/wireless.h> | ||
22 | #include <linux/ieee80211.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/version.h> | ||
25 | #include <net/cfg80211.h> | ||
26 | |||
27 | #include "wil6210.h" | 17 | #include "wil6210.h" |
28 | #include "wmi.h" | 18 | #include "wmi.h" |
29 | 19 | ||
@@ -292,7 +282,7 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, | |||
292 | 282 | ||
293 | /* WMI_CONNECT_CMD */ | 283 | /* WMI_CONNECT_CMD */ |
294 | memset(&conn, 0, sizeof(conn)); | 284 | memset(&conn, 0, sizeof(conn)); |
295 | switch (bss->capability & 0x03) { | 285 | switch (bss->capability & WLAN_CAPABILITY_DMG_TYPE_MASK) { |
296 | case WLAN_CAPABILITY_DMG_TYPE_AP: | 286 | case WLAN_CAPABILITY_DMG_TYPE_AP: |
297 | conn.network_type = WMI_NETTYPE_INFRA; | 287 | conn.network_type = WMI_NETTYPE_INFRA; |
298 | break; | 288 | break; |
@@ -437,17 +427,18 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy, | |||
437 | if (rc) | 427 | if (rc) |
438 | return rc; | 428 | return rc; |
439 | 429 | ||
440 | rc = wmi_set_channel(wil, channel->hw_value); | ||
441 | if (rc) | ||
442 | return rc; | ||
443 | |||
444 | /* MAC address - pre-requisite for other commands */ | 430 | /* MAC address - pre-requisite for other commands */ |
445 | wmi_set_mac_address(wil, ndev->dev_addr); | 431 | wmi_set_mac_address(wil, ndev->dev_addr); |
446 | 432 | ||
447 | /* IE's */ | 433 | /* IE's */ |
448 | /* bcon 'head IE's are not relevant for 60g band */ | 434 | /* bcon 'head IE's are not relevant for 60g band */ |
449 | wmi_set_ie(wil, WMI_FRAME_BEACON, bcon->beacon_ies_len, | 435 | /* |
450 | bcon->beacon_ies); | 436 | * FW do not form regular beacon, so bcon IE's are not set |
437 | * For the DMG bcon, when it will be supported, bcon IE's will | ||
438 | * be reused; add something like: | ||
439 | * wmi_set_ie(wil, WMI_FRAME_BEACON, bcon->beacon_ies_len, | ||
440 | * bcon->beacon_ies); | ||
441 | */ | ||
451 | wmi_set_ie(wil, WMI_FRAME_PROBE_RESP, bcon->proberesp_ies_len, | 442 | wmi_set_ie(wil, WMI_FRAME_PROBE_RESP, bcon->proberesp_ies_len, |
452 | bcon->proberesp_ies); | 443 | bcon->proberesp_ies); |
453 | wmi_set_ie(wil, WMI_FRAME_ASSOC_RESP, bcon->assocresp_ies_len, | 444 | wmi_set_ie(wil, WMI_FRAME_ASSOC_RESP, bcon->assocresp_ies_len, |
@@ -455,7 +446,8 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy, | |||
455 | 446 | ||
456 | wil->secure_pcp = info->privacy; | 447 | wil->secure_pcp = info->privacy; |
457 | 448 | ||
458 | rc = wmi_set_bcon(wil, info->beacon_interval, wmi_nettype); | 449 | rc = wmi_pcp_start(wil, info->beacon_interval, wmi_nettype, |
450 | channel->hw_value); | ||
459 | if (rc) | 451 | if (rc) |
460 | return rc; | 452 | return rc; |
461 | 453 | ||
@@ -472,11 +464,8 @@ static int wil_cfg80211_stop_ap(struct wiphy *wiphy, | |||
472 | { | 464 | { |
473 | int rc = 0; | 465 | int rc = 0; |
474 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | 466 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); |
475 | struct wireless_dev *wdev = ndev->ieee80211_ptr; | ||
476 | u8 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype); | ||
477 | 467 | ||
478 | /* To stop beaconing, set BI to 0 */ | 468 | rc = wmi_pcp_stop(wil); |
479 | rc = wmi_set_bcon(wil, 0, wmi_nettype); | ||
480 | 469 | ||
481 | return rc; | 470 | return rc; |
482 | } | 471 | } |
diff --git a/drivers/net/wireless/ath/wil6210/dbg_hexdump.h b/drivers/net/wireless/ath/wil6210/dbg_hexdump.h deleted file mode 100644 index e5712f026c47..000000000000 --- a/drivers/net/wireless/ath/wil6210/dbg_hexdump.h +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | #ifndef WIL_DBG_HEXDUMP_H_ | ||
2 | #define WIL_DBG_HEXDUMP_H_ | ||
3 | |||
4 | #include <linux/printk.h> | ||
5 | #include <linux/dynamic_debug.h> | ||
6 | |||
7 | #if defined(CONFIG_DYNAMIC_DEBUG) | ||
8 | #define wil_print_hex_dump_debug(prefix_str, prefix_type, rowsize, \ | ||
9 | groupsize, buf, len, ascii) \ | ||
10 | dynamic_hex_dump(prefix_str, prefix_type, rowsize, \ | ||
11 | groupsize, buf, len, ascii) | ||
12 | |||
13 | #else /* defined(CONFIG_DYNAMIC_DEBUG) */ | ||
14 | #define wil_print_hex_dump_debug(prefix_str, prefix_type, rowsize, \ | ||
15 | groupsize, buf, len, ascii) \ | ||
16 | print_hex_dump(KERN_DEBUG, prefix_str, prefix_type, rowsize, \ | ||
17 | groupsize, buf, len, ascii) | ||
18 | #endif /* defined(CONFIG_DYNAMIC_DEBUG) */ | ||
19 | |||
20 | #endif /* WIL_DBG_HEXDUMP_H_ */ | ||
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index 65fc9683bfd8..4be07f5e22b9 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c | |||
@@ -312,14 +312,6 @@ static const struct file_operations fops_memread = { | |||
312 | .llseek = seq_lseek, | 312 | .llseek = seq_lseek, |
313 | }; | 313 | }; |
314 | 314 | ||
315 | static int wil_default_open(struct inode *inode, struct file *file) | ||
316 | { | ||
317 | if (inode->i_private) | ||
318 | file->private_data = inode->i_private; | ||
319 | |||
320 | return 0; | ||
321 | } | ||
322 | |||
323 | static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf, | 315 | static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf, |
324 | size_t count, loff_t *ppos) | 316 | size_t count, loff_t *ppos) |
325 | { | 317 | { |
@@ -361,7 +353,7 @@ static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf, | |||
361 | 353 | ||
362 | static const struct file_operations fops_ioblob = { | 354 | static const struct file_operations fops_ioblob = { |
363 | .read = wil_read_file_ioblob, | 355 | .read = wil_read_file_ioblob, |
364 | .open = wil_default_open, | 356 | .open = simple_open, |
365 | .llseek = default_llseek, | 357 | .llseek = default_llseek, |
366 | }; | 358 | }; |
367 | 359 | ||
@@ -396,7 +388,7 @@ static ssize_t wil_write_file_reset(struct file *file, const char __user *buf, | |||
396 | 388 | ||
397 | static const struct file_operations fops_reset = { | 389 | static const struct file_operations fops_reset = { |
398 | .write = wil_write_file_reset, | 390 | .write = wil_write_file_reset, |
399 | .open = wil_default_open, | 391 | .open = simple_open, |
400 | }; | 392 | }; |
401 | /*---------Tx descriptor------------*/ | 393 | /*---------Tx descriptor------------*/ |
402 | 394 | ||
@@ -526,7 +518,50 @@ static ssize_t wil_write_file_ssid(struct file *file, const char __user *buf, | |||
526 | static const struct file_operations fops_ssid = { | 518 | static const struct file_operations fops_ssid = { |
527 | .read = wil_read_file_ssid, | 519 | .read = wil_read_file_ssid, |
528 | .write = wil_write_file_ssid, | 520 | .write = wil_write_file_ssid, |
529 | .open = wil_default_open, | 521 | .open = simple_open, |
522 | }; | ||
523 | |||
524 | /*---------temp------------*/ | ||
525 | static void print_temp(struct seq_file *s, const char *prefix, u32 t) | ||
526 | { | ||
527 | switch (t) { | ||
528 | case 0: | ||
529 | case ~(u32)0: | ||
530 | seq_printf(s, "%s N/A\n", prefix); | ||
531 | break; | ||
532 | default: | ||
533 | seq_printf(s, "%s %d.%03d\n", prefix, t / 1000, t % 1000); | ||
534 | break; | ||
535 | } | ||
536 | } | ||
537 | |||
538 | static int wil_temp_debugfs_show(struct seq_file *s, void *data) | ||
539 | { | ||
540 | struct wil6210_priv *wil = s->private; | ||
541 | u32 t_m, t_r; | ||
542 | |||
543 | int rc = wmi_get_temperature(wil, &t_m, &t_r); | ||
544 | if (rc) { | ||
545 | seq_printf(s, "Failed\n"); | ||
546 | return 0; | ||
547 | } | ||
548 | |||
549 | print_temp(s, "MAC temperature :", t_m); | ||
550 | print_temp(s, "Radio temperature :", t_r); | ||
551 | |||
552 | return 0; | ||
553 | } | ||
554 | |||
555 | static int wil_temp_seq_open(struct inode *inode, struct file *file) | ||
556 | { | ||
557 | return single_open(file, wil_temp_debugfs_show, inode->i_private); | ||
558 | } | ||
559 | |||
560 | static const struct file_operations fops_temp = { | ||
561 | .open = wil_temp_seq_open, | ||
562 | .release = single_release, | ||
563 | .read = seq_read, | ||
564 | .llseek = seq_lseek, | ||
530 | }; | 565 | }; |
531 | 566 | ||
532 | /*----------------*/ | 567 | /*----------------*/ |
@@ -563,6 +598,7 @@ int wil6210_debugfs_init(struct wil6210_priv *wil) | |||
563 | debugfs_create_file("mem_val", S_IRUGO, dbg, wil, &fops_memread); | 598 | debugfs_create_file("mem_val", S_IRUGO, dbg, wil, &fops_memread); |
564 | 599 | ||
565 | debugfs_create_file("reset", S_IWUSR, dbg, wil, &fops_reset); | 600 | debugfs_create_file("reset", S_IWUSR, dbg, wil, &fops_reset); |
601 | debugfs_create_file("temp", S_IRUGO, dbg, wil, &fops_temp); | ||
566 | 602 | ||
567 | wil->rgf_blob.data = (void * __force)wil->csr + 0; | 603 | wil->rgf_blob.data = (void * __force)wil->csr + 0; |
568 | wil->rgf_blob.size = 0xa000; | 604 | wil->rgf_blob.size = 0xa000; |
diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c index dc97e7b2609c..e3c1e7684f9c 100644 --- a/drivers/net/wireless/ath/wil6210/interrupt.c +++ b/drivers/net/wireless/ath/wil6210/interrupt.c | |||
@@ -240,6 +240,15 @@ static void wil_notify_fw_error(struct wil6210_priv *wil) | |||
240 | kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp); | 240 | kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp); |
241 | } | 241 | } |
242 | 242 | ||
243 | static void wil_cache_mbox_regs(struct wil6210_priv *wil) | ||
244 | { | ||
245 | /* make shadow copy of registers that should not change on run time */ | ||
246 | wil_memcpy_fromio_32(&wil->mbox_ctl, wil->csr + HOST_MBOX, | ||
247 | sizeof(struct wil6210_mbox_ctl)); | ||
248 | wil_mbox_ring_le2cpus(&wil->mbox_ctl.rx); | ||
249 | wil_mbox_ring_le2cpus(&wil->mbox_ctl.tx); | ||
250 | } | ||
251 | |||
243 | static irqreturn_t wil6210_irq_misc(int irq, void *cookie) | 252 | static irqreturn_t wil6210_irq_misc(int irq, void *cookie) |
244 | { | 253 | { |
245 | struct wil6210_priv *wil = cookie; | 254 | struct wil6210_priv *wil = cookie; |
@@ -257,14 +266,19 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie) | |||
257 | wil6210_mask_irq_misc(wil); | 266 | wil6210_mask_irq_misc(wil); |
258 | 267 | ||
259 | if (isr & ISR_MISC_FW_ERROR) { | 268 | if (isr & ISR_MISC_FW_ERROR) { |
260 | wil_dbg_irq(wil, "IRQ: Firmware error\n"); | 269 | wil_err(wil, "Firmware error detected\n"); |
261 | clear_bit(wil_status_fwready, &wil->status); | 270 | clear_bit(wil_status_fwready, &wil->status); |
262 | wil_notify_fw_error(wil); | 271 | /* |
263 | isr &= ~ISR_MISC_FW_ERROR; | 272 | * do not clear @isr here - we do 2-nd part in thread |
273 | * there, user space get notified, and it should be done | ||
274 | * in non-atomic context | ||
275 | */ | ||
264 | } | 276 | } |
265 | 277 | ||
266 | if (isr & ISR_MISC_FW_READY) { | 278 | if (isr & ISR_MISC_FW_READY) { |
267 | wil_dbg_irq(wil, "IRQ: FW ready\n"); | 279 | wil_dbg_irq(wil, "IRQ: FW ready\n"); |
280 | wil_cache_mbox_regs(wil); | ||
281 | set_bit(wil_status_reset_done, &wil->status); | ||
268 | /** | 282 | /** |
269 | * Actual FW ready indicated by the | 283 | * Actual FW ready indicated by the |
270 | * WMI_FW_READY_EVENTID | 284 | * WMI_FW_READY_EVENTID |
@@ -289,6 +303,11 @@ static irqreturn_t wil6210_irq_misc_thread(int irq, void *cookie) | |||
289 | 303 | ||
290 | wil_dbg_irq(wil, "Thread ISR MISC 0x%08x\n", isr); | 304 | wil_dbg_irq(wil, "Thread ISR MISC 0x%08x\n", isr); |
291 | 305 | ||
306 | if (isr & ISR_MISC_FW_ERROR) { | ||
307 | wil_notify_fw_error(wil); | ||
308 | isr &= ~ISR_MISC_FW_ERROR; | ||
309 | } | ||
310 | |||
292 | if (isr & ISR_MISC_MBOX_EVT) { | 311 | if (isr & ISR_MISC_MBOX_EVT) { |
293 | wil_dbg_irq(wil, "MBOX event\n"); | 312 | wil_dbg_irq(wil, "MBOX event\n"); |
294 | wmi_recv_cmd(wil); | 313 | wmi_recv_cmd(wil); |
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 761c389586d4..a0478e2f6868 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c | |||
@@ -14,12 +14,6 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/netdevice.h> | ||
19 | #include <linux/sched.h> | ||
20 | #include <linux/ieee80211.h> | ||
21 | #include <linux/wireless.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/moduleparam.h> | 17 | #include <linux/moduleparam.h> |
24 | #include <linux/if_arp.h> | 18 | #include <linux/if_arp.h> |
25 | 19 | ||
@@ -109,13 +103,24 @@ static void wil_connect_timer_fn(ulong x) | |||
109 | schedule_work(&wil->disconnect_worker); | 103 | schedule_work(&wil->disconnect_worker); |
110 | } | 104 | } |
111 | 105 | ||
112 | static void wil_cache_mbox_regs(struct wil6210_priv *wil) | 106 | static void wil_connect_worker(struct work_struct *work) |
113 | { | 107 | { |
114 | /* make shadow copy of registers that should not change on run time */ | 108 | int rc; |
115 | wil_memcpy_fromio_32(&wil->mbox_ctl, wil->csr + HOST_MBOX, | 109 | struct wil6210_priv *wil = container_of(work, struct wil6210_priv, |
116 | sizeof(struct wil6210_mbox_ctl)); | 110 | connect_worker); |
117 | wil_mbox_ring_le2cpus(&wil->mbox_ctl.rx); | 111 | int cid = wil->pending_connect_cid; |
118 | wil_mbox_ring_le2cpus(&wil->mbox_ctl.tx); | 112 | |
113 | if (cid < 0) { | ||
114 | wil_err(wil, "No connection pending\n"); | ||
115 | return; | ||
116 | } | ||
117 | |||
118 | wil_dbg_wmi(wil, "Configure for connection CID %d\n", cid); | ||
119 | |||
120 | rc = wil_vring_init_tx(wil, 0, WIL6210_TX_RING_SIZE, cid, 0); | ||
121 | wil->pending_connect_cid = -1; | ||
122 | if (rc == 0) | ||
123 | wil_link_on(wil); | ||
119 | } | 124 | } |
120 | 125 | ||
121 | int wil_priv_init(struct wil6210_priv *wil) | 126 | int wil_priv_init(struct wil6210_priv *wil) |
@@ -130,7 +135,7 @@ int wil_priv_init(struct wil6210_priv *wil) | |||
130 | wil->pending_connect_cid = -1; | 135 | wil->pending_connect_cid = -1; |
131 | setup_timer(&wil->connect_timer, wil_connect_timer_fn, (ulong)wil); | 136 | setup_timer(&wil->connect_timer, wil_connect_timer_fn, (ulong)wil); |
132 | 137 | ||
133 | INIT_WORK(&wil->wmi_connect_worker, wmi_connect_worker); | 138 | INIT_WORK(&wil->connect_worker, wil_connect_worker); |
134 | INIT_WORK(&wil->disconnect_worker, wil_disconnect_worker); | 139 | INIT_WORK(&wil->disconnect_worker, wil_disconnect_worker); |
135 | INIT_WORK(&wil->wmi_event_worker, wmi_event_worker); | 140 | INIT_WORK(&wil->wmi_event_worker, wmi_event_worker); |
136 | 141 | ||
@@ -147,8 +152,6 @@ int wil_priv_init(struct wil6210_priv *wil) | |||
147 | return -EAGAIN; | 152 | return -EAGAIN; |
148 | } | 153 | } |
149 | 154 | ||
150 | wil_cache_mbox_regs(wil); | ||
151 | |||
152 | return 0; | 155 | return 0; |
153 | } | 156 | } |
154 | 157 | ||
@@ -185,15 +188,11 @@ static void wil_target_reset(struct wil6210_priv *wil) | |||
185 | W(RGF_USER_MAC_CPU_0, BIT(1)); /* mac_cpu_man_rst */ | 188 | W(RGF_USER_MAC_CPU_0, BIT(1)); /* mac_cpu_man_rst */ |
186 | W(RGF_USER_USER_CPU_0, BIT(1)); /* user_cpu_man_rst */ | 189 | W(RGF_USER_USER_CPU_0, BIT(1)); /* user_cpu_man_rst */ |
187 | 190 | ||
188 | msleep(100); | ||
189 | |||
190 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0xFE000000); | 191 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0xFE000000); |
191 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0x0000003F); | 192 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0x0000003F); |
192 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000170); | 193 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000170); |
193 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0xFFE7FC00); | 194 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0xFFE7FC00); |
194 | 195 | ||
195 | msleep(100); | ||
196 | |||
197 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0); | 196 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0); |
198 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0); | 197 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0); |
199 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0); | 198 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0); |
@@ -203,12 +202,6 @@ static void wil_target_reset(struct wil6210_priv *wil) | |||
203 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00000080); | 202 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00000080); |
204 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0); | 203 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0); |
205 | 204 | ||
206 | msleep(2000); | ||
207 | |||
208 | W(RGF_USER_USER_CPU_0, BIT(0)); /* user_cpu_man_de_rst */ | ||
209 | |||
210 | msleep(2000); | ||
211 | |||
212 | wil_dbg_misc(wil, "Reset completed\n"); | 205 | wil_dbg_misc(wil, "Reset completed\n"); |
213 | 206 | ||
214 | #undef W | 207 | #undef W |
@@ -265,8 +258,6 @@ int wil_reset(struct wil6210_priv *wil) | |||
265 | wil->pending_connect_cid = -1; | 258 | wil->pending_connect_cid = -1; |
266 | INIT_COMPLETION(wil->wmi_ready); | 259 | INIT_COMPLETION(wil->wmi_ready); |
267 | 260 | ||
268 | wil_cache_mbox_regs(wil); | ||
269 | |||
270 | /* TODO: release MAC reset */ | 261 | /* TODO: release MAC reset */ |
271 | wil6210_enable_irq(wil); | 262 | wil6210_enable_irq(wil); |
272 | 263 | ||
@@ -352,9 +343,9 @@ static int __wil_up(struct wil6210_priv *wil) | |||
352 | wil_err(wil, "SSID not set\n"); | 343 | wil_err(wil, "SSID not set\n"); |
353 | return -EINVAL; | 344 | return -EINVAL; |
354 | } | 345 | } |
355 | wmi_set_ssid(wil, wdev->ssid_len, wdev->ssid); | 346 | rc = wmi_set_ssid(wil, wdev->ssid_len, wdev->ssid); |
356 | if (channel) | 347 | if (rc) |
357 | wmi_set_channel(wil, channel->hw_value); | 348 | return rc; |
358 | break; | 349 | break; |
359 | default: | 350 | default: |
360 | break; | 351 | break; |
@@ -364,9 +355,12 @@ static int __wil_up(struct wil6210_priv *wil) | |||
364 | wmi_set_mac_address(wil, ndev->dev_addr); | 355 | wmi_set_mac_address(wil, ndev->dev_addr); |
365 | 356 | ||
366 | /* Set up beaconing if required. */ | 357 | /* Set up beaconing if required. */ |
367 | rc = wmi_set_bcon(wil, bi, wmi_nettype); | 358 | if (bi > 0) { |
368 | if (rc) | 359 | rc = wmi_pcp_start(wil, bi, wmi_nettype, |
369 | return rc; | 360 | (channel ? channel->hw_value : 0)); |
361 | if (rc) | ||
362 | return rc; | ||
363 | } | ||
370 | 364 | ||
371 | /* Rx VRING. After MAC and beacon */ | 365 | /* Rx VRING. After MAC and beacon */ |
372 | wil_rx_init(wil); | 366 | wil_rx_init(wil); |
diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c index 8ce2e33dce20..098a8ec6b841 100644 --- a/drivers/net/wireless/ath/wil6210/netdev.c +++ b/drivers/net/wireless/ath/wil6210/netdev.c | |||
@@ -14,10 +14,7 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/netdevice.h> | ||
19 | #include <linux/etherdevice.h> | 17 | #include <linux/etherdevice.h> |
20 | #include <linux/slab.h> | ||
21 | 18 | ||
22 | #include "wil6210.h" | 19 | #include "wil6210.h" |
23 | 20 | ||
diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c index 81c35c6e3832..eb1dc7ad80fb 100644 --- a/drivers/net/wireless/ath/wil6210/pcie_bus.c +++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c | |||
@@ -14,10 +14,7 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/module.h> | 17 | #include <linux/module.h> |
19 | #include <linux/slab.h> | ||
20 | #include <linux/netdevice.h> | ||
21 | #include <linux/debugfs.h> | 18 | #include <linux/debugfs.h> |
22 | #include <linux/pci.h> | 19 | #include <linux/pci.h> |
23 | #include <linux/moduleparam.h> | 20 | #include <linux/moduleparam.h> |
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index 55dd95f9824f..79d4e3271b00 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c | |||
@@ -14,10 +14,7 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/netdevice.h> | ||
19 | #include <linux/etherdevice.h> | 17 | #include <linux/etherdevice.h> |
20 | #include <linux/hardirq.h> | ||
21 | #include <net/ieee80211_radiotap.h> | 18 | #include <net/ieee80211_radiotap.h> |
22 | #include <linux/if_arp.h> | 19 | #include <linux/if_arp.h> |
23 | #include <linux/moduleparam.h> | 20 | #include <linux/moduleparam.h> |
@@ -558,7 +555,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, | |||
558 | if (rc) | 555 | if (rc) |
559 | goto out_free; | 556 | goto out_free; |
560 | 557 | ||
561 | if (reply.cmd.status != WMI_VRING_CFG_SUCCESS) { | 558 | if (reply.cmd.status != WMI_FW_STATUS_SUCCESS) { |
562 | wil_err(wil, "Tx config failed, status 0x%02x\n", | 559 | wil_err(wil, "Tx config failed, status 0x%02x\n", |
563 | reply.cmd.status); | 560 | reply.cmd.status); |
564 | rc = -EINVAL; | 561 | rc = -EINVAL; |
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index aea961ff8f08..8f76ecd8a7e5 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h | |||
@@ -21,8 +21,6 @@ | |||
21 | #include <linux/wireless.h> | 21 | #include <linux/wireless.h> |
22 | #include <net/cfg80211.h> | 22 | #include <net/cfg80211.h> |
23 | 23 | ||
24 | #include "dbg_hexdump.h" | ||
25 | |||
26 | #define WIL_NAME "wil6210" | 24 | #define WIL_NAME "wil6210" |
27 | 25 | ||
28 | /** | 26 | /** |
@@ -188,6 +186,7 @@ enum { /* for wil6210_priv.status */ | |||
188 | wil_status_fwready = 0, | 186 | wil_status_fwready = 0, |
189 | wil_status_fwconnected, | 187 | wil_status_fwconnected, |
190 | wil_status_dontscan, | 188 | wil_status_dontscan, |
189 | wil_status_reset_done, | ||
191 | wil_status_irqen, /* FIXME: interrupts enabled - for debug */ | 190 | wil_status_irqen, /* FIXME: interrupts enabled - for debug */ |
192 | }; | 191 | }; |
193 | 192 | ||
@@ -210,6 +209,8 @@ struct wil6210_priv { | |||
210 | struct wireless_dev *wdev; | 209 | struct wireless_dev *wdev; |
211 | void __iomem *csr; | 210 | void __iomem *csr; |
212 | ulong status; | 211 | ulong status; |
212 | u32 fw_version; | ||
213 | u8 n_mids; /* number of additional MIDs as reported by FW */ | ||
213 | /* profile */ | 214 | /* profile */ |
214 | u32 monitor_flags; | 215 | u32 monitor_flags; |
215 | u32 secure_pcp; /* create secure PCP? */ | 216 | u32 secure_pcp; /* create secure PCP? */ |
@@ -227,7 +228,7 @@ struct wil6210_priv { | |||
227 | struct workqueue_struct *wmi_wq; /* for deferred calls */ | 228 | struct workqueue_struct *wmi_wq; /* for deferred calls */ |
228 | struct work_struct wmi_event_worker; | 229 | struct work_struct wmi_event_worker; |
229 | struct workqueue_struct *wmi_wq_conn; /* for connect worker */ | 230 | struct workqueue_struct *wmi_wq_conn; /* for connect worker */ |
230 | struct work_struct wmi_connect_worker; | 231 | struct work_struct connect_worker; |
231 | struct work_struct disconnect_worker; | 232 | struct work_struct disconnect_worker; |
232 | struct timer_list connect_timer; | 233 | struct timer_list connect_timer; |
233 | int pending_connect_cid; | 234 | int pending_connect_cid; |
@@ -277,13 +278,13 @@ struct wil6210_priv { | |||
277 | 278 | ||
278 | #define wil_hex_dump_txrx(prefix_str, prefix_type, rowsize, \ | 279 | #define wil_hex_dump_txrx(prefix_str, prefix_type, rowsize, \ |
279 | groupsize, buf, len, ascii) \ | 280 | groupsize, buf, len, ascii) \ |
280 | wil_print_hex_dump_debug("DBG[TXRX]" prefix_str,\ | 281 | print_hex_dump_debug("DBG[TXRX]" prefix_str,\ |
281 | prefix_type, rowsize, \ | 282 | prefix_type, rowsize, \ |
282 | groupsize, buf, len, ascii) | 283 | groupsize, buf, len, ascii) |
283 | 284 | ||
284 | #define wil_hex_dump_wmi(prefix_str, prefix_type, rowsize, \ | 285 | #define wil_hex_dump_wmi(prefix_str, prefix_type, rowsize, \ |
285 | groupsize, buf, len, ascii) \ | 286 | groupsize, buf, len, ascii) \ |
286 | wil_print_hex_dump_debug("DBG[ WMI]" prefix_str,\ | 287 | print_hex_dump_debug("DBG[ WMI]" prefix_str,\ |
287 | prefix_type, rowsize, \ | 288 | prefix_type, rowsize, \ |
288 | groupsize, buf, len, ascii) | 289 | groupsize, buf, len, ascii) |
289 | 290 | ||
@@ -313,7 +314,6 @@ int wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len); | |||
313 | void wmi_recv_cmd(struct wil6210_priv *wil); | 314 | void wmi_recv_cmd(struct wil6210_priv *wil); |
314 | int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len, | 315 | int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len, |
315 | u16 reply_id, void *reply, u8 reply_size, int to_msec); | 316 | u16 reply_id, void *reply, u8 reply_size, int to_msec); |
316 | void wmi_connect_worker(struct work_struct *work); | ||
317 | void wmi_event_worker(struct work_struct *work); | 317 | void wmi_event_worker(struct work_struct *work); |
318 | void wmi_event_flush(struct wil6210_priv *wil); | 318 | void wmi_event_flush(struct wil6210_priv *wil); |
319 | int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid); | 319 | int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid); |
@@ -328,6 +328,8 @@ int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index, | |||
328 | int wmi_echo(struct wil6210_priv *wil); | 328 | int wmi_echo(struct wil6210_priv *wil); |
329 | int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie); | 329 | int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie); |
330 | int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring); | 330 | int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring); |
331 | int wmi_p2p_cfg(struct wil6210_priv *wil, int channel); | ||
332 | int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_m, u32 *t_r); | ||
331 | 333 | ||
332 | int wil6210_init_irq(struct wil6210_priv *wil, int irq); | 334 | int wil6210_init_irq(struct wil6210_priv *wil, int irq); |
333 | void wil6210_fini_irq(struct wil6210_priv *wil, int irq); | 335 | void wil6210_fini_irq(struct wil6210_priv *wil, int irq); |
@@ -341,7 +343,8 @@ struct wireless_dev *wil_cfg80211_init(struct device *dev); | |||
341 | void wil_wdev_free(struct wil6210_priv *wil); | 343 | void wil_wdev_free(struct wil6210_priv *wil); |
342 | 344 | ||
343 | int wmi_set_mac_address(struct wil6210_priv *wil, void *addr); | 345 | int wmi_set_mac_address(struct wil6210_priv *wil, void *addr); |
344 | int wmi_set_bcon(struct wil6210_priv *wil, int bi, u8 wmi_nettype); | 346 | int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, u8 chan); |
347 | int wmi_pcp_stop(struct wil6210_priv *wil); | ||
345 | void wil6210_disconnect(struct wil6210_priv *wil, void *bssid); | 348 | void wil6210_disconnect(struct wil6210_priv *wil, void *bssid); |
346 | 349 | ||
347 | int wil_rx_init(struct wil6210_priv *wil); | 350 | int wil_rx_init(struct wil6210_priv *wil); |
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 0bb3b76b4b58..45b04e383f9a 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c | |||
@@ -14,9 +14,6 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/pci.h> | ||
18 | #include <linux/io.h> | ||
19 | #include <linux/list.h> | ||
20 | #include <linux/etherdevice.h> | 17 | #include <linux/etherdevice.h> |
21 | #include <linux/if_arp.h> | 18 | #include <linux/if_arp.h> |
22 | 19 | ||
@@ -272,16 +269,18 @@ static void wmi_evt_ready(struct wil6210_priv *wil, int id, void *d, int len) | |||
272 | struct net_device *ndev = wil_to_ndev(wil); | 269 | struct net_device *ndev = wil_to_ndev(wil); |
273 | struct wireless_dev *wdev = wil->wdev; | 270 | struct wireless_dev *wdev = wil->wdev; |
274 | struct wmi_ready_event *evt = d; | 271 | struct wmi_ready_event *evt = d; |
275 | u32 ver = le32_to_cpu(evt->sw_version); | 272 | wil->fw_version = le32_to_cpu(evt->sw_version); |
273 | wil->n_mids = evt->numof_additional_mids; | ||
276 | 274 | ||
277 | wil_dbg_wmi(wil, "FW ver. %d; MAC %pM\n", ver, evt->mac); | 275 | wil_dbg_wmi(wil, "FW ver. %d; MAC %pM; %d MID's\n", wil->fw_version, |
276 | evt->mac, wil->n_mids); | ||
278 | 277 | ||
279 | if (!is_valid_ether_addr(ndev->dev_addr)) { | 278 | if (!is_valid_ether_addr(ndev->dev_addr)) { |
280 | memcpy(ndev->dev_addr, evt->mac, ETH_ALEN); | 279 | memcpy(ndev->dev_addr, evt->mac, ETH_ALEN); |
281 | memcpy(ndev->perm_addr, evt->mac, ETH_ALEN); | 280 | memcpy(ndev->perm_addr, evt->mac, ETH_ALEN); |
282 | } | 281 | } |
283 | snprintf(wdev->wiphy->fw_version, sizeof(wdev->wiphy->fw_version), | 282 | snprintf(wdev->wiphy->fw_version, sizeof(wdev->wiphy->fw_version), |
284 | "%d", ver); | 283 | "%d", wil->fw_version); |
285 | } | 284 | } |
286 | 285 | ||
287 | static void wmi_evt_fw_ready(struct wil6210_priv *wil, int id, void *d, | 286 | static void wmi_evt_fw_ready(struct wil6210_priv *wil, int id, void *d, |
@@ -324,17 +323,9 @@ static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len) | |||
324 | 323 | ||
325 | if (ieee80211_is_beacon(fc) || ieee80211_is_probe_resp(fc)) { | 324 | if (ieee80211_is_beacon(fc) || ieee80211_is_probe_resp(fc)) { |
326 | struct cfg80211_bss *bss; | 325 | struct cfg80211_bss *bss; |
327 | u64 tsf = le64_to_cpu(rx_mgmt_frame->u.beacon.timestamp); | 326 | |
328 | u16 cap = le16_to_cpu(rx_mgmt_frame->u.beacon.capab_info); | 327 | bss = cfg80211_inform_bss_frame(wiphy, channel, rx_mgmt_frame, |
329 | u16 bi = le16_to_cpu(rx_mgmt_frame->u.beacon.beacon_int); | 328 | d_len, signal, GFP_KERNEL); |
330 | const u8 *ie_buf = rx_mgmt_frame->u.beacon.variable; | ||
331 | size_t ie_len = d_len - offsetof(struct ieee80211_mgmt, | ||
332 | u.beacon.variable); | ||
333 | wil_dbg_wmi(wil, "Capability info : 0x%04x\n", cap); | ||
334 | |||
335 | bss = cfg80211_inform_bss(wiphy, channel, rx_mgmt_frame->bssid, | ||
336 | tsf, cap, bi, ie_buf, ie_len, | ||
337 | signal, GFP_KERNEL); | ||
338 | if (bss) { | 329 | if (bss) { |
339 | wil_dbg_wmi(wil, "Added BSS %pM\n", | 330 | wil_dbg_wmi(wil, "Added BSS %pM\n", |
340 | rx_mgmt_frame->bssid); | 331 | rx_mgmt_frame->bssid); |
@@ -342,6 +333,9 @@ static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len) | |||
342 | } else { | 333 | } else { |
343 | wil_err(wil, "cfg80211_inform_bss() failed\n"); | 334 | wil_err(wil, "cfg80211_inform_bss() failed\n"); |
344 | } | 335 | } |
336 | } else { | ||
337 | cfg80211_rx_mgmt(wil->wdev, freq, signal, | ||
338 | (void *)rx_mgmt_frame, d_len, GFP_KERNEL); | ||
345 | } | 339 | } |
346 | } | 340 | } |
347 | 341 | ||
@@ -443,7 +437,7 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) | |||
443 | memcpy(wil->dst_addr[0], evt->bssid, ETH_ALEN); | 437 | memcpy(wil->dst_addr[0], evt->bssid, ETH_ALEN); |
444 | 438 | ||
445 | wil->pending_connect_cid = evt->cid; | 439 | wil->pending_connect_cid = evt->cid; |
446 | queue_work(wil->wmi_wq_conn, &wil->wmi_connect_worker); | 440 | queue_work(wil->wmi_wq_conn, &wil->connect_worker); |
447 | } | 441 | } |
448 | 442 | ||
449 | static void wmi_evt_disconnect(struct wil6210_priv *wil, int id, | 443 | static void wmi_evt_disconnect(struct wil6210_priv *wil, int id, |
@@ -528,6 +522,37 @@ static void wmi_evt_eapol_rx(struct wil6210_priv *wil, int id, | |||
528 | } | 522 | } |
529 | } | 523 | } |
530 | 524 | ||
525 | static void wmi_evt_linkup(struct wil6210_priv *wil, int id, void *d, int len) | ||
526 | { | ||
527 | struct net_device *ndev = wil_to_ndev(wil); | ||
528 | struct wmi_data_port_open_event *evt = d; | ||
529 | |||
530 | wil_dbg_wmi(wil, "Link UP for CID %d\n", evt->cid); | ||
531 | |||
532 | netif_carrier_on(ndev); | ||
533 | } | ||
534 | |||
535 | static void wmi_evt_linkdown(struct wil6210_priv *wil, int id, void *d, int len) | ||
536 | { | ||
537 | struct net_device *ndev = wil_to_ndev(wil); | ||
538 | struct wmi_wbe_link_down_event *evt = d; | ||
539 | |||
540 | wil_dbg_wmi(wil, "Link DOWN for CID %d, reason %d\n", | ||
541 | evt->cid, le32_to_cpu(evt->reason)); | ||
542 | |||
543 | netif_carrier_off(ndev); | ||
544 | } | ||
545 | |||
546 | static void wmi_evt_ba_status(struct wil6210_priv *wil, int id, void *d, | ||
547 | int len) | ||
548 | { | ||
549 | struct wmi_vring_ba_status_event *evt = d; | ||
550 | |||
551 | wil_dbg_wmi(wil, "BACK[%d] %s {%d} timeout %d\n", | ||
552 | evt->ringid, evt->status ? "N/A" : "OK", evt->agg_wsize, | ||
553 | __le16_to_cpu(evt->ba_timeout)); | ||
554 | } | ||
555 | |||
531 | static const struct { | 556 | static const struct { |
532 | int eventid; | 557 | int eventid; |
533 | void (*handler)(struct wil6210_priv *wil, int eventid, | 558 | void (*handler)(struct wil6210_priv *wil, int eventid, |
@@ -541,6 +566,9 @@ static const struct { | |||
541 | {WMI_DISCONNECT_EVENTID, wmi_evt_disconnect}, | 566 | {WMI_DISCONNECT_EVENTID, wmi_evt_disconnect}, |
542 | {WMI_NOTIFY_REQ_DONE_EVENTID, wmi_evt_notify}, | 567 | {WMI_NOTIFY_REQ_DONE_EVENTID, wmi_evt_notify}, |
543 | {WMI_EAPOL_RX_EVENTID, wmi_evt_eapol_rx}, | 568 | {WMI_EAPOL_RX_EVENTID, wmi_evt_eapol_rx}, |
569 | {WMI_DATA_PORT_OPEN_EVENTID, wmi_evt_linkup}, | ||
570 | {WMI_WBE_LINKDOWN_EVENTID, wmi_evt_linkdown}, | ||
571 | {WMI_BA_STATUS_EVENTID, wmi_evt_ba_status}, | ||
544 | }; | 572 | }; |
545 | 573 | ||
546 | /* | 574 | /* |
@@ -559,6 +587,11 @@ void wmi_recv_cmd(struct wil6210_priv *wil) | |||
559 | void __iomem *src; | 587 | void __iomem *src; |
560 | ulong flags; | 588 | ulong flags; |
561 | 589 | ||
590 | if (!test_bit(wil_status_reset_done, &wil->status)) { | ||
591 | wil_err(wil, "Reset not completed\n"); | ||
592 | return; | ||
593 | } | ||
594 | |||
562 | for (;;) { | 595 | for (;;) { |
563 | u16 len; | 596 | u16 len; |
564 | 597 | ||
@@ -683,18 +716,39 @@ int wmi_set_mac_address(struct wil6210_priv *wil, void *addr) | |||
683 | return wmi_send(wil, WMI_SET_MAC_ADDRESS_CMDID, &cmd, sizeof(cmd)); | 716 | return wmi_send(wil, WMI_SET_MAC_ADDRESS_CMDID, &cmd, sizeof(cmd)); |
684 | } | 717 | } |
685 | 718 | ||
686 | int wmi_set_bcon(struct wil6210_priv *wil, int bi, u8 wmi_nettype) | 719 | int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, u8 chan) |
687 | { | 720 | { |
688 | struct wmi_bcon_ctrl_cmd cmd = { | 721 | int rc; |
722 | |||
723 | struct wmi_pcp_start_cmd cmd = { | ||
689 | .bcon_interval = cpu_to_le16(bi), | 724 | .bcon_interval = cpu_to_le16(bi), |
690 | .network_type = wmi_nettype, | 725 | .network_type = wmi_nettype, |
691 | .disable_sec_offload = 1, | 726 | .disable_sec_offload = 1, |
727 | .channel = chan, | ||
692 | }; | 728 | }; |
729 | struct { | ||
730 | struct wil6210_mbox_hdr_wmi wmi; | ||
731 | struct wmi_pcp_started_event evt; | ||
732 | } __packed reply; | ||
693 | 733 | ||
694 | if (!wil->secure_pcp) | 734 | if (!wil->secure_pcp) |
695 | cmd.disable_sec = 1; | 735 | cmd.disable_sec = 1; |
696 | 736 | ||
697 | return wmi_send(wil, WMI_BCON_CTRL_CMDID, &cmd, sizeof(cmd)); | 737 | rc = wmi_call(wil, WMI_PCP_START_CMDID, &cmd, sizeof(cmd), |
738 | WMI_PCP_STARTED_EVENTID, &reply, sizeof(reply), 100); | ||
739 | if (rc) | ||
740 | return rc; | ||
741 | |||
742 | if (reply.evt.status != WMI_FW_STATUS_SUCCESS) | ||
743 | rc = -EINVAL; | ||
744 | |||
745 | return rc; | ||
746 | } | ||
747 | |||
748 | int wmi_pcp_stop(struct wil6210_priv *wil) | ||
749 | { | ||
750 | return wmi_call(wil, WMI_PCP_STOP_CMDID, NULL, 0, | ||
751 | WMI_PCP_STOPPED_EVENTID, NULL, 0, 20); | ||
698 | } | 752 | } |
699 | 753 | ||
700 | int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid) | 754 | int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid) |
@@ -765,6 +819,16 @@ int wmi_get_channel(struct wil6210_priv *wil, int *channel) | |||
765 | return 0; | 819 | return 0; |
766 | } | 820 | } |
767 | 821 | ||
822 | int wmi_p2p_cfg(struct wil6210_priv *wil, int channel) | ||
823 | { | ||
824 | struct wmi_p2p_cfg_cmd cmd = { | ||
825 | .discovery_mode = WMI_DISCOVERY_MODE_NON_OFFLOAD, | ||
826 | .channel = channel - 1, | ||
827 | }; | ||
828 | |||
829 | return wmi_send(wil, WMI_P2P_CFG_CMDID, &cmd, sizeof(cmd)); | ||
830 | } | ||
831 | |||
768 | int wmi_tx_eapol(struct wil6210_priv *wil, struct sk_buff *skb) | 832 | int wmi_tx_eapol(struct wil6210_priv *wil, struct sk_buff *skb) |
769 | { | 833 | { |
770 | struct wmi_eapol_tx_cmd *cmd; | 834 | struct wmi_eapol_tx_cmd *cmd; |
@@ -843,7 +907,7 @@ int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie) | |||
843 | /* BUG: FW API define ieLen as u8. Will fix FW */ | 907 | /* BUG: FW API define ieLen as u8. Will fix FW */ |
844 | cmd->ie_len = cpu_to_le16(ie_len); | 908 | cmd->ie_len = cpu_to_le16(ie_len); |
845 | memcpy(cmd->ie_info, ie, ie_len); | 909 | memcpy(cmd->ie_info, ie, ie_len); |
846 | rc = wmi_send(wil, WMI_SET_APPIE_CMDID, &cmd, len); | 910 | rc = wmi_send(wil, WMI_SET_APPIE_CMDID, cmd, len); |
847 | kfree(cmd); | 911 | kfree(cmd); |
848 | 912 | ||
849 | return rc; | 913 | return rc; |
@@ -898,6 +962,31 @@ int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring) | |||
898 | return rc; | 962 | return rc; |
899 | } | 963 | } |
900 | 964 | ||
965 | int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_m, u32 *t_r) | ||
966 | { | ||
967 | int rc; | ||
968 | struct wmi_temp_sense_cmd cmd = { | ||
969 | .measure_marlon_m_en = cpu_to_le32(!!t_m), | ||
970 | .measure_marlon_r_en = cpu_to_le32(!!t_r), | ||
971 | }; | ||
972 | struct { | ||
973 | struct wil6210_mbox_hdr_wmi wmi; | ||
974 | struct wmi_temp_sense_done_event evt; | ||
975 | } __packed reply; | ||
976 | |||
977 | rc = wmi_call(wil, WMI_TEMP_SENSE_CMDID, &cmd, sizeof(cmd), | ||
978 | WMI_TEMP_SENSE_DONE_EVENTID, &reply, sizeof(reply), 100); | ||
979 | if (rc) | ||
980 | return rc; | ||
981 | |||
982 | if (t_m) | ||
983 | *t_m = le32_to_cpu(reply.evt.marlon_m_t1000); | ||
984 | if (t_r) | ||
985 | *t_r = le32_to_cpu(reply.evt.marlon_r_t1000); | ||
986 | |||
987 | return 0; | ||
988 | } | ||
989 | |||
901 | void wmi_event_flush(struct wil6210_priv *wil) | 990 | void wmi_event_flush(struct wil6210_priv *wil) |
902 | { | 991 | { |
903 | struct pending_wmi_event *evt, *t; | 992 | struct pending_wmi_event *evt, *t; |
@@ -997,24 +1086,3 @@ void wmi_event_worker(struct work_struct *work) | |||
997 | kfree(evt); | 1086 | kfree(evt); |
998 | } | 1087 | } |
999 | } | 1088 | } |
1000 | |||
1001 | void wmi_connect_worker(struct work_struct *work) | ||
1002 | { | ||
1003 | int rc; | ||
1004 | struct wil6210_priv *wil = container_of(work, struct wil6210_priv, | ||
1005 | wmi_connect_worker); | ||
1006 | |||
1007 | if (wil->pending_connect_cid < 0) { | ||
1008 | wil_err(wil, "No connection pending\n"); | ||
1009 | return; | ||
1010 | } | ||
1011 | |||
1012 | wil_dbg_wmi(wil, "Configure for connection CID %d\n", | ||
1013 | wil->pending_connect_cid); | ||
1014 | |||
1015 | rc = wil_vring_init_tx(wil, 0, WIL6210_TX_RING_SIZE, | ||
1016 | wil->pending_connect_cid, 0); | ||
1017 | wil->pending_connect_cid = -1; | ||
1018 | if (rc == 0) | ||
1019 | wil_link_on(wil); | ||
1020 | } | ||
diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h index 3bbf87572b07..50b8528394f4 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.h +++ b/drivers/net/wireless/ath/wil6210/wmi.h | |||
@@ -36,6 +36,7 @@ | |||
36 | enum wmi_command_id { | 36 | enum wmi_command_id { |
37 | WMI_CONNECT_CMDID = 0x0001, | 37 | WMI_CONNECT_CMDID = 0x0001, |
38 | WMI_DISCONNECT_CMDID = 0x0003, | 38 | WMI_DISCONNECT_CMDID = 0x0003, |
39 | WMI_DISCONNECT_STA_CMDID = 0x0004, | ||
39 | WMI_START_SCAN_CMDID = 0x0007, | 40 | WMI_START_SCAN_CMDID = 0x0007, |
40 | WMI_SET_BSS_FILTER_CMDID = 0x0009, | 41 | WMI_SET_BSS_FILTER_CMDID = 0x0009, |
41 | WMI_SET_PROBED_SSID_CMDID = 0x000a, | 42 | WMI_SET_PROBED_SSID_CMDID = 0x000a, |
@@ -44,7 +45,6 @@ enum wmi_command_id { | |||
44 | WMI_ADD_CIPHER_KEY_CMDID = 0x0016, | 45 | WMI_ADD_CIPHER_KEY_CMDID = 0x0016, |
45 | WMI_DELETE_CIPHER_KEY_CMDID = 0x0017, | 46 | WMI_DELETE_CIPHER_KEY_CMDID = 0x0017, |
46 | WMI_SET_APPIE_CMDID = 0x003f, | 47 | WMI_SET_APPIE_CMDID = 0x003f, |
47 | WMI_GET_APPIE_CMDID = 0x0040, | ||
48 | WMI_SET_WSC_STATUS_CMDID = 0x0041, | 48 | WMI_SET_WSC_STATUS_CMDID = 0x0041, |
49 | WMI_PXMT_RANGE_CFG_CMDID = 0x0042, | 49 | WMI_PXMT_RANGE_CFG_CMDID = 0x0042, |
50 | WMI_PXMT_SNR2_RANGE_CFG_CMDID = 0x0043, | 50 | WMI_PXMT_SNR2_RANGE_CFG_CMDID = 0x0043, |
@@ -55,11 +55,11 @@ enum wmi_command_id { | |||
55 | WMI_DEEP_ECHO_CMDID = 0x0804, | 55 | WMI_DEEP_ECHO_CMDID = 0x0804, |
56 | WMI_CONFIG_MAC_CMDID = 0x0805, | 56 | WMI_CONFIG_MAC_CMDID = 0x0805, |
57 | WMI_CONFIG_PHY_DEBUG_CMDID = 0x0806, | 57 | WMI_CONFIG_PHY_DEBUG_CMDID = 0x0806, |
58 | WMI_ADD_STATION_CMDID = 0x0807, | ||
59 | WMI_ADD_DEBUG_TX_PCKT_CMDID = 0x0808, | 58 | WMI_ADD_DEBUG_TX_PCKT_CMDID = 0x0808, |
60 | WMI_PHY_GET_STATISTICS_CMDID = 0x0809, | 59 | WMI_PHY_GET_STATISTICS_CMDID = 0x0809, |
61 | WMI_FS_TUNE_CMDID = 0x080a, | 60 | WMI_FS_TUNE_CMDID = 0x080a, |
62 | WMI_CORR_MEASURE_CMDID = 0x080b, | 61 | WMI_CORR_MEASURE_CMDID = 0x080b, |
62 | WMI_READ_RSSI_CMDID = 0x080c, | ||
63 | WMI_TEMP_SENSE_CMDID = 0x080e, | 63 | WMI_TEMP_SENSE_CMDID = 0x080e, |
64 | WMI_DC_CALIB_CMDID = 0x080f, | 64 | WMI_DC_CALIB_CMDID = 0x080f, |
65 | WMI_SEND_TONE_CMDID = 0x0810, | 65 | WMI_SEND_TONE_CMDID = 0x0810, |
@@ -75,9 +75,9 @@ enum wmi_command_id { | |||
75 | MAC_IO_STATIC_PARAMS_CMDID = 0x081b, | 75 | MAC_IO_STATIC_PARAMS_CMDID = 0x081b, |
76 | MAC_IO_DYNAMIC_PARAMS_CMDID = 0x081c, | 76 | MAC_IO_DYNAMIC_PARAMS_CMDID = 0x081c, |
77 | WMI_SILENT_RSSI_CALIB_CMDID = 0x081d, | 77 | WMI_SILENT_RSSI_CALIB_CMDID = 0x081d, |
78 | WMI_RF_RX_TEST_CMDID = 0x081e, | ||
78 | WMI_CFG_RX_CHAIN_CMDID = 0x0820, | 79 | WMI_CFG_RX_CHAIN_CMDID = 0x0820, |
79 | WMI_VRING_CFG_CMDID = 0x0821, | 80 | WMI_VRING_CFG_CMDID = 0x0821, |
80 | WMI_RX_ON_CMDID = 0x0822, | ||
81 | WMI_VRING_BA_EN_CMDID = 0x0823, | 81 | WMI_VRING_BA_EN_CMDID = 0x0823, |
82 | WMI_VRING_BA_DIS_CMDID = 0x0824, | 82 | WMI_VRING_BA_DIS_CMDID = 0x0824, |
83 | WMI_RCP_ADDBA_RESP_CMDID = 0x0825, | 83 | WMI_RCP_ADDBA_RESP_CMDID = 0x0825, |
@@ -87,7 +87,6 @@ enum wmi_command_id { | |||
87 | WMI_SET_PCP_CHANNEL_CMDID = 0x0829, | 87 | WMI_SET_PCP_CHANNEL_CMDID = 0x0829, |
88 | WMI_GET_PCP_CHANNEL_CMDID = 0x082a, | 88 | WMI_GET_PCP_CHANNEL_CMDID = 0x082a, |
89 | WMI_SW_TX_REQ_CMDID = 0x082b, | 89 | WMI_SW_TX_REQ_CMDID = 0x082b, |
90 | WMI_RX_OFF_CMDID = 0x082c, | ||
91 | WMI_READ_MAC_RXQ_CMDID = 0x0830, | 90 | WMI_READ_MAC_RXQ_CMDID = 0x0830, |
92 | WMI_READ_MAC_TXQ_CMDID = 0x0831, | 91 | WMI_READ_MAC_TXQ_CMDID = 0x0831, |
93 | WMI_WRITE_MAC_RXQ_CMDID = 0x0832, | 92 | WMI_WRITE_MAC_RXQ_CMDID = 0x0832, |
@@ -112,6 +111,18 @@ enum wmi_command_id { | |||
112 | WMI_FLASH_READ_CMDID = 0x0902, | 111 | WMI_FLASH_READ_CMDID = 0x0902, |
113 | WMI_FLASH_WRITE_CMDID = 0x0903, | 112 | WMI_FLASH_WRITE_CMDID = 0x0903, |
114 | WMI_SECURITY_UNIT_TEST_CMDID = 0x0904, | 113 | WMI_SECURITY_UNIT_TEST_CMDID = 0x0904, |
114 | /*P2P*/ | ||
115 | WMI_P2P_CFG_CMDID = 0x0910, | ||
116 | WMI_PORT_ALLOCATE_CMDID = 0x0911, | ||
117 | WMI_PORT_DELETE_CMDID = 0x0912, | ||
118 | WMI_POWER_MGMT_CFG_CMDID = 0x0913, | ||
119 | WMI_START_LISTEN_CMDID = 0x0914, | ||
120 | WMI_START_SEARCH_CMDID = 0x0915, | ||
121 | WMI_DISCOVERY_START_CMDID = 0x0916, | ||
122 | WMI_DISCOVERY_STOP_CMDID = 0x0917, | ||
123 | WMI_PCP_START_CMDID = 0x0918, | ||
124 | WMI_PCP_STOP_CMDID = 0x0919, | ||
125 | WMI_GET_PCP_FACTOR_CMDID = 0x091b, | ||
115 | 126 | ||
116 | WMI_SET_MAC_ADDRESS_CMDID = 0xf003, | 127 | WMI_SET_MAC_ADDRESS_CMDID = 0xf003, |
117 | WMI_ABORT_SCAN_CMDID = 0xf007, | 128 | WMI_ABORT_SCAN_CMDID = 0xf007, |
@@ -132,18 +143,6 @@ enum wmi_command_id { | |||
132 | */ | 143 | */ |
133 | 144 | ||
134 | /* | 145 | /* |
135 | * Frame Types | ||
136 | */ | ||
137 | enum wmi_mgmt_frame_type { | ||
138 | WMI_FRAME_BEACON = 0, | ||
139 | WMI_FRAME_PROBE_REQ = 1, | ||
140 | WMI_FRAME_PROBE_RESP = 2, | ||
141 | WMI_FRAME_ASSOC_REQ = 3, | ||
142 | WMI_FRAME_ASSOC_RESP = 4, | ||
143 | WMI_NUM_MGMT_FRAME, | ||
144 | }; | ||
145 | |||
146 | /* | ||
147 | * WMI_CONNECT_CMDID | 146 | * WMI_CONNECT_CMDID |
148 | */ | 147 | */ |
149 | enum wmi_network_type { | 148 | enum wmi_network_type { |
@@ -184,7 +183,7 @@ enum wmi_crypto_type { | |||
184 | enum wmi_connect_ctrl_flag_bits { | 183 | enum wmi_connect_ctrl_flag_bits { |
185 | WMI_CONNECT_ASSOC_POLICY_USER = 0x0001, | 184 | WMI_CONNECT_ASSOC_POLICY_USER = 0x0001, |
186 | WMI_CONNECT_SEND_REASSOC = 0x0002, | 185 | WMI_CONNECT_SEND_REASSOC = 0x0002, |
187 | WMI_CONNECT_IGNORE_WPAx_GROUP_CIPHER = 0x0004, | 186 | WMI_CONNECT_IGNORE_WPA_GROUP_CIPHER = 0x0004, |
188 | WMI_CONNECT_PROFILE_MATCH_DONE = 0x0008, | 187 | WMI_CONNECT_PROFILE_MATCH_DONE = 0x0008, |
189 | WMI_CONNECT_IGNORE_AAC_BEACON = 0x0010, | 188 | WMI_CONNECT_IGNORE_AAC_BEACON = 0x0010, |
190 | WMI_CONNECT_CSA_FOLLOW_BSS = 0x0020, | 189 | WMI_CONNECT_CSA_FOLLOW_BSS = 0x0020, |
@@ -212,6 +211,13 @@ struct wmi_connect_cmd { | |||
212 | u8 reserved1[2]; | 211 | u8 reserved1[2]; |
213 | } __packed; | 212 | } __packed; |
214 | 213 | ||
214 | /* | ||
215 | * WMI_DISCONNECT_STA_CMDID | ||
216 | */ | ||
217 | struct wmi_disconnect_sta_cmd { | ||
218 | u8 dst_mac[WMI_MAC_LEN]; | ||
219 | __le16 disconnect_reason; | ||
220 | } __packed; | ||
215 | 221 | ||
216 | /* | 222 | /* |
217 | * WMI_RECONNECT_CMDID | 223 | * WMI_RECONNECT_CMDID |
@@ -289,10 +295,12 @@ struct wmi_delete_cipher_key_cmd { | |||
289 | enum wmi_scan_type { | 295 | enum wmi_scan_type { |
290 | WMI_LONG_SCAN = 0, | 296 | WMI_LONG_SCAN = 0, |
291 | WMI_SHORT_SCAN = 1, | 297 | WMI_SHORT_SCAN = 1, |
298 | WMI_PBC_SCAN = 2, | ||
292 | }; | 299 | }; |
293 | 300 | ||
294 | struct wmi_start_scan_cmd { | 301 | struct wmi_start_scan_cmd { |
295 | u8 reserved[8]; | 302 | u8 reserved[8]; |
303 | |||
296 | __le32 home_dwell_time; /* Max duration in the home channel(ms) */ | 304 | __le32 home_dwell_time; /* Max duration in the home channel(ms) */ |
297 | __le32 force_scan_interval; /* Time interval between scans (ms)*/ | 305 | __le32 force_scan_interval; /* Time interval between scans (ms)*/ |
298 | u8 scan_type; /* wmi_scan_type */ | 306 | u8 scan_type; /* wmi_scan_type */ |
@@ -309,7 +317,7 @@ struct wmi_start_scan_cmd { | |||
309 | /* | 317 | /* |
310 | * WMI_SET_PROBED_SSID_CMDID | 318 | * WMI_SET_PROBED_SSID_CMDID |
311 | */ | 319 | */ |
312 | #define MAX_PROBED_SSID_INDEX (15) | 320 | #define MAX_PROBED_SSID_INDEX (3) |
313 | 321 | ||
314 | enum wmi_ssid_flag { | 322 | enum wmi_ssid_flag { |
315 | WMI_SSID_FLAG_DISABLE = 0, /* disables entry */ | 323 | WMI_SSID_FLAG_DISABLE = 0, /* disables entry */ |
@@ -328,6 +336,20 @@ struct wmi_probed_ssid_cmd { | |||
328 | * WMI_SET_APPIE_CMDID | 336 | * WMI_SET_APPIE_CMDID |
329 | * Add Application specified IE to a management frame | 337 | * Add Application specified IE to a management frame |
330 | */ | 338 | */ |
339 | #define WMI_MAX_IE_LEN (1024) | ||
340 | |||
341 | /* | ||
342 | * Frame Types | ||
343 | */ | ||
344 | enum wmi_mgmt_frame_type { | ||
345 | WMI_FRAME_BEACON = 0, | ||
346 | WMI_FRAME_PROBE_REQ = 1, | ||
347 | WMI_FRAME_PROBE_RESP = 2, | ||
348 | WMI_FRAME_ASSOC_REQ = 3, | ||
349 | WMI_FRAME_ASSOC_RESP = 4, | ||
350 | WMI_NUM_MGMT_FRAME, | ||
351 | }; | ||
352 | |||
331 | struct wmi_set_appie_cmd { | 353 | struct wmi_set_appie_cmd { |
332 | u8 mgmt_frm_type; /* enum wmi_mgmt_frame_type */ | 354 | u8 mgmt_frm_type; /* enum wmi_mgmt_frame_type */ |
333 | u8 reserved; | 355 | u8 reserved; |
@@ -335,13 +357,18 @@ struct wmi_set_appie_cmd { | |||
335 | u8 ie_info[0]; | 357 | u8 ie_info[0]; |
336 | } __packed; | 358 | } __packed; |
337 | 359 | ||
338 | #define WMI_MAX_IE_LEN (1024) | ||
339 | 360 | ||
361 | /* | ||
362 | * WMI_PXMT_RANGE_CFG_CMDID | ||
363 | */ | ||
340 | struct wmi_pxmt_range_cfg_cmd { | 364 | struct wmi_pxmt_range_cfg_cmd { |
341 | u8 dst_mac[WMI_MAC_LEN]; | 365 | u8 dst_mac[WMI_MAC_LEN]; |
342 | __le16 range; | 366 | __le16 range; |
343 | } __packed; | 367 | } __packed; |
344 | 368 | ||
369 | /* | ||
370 | * WMI_PXMT_SNR2_RANGE_CFG_CMDID | ||
371 | */ | ||
345 | struct wmi_pxmt_snr2_range_cfg_cmd { | 372 | struct wmi_pxmt_snr2_range_cfg_cmd { |
346 | s8 snr2range_arr[WMI_PROX_RANGE_NUM-1]; | 373 | s8 snr2range_arr[WMI_PROX_RANGE_NUM-1]; |
347 | } __packed; | 374 | } __packed; |
@@ -359,6 +386,23 @@ struct wmi_rf_mgmt_cmd { | |||
359 | __le32 rf_mgmt_type; | 386 | __le32 rf_mgmt_type; |
360 | } __packed; | 387 | } __packed; |
361 | 388 | ||
389 | |||
390 | /* | ||
391 | * WMI_RF_RX_TEST_CMDID | ||
392 | */ | ||
393 | struct wmi_rf_rx_test_cmd { | ||
394 | __le32 sector; | ||
395 | } __packed; | ||
396 | |||
397 | /* | ||
398 | * WMI_CORR_MEASURE_CMDID | ||
399 | */ | ||
400 | struct wmi_corr_measure_cmd { | ||
401 | s32 freq_mhz; | ||
402 | __le32 length_samples; | ||
403 | __le32 iterations; | ||
404 | } __packed; | ||
405 | |||
362 | /* | 406 | /* |
363 | * WMI_SET_SSID_CMDID | 407 | * WMI_SET_SSID_CMDID |
364 | */ | 408 | */ |
@@ -388,6 +432,74 @@ struct wmi_bcon_ctrl_cmd { | |||
388 | u8 disable_sec; | 432 | u8 disable_sec; |
389 | } __packed; | 433 | } __packed; |
390 | 434 | ||
435 | |||
436 | /******* P2P ***********/ | ||
437 | |||
438 | /* | ||
439 | * WMI_PORT_ALLOCATE_CMDID | ||
440 | */ | ||
441 | enum wmi_port_role { | ||
442 | WMI_PORT_STA = 0, | ||
443 | WMI_PORT_PCP = 1, | ||
444 | WMI_PORT_AP = 2, | ||
445 | WMI_PORT_P2P_DEV = 3, | ||
446 | WMI_PORT_P2P_CLIENT = 4, | ||
447 | WMI_PORT_P2P_GO = 5, | ||
448 | }; | ||
449 | |||
450 | struct wmi_port_allocate_cmd { | ||
451 | u8 mac[WMI_MAC_LEN]; | ||
452 | u8 port_role; | ||
453 | u8 midid; | ||
454 | } __packed; | ||
455 | |||
456 | /* | ||
457 | * WMI_PORT_DELETE_CMDID | ||
458 | */ | ||
459 | struct wmi_delete_port_cmd { | ||
460 | u8 mid; | ||
461 | u8 reserved[3]; | ||
462 | } __packed; | ||
463 | |||
464 | /* | ||
465 | * WMI_P2P_CFG_CMDID | ||
466 | */ | ||
467 | enum wmi_discovery_mode { | ||
468 | WMI_DISCOVERY_MODE_NON_OFFLOAD = 0, | ||
469 | WMI_DISCOVERY_MODE_OFFLOAD = 1, | ||
470 | }; | ||
471 | |||
472 | struct wmi_p2p_cfg_cmd { | ||
473 | u8 discovery_mode; /* wmi_discovery_mode */ | ||
474 | u8 channel; | ||
475 | __le16 bcon_interval; /* base to listen/search duration calculation */ | ||
476 | } __packed; | ||
477 | |||
478 | /* | ||
479 | * WMI_POWER_MGMT_CFG_CMDID | ||
480 | */ | ||
481 | enum wmi_power_source_type { | ||
482 | WMI_POWER_SOURCE_BATTERY = 0, | ||
483 | WMI_POWER_SOURCE_OTHER = 1, | ||
484 | }; | ||
485 | |||
486 | struct wmi_power_mgmt_cfg_cmd { | ||
487 | u8 power_source; /* wmi_power_source_type */ | ||
488 | u8 reserved[3]; | ||
489 | } __packed; | ||
490 | |||
491 | /* | ||
492 | * WMI_PCP_START_CMDID | ||
493 | */ | ||
494 | struct wmi_pcp_start_cmd { | ||
495 | __le16 bcon_interval; | ||
496 | u8 reserved0[10]; | ||
497 | u8 network_type; | ||
498 | u8 channel; | ||
499 | u8 disable_sec_offload; | ||
500 | u8 disable_sec; | ||
501 | } __packed; | ||
502 | |||
391 | /* | 503 | /* |
392 | * WMI_SW_TX_REQ_CMDID | 504 | * WMI_SW_TX_REQ_CMDID |
393 | */ | 505 | */ |
@@ -435,16 +547,17 @@ enum wmi_vring_cfg_schd_params_priority { | |||
435 | WMI_SCH_PRIO_HIGH = 1, | 547 | WMI_SCH_PRIO_HIGH = 1, |
436 | }; | 548 | }; |
437 | 549 | ||
550 | #define CIDXTID_CID_POS (0) | ||
551 | #define CIDXTID_CID_LEN (4) | ||
552 | #define CIDXTID_CID_MSK (0xF) | ||
553 | #define CIDXTID_TID_POS (4) | ||
554 | #define CIDXTID_TID_LEN (4) | ||
555 | #define CIDXTID_TID_MSK (0xF0) | ||
556 | |||
438 | struct wmi_vring_cfg { | 557 | struct wmi_vring_cfg { |
439 | struct wmi_sw_ring_cfg tx_sw_ring; | 558 | struct wmi_sw_ring_cfg tx_sw_ring; |
440 | u8 ringid; /* 0-23 vrings */ | 559 | u8 ringid; /* 0-23 vrings */ |
441 | 560 | ||
442 | #define CIDXTID_CID_POS (0) | ||
443 | #define CIDXTID_CID_LEN (4) | ||
444 | #define CIDXTID_CID_MSK (0xF) | ||
445 | #define CIDXTID_TID_POS (4) | ||
446 | #define CIDXTID_TID_LEN (4) | ||
447 | #define CIDXTID_TID_MSK (0xF0) | ||
448 | u8 cidxtid; | 561 | u8 cidxtid; |
449 | 562 | ||
450 | u8 encap_trans_type; | 563 | u8 encap_trans_type; |
@@ -501,8 +614,14 @@ struct wmi_vring_ba_dis_cmd { | |||
501 | */ | 614 | */ |
502 | struct wmi_notify_req_cmd { | 615 | struct wmi_notify_req_cmd { |
503 | u8 cid; | 616 | u8 cid; |
504 | u8 reserved[3]; | 617 | u8 year; |
618 | u8 month; | ||
619 | u8 day; | ||
505 | __le32 interval_usec; | 620 | __le32 interval_usec; |
621 | u8 hour; | ||
622 | u8 minute; | ||
623 | u8 second; | ||
624 | u8 miliseconds; | ||
506 | } __packed; | 625 | } __packed; |
507 | 626 | ||
508 | /* | 627 | /* |
@@ -548,6 +667,11 @@ enum wmi_cfg_rx_chain_cmd_nwifi_ds_trans_type { | |||
548 | WMI_NWIFI_RX_TRANS_MODE_PBSS2STA = 2, | 667 | WMI_NWIFI_RX_TRANS_MODE_PBSS2STA = 2, |
549 | }; | 668 | }; |
550 | 669 | ||
670 | enum wmi_cfg_rx_chain_cmd_reorder_type { | ||
671 | WMI_RX_HW_REORDER = 0, | ||
672 | WMI_RX_SW_REORDER = 1, | ||
673 | }; | ||
674 | |||
551 | struct wmi_cfg_rx_chain_cmd { | 675 | struct wmi_cfg_rx_chain_cmd { |
552 | __le32 action; | 676 | __le32 action; |
553 | struct wmi_sw_ring_cfg rx_sw_ring; | 677 | struct wmi_sw_ring_cfg rx_sw_ring; |
@@ -596,7 +720,8 @@ struct wmi_cfg_rx_chain_cmd { | |||
596 | __le16 wb_thrsh; | 720 | __le16 wb_thrsh; |
597 | __le32 itr_value; | 721 | __le32 itr_value; |
598 | __le16 host_thrsh; | 722 | __le16 host_thrsh; |
599 | u8 reserved[2]; | 723 | u8 reorder_type; |
724 | u8 reserved; | ||
600 | struct wmi_sniffer_cfg sniffer_cfg; | 725 | struct wmi_sniffer_cfg sniffer_cfg; |
601 | } __packed; | 726 | } __packed; |
602 | 727 | ||
@@ -604,15 +729,7 @@ struct wmi_cfg_rx_chain_cmd { | |||
604 | * WMI_RCP_ADDBA_RESP_CMDID | 729 | * WMI_RCP_ADDBA_RESP_CMDID |
605 | */ | 730 | */ |
606 | struct wmi_rcp_addba_resp_cmd { | 731 | struct wmi_rcp_addba_resp_cmd { |
607 | |||
608 | #define CIDXTID_CID_POS (0) | ||
609 | #define CIDXTID_CID_LEN (4) | ||
610 | #define CIDXTID_CID_MSK (0xF) | ||
611 | #define CIDXTID_TID_POS (4) | ||
612 | #define CIDXTID_TID_LEN (4) | ||
613 | #define CIDXTID_TID_MSK (0xF0) | ||
614 | u8 cidxtid; | 732 | u8 cidxtid; |
615 | |||
616 | u8 dialog_token; | 733 | u8 dialog_token; |
617 | __le16 status_code; | 734 | __le16 status_code; |
618 | __le16 ba_param_set; /* ieee80211_ba_parameterset field to send */ | 735 | __le16 ba_param_set; /* ieee80211_ba_parameterset field to send */ |
@@ -623,15 +740,7 @@ struct wmi_rcp_addba_resp_cmd { | |||
623 | * WMI_RCP_DELBA_CMDID | 740 | * WMI_RCP_DELBA_CMDID |
624 | */ | 741 | */ |
625 | struct wmi_rcp_delba_cmd { | 742 | struct wmi_rcp_delba_cmd { |
626 | |||
627 | #define CIDXTID_CID_POS (0) | ||
628 | #define CIDXTID_CID_LEN (4) | ||
629 | #define CIDXTID_CID_MSK (0xF) | ||
630 | #define CIDXTID_TID_POS (4) | ||
631 | #define CIDXTID_TID_LEN (4) | ||
632 | #define CIDXTID_TID_MSK (0xF0) | ||
633 | u8 cidxtid; | 743 | u8 cidxtid; |
634 | |||
635 | u8 reserved; | 744 | u8 reserved; |
636 | __le16 reason; | 745 | __le16 reason; |
637 | } __packed; | 746 | } __packed; |
@@ -640,15 +749,7 @@ struct wmi_rcp_delba_cmd { | |||
640 | * WMI_RCP_ADDBA_REQ_CMDID | 749 | * WMI_RCP_ADDBA_REQ_CMDID |
641 | */ | 750 | */ |
642 | struct wmi_rcp_addba_req_cmd { | 751 | struct wmi_rcp_addba_req_cmd { |
643 | |||
644 | #define CIDXTID_CID_POS (0) | ||
645 | #define CIDXTID_CID_LEN (4) | ||
646 | #define CIDXTID_CID_MSK (0xF) | ||
647 | #define CIDXTID_TID_POS (4) | ||
648 | #define CIDXTID_TID_LEN (4) | ||
649 | #define CIDXTID_TID_MSK (0xF0) | ||
650 | u8 cidxtid; | 752 | u8 cidxtid; |
651 | |||
652 | u8 dialog_token; | 753 | u8 dialog_token; |
653 | /* ieee80211_ba_parameterset field as it received */ | 754 | /* ieee80211_ba_parameterset field as it received */ |
654 | __le16 ba_param_set; | 755 | __le16 ba_param_set; |
@@ -665,7 +766,6 @@ struct wmi_set_mac_address_cmd { | |||
665 | u8 reserved[2]; | 766 | u8 reserved[2]; |
666 | } __packed; | 767 | } __packed; |
667 | 768 | ||
668 | |||
669 | /* | 769 | /* |
670 | * WMI_EAPOL_TX_CMDID | 770 | * WMI_EAPOL_TX_CMDID |
671 | */ | 771 | */ |
@@ -692,6 +792,17 @@ struct wmi_echo_cmd { | |||
692 | } __packed; | 792 | } __packed; |
693 | 793 | ||
694 | /* | 794 | /* |
795 | * WMI_TEMP_SENSE_CMDID | ||
796 | * | ||
797 | * Measure MAC and radio temperatures | ||
798 | */ | ||
799 | struct wmi_temp_sense_cmd { | ||
800 | __le32 measure_marlon_m_en; | ||
801 | __le32 measure_marlon_r_en; | ||
802 | } __packed; | ||
803 | |||
804 | |||
805 | /* | ||
695 | * WMI Events | 806 | * WMI Events |
696 | */ | 807 | */ |
697 | 808 | ||
@@ -699,7 +810,6 @@ struct wmi_echo_cmd { | |||
699 | * List of Events (target to host) | 810 | * List of Events (target to host) |
700 | */ | 811 | */ |
701 | enum wmi_event_id { | 812 | enum wmi_event_id { |
702 | WMI_IMM_RSP_EVENTID = 0x0000, | ||
703 | WMI_READY_EVENTID = 0x1001, | 813 | WMI_READY_EVENTID = 0x1001, |
704 | WMI_CONNECT_EVENTID = 0x1002, | 814 | WMI_CONNECT_EVENTID = 0x1002, |
705 | WMI_DISCONNECT_EVENTID = 0x1003, | 815 | WMI_DISCONNECT_EVENTID = 0x1003, |
@@ -709,13 +819,9 @@ enum wmi_event_id { | |||
709 | WMI_FW_READY_EVENTID = 0x1801, | 819 | WMI_FW_READY_EVENTID = 0x1801, |
710 | WMI_EXIT_FAST_MEM_ACC_MODE_EVENTID = 0x0200, | 820 | WMI_EXIT_FAST_MEM_ACC_MODE_EVENTID = 0x0200, |
711 | WMI_ECHO_RSP_EVENTID = 0x1803, | 821 | WMI_ECHO_RSP_EVENTID = 0x1803, |
712 | WMI_CONFIG_MAC_DONE_EVENTID = 0x1805, | ||
713 | WMI_CONFIG_PHY_DEBUG_DONE_EVENTID = 0x1806, | ||
714 | WMI_ADD_STATION_DONE_EVENTID = 0x1807, | ||
715 | WMI_ADD_DEBUG_TX_PCKT_DONE_EVENTID = 0x1808, | ||
716 | WMI_PHY_GET_STATISTICS_EVENTID = 0x1809, | ||
717 | WMI_FS_TUNE_DONE_EVENTID = 0x180a, | 822 | WMI_FS_TUNE_DONE_EVENTID = 0x180a, |
718 | WMI_CORR_MEASURE_DONE_EVENTID = 0x180b, | 823 | WMI_CORR_MEASURE_EVENTID = 0x180b, |
824 | WMI_READ_RSSI_EVENTID = 0x180c, | ||
719 | WMI_TEMP_SENSE_DONE_EVENTID = 0x180e, | 825 | WMI_TEMP_SENSE_DONE_EVENTID = 0x180e, |
720 | WMI_DC_CALIB_DONE_EVENTID = 0x180f, | 826 | WMI_DC_CALIB_DONE_EVENTID = 0x180f, |
721 | WMI_IQ_TX_CALIB_DONE_EVENTID = 0x1811, | 827 | WMI_IQ_TX_CALIB_DONE_EVENTID = 0x1811, |
@@ -727,10 +833,9 @@ enum wmi_event_id { | |||
727 | WMI_MARLON_R_WRITE_DONE_EVENTID = 0x1819, | 833 | WMI_MARLON_R_WRITE_DONE_EVENTID = 0x1819, |
728 | WMI_MARLON_R_TXRX_SEL_DONE_EVENTID = 0x181a, | 834 | WMI_MARLON_R_TXRX_SEL_DONE_EVENTID = 0x181a, |
729 | WMI_SILENT_RSSI_CALIB_DONE_EVENTID = 0x181d, | 835 | WMI_SILENT_RSSI_CALIB_DONE_EVENTID = 0x181d, |
730 | 836 | WMI_RF_RX_TEST_DONE_EVENTID = 0x181e, | |
731 | WMI_CFG_RX_CHAIN_DONE_EVENTID = 0x1820, | 837 | WMI_CFG_RX_CHAIN_DONE_EVENTID = 0x1820, |
732 | WMI_VRING_CFG_DONE_EVENTID = 0x1821, | 838 | WMI_VRING_CFG_DONE_EVENTID = 0x1821, |
733 | WMI_RX_ON_DONE_EVENTID = 0x1822, | ||
734 | WMI_BA_STATUS_EVENTID = 0x1823, | 839 | WMI_BA_STATUS_EVENTID = 0x1823, |
735 | WMI_RCP_ADDBA_REQ_EVENTID = 0x1824, | 840 | WMI_RCP_ADDBA_REQ_EVENTID = 0x1824, |
736 | WMI_ADDBA_RESP_SENT_EVENTID = 0x1825, | 841 | WMI_ADDBA_RESP_SENT_EVENTID = 0x1825, |
@@ -738,7 +843,6 @@ enum wmi_event_id { | |||
738 | WMI_GET_SSID_EVENTID = 0x1828, | 843 | WMI_GET_SSID_EVENTID = 0x1828, |
739 | WMI_GET_PCP_CHANNEL_EVENTID = 0x182a, | 844 | WMI_GET_PCP_CHANNEL_EVENTID = 0x182a, |
740 | WMI_SW_TX_COMPLETE_EVENTID = 0x182b, | 845 | WMI_SW_TX_COMPLETE_EVENTID = 0x182b, |
741 | WMI_RX_OFF_DONE_EVENTID = 0x182c, | ||
742 | 846 | ||
743 | WMI_READ_MAC_RXQ_EVENTID = 0x1830, | 847 | WMI_READ_MAC_RXQ_EVENTID = 0x1830, |
744 | WMI_READ_MAC_TXQ_EVENTID = 0x1831, | 848 | WMI_READ_MAC_TXQ_EVENTID = 0x1831, |
@@ -765,7 +869,16 @@ enum wmi_event_id { | |||
765 | WMI_UNIT_TEST_EVENTID = 0x1900, | 869 | WMI_UNIT_TEST_EVENTID = 0x1900, |
766 | WMI_FLASH_READ_DONE_EVENTID = 0x1902, | 870 | WMI_FLASH_READ_DONE_EVENTID = 0x1902, |
767 | WMI_FLASH_WRITE_DONE_EVENTID = 0x1903, | 871 | WMI_FLASH_WRITE_DONE_EVENTID = 0x1903, |
768 | 872 | /*P2P*/ | |
873 | WMI_PORT_ALLOCATED_EVENTID = 0x1911, | ||
874 | WMI_PORT_DELETED_EVENTID = 0x1912, | ||
875 | WMI_LISTEN_STARTED_EVENTID = 0x1914, | ||
876 | WMI_SEARCH_STARTED_EVENTID = 0x1915, | ||
877 | WMI_DISCOVERY_STARTED_EVENTID = 0x1916, | ||
878 | WMI_DISCOVERY_STOPPED_EVENTID = 0x1917, | ||
879 | WMI_PCP_STARTED_EVENTID = 0x1918, | ||
880 | WMI_PCP_STOPPED_EVENTID = 0x1919, | ||
881 | WMI_PCP_FACTOR_EVENTID = 0x191a, | ||
769 | WMI_SET_CHANNEL_EVENTID = 0x9000, | 882 | WMI_SET_CHANNEL_EVENTID = 0x9000, |
770 | WMI_ASSOC_REQ_EVENTID = 0x9001, | 883 | WMI_ASSOC_REQ_EVENTID = 0x9001, |
771 | WMI_EAPOL_RX_EVENTID = 0x9002, | 884 | WMI_EAPOL_RX_EVENTID = 0x9002, |
@@ -777,6 +890,12 @@ enum wmi_event_id { | |||
777 | * Events data structures | 890 | * Events data structures |
778 | */ | 891 | */ |
779 | 892 | ||
893 | |||
894 | enum wmi_fw_status { | ||
895 | WMI_FW_STATUS_SUCCESS, | ||
896 | WMI_FW_STATUS_FAILURE, | ||
897 | }; | ||
898 | |||
780 | /* | 899 | /* |
781 | * WMI_RF_MGMT_STATUS_EVENTID | 900 | * WMI_RF_MGMT_STATUS_EVENTID |
782 | */ | 901 | */ |
@@ -857,7 +976,7 @@ struct wmi_ready_event { | |||
857 | __le32 abi_version; | 976 | __le32 abi_version; |
858 | u8 mac[WMI_MAC_LEN]; | 977 | u8 mac[WMI_MAC_LEN]; |
859 | u8 phy_capability; /* enum wmi_phy_capability */ | 978 | u8 phy_capability; /* enum wmi_phy_capability */ |
860 | u8 reserved; | 979 | u8 numof_additional_mids; |
861 | } __packed; | 980 | } __packed; |
862 | 981 | ||
863 | /* | 982 | /* |
@@ -876,6 +995,8 @@ struct wmi_notify_req_done_event { | |||
876 | __le16 other_rx_sector; | 995 | __le16 other_rx_sector; |
877 | __le16 other_tx_sector; | 996 | __le16 other_tx_sector; |
878 | __le16 range; | 997 | __le16 range; |
998 | u8 sqi; | ||
999 | u8 reserved[3]; | ||
879 | } __packed; | 1000 | } __packed; |
880 | 1001 | ||
881 | /* | 1002 | /* |
@@ -951,27 +1072,15 @@ struct wmi_vring_ba_status_event { | |||
951 | * WMI_DELBA_EVENTID | 1072 | * WMI_DELBA_EVENTID |
952 | */ | 1073 | */ |
953 | struct wmi_delba_event { | 1074 | struct wmi_delba_event { |
954 | |||
955 | #define CIDXTID_CID_POS (0) | ||
956 | #define CIDXTID_CID_LEN (4) | ||
957 | #define CIDXTID_CID_MSK (0xF) | ||
958 | #define CIDXTID_TID_POS (4) | ||
959 | #define CIDXTID_TID_LEN (4) | ||
960 | #define CIDXTID_TID_MSK (0xF0) | ||
961 | u8 cidxtid; | 1075 | u8 cidxtid; |
962 | |||
963 | u8 from_initiator; | 1076 | u8 from_initiator; |
964 | __le16 reason; | 1077 | __le16 reason; |
965 | } __packed; | 1078 | } __packed; |
966 | 1079 | ||
1080 | |||
967 | /* | 1081 | /* |
968 | * WMI_VRING_CFG_DONE_EVENTID | 1082 | * WMI_VRING_CFG_DONE_EVENTID |
969 | */ | 1083 | */ |
970 | enum wmi_vring_cfg_done_event_status { | ||
971 | WMI_VRING_CFG_SUCCESS = 0, | ||
972 | WMI_VRING_CFG_FAILURE = 1, | ||
973 | }; | ||
974 | |||
975 | struct wmi_vring_cfg_done_event { | 1084 | struct wmi_vring_cfg_done_event { |
976 | u8 ringid; | 1085 | u8 ringid; |
977 | u8 status; | 1086 | u8 status; |
@@ -982,21 +1091,8 @@ struct wmi_vring_cfg_done_event { | |||
982 | /* | 1091 | /* |
983 | * WMI_ADDBA_RESP_SENT_EVENTID | 1092 | * WMI_ADDBA_RESP_SENT_EVENTID |
984 | */ | 1093 | */ |
985 | enum wmi_rcp_addba_resp_sent_event_status { | ||
986 | WMI_ADDBA_SUCCESS = 0, | ||
987 | WMI_ADDBA_FAIL = 1, | ||
988 | }; | ||
989 | |||
990 | struct wmi_rcp_addba_resp_sent_event { | 1094 | struct wmi_rcp_addba_resp_sent_event { |
991 | |||
992 | #define CIDXTID_CID_POS (0) | ||
993 | #define CIDXTID_CID_LEN (4) | ||
994 | #define CIDXTID_CID_MSK (0xF) | ||
995 | #define CIDXTID_TID_POS (4) | ||
996 | #define CIDXTID_TID_LEN (4) | ||
997 | #define CIDXTID_TID_MSK (0xF0) | ||
998 | u8 cidxtid; | 1095 | u8 cidxtid; |
999 | |||
1000 | u8 reserved; | 1096 | u8 reserved; |
1001 | __le16 status; | 1097 | __le16 status; |
1002 | } __packed; | 1098 | } __packed; |
@@ -1005,15 +1101,7 @@ struct wmi_rcp_addba_resp_sent_event { | |||
1005 | * WMI_RCP_ADDBA_REQ_EVENTID | 1101 | * WMI_RCP_ADDBA_REQ_EVENTID |
1006 | */ | 1102 | */ |
1007 | struct wmi_rcp_addba_req_event { | 1103 | struct wmi_rcp_addba_req_event { |
1008 | |||
1009 | #define CIDXTID_CID_POS (0) | ||
1010 | #define CIDXTID_CID_LEN (4) | ||
1011 | #define CIDXTID_CID_MSK (0xF) | ||
1012 | #define CIDXTID_TID_POS (4) | ||
1013 | #define CIDXTID_TID_LEN (4) | ||
1014 | #define CIDXTID_TID_MSK (0xF0) | ||
1015 | u8 cidxtid; | 1104 | u8 cidxtid; |
1016 | |||
1017 | u8 dialog_token; | 1105 | u8 dialog_token; |
1018 | __le16 ba_param_set; /* ieee80211_ba_parameterset as it received */ | 1106 | __le16 ba_param_set; /* ieee80211_ba_parameterset as it received */ |
1019 | __le16 ba_timeout; | 1107 | __le16 ba_timeout; |
@@ -1055,6 +1143,7 @@ struct wmi_data_port_open_event { | |||
1055 | u8 reserved[3]; | 1143 | u8 reserved[3]; |
1056 | } __packed; | 1144 | } __packed; |
1057 | 1145 | ||
1146 | |||
1058 | /* | 1147 | /* |
1059 | * WMI_GET_PCP_CHANNEL_EVENTID | 1148 | * WMI_GET_PCP_CHANNEL_EVENTID |
1060 | */ | 1149 | */ |
@@ -1063,6 +1152,54 @@ struct wmi_get_pcp_channel_event { | |||
1063 | u8 reserved[3]; | 1152 | u8 reserved[3]; |
1064 | } __packed; | 1153 | } __packed; |
1065 | 1154 | ||
1155 | |||
1156 | /* | ||
1157 | * WMI_PORT_ALLOCATED_EVENTID | ||
1158 | */ | ||
1159 | struct wmi_port_allocated_event { | ||
1160 | u8 status; /* wmi_fw_status */ | ||
1161 | u8 reserved[3]; | ||
1162 | } __packed; | ||
1163 | |||
1164 | /* | ||
1165 | * WMI_PORT_DELETED_EVENTID | ||
1166 | */ | ||
1167 | struct wmi_port_deleted_event { | ||
1168 | u8 status; /* wmi_fw_status */ | ||
1169 | u8 reserved[3]; | ||
1170 | } __packed; | ||
1171 | |||
1172 | /* | ||
1173 | * WMI_LISTEN_STARTED_EVENTID | ||
1174 | */ | ||
1175 | struct wmi_listen_started_event { | ||
1176 | u8 status; /* wmi_fw_status */ | ||
1177 | u8 reserved[3]; | ||
1178 | } __packed; | ||
1179 | |||
1180 | /* | ||
1181 | * WMI_SEARCH_STARTED_EVENTID | ||
1182 | */ | ||
1183 | struct wmi_search_started_event { | ||
1184 | u8 status; /* wmi_fw_status */ | ||
1185 | u8 reserved[3]; | ||
1186 | } __packed; | ||
1187 | |||
1188 | /* | ||
1189 | * WMI_PCP_STARTED_EVENTID | ||
1190 | */ | ||
1191 | struct wmi_pcp_started_event { | ||
1192 | u8 status; /* wmi_fw_status */ | ||
1193 | u8 reserved[3]; | ||
1194 | } __packed; | ||
1195 | |||
1196 | /* | ||
1197 | * WMI_PCP_FACTOR_EVENTID | ||
1198 | */ | ||
1199 | struct wmi_pcp_factor_event { | ||
1200 | __le32 pcp_factor; | ||
1201 | } __packed; | ||
1202 | |||
1066 | /* | 1203 | /* |
1067 | * WMI_SW_TX_COMPLETE_EVENTID | 1204 | * WMI_SW_TX_COMPLETE_EVENTID |
1068 | */ | 1205 | */ |
@@ -1078,6 +1215,23 @@ struct wmi_sw_tx_complete_event { | |||
1078 | } __packed; | 1215 | } __packed; |
1079 | 1216 | ||
1080 | /* | 1217 | /* |
1218 | * WMI_CORR_MEASURE_EVENTID | ||
1219 | */ | ||
1220 | struct wmi_corr_measure_event { | ||
1221 | s32 i; | ||
1222 | s32 q; | ||
1223 | s32 image_i; | ||
1224 | s32 image_q; | ||
1225 | } __packed; | ||
1226 | |||
1227 | /* | ||
1228 | * WMI_READ_RSSI_EVENTID | ||
1229 | */ | ||
1230 | struct wmi_read_rssi_event { | ||
1231 | __le32 ina_rssi_adc_dbm; | ||
1232 | } __packed; | ||
1233 | |||
1234 | /* | ||
1081 | * WMI_GET_SSID_EVENTID | 1235 | * WMI_GET_SSID_EVENTID |
1082 | */ | 1236 | */ |
1083 | struct wmi_get_ssid_event { | 1237 | struct wmi_get_ssid_event { |
@@ -1091,7 +1245,8 @@ struct wmi_get_ssid_event { | |||
1091 | struct wmi_rx_mgmt_info { | 1245 | struct wmi_rx_mgmt_info { |
1092 | u8 mcs; | 1246 | u8 mcs; |
1093 | s8 snr; | 1247 | s8 snr; |
1094 | __le16 range; | 1248 | u8 range; |
1249 | u8 sqi; | ||
1095 | __le16 stype; | 1250 | __le16 stype; |
1096 | __le16 status; | 1251 | __le16 status; |
1097 | __le32 len; | 1252 | __le32 len; |
@@ -1113,4 +1268,14 @@ struct wmi_echo_event { | |||
1113 | __le32 echoed_value; | 1268 | __le32 echoed_value; |
1114 | } __packed; | 1269 | } __packed; |
1115 | 1270 | ||
1271 | /* | ||
1272 | * WMI_TEMP_SENSE_DONE_EVENTID | ||
1273 | * | ||
1274 | * Measure MAC and radio temperatures | ||
1275 | */ | ||
1276 | struct wmi_temp_sense_done_event { | ||
1277 | __le32 marlon_m_t1000; | ||
1278 | __le32 marlon_r_t1000; | ||
1279 | } __packed; | ||
1280 | |||
1116 | #endif /* __WILOCITY_WMI_H__ */ | 1281 | #endif /* __WILOCITY_WMI_H__ */ |
diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig index 287c6b670a36..078e6f3477a9 100644 --- a/drivers/net/wireless/b43/Kconfig +++ b/drivers/net/wireless/b43/Kconfig | |||
@@ -131,7 +131,7 @@ config B43_PHY_LP | |||
131 | 131 | ||
132 | config B43_PHY_HT | 132 | config B43_PHY_HT |
133 | bool "Support for HT-PHY (high throughput) devices" | 133 | bool "Support for HT-PHY (high throughput) devices" |
134 | depends on B43 | 134 | depends on B43 && B43_BCMA |
135 | ---help--- | 135 | ---help--- |
136 | Support for the HT-PHY. | 136 | Support for the HT-PHY. |
137 | 137 | ||
@@ -166,8 +166,8 @@ config B43_DEBUG | |||
166 | Broadcom 43xx debugging. | 166 | Broadcom 43xx debugging. |
167 | 167 | ||
168 | This adds additional runtime sanity checks and statistics to the driver. | 168 | This adds additional runtime sanity checks and statistics to the driver. |
169 | These checks and statistics might me expensive and hurt runtime performance | 169 | These checks and statistics might be expensive and hurt the runtime |
170 | of your system. | 170 | performance of your system. |
171 | This also adds the b43 debugfs interface. | 171 | This also adds the b43 debugfs interface. |
172 | 172 | ||
173 | Do not enable this, unless you are debugging the driver. | 173 | Do not enable this, unless you are debugging the driver. |
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 10e288d470e7..fe4a77ee05c9 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h | |||
@@ -473,6 +473,12 @@ enum { | |||
473 | #define B43_MACCMD_CCA 0x00000008 /* Clear channel assessment */ | 473 | #define B43_MACCMD_CCA 0x00000008 /* Clear channel assessment */ |
474 | #define B43_MACCMD_BGNOISE 0x00000010 /* Background noise */ | 474 | #define B43_MACCMD_BGNOISE 0x00000010 /* Background noise */ |
475 | 475 | ||
476 | /* See BCMA_CLKCTLST_EXTRESREQ and BCMA_CLKCTLST_EXTRESST */ | ||
477 | #define B43_BCMA_CLKCTLST_80211_PLL_REQ 0x00000100 | ||
478 | #define B43_BCMA_CLKCTLST_PHY_PLL_REQ 0x00000200 | ||
479 | #define B43_BCMA_CLKCTLST_80211_PLL_ST 0x01000000 | ||
480 | #define B43_BCMA_CLKCTLST_PHY_PLL_ST 0x02000000 | ||
481 | |||
476 | /* BCMA 802.11 core specific IO Control (BCMA_IOCTL) flags */ | 482 | /* BCMA 802.11 core specific IO Control (BCMA_IOCTL) flags */ |
477 | #define B43_BCMA_IOCTL_PHY_CLKEN 0x00000004 /* PHY Clock Enable */ | 483 | #define B43_BCMA_IOCTL_PHY_CLKEN 0x00000004 /* PHY Clock Enable */ |
478 | #define B43_BCMA_IOCTL_PHY_RESET 0x00000008 /* PHY Reset */ | 484 | #define B43_BCMA_IOCTL_PHY_RESET 0x00000008 /* PHY Reset */ |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 05682736e466..c4d0cc582555 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -1189,10 +1189,15 @@ static void b43_bcma_phy_reset(struct b43_wldev *dev) | |||
1189 | 1189 | ||
1190 | static void b43_bcma_wireless_core_reset(struct b43_wldev *dev, bool gmode) | 1190 | static void b43_bcma_wireless_core_reset(struct b43_wldev *dev, bool gmode) |
1191 | { | 1191 | { |
1192 | u32 req = B43_BCMA_CLKCTLST_80211_PLL_REQ | | ||
1193 | B43_BCMA_CLKCTLST_PHY_PLL_REQ; | ||
1194 | u32 status = B43_BCMA_CLKCTLST_80211_PLL_ST | | ||
1195 | B43_BCMA_CLKCTLST_PHY_PLL_ST; | ||
1196 | |||
1192 | b43_device_enable(dev, B43_BCMA_IOCTL_PHY_CLKEN); | 1197 | b43_device_enable(dev, B43_BCMA_IOCTL_PHY_CLKEN); |
1193 | bcma_core_set_clockmode(dev->dev->bdev, BCMA_CLKMODE_FAST); | 1198 | bcma_core_set_clockmode(dev->dev->bdev, BCMA_CLKMODE_FAST); |
1194 | b43_bcma_phy_reset(dev); | 1199 | b43_bcma_phy_reset(dev); |
1195 | bcma_core_pll_ctl(dev->dev->bdev, 0x300, 0x3000000, true); | 1200 | bcma_core_pll_ctl(dev->dev->bdev, req, status, true); |
1196 | } | 1201 | } |
1197 | #endif | 1202 | #endif |
1198 | 1203 | ||
diff --git a/drivers/net/wireless/b43/phy_ht.c b/drivers/net/wireless/b43/phy_ht.c index 7416c5e9154d..b8667706fc27 100644 --- a/drivers/net/wireless/b43/phy_ht.c +++ b/drivers/net/wireless/b43/phy_ht.c | |||
@@ -154,9 +154,84 @@ static void b43_radio_2059_init(struct b43_wldev *dev) | |||
154 | } | 154 | } |
155 | 155 | ||
156 | /************************************************** | 156 | /************************************************** |
157 | * RF | ||
158 | **************************************************/ | ||
159 | |||
160 | static void b43_phy_ht_force_rf_sequence(struct b43_wldev *dev, u16 rf_seq) | ||
161 | { | ||
162 | u8 i; | ||
163 | |||
164 | u16 save_seq_mode = b43_phy_read(dev, B43_PHY_HT_RF_SEQ_MODE); | ||
165 | b43_phy_set(dev, B43_PHY_HT_RF_SEQ_MODE, 0x3); | ||
166 | |||
167 | b43_phy_set(dev, B43_PHY_HT_RF_SEQ_TRIG, rf_seq); | ||
168 | for (i = 0; i < 200; i++) { | ||
169 | if (!(b43_phy_read(dev, B43_PHY_HT_RF_SEQ_STATUS) & rf_seq)) { | ||
170 | i = 0; | ||
171 | break; | ||
172 | } | ||
173 | msleep(1); | ||
174 | } | ||
175 | if (i) | ||
176 | b43err(dev->wl, "Forcing RF sequence timeout\n"); | ||
177 | |||
178 | b43_phy_write(dev, B43_PHY_HT_RF_SEQ_MODE, save_seq_mode); | ||
179 | } | ||
180 | |||
181 | static void b43_phy_ht_pa_override(struct b43_wldev *dev, bool enable) | ||
182 | { | ||
183 | struct b43_phy_ht *htphy = dev->phy.ht; | ||
184 | static const u16 regs[3] = { B43_PHY_HT_RF_CTL_INT_C1, | ||
185 | B43_PHY_HT_RF_CTL_INT_C2, | ||
186 | B43_PHY_HT_RF_CTL_INT_C3 }; | ||
187 | int i; | ||
188 | |||
189 | if (enable) { | ||
190 | for (i = 0; i < 3; i++) | ||
191 | b43_phy_write(dev, regs[i], htphy->rf_ctl_int_save[i]); | ||
192 | } else { | ||
193 | for (i = 0; i < 3; i++) | ||
194 | htphy->rf_ctl_int_save[i] = b43_phy_read(dev, regs[i]); | ||
195 | /* TODO: Does 5GHz band use different value (not 0x0400)? */ | ||
196 | for (i = 0; i < 3; i++) | ||
197 | b43_phy_write(dev, regs[i], 0x0400); | ||
198 | } | ||
199 | } | ||
200 | |||
201 | /************************************************** | ||
157 | * Various PHY ops | 202 | * Various PHY ops |
158 | **************************************************/ | 203 | **************************************************/ |
159 | 204 | ||
205 | static u16 b43_phy_ht_classifier(struct b43_wldev *dev, u16 mask, u16 val) | ||
206 | { | ||
207 | u16 tmp; | ||
208 | u16 allowed = B43_PHY_HT_CLASS_CTL_CCK_EN | | ||
209 | B43_PHY_HT_CLASS_CTL_OFDM_EN | | ||
210 | B43_PHY_HT_CLASS_CTL_WAITED_EN; | ||
211 | |||
212 | tmp = b43_phy_read(dev, B43_PHY_HT_CLASS_CTL); | ||
213 | tmp &= allowed; | ||
214 | tmp &= ~mask; | ||
215 | tmp |= (val & mask); | ||
216 | b43_phy_maskset(dev, B43_PHY_HT_CLASS_CTL, ~allowed, tmp); | ||
217 | |||
218 | return tmp; | ||
219 | } | ||
220 | |||
221 | static void b43_phy_ht_reset_cca(struct b43_wldev *dev) | ||
222 | { | ||
223 | u16 bbcfg; | ||
224 | |||
225 | b43_phy_force_clock(dev, true); | ||
226 | bbcfg = b43_phy_read(dev, B43_PHY_HT_BBCFG); | ||
227 | b43_phy_write(dev, B43_PHY_HT_BBCFG, bbcfg | B43_PHY_HT_BBCFG_RSTCCA); | ||
228 | udelay(1); | ||
229 | b43_phy_write(dev, B43_PHY_HT_BBCFG, bbcfg & ~B43_PHY_HT_BBCFG_RSTCCA); | ||
230 | b43_phy_force_clock(dev, false); | ||
231 | |||
232 | b43_phy_ht_force_rf_sequence(dev, B43_PHY_HT_RF_SEQ_TRIG_RST2RX); | ||
233 | } | ||
234 | |||
160 | static void b43_phy_ht_zero_extg(struct b43_wldev *dev) | 235 | static void b43_phy_ht_zero_extg(struct b43_wldev *dev) |
161 | { | 236 | { |
162 | u8 i, j; | 237 | u8 i, j; |
@@ -176,10 +251,10 @@ static void b43_phy_ht_afe_unk1(struct b43_wldev *dev) | |||
176 | { | 251 | { |
177 | u8 i; | 252 | u8 i; |
178 | 253 | ||
179 | const u16 ctl_regs[3][2] = { | 254 | static const u16 ctl_regs[3][2] = { |
180 | { B43_PHY_HT_AFE_CTL1, B43_PHY_HT_AFE_CTL2 }, | 255 | { B43_PHY_HT_AFE_C1_OVER, B43_PHY_HT_AFE_C1 }, |
181 | { B43_PHY_HT_AFE_CTL3, B43_PHY_HT_AFE_CTL4 }, | 256 | { B43_PHY_HT_AFE_C2_OVER, B43_PHY_HT_AFE_C2 }, |
182 | { B43_PHY_HT_AFE_CTL5, B43_PHY_HT_AFE_CTL6}, | 257 | { B43_PHY_HT_AFE_C3_OVER, B43_PHY_HT_AFE_C3}, |
183 | }; | 258 | }; |
184 | 259 | ||
185 | for (i = 0; i < 3; i++) { | 260 | for (i = 0; i < 3; i++) { |
@@ -193,27 +268,6 @@ static void b43_phy_ht_afe_unk1(struct b43_wldev *dev) | |||
193 | } | 268 | } |
194 | } | 269 | } |
195 | 270 | ||
196 | static void b43_phy_ht_force_rf_sequence(struct b43_wldev *dev, u16 rf_seq) | ||
197 | { | ||
198 | u8 i; | ||
199 | |||
200 | u16 save_seq_mode = b43_phy_read(dev, B43_PHY_HT_RF_SEQ_MODE); | ||
201 | b43_phy_set(dev, B43_PHY_HT_RF_SEQ_MODE, 0x3); | ||
202 | |||
203 | b43_phy_set(dev, B43_PHY_HT_RF_SEQ_TRIG, rf_seq); | ||
204 | for (i = 0; i < 200; i++) { | ||
205 | if (!(b43_phy_read(dev, B43_PHY_HT_RF_SEQ_STATUS) & rf_seq)) { | ||
206 | i = 0; | ||
207 | break; | ||
208 | } | ||
209 | msleep(1); | ||
210 | } | ||
211 | if (i) | ||
212 | b43err(dev->wl, "Forcing RF sequence timeout\n"); | ||
213 | |||
214 | b43_phy_write(dev, B43_PHY_HT_RF_SEQ_MODE, save_seq_mode); | ||
215 | } | ||
216 | |||
217 | static void b43_phy_ht_read_clip_detection(struct b43_wldev *dev, u16 *clip_st) | 271 | static void b43_phy_ht_read_clip_detection(struct b43_wldev *dev, u16 *clip_st) |
218 | { | 272 | { |
219 | clip_st[0] = b43_phy_read(dev, B43_PHY_HT_C1_CLIP1THRES); | 273 | clip_st[0] = b43_phy_read(dev, B43_PHY_HT_C1_CLIP1THRES); |
@@ -240,15 +294,426 @@ static void b43_phy_ht_bphy_init(struct b43_wldev *dev) | |||
240 | } | 294 | } |
241 | 295 | ||
242 | /************************************************** | 296 | /************************************************** |
297 | * Samples | ||
298 | **************************************************/ | ||
299 | |||
300 | static void b43_phy_ht_stop_playback(struct b43_wldev *dev) | ||
301 | { | ||
302 | struct b43_phy_ht *phy_ht = dev->phy.ht; | ||
303 | u16 tmp; | ||
304 | int i; | ||
305 | |||
306 | tmp = b43_phy_read(dev, B43_PHY_HT_SAMP_STAT); | ||
307 | if (tmp & 0x1) | ||
308 | b43_phy_set(dev, B43_PHY_HT_SAMP_CMD, B43_PHY_HT_SAMP_CMD_STOP); | ||
309 | else if (tmp & 0x2) | ||
310 | b43_phy_mask(dev, B43_PHY_HT_IQLOCAL_CMDGCTL, 0x7FFF); | ||
311 | |||
312 | b43_phy_mask(dev, B43_PHY_HT_SAMP_CMD, ~0x0004); | ||
313 | |||
314 | for (i = 0; i < 3; i++) { | ||
315 | if (phy_ht->bb_mult_save[i] >= 0) { | ||
316 | b43_httab_write(dev, B43_HTTAB16(13, 0x63 + i * 4), | ||
317 | phy_ht->bb_mult_save[i]); | ||
318 | b43_httab_write(dev, B43_HTTAB16(13, 0x67 + i * 4), | ||
319 | phy_ht->bb_mult_save[i]); | ||
320 | } | ||
321 | } | ||
322 | } | ||
323 | |||
324 | static u16 b43_phy_ht_load_samples(struct b43_wldev *dev) | ||
325 | { | ||
326 | int i; | ||
327 | u16 len = 20 << 3; | ||
328 | |||
329 | b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, 0x4400); | ||
330 | |||
331 | for (i = 0; i < len; i++) { | ||
332 | b43_phy_write(dev, B43_PHY_HT_TABLE_DATAHI, 0); | ||
333 | b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, 0); | ||
334 | } | ||
335 | |||
336 | return len; | ||
337 | } | ||
338 | |||
339 | static void b43_phy_ht_run_samples(struct b43_wldev *dev, u16 samps, u16 loops, | ||
340 | u16 wait) | ||
341 | { | ||
342 | struct b43_phy_ht *phy_ht = dev->phy.ht; | ||
343 | u16 save_seq_mode; | ||
344 | int i; | ||
345 | |||
346 | for (i = 0; i < 3; i++) { | ||
347 | if (phy_ht->bb_mult_save[i] < 0) | ||
348 | phy_ht->bb_mult_save[i] = b43_httab_read(dev, B43_HTTAB16(13, 0x63 + i * 4)); | ||
349 | } | ||
350 | |||
351 | b43_phy_write(dev, B43_PHY_HT_SAMP_DEP_CNT, samps - 1); | ||
352 | if (loops != 0xFFFF) | ||
353 | loops--; | ||
354 | b43_phy_write(dev, B43_PHY_HT_SAMP_LOOP_CNT, loops); | ||
355 | b43_phy_write(dev, B43_PHY_HT_SAMP_WAIT_CNT, wait); | ||
356 | |||
357 | save_seq_mode = b43_phy_read(dev, B43_PHY_HT_RF_SEQ_MODE); | ||
358 | b43_phy_set(dev, B43_PHY_HT_RF_SEQ_MODE, | ||
359 | B43_PHY_HT_RF_SEQ_MODE_CA_OVER); | ||
360 | |||
361 | /* TODO: find out mask bits! Do we need more function arguments? */ | ||
362 | b43_phy_mask(dev, B43_PHY_HT_SAMP_CMD, ~0); | ||
363 | b43_phy_mask(dev, B43_PHY_HT_SAMP_CMD, ~0); | ||
364 | b43_phy_mask(dev, B43_PHY_HT_IQLOCAL_CMDGCTL, ~0); | ||
365 | b43_phy_set(dev, B43_PHY_HT_SAMP_CMD, 0x1); | ||
366 | |||
367 | for (i = 0; i < 100; i++) { | ||
368 | if (!(b43_phy_read(dev, B43_PHY_HT_RF_SEQ_STATUS) & 1)) { | ||
369 | i = 0; | ||
370 | break; | ||
371 | } | ||
372 | udelay(10); | ||
373 | } | ||
374 | if (i) | ||
375 | b43err(dev->wl, "run samples timeout\n"); | ||
376 | |||
377 | b43_phy_write(dev, B43_PHY_HT_RF_SEQ_MODE, save_seq_mode); | ||
378 | } | ||
379 | |||
380 | static void b43_phy_ht_tx_tone(struct b43_wldev *dev) | ||
381 | { | ||
382 | u16 samp; | ||
383 | |||
384 | samp = b43_phy_ht_load_samples(dev); | ||
385 | b43_phy_ht_run_samples(dev, samp, 0xFFFF, 0); | ||
386 | } | ||
387 | |||
388 | /************************************************** | ||
389 | * RSSI | ||
390 | **************************************************/ | ||
391 | |||
392 | static void b43_phy_ht_rssi_select(struct b43_wldev *dev, u8 core_sel, | ||
393 | u8 rssi_type) | ||
394 | { | ||
395 | static const u16 ctl_regs[3][2] = { | ||
396 | { B43_PHY_HT_AFE_C1, B43_PHY_HT_AFE_C1_OVER, }, | ||
397 | { B43_PHY_HT_AFE_C2, B43_PHY_HT_AFE_C2_OVER, }, | ||
398 | { B43_PHY_HT_AFE_C3, B43_PHY_HT_AFE_C3_OVER, }, | ||
399 | }; | ||
400 | static const u16 radio_r[] = { R2059_SYN, R2059_TXRX0, R2059_RXRX1, }; | ||
401 | int core; | ||
402 | |||
403 | if (core_sel == 0) { | ||
404 | b43err(dev->wl, "RSSI selection for core off not implemented yet\n"); | ||
405 | } else { | ||
406 | for (core = 0; core < 3; core++) { | ||
407 | /* Check if caller requested a one specific core */ | ||
408 | if ((core_sel == 1 && core != 0) || | ||
409 | (core_sel == 2 && core != 1) || | ||
410 | (core_sel == 3 && core != 2)) | ||
411 | continue; | ||
412 | |||
413 | switch (rssi_type) { | ||
414 | case 4: | ||
415 | b43_phy_set(dev, ctl_regs[core][0], 0x3 << 8); | ||
416 | b43_phy_set(dev, ctl_regs[core][0], 0x3 << 10); | ||
417 | b43_phy_set(dev, ctl_regs[core][1], 0x1 << 9); | ||
418 | b43_phy_set(dev, ctl_regs[core][1], 0x1 << 10); | ||
419 | |||
420 | b43_radio_set(dev, R2059_RXRX1 | 0xbf, 0x1); | ||
421 | b43_radio_write(dev, radio_r[core] | 0x159, | ||
422 | 0x11); | ||
423 | break; | ||
424 | default: | ||
425 | b43err(dev->wl, "RSSI selection for type %d not implemented yet\n", | ||
426 | rssi_type); | ||
427 | } | ||
428 | } | ||
429 | } | ||
430 | } | ||
431 | |||
432 | static void b43_phy_ht_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf, | ||
433 | u8 nsamp) | ||
434 | { | ||
435 | u16 phy_regs_values[12]; | ||
436 | static const u16 phy_regs_to_save[] = { | ||
437 | B43_PHY_HT_AFE_C1, B43_PHY_HT_AFE_C1_OVER, | ||
438 | 0x848, 0x841, | ||
439 | B43_PHY_HT_AFE_C2, B43_PHY_HT_AFE_C2_OVER, | ||
440 | 0x868, 0x861, | ||
441 | B43_PHY_HT_AFE_C3, B43_PHY_HT_AFE_C3_OVER, | ||
442 | 0x888, 0x881, | ||
443 | }; | ||
444 | u16 tmp[3]; | ||
445 | int i; | ||
446 | |||
447 | for (i = 0; i < 12; i++) | ||
448 | phy_regs_values[i] = b43_phy_read(dev, phy_regs_to_save[i]); | ||
449 | |||
450 | b43_phy_ht_rssi_select(dev, 5, type); | ||
451 | |||
452 | for (i = 0; i < 6; i++) | ||
453 | buf[i] = 0; | ||
454 | |||
455 | for (i = 0; i < nsamp; i++) { | ||
456 | tmp[0] = b43_phy_read(dev, B43_PHY_HT_RSSI_C1); | ||
457 | tmp[1] = b43_phy_read(dev, B43_PHY_HT_RSSI_C2); | ||
458 | tmp[2] = b43_phy_read(dev, B43_PHY_HT_RSSI_C3); | ||
459 | |||
460 | buf[0] += ((s8)((tmp[0] & 0x3F) << 2)) >> 2; | ||
461 | buf[1] += ((s8)(((tmp[0] >> 8) & 0x3F) << 2)) >> 2; | ||
462 | buf[2] += ((s8)((tmp[1] & 0x3F) << 2)) >> 2; | ||
463 | buf[3] += ((s8)(((tmp[1] >> 8) & 0x3F) << 2)) >> 2; | ||
464 | buf[4] += ((s8)((tmp[2] & 0x3F) << 2)) >> 2; | ||
465 | buf[5] += ((s8)(((tmp[2] >> 8) & 0x3F) << 2)) >> 2; | ||
466 | } | ||
467 | |||
468 | for (i = 0; i < 12; i++) | ||
469 | b43_phy_write(dev, phy_regs_to_save[i], phy_regs_values[i]); | ||
470 | } | ||
471 | |||
472 | /************************************************** | ||
473 | * Tx/Rx | ||
474 | **************************************************/ | ||
475 | |||
476 | static void b43_phy_ht_tx_power_fix(struct b43_wldev *dev) | ||
477 | { | ||
478 | int i; | ||
479 | |||
480 | for (i = 0; i < 3; i++) { | ||
481 | u16 mask; | ||
482 | u32 tmp = b43_httab_read(dev, B43_HTTAB32(26, 0xE8)); | ||
483 | |||
484 | if (0) /* FIXME */ | ||
485 | mask = 0x2 << (i * 4); | ||
486 | else | ||
487 | mask = 0; | ||
488 | b43_phy_mask(dev, B43_PHY_EXTG(0x108), mask); | ||
489 | |||
490 | b43_httab_write(dev, B43_HTTAB16(7, 0x110 + i), tmp >> 16); | ||
491 | b43_httab_write(dev, B43_HTTAB8(13, 0x63 + (i * 4)), | ||
492 | tmp & 0xFF); | ||
493 | b43_httab_write(dev, B43_HTTAB8(13, 0x73 + (i * 4)), | ||
494 | tmp & 0xFF); | ||
495 | } | ||
496 | } | ||
497 | |||
498 | static void b43_phy_ht_tx_power_ctl(struct b43_wldev *dev, bool enable) | ||
499 | { | ||
500 | struct b43_phy_ht *phy_ht = dev->phy.ht; | ||
501 | u16 en_bits = B43_PHY_HT_TXPCTL_CMD_C1_COEFF | | ||
502 | B43_PHY_HT_TXPCTL_CMD_C1_HWPCTLEN | | ||
503 | B43_PHY_HT_TXPCTL_CMD_C1_PCTLEN; | ||
504 | static const u16 cmd_regs[3] = { B43_PHY_HT_TXPCTL_CMD_C1, | ||
505 | B43_PHY_HT_TXPCTL_CMD_C2, | ||
506 | B43_PHY_HT_TXPCTL_CMD_C3 }; | ||
507 | int i; | ||
508 | |||
509 | if (!enable) { | ||
510 | if (b43_phy_read(dev, B43_PHY_HT_TXPCTL_CMD_C1) & en_bits) { | ||
511 | /* We disable enabled TX pwr ctl, save it's state */ | ||
512 | /* | ||
513 | * TODO: find the registers. On N-PHY they were 0x1ed | ||
514 | * and 0x1ee, we need 3 such a registers for HT-PHY | ||
515 | */ | ||
516 | } | ||
517 | b43_phy_mask(dev, B43_PHY_HT_TXPCTL_CMD_C1, ~en_bits); | ||
518 | } else { | ||
519 | b43_phy_set(dev, B43_PHY_HT_TXPCTL_CMD_C1, en_bits); | ||
520 | |||
521 | if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { | ||
522 | for (i = 0; i < 3; i++) | ||
523 | b43_phy_write(dev, cmd_regs[i], 0x32); | ||
524 | } | ||
525 | |||
526 | for (i = 0; i < 3; i++) | ||
527 | if (phy_ht->tx_pwr_idx[i] <= | ||
528 | B43_PHY_HT_TXPCTL_CMD_C1_INIT) | ||
529 | b43_phy_write(dev, cmd_regs[i], | ||
530 | phy_ht->tx_pwr_idx[i]); | ||
531 | } | ||
532 | |||
533 | phy_ht->tx_pwr_ctl = enable; | ||
534 | } | ||
535 | |||
536 | static void b43_phy_ht_tx_power_ctl_idle_tssi(struct b43_wldev *dev) | ||
537 | { | ||
538 | struct b43_phy_ht *phy_ht = dev->phy.ht; | ||
539 | s32 rssi_buf[6]; | ||
540 | |||
541 | /* TODO */ | ||
542 | |||
543 | b43_phy_ht_tx_tone(dev); | ||
544 | udelay(20); | ||
545 | b43_phy_ht_poll_rssi(dev, 4, rssi_buf, 1); | ||
546 | b43_phy_ht_stop_playback(dev); | ||
547 | b43_phy_ht_reset_cca(dev); | ||
548 | |||
549 | phy_ht->idle_tssi[0] = rssi_buf[0] & 0xff; | ||
550 | phy_ht->idle_tssi[1] = rssi_buf[2] & 0xff; | ||
551 | phy_ht->idle_tssi[2] = rssi_buf[4] & 0xff; | ||
552 | |||
553 | /* TODO */ | ||
554 | } | ||
555 | |||
556 | static void b43_phy_ht_tx_power_ctl_setup(struct b43_wldev *dev) | ||
557 | { | ||
558 | struct b43_phy_ht *phy_ht = dev->phy.ht; | ||
559 | struct ssb_sprom *sprom = dev->dev->bus_sprom; | ||
560 | |||
561 | u8 *idle = phy_ht->idle_tssi; | ||
562 | u8 target[3]; | ||
563 | s16 a1[3], b0[3], b1[3]; | ||
564 | |||
565 | u16 freq = dev->phy.channel_freq; | ||
566 | int i, c; | ||
567 | |||
568 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { | ||
569 | for (c = 0; c < 3; c++) { | ||
570 | target[c] = sprom->core_pwr_info[c].maxpwr_2g; | ||
571 | a1[c] = sprom->core_pwr_info[c].pa_2g[0]; | ||
572 | b0[c] = sprom->core_pwr_info[c].pa_2g[1]; | ||
573 | b1[c] = sprom->core_pwr_info[c].pa_2g[2]; | ||
574 | } | ||
575 | } else if (freq >= 4900 && freq < 5100) { | ||
576 | for (c = 0; c < 3; c++) { | ||
577 | target[c] = sprom->core_pwr_info[c].maxpwr_5gl; | ||
578 | a1[c] = sprom->core_pwr_info[c].pa_5gl[0]; | ||
579 | b0[c] = sprom->core_pwr_info[c].pa_5gl[1]; | ||
580 | b1[c] = sprom->core_pwr_info[c].pa_5gl[2]; | ||
581 | } | ||
582 | } else if (freq >= 5100 && freq < 5500) { | ||
583 | for (c = 0; c < 3; c++) { | ||
584 | target[c] = sprom->core_pwr_info[c].maxpwr_5g; | ||
585 | a1[c] = sprom->core_pwr_info[c].pa_5g[0]; | ||
586 | b0[c] = sprom->core_pwr_info[c].pa_5g[1]; | ||
587 | b1[c] = sprom->core_pwr_info[c].pa_5g[2]; | ||
588 | } | ||
589 | } else if (freq >= 5500) { | ||
590 | for (c = 0; c < 3; c++) { | ||
591 | target[c] = sprom->core_pwr_info[c].maxpwr_5gh; | ||
592 | a1[c] = sprom->core_pwr_info[c].pa_5gh[0]; | ||
593 | b0[c] = sprom->core_pwr_info[c].pa_5gh[1]; | ||
594 | b1[c] = sprom->core_pwr_info[c].pa_5gh[2]; | ||
595 | } | ||
596 | } else { | ||
597 | target[0] = target[1] = target[2] = 52; | ||
598 | a1[0] = a1[1] = a1[2] = -424; | ||
599 | b0[0] = b0[1] = b0[2] = 5612; | ||
600 | b1[0] = b1[1] = b1[2] = -1393; | ||
601 | } | ||
602 | |||
603 | b43_phy_set(dev, B43_PHY_HT_TSSIMODE, B43_PHY_HT_TSSIMODE_EN); | ||
604 | b43_phy_mask(dev, B43_PHY_HT_TXPCTL_CMD_C1, | ||
605 | ~B43_PHY_HT_TXPCTL_CMD_C1_PCTLEN & 0xFFFF); | ||
606 | |||
607 | /* TODO: Does it depend on sprom->fem.ghz2.tssipos? */ | ||
608 | b43_phy_set(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI, 0x4000); | ||
609 | |||
610 | b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C1, | ||
611 | ~B43_PHY_HT_TXPCTL_CMD_C1_INIT, 0x19); | ||
612 | b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C2, | ||
613 | ~B43_PHY_HT_TXPCTL_CMD_C2_INIT, 0x19); | ||
614 | b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C3, | ||
615 | ~B43_PHY_HT_TXPCTL_CMD_C3_INIT, 0x19); | ||
616 | |||
617 | b43_phy_set(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI, | ||
618 | B43_PHY_HT_TXPCTL_IDLE_TSSI_BINF); | ||
619 | |||
620 | b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI, | ||
621 | ~B43_PHY_HT_TXPCTL_IDLE_TSSI_C1, | ||
622 | idle[0] << B43_PHY_HT_TXPCTL_IDLE_TSSI_C1_SHIFT); | ||
623 | b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI, | ||
624 | ~B43_PHY_HT_TXPCTL_IDLE_TSSI_C2, | ||
625 | idle[1] << B43_PHY_HT_TXPCTL_IDLE_TSSI_C2_SHIFT); | ||
626 | b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI2, | ||
627 | ~B43_PHY_HT_TXPCTL_IDLE_TSSI2_C3, | ||
628 | idle[2] << B43_PHY_HT_TXPCTL_IDLE_TSSI2_C3_SHIFT); | ||
629 | |||
630 | b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_N, ~B43_PHY_HT_TXPCTL_N_TSSID, | ||
631 | 0xf0); | ||
632 | b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_N, ~B43_PHY_HT_TXPCTL_N_NPTIL2, | ||
633 | 0x3 << B43_PHY_HT_TXPCTL_N_NPTIL2_SHIFT); | ||
634 | #if 0 | ||
635 | /* TODO: what to mask/set? */ | ||
636 | b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C1, 0x800, 0) | ||
637 | b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C1, 0x400, 0) | ||
638 | #endif | ||
639 | |||
640 | b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_TARG_PWR, | ||
641 | ~B43_PHY_HT_TXPCTL_TARG_PWR_C1, | ||
642 | target[0] << B43_PHY_HT_TXPCTL_TARG_PWR_C1_SHIFT); | ||
643 | b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_TARG_PWR, | ||
644 | ~B43_PHY_HT_TXPCTL_TARG_PWR_C2 & 0xFFFF, | ||
645 | target[1] << B43_PHY_HT_TXPCTL_TARG_PWR_C2_SHIFT); | ||
646 | b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_TARG_PWR2, | ||
647 | ~B43_PHY_HT_TXPCTL_TARG_PWR2_C3, | ||
648 | target[2] << B43_PHY_HT_TXPCTL_TARG_PWR2_C3_SHIFT); | ||
649 | |||
650 | for (c = 0; c < 3; c++) { | ||
651 | s32 num, den, pwr; | ||
652 | u32 regval[64]; | ||
653 | |||
654 | for (i = 0; i < 64; i++) { | ||
655 | num = 8 * (16 * b0[c] + b1[c] * i); | ||
656 | den = 32768 + a1[c] * i; | ||
657 | pwr = max((4 * num + den / 2) / den, -8); | ||
658 | regval[i] = pwr; | ||
659 | } | ||
660 | b43_httab_write_bulk(dev, B43_HTTAB16(26 + c, 0), 64, regval); | ||
661 | } | ||
662 | } | ||
663 | |||
664 | /************************************************** | ||
243 | * Channel switching ops. | 665 | * Channel switching ops. |
244 | **************************************************/ | 666 | **************************************************/ |
245 | 667 | ||
668 | static void b43_phy_ht_spur_avoid(struct b43_wldev *dev, | ||
669 | struct ieee80211_channel *new_channel) | ||
670 | { | ||
671 | struct bcma_device *core = dev->dev->bdev; | ||
672 | int spuravoid = 0; | ||
673 | u16 tmp; | ||
674 | |||
675 | /* Check for 13 and 14 is just a guess, we don't have enough logs. */ | ||
676 | if (new_channel->hw_value == 13 || new_channel->hw_value == 14) | ||
677 | spuravoid = 1; | ||
678 | bcma_core_pll_ctl(core, B43_BCMA_CLKCTLST_PHY_PLL_REQ, 0, false); | ||
679 | bcma_pmu_spuravoid_pllupdate(&core->bus->drv_cc, spuravoid); | ||
680 | bcma_core_pll_ctl(core, | ||
681 | B43_BCMA_CLKCTLST_80211_PLL_REQ | | ||
682 | B43_BCMA_CLKCTLST_PHY_PLL_REQ, | ||
683 | B43_BCMA_CLKCTLST_80211_PLL_ST | | ||
684 | B43_BCMA_CLKCTLST_PHY_PLL_ST, false); | ||
685 | |||
686 | /* Values has been taken from wlc_bmac_switch_macfreq comments */ | ||
687 | switch (spuravoid) { | ||
688 | case 2: /* 126MHz */ | ||
689 | tmp = 0x2082; | ||
690 | break; | ||
691 | case 1: /* 123MHz */ | ||
692 | tmp = 0x5341; | ||
693 | break; | ||
694 | default: /* 120MHz */ | ||
695 | tmp = 0x8889; | ||
696 | } | ||
697 | |||
698 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, tmp); | ||
699 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8); | ||
700 | |||
701 | /* TODO: reset PLL */ | ||
702 | |||
703 | if (spuravoid) | ||
704 | b43_phy_set(dev, B43_PHY_HT_BBCFG, B43_PHY_HT_BBCFG_RSTRX); | ||
705 | else | ||
706 | b43_phy_mask(dev, B43_PHY_HT_BBCFG, | ||
707 | ~B43_PHY_HT_BBCFG_RSTRX & 0xFFFF); | ||
708 | |||
709 | b43_phy_ht_reset_cca(dev); | ||
710 | } | ||
711 | |||
246 | static void b43_phy_ht_channel_setup(struct b43_wldev *dev, | 712 | static void b43_phy_ht_channel_setup(struct b43_wldev *dev, |
247 | const struct b43_phy_ht_channeltab_e_phy *e, | 713 | const struct b43_phy_ht_channeltab_e_phy *e, |
248 | struct ieee80211_channel *new_channel) | 714 | struct ieee80211_channel *new_channel) |
249 | { | 715 | { |
250 | bool old_band_5ghz; | 716 | bool old_band_5ghz; |
251 | u8 i; | ||
252 | 717 | ||
253 | old_band_5ghz = b43_phy_read(dev, B43_PHY_HT_BANDCTL) & 0; /* FIXME */ | 718 | old_band_5ghz = b43_phy_read(dev, B43_PHY_HT_BANDCTL) & 0; /* FIXME */ |
254 | if (new_channel->band == IEEE80211_BAND_5GHZ && !old_band_5ghz) { | 719 | if (new_channel->band == IEEE80211_BAND_5GHZ && !old_band_5ghz) { |
@@ -264,25 +729,20 @@ static void b43_phy_ht_channel_setup(struct b43_wldev *dev, | |||
264 | b43_phy_write(dev, B43_PHY_HT_BW5, e->bw5); | 729 | b43_phy_write(dev, B43_PHY_HT_BW5, e->bw5); |
265 | b43_phy_write(dev, B43_PHY_HT_BW6, e->bw6); | 730 | b43_phy_write(dev, B43_PHY_HT_BW6, e->bw6); |
266 | 731 | ||
267 | /* TODO: some ops on PHY regs 0x0B0 and 0xC0A */ | 732 | if (new_channel->hw_value == 14) { |
733 | b43_phy_ht_classifier(dev, B43_PHY_HT_CLASS_CTL_OFDM_EN, 0); | ||
734 | b43_phy_set(dev, B43_PHY_HT_TEST, 0x0800); | ||
735 | } else { | ||
736 | b43_phy_ht_classifier(dev, B43_PHY_HT_CLASS_CTL_OFDM_EN, | ||
737 | B43_PHY_HT_CLASS_CTL_OFDM_EN); | ||
738 | if (new_channel->band == IEEE80211_BAND_2GHZ) | ||
739 | b43_phy_mask(dev, B43_PHY_HT_TEST, ~0x840); | ||
740 | } | ||
268 | 741 | ||
269 | /* TODO: separated function? */ | 742 | if (1) /* TODO: On N it's for early devices only, what about HT? */ |
270 | for (i = 0; i < 3; i++) { | 743 | b43_phy_ht_tx_power_fix(dev); |
271 | u16 mask; | ||
272 | u32 tmp = b43_httab_read(dev, B43_HTTAB32(26, 0xE8)); | ||
273 | 744 | ||
274 | if (0) /* FIXME */ | 745 | b43_phy_ht_spur_avoid(dev, new_channel); |
275 | mask = 0x2 << (i * 4); | ||
276 | else | ||
277 | mask = 0; | ||
278 | b43_phy_mask(dev, B43_PHY_EXTG(0x108), mask); | ||
279 | |||
280 | b43_httab_write(dev, B43_HTTAB16(7, 0x110 + i), tmp >> 16); | ||
281 | b43_httab_write(dev, B43_HTTAB8(13, 0x63 + (i * 4)), | ||
282 | tmp & 0xFF); | ||
283 | b43_httab_write(dev, B43_HTTAB8(13, 0x73 + (i * 4)), | ||
284 | tmp & 0xFF); | ||
285 | } | ||
286 | 746 | ||
287 | b43_phy_write(dev, 0x017e, 0x3830); | 747 | b43_phy_write(dev, 0x017e, 0x3830); |
288 | } | 748 | } |
@@ -337,14 +797,29 @@ static void b43_phy_ht_op_prepare_structs(struct b43_wldev *dev) | |||
337 | { | 797 | { |
338 | struct b43_phy *phy = &dev->phy; | 798 | struct b43_phy *phy = &dev->phy; |
339 | struct b43_phy_ht *phy_ht = phy->ht; | 799 | struct b43_phy_ht *phy_ht = phy->ht; |
800 | int i; | ||
340 | 801 | ||
341 | memset(phy_ht, 0, sizeof(*phy_ht)); | 802 | memset(phy_ht, 0, sizeof(*phy_ht)); |
803 | |||
804 | phy_ht->tx_pwr_ctl = true; | ||
805 | for (i = 0; i < 3; i++) | ||
806 | phy_ht->tx_pwr_idx[i] = B43_PHY_HT_TXPCTL_CMD_C1_INIT + 1; | ||
807 | |||
808 | for (i = 0; i < 3; i++) | ||
809 | phy_ht->bb_mult_save[i] = -1; | ||
342 | } | 810 | } |
343 | 811 | ||
344 | static int b43_phy_ht_op_init(struct b43_wldev *dev) | 812 | static int b43_phy_ht_op_init(struct b43_wldev *dev) |
345 | { | 813 | { |
814 | struct b43_phy_ht *phy_ht = dev->phy.ht; | ||
346 | u16 tmp; | 815 | u16 tmp; |
347 | u16 clip_state[3]; | 816 | u16 clip_state[3]; |
817 | bool saved_tx_pwr_ctl; | ||
818 | |||
819 | if (dev->dev->bus_type != B43_BUS_BCMA) { | ||
820 | b43err(dev->wl, "HT-PHY is supported only on BCMA bus!\n"); | ||
821 | return -EOPNOTSUPP; | ||
822 | } | ||
348 | 823 | ||
349 | b43_phy_ht_tables_init(dev); | 824 | b43_phy_ht_tables_init(dev); |
350 | 825 | ||
@@ -357,9 +832,9 @@ static int b43_phy_ht_op_init(struct b43_wldev *dev) | |||
357 | 832 | ||
358 | b43_phy_mask(dev, B43_PHY_EXTG(0), ~0x3); | 833 | b43_phy_mask(dev, B43_PHY_EXTG(0), ~0x3); |
359 | 834 | ||
360 | b43_phy_write(dev, B43_PHY_HT_AFE_CTL1, 0); | 835 | b43_phy_write(dev, B43_PHY_HT_AFE_C1_OVER, 0); |
361 | b43_phy_write(dev, B43_PHY_HT_AFE_CTL3, 0); | 836 | b43_phy_write(dev, B43_PHY_HT_AFE_C2_OVER, 0); |
362 | b43_phy_write(dev, B43_PHY_HT_AFE_CTL5, 0); | 837 | b43_phy_write(dev, B43_PHY_HT_AFE_C3_OVER, 0); |
363 | 838 | ||
364 | b43_phy_write(dev, B43_PHY_EXTG(0x103), 0x20); | 839 | b43_phy_write(dev, B43_PHY_EXTG(0x103), 0x20); |
365 | b43_phy_write(dev, B43_PHY_EXTG(0x101), 0x20); | 840 | b43_phy_write(dev, B43_PHY_EXTG(0x101), 0x20); |
@@ -371,8 +846,11 @@ static int b43_phy_ht_op_init(struct b43_wldev *dev) | |||
371 | if (0) /* TODO: condition */ | 846 | if (0) /* TODO: condition */ |
372 | ; /* TODO: PHY op on reg 0x217 */ | 847 | ; /* TODO: PHY op on reg 0x217 */ |
373 | 848 | ||
374 | b43_phy_read(dev, 0xb0); /* TODO: what for? */ | 849 | if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) |
375 | b43_phy_set(dev, 0xb0, 0x1); | 850 | b43_phy_ht_classifier(dev, B43_PHY_HT_CLASS_CTL_CCK_EN, 0); |
851 | else | ||
852 | b43_phy_ht_classifier(dev, B43_PHY_HT_CLASS_CTL_CCK_EN, | ||
853 | B43_PHY_HT_CLASS_CTL_CCK_EN); | ||
376 | 854 | ||
377 | b43_phy_set(dev, 0xb1, 0x91); | 855 | b43_phy_set(dev, 0xb1, 0x91); |
378 | b43_phy_write(dev, 0x32f, 0x0003); | 856 | b43_phy_write(dev, 0x32f, 0x0003); |
@@ -448,12 +926,13 @@ static int b43_phy_ht_op_init(struct b43_wldev *dev) | |||
448 | 926 | ||
449 | b43_mac_phy_clock_set(dev, true); | 927 | b43_mac_phy_clock_set(dev, true); |
450 | 928 | ||
929 | b43_phy_ht_pa_override(dev, false); | ||
451 | b43_phy_ht_force_rf_sequence(dev, B43_PHY_HT_RF_SEQ_TRIG_RX2TX); | 930 | b43_phy_ht_force_rf_sequence(dev, B43_PHY_HT_RF_SEQ_TRIG_RX2TX); |
452 | b43_phy_ht_force_rf_sequence(dev, B43_PHY_HT_RF_SEQ_TRIG_RST2RX); | 931 | b43_phy_ht_force_rf_sequence(dev, B43_PHY_HT_RF_SEQ_TRIG_RST2RX); |
453 | 932 | b43_phy_ht_pa_override(dev, true); | |
454 | /* TODO: PHY op on reg 0xb0 */ | ||
455 | 933 | ||
456 | /* TODO: Should we restore it? Or store it in global PHY info? */ | 934 | /* TODO: Should we restore it? Or store it in global PHY info? */ |
935 | b43_phy_ht_classifier(dev, 0, 0); | ||
457 | b43_phy_ht_read_clip_detection(dev, clip_state); | 936 | b43_phy_ht_read_clip_detection(dev, clip_state); |
458 | 937 | ||
459 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) | 938 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) |
@@ -462,6 +941,13 @@ static int b43_phy_ht_op_init(struct b43_wldev *dev) | |||
462 | b43_httab_write_bulk(dev, B43_HTTAB32(0x1a, 0xc0), | 941 | b43_httab_write_bulk(dev, B43_HTTAB32(0x1a, 0xc0), |
463 | B43_HTTAB_1A_C0_LATE_SIZE, b43_httab_0x1a_0xc0_late); | 942 | B43_HTTAB_1A_C0_LATE_SIZE, b43_httab_0x1a_0xc0_late); |
464 | 943 | ||
944 | saved_tx_pwr_ctl = phy_ht->tx_pwr_ctl; | ||
945 | b43_phy_ht_tx_power_fix(dev); | ||
946 | b43_phy_ht_tx_power_ctl(dev, false); | ||
947 | b43_phy_ht_tx_power_ctl_idle_tssi(dev); | ||
948 | b43_phy_ht_tx_power_ctl_setup(dev); | ||
949 | b43_phy_ht_tx_power_ctl(dev, saved_tx_pwr_ctl); | ||
950 | |||
465 | return 0; | 951 | return 0; |
466 | } | 952 | } |
467 | 953 | ||
@@ -506,19 +992,19 @@ static void b43_phy_ht_op_software_rfkill(struct b43_wldev *dev, | |||
506 | static void b43_phy_ht_op_switch_analog(struct b43_wldev *dev, bool on) | 992 | static void b43_phy_ht_op_switch_analog(struct b43_wldev *dev, bool on) |
507 | { | 993 | { |
508 | if (on) { | 994 | if (on) { |
509 | b43_phy_write(dev, B43_PHY_HT_AFE_CTL2, 0x00cd); | 995 | b43_phy_write(dev, B43_PHY_HT_AFE_C1, 0x00cd); |
510 | b43_phy_write(dev, B43_PHY_HT_AFE_CTL1, 0x0000); | 996 | b43_phy_write(dev, B43_PHY_HT_AFE_C1_OVER, 0x0000); |
511 | b43_phy_write(dev, B43_PHY_HT_AFE_CTL4, 0x00cd); | 997 | b43_phy_write(dev, B43_PHY_HT_AFE_C2, 0x00cd); |
512 | b43_phy_write(dev, B43_PHY_HT_AFE_CTL3, 0x0000); | 998 | b43_phy_write(dev, B43_PHY_HT_AFE_C2_OVER, 0x0000); |
513 | b43_phy_write(dev, B43_PHY_HT_AFE_CTL6, 0x00cd); | 999 | b43_phy_write(dev, B43_PHY_HT_AFE_C3, 0x00cd); |
514 | b43_phy_write(dev, B43_PHY_HT_AFE_CTL5, 0x0000); | 1000 | b43_phy_write(dev, B43_PHY_HT_AFE_C3_OVER, 0x0000); |
515 | } else { | 1001 | } else { |
516 | b43_phy_write(dev, B43_PHY_HT_AFE_CTL1, 0x07ff); | 1002 | b43_phy_write(dev, B43_PHY_HT_AFE_C1_OVER, 0x07ff); |
517 | b43_phy_write(dev, B43_PHY_HT_AFE_CTL2, 0x00fd); | 1003 | b43_phy_write(dev, B43_PHY_HT_AFE_C1, 0x00fd); |
518 | b43_phy_write(dev, B43_PHY_HT_AFE_CTL3, 0x07ff); | 1004 | b43_phy_write(dev, B43_PHY_HT_AFE_C2_OVER, 0x07ff); |
519 | b43_phy_write(dev, B43_PHY_HT_AFE_CTL4, 0x00fd); | 1005 | b43_phy_write(dev, B43_PHY_HT_AFE_C2, 0x00fd); |
520 | b43_phy_write(dev, B43_PHY_HT_AFE_CTL5, 0x07ff); | 1006 | b43_phy_write(dev, B43_PHY_HT_AFE_C3_OVER, 0x07ff); |
521 | b43_phy_write(dev, B43_PHY_HT_AFE_CTL6, 0x00fd); | 1007 | b43_phy_write(dev, B43_PHY_HT_AFE_C3, 0x00fd); |
522 | } | 1008 | } |
523 | } | 1009 | } |
524 | 1010 | ||
diff --git a/drivers/net/wireless/b43/phy_ht.h b/drivers/net/wireless/b43/phy_ht.h index 6544c4293b34..9b2408efb224 100644 --- a/drivers/net/wireless/b43/phy_ht.h +++ b/drivers/net/wireless/b43/phy_ht.h | |||
@@ -12,18 +12,60 @@ | |||
12 | #define B43_PHY_HT_TABLE_ADDR 0x072 /* Table address */ | 12 | #define B43_PHY_HT_TABLE_ADDR 0x072 /* Table address */ |
13 | #define B43_PHY_HT_TABLE_DATALO 0x073 /* Table data low */ | 13 | #define B43_PHY_HT_TABLE_DATALO 0x073 /* Table data low */ |
14 | #define B43_PHY_HT_TABLE_DATAHI 0x074 /* Table data high */ | 14 | #define B43_PHY_HT_TABLE_DATAHI 0x074 /* Table data high */ |
15 | #define B43_PHY_HT_CLASS_CTL 0x0B0 /* Classifier control */ | ||
16 | #define B43_PHY_HT_CLASS_CTL_CCK_EN 0x0001 /* CCK enable */ | ||
17 | #define B43_PHY_HT_CLASS_CTL_OFDM_EN 0x0002 /* OFDM enable */ | ||
18 | #define B43_PHY_HT_CLASS_CTL_WAITED_EN 0x0004 /* Waited enable */ | ||
19 | #define B43_PHY_HT_IQLOCAL_CMDGCTL 0x0C2 /* I/Q LO cal command G control */ | ||
20 | #define B43_PHY_HT_SAMP_CMD 0x0C3 /* Sample command */ | ||
21 | #define B43_PHY_HT_SAMP_CMD_STOP 0x0002 /* Stop */ | ||
22 | #define B43_PHY_HT_SAMP_LOOP_CNT 0x0C4 /* Sample loop count */ | ||
23 | #define B43_PHY_HT_SAMP_WAIT_CNT 0x0C5 /* Sample wait count */ | ||
24 | #define B43_PHY_HT_SAMP_DEP_CNT 0x0C6 /* Sample depth count */ | ||
25 | #define B43_PHY_HT_SAMP_STAT 0x0C7 /* Sample status */ | ||
26 | #define B43_PHY_HT_TSSIMODE 0x122 /* TSSI mode */ | ||
27 | #define B43_PHY_HT_TSSIMODE_EN 0x0001 /* TSSI enable */ | ||
28 | #define B43_PHY_HT_TSSIMODE_PDEN 0x0002 /* Power det enable */ | ||
15 | #define B43_PHY_HT_BW1 0x1CE | 29 | #define B43_PHY_HT_BW1 0x1CE |
16 | #define B43_PHY_HT_BW2 0x1CF | 30 | #define B43_PHY_HT_BW2 0x1CF |
17 | #define B43_PHY_HT_BW3 0x1D0 | 31 | #define B43_PHY_HT_BW3 0x1D0 |
18 | #define B43_PHY_HT_BW4 0x1D1 | 32 | #define B43_PHY_HT_BW4 0x1D1 |
19 | #define B43_PHY_HT_BW5 0x1D2 | 33 | #define B43_PHY_HT_BW5 0x1D2 |
20 | #define B43_PHY_HT_BW6 0x1D3 | 34 | #define B43_PHY_HT_BW6 0x1D3 |
35 | #define B43_PHY_HT_TXPCTL_CMD_C1 0x1E7 /* TX power control command */ | ||
36 | #define B43_PHY_HT_TXPCTL_CMD_C1_INIT 0x007F /* Init */ | ||
37 | #define B43_PHY_HT_TXPCTL_CMD_C1_COEFF 0x2000 /* Power control coefficients */ | ||
38 | #define B43_PHY_HT_TXPCTL_CMD_C1_HWPCTLEN 0x4000 /* Hardware TX power control enable */ | ||
39 | #define B43_PHY_HT_TXPCTL_CMD_C1_PCTLEN 0x8000 /* TX power control enable */ | ||
40 | #define B43_PHY_HT_TXPCTL_N 0x1E8 /* TX power control N num */ | ||
41 | #define B43_PHY_HT_TXPCTL_N_TSSID 0x00FF /* N TSSI delay */ | ||
42 | #define B43_PHY_HT_TXPCTL_N_TSSID_SHIFT 0 | ||
43 | #define B43_PHY_HT_TXPCTL_N_NPTIL2 0x0700 /* N PT integer log2 */ | ||
44 | #define B43_PHY_HT_TXPCTL_N_NPTIL2_SHIFT 8 | ||
45 | #define B43_PHY_HT_TXPCTL_IDLE_TSSI 0x1E9 /* TX power control idle TSSI */ | ||
46 | #define B43_PHY_HT_TXPCTL_IDLE_TSSI_C1 0x003F | ||
47 | #define B43_PHY_HT_TXPCTL_IDLE_TSSI_C1_SHIFT 0 | ||
48 | #define B43_PHY_HT_TXPCTL_IDLE_TSSI_C2 0x3F00 | ||
49 | #define B43_PHY_HT_TXPCTL_IDLE_TSSI_C2_SHIFT 8 | ||
50 | #define B43_PHY_HT_TXPCTL_IDLE_TSSI_BINF 0x8000 /* Raw TSSI offset bin format */ | ||
51 | #define B43_PHY_HT_TXPCTL_TARG_PWR 0x1EA /* TX power control target power */ | ||
52 | #define B43_PHY_HT_TXPCTL_TARG_PWR_C1 0x00FF /* Power 0 */ | ||
53 | #define B43_PHY_HT_TXPCTL_TARG_PWR_C1_SHIFT 0 | ||
54 | #define B43_PHY_HT_TXPCTL_TARG_PWR_C2 0xFF00 /* Power 1 */ | ||
55 | #define B43_PHY_HT_TXPCTL_TARG_PWR_C2_SHIFT 8 | ||
56 | #define B43_PHY_HT_TXPCTL_CMD_C2 0x222 | ||
57 | #define B43_PHY_HT_TXPCTL_CMD_C2_INIT 0x007F | ||
58 | #define B43_PHY_HT_RSSI_C1 0x219 | ||
59 | #define B43_PHY_HT_RSSI_C2 0x21A | ||
60 | #define B43_PHY_HT_RSSI_C3 0x21B | ||
21 | 61 | ||
22 | #define B43_PHY_HT_C1_CLIP1THRES B43_PHY_OFDM(0x00E) | 62 | #define B43_PHY_HT_C1_CLIP1THRES B43_PHY_OFDM(0x00E) |
23 | #define B43_PHY_HT_C2_CLIP1THRES B43_PHY_OFDM(0x04E) | 63 | #define B43_PHY_HT_C2_CLIP1THRES B43_PHY_OFDM(0x04E) |
24 | #define B43_PHY_HT_C3_CLIP1THRES B43_PHY_OFDM(0x08E) | 64 | #define B43_PHY_HT_C3_CLIP1THRES B43_PHY_OFDM(0x08E) |
25 | 65 | ||
26 | #define B43_PHY_HT_RF_SEQ_MODE B43_PHY_EXTG(0x000) | 66 | #define B43_PHY_HT_RF_SEQ_MODE B43_PHY_EXTG(0x000) |
67 | #define B43_PHY_HT_RF_SEQ_MODE_CA_OVER 0x0001 /* Core active override */ | ||
68 | #define B43_PHY_HT_RF_SEQ_MODE_TR_OVER 0x0002 /* Trigger override */ | ||
27 | #define B43_PHY_HT_RF_SEQ_TRIG B43_PHY_EXTG(0x003) | 69 | #define B43_PHY_HT_RF_SEQ_TRIG B43_PHY_EXTG(0x003) |
28 | #define B43_PHY_HT_RF_SEQ_TRIG_RX2TX 0x0001 /* RX2TX */ | 70 | #define B43_PHY_HT_RF_SEQ_TRIG_RX2TX 0x0001 /* RX2TX */ |
29 | #define B43_PHY_HT_RF_SEQ_TRIG_TX2RX 0x0002 /* TX2RX */ | 71 | #define B43_PHY_HT_RF_SEQ_TRIG_TX2RX 0x0002 /* TX2RX */ |
@@ -36,12 +78,27 @@ | |||
36 | 78 | ||
37 | #define B43_PHY_HT_RF_CTL1 B43_PHY_EXTG(0x010) | 79 | #define B43_PHY_HT_RF_CTL1 B43_PHY_EXTG(0x010) |
38 | 80 | ||
39 | #define B43_PHY_HT_AFE_CTL1 B43_PHY_EXTG(0x110) | 81 | #define B43_PHY_HT_RF_CTL_INT_C1 B43_PHY_EXTG(0x04c) |
40 | #define B43_PHY_HT_AFE_CTL2 B43_PHY_EXTG(0x111) | 82 | #define B43_PHY_HT_RF_CTL_INT_C2 B43_PHY_EXTG(0x06c) |
41 | #define B43_PHY_HT_AFE_CTL3 B43_PHY_EXTG(0x114) | 83 | #define B43_PHY_HT_RF_CTL_INT_C3 B43_PHY_EXTG(0x08c) |
42 | #define B43_PHY_HT_AFE_CTL4 B43_PHY_EXTG(0x115) | 84 | |
43 | #define B43_PHY_HT_AFE_CTL5 B43_PHY_EXTG(0x118) | 85 | #define B43_PHY_HT_AFE_C1_OVER B43_PHY_EXTG(0x110) |
44 | #define B43_PHY_HT_AFE_CTL6 B43_PHY_EXTG(0x119) | 86 | #define B43_PHY_HT_AFE_C1 B43_PHY_EXTG(0x111) |
87 | #define B43_PHY_HT_AFE_C2_OVER B43_PHY_EXTG(0x114) | ||
88 | #define B43_PHY_HT_AFE_C2 B43_PHY_EXTG(0x115) | ||
89 | #define B43_PHY_HT_AFE_C3_OVER B43_PHY_EXTG(0x118) | ||
90 | #define B43_PHY_HT_AFE_C3 B43_PHY_EXTG(0x119) | ||
91 | |||
92 | #define B43_PHY_HT_TXPCTL_CMD_C3 B43_PHY_EXTG(0x164) | ||
93 | #define B43_PHY_HT_TXPCTL_CMD_C3_INIT 0x007F | ||
94 | #define B43_PHY_HT_TXPCTL_IDLE_TSSI2 B43_PHY_EXTG(0x165) /* TX power control idle TSSI */ | ||
95 | #define B43_PHY_HT_TXPCTL_IDLE_TSSI2_C3 0x003F | ||
96 | #define B43_PHY_HT_TXPCTL_IDLE_TSSI2_C3_SHIFT 0 | ||
97 | #define B43_PHY_HT_TXPCTL_TARG_PWR2 B43_PHY_EXTG(0x166) /* TX power control target power */ | ||
98 | #define B43_PHY_HT_TXPCTL_TARG_PWR2_C3 0x00FF | ||
99 | #define B43_PHY_HT_TXPCTL_TARG_PWR2_C3_SHIFT 0 | ||
100 | |||
101 | #define B43_PHY_HT_TEST B43_PHY_N_BMODE(0x00A) | ||
45 | 102 | ||
46 | 103 | ||
47 | /* Values for PHY registers used on channel switching */ | 104 | /* Values for PHY registers used on channel switching */ |
@@ -56,6 +113,14 @@ struct b43_phy_ht_channeltab_e_phy { | |||
56 | 113 | ||
57 | 114 | ||
58 | struct b43_phy_ht { | 115 | struct b43_phy_ht { |
116 | u16 rf_ctl_int_save[3]; | ||
117 | |||
118 | bool tx_pwr_ctl; | ||
119 | u8 tx_pwr_idx[3]; | ||
120 | |||
121 | s32 bb_mult_save[3]; | ||
122 | |||
123 | u8 idle_tssi[3]; | ||
59 | }; | 124 | }; |
60 | 125 | ||
61 | 126 | ||
diff --git a/drivers/net/wireless/brcm80211/Kconfig b/drivers/net/wireless/brcm80211/Kconfig index 1d92d874ebb6..747e9317dabd 100644 --- a/drivers/net/wireless/brcm80211/Kconfig +++ b/drivers/net/wireless/brcm80211/Kconfig | |||
@@ -12,8 +12,9 @@ config BRCMSMAC | |||
12 | select CORDIC | 12 | select CORDIC |
13 | ---help--- | 13 | ---help--- |
14 | This module adds support for PCIe wireless adapters based on Broadcom | 14 | This module adds support for PCIe wireless adapters based on Broadcom |
15 | IEEE802.11n SoftMAC chipsets. If you choose to build a module, it'll | 15 | IEEE802.11n SoftMAC chipsets. It also has WLAN led support, which will |
16 | be called brcmsmac.ko. | 16 | be available if you select BCMA_DRIVER_GPIO. If you choose to build a |
17 | module, the driver will be called brcmsmac.ko. | ||
17 | 18 | ||
18 | config BRCMFMAC | 19 | config BRCMFMAC |
19 | tristate "Broadcom IEEE802.11n embedded FullMAC WLAN driver" | 20 | tristate "Broadcom IEEE802.11n embedded FullMAC WLAN driver" |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/brcm80211/brcmfmac/Makefile index 756e19fc2795..598c8e2f8d2b 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/Makefile +++ b/drivers/net/wireless/brcm80211/brcmfmac/Makefile | |||
@@ -26,6 +26,7 @@ brcmfmac-objs += \ | |||
26 | wl_cfg80211.o \ | 26 | wl_cfg80211.o \ |
27 | fwil.o \ | 27 | fwil.o \ |
28 | fweh.o \ | 28 | fweh.o \ |
29 | fwsignal.o \ | ||
29 | p2p.o \ | 30 | p2p.o \ |
30 | dhd_cdc.o \ | 31 | dhd_cdc.o \ |
31 | dhd_common.o \ | 32 | dhd_common.o \ |
@@ -39,3 +40,5 @@ brcmfmac-$(CONFIG_BRCMFMAC_USB) += \ | |||
39 | usb.o | 40 | usb.o |
40 | brcmfmac-$(CONFIG_BRCMDBG) += \ | 41 | brcmfmac-$(CONFIG_BRCMDBG) += \ |
41 | dhd_dbg.o | 42 | dhd_dbg.o |
43 | brcmfmac-$(CONFIG_BRCM_TRACING) += \ | ||
44 | tracepoint.o | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h index ef6f23be6d32..c7fa20846b32 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h | |||
@@ -501,6 +501,7 @@ struct brcmf_dcmd { | |||
501 | /* Forward decls for struct brcmf_pub (see below) */ | 501 | /* Forward decls for struct brcmf_pub (see below) */ |
502 | struct brcmf_proto; /* device communication protocol info */ | 502 | struct brcmf_proto; /* device communication protocol info */ |
503 | struct brcmf_cfg80211_dev; /* cfg80211 device info */ | 503 | struct brcmf_cfg80211_dev; /* cfg80211 device info */ |
504 | struct brcmf_fws_info; /* firmware signalling info */ | ||
504 | 505 | ||
505 | /* Common structure for module and instance linkage */ | 506 | /* Common structure for module and instance linkage */ |
506 | struct brcmf_pub { | 507 | struct brcmf_pub { |
@@ -527,6 +528,10 @@ struct brcmf_pub { | |||
527 | unsigned char proto_buf[BRCMF_DCMD_MAXLEN]; | 528 | unsigned char proto_buf[BRCMF_DCMD_MAXLEN]; |
528 | 529 | ||
529 | struct brcmf_fweh_info fweh; | 530 | struct brcmf_fweh_info fweh; |
531 | |||
532 | bool fw_signals; | ||
533 | struct brcmf_fws_info *fws; | ||
534 | spinlock_t fws_spinlock; | ||
530 | #ifdef DEBUG | 535 | #ifdef DEBUG |
531 | struct dentry *dbgfs_dir; | 536 | struct dentry *dbgfs_dir; |
532 | #endif | 537 | #endif |
@@ -582,7 +587,7 @@ extern int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, | |||
582 | void *buf, uint len); | 587 | void *buf, uint len); |
583 | 588 | ||
584 | /* Remove any protocol-specific data header. */ | 589 | /* Remove any protocol-specific data header. */ |
585 | extern int brcmf_proto_hdrpull(struct brcmf_pub *drvr, u8 *ifidx, | 590 | extern int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, |
586 | struct sk_buff *rxp); | 591 | struct sk_buff *rxp); |
587 | 592 | ||
588 | extern int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked); | 593 | extern int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h index ad25c3408b59..883ef9063e8a 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h | |||
@@ -134,7 +134,7 @@ extern void brcmf_dev_reset(struct device *dev); | |||
134 | /* Indication from bus module to change flow-control state */ | 134 | /* Indication from bus module to change flow-control state */ |
135 | extern void brcmf_txflowblock(struct device *dev, bool state); | 135 | extern void brcmf_txflowblock(struct device *dev, bool state); |
136 | 136 | ||
137 | /* Notify tx completion */ | 137 | /* Notify the bus has transferred the tx packet to firmware */ |
138 | extern void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, | 138 | extern void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, |
139 | bool success); | 139 | bool success); |
140 | 140 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c index a2354d951dd7..e224bcb90024 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include "dhd.h" | 28 | #include "dhd.h" |
29 | #include "dhd_proto.h" | 29 | #include "dhd_proto.h" |
30 | #include "dhd_bus.h" | 30 | #include "dhd_bus.h" |
31 | #include "fwsignal.h" | ||
31 | #include "dhd_dbg.h" | 32 | #include "dhd_dbg.h" |
32 | 33 | ||
33 | struct brcmf_proto_cdc_dcmd { | 34 | struct brcmf_proto_cdc_dcmd { |
@@ -71,13 +72,26 @@ struct brcmf_proto_cdc_dcmd { | |||
71 | ((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_IF_MASK) | \ | 72 | ((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_IF_MASK) | \ |
72 | ((idx) << BDC_FLAG2_IF_SHIFT))) | 73 | ((idx) << BDC_FLAG2_IF_SHIFT))) |
73 | 74 | ||
75 | /** | ||
76 | * struct brcmf_proto_bdc_header - BDC header format | ||
77 | * | ||
78 | * @flags: flags contain protocol and checksum info. | ||
79 | * @priority: 802.1d priority and USB flow control info (bit 4:7). | ||
80 | * @flags2: additional flags containing dongle interface index. | ||
81 | * @data_offset: start of packet data. header is following by firmware signals. | ||
82 | */ | ||
74 | struct brcmf_proto_bdc_header { | 83 | struct brcmf_proto_bdc_header { |
75 | u8 flags; | 84 | u8 flags; |
76 | u8 priority; /* 802.1d Priority, 4:7 flow control info for usb */ | 85 | u8 priority; |
77 | u8 flags2; | 86 | u8 flags2; |
78 | u8 data_offset; | 87 | u8 data_offset; |
79 | }; | 88 | }; |
80 | 89 | ||
90 | /* | ||
91 | * maximum length of firmware signal data between | ||
92 | * the BDC header and packet data in the tx path. | ||
93 | */ | ||
94 | #define BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES 12 | ||
81 | 95 | ||
82 | #define RETRIES 2 /* # of retries to retrieve matching dcmd response */ | 96 | #define RETRIES 2 /* # of retries to retrieve matching dcmd response */ |
83 | #define BUS_HEADER_LEN (16+64) /* Must be atleast SDPCM_RESERVE | 97 | #define BUS_HEADER_LEN (16+64) /* Must be atleast SDPCM_RESERVE |
@@ -258,7 +272,7 @@ static void pkt_set_sum_good(struct sk_buff *skb, bool x) | |||
258 | skb->ip_summed = (x ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE); | 272 | skb->ip_summed = (x ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE); |
259 | } | 273 | } |
260 | 274 | ||
261 | void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx, | 275 | void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx, u8 offset, |
262 | struct sk_buff *pktbuf) | 276 | struct sk_buff *pktbuf) |
263 | { | 277 | { |
264 | struct brcmf_proto_bdc_header *h; | 278 | struct brcmf_proto_bdc_header *h; |
@@ -266,7 +280,6 @@ void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx, | |||
266 | brcmf_dbg(CDC, "Enter\n"); | 280 | brcmf_dbg(CDC, "Enter\n"); |
267 | 281 | ||
268 | /* Push BDC header used to convey priority for buses that don't */ | 282 | /* Push BDC header used to convey priority for buses that don't */ |
269 | |||
270 | skb_push(pktbuf, BDC_HEADER_LEN); | 283 | skb_push(pktbuf, BDC_HEADER_LEN); |
271 | 284 | ||
272 | h = (struct brcmf_proto_bdc_header *)(pktbuf->data); | 285 | h = (struct brcmf_proto_bdc_header *)(pktbuf->data); |
@@ -277,11 +290,11 @@ void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx, | |||
277 | 290 | ||
278 | h->priority = (pktbuf->priority & BDC_PRIORITY_MASK); | 291 | h->priority = (pktbuf->priority & BDC_PRIORITY_MASK); |
279 | h->flags2 = 0; | 292 | h->flags2 = 0; |
280 | h->data_offset = 0; | 293 | h->data_offset = offset; |
281 | BDC_SET_IF_IDX(h, ifidx); | 294 | BDC_SET_IF_IDX(h, ifidx); |
282 | } | 295 | } |
283 | 296 | ||
284 | int brcmf_proto_hdrpull(struct brcmf_pub *drvr, u8 *ifidx, | 297 | int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, |
285 | struct sk_buff *pktbuf) | 298 | struct sk_buff *pktbuf) |
286 | { | 299 | { |
287 | struct brcmf_proto_bdc_header *h; | 300 | struct brcmf_proto_bdc_header *h; |
@@ -328,7 +341,10 @@ int brcmf_proto_hdrpull(struct brcmf_pub *drvr, u8 *ifidx, | |||
328 | pktbuf->priority = h->priority & BDC_PRIORITY_MASK; | 341 | pktbuf->priority = h->priority & BDC_PRIORITY_MASK; |
329 | 342 | ||
330 | skb_pull(pktbuf, BDC_HEADER_LEN); | 343 | skb_pull(pktbuf, BDC_HEADER_LEN); |
331 | skb_pull(pktbuf, h->data_offset << 2); | 344 | if (do_fws) |
345 | brcmf_fws_hdrpull(drvr, *ifidx, h->data_offset << 2, pktbuf); | ||
346 | else | ||
347 | skb_pull(pktbuf, h->data_offset << 2); | ||
332 | 348 | ||
333 | if (pktbuf->len == 0) | 349 | if (pktbuf->len == 0) |
334 | return -ENODATA; | 350 | return -ENODATA; |
@@ -350,7 +366,7 @@ int brcmf_proto_attach(struct brcmf_pub *drvr) | |||
350 | } | 366 | } |
351 | 367 | ||
352 | drvr->prot = cdc; | 368 | drvr->prot = cdc; |
353 | drvr->hdrlen += BDC_HEADER_LEN; | 369 | drvr->hdrlen += BDC_HEADER_LEN + BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES; |
354 | drvr->bus_if->maxctl = BRCMF_DCMD_MAXLEN + | 370 | drvr->bus_if->maxctl = BRCMF_DCMD_MAXLEN + |
355 | sizeof(struct brcmf_proto_cdc_dcmd) + ROUND_UP_MARGIN; | 371 | sizeof(struct brcmf_proto_cdc_dcmd) + ROUND_UP_MARGIN; |
356 | return 0; | 372 | return 0; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c index 4544342a0428..be0787cab24f 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include "dhd_proto.h" | 24 | #include "dhd_proto.h" |
25 | #include "dhd_dbg.h" | 25 | #include "dhd_dbg.h" |
26 | #include "fwil.h" | 26 | #include "fwil.h" |
27 | #include "tracepoint.h" | ||
27 | 28 | ||
28 | #define PKTFILTER_BUF_SIZE 128 | 29 | #define PKTFILTER_BUF_SIZE 128 |
29 | #define BRCMF_ARPOL_MODE 0xb /* agent|snoop|peer_autoreply */ | 30 | #define BRCMF_ARPOL_MODE 0xb /* agent|snoop|peer_autoreply */ |
@@ -373,3 +374,35 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) | |||
373 | done: | 374 | done: |
374 | return err; | 375 | return err; |
375 | } | 376 | } |
377 | |||
378 | #ifdef CONFIG_BRCM_TRACING | ||
379 | void __brcmf_err(const char *func, const char *fmt, ...) | ||
380 | { | ||
381 | struct va_format vaf = { | ||
382 | .fmt = fmt, | ||
383 | }; | ||
384 | va_list args; | ||
385 | |||
386 | va_start(args, fmt); | ||
387 | vaf.va = &args; | ||
388 | pr_err("%s: %pV", func, &vaf); | ||
389 | trace_brcmf_err(func, &vaf); | ||
390 | va_end(args); | ||
391 | } | ||
392 | #endif | ||
393 | #if defined(CONFIG_BRCM_TRACING) || defined(CONFIG_BRCMDBG) | ||
394 | void __brcmf_dbg(u32 level, const char *func, const char *fmt, ...) | ||
395 | { | ||
396 | struct va_format vaf = { | ||
397 | .fmt = fmt, | ||
398 | }; | ||
399 | va_list args; | ||
400 | |||
401 | va_start(args, fmt); | ||
402 | vaf.va = &args; | ||
403 | if (brcmf_msg_level & level) | ||
404 | pr_debug("%s %pV", func, &vaf); | ||
405 | trace_brcmf_dbg(level, func, &vaf); | ||
406 | va_end(args); | ||
407 | } | ||
408 | #endif | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c index 57671eddf79d..ac792499b46a 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include "dhd.h" | 22 | #include "dhd.h" |
23 | #include "dhd_bus.h" | 23 | #include "dhd_bus.h" |
24 | #include "dhd_dbg.h" | 24 | #include "dhd_dbg.h" |
25 | #include "tracepoint.h" | ||
25 | 26 | ||
26 | static struct dentry *root_folder; | 27 | static struct dentry *root_folder; |
27 | 28 | ||
@@ -123,3 +124,44 @@ void brcmf_debugfs_create_sdio_count(struct brcmf_pub *drvr, | |||
123 | debugfs_create_file("counters", S_IRUGO, dentry, | 124 | debugfs_create_file("counters", S_IRUGO, dentry, |
124 | sdcnt, &brcmf_debugfs_sdio_counter_ops); | 125 | sdcnt, &brcmf_debugfs_sdio_counter_ops); |
125 | } | 126 | } |
127 | |||
128 | static | ||
129 | ssize_t brcmf_debugfs_fws_stats_read(struct file *f, char __user *data, | ||
130 | size_t count, loff_t *ppos) | ||
131 | { | ||
132 | struct brcmf_fws_stats *fwstats = f->private_data; | ||
133 | char buf[100]; | ||
134 | int res; | ||
135 | |||
136 | /* only allow read from start */ | ||
137 | if (*ppos > 0) | ||
138 | return 0; | ||
139 | |||
140 | res = scnprintf(buf, sizeof(buf), | ||
141 | "header_pulls: %u\n" | ||
142 | "header_only_pkt: %u\n" | ||
143 | "tlv_parse_failed: %u\n" | ||
144 | "tlv_invalid_type: %u\n", | ||
145 | fwstats->header_pulls, | ||
146 | fwstats->header_only_pkt, | ||
147 | fwstats->tlv_parse_failed, | ||
148 | fwstats->tlv_invalid_type); | ||
149 | |||
150 | return simple_read_from_buffer(data, count, ppos, buf, res); | ||
151 | } | ||
152 | |||
153 | static const struct file_operations brcmf_debugfs_fws_stats_ops = { | ||
154 | .owner = THIS_MODULE, | ||
155 | .open = simple_open, | ||
156 | .read = brcmf_debugfs_fws_stats_read | ||
157 | }; | ||
158 | |||
159 | void brcmf_debugfs_create_fws_stats(struct brcmf_pub *drvr, | ||
160 | struct brcmf_fws_stats *stats) | ||
161 | { | ||
162 | struct dentry *dentry = drvr->dbgfs_dir; | ||
163 | |||
164 | if (!IS_ERR_OR_NULL(dentry)) | ||
165 | debugfs_create_file("fws_stats", S_IRUGO, dentry, | ||
166 | stats, &brcmf_debugfs_fws_stats_ops); | ||
167 | } | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h index bc013cbe06f6..4bc646bde16f 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h | |||
@@ -43,6 +43,7 @@ | |||
43 | * debugging is not selected. When debugging the driver error | 43 | * debugging is not selected. When debugging the driver error |
44 | * messages are as important as other tracing or even more so. | 44 | * messages are as important as other tracing or even more so. |
45 | */ | 45 | */ |
46 | #ifndef CONFIG_BRCM_TRACING | ||
46 | #ifdef CONFIG_BRCMDBG | 47 | #ifdef CONFIG_BRCMDBG |
47 | #define brcmf_err(fmt, ...) pr_err("%s: " fmt, __func__, ##__VA_ARGS__) | 48 | #define brcmf_err(fmt, ...) pr_err("%s: " fmt, __func__, ##__VA_ARGS__) |
48 | #else | 49 | #else |
@@ -52,15 +53,21 @@ | |||
52 | pr_err("%s: " fmt, __func__, ##__VA_ARGS__); \ | 53 | pr_err("%s: " fmt, __func__, ##__VA_ARGS__); \ |
53 | } while (0) | 54 | } while (0) |
54 | #endif | 55 | #endif |
56 | #else | ||
57 | __printf(2, 3) | ||
58 | void __brcmf_err(const char *func, const char *fmt, ...); | ||
59 | #define brcmf_err(fmt, ...) \ | ||
60 | __brcmf_err(__func__, fmt, ##__VA_ARGS__) | ||
61 | #endif | ||
55 | 62 | ||
56 | #if defined(DEBUG) | 63 | #if defined(DEBUG) || defined(CONFIG_BRCM_TRACING) |
57 | 64 | __printf(3, 4) | |
65 | void __brcmf_dbg(u32 level, const char *func, const char *fmt, ...); | ||
58 | #define brcmf_dbg(level, fmt, ...) \ | 66 | #define brcmf_dbg(level, fmt, ...) \ |
59 | do { \ | 67 | do { \ |
60 | if (brcmf_msg_level & BRCMF_##level##_VAL) \ | 68 | __brcmf_dbg(BRCMF_##level##_VAL, __func__, \ |
61 | pr_debug("%s: " fmt, __func__, ##__VA_ARGS__); \ | 69 | fmt, ##__VA_ARGS__); \ |
62 | } while (0) | 70 | } while (0) |
63 | |||
64 | #define BRCMF_DATA_ON() (brcmf_msg_level & BRCMF_DATA_VAL) | 71 | #define BRCMF_DATA_ON() (brcmf_msg_level & BRCMF_DATA_VAL) |
65 | #define BRCMF_CTL_ON() (brcmf_msg_level & BRCMF_CTL_VAL) | 72 | #define BRCMF_CTL_ON() (brcmf_msg_level & BRCMF_CTL_VAL) |
66 | #define BRCMF_HDRS_ON() (brcmf_msg_level & BRCMF_HDRS_VAL) | 73 | #define BRCMF_HDRS_ON() (brcmf_msg_level & BRCMF_HDRS_VAL) |
@@ -69,7 +76,7 @@ do { \ | |||
69 | #define BRCMF_EVENT_ON() (brcmf_msg_level & BRCMF_EVENT_VAL) | 76 | #define BRCMF_EVENT_ON() (brcmf_msg_level & BRCMF_EVENT_VAL) |
70 | #define BRCMF_FIL_ON() (brcmf_msg_level & BRCMF_FIL_VAL) | 77 | #define BRCMF_FIL_ON() (brcmf_msg_level & BRCMF_FIL_VAL) |
71 | 78 | ||
72 | #else /* (defined DEBUG) || (defined DEBUG) */ | 79 | #else /* defined(DEBUG) || defined(CONFIG_BRCM_TRACING) */ |
73 | 80 | ||
74 | #define brcmf_dbg(level, fmt, ...) no_printk(fmt, ##__VA_ARGS__) | 81 | #define brcmf_dbg(level, fmt, ...) no_printk(fmt, ##__VA_ARGS__) |
75 | 82 | ||
@@ -81,7 +88,7 @@ do { \ | |||
81 | #define BRCMF_EVENT_ON() 0 | 88 | #define BRCMF_EVENT_ON() 0 |
82 | #define BRCMF_FIL_ON() 0 | 89 | #define BRCMF_FIL_ON() 0 |
83 | 90 | ||
84 | #endif /* defined(DEBUG) */ | 91 | #endif /* defined(DEBUG) || defined(CONFIG_BRCM_TRACING) */ |
85 | 92 | ||
86 | #define brcmf_dbg_hex_dump(test, data, len, fmt, ...) \ | 93 | #define brcmf_dbg_hex_dump(test, data, len, fmt, ...) \ |
87 | do { \ | 94 | do { \ |
@@ -125,6 +132,13 @@ struct brcmf_sdio_count { | |||
125 | ulong rx_readahead_cnt; /* packets where header read-ahead was used */ | 132 | ulong rx_readahead_cnt; /* packets where header read-ahead was used */ |
126 | }; | 133 | }; |
127 | 134 | ||
135 | struct brcmf_fws_stats { | ||
136 | u32 tlv_parse_failed; | ||
137 | u32 tlv_invalid_type; | ||
138 | u32 header_only_pkt; | ||
139 | u32 header_pulls; | ||
140 | }; | ||
141 | |||
128 | struct brcmf_pub; | 142 | struct brcmf_pub; |
129 | #ifdef DEBUG | 143 | #ifdef DEBUG |
130 | void brcmf_debugfs_init(void); | 144 | void brcmf_debugfs_init(void); |
@@ -134,6 +148,8 @@ void brcmf_debugfs_detach(struct brcmf_pub *drvr); | |||
134 | struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr); | 148 | struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr); |
135 | void brcmf_debugfs_create_sdio_count(struct brcmf_pub *drvr, | 149 | void brcmf_debugfs_create_sdio_count(struct brcmf_pub *drvr, |
136 | struct brcmf_sdio_count *sdcnt); | 150 | struct brcmf_sdio_count *sdcnt); |
151 | void brcmf_debugfs_create_fws_stats(struct brcmf_pub *drvr, | ||
152 | struct brcmf_fws_stats *stats); | ||
137 | #else | 153 | #else |
138 | static inline void brcmf_debugfs_init(void) | 154 | static inline void brcmf_debugfs_init(void) |
139 | { | 155 | { |
@@ -148,6 +164,10 @@ static inline int brcmf_debugfs_attach(struct brcmf_pub *drvr) | |||
148 | static inline void brcmf_debugfs_detach(struct brcmf_pub *drvr) | 164 | static inline void brcmf_debugfs_detach(struct brcmf_pub *drvr) |
149 | { | 165 | { |
150 | } | 166 | } |
167 | static inline void brcmf_debugfs_create_fws_stats(struct brcmf_pub *drvr, | ||
168 | struct brcmf_fws_stats *stats) | ||
169 | { | ||
170 | } | ||
151 | #endif | 171 | #endif |
152 | 172 | ||
153 | #endif /* _BRCMF_DBG_H_ */ | 173 | #endif /* _BRCMF_DBG_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index c06cea88df0d..fa5a2af04d46 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c | |||
@@ -30,17 +30,18 @@ | |||
30 | #include "p2p.h" | 30 | #include "p2p.h" |
31 | #include "wl_cfg80211.h" | 31 | #include "wl_cfg80211.h" |
32 | #include "fwil.h" | 32 | #include "fwil.h" |
33 | #include "fwsignal.h" | ||
33 | 34 | ||
34 | MODULE_AUTHOR("Broadcom Corporation"); | 35 | MODULE_AUTHOR("Broadcom Corporation"); |
35 | MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver."); | 36 | MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver."); |
36 | MODULE_SUPPORTED_DEVICE("Broadcom 802.11 WLAN fullmac cards"); | ||
37 | MODULE_LICENSE("Dual BSD/GPL"); | 37 | MODULE_LICENSE("Dual BSD/GPL"); |
38 | 38 | ||
39 | #define MAX_WAIT_FOR_8021X_TX 50 /* msecs */ | 39 | #define MAX_WAIT_FOR_8021X_TX 50 /* msecs */ |
40 | 40 | ||
41 | /* Error bits */ | 41 | /* Error bits */ |
42 | int brcmf_msg_level; | 42 | int brcmf_msg_level; |
43 | module_param(brcmf_msg_level, int, 0); | 43 | module_param_named(debug, brcmf_msg_level, int, S_IRUSR | S_IWUSR); |
44 | MODULE_PARM_DESC(debug, "level of debug output"); | ||
44 | 45 | ||
45 | /* P2P0 enable */ | 46 | /* P2P0 enable */ |
46 | static int brcmf_p2p_enable; | 47 | static int brcmf_p2p_enable; |
@@ -230,7 +231,7 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb, | |||
230 | atomic_inc(&ifp->pend_8021x_cnt); | 231 | atomic_inc(&ifp->pend_8021x_cnt); |
231 | 232 | ||
232 | /* If the protocol uses a data header, apply it */ | 233 | /* If the protocol uses a data header, apply it */ |
233 | brcmf_proto_hdrpush(drvr, ifp->ifidx, skb); | 234 | brcmf_proto_hdrpush(drvr, ifp->ifidx, 0, skb); |
234 | 235 | ||
235 | /* Use bus module to send data frame */ | 236 | /* Use bus module to send data frame */ |
236 | ret = brcmf_bus_txdata(drvr->bus_if, skb); | 237 | ret = brcmf_bus_txdata(drvr->bus_if, skb); |
@@ -283,7 +284,7 @@ void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list) | |||
283 | skb_unlink(skb, skb_list); | 284 | skb_unlink(skb, skb_list); |
284 | 285 | ||
285 | /* process and remove protocol-specific header */ | 286 | /* process and remove protocol-specific header */ |
286 | ret = brcmf_proto_hdrpull(drvr, &ifidx, skb); | 287 | ret = brcmf_proto_hdrpull(drvr, drvr->fw_signals, &ifidx, skb); |
287 | ifp = drvr->iflist[ifidx]; | 288 | ifp = drvr->iflist[ifidx]; |
288 | 289 | ||
289 | if (ret || !ifp || !ifp->ndev) { | 290 | if (ret || !ifp || !ifp->ndev) { |
@@ -357,23 +358,29 @@ void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success) | |||
357 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | 358 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); |
358 | struct brcmf_pub *drvr = bus_if->drvr; | 359 | struct brcmf_pub *drvr = bus_if->drvr; |
359 | struct brcmf_if *ifp; | 360 | struct brcmf_if *ifp; |
361 | int res; | ||
360 | 362 | ||
361 | brcmf_proto_hdrpull(drvr, &ifidx, txp); | 363 | res = brcmf_proto_hdrpull(drvr, false, &ifidx, txp); |
362 | 364 | ||
363 | ifp = drvr->iflist[ifidx]; | 365 | ifp = drvr->iflist[ifidx]; |
364 | if (!ifp) | 366 | if (!ifp) |
365 | return; | 367 | goto done; |
366 | 368 | ||
367 | eh = (struct ethhdr *)(txp->data); | 369 | if (res == 0) { |
368 | type = ntohs(eh->h_proto); | 370 | eh = (struct ethhdr *)(txp->data); |
371 | type = ntohs(eh->h_proto); | ||
369 | 372 | ||
370 | if (type == ETH_P_PAE) { | 373 | if (type == ETH_P_PAE) { |
371 | atomic_dec(&ifp->pend_8021x_cnt); | 374 | atomic_dec(&ifp->pend_8021x_cnt); |
372 | if (waitqueue_active(&ifp->pend_8021x_wait)) | 375 | if (waitqueue_active(&ifp->pend_8021x_wait)) |
373 | wake_up(&ifp->pend_8021x_wait); | 376 | wake_up(&ifp->pend_8021x_wait); |
377 | } | ||
374 | } | 378 | } |
375 | if (!success) | 379 | if (!success) |
376 | ifp->stats.tx_errors++; | 380 | ifp->stats.tx_errors++; |
381 | |||
382 | done: | ||
383 | brcmu_pkt_buf_free_skb(txp); | ||
377 | } | 384 | } |
378 | 385 | ||
379 | static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev) | 386 | static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev) |
@@ -873,6 +880,9 @@ int brcmf_bus_start(struct device *dev) | |||
873 | if (ret < 0) | 880 | if (ret < 0) |
874 | goto fail; | 881 | goto fail; |
875 | 882 | ||
883 | drvr->fw_signals = true; | ||
884 | (void)brcmf_fws_init(drvr); | ||
885 | |||
876 | drvr->config = brcmf_cfg80211_attach(drvr, bus_if->dev); | 886 | drvr->config = brcmf_cfg80211_attach(drvr, bus_if->dev); |
877 | if (drvr->config == NULL) { | 887 | if (drvr->config == NULL) { |
878 | ret = -ENOMEM; | 888 | ret = -ENOMEM; |
@@ -889,6 +899,8 @@ fail: | |||
889 | brcmf_err("failed: %d\n", ret); | 899 | brcmf_err("failed: %d\n", ret); |
890 | if (drvr->config) | 900 | if (drvr->config) |
891 | brcmf_cfg80211_detach(drvr->config); | 901 | brcmf_cfg80211_detach(drvr->config); |
902 | if (drvr->fws) | ||
903 | brcmf_fws_deinit(drvr); | ||
892 | free_netdev(ifp->ndev); | 904 | free_netdev(ifp->ndev); |
893 | drvr->iflist[0] = NULL; | 905 | drvr->iflist[0] = NULL; |
894 | if (p2p_ifp) { | 906 | if (p2p_ifp) { |
@@ -952,6 +964,9 @@ void brcmf_detach(struct device *dev) | |||
952 | if (drvr->prot) | 964 | if (drvr->prot) |
953 | brcmf_proto_detach(drvr); | 965 | brcmf_proto_detach(drvr); |
954 | 966 | ||
967 | if (drvr->fws) | ||
968 | brcmf_fws_deinit(drvr); | ||
969 | |||
955 | brcmf_debugfs_detach(drvr); | 970 | brcmf_debugfs_detach(drvr); |
956 | bus_if->drvr = NULL; | 971 | bus_if->drvr = NULL; |
957 | kfree(drvr); | 972 | kfree(drvr); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h index 48fa70302192..ef9179883748 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h | |||
@@ -33,7 +33,7 @@ extern void brcmf_proto_stop(struct brcmf_pub *drvr); | |||
33 | /* Add any protocol-specific data header. | 33 | /* Add any protocol-specific data header. |
34 | * Caller must reserve prot_hdrlen prepend space. | 34 | * Caller must reserve prot_hdrlen prepend space. |
35 | */ | 35 | */ |
36 | extern void brcmf_proto_hdrpush(struct brcmf_pub *, int ifidx, | 36 | extern void brcmf_proto_hdrpush(struct brcmf_pub *, int ifidx, u8 offset, |
37 | struct sk_buff *txp); | 37 | struct sk_buff *txp); |
38 | 38 | ||
39 | /* Sets dongle media info (drv_version, mac address). */ | 39 | /* Sets dongle media info (drv_version, mac address). */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index 4469321c0eb3..9a2edd3f0a5c 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | |||
@@ -1546,7 +1546,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) | |||
1546 | struct sk_buff_head pktlist; /* needed for bus interface */ | 1546 | struct sk_buff_head pktlist; /* needed for bus interface */ |
1547 | u16 pad; /* Number of pad bytes to read */ | 1547 | u16 pad; /* Number of pad bytes to read */ |
1548 | uint rxleft = 0; /* Remaining number of frames allowed */ | 1548 | uint rxleft = 0; /* Remaining number of frames allowed */ |
1549 | int sdret; /* Return code from calls */ | 1549 | int ret; /* Return code from calls */ |
1550 | uint rxcount = 0; /* Total frames read */ | 1550 | uint rxcount = 0; /* Total frames read */ |
1551 | struct brcmf_sdio_read *rd = &bus->cur_read, rd_new; | 1551 | struct brcmf_sdio_read *rd = &bus->cur_read, rd_new; |
1552 | u8 head_read = 0; | 1552 | u8 head_read = 0; |
@@ -1577,15 +1577,15 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) | |||
1577 | /* read header first for unknow frame length */ | 1577 | /* read header first for unknow frame length */ |
1578 | sdio_claim_host(bus->sdiodev->func[1]); | 1578 | sdio_claim_host(bus->sdiodev->func[1]); |
1579 | if (!rd->len) { | 1579 | if (!rd->len) { |
1580 | sdret = brcmf_sdcard_recv_buf(bus->sdiodev, | 1580 | ret = brcmf_sdcard_recv_buf(bus->sdiodev, |
1581 | bus->sdiodev->sbwad, | 1581 | bus->sdiodev->sbwad, |
1582 | SDIO_FUNC_2, F2SYNC, | 1582 | SDIO_FUNC_2, F2SYNC, |
1583 | bus->rxhdr, | 1583 | bus->rxhdr, |
1584 | BRCMF_FIRSTREAD); | 1584 | BRCMF_FIRSTREAD); |
1585 | bus->sdcnt.f2rxhdrs++; | 1585 | bus->sdcnt.f2rxhdrs++; |
1586 | if (sdret < 0) { | 1586 | if (ret < 0) { |
1587 | brcmf_err("RXHEADER FAILED: %d\n", | 1587 | brcmf_err("RXHEADER FAILED: %d\n", |
1588 | sdret); | 1588 | ret); |
1589 | bus->sdcnt.rx_hdrfail++; | 1589 | bus->sdcnt.rx_hdrfail++; |
1590 | brcmf_sdbrcm_rxfail(bus, true, true); | 1590 | brcmf_sdbrcm_rxfail(bus, true, true); |
1591 | sdio_release_host(bus->sdiodev->func[1]); | 1591 | sdio_release_host(bus->sdiodev->func[1]); |
@@ -1637,14 +1637,14 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) | |||
1637 | skb_pull(pkt, head_read); | 1637 | skb_pull(pkt, head_read); |
1638 | pkt_align(pkt, rd->len_left, BRCMF_SDALIGN); | 1638 | pkt_align(pkt, rd->len_left, BRCMF_SDALIGN); |
1639 | 1639 | ||
1640 | sdret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad, | 1640 | ret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad, |
1641 | SDIO_FUNC_2, F2SYNC, pkt); | 1641 | SDIO_FUNC_2, F2SYNC, pkt); |
1642 | bus->sdcnt.f2rxdata++; | 1642 | bus->sdcnt.f2rxdata++; |
1643 | sdio_release_host(bus->sdiodev->func[1]); | 1643 | sdio_release_host(bus->sdiodev->func[1]); |
1644 | 1644 | ||
1645 | if (sdret < 0) { | 1645 | if (ret < 0) { |
1646 | brcmf_err("read %d bytes from channel %d failed: %d\n", | 1646 | brcmf_err("read %d bytes from channel %d failed: %d\n", |
1647 | rd->len, rd->channel, sdret); | 1647 | rd->len, rd->channel, ret); |
1648 | brcmu_pkt_buf_free_skb(pkt); | 1648 | brcmu_pkt_buf_free_skb(pkt); |
1649 | sdio_claim_host(bus->sdiodev->func[1]); | 1649 | sdio_claim_host(bus->sdiodev->func[1]); |
1650 | brcmf_sdbrcm_rxfail(bus, true, | 1650 | brcmf_sdbrcm_rxfail(bus, true, |
@@ -1775,7 +1775,7 @@ brcmf_sdbrcm_wait_event_wakeup(struct brcmf_sdio *bus) | |||
1775 | /* Writes a HW/SW header into the packet and sends it. */ | 1775 | /* Writes a HW/SW header into the packet and sends it. */ |
1776 | /* Assumes: (a) header space already there, (b) caller holds lock */ | 1776 | /* Assumes: (a) header space already there, (b) caller holds lock */ |
1777 | static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt, | 1777 | static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt, |
1778 | uint chan, bool free_pkt) | 1778 | uint chan) |
1779 | { | 1779 | { |
1780 | int ret; | 1780 | int ret; |
1781 | u8 *frame; | 1781 | u8 *frame; |
@@ -1805,10 +1805,7 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt, | |||
1805 | 1805 | ||
1806 | pkt_align(new, pkt->len, BRCMF_SDALIGN); | 1806 | pkt_align(new, pkt->len, BRCMF_SDALIGN); |
1807 | memcpy(new->data, pkt->data, pkt->len); | 1807 | memcpy(new->data, pkt->data, pkt->len); |
1808 | if (free_pkt) | 1808 | brcmu_pkt_buf_free_skb(pkt); |
1809 | brcmu_pkt_buf_free_skb(pkt); | ||
1810 | /* free the pkt if canned one is not used */ | ||
1811 | free_pkt = true; | ||
1812 | pkt = new; | 1809 | pkt = new; |
1813 | frame = (u8 *) (pkt->data); | 1810 | frame = (u8 *) (pkt->data); |
1814 | /* precondition: (frame % BRCMF_SDALIGN) == 0) */ | 1811 | /* precondition: (frame % BRCMF_SDALIGN) == 0) */ |
@@ -1901,10 +1898,6 @@ done: | |||
1901 | /* restore pkt buffer pointer before calling tx complete routine */ | 1898 | /* restore pkt buffer pointer before calling tx complete routine */ |
1902 | skb_pull(pkt, SDPCM_HDRLEN + pad); | 1899 | skb_pull(pkt, SDPCM_HDRLEN + pad); |
1903 | brcmf_txcomplete(bus->sdiodev->dev, pkt, ret != 0); | 1900 | brcmf_txcomplete(bus->sdiodev->dev, pkt, ret != 0); |
1904 | |||
1905 | if (free_pkt) | ||
1906 | brcmu_pkt_buf_free_skb(pkt); | ||
1907 | |||
1908 | return ret; | 1901 | return ret; |
1909 | } | 1902 | } |
1910 | 1903 | ||
@@ -1932,7 +1925,7 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes) | |||
1932 | spin_unlock_bh(&bus->txqlock); | 1925 | spin_unlock_bh(&bus->txqlock); |
1933 | datalen = pkt->len - SDPCM_HDRLEN; | 1926 | datalen = pkt->len - SDPCM_HDRLEN; |
1934 | 1927 | ||
1935 | ret = brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, true); | 1928 | ret = brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_DATA_CHANNEL); |
1936 | 1929 | ||
1937 | /* In poll mode, need to check for other events */ | 1930 | /* In poll mode, need to check for other events */ |
1938 | if (!bus->intr && cnt) { | 1931 | if (!bus->intr && cnt) { |
@@ -2343,7 +2336,6 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt) | |||
2343 | if (!brcmf_c_prec_enq(bus->sdiodev->dev, &bus->txq, pkt, prec)) { | 2336 | if (!brcmf_c_prec_enq(bus->sdiodev->dev, &bus->txq, pkt, prec)) { |
2344 | skb_pull(pkt, SDPCM_HDRLEN); | 2337 | skb_pull(pkt, SDPCM_HDRLEN); |
2345 | brcmf_txcomplete(bus->sdiodev->dev, pkt, false); | 2338 | brcmf_txcomplete(bus->sdiodev->dev, pkt, false); |
2346 | brcmu_pkt_buf_free_skb(pkt); | ||
2347 | brcmf_err("out of bus->txq !!!\n"); | 2339 | brcmf_err("out of bus->txq !!!\n"); |
2348 | ret = -ENOSR; | 2340 | ret = -ENOSR; |
2349 | } else { | 2341 | } else { |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c new file mode 100644 index 000000000000..071d55f9cd4d --- /dev/null +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | |||
@@ -0,0 +1,382 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 Broadcom Corporation | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | #include <linux/types.h> | ||
17 | #include <linux/if_ether.h> | ||
18 | #include <linux/spinlock.h> | ||
19 | #include <linux/skbuff.h> | ||
20 | #include <linux/netdevice.h> | ||
21 | #include <linux/err.h> | ||
22 | #include <uapi/linux/nl80211.h> | ||
23 | |||
24 | #include <brcmu_utils.h> | ||
25 | #include <brcmu_wifi.h> | ||
26 | #include "dhd.h" | ||
27 | #include "dhd_dbg.h" | ||
28 | #include "fwil.h" | ||
29 | #include "fweh.h" | ||
30 | #include "fwsignal.h" | ||
31 | |||
32 | /** | ||
33 | * DOC: Firmware Signalling | ||
34 | * | ||
35 | * Firmware can send signals to host and vice versa, which are passed in the | ||
36 | * data packets using TLV based header. This signalling layer is on top of the | ||
37 | * BDC bus protocol layer. | ||
38 | */ | ||
39 | |||
40 | /* | ||
41 | * single definition for firmware-driver flow control tlv's. | ||
42 | * | ||
43 | * each tlv is specified by BRCMF_FWS_TLV_DEF(name, ID, length). | ||
44 | * A length value 0 indicates variable length tlv. | ||
45 | */ | ||
46 | #define BRCMF_FWS_TLV_DEFLIST \ | ||
47 | BRCMF_FWS_TLV_DEF(MAC_OPEN, 1, 1) \ | ||
48 | BRCMF_FWS_TLV_DEF(MAC_CLOSE, 2, 1) \ | ||
49 | BRCMF_FWS_TLV_DEF(MAC_REQUEST_CREDIT, 3, 2) \ | ||
50 | BRCMF_FWS_TLV_DEF(TXSTATUS, 4, 4) \ | ||
51 | BRCMF_FWS_TLV_DEF(PKTTAG, 5, 4) \ | ||
52 | BRCMF_FWS_TLV_DEF(MACDESC_ADD, 6, 8) \ | ||
53 | BRCMF_FWS_TLV_DEF(MACDESC_DEL, 7, 8) \ | ||
54 | BRCMF_FWS_TLV_DEF(RSSI, 8, 1) \ | ||
55 | BRCMF_FWS_TLV_DEF(INTERFACE_OPEN, 9, 1) \ | ||
56 | BRCMF_FWS_TLV_DEF(INTERFACE_CLOSE, 10, 1) \ | ||
57 | BRCMF_FWS_TLV_DEF(FIFO_CREDITBACK, 11, 8) \ | ||
58 | BRCMF_FWS_TLV_DEF(PENDING_TRAFFIC_BMP, 12, 2) \ | ||
59 | BRCMF_FWS_TLV_DEF(MAC_REQUEST_PACKET, 13, 3) \ | ||
60 | BRCMF_FWS_TLV_DEF(HOST_REORDER_RXPKTS, 14, 10) \ | ||
61 | BRCMF_FWS_TLV_DEF(TRANS_ID, 18, 6) \ | ||
62 | BRCMF_FWS_TLV_DEF(COMP_TXSTATUS, 19, 1) \ | ||
63 | BRCMF_FWS_TLV_DEF(FILLER, 255, 0) | ||
64 | |||
65 | /** | ||
66 | * enum brcmf_fws_tlv_type - definition of tlv identifiers. | ||
67 | */ | ||
68 | #define BRCMF_FWS_TLV_DEF(name, id, len) \ | ||
69 | BRCMF_FWS_TYPE_ ## name = id, | ||
70 | enum brcmf_fws_tlv_type { | ||
71 | BRCMF_FWS_TLV_DEFLIST | ||
72 | BRCMF_FWS_TYPE_INVALID | ||
73 | }; | ||
74 | #undef BRCMF_FWS_TLV_DEF | ||
75 | |||
76 | /** | ||
77 | * enum brcmf_fws_tlv_len - length values for tlvs. | ||
78 | */ | ||
79 | #define BRCMF_FWS_TLV_DEF(name, id, len) \ | ||
80 | BRCMF_FWS_TYPE_ ## name ## _LEN = len, | ||
81 | enum brcmf_fws_tlv_len { | ||
82 | BRCMF_FWS_TLV_DEFLIST | ||
83 | }; | ||
84 | #undef BRCMF_FWS_TLV_DEF | ||
85 | |||
86 | #ifdef DEBUG | ||
87 | /** | ||
88 | * brcmf_fws_tlv_names - array of tlv names. | ||
89 | */ | ||
90 | #define BRCMF_FWS_TLV_DEF(name, id, len) \ | ||
91 | { id, #name }, | ||
92 | static struct { | ||
93 | enum brcmf_fws_tlv_type id; | ||
94 | const char *name; | ||
95 | } brcmf_fws_tlv_names[] = { | ||
96 | BRCMF_FWS_TLV_DEFLIST | ||
97 | }; | ||
98 | #undef BRCMF_FWS_TLV_DEF | ||
99 | |||
100 | static const char *brcmf_fws_get_tlv_name(enum brcmf_fws_tlv_type id) | ||
101 | { | ||
102 | int i; | ||
103 | |||
104 | for (i = 0; i < ARRAY_SIZE(brcmf_fws_tlv_names); i++) | ||
105 | if (brcmf_fws_tlv_names[i].id == id) | ||
106 | return brcmf_fws_tlv_names[i].name; | ||
107 | |||
108 | return "INVALID"; | ||
109 | } | ||
110 | #else | ||
111 | static const char *brcmf_fws_get_tlv_name(enum brcmf_fws_tlv_type id) | ||
112 | { | ||
113 | return "NODEBUG"; | ||
114 | } | ||
115 | #endif /* DEBUG */ | ||
116 | |||
117 | /** | ||
118 | * flags used to enable tlv signalling from firmware. | ||
119 | */ | ||
120 | #define BRCMF_FWS_FLAGS_RSSI_SIGNALS 0x0001 | ||
121 | #define BRCMF_FWS_FLAGS_XONXOFF_SIGNALS 0x0002 | ||
122 | #define BRCMF_FWS_FLAGS_CREDIT_STATUS_SIGNALS 0x0004 | ||
123 | #define BRCMF_FWS_FLAGS_HOST_PROPTXSTATUS_ACTIVE 0x0008 | ||
124 | #define BRCMF_FWS_FLAGS_PSQ_GENERATIONFSM_ENABLE 0x0010 | ||
125 | #define BRCMF_FWS_FLAGS_PSQ_ZERO_BUFFER_ENABLE 0x0020 | ||
126 | #define BRCMF_FWS_FLAGS_HOST_RXREORDER_ACTIVE 0x0040 | ||
127 | |||
128 | #define BRCMF_FWS_HANGER_MAXITEMS 1024 | ||
129 | #define BRCMF_FWS_HANGER_ITEM_STATE_FREE 1 | ||
130 | #define BRCMF_FWS_HANGER_ITEM_STATE_INUSE 2 | ||
131 | #define BRCMF_FWS_HANGER_ITEM_STATE_INUSE_SUPPRESSED 3 | ||
132 | |||
133 | #define BRCMF_FWS_STATE_OPEN 1 | ||
134 | #define BRCMF_FWS_STATE_CLOSE 2 | ||
135 | |||
136 | #define BRCMF_FWS_FCMODE_NONE 0 | ||
137 | #define BRCMF_FWS_FCMODE_IMPLIED_CREDIT 1 | ||
138 | #define BRCMF_FWS_FCMODE_EXPLICIT_CREDIT 2 | ||
139 | |||
140 | #define BRCMF_FWS_MAC_DESC_TABLE_SIZE 32 | ||
141 | #define BRCMF_FWS_MAX_IFNUM 16 | ||
142 | #define BRCMF_FWS_MAC_DESC_ID_INVALID 0xff | ||
143 | |||
144 | #define BRCMF_FWS_HOSTIF_FLOWSTATE_OFF 0 | ||
145 | #define BRCMF_FWS_HOSTIF_FLOWSTATE_ON 1 | ||
146 | |||
147 | /** | ||
148 | * FWFC packet identifier | ||
149 | * | ||
150 | * 32-bit packet identifier used in PKTTAG tlv from host to dongle. | ||
151 | * | ||
152 | * - Generated at the host (e.g. dhd) | ||
153 | * - Seen as a generic sequence number by wlc except the flags field | ||
154 | * | ||
155 | * Generation : b[31] => generation number for this packet [host->fw] | ||
156 | * OR, current generation number [fw->host] | ||
157 | * Flags : b[30:27] => command, status flags | ||
158 | * FIFO-AC : b[26:24] => AC-FIFO id | ||
159 | * h-slot : b[23:8] => hanger-slot | ||
160 | * freerun : b[7:0] => A free running counter | ||
161 | */ | ||
162 | #define BRCMF_FWS_PKTTAG_GENERATION_MASK 0x80000000 | ||
163 | #define BRCMF_FWS_PKTTAG_GENERATION_SHIFT 31 | ||
164 | #define BRCMF_FWS_PKTTAG_FLAGS_MASK 0x78000000 | ||
165 | #define BRCMF_FWS_PKTTAG_FLAGS_SHIFT 27 | ||
166 | #define BRCMF_FWS_PKTTAG_FIFO_MASK 0x07000000 | ||
167 | #define BRCMF_FWS_PKTTAG_FIFO_SHIFT 24 | ||
168 | #define BRCMF_FWS_PKTTAG_HSLOT_MASK 0x00ffff00 | ||
169 | #define BRCMF_FWS_PKTTAG_HSLOT_SHIFT 8 | ||
170 | #define BRCMF_FWS_PKTTAG_FREERUN_MASK 0x000000ff | ||
171 | #define BRCMF_FWS_PKTTAG_FREERUN_SHIFT 0 | ||
172 | |||
173 | #define brcmf_fws_pkttag_set_field(var, field, value) \ | ||
174 | brcmu_maskset32((var), BRCMF_FWS_PKTTAG_ ## field ## _MASK, \ | ||
175 | BRCMF_FWS_PKTTAG_ ## field ## _SHIFT, (value)) | ||
176 | #define brcmf_fws_pkttag_get_field(var, field) \ | ||
177 | brcmu_maskget32((var), BRCMF_FWS_PKTTAG_ ## field ## _MASK, \ | ||
178 | BRCMF_FWS_PKTTAG_ ## field ## _SHIFT) | ||
179 | |||
180 | struct brcmf_fws_info { | ||
181 | struct brcmf_pub *drvr; | ||
182 | struct brcmf_fws_stats stats; | ||
183 | }; | ||
184 | |||
185 | static int brcmf_fws_rssi_indicate(struct brcmf_fws_info *fws, s8 rssi) | ||
186 | { | ||
187 | brcmf_dbg(CTL, "rssi %d\n", rssi); | ||
188 | return 0; | ||
189 | } | ||
190 | |||
191 | static int brcmf_fws_dbg_seqnum_check(struct brcmf_fws_info *fws, u8 *data) | ||
192 | { | ||
193 | __le32 timestamp; | ||
194 | |||
195 | memcpy(×tamp, &data[2], sizeof(timestamp)); | ||
196 | brcmf_dbg(INFO, "received: seq %d, timestamp %d\n", data[1], | ||
197 | le32_to_cpu(timestamp)); | ||
198 | return 0; | ||
199 | } | ||
200 | |||
201 | /* using macro so sparse checking does not complain | ||
202 | * about locking imbalance. | ||
203 | */ | ||
204 | #define brcmf_fws_lock(drvr, flags) \ | ||
205 | do { \ | ||
206 | flags = 0; \ | ||
207 | spin_lock_irqsave(&((drvr)->fws_spinlock), (flags)); \ | ||
208 | } while (0) | ||
209 | |||
210 | /* using macro so sparse checking does not complain | ||
211 | * about locking imbalance. | ||
212 | */ | ||
213 | #define brcmf_fws_unlock(drvr, flags) \ | ||
214 | spin_unlock_irqrestore(&((drvr)->fws_spinlock), (flags)) | ||
215 | |||
216 | int brcmf_fws_init(struct brcmf_pub *drvr) | ||
217 | { | ||
218 | u32 tlv; | ||
219 | int rc; | ||
220 | |||
221 | /* enable rssi signals */ | ||
222 | tlv = drvr->fw_signals ? BRCMF_FWS_FLAGS_RSSI_SIGNALS : 0; | ||
223 | |||
224 | spin_lock_init(&drvr->fws_spinlock); | ||
225 | |||
226 | drvr->fws = kzalloc(sizeof(*(drvr->fws)), GFP_KERNEL); | ||
227 | if (!drvr->fws) { | ||
228 | rc = -ENOMEM; | ||
229 | goto fail; | ||
230 | } | ||
231 | |||
232 | /* enable proptxtstatus signaling by default */ | ||
233 | rc = brcmf_fil_iovar_int_set(drvr->iflist[0], "tlv", tlv); | ||
234 | if (rc < 0) { | ||
235 | brcmf_err("failed to set bdcv2 tlv signaling\n"); | ||
236 | goto fail; | ||
237 | } | ||
238 | /* set linkage back */ | ||
239 | drvr->fws->drvr = drvr; | ||
240 | |||
241 | /* create debugfs file for statistics */ | ||
242 | brcmf_debugfs_create_fws_stats(drvr, &drvr->fws->stats); | ||
243 | |||
244 | /* TODO: remove upon feature delivery */ | ||
245 | brcmf_err("%s bdcv2 tlv signaling [%x]\n", | ||
246 | drvr->fw_signals ? "enabled" : "disabled", tlv); | ||
247 | return 0; | ||
248 | |||
249 | fail: | ||
250 | /* disable flow control entirely */ | ||
251 | drvr->fw_signals = false; | ||
252 | brcmf_fws_deinit(drvr); | ||
253 | return rc; | ||
254 | } | ||
255 | |||
256 | void brcmf_fws_deinit(struct brcmf_pub *drvr) | ||
257 | { | ||
258 | /* free top structure */ | ||
259 | kfree(drvr->fws); | ||
260 | drvr->fws = NULL; | ||
261 | } | ||
262 | |||
263 | int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len, | ||
264 | struct sk_buff *skb) | ||
265 | { | ||
266 | struct brcmf_fws_info *fws = drvr->fws; | ||
267 | ulong flags; | ||
268 | u8 *signal_data; | ||
269 | s16 data_len; | ||
270 | u8 type; | ||
271 | u8 len; | ||
272 | u8 *data; | ||
273 | |||
274 | brcmf_dbg(TRACE, "enter: ifidx %d, skblen %u, sig %d\n", | ||
275 | ifidx, skb->len, signal_len); | ||
276 | |||
277 | WARN_ON(signal_len > skb->len); | ||
278 | |||
279 | /* if flow control disabled, skip to packet data and leave */ | ||
280 | if (!signal_len || !drvr->fw_signals) { | ||
281 | skb_pull(skb, signal_len); | ||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | /* lock during tlv parsing */ | ||
286 | brcmf_fws_lock(drvr, flags); | ||
287 | |||
288 | fws->stats.header_pulls++; | ||
289 | data_len = signal_len; | ||
290 | signal_data = skb->data; | ||
291 | |||
292 | while (data_len > 0) { | ||
293 | /* extract tlv info */ | ||
294 | type = signal_data[0]; | ||
295 | |||
296 | /* FILLER type is actually not a TLV, but | ||
297 | * a single byte that can be skipped. | ||
298 | */ | ||
299 | if (type == BRCMF_FWS_TYPE_FILLER) { | ||
300 | signal_data += 1; | ||
301 | data_len -= 1; | ||
302 | continue; | ||
303 | } | ||
304 | len = signal_data[1]; | ||
305 | data = signal_data + 2; | ||
306 | |||
307 | /* abort parsing when length invalid */ | ||
308 | if (data_len < len + 2) | ||
309 | break; | ||
310 | |||
311 | brcmf_dbg(INFO, "tlv type=%d (%s), len=%d\n", type, | ||
312 | brcmf_fws_get_tlv_name(type), len); | ||
313 | switch (type) { | ||
314 | case BRCMF_FWS_TYPE_MAC_OPEN: | ||
315 | case BRCMF_FWS_TYPE_MAC_CLOSE: | ||
316 | WARN_ON(len != BRCMF_FWS_TYPE_MAC_OPEN_LEN); | ||
317 | break; | ||
318 | case BRCMF_FWS_TYPE_MAC_REQUEST_CREDIT: | ||
319 | WARN_ON(len != BRCMF_FWS_TYPE_MAC_REQUEST_CREDIT_LEN); | ||
320 | break; | ||
321 | case BRCMF_FWS_TYPE_TXSTATUS: | ||
322 | WARN_ON(len != BRCMF_FWS_TYPE_TXSTATUS_LEN); | ||
323 | break; | ||
324 | case BRCMF_FWS_TYPE_PKTTAG: | ||
325 | WARN_ON(len != BRCMF_FWS_TYPE_PKTTAG_LEN); | ||
326 | break; | ||
327 | case BRCMF_FWS_TYPE_MACDESC_ADD: | ||
328 | case BRCMF_FWS_TYPE_MACDESC_DEL: | ||
329 | WARN_ON(len != BRCMF_FWS_TYPE_MACDESC_ADD_LEN); | ||
330 | break; | ||
331 | case BRCMF_FWS_TYPE_RSSI: | ||
332 | WARN_ON(len != BRCMF_FWS_TYPE_RSSI_LEN); | ||
333 | brcmf_fws_rssi_indicate(fws, *(s8 *)data); | ||
334 | break; | ||
335 | case BRCMF_FWS_TYPE_INTERFACE_OPEN: | ||
336 | case BRCMF_FWS_TYPE_INTERFACE_CLOSE: | ||
337 | WARN_ON(len != BRCMF_FWS_TYPE_INTERFACE_OPEN_LEN); | ||
338 | break; | ||
339 | case BRCMF_FWS_TYPE_FIFO_CREDITBACK: | ||
340 | WARN_ON(len != BRCMF_FWS_TYPE_FIFO_CREDITBACK_LEN); | ||
341 | break; | ||
342 | case BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP: | ||
343 | WARN_ON(len != BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN); | ||
344 | break; | ||
345 | case BRCMF_FWS_TYPE_MAC_REQUEST_PACKET: | ||
346 | WARN_ON(len != BRCMF_FWS_TYPE_MAC_REQUEST_PACKET_LEN); | ||
347 | break; | ||
348 | case BRCMF_FWS_TYPE_HOST_REORDER_RXPKTS: | ||
349 | WARN_ON(len != BRCMF_FWS_TYPE_HOST_REORDER_RXPKTS_LEN); | ||
350 | break; | ||
351 | case BRCMF_FWS_TYPE_TRANS_ID: | ||
352 | WARN_ON(len != BRCMF_FWS_TYPE_TRANS_ID_LEN); | ||
353 | brcmf_fws_dbg_seqnum_check(fws, data); | ||
354 | break; | ||
355 | case BRCMF_FWS_TYPE_COMP_TXSTATUS: | ||
356 | WARN_ON(len != BRCMF_FWS_TYPE_COMP_TXSTATUS_LEN); | ||
357 | break; | ||
358 | default: | ||
359 | fws->stats.tlv_invalid_type++; | ||
360 | break; | ||
361 | } | ||
362 | |||
363 | signal_data += len + 2; | ||
364 | data_len -= len + 2; | ||
365 | } | ||
366 | |||
367 | if (data_len != 0) | ||
368 | fws->stats.tlv_parse_failed++; | ||
369 | |||
370 | /* signalling processing result does | ||
371 | * not affect the actual ethernet packet. | ||
372 | */ | ||
373 | skb_pull(skb, signal_len); | ||
374 | |||
375 | /* this may be a signal-only packet | ||
376 | */ | ||
377 | if (skb->len == 0) | ||
378 | fws->stats.header_only_pkt++; | ||
379 | |||
380 | brcmf_fws_unlock(drvr, flags); | ||
381 | return 0; | ||
382 | } | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h new file mode 100644 index 000000000000..e728eea72bb4 --- /dev/null +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h | |||
@@ -0,0 +1,25 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Broadcom Corporation | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | |||
18 | #ifndef FWSIGNAL_H_ | ||
19 | #define FWSIGNAL_H_ | ||
20 | |||
21 | int brcmf_fws_init(struct brcmf_pub *drvr); | ||
22 | void brcmf_fws_deinit(struct brcmf_pub *drvr); | ||
23 | int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len, | ||
24 | struct sk_buff *skb); | ||
25 | #endif /* FWSIGNAL_H_ */ | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.c b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.c new file mode 100644 index 000000000000..b505db48c60d --- /dev/null +++ b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.c | |||
@@ -0,0 +1,22 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Broadcom Corporation | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include <linux/module.h> /* bug in tracepoint.h, it should include this */ | ||
18 | |||
19 | #ifndef __CHECKER__ | ||
20 | #define CREATE_TRACE_POINTS | ||
21 | #include "tracepoint.h" | ||
22 | #endif | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h new file mode 100644 index 000000000000..35efc7a67644 --- /dev/null +++ b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h | |||
@@ -0,0 +1,87 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Broadcom Corporation | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | #if !defined(BRCMF_TRACEPOINT_H_) || defined(TRACE_HEADER_MULTI_READ) | ||
17 | #define BRCMF_TRACEPOINT_H_ | ||
18 | |||
19 | #include <linux/types.h> | ||
20 | #include <linux/tracepoint.h> | ||
21 | |||
22 | #ifndef CONFIG_BRCM_TRACING | ||
23 | |||
24 | #undef TRACE_EVENT | ||
25 | #define TRACE_EVENT(name, proto, ...) \ | ||
26 | static inline void trace_ ## name(proto) {} | ||
27 | |||
28 | #undef DECLARE_EVENT_CLASS | ||
29 | #define DECLARE_EVENT_CLASS(...) | ||
30 | |||
31 | #undef DEFINE_EVENT | ||
32 | #define DEFINE_EVENT(evt_class, name, proto, ...) \ | ||
33 | static inline void trace_ ## name(proto) {} | ||
34 | |||
35 | #endif /* CONFIG_BRCM_TRACING */ | ||
36 | |||
37 | #undef TRACE_SYSTEM | ||
38 | #define TRACE_SYSTEM brcmfmac | ||
39 | |||
40 | #define MAX_MSG_LEN 100 | ||
41 | |||
42 | TRACE_EVENT(brcmf_err, | ||
43 | TP_PROTO(const char *func, struct va_format *vaf), | ||
44 | TP_ARGS(func, vaf), | ||
45 | TP_STRUCT__entry( | ||
46 | __string(func, func) | ||
47 | __dynamic_array(char, msg, MAX_MSG_LEN) | ||
48 | ), | ||
49 | TP_fast_assign( | ||
50 | __assign_str(func, func); | ||
51 | WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg), | ||
52 | MAX_MSG_LEN, vaf->fmt, | ||
53 | *vaf->va) >= MAX_MSG_LEN); | ||
54 | ), | ||
55 | TP_printk("%s: %s", __get_str(func), __get_str(msg)) | ||
56 | ); | ||
57 | |||
58 | TRACE_EVENT(brcmf_dbg, | ||
59 | TP_PROTO(u32 level, const char *func, struct va_format *vaf), | ||
60 | TP_ARGS(level, func, vaf), | ||
61 | TP_STRUCT__entry( | ||
62 | __field(u32, level) | ||
63 | __string(func, func) | ||
64 | __dynamic_array(char, msg, MAX_MSG_LEN) | ||
65 | ), | ||
66 | TP_fast_assign( | ||
67 | __entry->level = level; | ||
68 | __assign_str(func, func); | ||
69 | WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg), | ||
70 | MAX_MSG_LEN, vaf->fmt, | ||
71 | *vaf->va) >= MAX_MSG_LEN); | ||
72 | ), | ||
73 | TP_printk("%s: %s", __get_str(func), __get_str(msg)) | ||
74 | ); | ||
75 | |||
76 | #ifdef CONFIG_BRCM_TRACING | ||
77 | |||
78 | #undef TRACE_INCLUDE_PATH | ||
79 | #define TRACE_INCLUDE_PATH . | ||
80 | #undef TRACE_INCLUDE_FILE | ||
81 | #define TRACE_INCLUDE_FILE tracepoint | ||
82 | |||
83 | #include <trace/define_trace.h> | ||
84 | |||
85 | #endif /* CONFIG_BRCM_TRACING */ | ||
86 | |||
87 | #endif /* BRCMF_TRACEPOINT_H_ */ | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index 42289e9ea886..01aed7ad6bec 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c | |||
@@ -112,11 +112,6 @@ struct brcmf_usbdev_info { | |||
112 | static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo, | 112 | static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo, |
113 | struct brcmf_usbreq *req); | 113 | struct brcmf_usbreq *req); |
114 | 114 | ||
115 | MODULE_AUTHOR("Broadcom Corporation"); | ||
116 | MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN fullmac usb driver."); | ||
117 | MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN fullmac usb cards"); | ||
118 | MODULE_LICENSE("Dual BSD/GPL"); | ||
119 | |||
120 | static struct brcmf_usbdev *brcmf_usb_get_buspub(struct device *dev) | 115 | static struct brcmf_usbdev *brcmf_usb_get_buspub(struct device *dev) |
121 | { | 116 | { |
122 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | 117 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); |
@@ -422,8 +417,6 @@ static void brcmf_usb_tx_complete(struct urb *urb) | |||
422 | brcmf_usb_del_fromq(devinfo, req); | 417 | brcmf_usb_del_fromq(devinfo, req); |
423 | 418 | ||
424 | brcmf_txcomplete(devinfo->dev, req->skb, urb->status == 0); | 419 | brcmf_txcomplete(devinfo->dev, req->skb, urb->status == 0); |
425 | |||
426 | brcmu_pkt_buf_free_skb(req->skb); | ||
427 | req->skb = NULL; | 420 | req->skb = NULL; |
428 | brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req, &devinfo->tx_freecount); | 421 | brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req, &devinfo->tx_freecount); |
429 | if (devinfo->tx_freecount > devinfo->tx_high_watermark && | 422 | if (devinfo->tx_freecount > devinfo->tx_high_watermark && |
@@ -577,15 +570,17 @@ static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb) | |||
577 | int ret; | 570 | int ret; |
578 | 571 | ||
579 | brcmf_dbg(USB, "Enter, skb=%p\n", skb); | 572 | brcmf_dbg(USB, "Enter, skb=%p\n", skb); |
580 | if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP) | 573 | if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP) { |
581 | return -EIO; | 574 | ret = -EIO; |
575 | goto fail; | ||
576 | } | ||
582 | 577 | ||
583 | req = brcmf_usb_deq(devinfo, &devinfo->tx_freeq, | 578 | req = brcmf_usb_deq(devinfo, &devinfo->tx_freeq, |
584 | &devinfo->tx_freecount); | 579 | &devinfo->tx_freecount); |
585 | if (!req) { | 580 | if (!req) { |
586 | brcmu_pkt_buf_free_skb(skb); | ||
587 | brcmf_err("no req to send\n"); | 581 | brcmf_err("no req to send\n"); |
588 | return -ENOMEM; | 582 | ret = -ENOMEM; |
583 | goto fail; | ||
589 | } | 584 | } |
590 | 585 | ||
591 | req->skb = skb; | 586 | req->skb = skb; |
@@ -598,18 +593,21 @@ static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb) | |||
598 | if (ret) { | 593 | if (ret) { |
599 | brcmf_err("brcmf_usb_tx usb_submit_urb FAILED\n"); | 594 | brcmf_err("brcmf_usb_tx usb_submit_urb FAILED\n"); |
600 | brcmf_usb_del_fromq(devinfo, req); | 595 | brcmf_usb_del_fromq(devinfo, req); |
601 | brcmu_pkt_buf_free_skb(req->skb); | ||
602 | req->skb = NULL; | 596 | req->skb = NULL; |
603 | brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req, | 597 | brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req, |
604 | &devinfo->tx_freecount); | 598 | &devinfo->tx_freecount); |
605 | } else { | 599 | goto fail; |
606 | if (devinfo->tx_freecount < devinfo->tx_low_watermark && | ||
607 | !devinfo->tx_flowblock) { | ||
608 | brcmf_txflowblock(dev, true); | ||
609 | devinfo->tx_flowblock = true; | ||
610 | } | ||
611 | } | 600 | } |
612 | 601 | ||
602 | if (devinfo->tx_freecount < devinfo->tx_low_watermark && | ||
603 | !devinfo->tx_flowblock) { | ||
604 | brcmf_txflowblock(dev, true); | ||
605 | devinfo->tx_flowblock = true; | ||
606 | } | ||
607 | return 0; | ||
608 | |||
609 | fail: | ||
610 | brcmf_txcomplete(dev, skb, false); | ||
613 | return ret; | 611 | return ret; |
614 | } | 612 | } |
615 | 613 | ||
@@ -1485,6 +1483,7 @@ static struct usb_device_id brcmf_usb_devid_table[] = { | |||
1485 | { USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_BCMFW) }, | 1483 | { USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_BCMFW) }, |
1486 | { } | 1484 | { } |
1487 | }; | 1485 | }; |
1486 | |||
1488 | MODULE_DEVICE_TABLE(usb, brcmf_usb_devid_table); | 1487 | MODULE_DEVICE_TABLE(usb, brcmf_usb_devid_table); |
1489 | MODULE_FIRMWARE(BRCMF_USB_43143_FW_NAME); | 1488 | MODULE_FIRMWARE(BRCMF_USB_43143_FW_NAME); |
1490 | MODULE_FIRMWARE(BRCMF_USB_43236_FW_NAME); | 1489 | MODULE_FIRMWARE(BRCMF_USB_43236_FW_NAME); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 2af9c0f0798d..804473fc5c5e 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | |||
@@ -3052,16 +3052,16 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy, | |||
3052 | int i; | 3052 | int i; |
3053 | int ret = 0; | 3053 | int ret = 0; |
3054 | 3054 | ||
3055 | brcmf_dbg(SCAN, "Enter n_match_sets:%d n_ssids:%d\n", | 3055 | brcmf_dbg(SCAN, "Enter n_match_sets:%d n_ssids:%d\n", |
3056 | request->n_match_sets, request->n_ssids); | 3056 | request->n_match_sets, request->n_ssids); |
3057 | if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { | 3057 | if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { |
3058 | brcmf_err("Scanning already: status (%lu)\n", cfg->scan_status); | 3058 | brcmf_err("Scanning already: status (%lu)\n", cfg->scan_status); |
3059 | return -EAGAIN; | 3059 | return -EAGAIN; |
3060 | } | 3060 | } |
3061 | 3061 | ||
3062 | if (!request || !request->n_ssids || !request->n_match_sets) { | 3062 | if (!request->n_ssids || !request->n_match_sets) { |
3063 | brcmf_err("Invalid sched scan req!! n_ssids:%d\n", | 3063 | brcmf_err("Invalid sched scan req!! n_ssids:%d\n", |
3064 | request ? request->n_ssids : 0); | 3064 | request->n_ssids); |
3065 | return -EINVAL; | 3065 | return -EINVAL; |
3066 | } | 3066 | } |
3067 | 3067 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/Makefile b/drivers/net/wireless/brcm80211/brcmsmac/Makefile index d3d4151c3eda..cba19d839b77 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/Makefile +++ b/drivers/net/wireless/brcm80211/brcmsmac/Makefile | |||
@@ -43,6 +43,10 @@ BRCMSMAC_OFILES := \ | |||
43 | brcms_trace_events.o \ | 43 | brcms_trace_events.o \ |
44 | debug.o | 44 | debug.o |
45 | 45 | ||
46 | ifdef CONFIG_BCMA_DRIVER_GPIO | ||
47 | BRCMSMAC_OFILES += led.o | ||
48 | endif | ||
49 | |||
46 | MODULEPFX := brcmsmac | 50 | MODULEPFX := brcmsmac |
47 | 51 | ||
48 | obj-$(CONFIG_BRCMSMAC) += $(MODULEPFX).o | 52 | obj-$(CONFIG_BRCMSMAC) += $(MODULEPFX).o |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/led.c b/drivers/net/wireless/brcm80211/brcmsmac/led.c new file mode 100644 index 000000000000..74b17cecb189 --- /dev/null +++ b/drivers/net/wireless/brcm80211/brcmsmac/led.c | |||
@@ -0,0 +1,126 @@ | |||
1 | #include <net/mac80211.h> | ||
2 | #include <linux/bcma/bcma_driver_chipcommon.h> | ||
3 | #include <linux/gpio.h> | ||
4 | |||
5 | #include "mac80211_if.h" | ||
6 | #include "pub.h" | ||
7 | #include "main.h" | ||
8 | #include "led.h" | ||
9 | |||
10 | /* number of leds */ | ||
11 | #define BRCMS_LED_NO 4 | ||
12 | /* behavior mask */ | ||
13 | #define BRCMS_LED_BEH_MASK 0x7f | ||
14 | /* activelow (polarity) bit */ | ||
15 | #define BRCMS_LED_AL_MASK 0x80 | ||
16 | /* radio enabled */ | ||
17 | #define BRCMS_LED_RADIO 3 | ||
18 | |||
19 | static void brcms_radio_led_ctrl(struct brcms_info *wl, bool state) | ||
20 | { | ||
21 | if (wl->radio_led.gpio == -1) | ||
22 | return; | ||
23 | |||
24 | if (wl->radio_led.active_low) | ||
25 | state = !state; | ||
26 | |||
27 | if (state) | ||
28 | gpio_set_value(wl->radio_led.gpio, 1); | ||
29 | else | ||
30 | gpio_set_value(wl->radio_led.gpio, 0); | ||
31 | } | ||
32 | |||
33 | |||
34 | /* Callback from the LED subsystem. */ | ||
35 | static void brcms_led_brightness_set(struct led_classdev *led_dev, | ||
36 | enum led_brightness brightness) | ||
37 | { | ||
38 | struct brcms_info *wl = container_of(led_dev, | ||
39 | struct brcms_info, led_dev); | ||
40 | brcms_radio_led_ctrl(wl, brightness); | ||
41 | } | ||
42 | |||
43 | void brcms_led_unregister(struct brcms_info *wl) | ||
44 | { | ||
45 | if (wl->led_dev.dev) | ||
46 | led_classdev_unregister(&wl->led_dev); | ||
47 | if (wl->radio_led.gpio != -1) | ||
48 | gpio_free(wl->radio_led.gpio); | ||
49 | } | ||
50 | |||
51 | int brcms_led_register(struct brcms_info *wl) | ||
52 | { | ||
53 | int i, err; | ||
54 | struct brcms_led *radio_led = &wl->radio_led; | ||
55 | /* get CC core */ | ||
56 | struct bcma_drv_cc *cc_drv = &wl->wlc->hw->d11core->bus->drv_cc; | ||
57 | struct gpio_chip *bcma_gpio = &cc_drv->gpio; | ||
58 | struct ssb_sprom *sprom = &wl->wlc->hw->d11core->bus->sprom; | ||
59 | u8 *leds[] = { &sprom->gpio0, | ||
60 | &sprom->gpio1, | ||
61 | &sprom->gpio2, | ||
62 | &sprom->gpio3 }; | ||
63 | unsigned gpio = -1; | ||
64 | bool active_low = false; | ||
65 | |||
66 | /* none by default */ | ||
67 | radio_led->gpio = -1; | ||
68 | radio_led->active_low = false; | ||
69 | |||
70 | if (!bcma_gpio || !gpio_is_valid(bcma_gpio->base)) | ||
71 | return -ENODEV; | ||
72 | |||
73 | /* find radio enabled LED */ | ||
74 | for (i = 0; i < BRCMS_LED_NO; i++) { | ||
75 | u8 led = *leds[i]; | ||
76 | if ((led & BRCMS_LED_BEH_MASK) == BRCMS_LED_RADIO) { | ||
77 | gpio = bcma_gpio->base + i; | ||
78 | if (led & BRCMS_LED_AL_MASK) | ||
79 | active_low = true; | ||
80 | break; | ||
81 | } | ||
82 | } | ||
83 | |||
84 | if (gpio == -1 || !gpio_is_valid(gpio)) | ||
85 | return -ENODEV; | ||
86 | |||
87 | /* request and configure LED gpio */ | ||
88 | err = gpio_request_one(gpio, | ||
89 | active_low ? GPIOF_OUT_INIT_HIGH | ||
90 | : GPIOF_OUT_INIT_LOW, | ||
91 | "radio on"); | ||
92 | if (err) { | ||
93 | wiphy_err(wl->wiphy, "requesting led gpio %d failed (err: %d)\n", | ||
94 | gpio, err); | ||
95 | return err; | ||
96 | } | ||
97 | err = gpio_direction_output(gpio, 1); | ||
98 | if (err) { | ||
99 | wiphy_err(wl->wiphy, "cannot set led gpio %d to output (err: %d)\n", | ||
100 | gpio, err); | ||
101 | return err; | ||
102 | } | ||
103 | |||
104 | snprintf(wl->radio_led.name, sizeof(wl->radio_led.name), | ||
105 | "brcmsmac-%s:radio", wiphy_name(wl->wiphy)); | ||
106 | |||
107 | wl->led_dev.name = wl->radio_led.name; | ||
108 | wl->led_dev.default_trigger = | ||
109 | ieee80211_get_radio_led_name(wl->pub->ieee_hw); | ||
110 | wl->led_dev.brightness_set = brcms_led_brightness_set; | ||
111 | err = led_classdev_register(wiphy_dev(wl->wiphy), &wl->led_dev); | ||
112 | |||
113 | if (err) { | ||
114 | wiphy_err(wl->wiphy, "cannot register led device: %s (err: %d)\n", | ||
115 | wl->radio_led.name, err); | ||
116 | return err; | ||
117 | } | ||
118 | |||
119 | wiphy_info(wl->wiphy, "registered radio enabled led device: %s gpio: %d\n", | ||
120 | wl->radio_led.name, | ||
121 | gpio); | ||
122 | radio_led->gpio = gpio; | ||
123 | radio_led->active_low = active_low; | ||
124 | |||
125 | return 0; | ||
126 | } | ||
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/led.h b/drivers/net/wireless/brcm80211/brcmsmac/led.h new file mode 100644 index 000000000000..17a0b1f5dbcf --- /dev/null +++ b/drivers/net/wireless/brcm80211/brcmsmac/led.h | |||
@@ -0,0 +1,36 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Broadcom Corporation | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef _BRCM_LED_H_ | ||
18 | #define _BRCM_LED_H_ | ||
19 | struct brcms_led { | ||
20 | char name[32]; | ||
21 | unsigned gpio; | ||
22 | bool active_low; | ||
23 | }; | ||
24 | |||
25 | #ifdef CONFIG_BCMA_DRIVER_GPIO | ||
26 | void brcms_led_unregister(struct brcms_info *wl); | ||
27 | int brcms_led_register(struct brcms_info *wl); | ||
28 | #else | ||
29 | static inline void brcms_led_unregister(struct brcms_info *wl) {}; | ||
30 | static inline int brcms_led_register(struct brcms_info *wl) | ||
31 | { | ||
32 | return -ENOTSUPP; | ||
33 | }; | ||
34 | #endif | ||
35 | |||
36 | #endif /* _BRCM_LED_H_ */ | ||
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index c6451c61407a..c70cf7b654cd 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include "mac80211_if.h" | 34 | #include "mac80211_if.h" |
35 | #include "main.h" | 35 | #include "main.h" |
36 | #include "debug.h" | 36 | #include "debug.h" |
37 | #include "led.h" | ||
37 | 38 | ||
38 | #define N_TX_QUEUES 4 /* #tx queues on mac80211<->driver interface */ | 39 | #define N_TX_QUEUES 4 /* #tx queues on mac80211<->driver interface */ |
39 | #define BRCMS_FLUSH_TIMEOUT 500 /* msec */ | 40 | #define BRCMS_FLUSH_TIMEOUT 500 /* msec */ |
@@ -904,6 +905,7 @@ static void brcms_remove(struct bcma_device *pdev) | |||
904 | struct brcms_info *wl = hw->priv; | 905 | struct brcms_info *wl = hw->priv; |
905 | 906 | ||
906 | if (wl->wlc) { | 907 | if (wl->wlc) { |
908 | brcms_led_unregister(wl); | ||
907 | wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false); | 909 | wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false); |
908 | wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy); | 910 | wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy); |
909 | ieee80211_unregister_hw(hw); | 911 | ieee80211_unregister_hw(hw); |
@@ -1151,6 +1153,8 @@ static int brcms_bcma_probe(struct bcma_device *pdev) | |||
1151 | pr_err("%s: brcms_attach failed!\n", __func__); | 1153 | pr_err("%s: brcms_attach failed!\n", __func__); |
1152 | return -ENODEV; | 1154 | return -ENODEV; |
1153 | } | 1155 | } |
1156 | brcms_led_register(wl); | ||
1157 | |||
1154 | return 0; | 1158 | return 0; |
1155 | } | 1159 | } |
1156 | 1160 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h index 947ccacf43e6..4090032e81a2 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h | |||
@@ -20,8 +20,10 @@ | |||
20 | #include <linux/timer.h> | 20 | #include <linux/timer.h> |
21 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
22 | #include <linux/workqueue.h> | 22 | #include <linux/workqueue.h> |
23 | #include <linux/leds.h> | ||
23 | 24 | ||
24 | #include "ucode_loader.h" | 25 | #include "ucode_loader.h" |
26 | #include "led.h" | ||
25 | /* | 27 | /* |
26 | * Starting index for 5G rates in the | 28 | * Starting index for 5G rates in the |
27 | * legacy rate table. | 29 | * legacy rate table. |
@@ -81,6 +83,8 @@ struct brcms_info { | |||
81 | struct wiphy *wiphy; | 83 | struct wiphy *wiphy; |
82 | struct brcms_ucode ucode; | 84 | struct brcms_ucode ucode; |
83 | bool mute_tx; | 85 | bool mute_tx; |
86 | struct brcms_led radio_led; | ||
87 | struct led_classdev led_dev; | ||
84 | }; | 88 | }; |
85 | 89 | ||
86 | /* misc callbacks */ | 90 | /* misc callbacks */ |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c index 8ef02dca8f8c..0c8e998bfb1e 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c | |||
@@ -7810,9 +7810,14 @@ void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx) | |||
7810 | 7810 | ||
7811 | /* read the ucode version if we have not yet done so */ | 7811 | /* read the ucode version if we have not yet done so */ |
7812 | if (wlc->ucode_rev == 0) { | 7812 | if (wlc->ucode_rev == 0) { |
7813 | wlc->ucode_rev = | 7813 | u16 rev; |
7814 | brcms_b_read_shm(wlc->hw, M_BOM_REV_MAJOR) << NBITS(u16); | 7814 | u16 patch; |
7815 | wlc->ucode_rev |= brcms_b_read_shm(wlc->hw, M_BOM_REV_MINOR); | 7815 | |
7816 | rev = brcms_b_read_shm(wlc->hw, M_BOM_REV_MAJOR); | ||
7817 | patch = brcms_b_read_shm(wlc->hw, M_BOM_REV_MINOR); | ||
7818 | wlc->ucode_rev = (rev << NBITS(u16)) | patch; | ||
7819 | snprintf(wlc->wiphy->fw_version, | ||
7820 | sizeof(wlc->wiphy->fw_version), "%u.%u", rev, patch); | ||
7816 | } | 7821 | } |
7817 | 7822 | ||
7818 | /* ..now really unleash hell (allow the MAC out of suspend) */ | 7823 | /* ..now really unleash hell (allow the MAC out of suspend) */ |
diff --git a/drivers/net/wireless/brcm80211/brcmutil/utils.c b/drivers/net/wireless/brcm80211/brcmutil/utils.c index 3e6405e06ac0..bf5e50fc21ba 100644 --- a/drivers/net/wireless/brcm80211/brcmutil/utils.c +++ b/drivers/net/wireless/brcm80211/brcmutil/utils.c | |||
@@ -116,6 +116,31 @@ struct sk_buff *brcmu_pktq_pdeq(struct pktq *pq, int prec) | |||
116 | } | 116 | } |
117 | EXPORT_SYMBOL(brcmu_pktq_pdeq); | 117 | EXPORT_SYMBOL(brcmu_pktq_pdeq); |
118 | 118 | ||
119 | /* | ||
120 | * precedence based dequeue with match function. Passing a NULL pointer | ||
121 | * for the match function parameter is considered to be a wildcard so | ||
122 | * any packet on the queue is returned. In that case it is no different | ||
123 | * from brcmu_pktq_pdeq() above. | ||
124 | */ | ||
125 | struct sk_buff *brcmu_pktq_pdeq_match(struct pktq *pq, int prec, | ||
126 | bool (*match_fn)(struct sk_buff *skb, | ||
127 | void *arg), void *arg) | ||
128 | { | ||
129 | struct sk_buff_head *q; | ||
130 | struct sk_buff *p, *next; | ||
131 | |||
132 | q = &pq->q[prec].skblist; | ||
133 | skb_queue_walk_safe(q, p, next) { | ||
134 | if (match_fn == NULL || match_fn(p, arg)) { | ||
135 | skb_unlink(p, q); | ||
136 | pq->len--; | ||
137 | return p; | ||
138 | } | ||
139 | } | ||
140 | return NULL; | ||
141 | } | ||
142 | EXPORT_SYMBOL(brcmu_pktq_pdeq_match); | ||
143 | |||
119 | struct sk_buff *brcmu_pktq_pdeq_tail(struct pktq *pq, int prec) | 144 | struct sk_buff *brcmu_pktq_pdeq_tail(struct pktq *pq, int prec) |
120 | { | 145 | { |
121 | struct sk_buff_head *q; | 146 | struct sk_buff_head *q; |
diff --git a/drivers/net/wireless/brcm80211/include/brcmu_utils.h b/drivers/net/wireless/brcm80211/include/brcmu_utils.h index 477b92ad3d62..898cacb8d01d 100644 --- a/drivers/net/wireless/brcm80211/include/brcmu_utils.h +++ b/drivers/net/wireless/brcm80211/include/brcmu_utils.h | |||
@@ -120,6 +120,10 @@ extern struct sk_buff *brcmu_pktq_penq_head(struct pktq *pq, int prec, | |||
120 | struct sk_buff *p); | 120 | struct sk_buff *p); |
121 | extern struct sk_buff *brcmu_pktq_pdeq(struct pktq *pq, int prec); | 121 | extern struct sk_buff *brcmu_pktq_pdeq(struct pktq *pq, int prec); |
122 | extern struct sk_buff *brcmu_pktq_pdeq_tail(struct pktq *pq, int prec); | 122 | extern struct sk_buff *brcmu_pktq_pdeq_tail(struct pktq *pq, int prec); |
123 | extern struct sk_buff *brcmu_pktq_pdeq_match(struct pktq *pq, int prec, | ||
124 | bool (*match_fn)(struct sk_buff *p, | ||
125 | void *arg), | ||
126 | void *arg); | ||
123 | 127 | ||
124 | /* packet primitives */ | 128 | /* packet primitives */ |
125 | extern struct sk_buff *brcmu_pkt_buf_get_skb(uint len); | 129 | extern struct sk_buff *brcmu_pkt_buf_get_skb(uint len); |
@@ -173,6 +177,29 @@ extern void brcmu_pktq_flush(struct pktq *pq, bool dir, | |||
173 | /* ip address */ | 177 | /* ip address */ |
174 | struct ipv4_addr; | 178 | struct ipv4_addr; |
175 | 179 | ||
180 | /* | ||
181 | * bitfield macros using masking and shift | ||
182 | * | ||
183 | * remark: the mask parameter should be a shifted mask. | ||
184 | */ | ||
185 | static inline void brcmu_maskset32(u32 *var, u32 mask, u8 shift, u32 value) | ||
186 | { | ||
187 | value = (value << shift) & mask; | ||
188 | *var = (*var & ~mask) | value; | ||
189 | } | ||
190 | static inline u32 brcmu_maskget32(u32 var, u32 mask, u8 shift) | ||
191 | { | ||
192 | return (var & mask) >> shift; | ||
193 | } | ||
194 | static inline void brcmu_maskset16(u16 *var, u16 mask, u8 shift, u16 value) | ||
195 | { | ||
196 | value = (value << shift) & mask; | ||
197 | *var = (*var & ~mask) | value; | ||
198 | } | ||
199 | static inline u16 brcmu_maskget16(u16 var, u16 mask, u8 shift) | ||
200 | { | ||
201 | return (var & mask) >> shift; | ||
202 | } | ||
176 | 203 | ||
177 | /* externs */ | 204 | /* externs */ |
178 | /* format/print */ | 205 | /* format/print */ |
diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c index 3630a41df50d..df5a57c74808 100644 --- a/drivers/net/wireless/iwlegacy/3945-mac.c +++ b/drivers/net/wireless/iwlegacy/3945-mac.c | |||
@@ -3475,7 +3475,7 @@ static struct attribute_group il3945_attribute_group = { | |||
3475 | .attrs = il3945_sysfs_entries, | 3475 | .attrs = il3945_sysfs_entries, |
3476 | }; | 3476 | }; |
3477 | 3477 | ||
3478 | struct ieee80211_ops il3945_mac_ops = { | 3478 | static struct ieee80211_ops il3945_mac_ops __read_mostly = { |
3479 | .tx = il3945_mac_tx, | 3479 | .tx = il3945_mac_tx, |
3480 | .start = il3945_mac_start, | 3480 | .start = il3945_mac_start, |
3481 | .stop = il3945_mac_stop, | 3481 | .stop = il3945_mac_stop, |
diff --git a/drivers/net/wireless/iwlegacy/3945.h b/drivers/net/wireless/iwlegacy/3945.h index 1d45075e0d5b..9a8703def0ba 100644 --- a/drivers/net/wireless/iwlegacy/3945.h +++ b/drivers/net/wireless/iwlegacy/3945.h | |||
@@ -150,10 +150,6 @@ struct il3945_frame { | |||
150 | struct list_head list; | 150 | struct list_head list; |
151 | }; | 151 | }; |
152 | 152 | ||
153 | #define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4) | ||
154 | #define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ) | ||
155 | #define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4) | ||
156 | |||
157 | #define SUP_RATE_11A_MAX_NUM_CHANNELS 8 | 153 | #define SUP_RATE_11A_MAX_NUM_CHANNELS 8 |
158 | #define SUP_RATE_11B_MAX_NUM_CHANNELS 4 | 154 | #define SUP_RATE_11B_MAX_NUM_CHANNELS 4 |
159 | #define SUP_RATE_11G_MAX_NUM_CHANNELS 12 | 155 | #define SUP_RATE_11G_MAX_NUM_CHANNELS 12 |
diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index 238f52874f16..6affa7e8f017 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c | |||
@@ -612,7 +612,7 @@ il4965_pass_packet_to_mac80211(struct il_priv *il, struct ieee80211_hdr *hdr, | |||
612 | 612 | ||
613 | /* Called for N_RX (legacy ABG frames), or | 613 | /* Called for N_RX (legacy ABG frames), or |
614 | * N_RX_MPDU (HT high-throughput N frames). */ | 614 | * N_RX_MPDU (HT high-throughput N frames). */ |
615 | void | 615 | static void |
616 | il4965_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb) | 616 | il4965_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb) |
617 | { | 617 | { |
618 | struct ieee80211_hdr *header; | 618 | struct ieee80211_hdr *header; |
@@ -744,7 +744,7 @@ il4965_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb) | |||
744 | 744 | ||
745 | /* Cache phy data (Rx signal strength, etc) for HT frame (N_RX_PHY). | 745 | /* Cache phy data (Rx signal strength, etc) for HT frame (N_RX_PHY). |
746 | * This will be used later in il_hdl_rx() for N_RX_MPDU. */ | 746 | * This will be used later in il_hdl_rx() for N_RX_MPDU. */ |
747 | void | 747 | static void |
748 | il4965_hdl_rx_phy(struct il_priv *il, struct il_rx_buf *rxb) | 748 | il4965_hdl_rx_phy(struct il_priv *il, struct il_rx_buf *rxb) |
749 | { | 749 | { |
750 | struct il_rx_pkt *pkt = rxb_addr(rxb); | 750 | struct il_rx_pkt *pkt = rxb_addr(rxb); |
@@ -1250,7 +1250,7 @@ il4965_dump_fh(struct il_priv *il, char **buf, bool display) | |||
1250 | return 0; | 1250 | return 0; |
1251 | } | 1251 | } |
1252 | 1252 | ||
1253 | void | 1253 | static void |
1254 | il4965_hdl_missed_beacon(struct il_priv *il, struct il_rx_buf *rxb) | 1254 | il4965_hdl_missed_beacon(struct il_priv *il, struct il_rx_buf *rxb) |
1255 | { | 1255 | { |
1256 | struct il_rx_pkt *pkt = rxb_addr(rxb); | 1256 | struct il_rx_pkt *pkt = rxb_addr(rxb); |
@@ -1357,7 +1357,7 @@ il4965_accumulative_stats(struct il_priv *il, __le32 * stats) | |||
1357 | } | 1357 | } |
1358 | #endif | 1358 | #endif |
1359 | 1359 | ||
1360 | void | 1360 | static void |
1361 | il4965_hdl_stats(struct il_priv *il, struct il_rx_buf *rxb) | 1361 | il4965_hdl_stats(struct il_priv *il, struct il_rx_buf *rxb) |
1362 | { | 1362 | { |
1363 | const int recalib_seconds = 60; | 1363 | const int recalib_seconds = 60; |
@@ -1399,7 +1399,7 @@ il4965_hdl_stats(struct il_priv *il, struct il_rx_buf *rxb) | |||
1399 | il4965_temperature_calib(il); | 1399 | il4965_temperature_calib(il); |
1400 | } | 1400 | } |
1401 | 1401 | ||
1402 | void | 1402 | static void |
1403 | il4965_hdl_c_stats(struct il_priv *il, struct il_rx_buf *rxb) | 1403 | il4965_hdl_c_stats(struct il_priv *il, struct il_rx_buf *rxb) |
1404 | { | 1404 | { |
1405 | struct il_rx_pkt *pkt = rxb_addr(rxb); | 1405 | struct il_rx_pkt *pkt = rxb_addr(rxb); |
@@ -2050,7 +2050,7 @@ il4965_txq_ctx_reset(struct il_priv *il) | |||
2050 | il_tx_queue_reset(il, txq_id); | 2050 | il_tx_queue_reset(il, txq_id); |
2051 | } | 2051 | } |
2052 | 2052 | ||
2053 | void | 2053 | static void |
2054 | il4965_txq_ctx_unmap(struct il_priv *il) | 2054 | il4965_txq_ctx_unmap(struct il_priv *il) |
2055 | { | 2055 | { |
2056 | int txq_id; | 2056 | int txq_id; |
@@ -2258,7 +2258,7 @@ il4965_tx_agg_start(struct il_priv *il, struct ieee80211_vif *vif, | |||
2258 | 2258 | ||
2259 | spin_lock_irqsave(&il->sta_lock, flags); | 2259 | spin_lock_irqsave(&il->sta_lock, flags); |
2260 | tid_data = &il->stations[sta_id].tid[tid]; | 2260 | tid_data = &il->stations[sta_id].tid[tid]; |
2261 | *ssn = SEQ_TO_SN(tid_data->seq_number); | 2261 | *ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number); |
2262 | tid_data->agg.txq_id = txq_id; | 2262 | tid_data->agg.txq_id = txq_id; |
2263 | il_set_swq_id(&il->txq[txq_id], il4965_get_ac_from_tid(tid), txq_id); | 2263 | il_set_swq_id(&il->txq[txq_id], il4965_get_ac_from_tid(tid), txq_id); |
2264 | spin_unlock_irqrestore(&il->sta_lock, flags); | 2264 | 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) | |||
2408 | /* aggregated HW queue */ | 2408 | /* aggregated HW queue */ |
2409 | if (txq_id == tid_data->agg.txq_id && | 2409 | if (txq_id == tid_data->agg.txq_id && |
2410 | q->read_ptr == q->write_ptr) { | 2410 | q->read_ptr == q->write_ptr) { |
2411 | u16 ssn = SEQ_TO_SN(tid_data->seq_number); | 2411 | u16 ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number); |
2412 | int tx_fifo = il4965_get_fifo_from_tid(tid); | 2412 | int tx_fifo = il4965_get_fifo_from_tid(tid); |
2413 | D_HT("HW queue empty: continue DELBA flow\n"); | 2413 | D_HT("HW queue empty: continue DELBA flow\n"); |
2414 | il4965_txq_agg_disable(il, txq_id, ssn, tx_fifo); | 2414 | il4965_txq_agg_disable(il, txq_id, ssn, tx_fifo); |
@@ -2627,7 +2627,8 @@ il4965_get_ra_sta_id(struct il_priv *il, struct ieee80211_hdr *hdr) | |||
2627 | static inline u32 | 2627 | static inline u32 |
2628 | il4965_get_scd_ssn(struct il4965_tx_resp *tx_resp) | 2628 | il4965_get_scd_ssn(struct il4965_tx_resp *tx_resp) |
2629 | { | 2629 | { |
2630 | return le32_to_cpup(&tx_resp->u.status + tx_resp->frame_count) & MAX_SN; | 2630 | return le32_to_cpup(&tx_resp->u.status + |
2631 | tx_resp->frame_count) & IEEE80211_MAX_SN; | ||
2631 | } | 2632 | } |
2632 | 2633 | ||
2633 | static inline u32 | 2634 | static inline u32 |
@@ -2717,15 +2718,15 @@ il4965_tx_status_reply_tx(struct il_priv *il, struct il_ht_agg *agg, | |||
2717 | hdr = (struct ieee80211_hdr *) skb->data; | 2718 | hdr = (struct ieee80211_hdr *) skb->data; |
2718 | 2719 | ||
2719 | sc = le16_to_cpu(hdr->seq_ctrl); | 2720 | sc = le16_to_cpu(hdr->seq_ctrl); |
2720 | if (idx != (SEQ_TO_SN(sc) & 0xff)) { | 2721 | if (idx != (IEEE80211_SEQ_TO_SN(sc) & 0xff)) { |
2721 | IL_ERR("BUG_ON idx doesn't match seq control" | 2722 | IL_ERR("BUG_ON idx doesn't match seq control" |
2722 | " idx=%d, seq_idx=%d, seq=%d\n", idx, | 2723 | " idx=%d, seq_idx=%d, seq=%d\n", idx, |
2723 | SEQ_TO_SN(sc), hdr->seq_ctrl); | 2724 | IEEE80211_SEQ_TO_SN(sc), hdr->seq_ctrl); |
2724 | return -1; | 2725 | return -1; |
2725 | } | 2726 | } |
2726 | 2727 | ||
2727 | D_TX_REPLY("AGG Frame i=%d idx %d seq=%d\n", i, idx, | 2728 | D_TX_REPLY("AGG Frame i=%d idx %d seq=%d\n", i, idx, |
2728 | SEQ_TO_SN(sc)); | 2729 | IEEE80211_SEQ_TO_SN(sc)); |
2729 | 2730 | ||
2730 | sh = idx - start; | 2731 | sh = idx - start; |
2731 | if (sh > 64) { | 2732 | if (sh > 64) { |
@@ -2895,7 +2896,7 @@ il4965_hwrate_to_tx_control(struct il_priv *il, u32 rate_n_flags, | |||
2895 | * Handles block-acknowledge notification from device, which reports success | 2896 | * Handles block-acknowledge notification from device, which reports success |
2896 | * of frames sent via aggregation. | 2897 | * of frames sent via aggregation. |
2897 | */ | 2898 | */ |
2898 | void | 2899 | static void |
2899 | il4965_hdl_compressed_ba(struct il_priv *il, struct il_rx_buf *rxb) | 2900 | il4965_hdl_compressed_ba(struct il_priv *il, struct il_rx_buf *rxb) |
2900 | { | 2901 | { |
2901 | struct il_rx_pkt *pkt = rxb_addr(rxb); | 2902 | struct il_rx_pkt *pkt = rxb_addr(rxb); |
@@ -6316,7 +6317,7 @@ il4965_tx_queue_set_status(struct il_priv *il, struct il_tx_queue *txq, | |||
6316 | scd_retry ? "BA" : "AC", txq_id, tx_fifo_id); | 6317 | scd_retry ? "BA" : "AC", txq_id, tx_fifo_id); |
6317 | } | 6318 | } |
6318 | 6319 | ||
6319 | const struct ieee80211_ops il4965_mac_ops = { | 6320 | static const struct ieee80211_ops il4965_mac_ops = { |
6320 | .tx = il4965_mac_tx, | 6321 | .tx = il4965_mac_tx, |
6321 | .start = il4965_mac_start, | 6322 | .start = il4965_mac_start, |
6322 | .stop = il4965_mac_stop, | 6323 | .stop = il4965_mac_stop, |
diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index db2187124032..01e2d2b4ec59 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c | |||
@@ -1122,7 +1122,7 @@ il_set_power(struct il_priv *il, struct il_powertable_cmd *cmd) | |||
1122 | sizeof(struct il_powertable_cmd), cmd); | 1122 | sizeof(struct il_powertable_cmd), cmd); |
1123 | } | 1123 | } |
1124 | 1124 | ||
1125 | int | 1125 | static int |
1126 | il_power_set_mode(struct il_priv *il, struct il_powertable_cmd *cmd, bool force) | 1126 | il_power_set_mode(struct il_priv *il, struct il_powertable_cmd *cmd, bool force) |
1127 | { | 1127 | { |
1128 | int ret; | 1128 | int ret; |
diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h index 458e699c63cd..10986aaf9085 100644 --- a/drivers/net/wireless/iwlegacy/common.h +++ b/drivers/net/wireless/iwlegacy/common.h | |||
@@ -541,10 +541,6 @@ struct il_frame { | |||
541 | struct list_head list; | 541 | struct list_head list; |
542 | }; | 542 | }; |
543 | 543 | ||
544 | #define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4) | ||
545 | #define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ) | ||
546 | #define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4) | ||
547 | |||
548 | enum { | 544 | enum { |
549 | CMD_SYNC = 0, | 545 | CMD_SYNC = 0, |
550 | CMD_SIZE_NORMAL = 0, | 546 | CMD_SIZE_NORMAL = 0, |
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index ba319cba3f1e..56c2040a955b 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig | |||
@@ -6,7 +6,6 @@ config IWLWIFI | |||
6 | select LEDS_CLASS | 6 | select LEDS_CLASS |
7 | select LEDS_TRIGGERS | 7 | select LEDS_TRIGGERS |
8 | select MAC80211_LEDS | 8 | select MAC80211_LEDS |
9 | select IWLDVM | ||
10 | ---help--- | 9 | ---help--- |
11 | Select to build the driver supporting the: | 10 | Select to build the driver supporting the: |
12 | 11 | ||
@@ -45,6 +44,7 @@ config IWLWIFI | |||
45 | config IWLDVM | 44 | config IWLDVM |
46 | tristate "Intel Wireless WiFi DVM Firmware support" | 45 | tristate "Intel Wireless WiFi DVM Firmware support" |
47 | depends on IWLWIFI | 46 | depends on IWLWIFI |
47 | default IWLWIFI | ||
48 | help | 48 | help |
49 | This is the driver supporting the DVM firmware which is | 49 | This is the driver supporting the DVM firmware which is |
50 | currently the only firmware available for existing devices. | 50 | currently the only firmware available for existing devices. |
@@ -58,6 +58,15 @@ config IWLMVM | |||
58 | 58 | ||
59 | Say yes if you have such a device. | 59 | Say yes if you have such a device. |
60 | 60 | ||
61 | # don't call it _MODULE -- will confuse Kconfig/fixdep/... | ||
62 | config IWLWIFI_OPMODE_MODULAR | ||
63 | bool | ||
64 | default y if IWLDVM=m | ||
65 | default y if IWLMVM=m | ||
66 | |||
67 | comment "WARNING: iwlwifi is useless without IWLDVM or IWLMVM" | ||
68 | depends on IWLWIFI && IWLDVM=n && IWLMVM=n | ||
69 | |||
61 | menu "Debugging Options" | 70 | menu "Debugging Options" |
62 | depends on IWLWIFI | 71 | depends on IWLWIFI |
63 | 72 | ||
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 6c7800044a04..3b5613ea458b 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile | |||
@@ -7,8 +7,7 @@ iwlwifi-objs += iwl-notif-wait.o | |||
7 | iwlwifi-objs += iwl-eeprom-read.o iwl-eeprom-parse.o | 7 | iwlwifi-objs += iwl-eeprom-read.o iwl-eeprom-parse.o |
8 | iwlwifi-objs += iwl-phy-db.o iwl-nvm-parse.o | 8 | iwlwifi-objs += iwl-phy-db.o iwl-nvm-parse.o |
9 | iwlwifi-objs += pcie/drv.o pcie/rx.o pcie/tx.o pcie/trans.o | 9 | iwlwifi-objs += pcie/drv.o pcie/rx.o pcie/tx.o pcie/trans.o |
10 | iwlwifi-objs += pcie/1000.o pcie/2000.o pcie/5000.o pcie/6000.o | 10 | iwlwifi-objs += iwl-1000.o iwl-2000.o iwl-5000.o iwl-6000.o iwl-7000.o |
11 | iwlwifi-objs += pcie/7000.o | ||
12 | 11 | ||
13 | iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o | 12 | iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o |
14 | iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TESTMODE) += iwl-test.o | 13 | iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TESTMODE) += iwl-test.o |
diff --git a/drivers/net/wireless/iwlwifi/dvm/agn.h b/drivers/net/wireless/iwlwifi/dvm/agn.h index 41ec27cb6efe..019d433900ef 100644 --- a/drivers/net/wireless/iwlwifi/dvm/agn.h +++ b/drivers/net/wireless/iwlwifi/dvm/agn.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/dvm/calib.c b/drivers/net/wireless/iwlwifi/dvm/calib.c index 6468de8634b0..d6c4cf2ad7c5 100644 --- a/drivers/net/wireless/iwlwifi/dvm/calib.c +++ b/drivers/net/wireless/iwlwifi/dvm/calib.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/dvm/calib.h b/drivers/net/wireless/iwlwifi/dvm/calib.h index 65e920cab2b7..cfddde194940 100644 --- a/drivers/net/wireless/iwlwifi/dvm/calib.h +++ b/drivers/net/wireless/iwlwifi/dvm/calib.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/dvm/commands.h b/drivers/net/wireless/iwlwifi/dvm/commands.h index 84e2c0fcfef6..95ca026ecc9d 100644 --- a/drivers/net/wireless/iwlwifi/dvm/commands.h +++ b/drivers/net/wireless/iwlwifi/dvm/commands.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -1526,6 +1526,7 @@ struct iwl_compressed_ba_resp { | |||
1526 | __le16 scd_ssn; | 1526 | __le16 scd_ssn; |
1527 | u8 txed; /* number of frames sent */ | 1527 | u8 txed; /* number of frames sent */ |
1528 | u8 txed_2_done; /* number of frames acked */ | 1528 | u8 txed_2_done; /* number of frames acked */ |
1529 | __le16 reserved1; | ||
1529 | } __packed; | 1530 | } __packed; |
1530 | 1531 | ||
1531 | /* | 1532 | /* |
diff --git a/drivers/net/wireless/iwlwifi/dvm/debugfs.c b/drivers/net/wireless/iwlwifi/dvm/debugfs.c index 20806cae11b7..7b8178be119f 100644 --- a/drivers/net/wireless/iwlwifi/dvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/dvm/debugfs.c | |||
@@ -19,7 +19,7 @@ | |||
19 | * USA | 19 | * USA |
20 | * | 20 | * |
21 | * The full GNU General Public License is included in this distribution | 21 | * The full GNU General Public License is included in this distribution |
22 | * in the file called LICENSE.GPL. | 22 | * in the file called COPYING. |
23 | * | 23 | * |
24 | * Contact Information: | 24 | * Contact Information: |
25 | * Intel Linux Wireless <ilw@linux.intel.com> | 25 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -2324,6 +2324,28 @@ static ssize_t iwl_dbgfs_calib_disabled_write(struct file *file, | |||
2324 | return count; | 2324 | return count; |
2325 | } | 2325 | } |
2326 | 2326 | ||
2327 | static ssize_t iwl_dbgfs_fw_restart_write(struct file *file, | ||
2328 | const char __user *user_buf, | ||
2329 | size_t count, loff_t *ppos) | ||
2330 | { | ||
2331 | struct iwl_priv *priv = file->private_data; | ||
2332 | bool restart_fw = iwlwifi_mod_params.restart_fw; | ||
2333 | int ret; | ||
2334 | |||
2335 | iwlwifi_mod_params.restart_fw = true; | ||
2336 | |||
2337 | mutex_lock(&priv->mutex); | ||
2338 | |||
2339 | /* take the return value to make compiler happy - it will fail anyway */ | ||
2340 | ret = iwl_dvm_send_cmd_pdu(priv, REPLY_ERROR, CMD_SYNC, 0, NULL); | ||
2341 | |||
2342 | mutex_unlock(&priv->mutex); | ||
2343 | |||
2344 | iwlwifi_mod_params.restart_fw = restart_fw; | ||
2345 | |||
2346 | return count; | ||
2347 | } | ||
2348 | |||
2327 | DEBUGFS_READ_FILE_OPS(ucode_rx_stats); | 2349 | DEBUGFS_READ_FILE_OPS(ucode_rx_stats); |
2328 | DEBUGFS_READ_FILE_OPS(ucode_tx_stats); | 2350 | DEBUGFS_READ_FILE_OPS(ucode_tx_stats); |
2329 | DEBUGFS_READ_FILE_OPS(ucode_general_stats); | 2351 | DEBUGFS_READ_FILE_OPS(ucode_general_stats); |
@@ -2343,6 +2365,7 @@ DEBUGFS_READ_FILE_OPS(bt_traffic); | |||
2343 | DEBUGFS_READ_WRITE_FILE_OPS(protection_mode); | 2365 | DEBUGFS_READ_WRITE_FILE_OPS(protection_mode); |
2344 | DEBUGFS_READ_FILE_OPS(reply_tx_error); | 2366 | DEBUGFS_READ_FILE_OPS(reply_tx_error); |
2345 | DEBUGFS_WRITE_FILE_OPS(echo_test); | 2367 | DEBUGFS_WRITE_FILE_OPS(echo_test); |
2368 | DEBUGFS_WRITE_FILE_OPS(fw_restart); | ||
2346 | #ifdef CONFIG_IWLWIFI_DEBUG | 2369 | #ifdef CONFIG_IWLWIFI_DEBUG |
2347 | DEBUGFS_READ_WRITE_FILE_OPS(log_event); | 2370 | DEBUGFS_READ_WRITE_FILE_OPS(log_event); |
2348 | #endif | 2371 | #endif |
@@ -2400,6 +2423,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, struct dentry *dbgfs_dir) | |||
2400 | DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR); | 2423 | DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR); |
2401 | DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR); | 2424 | DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR); |
2402 | DEBUGFS_ADD_FILE(echo_test, dir_debug, S_IWUSR); | 2425 | DEBUGFS_ADD_FILE(echo_test, dir_debug, S_IWUSR); |
2426 | DEBUGFS_ADD_FILE(fw_restart, dir_debug, S_IWUSR); | ||
2403 | #ifdef CONFIG_IWLWIFI_DEBUG | 2427 | #ifdef CONFIG_IWLWIFI_DEBUG |
2404 | DEBUGFS_ADD_FILE(log_event, dir_debug, S_IWUSR | S_IRUSR); | 2428 | DEBUGFS_ADD_FILE(log_event, dir_debug, S_IWUSR | S_IRUSR); |
2405 | #endif | 2429 | #endif |
diff --git a/drivers/net/wireless/iwlwifi/dvm/lib.c b/drivers/net/wireless/iwlwifi/dvm/lib.c index 86ea5f4c3939..cddf77c36b36 100644 --- a/drivers/net/wireless/iwlwifi/dvm/lib.c +++ b/drivers/net/wireless/iwlwifi/dvm/lib.c | |||
@@ -19,7 +19,7 @@ | |||
19 | * USA | 19 | * USA |
20 | * | 20 | * |
21 | * The full GNU General Public License is included in this distribution | 21 | * The full GNU General Public License is included in this distribution |
22 | * in the file called LICENSE.GPL. | 22 | * in the file called COPYING. |
23 | * | 23 | * |
24 | * Contact Information: | 24 | * Contact Information: |
25 | * Intel Linux Wireless <ilw@linux.intel.com> | 25 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c index 323e4a33fcac..c7cd2dffa5cd 100644 --- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c | |||
@@ -1137,7 +1137,8 @@ done: | |||
1137 | static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw, | 1137 | static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw, |
1138 | struct ieee80211_vif *vif, | 1138 | struct ieee80211_vif *vif, |
1139 | struct ieee80211_channel *channel, | 1139 | struct ieee80211_channel *channel, |
1140 | int duration) | 1140 | int duration, |
1141 | enum ieee80211_roc_type type) | ||
1141 | { | 1142 | { |
1142 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 1143 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
1143 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN]; | 1144 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN]; |
diff --git a/drivers/net/wireless/iwlwifi/dvm/scan.c b/drivers/net/wireless/iwlwifi/dvm/scan.c index 3a4aa5239c45..d69b55866714 100644 --- a/drivers/net/wireless/iwlwifi/dvm/scan.c +++ b/drivers/net/wireless/iwlwifi/dvm/scan.c | |||
@@ -19,7 +19,7 @@ | |||
19 | * USA | 19 | * USA |
20 | * | 20 | * |
21 | * The full GNU General Public License is included in this distribution | 21 | * The full GNU General Public License is included in this distribution |
22 | * in the file called LICENSE.GPL. | 22 | * in the file called COPYING. |
23 | * | 23 | * |
24 | * Contact Information: | 24 | * Contact Information: |
25 | * Intel Linux Wireless <ilw@linux.intel.com> | 25 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/dvm/testmode.c b/drivers/net/wireless/iwlwifi/dvm/testmode.c index dc6f965a123a..b89b9d9b9969 100644 --- a/drivers/net/wireless/iwlwifi/dvm/testmode.c +++ b/drivers/net/wireless/iwlwifi/dvm/testmode.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c index 6aec2df3bb27..cc1e0c1a6f48 100644 --- a/drivers/net/wireless/iwlwifi/dvm/tx.c +++ b/drivers/net/wireless/iwlwifi/dvm/tx.c | |||
@@ -19,7 +19,7 @@ | |||
19 | * USA | 19 | * USA |
20 | * | 20 | * |
21 | * The full GNU General Public License is included in this distribution | 21 | * The full GNU General Public License is included in this distribution |
22 | * in the file called LICENSE.GPL. | 22 | * in the file called COPYING. |
23 | * | 23 | * |
24 | * Contact Information: | 24 | * Contact Information: |
25 | * Intel Linux Wireless <ilw@linux.intel.com> | 25 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -418,7 +418,8 @@ int iwlagn_tx_skb(struct iwl_priv *priv, | |||
418 | " Tx flags = 0x%08x, agg.state = %d", | 418 | " Tx flags = 0x%08x, agg.state = %d", |
419 | info->flags, tid_data->agg.state); | 419 | info->flags, tid_data->agg.state); |
420 | IWL_ERR(priv, "sta_id = %d, tid = %d seq_num = %d", | 420 | IWL_ERR(priv, "sta_id = %d, tid = %d seq_num = %d", |
421 | sta_id, tid, SEQ_TO_SN(tid_data->seq_number)); | 421 | sta_id, tid, |
422 | IEEE80211_SEQ_TO_SN(tid_data->seq_number)); | ||
422 | goto drop_unlock_sta; | 423 | goto drop_unlock_sta; |
423 | } | 424 | } |
424 | 425 | ||
@@ -569,7 +570,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, | |||
569 | return 0; | 570 | return 0; |
570 | } | 571 | } |
571 | 572 | ||
572 | tid_data->agg.ssn = SEQ_TO_SN(tid_data->seq_number); | 573 | tid_data->agg.ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number); |
573 | 574 | ||
574 | /* There are still packets for this RA / TID in the HW */ | 575 | /* There are still packets for this RA / TID in the HW */ |
575 | if (!test_bit(txq_id, priv->agg_q_alloc)) { | 576 | if (!test_bit(txq_id, priv->agg_q_alloc)) { |
@@ -651,7 +652,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, | |||
651 | 652 | ||
652 | spin_lock_bh(&priv->sta_lock); | 653 | spin_lock_bh(&priv->sta_lock); |
653 | tid_data = &priv->tid_data[sta_id][tid]; | 654 | tid_data = &priv->tid_data[sta_id][tid]; |
654 | tid_data->agg.ssn = SEQ_TO_SN(tid_data->seq_number); | 655 | tid_data->agg.ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number); |
655 | tid_data->agg.txq_id = txq_id; | 656 | tid_data->agg.txq_id = txq_id; |
656 | 657 | ||
657 | *ssn = tid_data->agg.ssn; | 658 | *ssn = tid_data->agg.ssn; |
@@ -911,7 +912,7 @@ static void iwlagn_count_agg_tx_err_status(struct iwl_priv *priv, u16 status) | |||
911 | static inline u32 iwlagn_get_scd_ssn(struct iwlagn_tx_resp *tx_resp) | 912 | static inline u32 iwlagn_get_scd_ssn(struct iwlagn_tx_resp *tx_resp) |
912 | { | 913 | { |
913 | return le32_to_cpup((__le32 *)&tx_resp->status + | 914 | return le32_to_cpup((__le32 *)&tx_resp->status + |
914 | tx_resp->frame_count) & MAX_SN; | 915 | tx_resp->frame_count) & IEEE80211_MAX_SN; |
915 | } | 916 | } |
916 | 917 | ||
917 | static void iwl_rx_reply_tx_agg(struct iwl_priv *priv, | 918 | static void iwl_rx_reply_tx_agg(struct iwl_priv *priv, |
@@ -1148,7 +1149,7 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, | |||
1148 | 1149 | ||
1149 | if (tx_resp->frame_count == 1) { | 1150 | if (tx_resp->frame_count == 1) { |
1150 | u16 next_reclaimed = le16_to_cpu(tx_resp->seq_ctl); | 1151 | u16 next_reclaimed = le16_to_cpu(tx_resp->seq_ctl); |
1151 | next_reclaimed = SEQ_TO_SN(next_reclaimed + 0x10); | 1152 | next_reclaimed = IEEE80211_SEQ_TO_SN(next_reclaimed + 0x10); |
1152 | 1153 | ||
1153 | if (is_agg) { | 1154 | if (is_agg) { |
1154 | /* If this is an aggregation queue, we can rely on the | 1155 | /* If this is an aggregation queue, we can rely on the |
diff --git a/drivers/net/wireless/iwlwifi/dvm/ucode.c b/drivers/net/wireless/iwlwifi/dvm/ucode.c index 736fe9bb140e..166019afc2d0 100644 --- a/drivers/net/wireless/iwlwifi/dvm/ucode.c +++ b/drivers/net/wireless/iwlwifi/dvm/ucode.c | |||
@@ -19,7 +19,7 @@ | |||
19 | * USA | 19 | * USA |
20 | * | 20 | * |
21 | * The full GNU General Public License is included in this distribution | 21 | * The full GNU General Public License is included in this distribution |
22 | * in the file called LICENSE.GPL. | 22 | * in the file called COPYING. |
23 | * | 23 | * |
24 | * Contact Information: | 24 | * Contact Information: |
25 | * Intel Linux Wireless <ilw@linux.intel.com> | 25 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/pcie/1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index ff3389757281..c080ae3070b2 100644 --- a/drivers/net/wireless/iwlwifi/pcie/1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c | |||
@@ -29,7 +29,6 @@ | |||
29 | #include "iwl-config.h" | 29 | #include "iwl-config.h" |
30 | #include "iwl-csr.h" | 30 | #include "iwl-csr.h" |
31 | #include "iwl-agn-hw.h" | 31 | #include "iwl-agn-hw.h" |
32 | #include "cfg.h" | ||
33 | 32 | ||
34 | /* Highest firmware API version supported */ | 33 | /* Highest firmware API version supported */ |
35 | #define IWL1000_UCODE_API_MAX 5 | 34 | #define IWL1000_UCODE_API_MAX 5 |
diff --git a/drivers/net/wireless/iwlwifi/pcie/2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index e7de33128b16..a6ddd2f9fba0 100644 --- a/drivers/net/wireless/iwlwifi/pcie/2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c | |||
@@ -28,7 +28,6 @@ | |||
28 | #include <linux/stringify.h> | 28 | #include <linux/stringify.h> |
29 | #include "iwl-config.h" | 29 | #include "iwl-config.h" |
30 | #include "iwl-agn-hw.h" | 30 | #include "iwl-agn-hw.h" |
31 | #include "cfg.h" | ||
32 | #include "dvm/commands.h" /* needed for BT for now */ | 31 | #include "dvm/commands.h" /* needed for BT for now */ |
33 | 32 | ||
34 | /* Highest firmware API version supported */ | 33 | /* Highest firmware API version supported */ |
diff --git a/drivers/net/wireless/iwlwifi/pcie/5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 5096f7c96ab6..403f3f224bf6 100644 --- a/drivers/net/wireless/iwlwifi/pcie/5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -29,7 +29,6 @@ | |||
29 | #include "iwl-config.h" | 29 | #include "iwl-config.h" |
30 | #include "iwl-agn-hw.h" | 30 | #include "iwl-agn-hw.h" |
31 | #include "iwl-csr.h" | 31 | #include "iwl-csr.h" |
32 | #include "cfg.h" | ||
33 | 32 | ||
34 | /* Highest firmware API version supported */ | 33 | /* Highest firmware API version supported */ |
35 | #define IWL5000_UCODE_API_MAX 5 | 34 | #define IWL5000_UCODE_API_MAX 5 |
diff --git a/drivers/net/wireless/iwlwifi/pcie/6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 801ff49796dd..b5ab8d1bcac0 100644 --- a/drivers/net/wireless/iwlwifi/pcie/6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c | |||
@@ -28,7 +28,6 @@ | |||
28 | #include <linux/stringify.h> | 28 | #include <linux/stringify.h> |
29 | #include "iwl-config.h" | 29 | #include "iwl-config.h" |
30 | #include "iwl-agn-hw.h" | 30 | #include "iwl-agn-hw.h" |
31 | #include "cfg.h" | ||
32 | #include "dvm/commands.h" /* needed for BT for now */ | 31 | #include "dvm/commands.h" /* needed for BT for now */ |
33 | 32 | ||
34 | /* Highest firmware API version supported */ | 33 | /* Highest firmware API version supported */ |
diff --git a/drivers/net/wireless/iwlwifi/pcie/7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c index 6e35b2b72332..50263e87fe15 100644 --- a/drivers/net/wireless/iwlwifi/pcie/7000.c +++ b/drivers/net/wireless/iwlwifi/iwl-7000.c | |||
@@ -1,34 +1,70 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | * | 2 | * |
3 | * Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved. | 3 | * This file is provided under a dual BSD/GPLv2 license. When using or |
4 | * redistributing this file, you may do so under either license. | ||
4 | * | 5 | * |
5 | * This program is free software; you can redistribute it and/or modify it | 6 | * GPL LICENSE SUMMARY |
6 | * under the terms of version 2 of the GNU General Public License as | 7 | * |
8 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | 12 | * published by the Free Software Foundation. |
8 | * | 13 | * |
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | 14 | * This program is distributed in the hope that it will be useful, but |
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | 15 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | * more details. | 17 | * General Public License for more details. |
13 | * | 18 | * |
14 | * You should have received a copy of the GNU General Public License along with | 19 | * You should have received a copy of the GNU General Public License |
15 | * this program; if not, write to the Free Software Foundation, Inc., | 20 | * along with this program; if not, write to the Free Software |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | 21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, |
22 | * USA | ||
17 | * | 23 | * |
18 | * The full GNU General Public License is included in this distribution in the | 24 | * The full GNU General Public License is included in this distribution |
19 | * file called LICENSE. | 25 | * in the file called COPYING. |
20 | * | 26 | * |
21 | * Contact Information: | 27 | * Contact Information: |
22 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
23 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | 29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 |
24 | * | 30 | * |
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | * | ||
25 | *****************************************************************************/ | 62 | *****************************************************************************/ |
26 | 63 | ||
27 | #include <linux/module.h> | 64 | #include <linux/module.h> |
28 | #include <linux/stringify.h> | 65 | #include <linux/stringify.h> |
29 | #include "iwl-config.h" | 66 | #include "iwl-config.h" |
30 | #include "iwl-agn-hw.h" | 67 | #include "iwl-agn-hw.h" |
31 | #include "cfg.h" | ||
32 | 68 | ||
33 | /* Highest firmware API version supported */ | 69 | /* Highest firmware API version supported */ |
34 | #define IWL7260_UCODE_API_MAX 6 | 70 | #define IWL7260_UCODE_API_MAX 6 |
@@ -70,7 +106,6 @@ static const struct iwl_base_params iwl7000_base_params = { | |||
70 | }; | 106 | }; |
71 | 107 | ||
72 | static const struct iwl_ht_params iwl7000_ht_params = { | 108 | static const struct iwl_ht_params iwl7000_ht_params = { |
73 | .ht_greenfield_support = true, | ||
74 | .use_rts_for_aggregation = true, /* use rts/cts protection */ | 109 | .use_rts_for_aggregation = true, /* use rts/cts protection */ |
75 | .ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ), | 110 | .ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ), |
76 | }; | 111 | }; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hw.h b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h index e9975c54c276..6d73f943cefa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h index 743b48343358..c38aa8f77554 100644 --- a/drivers/net/wireless/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/iwlwifi/iwl-config.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -275,4 +275,51 @@ struct iwl_cfg { | |||
275 | const bool temp_offset_v2; | 275 | const bool temp_offset_v2; |
276 | }; | 276 | }; |
277 | 277 | ||
278 | /* | ||
279 | * This list declares the config structures for all devices. | ||
280 | */ | ||
281 | extern const struct iwl_cfg iwl5300_agn_cfg; | ||
282 | extern const struct iwl_cfg iwl5100_agn_cfg; | ||
283 | extern const struct iwl_cfg iwl5350_agn_cfg; | ||
284 | extern const struct iwl_cfg iwl5100_bgn_cfg; | ||
285 | extern const struct iwl_cfg iwl5100_abg_cfg; | ||
286 | extern const struct iwl_cfg iwl5150_agn_cfg; | ||
287 | extern const struct iwl_cfg iwl5150_abg_cfg; | ||
288 | extern const struct iwl_cfg iwl6005_2agn_cfg; | ||
289 | extern const struct iwl_cfg iwl6005_2abg_cfg; | ||
290 | extern const struct iwl_cfg iwl6005_2bg_cfg; | ||
291 | extern const struct iwl_cfg iwl6005_2agn_sff_cfg; | ||
292 | extern const struct iwl_cfg iwl6005_2agn_d_cfg; | ||
293 | extern const struct iwl_cfg iwl6005_2agn_mow1_cfg; | ||
294 | extern const struct iwl_cfg iwl6005_2agn_mow2_cfg; | ||
295 | extern const struct iwl_cfg iwl1030_bgn_cfg; | ||
296 | extern const struct iwl_cfg iwl1030_bg_cfg; | ||
297 | extern const struct iwl_cfg iwl6030_2agn_cfg; | ||
298 | extern const struct iwl_cfg iwl6030_2abg_cfg; | ||
299 | extern const struct iwl_cfg iwl6030_2bgn_cfg; | ||
300 | extern const struct iwl_cfg iwl6030_2bg_cfg; | ||
301 | extern const struct iwl_cfg iwl6000i_2agn_cfg; | ||
302 | extern const struct iwl_cfg iwl6000i_2abg_cfg; | ||
303 | extern const struct iwl_cfg iwl6000i_2bg_cfg; | ||
304 | extern const struct iwl_cfg iwl6000_3agn_cfg; | ||
305 | extern const struct iwl_cfg iwl6050_2agn_cfg; | ||
306 | extern const struct iwl_cfg iwl6050_2abg_cfg; | ||
307 | extern const struct iwl_cfg iwl6150_bgn_cfg; | ||
308 | extern const struct iwl_cfg iwl6150_bg_cfg; | ||
309 | extern const struct iwl_cfg iwl1000_bgn_cfg; | ||
310 | extern const struct iwl_cfg iwl1000_bg_cfg; | ||
311 | extern const struct iwl_cfg iwl100_bgn_cfg; | ||
312 | extern const struct iwl_cfg iwl100_bg_cfg; | ||
313 | extern const struct iwl_cfg iwl130_bgn_cfg; | ||
314 | extern const struct iwl_cfg iwl130_bg_cfg; | ||
315 | extern const struct iwl_cfg iwl2000_2bgn_cfg; | ||
316 | extern const struct iwl_cfg iwl2000_2bgn_d_cfg; | ||
317 | extern const struct iwl_cfg iwl2030_2bgn_cfg; | ||
318 | extern const struct iwl_cfg iwl6035_2agn_cfg; | ||
319 | extern const struct iwl_cfg iwl105_bgn_cfg; | ||
320 | extern const struct iwl_cfg iwl105_bgn_d_cfg; | ||
321 | extern const struct iwl_cfg iwl135_bgn_cfg; | ||
322 | extern const struct iwl_cfg iwl7260_2ac_cfg; | ||
323 | extern const struct iwl_cfg iwl3160_ac_cfg; | ||
324 | |||
278 | #endif /* __IWL_CONFIG_H__ */ | 325 | #endif /* __IWL_CONFIG_H__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index df3463a38704..20e845d4da04 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.c b/drivers/net/wireless/iwlwifi/iwl-debug.c index 87535a67de76..8a44f594528d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.c +++ b/drivers/net/wireless/iwlwifi/iwl-debug.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -66,6 +66,7 @@ | |||
66 | #include <linux/device.h> | 66 | #include <linux/device.h> |
67 | #include <linux/interrupt.h> | 67 | #include <linux/interrupt.h> |
68 | #include <linux/export.h> | 68 | #include <linux/export.h> |
69 | #include "iwl-drv.h" | ||
69 | #include "iwl-debug.h" | 70 | #include "iwl-debug.h" |
70 | #include "iwl-devtrace.h" | 71 | #include "iwl-devtrace.h" |
71 | 72 | ||
@@ -85,11 +86,11 @@ void __iwl_ ##fn(struct device *dev, const char *fmt, ...) \ | |||
85 | } | 86 | } |
86 | 87 | ||
87 | __iwl_fn(warn) | 88 | __iwl_fn(warn) |
88 | EXPORT_SYMBOL_GPL(__iwl_warn); | 89 | IWL_EXPORT_SYMBOL(__iwl_warn); |
89 | __iwl_fn(info) | 90 | __iwl_fn(info) |
90 | EXPORT_SYMBOL_GPL(__iwl_info); | 91 | IWL_EXPORT_SYMBOL(__iwl_info); |
91 | __iwl_fn(crit) | 92 | __iwl_fn(crit) |
92 | EXPORT_SYMBOL_GPL(__iwl_crit); | 93 | IWL_EXPORT_SYMBOL(__iwl_crit); |
93 | 94 | ||
94 | void __iwl_err(struct device *dev, bool rfkill_prefix, bool trace_only, | 95 | void __iwl_err(struct device *dev, bool rfkill_prefix, bool trace_only, |
95 | const char *fmt, ...) | 96 | const char *fmt, ...) |
@@ -110,7 +111,7 @@ void __iwl_err(struct device *dev, bool rfkill_prefix, bool trace_only, | |||
110 | trace_iwlwifi_err(&vaf); | 111 | trace_iwlwifi_err(&vaf); |
111 | va_end(args); | 112 | va_end(args); |
112 | } | 113 | } |
113 | EXPORT_SYMBOL_GPL(__iwl_err); | 114 | IWL_EXPORT_SYMBOL(__iwl_err); |
114 | 115 | ||
115 | #if defined(CONFIG_IWLWIFI_DEBUG) || defined(CONFIG_IWLWIFI_DEVICE_TRACING) | 116 | #if defined(CONFIG_IWLWIFI_DEBUG) || defined(CONFIG_IWLWIFI_DEVICE_TRACING) |
116 | void __iwl_dbg(struct device *dev, | 117 | void __iwl_dbg(struct device *dev, |
@@ -133,5 +134,5 @@ void __iwl_dbg(struct device *dev, | |||
133 | trace_iwlwifi_dbg(level, in_interrupt(), function, &vaf); | 134 | trace_iwlwifi_dbg(level, in_interrupt(), function, &vaf); |
134 | va_end(args); | 135 | va_end(args); |
135 | } | 136 | } |
136 | EXPORT_SYMBOL_GPL(__iwl_dbg); | 137 | IWL_EXPORT_SYMBOL(__iwl_dbg); |
137 | #endif | 138 | #endif |
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h index 81aa91fab5aa..4491c1c72cc7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.h +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.h | |||
@@ -298,7 +298,7 @@ TRACE_EVENT(iwlwifi_dbg, | |||
298 | MAX_MSG_LEN, vaf->fmt, | 298 | MAX_MSG_LEN, vaf->fmt, |
299 | *vaf->va) >= MAX_MSG_LEN); | 299 | *vaf->va) >= MAX_MSG_LEN); |
300 | ), | 300 | ), |
301 | TP_printk("%s", (char *)__get_dynamic_array(msg)) | 301 | TP_printk("%s", __get_str(msg)) |
302 | ); | 302 | ); |
303 | 303 | ||
304 | #undef TRACE_SYSTEM | 304 | #undef TRACE_SYSTEM |
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index fbfd2d137117..3ce4e9d5082d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -1102,7 +1102,7 @@ void iwl_drv_stop(struct iwl_drv *drv) | |||
1102 | 1102 | ||
1103 | /* shared module parameters */ | 1103 | /* shared module parameters */ |
1104 | struct iwl_mod_params iwlwifi_mod_params = { | 1104 | struct iwl_mod_params iwlwifi_mod_params = { |
1105 | .restart_fw = 1, | 1105 | .restart_fw = true, |
1106 | .plcp_check = true, | 1106 | .plcp_check = true, |
1107 | .bt_coex_active = true, | 1107 | .bt_coex_active = true, |
1108 | .power_level = IWL_POWER_INDEX_1, | 1108 | .power_level = IWL_POWER_INDEX_1, |
@@ -1111,7 +1111,7 @@ struct iwl_mod_params iwlwifi_mod_params = { | |||
1111 | .wd_disable = true, | 1111 | .wd_disable = true, |
1112 | /* the rest are 0 by default */ | 1112 | /* the rest are 0 by default */ |
1113 | }; | 1113 | }; |
1114 | EXPORT_SYMBOL_GPL(iwlwifi_mod_params); | 1114 | IWL_EXPORT_SYMBOL(iwlwifi_mod_params); |
1115 | 1115 | ||
1116 | int iwl_opmode_register(const char *name, const struct iwl_op_mode_ops *ops) | 1116 | int iwl_opmode_register(const char *name, const struct iwl_op_mode_ops *ops) |
1117 | { | 1117 | { |
@@ -1135,7 +1135,7 @@ int iwl_opmode_register(const char *name, const struct iwl_op_mode_ops *ops) | |||
1135 | mutex_unlock(&iwlwifi_opmode_table_mtx); | 1135 | mutex_unlock(&iwlwifi_opmode_table_mtx); |
1136 | return -EIO; | 1136 | return -EIO; |
1137 | } | 1137 | } |
1138 | EXPORT_SYMBOL_GPL(iwl_opmode_register); | 1138 | IWL_EXPORT_SYMBOL(iwl_opmode_register); |
1139 | 1139 | ||
1140 | void iwl_opmode_deregister(const char *name) | 1140 | void iwl_opmode_deregister(const char *name) |
1141 | { | 1141 | { |
@@ -1157,7 +1157,7 @@ void iwl_opmode_deregister(const char *name) | |||
1157 | } | 1157 | } |
1158 | mutex_unlock(&iwlwifi_opmode_table_mtx); | 1158 | mutex_unlock(&iwlwifi_opmode_table_mtx); |
1159 | } | 1159 | } |
1160 | EXPORT_SYMBOL_GPL(iwl_opmode_deregister); | 1160 | IWL_EXPORT_SYMBOL(iwl_opmode_deregister); |
1161 | 1161 | ||
1162 | static int __init iwl_drv_init(void) | 1162 | static int __init iwl_drv_init(void) |
1163 | { | 1163 | { |
@@ -1207,8 +1207,8 @@ MODULE_PARM_DESC(11n_disable, | |||
1207 | module_param_named(amsdu_size_8K, iwlwifi_mod_params.amsdu_size_8K, | 1207 | module_param_named(amsdu_size_8K, iwlwifi_mod_params.amsdu_size_8K, |
1208 | int, S_IRUGO); | 1208 | int, S_IRUGO); |
1209 | MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size (default 0)"); | 1209 | MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size (default 0)"); |
1210 | module_param_named(fw_restart, iwlwifi_mod_params.restart_fw, int, S_IRUGO); | 1210 | module_param_named(fw_restart, iwlwifi_mod_params.restart_fw, bool, S_IRUGO); |
1211 | MODULE_PARM_DESC(fw_restart, "restart firmware in case of error"); | 1211 | MODULE_PARM_DESC(fw_restart, "restart firmware in case of error (default true)"); |
1212 | 1212 | ||
1213 | module_param_named(antenna_coupling, iwlwifi_mod_params.ant_coupling, | 1213 | module_param_named(antenna_coupling, iwlwifi_mod_params.ant_coupling, |
1214 | int, S_IRUGO); | 1214 | int, S_IRUGO); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.h b/drivers/net/wireless/iwlwifi/iwl-drv.h index 594a5c71b272..7d1450916308 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.h +++ b/drivers/net/wireless/iwlwifi/iwl-drv.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -63,6 +63,8 @@ | |||
63 | #ifndef __iwl_drv_h__ | 63 | #ifndef __iwl_drv_h__ |
64 | #define __iwl_drv_h__ | 64 | #define __iwl_drv_h__ |
65 | 65 | ||
66 | #include <linux/module.h> | ||
67 | |||
66 | /* for all modules */ | 68 | /* for all modules */ |
67 | #define DRV_NAME "iwlwifi" | 69 | #define DRV_NAME "iwlwifi" |
68 | #define IWLWIFI_VERSION "in-tree:" | 70 | #define IWLWIFI_VERSION "in-tree:" |
@@ -123,4 +125,17 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans, | |||
123 | */ | 125 | */ |
124 | void iwl_drv_stop(struct iwl_drv *drv); | 126 | void iwl_drv_stop(struct iwl_drv *drv); |
125 | 127 | ||
128 | /* | ||
129 | * exported symbol management | ||
130 | * | ||
131 | * The driver can be split into multiple modules, in which case some symbols | ||
132 | * must be exported for the sub-modules. However, if it's not split and | ||
133 | * everything is built-in, then we can avoid that. | ||
134 | */ | ||
135 | #ifdef CONFIG_IWLWIFI_OPMODE_MODULAR | ||
136 | #define IWL_EXPORT_SYMBOL(sym) EXPORT_SYMBOL_GPL(sym) | ||
137 | #else | ||
138 | #define IWL_EXPORT_SYMBOL(sym) | ||
139 | #endif | ||
140 | |||
126 | #endif /* __iwl_drv_h__ */ | 141 | #endif /* __iwl_drv_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c index 034f2ff4f43d..600c9fdd7f71 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -62,6 +62,7 @@ | |||
62 | #include <linux/types.h> | 62 | #include <linux/types.h> |
63 | #include <linux/slab.h> | 63 | #include <linux/slab.h> |
64 | #include <linux/export.h> | 64 | #include <linux/export.h> |
65 | #include "iwl-drv.h" | ||
65 | #include "iwl-modparams.h" | 66 | #include "iwl-modparams.h" |
66 | #include "iwl-eeprom-parse.h" | 67 | #include "iwl-eeprom-parse.h" |
67 | 68 | ||
@@ -749,7 +750,7 @@ void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg, | |||
749 | } | 750 | } |
750 | 751 | ||
751 | ht_info->ht_supported = true; | 752 | ht_info->ht_supported = true; |
752 | ht_info->cap = 0; | 753 | ht_info->cap = IEEE80211_HT_CAP_DSSSCCK40; |
753 | 754 | ||
754 | if (iwlwifi_mod_params.amsdu_size_8K) | 755 | if (iwlwifi_mod_params.amsdu_size_8K) |
755 | ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU; | 756 | ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU; |
@@ -909,7 +910,7 @@ iwl_parse_eeprom_data(struct device *dev, const struct iwl_cfg *cfg, | |||
909 | kfree(data); | 910 | kfree(data); |
910 | return NULL; | 911 | return NULL; |
911 | } | 912 | } |
912 | EXPORT_SYMBOL_GPL(iwl_parse_eeprom_data); | 913 | IWL_EXPORT_SYMBOL(iwl_parse_eeprom_data); |
913 | 914 | ||
914 | /* helper functions */ | 915 | /* helper functions */ |
915 | int iwl_nvm_check_version(struct iwl_nvm_data *data, | 916 | int iwl_nvm_check_version(struct iwl_nvm_data *data, |
@@ -928,4 +929,4 @@ int iwl_nvm_check_version(struct iwl_nvm_data *data, | |||
928 | data->calib_version, trans->cfg->nvm_calib_ver); | 929 | data->calib_version, trans->cfg->nvm_calib_ver); |
929 | return -EINVAL; | 930 | return -EINVAL; |
930 | } | 931 | } |
931 | EXPORT_SYMBOL_GPL(iwl_nvm_check_version); | 932 | IWL_EXPORT_SYMBOL(iwl_nvm_check_version); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h index 683fe6a8c58f..37f115390b19 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-read.c b/drivers/net/wireless/iwlwifi/iwl-eeprom-read.c index ef4806f27cf8..e5f2e362ab0b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom-read.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-read.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -63,6 +63,7 @@ | |||
63 | #include <linux/slab.h> | 63 | #include <linux/slab.h> |
64 | #include <linux/export.h> | 64 | #include <linux/export.h> |
65 | 65 | ||
66 | #include "iwl-drv.h" | ||
66 | #include "iwl-debug.h" | 67 | #include "iwl-debug.h" |
67 | #include "iwl-eeprom-read.h" | 68 | #include "iwl-eeprom-read.h" |
68 | #include "iwl-io.h" | 69 | #include "iwl-io.h" |
@@ -460,4 +461,4 @@ int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size) | |||
460 | 461 | ||
461 | return ret; | 462 | return ret; |
462 | } | 463 | } |
463 | EXPORT_SYMBOL_GPL(iwl_read_eeprom); | 464 | IWL_EXPORT_SYMBOL(iwl_read_eeprom); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-read.h b/drivers/net/wireless/iwlwifi/iwl-eeprom-read.h index b2588c5cbf93..8e941f8bd7d6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom-read.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-read.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h index f5592fb3b1ed..484d318245fb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fh.h +++ b/drivers/net/wireless/iwlwifi/iwl-fh.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/iwlwifi/iwl-fw-file.h index 90873eca35f7..8b6c6fd95ed0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw-file.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h index b545178e46e3..435618574240 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -73,12 +73,14 @@ | |||
73 | * treats good CRC threshold as a boolean | 73 | * treats good CRC threshold as a boolean |
74 | * @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w). | 74 | * @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w). |
75 | * @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P. | 75 | * @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P. |
76 | * @IWL_UCODE_TLV_FLAGS_DW_BC_TABLE: The SCD byte count table is in DWORDS | ||
76 | */ | 77 | */ |
77 | enum iwl_ucode_tlv_flag { | 78 | enum iwl_ucode_tlv_flag { |
78 | IWL_UCODE_TLV_FLAGS_PAN = BIT(0), | 79 | IWL_UCODE_TLV_FLAGS_PAN = BIT(0), |
79 | IWL_UCODE_TLV_FLAGS_NEWSCAN = BIT(1), | 80 | IWL_UCODE_TLV_FLAGS_NEWSCAN = BIT(1), |
80 | IWL_UCODE_TLV_FLAGS_MFP = BIT(2), | 81 | IWL_UCODE_TLV_FLAGS_MFP = BIT(2), |
81 | IWL_UCODE_TLV_FLAGS_P2P = BIT(3), | 82 | IWL_UCODE_TLV_FLAGS_P2P = BIT(3), |
83 | IWL_UCODE_TLV_FLAGS_DW_BC_TABLE = BIT(4), | ||
82 | }; | 84 | }; |
83 | 85 | ||
84 | /* The default calibrate table size if not specified by firmware file */ | 86 | /* The default calibrate table size if not specified by firmware file */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c index 276410d82de4..305c81f2c2b4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/iwlwifi/iwl-io.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/device.h> | 29 | #include <linux/device.h> |
30 | #include <linux/export.h> | 30 | #include <linux/export.h> |
31 | 31 | ||
32 | #include "iwl-drv.h" | ||
32 | #include "iwl-io.h" | 33 | #include "iwl-io.h" |
33 | #include "iwl-csr.h" | 34 | #include "iwl-csr.h" |
34 | #include "iwl-debug.h" | 35 | #include "iwl-debug.h" |
@@ -49,7 +50,7 @@ int iwl_poll_bit(struct iwl_trans *trans, u32 addr, | |||
49 | 50 | ||
50 | return -ETIMEDOUT; | 51 | return -ETIMEDOUT; |
51 | } | 52 | } |
52 | EXPORT_SYMBOL_GPL(iwl_poll_bit); | 53 | IWL_EXPORT_SYMBOL(iwl_poll_bit); |
53 | 54 | ||
54 | u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg) | 55 | u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg) |
55 | { | 56 | { |
@@ -62,7 +63,7 @@ u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg) | |||
62 | 63 | ||
63 | return value; | 64 | return value; |
64 | } | 65 | } |
65 | EXPORT_SYMBOL_GPL(iwl_read_direct32); | 66 | IWL_EXPORT_SYMBOL(iwl_read_direct32); |
66 | 67 | ||
67 | void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value) | 68 | void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value) |
68 | { | 69 | { |
@@ -73,7 +74,7 @@ void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value) | |||
73 | iwl_trans_release_nic_access(trans, &flags); | 74 | iwl_trans_release_nic_access(trans, &flags); |
74 | } | 75 | } |
75 | } | 76 | } |
76 | EXPORT_SYMBOL_GPL(iwl_write_direct32); | 77 | IWL_EXPORT_SYMBOL(iwl_write_direct32); |
77 | 78 | ||
78 | int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask, | 79 | int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask, |
79 | int timeout) | 80 | int timeout) |
@@ -89,7 +90,7 @@ int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask, | |||
89 | 90 | ||
90 | return -ETIMEDOUT; | 91 | return -ETIMEDOUT; |
91 | } | 92 | } |
92 | EXPORT_SYMBOL_GPL(iwl_poll_direct_bit); | 93 | IWL_EXPORT_SYMBOL(iwl_poll_direct_bit); |
93 | 94 | ||
94 | static inline u32 __iwl_read_prph(struct iwl_trans *trans, u32 ofs) | 95 | static inline u32 __iwl_read_prph(struct iwl_trans *trans, u32 ofs) |
95 | { | 96 | { |
@@ -115,7 +116,7 @@ u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs) | |||
115 | } | 116 | } |
116 | return val; | 117 | return val; |
117 | } | 118 | } |
118 | EXPORT_SYMBOL_GPL(iwl_read_prph); | 119 | IWL_EXPORT_SYMBOL(iwl_read_prph); |
119 | 120 | ||
120 | void iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val) | 121 | void iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val) |
121 | { | 122 | { |
@@ -126,7 +127,7 @@ void iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val) | |||
126 | iwl_trans_release_nic_access(trans, &flags); | 127 | iwl_trans_release_nic_access(trans, &flags); |
127 | } | 128 | } |
128 | } | 129 | } |
129 | EXPORT_SYMBOL_GPL(iwl_write_prph); | 130 | IWL_EXPORT_SYMBOL(iwl_write_prph); |
130 | 131 | ||
131 | void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask) | 132 | void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask) |
132 | { | 133 | { |
@@ -138,7 +139,7 @@ void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask) | |||
138 | iwl_trans_release_nic_access(trans, &flags); | 139 | iwl_trans_release_nic_access(trans, &flags); |
139 | } | 140 | } |
140 | } | 141 | } |
141 | EXPORT_SYMBOL_GPL(iwl_set_bits_prph); | 142 | IWL_EXPORT_SYMBOL(iwl_set_bits_prph); |
142 | 143 | ||
143 | void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs, | 144 | void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs, |
144 | u32 bits, u32 mask) | 145 | u32 bits, u32 mask) |
@@ -151,7 +152,7 @@ void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs, | |||
151 | iwl_trans_release_nic_access(trans, &flags); | 152 | iwl_trans_release_nic_access(trans, &flags); |
152 | } | 153 | } |
153 | } | 154 | } |
154 | EXPORT_SYMBOL_GPL(iwl_set_bits_mask_prph); | 155 | IWL_EXPORT_SYMBOL(iwl_set_bits_mask_prph); |
155 | 156 | ||
156 | void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask) | 157 | void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask) |
157 | { | 158 | { |
@@ -164,4 +165,4 @@ void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask) | |||
164 | iwl_trans_release_nic_access(trans, &flags); | 165 | iwl_trans_release_nic_access(trans, &flags); |
165 | } | 166 | } |
166 | } | 167 | } |
167 | EXPORT_SYMBOL_GPL(iwl_clear_bits_prph); | 168 | IWL_EXPORT_SYMBOL(iwl_clear_bits_prph); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-modparams.h b/drivers/net/wireless/iwlwifi/iwl-modparams.h index 2c2a729092f5..3cc39ffe8ba5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-modparams.h +++ b/drivers/net/wireless/iwlwifi/iwl-modparams.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -109,7 +109,7 @@ struct iwl_mod_params { | |||
109 | int sw_crypto; | 109 | int sw_crypto; |
110 | unsigned int disable_11n; | 110 | unsigned int disable_11n; |
111 | int amsdu_size_8K; | 111 | int amsdu_size_8K; |
112 | int restart_fw; | 112 | bool restart_fw; |
113 | bool plcp_check; | 113 | bool plcp_check; |
114 | int wd_disable; | 114 | int wd_disable; |
115 | bool bt_coex_active; | 115 | bool bt_coex_active; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-notif-wait.c b/drivers/net/wireless/iwlwifi/iwl-notif-wait.c index c3affbc62cdf..940b8a9d5285 100644 --- a/drivers/net/wireless/iwlwifi/iwl-notif-wait.c +++ b/drivers/net/wireless/iwlwifi/iwl-notif-wait.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -63,6 +63,7 @@ | |||
63 | #include <linux/sched.h> | 63 | #include <linux/sched.h> |
64 | #include <linux/export.h> | 64 | #include <linux/export.h> |
65 | 65 | ||
66 | #include "iwl-drv.h" | ||
66 | #include "iwl-notif-wait.h" | 67 | #include "iwl-notif-wait.h" |
67 | 68 | ||
68 | 69 | ||
@@ -72,7 +73,7 @@ void iwl_notification_wait_init(struct iwl_notif_wait_data *notif_wait) | |||
72 | INIT_LIST_HEAD(¬if_wait->notif_waits); | 73 | INIT_LIST_HEAD(¬if_wait->notif_waits); |
73 | init_waitqueue_head(¬if_wait->notif_waitq); | 74 | init_waitqueue_head(¬if_wait->notif_waitq); |
74 | } | 75 | } |
75 | EXPORT_SYMBOL_GPL(iwl_notification_wait_init); | 76 | IWL_EXPORT_SYMBOL(iwl_notification_wait_init); |
76 | 77 | ||
77 | void iwl_notification_wait_notify(struct iwl_notif_wait_data *notif_wait, | 78 | void iwl_notification_wait_notify(struct iwl_notif_wait_data *notif_wait, |
78 | struct iwl_rx_packet *pkt) | 79 | struct iwl_rx_packet *pkt) |
@@ -117,7 +118,7 @@ void iwl_notification_wait_notify(struct iwl_notif_wait_data *notif_wait, | |||
117 | if (triggered) | 118 | if (triggered) |
118 | wake_up_all(¬if_wait->notif_waitq); | 119 | wake_up_all(¬if_wait->notif_waitq); |
119 | } | 120 | } |
120 | EXPORT_SYMBOL_GPL(iwl_notification_wait_notify); | 121 | IWL_EXPORT_SYMBOL(iwl_notification_wait_notify); |
121 | 122 | ||
122 | void iwl_abort_notification_waits(struct iwl_notif_wait_data *notif_wait) | 123 | void iwl_abort_notification_waits(struct iwl_notif_wait_data *notif_wait) |
123 | { | 124 | { |
@@ -130,7 +131,7 @@ void iwl_abort_notification_waits(struct iwl_notif_wait_data *notif_wait) | |||
130 | 131 | ||
131 | wake_up_all(¬if_wait->notif_waitq); | 132 | wake_up_all(¬if_wait->notif_waitq); |
132 | } | 133 | } |
133 | EXPORT_SYMBOL_GPL(iwl_abort_notification_waits); | 134 | IWL_EXPORT_SYMBOL(iwl_abort_notification_waits); |
134 | 135 | ||
135 | void | 136 | void |
136 | iwl_init_notification_wait(struct iwl_notif_wait_data *notif_wait, | 137 | iwl_init_notification_wait(struct iwl_notif_wait_data *notif_wait, |
@@ -154,7 +155,7 @@ iwl_init_notification_wait(struct iwl_notif_wait_data *notif_wait, | |||
154 | list_add(&wait_entry->list, ¬if_wait->notif_waits); | 155 | list_add(&wait_entry->list, ¬if_wait->notif_waits); |
155 | spin_unlock_bh(¬if_wait->notif_wait_lock); | 156 | spin_unlock_bh(¬if_wait->notif_wait_lock); |
156 | } | 157 | } |
157 | EXPORT_SYMBOL_GPL(iwl_init_notification_wait); | 158 | IWL_EXPORT_SYMBOL(iwl_init_notification_wait); |
158 | 159 | ||
159 | int iwl_wait_notification(struct iwl_notif_wait_data *notif_wait, | 160 | int iwl_wait_notification(struct iwl_notif_wait_data *notif_wait, |
160 | struct iwl_notification_wait *wait_entry, | 161 | struct iwl_notification_wait *wait_entry, |
@@ -178,7 +179,7 @@ int iwl_wait_notification(struct iwl_notif_wait_data *notif_wait, | |||
178 | return -ETIMEDOUT; | 179 | return -ETIMEDOUT; |
179 | return 0; | 180 | return 0; |
180 | } | 181 | } |
181 | EXPORT_SYMBOL_GPL(iwl_wait_notification); | 182 | IWL_EXPORT_SYMBOL(iwl_wait_notification); |
182 | 183 | ||
183 | void iwl_remove_notification(struct iwl_notif_wait_data *notif_wait, | 184 | void iwl_remove_notification(struct iwl_notif_wait_data *notif_wait, |
184 | struct iwl_notification_wait *wait_entry) | 185 | struct iwl_notification_wait *wait_entry) |
@@ -187,4 +188,4 @@ void iwl_remove_notification(struct iwl_notif_wait_data *notif_wait, | |||
187 | list_del(&wait_entry->list); | 188 | list_del(&wait_entry->list); |
188 | spin_unlock_bh(¬if_wait->notif_wait_lock); | 189 | spin_unlock_bh(¬if_wait->notif_wait_lock); |
189 | } | 190 | } |
190 | EXPORT_SYMBOL_GPL(iwl_remove_notification); | 191 | IWL_EXPORT_SYMBOL(iwl_remove_notification); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-notif-wait.h b/drivers/net/wireless/iwlwifi/iwl-notif-wait.h index c2ce764463a3..2e2f1c8c99f9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-notif-wait.h +++ b/drivers/net/wireless/iwlwifi/iwl-notif-wait.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c index a70213bdb83c..6199a0a597a6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -62,6 +62,7 @@ | |||
62 | #include <linux/types.h> | 62 | #include <linux/types.h> |
63 | #include <linux/slab.h> | 63 | #include <linux/slab.h> |
64 | #include <linux/export.h> | 64 | #include <linux/export.h> |
65 | #include "iwl-drv.h" | ||
65 | #include "iwl-modparams.h" | 66 | #include "iwl-modparams.h" |
66 | #include "iwl-nvm-parse.h" | 67 | #include "iwl-nvm-parse.h" |
67 | 68 | ||
@@ -149,6 +150,8 @@ static struct ieee80211_rate iwl_cfg80211_rates[] = { | |||
149 | * @NVM_CHANNEL_DFS: dynamic freq selection candidate | 150 | * @NVM_CHANNEL_DFS: dynamic freq selection candidate |
150 | * @NVM_CHANNEL_WIDE: 20 MHz channel okay (?) | 151 | * @NVM_CHANNEL_WIDE: 20 MHz channel okay (?) |
151 | * @NVM_CHANNEL_40MHZ: 40 MHz channel okay (?) | 152 | * @NVM_CHANNEL_40MHZ: 40 MHz channel okay (?) |
153 | * @NVM_CHANNEL_80MHZ: 80 MHz channel okay (?) | ||
154 | * @NVM_CHANNEL_160MHZ: 160 MHz channel okay (?) | ||
152 | */ | 155 | */ |
153 | enum iwl_nvm_channel_flags { | 156 | enum iwl_nvm_channel_flags { |
154 | NVM_CHANNEL_VALID = BIT(0), | 157 | NVM_CHANNEL_VALID = BIT(0), |
@@ -158,6 +161,8 @@ enum iwl_nvm_channel_flags { | |||
158 | NVM_CHANNEL_DFS = BIT(7), | 161 | NVM_CHANNEL_DFS = BIT(7), |
159 | NVM_CHANNEL_WIDE = BIT(8), | 162 | NVM_CHANNEL_WIDE = BIT(8), |
160 | NVM_CHANNEL_40MHZ = BIT(9), | 163 | NVM_CHANNEL_40MHZ = BIT(9), |
164 | NVM_CHANNEL_80MHZ = BIT(10), | ||
165 | NVM_CHANNEL_160MHZ = BIT(11), | ||
161 | }; | 166 | }; |
162 | 167 | ||
163 | #define CHECK_AND_PRINT_I(x) \ | 168 | #define CHECK_AND_PRINT_I(x) \ |
@@ -210,6 +215,10 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, | |||
210 | else | 215 | else |
211 | channel->flags &= ~IEEE80211_CHAN_NO_HT40MINUS; | 216 | channel->flags &= ~IEEE80211_CHAN_NO_HT40MINUS; |
212 | } | 217 | } |
218 | if (!(ch_flags & NVM_CHANNEL_80MHZ)) | ||
219 | channel->flags |= IEEE80211_CHAN_NO_80MHZ; | ||
220 | if (!(ch_flags & NVM_CHANNEL_160MHZ)) | ||
221 | channel->flags |= IEEE80211_CHAN_NO_160MHZ; | ||
213 | 222 | ||
214 | if (!(ch_flags & NVM_CHANNEL_IBSS)) | 223 | if (!(ch_flags & NVM_CHANNEL_IBSS)) |
215 | channel->flags |= IEEE80211_CHAN_NO_IBSS; | 224 | channel->flags |= IEEE80211_CHAN_NO_IBSS; |
@@ -245,6 +254,43 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, | |||
245 | return n_channels; | 254 | return n_channels; |
246 | } | 255 | } |
247 | 256 | ||
257 | static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg, | ||
258 | struct iwl_nvm_data *data, | ||
259 | struct ieee80211_sta_vht_cap *vht_cap) | ||
260 | { | ||
261 | /* For now, assume new devices with NVM are VHT capable */ | ||
262 | |||
263 | vht_cap->vht_supported = true; | ||
264 | |||
265 | vht_cap->cap = IEEE80211_VHT_CAP_SHORT_GI_80 | | ||
266 | IEEE80211_VHT_CAP_RXSTBC_1 | | ||
267 | IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | | ||
268 | 7 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT; | ||
269 | |||
270 | if (iwlwifi_mod_params.amsdu_size_8K) | ||
271 | vht_cap->cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991; | ||
272 | |||
273 | vht_cap->vht_mcs.rx_mcs_map = | ||
274 | cpu_to_le16(IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 | | ||
275 | IEEE80211_VHT_MCS_SUPPORT_0_9 << 2 | | ||
276 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 | | ||
277 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 | | ||
278 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 | | ||
279 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 | | ||
280 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 | | ||
281 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 14); | ||
282 | |||
283 | if (data->valid_rx_ant == 1 || cfg->rx_with_siso_diversity) { | ||
284 | vht_cap->cap |= IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN | | ||
285 | IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN; | ||
286 | /* this works because NOT_SUPPORTED == 3 */ | ||
287 | vht_cap->vht_mcs.rx_mcs_map |= | ||
288 | cpu_to_le16(IEEE80211_VHT_MCS_NOT_SUPPORTED << 2); | ||
289 | } | ||
290 | |||
291 | vht_cap->vht_mcs.tx_mcs_map = vht_cap->vht_mcs.rx_mcs_map; | ||
292 | } | ||
293 | |||
248 | static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, | 294 | static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, |
249 | struct iwl_nvm_data *data, const __le16 *nvm_sw) | 295 | struct iwl_nvm_data *data, const __le16 *nvm_sw) |
250 | { | 296 | { |
@@ -268,6 +314,7 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, | |||
268 | n_used += iwl_init_sband_channels(data, sband, n_channels, | 314 | n_used += iwl_init_sband_channels(data, sband, n_channels, |
269 | IEEE80211_BAND_5GHZ); | 315 | IEEE80211_BAND_5GHZ); |
270 | iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_5GHZ); | 316 | iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_5GHZ); |
317 | iwl_init_vht_hw_capab(cfg, data, &sband->vht_cap); | ||
271 | 318 | ||
272 | if (n_channels != n_used) | 319 | if (n_channels != n_used) |
273 | IWL_ERR_DEV(dev, "NVM: used only %d of %d channels\n", | 320 | IWL_ERR_DEV(dev, "NVM: used only %d of %d channels\n", |
@@ -343,4 +390,4 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, | |||
343 | 390 | ||
344 | return data; | 391 | return data; |
345 | } | 392 | } |
346 | EXPORT_SYMBOL_GPL(iwl_parse_nvm_data); | 393 | IWL_EXPORT_SYMBOL(iwl_parse_nvm_data); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h index b2692bd287fa..e57fb989661e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h +++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/iwl-op-mode.h b/drivers/net/wireless/iwlwifi/iwl-op-mode.h index 4a680019e117..98c7aa7346da 100644 --- a/drivers/net/wireless/iwlwifi/iwl-op-mode.h +++ b/drivers/net/wireless/iwlwifi/iwl-op-mode.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/iwl-phy-db.c b/drivers/net/wireless/iwlwifi/iwl-phy-db.c index 3392011a8768..25745daa0d5d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-phy-db.c +++ b/drivers/net/wireless/iwlwifi/iwl-phy-db.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -65,6 +65,7 @@ | |||
65 | #include <linux/string.h> | 65 | #include <linux/string.h> |
66 | #include <linux/export.h> | 66 | #include <linux/export.h> |
67 | 67 | ||
68 | #include "iwl-drv.h" | ||
68 | #include "iwl-phy-db.h" | 69 | #include "iwl-phy-db.h" |
69 | #include "iwl-debug.h" | 70 | #include "iwl-debug.h" |
70 | #include "iwl-op-mode.h" | 71 | #include "iwl-op-mode.h" |
@@ -149,7 +150,7 @@ struct iwl_phy_db *iwl_phy_db_init(struct iwl_trans *trans) | |||
149 | /* TODO: add default values of the phy db. */ | 150 | /* TODO: add default values of the phy db. */ |
150 | return phy_db; | 151 | return phy_db; |
151 | } | 152 | } |
152 | EXPORT_SYMBOL(iwl_phy_db_init); | 153 | IWL_EXPORT_SYMBOL(iwl_phy_db_init); |
153 | 154 | ||
154 | /* | 155 | /* |
155 | * get phy db section: returns a pointer to a phy db section specified by | 156 | * get phy db section: returns a pointer to a phy db section specified by |
@@ -215,7 +216,7 @@ void iwl_phy_db_free(struct iwl_phy_db *phy_db) | |||
215 | 216 | ||
216 | kfree(phy_db); | 217 | kfree(phy_db); |
217 | } | 218 | } |
218 | EXPORT_SYMBOL(iwl_phy_db_free); | 219 | IWL_EXPORT_SYMBOL(iwl_phy_db_free); |
219 | 220 | ||
220 | int iwl_phy_db_set_section(struct iwl_phy_db *phy_db, struct iwl_rx_packet *pkt, | 221 | int iwl_phy_db_set_section(struct iwl_phy_db *phy_db, struct iwl_rx_packet *pkt, |
221 | gfp_t alloc_ctx) | 222 | gfp_t alloc_ctx) |
@@ -260,7 +261,7 @@ int iwl_phy_db_set_section(struct iwl_phy_db *phy_db, struct iwl_rx_packet *pkt, | |||
260 | 261 | ||
261 | return 0; | 262 | return 0; |
262 | } | 263 | } |
263 | EXPORT_SYMBOL(iwl_phy_db_set_section); | 264 | IWL_EXPORT_SYMBOL(iwl_phy_db_set_section); |
264 | 265 | ||
265 | static int is_valid_channel(u16 ch_id) | 266 | static int is_valid_channel(u16 ch_id) |
266 | { | 267 | { |
@@ -495,4 +496,4 @@ int iwl_send_phy_db_data(struct iwl_phy_db *phy_db) | |||
495 | "Finished sending phy db non channel data\n"); | 496 | "Finished sending phy db non channel data\n"); |
496 | return 0; | 497 | return 0; |
497 | } | 498 | } |
498 | EXPORT_SYMBOL(iwl_send_phy_db_data); | 499 | IWL_EXPORT_SYMBOL(iwl_send_phy_db_data); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-phy-db.h b/drivers/net/wireless/iwlwifi/iwl-phy-db.h index d0e43d96ab38..ce983af79644 100644 --- a/drivers/net/wireless/iwlwifi/iwl-phy-db.h +++ b/drivers/net/wireless/iwlwifi/iwl-phy-db.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index f76e9cad7757..386f2a7c87cb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/iwl-test.c b/drivers/net/wireless/iwlwifi/iwl-test.c index ce0c67b425ee..efff2986b5b4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-test.c +++ b/drivers/net/wireless/iwlwifi/iwl-test.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -64,6 +64,7 @@ | |||
64 | #include <linux/export.h> | 64 | #include <linux/export.h> |
65 | #include <net/netlink.h> | 65 | #include <net/netlink.h> |
66 | 66 | ||
67 | #include "iwl-drv.h" | ||
67 | #include "iwl-io.h" | 68 | #include "iwl-io.h" |
68 | #include "iwl-fh.h" | 69 | #include "iwl-fh.h" |
69 | #include "iwl-prph.h" | 70 | #include "iwl-prph.h" |
@@ -653,7 +654,7 @@ int iwl_test_parse(struct iwl_test *tst, struct nlattr **tb, | |||
653 | } | 654 | } |
654 | return 0; | 655 | return 0; |
655 | } | 656 | } |
656 | EXPORT_SYMBOL_GPL(iwl_test_parse); | 657 | IWL_EXPORT_SYMBOL(iwl_test_parse); |
657 | 658 | ||
658 | /* | 659 | /* |
659 | * Handle test commands. | 660 | * Handle test commands. |
@@ -715,7 +716,7 @@ int iwl_test_handle_cmd(struct iwl_test *tst, struct nlattr **tb) | |||
715 | } | 716 | } |
716 | return result; | 717 | return result; |
717 | } | 718 | } |
718 | EXPORT_SYMBOL_GPL(iwl_test_handle_cmd); | 719 | IWL_EXPORT_SYMBOL(iwl_test_handle_cmd); |
719 | 720 | ||
720 | static int iwl_test_trace_dump(struct iwl_test *tst, struct sk_buff *skb, | 721 | static int iwl_test_trace_dump(struct iwl_test *tst, struct sk_buff *skb, |
721 | struct netlink_callback *cb) | 722 | struct netlink_callback *cb) |
@@ -803,7 +804,7 @@ int iwl_test_dump(struct iwl_test *tst, u32 cmd, struct sk_buff *skb, | |||
803 | } | 804 | } |
804 | return result; | 805 | return result; |
805 | } | 806 | } |
806 | EXPORT_SYMBOL_GPL(iwl_test_dump); | 807 | IWL_EXPORT_SYMBOL(iwl_test_dump); |
807 | 808 | ||
808 | /* | 809 | /* |
809 | * Multicast a spontaneous messages from the device to the user space. | 810 | * Multicast a spontaneous messages from the device to the user space. |
@@ -849,4 +850,4 @@ void iwl_test_rx(struct iwl_test *tst, struct iwl_rx_cmd_buffer *rxb) | |||
849 | if (tst->notify) | 850 | if (tst->notify) |
850 | iwl_test_send_rx(tst, rxb); | 851 | iwl_test_send_rx(tst, rxb); |
851 | } | 852 | } |
852 | EXPORT_SYMBOL_GPL(iwl_test_rx); | 853 | IWL_EXPORT_SYMBOL(iwl_test_rx); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-test.h b/drivers/net/wireless/iwlwifi/iwl-test.h index 7fbf4d717caa..8fbd21704840 100644 --- a/drivers/net/wireless/iwlwifi/iwl-test.h +++ b/drivers/net/wireless/iwlwifi/iwl-test.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.h b/drivers/net/wireless/iwlwifi/iwl-testmode.h index a963f45c6849..98f48a9afc98 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.h +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 0cac2b7af78b..7f9c254292a8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -114,9 +114,6 @@ | |||
114 | * completely agnostic to these differences. | 114 | * completely agnostic to these differences. |
115 | * The transport does provide helper functionnality (i.e. SYNC / ASYNC mode), | 115 | * The transport does provide helper functionnality (i.e. SYNC / ASYNC mode), |
116 | */ | 116 | */ |
117 | #define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4) | ||
118 | #define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ) | ||
119 | #define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4) | ||
120 | #define SEQ_TO_QUEUE(s) (((s) >> 8) & 0x1f) | 117 | #define SEQ_TO_QUEUE(s) (((s) >> 8) & 0x1f) |
121 | #define QUEUE_TO_SEQ(q) (((q) & 0x1f) << 8) | 118 | #define QUEUE_TO_SEQ(q) (((q) & 0x1f) << 8) |
122 | #define SEQ_TO_INDEX(s) ((s) & 0xff) | 119 | #define SEQ_TO_INDEX(s) ((s) & 0xff) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/Makefile b/drivers/net/wireless/iwlwifi/mvm/Makefile index 807b250ec396..2acc44b40986 100644 --- a/drivers/net/wireless/iwlwifi/mvm/Makefile +++ b/drivers/net/wireless/iwlwifi/mvm/Makefile | |||
@@ -2,7 +2,7 @@ obj-$(CONFIG_IWLMVM) += iwlmvm.o | |||
2 | iwlmvm-y += fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o | 2 | iwlmvm-y += fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o |
3 | iwlmvm-y += utils.o rx.o tx.o binding.o quota.o sta.o | 3 | iwlmvm-y += utils.o rx.o tx.o binding.o quota.o sta.o |
4 | iwlmvm-y += scan.o time-event.o rs.o | 4 | iwlmvm-y += scan.o time-event.o rs.o |
5 | iwlmvm-y += power.o | 5 | iwlmvm-y += power.o bt-coex.o |
6 | iwlmvm-y += led.o | 6 | iwlmvm-y += led.o |
7 | iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o | 7 | iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o |
8 | iwlmvm-$(CONFIG_PM_SLEEP) += d3.o | 8 | iwlmvm-$(CONFIG_PM_SLEEP) += d3.o |
diff --git a/drivers/net/wireless/iwlwifi/mvm/binding.c b/drivers/net/wireless/iwlwifi/mvm/binding.c index 73d24aacb90a..93fd1457954b 100644 --- a/drivers/net/wireless/iwlwifi/mvm/binding.c +++ b/drivers/net/wireless/iwlwifi/mvm/binding.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c new file mode 100644 index 000000000000..47954deb6493 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c | |||
@@ -0,0 +1,347 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2013 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called COPYING. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2013 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | * | ||
62 | *****************************************************************************/ | ||
63 | |||
64 | #include "fw-api-bt-coex.h" | ||
65 | #include "iwl-modparams.h" | ||
66 | #include "mvm.h" | ||
67 | #include "iwl-debug.h" | ||
68 | |||
69 | #define EVENT_PRIO_ANT(_evt, _prio, _shrd_ant) \ | ||
70 | [(_evt)] = (((_prio) << BT_COEX_PRIO_TBL_PRIO_POS) | \ | ||
71 | ((_shrd_ant) << BT_COEX_PRIO_TBL_SHRD_ANT_POS)) | ||
72 | |||
73 | static const u8 iwl_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = { | ||
74 | EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_INIT_CALIB1, | ||
75 | BT_COEX_PRIO_TBL_PRIO_BYPASS, 0), | ||
76 | EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_INIT_CALIB2, | ||
77 | BT_COEX_PRIO_TBL_PRIO_BYPASS, 1), | ||
78 | EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_LOW1, | ||
79 | BT_COEX_PRIO_TBL_PRIO_LOW, 0), | ||
80 | EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_LOW2, | ||
81 | BT_COEX_PRIO_TBL_PRIO_LOW, 1), | ||
82 | EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_HIGH1, | ||
83 | BT_COEX_PRIO_TBL_PRIO_HIGH, 0), | ||
84 | EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_HIGH2, | ||
85 | BT_COEX_PRIO_TBL_PRIO_HIGH, 1), | ||
86 | EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_DTIM, | ||
87 | BT_COEX_PRIO_TBL_DISABLED, 0), | ||
88 | EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_SCAN52, | ||
89 | BT_COEX_PRIO_TBL_PRIO_COEX_OFF, 0), | ||
90 | EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_SCAN24, | ||
91 | BT_COEX_PRIO_TBL_PRIO_COEX_ON, 0), | ||
92 | EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_IDLE, | ||
93 | BT_COEX_PRIO_TBL_PRIO_COEX_IDLE, 0), | ||
94 | 0, 0, 0, 0, 0, 0, | ||
95 | }; | ||
96 | |||
97 | #undef EVENT_PRIO_ANT | ||
98 | |||
99 | int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm) | ||
100 | { | ||
101 | return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_PRIO_TABLE, CMD_SYNC, | ||
102 | sizeof(struct iwl_bt_coex_prio_tbl_cmd), | ||
103 | &iwl_bt_prio_tbl); | ||
104 | } | ||
105 | |||
106 | static int iwl_send_bt_env(struct iwl_mvm *mvm, u8 action, u8 type) | ||
107 | { | ||
108 | struct iwl_bt_coex_prot_env_cmd env_cmd; | ||
109 | int ret; | ||
110 | |||
111 | env_cmd.action = action; | ||
112 | env_cmd.type = type; | ||
113 | ret = iwl_mvm_send_cmd_pdu(mvm, BT_COEX_PROT_ENV, CMD_SYNC, | ||
114 | sizeof(env_cmd), &env_cmd); | ||
115 | if (ret) | ||
116 | IWL_ERR(mvm, "failed to send BT env command\n"); | ||
117 | return ret; | ||
118 | } | ||
119 | |||
120 | enum iwl_bt_kill_msk { | ||
121 | BT_KILL_MSK_DEFAULT, | ||
122 | BT_KILL_MSK_SCO_HID_A2DP, | ||
123 | BT_KILL_MSK_REDUCED_TXPOW, | ||
124 | BT_KILL_MSK_MAX, | ||
125 | }; | ||
126 | |||
127 | static const u32 iwl_bt_ack_kill_msk[BT_KILL_MSK_MAX] = { | ||
128 | 0xffffffff, | ||
129 | 0xfffffc00, | ||
130 | 0, | ||
131 | }; | ||
132 | |||
133 | static const u32 iwl_bt_cts_kill_msk[BT_KILL_MSK_MAX] = { | ||
134 | 0xffffffff, | ||
135 | 0xfffffc00, | ||
136 | 0, | ||
137 | }; | ||
138 | |||
139 | #define IWL_BT_DEFAULT_BOOST (0xf0f0f0f0) | ||
140 | |||
141 | /* Tight Coex */ | ||
142 | static const __le32 iwl_tight_lookup[BT_COEX_LUT_SIZE] = { | ||
143 | cpu_to_le32(0xaaaaaaaa), | ||
144 | cpu_to_le32(0xaaaaaaaa), | ||
145 | cpu_to_le32(0xaeaaaaaa), | ||
146 | cpu_to_le32(0xaaaaaaaa), | ||
147 | cpu_to_le32(0xcc00ff28), | ||
148 | cpu_to_le32(0x0000aaaa), | ||
149 | cpu_to_le32(0xcc00aaaa), | ||
150 | cpu_to_le32(0x0000aaaa), | ||
151 | cpu_to_le32(0xc0004000), | ||
152 | cpu_to_le32(0x00000000), | ||
153 | cpu_to_le32(0xf0005000), | ||
154 | cpu_to_le32(0xf0005000), | ||
155 | }; | ||
156 | |||
157 | /* Loose Coex */ | ||
158 | static const __le32 iwl_loose_lookup[BT_COEX_LUT_SIZE] = { | ||
159 | cpu_to_le32(0xaaaaaaaa), | ||
160 | cpu_to_le32(0xaaaaaaaa), | ||
161 | cpu_to_le32(0xaeaaaaaa), | ||
162 | cpu_to_le32(0xaaaaaaaa), | ||
163 | cpu_to_le32(0xcc00ff28), | ||
164 | cpu_to_le32(0x0000aaaa), | ||
165 | cpu_to_le32(0xcc00aaaa), | ||
166 | cpu_to_le32(0x0000aaaa), | ||
167 | cpu_to_le32(0x00000000), | ||
168 | cpu_to_le32(0x00000000), | ||
169 | cpu_to_le32(0xf0005000), | ||
170 | cpu_to_le32(0xf0005000), | ||
171 | }; | ||
172 | |||
173 | /* Full concurrency */ | ||
174 | static const __le32 iwl_concurrent_lookup[BT_COEX_LUT_SIZE] = { | ||
175 | cpu_to_le32(0xaaaaaaaa), | ||
176 | cpu_to_le32(0xaaaaaaaa), | ||
177 | cpu_to_le32(0xaaaaaaaa), | ||
178 | cpu_to_le32(0xaaaaaaaa), | ||
179 | cpu_to_le32(0xaaaaaaaa), | ||
180 | cpu_to_le32(0xaaaaaaaa), | ||
181 | cpu_to_le32(0xaaaaaaaa), | ||
182 | cpu_to_le32(0xaaaaaaaa), | ||
183 | cpu_to_le32(0x00000000), | ||
184 | cpu_to_le32(0x00000000), | ||
185 | cpu_to_le32(0x00000000), | ||
186 | cpu_to_le32(0x00000000), | ||
187 | }; | ||
188 | |||
189 | /* BT Antenna Coupling Threshold (dB) */ | ||
190 | #define IWL_BT_ANTENNA_COUPLING_THRESHOLD (35) | ||
191 | |||
192 | int iwl_send_bt_init_conf(struct iwl_mvm *mvm) | ||
193 | { | ||
194 | struct iwl_bt_coex_cmd cmd = { | ||
195 | .max_kill = 5, | ||
196 | .bt3_time_t7_value = 1, | ||
197 | .bt3_prio_sample_time = 2, | ||
198 | .bt3_timer_t2_value = 0xc, | ||
199 | }; | ||
200 | int ret; | ||
201 | |||
202 | cmd.flags = iwlwifi_mod_params.bt_coex_active ? | ||
203 | BT_COEX_NW : BT_COEX_DISABLE; | ||
204 | cmd.flags |= iwlwifi_mod_params.bt_ch_announce ? | ||
205 | BT_CH_PRIMARY_EN | BT_CH_SECONDARY_EN : 0; | ||
206 | cmd.flags |= BT_SYNC_2_BT_DISABLE; | ||
207 | |||
208 | cmd.valid_bit_msk = cpu_to_le16(BT_VALID_ENABLE | | ||
209 | BT_VALID_BT_PRIO_BOOST | | ||
210 | BT_VALID_MAX_KILL | | ||
211 | BT_VALID_3W_TMRS | | ||
212 | BT_VALID_KILL_ACK | | ||
213 | BT_VALID_KILL_CTS | | ||
214 | BT_VALID_REDUCED_TX_POWER | | ||
215 | BT_VALID_LUT); | ||
216 | |||
217 | if (iwlwifi_mod_params.ant_coupling > IWL_BT_ANTENNA_COUPLING_THRESHOLD) | ||
218 | memcpy(&cmd.decision_lut, iwl_loose_lookup, | ||
219 | sizeof(iwl_tight_lookup)); | ||
220 | else | ||
221 | memcpy(&cmd.decision_lut, iwl_tight_lookup, | ||
222 | sizeof(iwl_tight_lookup)); | ||
223 | |||
224 | cmd.bt_prio_boost = cpu_to_le32(IWL_BT_DEFAULT_BOOST); | ||
225 | cmd.kill_ack_msk = | ||
226 | cpu_to_le32(iwl_bt_ack_kill_msk[BT_KILL_MSK_DEFAULT]); | ||
227 | cmd.kill_cts_msk = | ||
228 | cpu_to_le32(iwl_bt_cts_kill_msk[BT_KILL_MSK_DEFAULT]); | ||
229 | |||
230 | /* go to CALIB state in internal BT-Coex state machine */ | ||
231 | ret = iwl_send_bt_env(mvm, BT_COEX_ENV_OPEN, | ||
232 | BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); | ||
233 | if (ret) | ||
234 | return ret; | ||
235 | |||
236 | ret = iwl_send_bt_env(mvm, BT_COEX_ENV_CLOSE, | ||
237 | BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); | ||
238 | if (ret) | ||
239 | return ret; | ||
240 | |||
241 | return iwl_mvm_send_cmd_pdu(mvm, BT_CONFIG, CMD_SYNC, | ||
242 | sizeof(cmd), &cmd); | ||
243 | } | ||
244 | |||
245 | struct iwl_bt_notif_iterator_data { | ||
246 | struct iwl_mvm *mvm; | ||
247 | struct iwl_bt_coex_profile_notif *notif; | ||
248 | }; | ||
249 | |||
250 | static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, | ||
251 | struct ieee80211_vif *vif) | ||
252 | { | ||
253 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
254 | struct iwl_bt_notif_iterator_data *data = _data; | ||
255 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
256 | enum ieee80211_smps_mode smps_mode; | ||
257 | enum ieee80211_band band; | ||
258 | |||
259 | if (vif->type != NL80211_IFTYPE_STATION) | ||
260 | return; | ||
261 | |||
262 | rcu_read_lock(); | ||
263 | chanctx_conf = rcu_dereference(vif->chanctx_conf); | ||
264 | if (chanctx_conf && chanctx_conf->def.chan) | ||
265 | band = chanctx_conf->def.chan->band; | ||
266 | else | ||
267 | band = -1; | ||
268 | rcu_read_unlock(); | ||
269 | |||
270 | if (band != IEEE80211_BAND_2GHZ) | ||
271 | return; | ||
272 | |||
273 | smps_mode = IEEE80211_SMPS_AUTOMATIC; | ||
274 | |||
275 | if (data->notif->bt_status) | ||
276 | smps_mode = IEEE80211_SMPS_DYNAMIC; | ||
277 | |||
278 | if (data->notif->bt_traffic_load) | ||
279 | smps_mode = IEEE80211_SMPS_STATIC; | ||
280 | |||
281 | IWL_DEBUG_COEX(data->mvm, | ||
282 | "mac %d: bt_status %d traffic_load %d smps_req %d\n", | ||
283 | mvmvif->id, data->notif->bt_status, | ||
284 | data->notif->bt_traffic_load, smps_mode); | ||
285 | |||
286 | ieee80211_request_smps(vif, smps_mode); | ||
287 | } | ||
288 | |||
289 | int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm, | ||
290 | struct iwl_rx_cmd_buffer *rxb, | ||
291 | struct iwl_device_cmd *dev_cmd) | ||
292 | { | ||
293 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
294 | struct iwl_bt_coex_profile_notif *notif = (void *)pkt->data; | ||
295 | struct iwl_bt_notif_iterator_data data = { | ||
296 | .mvm = mvm, | ||
297 | .notif = notif, | ||
298 | }; | ||
299 | struct iwl_bt_coex_cmd cmd = {}; | ||
300 | enum iwl_bt_kill_msk bt_kill_msk; | ||
301 | |||
302 | IWL_DEBUG_COEX(mvm, "BT Coex Notification received\n"); | ||
303 | IWL_DEBUG_COEX(mvm, "\tBT %salive\n", notif->bt_status ? "" : "not "); | ||
304 | IWL_DEBUG_COEX(mvm, "\tBT open conn %d\n", notif->bt_open_conn); | ||
305 | IWL_DEBUG_COEX(mvm, "\tBT traffic load %d\n", notif->bt_traffic_load); | ||
306 | IWL_DEBUG_COEX(mvm, "\tBT agg traffic load %d\n", | ||
307 | notif->bt_agg_traffic_load); | ||
308 | IWL_DEBUG_COEX(mvm, "\tBT ci compliance %d\n", notif->bt_ci_compliance); | ||
309 | |||
310 | /* remember this notification for future use: rssi fluctuations */ | ||
311 | memcpy(&mvm->last_bt_notif, notif, sizeof(mvm->last_bt_notif)); | ||
312 | |||
313 | ieee80211_iterate_active_interfaces_atomic( | ||
314 | mvm->hw, IEEE80211_IFACE_ITER_NORMAL, | ||
315 | iwl_mvm_bt_notif_iterator, &data); | ||
316 | |||
317 | /* Low latency BT profile is active: give higher prio to BT */ | ||
318 | if (BT_MBOX_MSG(notif, 3, SCO_STATE) || | ||
319 | BT_MBOX_MSG(notif, 3, A2DP_STATE) || | ||
320 | BT_MBOX_MSG(notif, 3, SNIFF_STATE)) | ||
321 | bt_kill_msk = BT_KILL_MSK_SCO_HID_A2DP; | ||
322 | else | ||
323 | bt_kill_msk = BT_KILL_MSK_DEFAULT; | ||
324 | |||
325 | /* Don't send HCMD if there is no update */ | ||
326 | if (bt_kill_msk == mvm->bt_kill_msk) | ||
327 | return 0; | ||
328 | |||
329 | IWL_DEBUG_COEX(mvm, | ||
330 | "Udpate kill_msk: %d\n\t SCO %sactive A2DP %sactive SNIFF %sactive\n", | ||
331 | bt_kill_msk, | ||
332 | BT_MBOX_MSG(notif, 3, SCO_STATE) ? "" : "in", | ||
333 | BT_MBOX_MSG(notif, 3, A2DP_STATE) ? "" : "in", | ||
334 | BT_MBOX_MSG(notif, 3, SNIFF_STATE) ? "" : "in"); | ||
335 | |||
336 | mvm->bt_kill_msk = bt_kill_msk; | ||
337 | cmd.kill_ack_msk = cpu_to_le32(iwl_bt_ack_kill_msk[bt_kill_msk]); | ||
338 | cmd.kill_cts_msk = cpu_to_le32(iwl_bt_cts_kill_msk[bt_kill_msk]); | ||
339 | |||
340 | cmd.valid_bit_msk = cpu_to_le16(BT_VALID_KILL_ACK | BT_VALID_KILL_CTS); | ||
341 | |||
342 | if (iwl_mvm_send_cmd_pdu(mvm, BT_CONFIG, CMD_SYNC, sizeof(cmd), &cmd)) | ||
343 | IWL_ERR(mvm, "Failed to sent BT Coex CMD\n"); | ||
344 | |||
345 | /* This handler is ASYNC */ | ||
346 | return 0; | ||
347 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c index 994c8c263dc0..d4578cefe445 100644 --- a/drivers/net/wireless/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/iwlwifi/mvm/d3.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -62,8 +62,10 @@ | |||
62 | *****************************************************************************/ | 62 | *****************************************************************************/ |
63 | 63 | ||
64 | #include <linux/etherdevice.h> | 64 | #include <linux/etherdevice.h> |
65 | #include <linux/ip.h> | ||
65 | #include <net/cfg80211.h> | 66 | #include <net/cfg80211.h> |
66 | #include <net/ipv6.h> | 67 | #include <net/ipv6.h> |
68 | #include <net/tcp.h> | ||
67 | #include "iwl-modparams.h" | 69 | #include "iwl-modparams.h" |
68 | #include "fw-api.h" | 70 | #include "fw-api.h" |
69 | #include "mvm.h" | 71 | #include "mvm.h" |
@@ -402,6 +404,233 @@ static int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm, | |||
402 | sizeof(cmd), &cmd); | 404 | sizeof(cmd), &cmd); |
403 | } | 405 | } |
404 | 406 | ||
407 | enum iwl_mvm_tcp_packet_type { | ||
408 | MVM_TCP_TX_SYN, | ||
409 | MVM_TCP_RX_SYNACK, | ||
410 | MVM_TCP_TX_DATA, | ||
411 | MVM_TCP_RX_ACK, | ||
412 | MVM_TCP_RX_WAKE, | ||
413 | MVM_TCP_TX_FIN, | ||
414 | }; | ||
415 | |||
416 | static __le16 pseudo_hdr_check(int len, __be32 saddr, __be32 daddr) | ||
417 | { | ||
418 | __sum16 check = tcp_v4_check(len, saddr, daddr, 0); | ||
419 | return cpu_to_le16(be16_to_cpu((__force __be16)check)); | ||
420 | } | ||
421 | |||
422 | static void iwl_mvm_build_tcp_packet(struct iwl_mvm *mvm, | ||
423 | struct ieee80211_vif *vif, | ||
424 | struct cfg80211_wowlan_tcp *tcp, | ||
425 | void *_pkt, u8 *mask, | ||
426 | __le16 *pseudo_hdr_csum, | ||
427 | enum iwl_mvm_tcp_packet_type ptype) | ||
428 | { | ||
429 | struct { | ||
430 | struct ethhdr eth; | ||
431 | struct iphdr ip; | ||
432 | struct tcphdr tcp; | ||
433 | u8 data[]; | ||
434 | } __packed *pkt = _pkt; | ||
435 | u16 ip_tot_len = sizeof(struct iphdr) + sizeof(struct tcphdr); | ||
436 | int i; | ||
437 | |||
438 | pkt->eth.h_proto = cpu_to_be16(ETH_P_IP), | ||
439 | pkt->ip.version = 4; | ||
440 | pkt->ip.ihl = 5; | ||
441 | pkt->ip.protocol = IPPROTO_TCP; | ||
442 | |||
443 | switch (ptype) { | ||
444 | case MVM_TCP_TX_SYN: | ||
445 | case MVM_TCP_TX_DATA: | ||
446 | case MVM_TCP_TX_FIN: | ||
447 | memcpy(pkt->eth.h_dest, tcp->dst_mac, ETH_ALEN); | ||
448 | memcpy(pkt->eth.h_source, vif->addr, ETH_ALEN); | ||
449 | pkt->ip.ttl = 128; | ||
450 | pkt->ip.saddr = tcp->src; | ||
451 | pkt->ip.daddr = tcp->dst; | ||
452 | pkt->tcp.source = cpu_to_be16(tcp->src_port); | ||
453 | pkt->tcp.dest = cpu_to_be16(tcp->dst_port); | ||
454 | /* overwritten for TX SYN later */ | ||
455 | pkt->tcp.doff = sizeof(struct tcphdr) / 4; | ||
456 | pkt->tcp.window = cpu_to_be16(65000); | ||
457 | break; | ||
458 | case MVM_TCP_RX_SYNACK: | ||
459 | case MVM_TCP_RX_ACK: | ||
460 | case MVM_TCP_RX_WAKE: | ||
461 | memcpy(pkt->eth.h_dest, vif->addr, ETH_ALEN); | ||
462 | memcpy(pkt->eth.h_source, tcp->dst_mac, ETH_ALEN); | ||
463 | pkt->ip.saddr = tcp->dst; | ||
464 | pkt->ip.daddr = tcp->src; | ||
465 | pkt->tcp.source = cpu_to_be16(tcp->dst_port); | ||
466 | pkt->tcp.dest = cpu_to_be16(tcp->src_port); | ||
467 | break; | ||
468 | default: | ||
469 | WARN_ON(1); | ||
470 | return; | ||
471 | } | ||
472 | |||
473 | switch (ptype) { | ||
474 | case MVM_TCP_TX_SYN: | ||
475 | /* firmware assumes 8 option bytes - 8 NOPs for now */ | ||
476 | memset(pkt->data, 0x01, 8); | ||
477 | ip_tot_len += 8; | ||
478 | pkt->tcp.doff = (sizeof(struct tcphdr) + 8) / 4; | ||
479 | pkt->tcp.syn = 1; | ||
480 | break; | ||
481 | case MVM_TCP_TX_DATA: | ||
482 | ip_tot_len += tcp->payload_len; | ||
483 | memcpy(pkt->data, tcp->payload, tcp->payload_len); | ||
484 | pkt->tcp.psh = 1; | ||
485 | pkt->tcp.ack = 1; | ||
486 | break; | ||
487 | case MVM_TCP_TX_FIN: | ||
488 | pkt->tcp.fin = 1; | ||
489 | pkt->tcp.ack = 1; | ||
490 | break; | ||
491 | case MVM_TCP_RX_SYNACK: | ||
492 | pkt->tcp.syn = 1; | ||
493 | pkt->tcp.ack = 1; | ||
494 | break; | ||
495 | case MVM_TCP_RX_ACK: | ||
496 | pkt->tcp.ack = 1; | ||
497 | break; | ||
498 | case MVM_TCP_RX_WAKE: | ||
499 | ip_tot_len += tcp->wake_len; | ||
500 | pkt->tcp.psh = 1; | ||
501 | pkt->tcp.ack = 1; | ||
502 | memcpy(pkt->data, tcp->wake_data, tcp->wake_len); | ||
503 | break; | ||
504 | } | ||
505 | |||
506 | switch (ptype) { | ||
507 | case MVM_TCP_TX_SYN: | ||
508 | case MVM_TCP_TX_DATA: | ||
509 | case MVM_TCP_TX_FIN: | ||
510 | pkt->ip.tot_len = cpu_to_be16(ip_tot_len); | ||
511 | pkt->ip.check = ip_fast_csum(&pkt->ip, pkt->ip.ihl); | ||
512 | break; | ||
513 | case MVM_TCP_RX_WAKE: | ||
514 | for (i = 0; i < DIV_ROUND_UP(tcp->wake_len, 8); i++) { | ||
515 | u8 tmp = tcp->wake_mask[i]; | ||
516 | mask[i + 6] |= tmp << 6; | ||
517 | if (i + 1 < DIV_ROUND_UP(tcp->wake_len, 8)) | ||
518 | mask[i + 7] = tmp >> 2; | ||
519 | } | ||
520 | /* fall through for ethernet/IP/TCP headers mask */ | ||
521 | case MVM_TCP_RX_SYNACK: | ||
522 | case MVM_TCP_RX_ACK: | ||
523 | mask[0] = 0xff; /* match ethernet */ | ||
524 | /* | ||
525 | * match ethernet, ip.version, ip.ihl | ||
526 | * the ip.ihl half byte is really masked out by firmware | ||
527 | */ | ||
528 | mask[1] = 0x7f; | ||
529 | mask[2] = 0x80; /* match ip.protocol */ | ||
530 | mask[3] = 0xfc; /* match ip.saddr, ip.daddr */ | ||
531 | mask[4] = 0x3f; /* match ip.daddr, tcp.source, tcp.dest */ | ||
532 | mask[5] = 0x80; /* match tcp flags */ | ||
533 | /* leave rest (0 or set for MVM_TCP_RX_WAKE) */ | ||
534 | break; | ||
535 | }; | ||
536 | |||
537 | *pseudo_hdr_csum = pseudo_hdr_check(ip_tot_len - sizeof(struct iphdr), | ||
538 | pkt->ip.saddr, pkt->ip.daddr); | ||
539 | } | ||
540 | |||
541 | static int iwl_mvm_send_remote_wake_cfg(struct iwl_mvm *mvm, | ||
542 | struct ieee80211_vif *vif, | ||
543 | struct cfg80211_wowlan_tcp *tcp) | ||
544 | { | ||
545 | struct iwl_wowlan_remote_wake_config *cfg; | ||
546 | struct iwl_host_cmd cmd = { | ||
547 | .id = REMOTE_WAKE_CONFIG_CMD, | ||
548 | .len = { sizeof(*cfg), }, | ||
549 | .dataflags = { IWL_HCMD_DFL_NOCOPY, }, | ||
550 | .flags = CMD_SYNC, | ||
551 | }; | ||
552 | int ret; | ||
553 | |||
554 | if (!tcp) | ||
555 | return 0; | ||
556 | |||
557 | cfg = kzalloc(sizeof(*cfg), GFP_KERNEL); | ||
558 | if (!cfg) | ||
559 | return -ENOMEM; | ||
560 | cmd.data[0] = cfg; | ||
561 | |||
562 | cfg->max_syn_retries = 10; | ||
563 | cfg->max_data_retries = 10; | ||
564 | cfg->tcp_syn_ack_timeout = 1; /* seconds */ | ||
565 | cfg->tcp_ack_timeout = 1; /* seconds */ | ||
566 | |||
567 | /* SYN (TX) */ | ||
568 | iwl_mvm_build_tcp_packet( | ||
569 | mvm, vif, tcp, cfg->syn_tx.data, NULL, | ||
570 | &cfg->syn_tx.info.tcp_pseudo_header_checksum, | ||
571 | MVM_TCP_TX_SYN); | ||
572 | cfg->syn_tx.info.tcp_payload_length = 0; | ||
573 | |||
574 | /* SYN/ACK (RX) */ | ||
575 | iwl_mvm_build_tcp_packet( | ||
576 | mvm, vif, tcp, cfg->synack_rx.data, cfg->synack_rx.rx_mask, | ||
577 | &cfg->synack_rx.info.tcp_pseudo_header_checksum, | ||
578 | MVM_TCP_RX_SYNACK); | ||
579 | cfg->synack_rx.info.tcp_payload_length = 0; | ||
580 | |||
581 | /* KEEPALIVE/ACK (TX) */ | ||
582 | iwl_mvm_build_tcp_packet( | ||
583 | mvm, vif, tcp, cfg->keepalive_tx.data, NULL, | ||
584 | &cfg->keepalive_tx.info.tcp_pseudo_header_checksum, | ||
585 | MVM_TCP_TX_DATA); | ||
586 | cfg->keepalive_tx.info.tcp_payload_length = | ||
587 | cpu_to_le16(tcp->payload_len); | ||
588 | cfg->sequence_number_offset = tcp->payload_seq.offset; | ||
589 | /* length must be 0..4, the field is little endian */ | ||
590 | cfg->sequence_number_length = tcp->payload_seq.len; | ||
591 | cfg->initial_sequence_number = cpu_to_le32(tcp->payload_seq.start); | ||
592 | cfg->keepalive_interval = cpu_to_le16(tcp->data_interval); | ||
593 | if (tcp->payload_tok.len) { | ||
594 | cfg->token_offset = tcp->payload_tok.offset; | ||
595 | cfg->token_length = tcp->payload_tok.len; | ||
596 | cfg->num_tokens = | ||
597 | cpu_to_le16(tcp->tokens_size % tcp->payload_tok.len); | ||
598 | memcpy(cfg->tokens, tcp->payload_tok.token_stream, | ||
599 | tcp->tokens_size); | ||
600 | } else { | ||
601 | /* set tokens to max value to almost never run out */ | ||
602 | cfg->num_tokens = cpu_to_le16(65535); | ||
603 | } | ||
604 | |||
605 | /* ACK (RX) */ | ||
606 | iwl_mvm_build_tcp_packet( | ||
607 | mvm, vif, tcp, cfg->keepalive_ack_rx.data, | ||
608 | cfg->keepalive_ack_rx.rx_mask, | ||
609 | &cfg->keepalive_ack_rx.info.tcp_pseudo_header_checksum, | ||
610 | MVM_TCP_RX_ACK); | ||
611 | cfg->keepalive_ack_rx.info.tcp_payload_length = 0; | ||
612 | |||
613 | /* WAKEUP (RX) */ | ||
614 | iwl_mvm_build_tcp_packet( | ||
615 | mvm, vif, tcp, cfg->wake_rx.data, cfg->wake_rx.rx_mask, | ||
616 | &cfg->wake_rx.info.tcp_pseudo_header_checksum, | ||
617 | MVM_TCP_RX_WAKE); | ||
618 | cfg->wake_rx.info.tcp_payload_length = | ||
619 | cpu_to_le16(tcp->wake_len); | ||
620 | |||
621 | /* FIN */ | ||
622 | iwl_mvm_build_tcp_packet( | ||
623 | mvm, vif, tcp, cfg->fin_tx.data, NULL, | ||
624 | &cfg->fin_tx.info.tcp_pseudo_header_checksum, | ||
625 | MVM_TCP_TX_FIN); | ||
626 | cfg->fin_tx.info.tcp_payload_length = 0; | ||
627 | |||
628 | ret = iwl_mvm_send_cmd(mvm, &cmd); | ||
629 | kfree(cfg); | ||
630 | |||
631 | return ret; | ||
632 | } | ||
633 | |||
405 | struct iwl_d3_iter_data { | 634 | struct iwl_d3_iter_data { |
406 | struct iwl_mvm *mvm; | 635 | struct iwl_mvm *mvm; |
407 | struct ieee80211_vif *vif; | 636 | struct ieee80211_vif *vif; |
@@ -640,6 +869,22 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
640 | d3_cfg_cmd.wakeup_flags |= | 869 | d3_cfg_cmd.wakeup_flags |= |
641 | cpu_to_le32(IWL_WOWLAN_WAKEUP_RF_KILL_DEASSERT); | 870 | cpu_to_le32(IWL_WOWLAN_WAKEUP_RF_KILL_DEASSERT); |
642 | 871 | ||
872 | if (wowlan->tcp) { | ||
873 | /* | ||
874 | * The firmware currently doesn't really look at these, only | ||
875 | * the IWL_WOWLAN_WAKEUP_LINK_CHANGE bit. We have to set that | ||
876 | * reason bit since losing the connection to the AP implies | ||
877 | * losing the TCP connection. | ||
878 | * Set the flags anyway as long as they exist, in case this | ||
879 | * will be changed in the firmware. | ||
880 | */ | ||
881 | wowlan_config_cmd.wakeup_filter |= | ||
882 | cpu_to_le32(IWL_WOWLAN_WAKEUP_REMOTE_LINK_LOSS | | ||
883 | IWL_WOWLAN_WAKEUP_REMOTE_SIGNATURE_TABLE | | ||
884 | IWL_WOWLAN_WAKEUP_REMOTE_WAKEUP_PACKET | | ||
885 | IWL_WOWLAN_WAKEUP_LINK_CHANGE); | ||
886 | } | ||
887 | |||
643 | iwl_mvm_cancel_scan(mvm); | 888 | iwl_mvm_cancel_scan(mvm); |
644 | 889 | ||
645 | iwl_trans_stop_device(mvm->trans); | 890 | iwl_trans_stop_device(mvm->trans); |
@@ -755,6 +1000,10 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
755 | if (ret) | 1000 | if (ret) |
756 | goto out; | 1001 | goto out; |
757 | 1002 | ||
1003 | ret = iwl_mvm_send_remote_wake_cfg(mvm, vif, wowlan->tcp); | ||
1004 | if (ret) | ||
1005 | goto out; | ||
1006 | |||
758 | /* must be last -- this switches firmware state */ | 1007 | /* must be last -- this switches firmware state */ |
759 | ret = iwl_mvm_send_cmd_pdu(mvm, D3_CONFIG_CMD, CMD_SYNC, | 1008 | ret = iwl_mvm_send_cmd_pdu(mvm, D3_CONFIG_CMD, CMD_SYNC, |
760 | sizeof(d3_cfg_cmd), &d3_cfg_cmd); | 1009 | sizeof(d3_cfg_cmd), &d3_cfg_cmd); |
@@ -874,6 +1123,15 @@ static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, | |||
874 | if (reasons & IWL_WOWLAN_WAKEUP_BY_FOUR_WAY_HANDSHAKE) | 1123 | if (reasons & IWL_WOWLAN_WAKEUP_BY_FOUR_WAY_HANDSHAKE) |
875 | wakeup.four_way_handshake = true; | 1124 | wakeup.four_way_handshake = true; |
876 | 1125 | ||
1126 | if (reasons & IWL_WOWLAN_WAKEUP_BY_REM_WAKE_LINK_LOSS) | ||
1127 | wakeup.tcp_connlost = true; | ||
1128 | |||
1129 | if (reasons & IWL_WOWLAN_WAKEUP_BY_REM_WAKE_SIGNATURE_TABLE) | ||
1130 | wakeup.tcp_nomoretokens = true; | ||
1131 | |||
1132 | if (reasons & IWL_WOWLAN_WAKEUP_BY_REM_WAKE_WAKEUP_PACKET) | ||
1133 | wakeup.tcp_match = true; | ||
1134 | |||
877 | if (status->wake_packet_bufsize) { | 1135 | if (status->wake_packet_bufsize) { |
878 | int pktsize = le32_to_cpu(status->wake_packet_bufsize); | 1136 | int pktsize = le32_to_cpu(status->wake_packet_bufsize); |
879 | int pktlen = le32_to_cpu(status->wake_packet_length); | 1137 | int pktlen = le32_to_cpu(status->wake_packet_length); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index c1bdb5582126..b080b4ba5458 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -69,12 +69,6 @@ struct iwl_dbgfs_mvm_ctx { | |||
69 | struct ieee80211_vif *vif; | 69 | struct ieee80211_vif *vif; |
70 | }; | 70 | }; |
71 | 71 | ||
72 | static int iwl_dbgfs_open_file_generic(struct inode *inode, struct file *file) | ||
73 | { | ||
74 | file->private_data = inode->i_private; | ||
75 | return 0; | ||
76 | } | ||
77 | |||
78 | static ssize_t iwl_dbgfs_tx_flush_write(struct file *file, | 72 | static ssize_t iwl_dbgfs_tx_flush_write(struct file *file, |
79 | const char __user *user_buf, | 73 | const char __user *user_buf, |
80 | size_t count, loff_t *ppos) | 74 | size_t count, loff_t *ppos) |
@@ -306,10 +300,130 @@ static ssize_t iwl_dbgfs_power_down_d3_allow_write(struct file *file, | |||
306 | return count; | 300 | return count; |
307 | } | 301 | } |
308 | 302 | ||
303 | #define BT_MBOX_MSG(_notif, _num, _field) \ | ||
304 | ((le32_to_cpu((_notif)->mbox_msg[(_num)]) & BT_MBOX##_num##_##_field)\ | ||
305 | >> BT_MBOX##_num##_##_field##_POS) | ||
306 | |||
307 | |||
308 | #define BT_MBOX_PRINT(_num, _field, _end) \ | ||
309 | pos += scnprintf(buf + pos, bufsz - pos, \ | ||
310 | "\t%s: %d%s", \ | ||
311 | #_field, \ | ||
312 | BT_MBOX_MSG(notif, _num, _field), \ | ||
313 | true ? "\n" : ", "); | ||
314 | |||
315 | static ssize_t iwl_dbgfs_bt_notif_read(struct file *file, char __user *user_buf, | ||
316 | size_t count, loff_t *ppos) | ||
317 | { | ||
318 | struct iwl_mvm *mvm = file->private_data; | ||
319 | struct iwl_bt_coex_profile_notif *notif = &mvm->last_bt_notif; | ||
320 | char *buf; | ||
321 | int ret, pos = 0, bufsz = sizeof(char) * 1024; | ||
322 | |||
323 | buf = kmalloc(bufsz, GFP_KERNEL); | ||
324 | if (!buf) | ||
325 | return -ENOMEM; | ||
326 | |||
327 | mutex_lock(&mvm->mutex); | ||
328 | |||
329 | pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw0:\n"); | ||
330 | |||
331 | BT_MBOX_PRINT(0, LE_SLAVE_LAT, false); | ||
332 | BT_MBOX_PRINT(0, LE_PROF1, false); | ||
333 | BT_MBOX_PRINT(0, LE_PROF2, false); | ||
334 | BT_MBOX_PRINT(0, LE_PROF_OTHER, false); | ||
335 | BT_MBOX_PRINT(0, CHL_SEQ_N, false); | ||
336 | BT_MBOX_PRINT(0, INBAND_S, false); | ||
337 | BT_MBOX_PRINT(0, LE_MIN_RSSI, false); | ||
338 | BT_MBOX_PRINT(0, LE_SCAN, false); | ||
339 | BT_MBOX_PRINT(0, LE_ADV, false); | ||
340 | BT_MBOX_PRINT(0, LE_MAX_TX_POWER, false); | ||
341 | BT_MBOX_PRINT(0, OPEN_CON_1, true); | ||
342 | |||
343 | pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw1:\n"); | ||
344 | |||
345 | BT_MBOX_PRINT(1, BR_MAX_TX_POWER, false); | ||
346 | BT_MBOX_PRINT(1, IP_SR, false); | ||
347 | BT_MBOX_PRINT(1, LE_MSTR, false); | ||
348 | BT_MBOX_PRINT(1, AGGR_TRFC_LD, false); | ||
349 | BT_MBOX_PRINT(1, MSG_TYPE, false); | ||
350 | BT_MBOX_PRINT(1, SSN, true); | ||
351 | |||
352 | pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw2:\n"); | ||
353 | |||
354 | BT_MBOX_PRINT(2, SNIFF_ACT, false); | ||
355 | BT_MBOX_PRINT(2, PAG, false); | ||
356 | BT_MBOX_PRINT(2, INQUIRY, false); | ||
357 | BT_MBOX_PRINT(2, CONN, false); | ||
358 | BT_MBOX_PRINT(2, SNIFF_INTERVAL, false); | ||
359 | BT_MBOX_PRINT(2, DISC, false); | ||
360 | BT_MBOX_PRINT(2, SCO_TX_ACT, false); | ||
361 | BT_MBOX_PRINT(2, SCO_RX_ACT, false); | ||
362 | BT_MBOX_PRINT(2, ESCO_RE_TX, false); | ||
363 | BT_MBOX_PRINT(2, SCO_DURATION, true); | ||
364 | |||
365 | pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw3:\n"); | ||
366 | |||
367 | BT_MBOX_PRINT(3, SCO_STATE, false); | ||
368 | BT_MBOX_PRINT(3, SNIFF_STATE, false); | ||
369 | BT_MBOX_PRINT(3, A2DP_STATE, false); | ||
370 | BT_MBOX_PRINT(3, ACL_STATE, false); | ||
371 | BT_MBOX_PRINT(3, MSTR_STATE, false); | ||
372 | BT_MBOX_PRINT(3, OBX_STATE, false); | ||
373 | BT_MBOX_PRINT(3, OPEN_CON_2, false); | ||
374 | BT_MBOX_PRINT(3, TRAFFIC_LOAD, false); | ||
375 | BT_MBOX_PRINT(3, CHL_SEQN_LSB, false); | ||
376 | BT_MBOX_PRINT(3, INBAND_P, false); | ||
377 | BT_MBOX_PRINT(3, MSG_TYPE_2, false); | ||
378 | BT_MBOX_PRINT(3, SSN_2, false); | ||
379 | BT_MBOX_PRINT(3, UPDATE_REQUEST, true); | ||
380 | |||
381 | pos += scnprintf(buf+pos, bufsz-pos, "bt_status = %d\n", | ||
382 | notif->bt_status); | ||
383 | pos += scnprintf(buf+pos, bufsz-pos, "bt_open_conn = %d\n", | ||
384 | notif->bt_open_conn); | ||
385 | pos += scnprintf(buf+pos, bufsz-pos, "bt_traffic_load = %d\n", | ||
386 | notif->bt_traffic_load); | ||
387 | pos += scnprintf(buf+pos, bufsz-pos, "bt_agg_traffic_load = %d\n", | ||
388 | notif->bt_agg_traffic_load); | ||
389 | pos += scnprintf(buf+pos, bufsz-pos, "bt_ci_compliance = %d\n", | ||
390 | notif->bt_ci_compliance); | ||
391 | |||
392 | mutex_unlock(&mvm->mutex); | ||
393 | |||
394 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
395 | kfree(buf); | ||
396 | |||
397 | return ret; | ||
398 | } | ||
399 | #undef BT_MBOX_PRINT | ||
400 | |||
401 | static ssize_t iwl_dbgfs_fw_restart_write(struct file *file, | ||
402 | const char __user *user_buf, | ||
403 | size_t count, loff_t *ppos) | ||
404 | { | ||
405 | struct iwl_mvm *mvm = file->private_data; | ||
406 | bool restart_fw = iwlwifi_mod_params.restart_fw; | ||
407 | int ret; | ||
408 | |||
409 | iwlwifi_mod_params.restart_fw = true; | ||
410 | |||
411 | mutex_lock(&mvm->mutex); | ||
412 | |||
413 | /* take the return value to make compiler happy - it will fail anyway */ | ||
414 | ret = iwl_mvm_send_cmd_pdu(mvm, REPLY_ERROR, CMD_SYNC, 0, NULL); | ||
415 | |||
416 | mutex_unlock(&mvm->mutex); | ||
417 | |||
418 | iwlwifi_mod_params.restart_fw = restart_fw; | ||
419 | |||
420 | return count; | ||
421 | } | ||
422 | |||
309 | #define MVM_DEBUGFS_READ_FILE_OPS(name) \ | 423 | #define MVM_DEBUGFS_READ_FILE_OPS(name) \ |
310 | static const struct file_operations iwl_dbgfs_##name##_ops = { \ | 424 | static const struct file_operations iwl_dbgfs_##name##_ops = { \ |
311 | .read = iwl_dbgfs_##name##_read, \ | 425 | .read = iwl_dbgfs_##name##_read, \ |
312 | .open = iwl_dbgfs_open_file_generic, \ | 426 | .open = simple_open, \ |
313 | .llseek = generic_file_llseek, \ | 427 | .llseek = generic_file_llseek, \ |
314 | } | 428 | } |
315 | 429 | ||
@@ -317,14 +431,14 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \ | |||
317 | static const struct file_operations iwl_dbgfs_##name##_ops = { \ | 431 | static const struct file_operations iwl_dbgfs_##name##_ops = { \ |
318 | .write = iwl_dbgfs_##name##_write, \ | 432 | .write = iwl_dbgfs_##name##_write, \ |
319 | .read = iwl_dbgfs_##name##_read, \ | 433 | .read = iwl_dbgfs_##name##_read, \ |
320 | .open = iwl_dbgfs_open_file_generic, \ | 434 | .open = simple_open, \ |
321 | .llseek = generic_file_llseek, \ | 435 | .llseek = generic_file_llseek, \ |
322 | }; | 436 | }; |
323 | 437 | ||
324 | #define MVM_DEBUGFS_WRITE_FILE_OPS(name) \ | 438 | #define MVM_DEBUGFS_WRITE_FILE_OPS(name) \ |
325 | static const struct file_operations iwl_dbgfs_##name##_ops = { \ | 439 | static const struct file_operations iwl_dbgfs_##name##_ops = { \ |
326 | .write = iwl_dbgfs_##name##_write, \ | 440 | .write = iwl_dbgfs_##name##_write, \ |
327 | .open = iwl_dbgfs_open_file_generic, \ | 441 | .open = simple_open, \ |
328 | .llseek = generic_file_llseek, \ | 442 | .llseek = generic_file_llseek, \ |
329 | }; | 443 | }; |
330 | 444 | ||
@@ -345,8 +459,10 @@ MVM_DEBUGFS_WRITE_FILE_OPS(tx_flush); | |||
345 | MVM_DEBUGFS_WRITE_FILE_OPS(sta_drain); | 459 | MVM_DEBUGFS_WRITE_FILE_OPS(sta_drain); |
346 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(sram); | 460 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(sram); |
347 | MVM_DEBUGFS_READ_FILE_OPS(stations); | 461 | MVM_DEBUGFS_READ_FILE_OPS(stations); |
462 | MVM_DEBUGFS_READ_FILE_OPS(bt_notif); | ||
348 | MVM_DEBUGFS_WRITE_FILE_OPS(power_down_allow); | 463 | MVM_DEBUGFS_WRITE_FILE_OPS(power_down_allow); |
349 | MVM_DEBUGFS_WRITE_FILE_OPS(power_down_d3_allow); | 464 | MVM_DEBUGFS_WRITE_FILE_OPS(power_down_d3_allow); |
465 | MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart); | ||
350 | 466 | ||
351 | int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) | 467 | int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) |
352 | { | 468 | { |
@@ -358,8 +474,10 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) | |||
358 | MVM_DEBUGFS_ADD_FILE(sta_drain, mvm->debugfs_dir, S_IWUSR); | 474 | MVM_DEBUGFS_ADD_FILE(sta_drain, mvm->debugfs_dir, S_IWUSR); |
359 | MVM_DEBUGFS_ADD_FILE(sram, mvm->debugfs_dir, S_IWUSR | S_IRUSR); | 475 | MVM_DEBUGFS_ADD_FILE(sram, mvm->debugfs_dir, S_IWUSR | S_IRUSR); |
360 | MVM_DEBUGFS_ADD_FILE(stations, dbgfs_dir, S_IRUSR); | 476 | MVM_DEBUGFS_ADD_FILE(stations, dbgfs_dir, S_IRUSR); |
477 | MVM_DEBUGFS_ADD_FILE(bt_notif, dbgfs_dir, S_IRUSR); | ||
361 | MVM_DEBUGFS_ADD_FILE(power_down_allow, mvm->debugfs_dir, S_IWUSR); | 478 | MVM_DEBUGFS_ADD_FILE(power_down_allow, mvm->debugfs_dir, S_IWUSR); |
362 | MVM_DEBUGFS_ADD_FILE(power_down_d3_allow, mvm->debugfs_dir, S_IWUSR); | 479 | MVM_DEBUGFS_ADD_FILE(power_down_d3_allow, mvm->debugfs_dir, S_IWUSR); |
480 | MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR); | ||
363 | 481 | ||
364 | /* | 482 | /* |
365 | * Create a symlink with mac80211. It will be removed when mac80211 | 483 | * Create a symlink with mac80211. It will be removed when mac80211 |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h new file mode 100644 index 000000000000..05c61d6f384e --- /dev/null +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h | |||
@@ -0,0 +1,319 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2013 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called COPYING. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2013 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | *****************************************************************************/ | ||
62 | |||
63 | #ifndef __fw_api_bt_coex_h__ | ||
64 | #define __fw_api_bt_coex_h__ | ||
65 | |||
66 | #include <linux/types.h> | ||
67 | #include <linux/bitops.h> | ||
68 | |||
69 | #define BITS(nb) (BIT(nb) - 1) | ||
70 | |||
71 | /** | ||
72 | * enum iwl_bt_coex_flags - flags for BT_COEX command | ||
73 | * @BT_CH_PRIMARY_EN: | ||
74 | * @BT_CH_SECONDARY_EN: | ||
75 | * @BT_NOTIF_COEX_OFF: | ||
76 | * @BT_COEX_MODE_POS: | ||
77 | * @BT_COEX_MODE_MSK: | ||
78 | * @BT_COEX_DISABLE: | ||
79 | * @BT_COEX_2W: | ||
80 | * @BT_COEX_3W: | ||
81 | * @BT_COEX_NW: | ||
82 | * @BT_USE_DEFAULTS: | ||
83 | * @BT_SYNC_2_BT_DISABLE: | ||
84 | * @BT_COEX_CORUNNING_TBL_EN: | ||
85 | */ | ||
86 | enum iwl_bt_coex_flags { | ||
87 | BT_CH_PRIMARY_EN = BIT(0), | ||
88 | BT_CH_SECONDARY_EN = BIT(1), | ||
89 | BT_NOTIF_COEX_OFF = BIT(2), | ||
90 | BT_COEX_MODE_POS = 3, | ||
91 | BT_COEX_MODE_MSK = BITS(3) << BT_COEX_MODE_POS, | ||
92 | BT_COEX_DISABLE = 0x0 << BT_COEX_MODE_POS, | ||
93 | BT_COEX_2W = 0x1 << BT_COEX_MODE_POS, | ||
94 | BT_COEX_3W = 0x2 << BT_COEX_MODE_POS, | ||
95 | BT_COEX_NW = 0x3 << BT_COEX_MODE_POS, | ||
96 | BT_USE_DEFAULTS = BIT(6), | ||
97 | BT_SYNC_2_BT_DISABLE = BIT(7), | ||
98 | /* | ||
99 | * For future use - when the flags will be enlarged | ||
100 | * BT_COEX_CORUNNING_TBL_EN = BIT(8), | ||
101 | */ | ||
102 | }; | ||
103 | |||
104 | /* | ||
105 | * indicates what has changed in the BT_COEX command. | ||
106 | */ | ||
107 | enum iwl_bt_coex_valid_bit_msk { | ||
108 | BT_VALID_ENABLE = BIT(0), | ||
109 | BT_VALID_BT_PRIO_BOOST = BIT(1), | ||
110 | BT_VALID_MAX_KILL = BIT(2), | ||
111 | BT_VALID_3W_TMRS = BIT(3), | ||
112 | BT_VALID_KILL_ACK = BIT(4), | ||
113 | BT_VALID_KILL_CTS = BIT(5), | ||
114 | BT_VALID_REDUCED_TX_POWER = BIT(6), | ||
115 | BT_VALID_LUT = BIT(7), | ||
116 | BT_VALID_WIFI_RX_SW_PRIO_BOOST = BIT(8), | ||
117 | BT_VALID_WIFI_TX_SW_PRIO_BOOST = BIT(9), | ||
118 | BT_VALID_MULTI_PRIO_LUT = BIT(10), | ||
119 | BT_VALID_TRM_KICK_FILTER = BIT(11), | ||
120 | BT_VALID_CORUN_LUT_20 = BIT(12), | ||
121 | BT_VALID_CORUN_LUT_40 = BIT(13), | ||
122 | BT_VALID_ANT_ISOLATION = BIT(14), | ||
123 | BT_VALID_ANT_ISOLATION_THRS = BIT(15), | ||
124 | /* | ||
125 | * For future use - when the valid flags will be enlarged | ||
126 | * BT_VALID_TXTX_DELTA_FREQ_THRS = BIT(16), | ||
127 | * BT_VALID_TXRX_MAX_FREQ_0 = BIT(17), | ||
128 | */ | ||
129 | }; | ||
130 | |||
131 | /** | ||
132 | * enum iwl_bt_reduced_tx_power - allows to reduce txpower for WiFi frames. | ||
133 | * @BT_REDUCED_TX_POWER_CTL: reduce Tx power for control frames | ||
134 | * @BT_REDUCED_TX_POWER_DATA: reduce Tx power for data frames | ||
135 | * | ||
136 | * This mechanism allows to have BT and WiFi run concurrently. Since WiFi | ||
137 | * reduces its Tx power, it can work along with BT, hence reducing the amount | ||
138 | * of WiFi frames being killed by BT. | ||
139 | */ | ||
140 | enum iwl_bt_reduced_tx_power { | ||
141 | BT_REDUCED_TX_POWER_CTL = BIT(0), | ||
142 | BT_REDUCED_TX_POWER_DATA = BIT(1), | ||
143 | }; | ||
144 | |||
145 | #define BT_COEX_LUT_SIZE (12) | ||
146 | |||
147 | /** | ||
148 | * struct iwl_bt_coex_cmd - bt coex configuration command | ||
149 | * @flags:&enum iwl_bt_coex_flags | ||
150 | * @lead_time: | ||
151 | * @max_kill: | ||
152 | * @bt3_time_t7_value: | ||
153 | * @kill_ack_msk: | ||
154 | * @kill_cts_msk: | ||
155 | * @bt3_prio_sample_time: | ||
156 | * @bt3_timer_t2_value: | ||
157 | * @bt4_reaction_time: | ||
158 | * @decision_lut[12]: | ||
159 | * @bt_reduced_tx_power: enum %iwl_bt_reduced_tx_power | ||
160 | * @valid_bit_msk: enum %iwl_bt_coex_valid_bit_msk | ||
161 | * @bt_prio_boost: values for PTA boost register | ||
162 | * @wifi_tx_prio_boost: SW boost of wifi tx priority | ||
163 | * @wifi_rx_prio_boost: SW boost of wifi rx priority | ||
164 | * | ||
165 | * The structure is used for the BT_COEX command. | ||
166 | */ | ||
167 | struct iwl_bt_coex_cmd { | ||
168 | u8 flags; | ||
169 | u8 lead_time; | ||
170 | u8 max_kill; | ||
171 | u8 bt3_time_t7_value; | ||
172 | __le32 kill_ack_msk; | ||
173 | __le32 kill_cts_msk; | ||
174 | u8 bt3_prio_sample_time; | ||
175 | u8 bt3_timer_t2_value; | ||
176 | __le16 bt4_reaction_time; | ||
177 | __le32 decision_lut[BT_COEX_LUT_SIZE]; | ||
178 | u8 bt_reduced_tx_power; | ||
179 | u8 reserved; | ||
180 | __le16 valid_bit_msk; | ||
181 | __le32 bt_prio_boost; | ||
182 | u8 reserved2; | ||
183 | u8 wifi_tx_prio_boost; | ||
184 | __le16 wifi_rx_prio_boost; | ||
185 | } __packed; /* BT_COEX_CMD_API_S_VER_3 */ | ||
186 | |||
187 | #define BT_MBOX(n_dw, _msg, _pos, _nbits) \ | ||
188 | BT_MBOX##n_dw##_##_msg##_POS = (_pos), \ | ||
189 | BT_MBOX##n_dw##_##_msg = BITS(_nbits) << BT_MBOX##n_dw##_##_msg##_POS | ||
190 | |||
191 | enum iwl_bt_mxbox_dw0 { | ||
192 | BT_MBOX(0, LE_SLAVE_LAT, 0, 3), | ||
193 | BT_MBOX(0, LE_PROF1, 3, 1), | ||
194 | BT_MBOX(0, LE_PROF2, 4, 1), | ||
195 | BT_MBOX(0, LE_PROF_OTHER, 5, 1), | ||
196 | BT_MBOX(0, CHL_SEQ_N, 8, 4), | ||
197 | BT_MBOX(0, INBAND_S, 13, 1), | ||
198 | BT_MBOX(0, LE_MIN_RSSI, 16, 4), | ||
199 | BT_MBOX(0, LE_SCAN, 20, 1), | ||
200 | BT_MBOX(0, LE_ADV, 21, 1), | ||
201 | BT_MBOX(0, LE_MAX_TX_POWER, 24, 4), | ||
202 | BT_MBOX(0, OPEN_CON_1, 28, 2), | ||
203 | }; | ||
204 | |||
205 | enum iwl_bt_mxbox_dw1 { | ||
206 | BT_MBOX(1, BR_MAX_TX_POWER, 0, 4), | ||
207 | BT_MBOX(1, IP_SR, 4, 1), | ||
208 | BT_MBOX(1, LE_MSTR, 5, 1), | ||
209 | BT_MBOX(1, AGGR_TRFC_LD, 8, 6), | ||
210 | BT_MBOX(1, MSG_TYPE, 16, 3), | ||
211 | BT_MBOX(1, SSN, 19, 2), | ||
212 | }; | ||
213 | |||
214 | enum iwl_bt_mxbox_dw2 { | ||
215 | BT_MBOX(2, SNIFF_ACT, 0, 3), | ||
216 | BT_MBOX(2, PAG, 3, 1), | ||
217 | BT_MBOX(2, INQUIRY, 4, 1), | ||
218 | BT_MBOX(2, CONN, 5, 1), | ||
219 | BT_MBOX(2, SNIFF_INTERVAL, 8, 5), | ||
220 | BT_MBOX(2, DISC, 13, 1), | ||
221 | BT_MBOX(2, SCO_TX_ACT, 16, 2), | ||
222 | BT_MBOX(2, SCO_RX_ACT, 18, 2), | ||
223 | BT_MBOX(2, ESCO_RE_TX, 20, 2), | ||
224 | BT_MBOX(2, SCO_DURATION, 24, 6), | ||
225 | }; | ||
226 | |||
227 | enum iwl_bt_mxbox_dw3 { | ||
228 | BT_MBOX(3, SCO_STATE, 0, 1), | ||
229 | BT_MBOX(3, SNIFF_STATE, 1, 1), | ||
230 | BT_MBOX(3, A2DP_STATE, 2, 1), | ||
231 | BT_MBOX(3, ACL_STATE, 3, 1), | ||
232 | BT_MBOX(3, MSTR_STATE, 4, 1), | ||
233 | BT_MBOX(3, OBX_STATE, 5, 1), | ||
234 | BT_MBOX(3, OPEN_CON_2, 8, 2), | ||
235 | BT_MBOX(3, TRAFFIC_LOAD, 10, 2), | ||
236 | BT_MBOX(3, CHL_SEQN_LSB, 12, 1), | ||
237 | BT_MBOX(3, INBAND_P, 13, 1), | ||
238 | BT_MBOX(3, MSG_TYPE_2, 16, 3), | ||
239 | BT_MBOX(3, SSN_2, 19, 2), | ||
240 | BT_MBOX(3, UPDATE_REQUEST, 21, 1), | ||
241 | }; | ||
242 | |||
243 | #define BT_MBOX_MSG(_notif, _num, _field) \ | ||
244 | ((le32_to_cpu((_notif)->mbox_msg[(_num)]) & BT_MBOX##_num##_##_field)\ | ||
245 | >> BT_MBOX##_num##_##_field##_POS) | ||
246 | |||
247 | /** | ||
248 | * struct iwl_bt_coex_profile_notif - notification about BT coex | ||
249 | * @mbox_msg: message from BT to WiFi | ||
250 | * @:bt_status: 0 - off, 1 - on | ||
251 | * @:bt_open_conn: number of BT connections open | ||
252 | * @:bt_traffic_load: load of BT traffic | ||
253 | * @:bt_agg_traffic_load: aggregated load of BT traffic | ||
254 | * @:bt_ci_compliance: 0 - no CI compliance, 1 - CI compliant | ||
255 | */ | ||
256 | struct iwl_bt_coex_profile_notif { | ||
257 | __le32 mbox_msg[4]; | ||
258 | u8 bt_status; | ||
259 | u8 bt_open_conn; | ||
260 | u8 bt_traffic_load; | ||
261 | u8 bt_agg_traffic_load; | ||
262 | u8 bt_ci_compliance; | ||
263 | u8 reserved[3]; | ||
264 | } __packed; /* BT_COEX_PROFILE_NTFY_API_S_VER_2 */ | ||
265 | |||
266 | enum iwl_bt_coex_prio_table_event { | ||
267 | BT_COEX_PRIO_TBL_EVT_INIT_CALIB1 = 0, | ||
268 | BT_COEX_PRIO_TBL_EVT_INIT_CALIB2 = 1, | ||
269 | BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_LOW1 = 2, | ||
270 | BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_LOW2 = 3, | ||
271 | BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_HIGH1 = 4, | ||
272 | BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_HIGH2 = 5, | ||
273 | BT_COEX_PRIO_TBL_EVT_DTIM = 6, | ||
274 | BT_COEX_PRIO_TBL_EVT_SCAN52 = 7, | ||
275 | BT_COEX_PRIO_TBL_EVT_SCAN24 = 8, | ||
276 | BT_COEX_PRIO_TBL_EVT_IDLE = 9, | ||
277 | BT_COEX_PRIO_TBL_EVT_MAX = 16, | ||
278 | }; /* BT_COEX_PRIO_TABLE_EVENTS_API_E_VER_1 */ | ||
279 | |||
280 | enum iwl_bt_coex_prio_table_prio { | ||
281 | BT_COEX_PRIO_TBL_DISABLED = 0, | ||
282 | BT_COEX_PRIO_TBL_PRIO_LOW = 1, | ||
283 | BT_COEX_PRIO_TBL_PRIO_HIGH = 2, | ||
284 | BT_COEX_PRIO_TBL_PRIO_BYPASS = 3, | ||
285 | BT_COEX_PRIO_TBL_PRIO_COEX_OFF = 4, | ||
286 | BT_COEX_PRIO_TBL_PRIO_COEX_ON = 5, | ||
287 | BT_COEX_PRIO_TBL_PRIO_COEX_IDLE = 6, | ||
288 | BT_COEX_PRIO_TBL_MAX = 8, | ||
289 | }; /* BT_COEX_PRIO_TABLE_PRIORITIES_API_E_VER_1 */ | ||
290 | |||
291 | #define BT_COEX_PRIO_TBL_SHRD_ANT_POS (0) | ||
292 | #define BT_COEX_PRIO_TBL_PRIO_POS (1) | ||
293 | #define BT_COEX_PRIO_TBL_RESERVED_POS (4) | ||
294 | |||
295 | /** | ||
296 | * struct iwl_bt_coex_prio_tbl_cmd - priority table for BT coex | ||
297 | * @prio_tbl: | ||
298 | */ | ||
299 | struct iwl_bt_coex_prio_tbl_cmd { | ||
300 | u8 prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX]; | ||
301 | } __packed; | ||
302 | |||
303 | enum iwl_bt_coex_env_action { | ||
304 | BT_COEX_ENV_CLOSE = 0, | ||
305 | BT_COEX_ENV_OPEN = 1, | ||
306 | }; /* BT_COEX_PROT_ENV_ACTION_API_E_VER_1 */ | ||
307 | |||
308 | /** | ||
309 | * struct iwl_bt_coex_prot_env_cmd - BT Protection Envelope | ||
310 | * @action: enum %iwl_bt_coex_env_action | ||
311 | * @type: enum %iwl_bt_coex_prio_table_event | ||
312 | */ | ||
313 | struct iwl_bt_coex_prot_env_cmd { | ||
314 | u8 action; /* 0 = closed, 1 = open */ | ||
315 | u8 type; /* 0 .. 15 */ | ||
316 | u8 reserved[2]; | ||
317 | } __packed; | ||
318 | |||
319 | #endif /* __fw_api_bt_coex_h__ */ | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h index cf6f9a02fb74..51e015d1dfb2 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -258,7 +258,7 @@ enum iwl_wowlan_wakeup_reason { | |||
258 | IWL_WOWLAN_WAKEUP_BY_FOUR_WAY_HANDSHAKE = BIT(8), | 258 | IWL_WOWLAN_WAKEUP_BY_FOUR_WAY_HANDSHAKE = BIT(8), |
259 | IWL_WOWLAN_WAKEUP_BY_REM_WAKE_LINK_LOSS = BIT(9), | 259 | IWL_WOWLAN_WAKEUP_BY_REM_WAKE_LINK_LOSS = BIT(9), |
260 | IWL_WOWLAN_WAKEUP_BY_REM_WAKE_SIGNATURE_TABLE = BIT(10), | 260 | IWL_WOWLAN_WAKEUP_BY_REM_WAKE_SIGNATURE_TABLE = BIT(10), |
261 | IWL_WOWLAN_WAKEUP_BY_REM_WAKE_TCP_EXTERNAL = BIT(11), | 261 | /* BIT(11) reserved */ |
262 | IWL_WOWLAN_WAKEUP_BY_REM_WAKE_WAKEUP_PACKET = BIT(12), | 262 | IWL_WOWLAN_WAKEUP_BY_REM_WAKE_WAKEUP_PACKET = BIT(12), |
263 | }; /* WOWLAN_WAKE_UP_REASON_API_E_VER_2 */ | 263 | }; /* WOWLAN_WAKE_UP_REASON_API_E_VER_2 */ |
264 | 264 | ||
@@ -277,6 +277,55 @@ struct iwl_wowlan_status { | |||
277 | u8 wake_packet[]; /* can be truncated from _length to _bufsize */ | 277 | u8 wake_packet[]; /* can be truncated from _length to _bufsize */ |
278 | } __packed; /* WOWLAN_STATUSES_API_S_VER_4 */ | 278 | } __packed; /* WOWLAN_STATUSES_API_S_VER_4 */ |
279 | 279 | ||
280 | #define IWL_WOWLAN_TCP_MAX_PACKET_LEN 64 | ||
281 | #define IWL_WOWLAN_REMOTE_WAKE_MAX_PACKET_LEN 128 | ||
282 | #define IWL_WOWLAN_REMOTE_WAKE_MAX_TOKENS 2048 | ||
283 | |||
284 | struct iwl_tcp_packet_info { | ||
285 | __le16 tcp_pseudo_header_checksum; | ||
286 | __le16 tcp_payload_length; | ||
287 | } __packed; /* TCP_PACKET_INFO_API_S_VER_2 */ | ||
288 | |||
289 | struct iwl_tcp_packet { | ||
290 | struct iwl_tcp_packet_info info; | ||
291 | u8 rx_mask[IWL_WOWLAN_MAX_PATTERN_LEN / 8]; | ||
292 | u8 data[IWL_WOWLAN_TCP_MAX_PACKET_LEN]; | ||
293 | } __packed; /* TCP_PROTOCOL_PACKET_API_S_VER_1 */ | ||
294 | |||
295 | struct iwl_remote_wake_packet { | ||
296 | struct iwl_tcp_packet_info info; | ||
297 | u8 rx_mask[IWL_WOWLAN_MAX_PATTERN_LEN / 8]; | ||
298 | u8 data[IWL_WOWLAN_REMOTE_WAKE_MAX_PACKET_LEN]; | ||
299 | } __packed; /* TCP_PROTOCOL_PACKET_API_S_VER_1 */ | ||
300 | |||
301 | struct iwl_wowlan_remote_wake_config { | ||
302 | __le32 connection_max_time; /* unused */ | ||
303 | /* TCP_PROTOCOL_CONFIG_API_S_VER_1 */ | ||
304 | u8 max_syn_retries; | ||
305 | u8 max_data_retries; | ||
306 | u8 tcp_syn_ack_timeout; | ||
307 | u8 tcp_ack_timeout; | ||
308 | |||
309 | struct iwl_tcp_packet syn_tx; | ||
310 | struct iwl_tcp_packet synack_rx; | ||
311 | struct iwl_tcp_packet keepalive_ack_rx; | ||
312 | struct iwl_tcp_packet fin_tx; | ||
313 | |||
314 | struct iwl_remote_wake_packet keepalive_tx; | ||
315 | struct iwl_remote_wake_packet wake_rx; | ||
316 | |||
317 | /* REMOTE_WAKE_OFFSET_INFO_API_S_VER_1 */ | ||
318 | u8 sequence_number_offset; | ||
319 | u8 sequence_number_length; | ||
320 | u8 token_offset; | ||
321 | u8 token_length; | ||
322 | /* REMOTE_WAKE_PROTOCOL_PARAMS_API_S_VER_1 */ | ||
323 | __le32 initial_sequence_number; | ||
324 | __le16 keepalive_interval; | ||
325 | __le16 num_tokens; | ||
326 | u8 tokens[IWL_WOWLAN_REMOTE_WAKE_MAX_TOKENS]; | ||
327 | } __packed; /* REMOTE_WAKE_CONFIG_API_S_VER_2 */ | ||
328 | |||
280 | /* TODO: NetDetect API */ | 329 | /* TODO: NetDetect API */ |
281 | 330 | ||
282 | #endif /* __fw_api_d3_h__ */ | 331 | #endif /* __fw_api_d3_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h index ae39b7dfda7b..d68640ea41d4 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h index be36b7604b7f..127051891e9b 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h index aa3474d08231..fdd33bc0a594 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h index 670ac8f95e26..b60d14151721 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h index 0acb53dda22d..a30691a8a85b 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h index 2677914bf0a6..6d53850c5448 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h index 2adb61f103f4..f8d7e88234e4 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -70,6 +70,7 @@ | |||
70 | #include "fw-api-mac.h" | 70 | #include "fw-api-mac.h" |
71 | #include "fw-api-power.h" | 71 | #include "fw-api-power.h" |
72 | #include "fw-api-d3.h" | 72 | #include "fw-api-d3.h" |
73 | #include "fw-api-bt-coex.h" | ||
73 | 74 | ||
74 | /* queue and FIFO numbers by usage */ | 75 | /* queue and FIFO numbers by usage */ |
75 | enum { | 76 | enum { |
@@ -152,6 +153,7 @@ enum { | |||
152 | 153 | ||
153 | BEACON_TEMPLATE_CMD = 0x91, | 154 | BEACON_TEMPLATE_CMD = 0x91, |
154 | TX_ANT_CONFIGURATION_CMD = 0x98, | 155 | TX_ANT_CONFIGURATION_CMD = 0x98, |
156 | BT_CONFIG = 0x9b, | ||
155 | STATISTICS_NOTIFICATION = 0x9d, | 157 | STATISTICS_NOTIFICATION = 0x9d, |
156 | 158 | ||
157 | /* RF-KILL commands and notifications */ | 159 | /* RF-KILL commands and notifications */ |
@@ -162,6 +164,11 @@ enum { | |||
162 | REPLY_RX_MPDU_CMD = 0xc1, | 164 | REPLY_RX_MPDU_CMD = 0xc1, |
163 | BA_NOTIF = 0xc5, | 165 | BA_NOTIF = 0xc5, |
164 | 166 | ||
167 | /* BT Coex */ | ||
168 | BT_COEX_PRIO_TABLE = 0xcc, | ||
169 | BT_COEX_PROT_ENV = 0xcd, | ||
170 | BT_PROFILE_NOTIFICATION = 0xce, | ||
171 | |||
165 | REPLY_DEBUG_CMD = 0xf0, | 172 | REPLY_DEBUG_CMD = 0xf0, |
166 | DEBUG_LOG_MSG = 0xf7, | 173 | DEBUG_LOG_MSG = 0xf7, |
167 | 174 | ||
@@ -794,6 +801,7 @@ struct iwl_phy_context_cmd { | |||
794 | * @byte_count: frame's byte-count | 801 | * @byte_count: frame's byte-count |
795 | * @frame_time: frame's time on the air, based on byte count and frame rate | 802 | * @frame_time: frame's time on the air, based on byte count and frame rate |
796 | * calculation | 803 | * calculation |
804 | * @mac_active_msk: what MACs were active when the frame was received | ||
797 | * | 805 | * |
798 | * Before each Rx, the device sends this data. It contains PHY information | 806 | * Before each Rx, the device sends this data. It contains PHY information |
799 | * about the reception of the packet. | 807 | * about the reception of the packet. |
@@ -811,7 +819,7 @@ struct iwl_rx_phy_info { | |||
811 | __le32 non_cfg_phy[IWL_RX_INFO_PHY_CNT]; | 819 | __le32 non_cfg_phy[IWL_RX_INFO_PHY_CNT]; |
812 | __le32 rate_n_flags; | 820 | __le32 rate_n_flags; |
813 | __le32 byte_count; | 821 | __le32 byte_count; |
814 | __le16 reserved2; | 822 | __le16 mac_active_msk; |
815 | __le16 frame_time; | 823 | __le16 frame_time; |
816 | } __packed; | 824 | } __packed; |
817 | 825 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c index 500f818dba04..1006b3204e7b 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/iwlwifi/mvm/fw.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -309,6 +309,10 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) | |||
309 | goto error; | 309 | goto error; |
310 | } | 310 | } |
311 | 311 | ||
312 | ret = iwl_send_bt_prio_tbl(mvm); | ||
313 | if (ret) | ||
314 | goto error; | ||
315 | |||
312 | if (read_nvm) { | 316 | if (read_nvm) { |
313 | /* Read nvm */ | 317 | /* Read nvm */ |
314 | ret = iwl_nvm_init(mvm); | 318 | ret = iwl_nvm_init(mvm); |
@@ -414,6 +418,14 @@ int iwl_mvm_up(struct iwl_mvm *mvm) | |||
414 | if (ret) | 418 | if (ret) |
415 | goto error; | 419 | goto error; |
416 | 420 | ||
421 | ret = iwl_send_bt_prio_tbl(mvm); | ||
422 | if (ret) | ||
423 | goto error; | ||
424 | |||
425 | ret = iwl_send_bt_init_conf(mvm); | ||
426 | if (ret) | ||
427 | goto error; | ||
428 | |||
417 | /* Send phy db control command and then phy db calibration*/ | 429 | /* Send phy db control command and then phy db calibration*/ |
418 | ret = iwl_send_phy_db_data(mvm->phy_db); | 430 | ret = iwl_send_phy_db_data(mvm->phy_db); |
419 | if (ret) | 431 | if (ret) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/led.c b/drivers/net/wireless/iwlwifi/mvm/led.c index 011906e73a05..2269a9e5cc67 100644 --- a/drivers/net/wireless/iwlwifi/mvm/led.c +++ b/drivers/net/wireless/iwlwifi/mvm/led.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c index 341dbc0237ea..2779235daa35 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -553,9 +553,9 @@ static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm, | |||
553 | if (vif->bss_conf.qos) | 553 | if (vif->bss_conf.qos) |
554 | cmd->qos_flags |= cpu_to_le32(MAC_QOS_FLG_UPDATE_EDCA); | 554 | cmd->qos_flags |= cpu_to_le32(MAC_QOS_FLG_UPDATE_EDCA); |
555 | 555 | ||
556 | /* Don't use cts to self as the fw doesn't support it currently. */ | ||
556 | if (vif->bss_conf.use_cts_prot) | 557 | if (vif->bss_conf.use_cts_prot) |
557 | cmd->protection_flags |= cpu_to_le32(MAC_PROT_FLG_TGG_PROTECT | | 558 | cmd->protection_flags |= cpu_to_le32(MAC_PROT_FLG_TGG_PROTECT); |
558 | MAC_PROT_FLG_SELF_CTS_EN); | ||
559 | 559 | ||
560 | /* | 560 | /* |
561 | * I think that we should enable these 2 flags regardless the HT PROT | 561 | * I think that we should enable these 2 flags regardless the HT PROT |
@@ -651,6 +651,13 @@ static int iwl_mvm_mac_ctxt_cmd_station(struct iwl_mvm *mvm, | |||
651 | /* Fill the common data for all mac context types */ | 651 | /* Fill the common data for all mac context types */ |
652 | iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action); | 652 | iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action); |
653 | 653 | ||
654 | /* Allow beacons to pass through as long as we are not associated,or we | ||
655 | * do not have dtim period information */ | ||
656 | if (!vif->bss_conf.assoc || !vif->bss_conf.dtim_period) | ||
657 | cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_BEACON); | ||
658 | else | ||
659 | cmd.filter_flags &= ~cpu_to_le32(MAC_FILTER_IN_BEACON); | ||
660 | |||
654 | /* Fill the data specific for station mode */ | 661 | /* Fill the data specific for station mode */ |
655 | iwl_mvm_mac_ctxt_cmd_fill_sta(mvm, vif, &cmd.sta); | 662 | iwl_mvm_mac_ctxt_cmd_fill_sta(mvm, vif, &cmd.sta); |
656 | 663 | ||
@@ -714,7 +721,9 @@ static int iwl_mvm_mac_ctxt_cmd_p2p_device(struct iwl_mvm *mvm, | |||
714 | iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action); | 721 | iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action); |
715 | 722 | ||
716 | cmd.protection_flags |= cpu_to_le32(MAC_PROT_FLG_TGG_PROTECT); | 723 | cmd.protection_flags |= cpu_to_le32(MAC_PROT_FLG_TGG_PROTECT); |
717 | cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROMISC); | 724 | |
725 | /* Override the filter flags to accept only probe requests */ | ||
726 | cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST); | ||
718 | 727 | ||
719 | /* | 728 | /* |
720 | * This flag should be set to true when the P2P Device is | 729 | * This flag should be set to true when the P2P Device is |
@@ -846,10 +855,10 @@ int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm, | |||
846 | */ | 855 | */ |
847 | static void iwl_mvm_mac_ctxt_cmd_fill_ap(struct iwl_mvm *mvm, | 856 | static void iwl_mvm_mac_ctxt_cmd_fill_ap(struct iwl_mvm *mvm, |
848 | struct ieee80211_vif *vif, | 857 | struct ieee80211_vif *vif, |
849 | struct iwl_mac_data_ap *ctxt_ap) | 858 | struct iwl_mac_data_ap *ctxt_ap, |
859 | bool add) | ||
850 | { | 860 | { |
851 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 861 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
852 | u32 curr_dev_time; | ||
853 | 862 | ||
854 | ctxt_ap->bi = cpu_to_le32(vif->bss_conf.beacon_int); | 863 | ctxt_ap->bi = cpu_to_le32(vif->bss_conf.beacon_int); |
855 | ctxt_ap->bi_reciprocal = | 864 | ctxt_ap->bi_reciprocal = |
@@ -861,10 +870,19 @@ static void iwl_mvm_mac_ctxt_cmd_fill_ap(struct iwl_mvm *mvm, | |||
861 | vif->bss_conf.dtim_period)); | 870 | vif->bss_conf.dtim_period)); |
862 | 871 | ||
863 | ctxt_ap->mcast_qid = cpu_to_le32(vif->cab_queue); | 872 | ctxt_ap->mcast_qid = cpu_to_le32(vif->cab_queue); |
864 | curr_dev_time = iwl_read_prph(mvm->trans, DEVICE_SYSTEM_TIME_REG); | ||
865 | ctxt_ap->beacon_time = cpu_to_le32(curr_dev_time); | ||
866 | 873 | ||
867 | ctxt_ap->beacon_tsf = cpu_to_le64(curr_dev_time); | 874 | /* |
875 | * Only read the system time when the MAC is being added, when we | ||
876 | * just modify the MAC then we should keep the time -- the firmware | ||
877 | * can otherwise have a "jumping" TBTT. | ||
878 | */ | ||
879 | if (add) | ||
880 | mvmvif->ap_beacon_time = | ||
881 | iwl_read_prph(mvm->trans, DEVICE_SYSTEM_TIME_REG); | ||
882 | |||
883 | ctxt_ap->beacon_time = cpu_to_le32(mvmvif->ap_beacon_time); | ||
884 | |||
885 | ctxt_ap->beacon_tsf = 0; /* unused */ | ||
868 | 886 | ||
869 | /* TODO: Assume that the beacon id == mac context id */ | 887 | /* TODO: Assume that the beacon id == mac context id */ |
870 | ctxt_ap->beacon_template = cpu_to_le32(mvmvif->id); | 888 | ctxt_ap->beacon_template = cpu_to_le32(mvmvif->id); |
@@ -881,8 +899,12 @@ static int iwl_mvm_mac_ctxt_cmd_ap(struct iwl_mvm *mvm, | |||
881 | /* Fill the common data for all mac context types */ | 899 | /* Fill the common data for all mac context types */ |
882 | iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action); | 900 | iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action); |
883 | 901 | ||
902 | /* Also enable probe requests to pass */ | ||
903 | cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST); | ||
904 | |||
884 | /* Fill the data specific for ap mode */ | 905 | /* Fill the data specific for ap mode */ |
885 | iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.ap); | 906 | iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.ap, |
907 | action == FW_CTXT_ACTION_ADD); | ||
886 | 908 | ||
887 | return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd); | 909 | return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd); |
888 | } | 910 | } |
@@ -899,7 +921,8 @@ static int iwl_mvm_mac_ctxt_cmd_go(struct iwl_mvm *mvm, | |||
899 | iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action); | 921 | iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action); |
900 | 922 | ||
901 | /* Fill the data specific for GO mode */ | 923 | /* Fill the data specific for GO mode */ |
902 | iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.go.ap); | 924 | iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.go.ap, |
925 | action == FW_CTXT_ACTION_ADD); | ||
903 | 926 | ||
904 | cmd.go.ctwin = cpu_to_le32(vif->bss_conf.p2p_ctwindow); | 927 | cmd.go.ctwin = cpu_to_le32(vif->bss_conf.p2p_ctwindow); |
905 | cmd.go.opp_ps_enabled = cpu_to_le32(!!vif->bss_conf.p2p_oppps); | 928 | cmd.go.opp_ps_enabled = cpu_to_le32(!!vif->bss_conf.p2p_oppps); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 7e169b085afe..14dd5ee9a01e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -65,7 +65,9 @@ | |||
65 | #include <linux/skbuff.h> | 65 | #include <linux/skbuff.h> |
66 | #include <linux/netdevice.h> | 66 | #include <linux/netdevice.h> |
67 | #include <linux/etherdevice.h> | 67 | #include <linux/etherdevice.h> |
68 | #include <linux/ip.h> | ||
68 | #include <net/mac80211.h> | 69 | #include <net/mac80211.h> |
70 | #include <net/tcp.h> | ||
69 | 71 | ||
70 | #include "iwl-op-mode.h" | 72 | #include "iwl-op-mode.h" |
71 | #include "iwl-io.h" | 73 | #include "iwl-io.h" |
@@ -102,10 +104,33 @@ static const struct ieee80211_iface_combination iwl_mvm_iface_combinations[] = { | |||
102 | }, | 104 | }, |
103 | }; | 105 | }; |
104 | 106 | ||
107 | #ifdef CONFIG_PM_SLEEP | ||
108 | static const struct nl80211_wowlan_tcp_data_token_feature | ||
109 | iwl_mvm_wowlan_tcp_token_feature = { | ||
110 | .min_len = 0, | ||
111 | .max_len = 255, | ||
112 | .bufsize = IWL_WOWLAN_REMOTE_WAKE_MAX_TOKENS, | ||
113 | }; | ||
114 | |||
115 | static const struct wiphy_wowlan_tcp_support iwl_mvm_wowlan_tcp_support = { | ||
116 | .tok = &iwl_mvm_wowlan_tcp_token_feature, | ||
117 | .data_payload_max = IWL_WOWLAN_TCP_MAX_PACKET_LEN - | ||
118 | sizeof(struct ethhdr) - | ||
119 | sizeof(struct iphdr) - | ||
120 | sizeof(struct tcphdr), | ||
121 | .data_interval_max = 65535, /* __le16 in API */ | ||
122 | .wake_payload_max = IWL_WOWLAN_REMOTE_WAKE_MAX_PACKET_LEN - | ||
123 | sizeof(struct ethhdr) - | ||
124 | sizeof(struct iphdr) - | ||
125 | sizeof(struct tcphdr), | ||
126 | .seq = true, | ||
127 | }; | ||
128 | #endif | ||
129 | |||
105 | int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | 130 | int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) |
106 | { | 131 | { |
107 | struct ieee80211_hw *hw = mvm->hw; | 132 | struct ieee80211_hw *hw = mvm->hw; |
108 | int num_mac, ret; | 133 | int num_mac, ret, i; |
109 | 134 | ||
110 | /* Tell mac80211 our characteristics */ | 135 | /* Tell mac80211 our characteristics */ |
111 | hw->flags = IEEE80211_HW_SIGNAL_DBM | | 136 | hw->flags = IEEE80211_HW_SIGNAL_DBM | |
@@ -156,11 +181,15 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
156 | memcpy(mvm->addresses[0].addr, mvm->nvm_data->hw_addr, ETH_ALEN); | 181 | memcpy(mvm->addresses[0].addr, mvm->nvm_data->hw_addr, ETH_ALEN); |
157 | hw->wiphy->addresses = mvm->addresses; | 182 | hw->wiphy->addresses = mvm->addresses; |
158 | hw->wiphy->n_addresses = 1; | 183 | hw->wiphy->n_addresses = 1; |
159 | num_mac = mvm->nvm_data->n_hw_addrs; | 184 | |
160 | if (num_mac > 1) { | 185 | /* Extract additional MAC addresses if available */ |
161 | memcpy(mvm->addresses[1].addr, mvm->addresses[0].addr, | 186 | num_mac = (mvm->nvm_data->n_hw_addrs > 1) ? |
187 | min(IWL_MVM_MAX_ADDRESSES, mvm->nvm_data->n_hw_addrs) : 1; | ||
188 | |||
189 | for (i = 1; i < num_mac; i++) { | ||
190 | memcpy(mvm->addresses[i].addr, mvm->addresses[i-1].addr, | ||
162 | ETH_ALEN); | 191 | ETH_ALEN); |
163 | mvm->addresses[1].addr[5]++; | 192 | mvm->addresses[i].addr[5]++; |
164 | hw->wiphy->n_addresses++; | 193 | hw->wiphy->n_addresses++; |
165 | } | 194 | } |
166 | 195 | ||
@@ -206,6 +235,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
206 | hw->wiphy->wowlan.n_patterns = IWL_WOWLAN_MAX_PATTERNS; | 235 | hw->wiphy->wowlan.n_patterns = IWL_WOWLAN_MAX_PATTERNS; |
207 | hw->wiphy->wowlan.pattern_min_len = IWL_WOWLAN_MIN_PATTERN_LEN; | 236 | hw->wiphy->wowlan.pattern_min_len = IWL_WOWLAN_MIN_PATTERN_LEN; |
208 | hw->wiphy->wowlan.pattern_max_len = IWL_WOWLAN_MAX_PATTERN_LEN; | 237 | hw->wiphy->wowlan.pattern_max_len = IWL_WOWLAN_MAX_PATTERN_LEN; |
238 | hw->wiphy->wowlan.tcp = &iwl_mvm_wowlan_tcp_support; | ||
209 | } | 239 | } |
210 | #endif | 240 | #endif |
211 | 241 | ||
@@ -273,12 +303,18 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw, | |||
273 | ret = iwl_mvm_sta_rx_agg(mvm, sta, tid, 0, false); | 303 | ret = iwl_mvm_sta_rx_agg(mvm, sta, tid, 0, false); |
274 | break; | 304 | break; |
275 | case IEEE80211_AMPDU_TX_START: | 305 | case IEEE80211_AMPDU_TX_START: |
306 | if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG) { | ||
307 | ret = -EINVAL; | ||
308 | break; | ||
309 | } | ||
276 | ret = iwl_mvm_sta_tx_agg_start(mvm, vif, sta, tid, ssn); | 310 | ret = iwl_mvm_sta_tx_agg_start(mvm, vif, sta, tid, ssn); |
277 | break; | 311 | break; |
278 | case IEEE80211_AMPDU_TX_STOP_CONT: | 312 | case IEEE80211_AMPDU_TX_STOP_CONT: |
313 | ret = iwl_mvm_sta_tx_agg_stop(mvm, vif, sta, tid); | ||
314 | break; | ||
279 | case IEEE80211_AMPDU_TX_STOP_FLUSH: | 315 | case IEEE80211_AMPDU_TX_STOP_FLUSH: |
280 | case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: | 316 | case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: |
281 | ret = iwl_mvm_sta_tx_agg_stop(mvm, vif, sta, tid); | 317 | ret = iwl_mvm_sta_tx_agg_flush(mvm, vif, sta, tid); |
282 | break; | 318 | break; |
283 | case IEEE80211_AMPDU_TX_OPERATIONAL: | 319 | case IEEE80211_AMPDU_TX_OPERATIONAL: |
284 | ret = iwl_mvm_sta_tx_agg_oper(mvm, vif, sta, tid, buf_size); | 320 | ret = iwl_mvm_sta_tx_agg_oper(mvm, vif, sta, tid, buf_size); |
@@ -1090,7 +1126,8 @@ static void iwl_mvm_mac_update_tkip_key(struct ieee80211_hw *hw, | |||
1090 | static int iwl_mvm_roc(struct ieee80211_hw *hw, | 1126 | static int iwl_mvm_roc(struct ieee80211_hw *hw, |
1091 | struct ieee80211_vif *vif, | 1127 | struct ieee80211_vif *vif, |
1092 | struct ieee80211_channel *channel, | 1128 | struct ieee80211_channel *channel, |
1093 | int duration) | 1129 | int duration, |
1130 | enum ieee80211_roc_type type) | ||
1094 | { | 1131 | { |
1095 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | 1132 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
1096 | struct cfg80211_chan_def chandef; | 1133 | struct cfg80211_chan_def chandef; |
@@ -1101,8 +1138,8 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw, | |||
1101 | return -EINVAL; | 1138 | return -EINVAL; |
1102 | } | 1139 | } |
1103 | 1140 | ||
1104 | IWL_DEBUG_MAC80211(mvm, "enter (%d, %d)\n", channel->hw_value, | 1141 | IWL_DEBUG_MAC80211(mvm, "enter (%d, %d, %d)\n", channel->hw_value, |
1105 | duration); | 1142 | duration, type); |
1106 | 1143 | ||
1107 | mutex_lock(&mvm->mutex); | 1144 | mutex_lock(&mvm->mutex); |
1108 | 1145 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index bdae700c769e..203eb85e03d3 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -79,7 +79,7 @@ | |||
79 | #include "fw-api.h" | 79 | #include "fw-api.h" |
80 | 80 | ||
81 | #define IWL_INVALID_MAC80211_QUEUE 0xff | 81 | #define IWL_INVALID_MAC80211_QUEUE 0xff |
82 | #define IWL_MVM_MAX_ADDRESSES 2 | 82 | #define IWL_MVM_MAX_ADDRESSES 5 |
83 | /* RSSI offset for WkP */ | 83 | /* RSSI offset for WkP */ |
84 | #define IWL_RSSI_OFFSET 50 | 84 | #define IWL_RSSI_OFFSET 50 |
85 | 85 | ||
@@ -174,6 +174,8 @@ struct iwl_mvm_vif { | |||
174 | bool uploaded; | 174 | bool uploaded; |
175 | bool ap_active; | 175 | bool ap_active; |
176 | 176 | ||
177 | u32 ap_beacon_time; | ||
178 | |||
177 | enum iwl_tsf_id tsf_id; | 179 | enum iwl_tsf_id tsf_id; |
178 | 180 | ||
179 | /* | 181 | /* |
@@ -332,6 +334,10 @@ struct iwl_mvm { | |||
332 | #ifdef CONFIG_PM_SLEEP | 334 | #ifdef CONFIG_PM_SLEEP |
333 | int gtk_ivlen, gtk_icvlen, ptk_ivlen, ptk_icvlen; | 335 | int gtk_ivlen, gtk_icvlen, ptk_ivlen, ptk_icvlen; |
334 | #endif | 336 | #endif |
337 | |||
338 | /* BT-Coex */ | ||
339 | u8 bt_kill_msk; | ||
340 | struct iwl_bt_coex_profile_notif last_bt_notif; | ||
335 | }; | 341 | }; |
336 | 342 | ||
337 | /* Extract MVM priv from op_mode and _hw */ | 343 | /* Extract MVM priv from op_mode and _hw */ |
@@ -502,4 +508,11 @@ void iwl_mvm_ipv6_addr_change(struct ieee80211_hw *hw, | |||
502 | void iwl_mvm_set_default_unicast_key(struct ieee80211_hw *hw, | 508 | void iwl_mvm_set_default_unicast_key(struct ieee80211_hw *hw, |
503 | struct ieee80211_vif *vif, int idx); | 509 | struct ieee80211_vif *vif, int idx); |
504 | 510 | ||
511 | /* BT Coex */ | ||
512 | int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm); | ||
513 | int iwl_send_bt_init_conf(struct iwl_mvm *mvm); | ||
514 | int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm, | ||
515 | struct iwl_rx_cmd_buffer *rxb, | ||
516 | struct iwl_device_cmd *cmd); | ||
517 | |||
505 | #endif /* __IWL_MVM_H__ */ | 518 | #endif /* __IWL_MVM_H__ */ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c index 20016bcbdeab..93e3d0f174cc 100644 --- a/drivers/net/wireless/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -74,6 +74,9 @@ static const int nvm_to_read[] = { | |||
74 | NVM_SECTION_TYPE_PRODUCTION, | 74 | NVM_SECTION_TYPE_PRODUCTION, |
75 | }; | 75 | }; |
76 | 76 | ||
77 | /* Default NVM size to read */ | ||
78 | #define IWL_NVM_DEFAULT_CHUNK_SIZE (2*1024); | ||
79 | |||
77 | /* used to simplify the shared operations on NCM_ACCESS_CMD versions */ | 80 | /* used to simplify the shared operations on NCM_ACCESS_CMD versions */ |
78 | union iwl_nvm_access_cmd { | 81 | union iwl_nvm_access_cmd { |
79 | struct iwl_nvm_access_cmd_ver1 ver1; | 82 | struct iwl_nvm_access_cmd_ver1 ver1; |
@@ -193,9 +196,9 @@ static int iwl_nvm_read_section(struct iwl_mvm *mvm, u16 section, | |||
193 | int ret; | 196 | int ret; |
194 | bool old_eeprom = mvm->cfg->device_family != IWL_DEVICE_FAMILY_7000; | 197 | bool old_eeprom = mvm->cfg->device_family != IWL_DEVICE_FAMILY_7000; |
195 | 198 | ||
196 | length = (iwlwifi_mod_params.amsdu_size_8K ? (8 * 1024) : (4 * 1024)) | 199 | /* Set nvm section read length */ |
197 | - sizeof(union iwl_nvm_access_cmd) | 200 | length = IWL_NVM_DEFAULT_CHUNK_SIZE; |
198 | - sizeof(struct iwl_rx_packet); | 201 | |
199 | /* | 202 | /* |
200 | * if length is greater than EEPROM size, truncate it because uCode | 203 | * if length is greater than EEPROM size, truncate it because uCode |
201 | * doesn't check it by itself, and exit the loop when reached. | 204 | * doesn't check it by itself, and exit the loop when reached. |
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index d0f9c1e0475e..828bdddd07e9 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -230,6 +230,8 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { | |||
230 | RX_HANDLER(SCAN_REQUEST_CMD, iwl_mvm_rx_scan_response, false), | 230 | RX_HANDLER(SCAN_REQUEST_CMD, iwl_mvm_rx_scan_response, false), |
231 | RX_HANDLER(SCAN_COMPLETE_NOTIFICATION, iwl_mvm_rx_scan_complete, false), | 231 | RX_HANDLER(SCAN_COMPLETE_NOTIFICATION, iwl_mvm_rx_scan_complete, false), |
232 | 232 | ||
233 | RX_HANDLER(BT_PROFILE_NOTIFICATION, iwl_mvm_rx_bt_coex_notif, true), | ||
234 | |||
233 | RX_HANDLER(RADIO_VERSION_NOTIFICATION, iwl_mvm_rx_radio_ver, false), | 235 | RX_HANDLER(RADIO_VERSION_NOTIFICATION, iwl_mvm_rx_radio_ver, false), |
234 | RX_HANDLER(CARD_STATE_NOTIFICATION, iwl_mvm_rx_card_state_notif, false), | 236 | RX_HANDLER(CARD_STATE_NOTIFICATION, iwl_mvm_rx_card_state_notif, false), |
235 | 237 | ||
@@ -293,6 +295,11 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = { | |||
293 | CMD(NET_DETECT_PROFILES_CMD), | 295 | CMD(NET_DETECT_PROFILES_CMD), |
294 | CMD(NET_DETECT_HOTSPOTS_CMD), | 296 | CMD(NET_DETECT_HOTSPOTS_CMD), |
295 | CMD(NET_DETECT_HOTSPOTS_QUERY_CMD), | 297 | CMD(NET_DETECT_HOTSPOTS_QUERY_CMD), |
298 | CMD(CARD_STATE_NOTIFICATION), | ||
299 | CMD(BT_COEX_PRIO_TABLE), | ||
300 | CMD(BT_COEX_PROT_ENV), | ||
301 | CMD(BT_PROFILE_NOTIFICATION), | ||
302 | CMD(BT_CONFIG), | ||
296 | }; | 303 | }; |
297 | #undef CMD | 304 | #undef CMD |
298 | 305 | ||
@@ -363,8 +370,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
363 | trans_cfg.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds); | 370 | trans_cfg.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds); |
364 | trans_cfg.rx_buf_size_8k = iwlwifi_mod_params.amsdu_size_8K; | 371 | trans_cfg.rx_buf_size_8k = iwlwifi_mod_params.amsdu_size_8K; |
365 | 372 | ||
366 | /* TODO: this should really be a TLV */ | 373 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DW_BC_TABLE) |
367 | if (cfg->device_family == IWL_DEVICE_FAMILY_7000) | ||
368 | trans_cfg.bc_table_dword = true; | 374 | trans_cfg.bc_table_dword = true; |
369 | 375 | ||
370 | if (!iwlwifi_mod_params.wd_disable) | 376 | if (!iwlwifi_mod_params.wd_disable) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c index b428448f8ddf..0d537e035ef0 100644 --- a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c index 5a92a4978795..efb9a6f3faac 100644 --- a/drivers/net/wireless/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/iwlwifi/mvm/power.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/mvm/quota.c b/drivers/net/wireless/iwlwifi/mvm/quota.c index 925628468146..df85c49dc599 100644 --- a/drivers/net/wireless/iwlwifi/mvm/quota.c +++ b/drivers/net/wireless/iwlwifi/mvm/quota.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 56b636d9ab30..a01a6612677e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c | |||
@@ -680,12 +680,14 @@ static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags, | |||
680 | */ | 680 | */ |
681 | static bool rs_use_green(struct ieee80211_sta *sta) | 681 | static bool rs_use_green(struct ieee80211_sta *sta) |
682 | { | 682 | { |
683 | struct iwl_mvm_sta *sta_priv = (void *)sta->drv_priv; | 683 | /* |
684 | 684 | * There's a bug somewhere in this code that causes the | |
685 | bool use_green = !(sta_priv->vif->bss_conf.ht_operation_mode & | 685 | * scaling to get stuck because GF+SGI can't be combined |
686 | IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); | 686 | * in SISO rates. Until we find that bug, disable GF, it |
687 | 687 | * has only limited benefit and we still interoperate with | |
688 | return (sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) && use_green; | 688 | * GF APs since we can always receive GF transmissions. |
689 | */ | ||
690 | return false; | ||
689 | } | 691 | } |
690 | 692 | ||
691 | /** | 693 | /** |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c index b0b190d0ec23..4dfc21a3e83e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/iwlwifi/mvm/rx.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index 9b21b92aa8d1..0d3c76b29242 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index 274f44e2ef60..4d872d69577f 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -101,8 +101,55 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
101 | } | 101 | } |
102 | add_sta_cmd.add_modify = update ? 1 : 0; | 102 | add_sta_cmd.add_modify = update ? 1 : 0; |
103 | 103 | ||
104 | /* STA_FLG_FAT_EN_MSK ? */ | 104 | add_sta_cmd.station_flags_msk |= cpu_to_le32(STA_FLG_FAT_EN_MSK | |
105 | /* STA_FLG_MIMO_EN_MSK ? */ | 105 | STA_FLG_MIMO_EN_MSK); |
106 | |||
107 | switch (sta->bandwidth) { | ||
108 | case IEEE80211_STA_RX_BW_160: | ||
109 | add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_FAT_EN_160MHZ); | ||
110 | /* fall through */ | ||
111 | case IEEE80211_STA_RX_BW_80: | ||
112 | add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_FAT_EN_80MHZ); | ||
113 | /* fall through */ | ||
114 | case IEEE80211_STA_RX_BW_40: | ||
115 | add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_FAT_EN_40MHZ); | ||
116 | /* fall through */ | ||
117 | case IEEE80211_STA_RX_BW_20: | ||
118 | if (sta->ht_cap.ht_supported) | ||
119 | add_sta_cmd.station_flags |= | ||
120 | cpu_to_le32(STA_FLG_FAT_EN_20MHZ); | ||
121 | break; | ||
122 | } | ||
123 | |||
124 | switch (sta->rx_nss) { | ||
125 | case 1: | ||
126 | add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_MIMO_EN_SISO); | ||
127 | break; | ||
128 | case 2: | ||
129 | add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_MIMO_EN_MIMO2); | ||
130 | break; | ||
131 | case 3 ... 8: | ||
132 | add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_MIMO_EN_MIMO3); | ||
133 | break; | ||
134 | } | ||
135 | |||
136 | switch (sta->smps_mode) { | ||
137 | case IEEE80211_SMPS_AUTOMATIC: | ||
138 | case IEEE80211_SMPS_NUM_MODES: | ||
139 | WARN_ON(1); | ||
140 | break; | ||
141 | case IEEE80211_SMPS_STATIC: | ||
142 | /* override NSS */ | ||
143 | add_sta_cmd.station_flags &= ~cpu_to_le32(STA_FLG_MIMO_EN_MSK); | ||
144 | add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_MIMO_EN_SISO); | ||
145 | break; | ||
146 | case IEEE80211_SMPS_DYNAMIC: | ||
147 | add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_RTS_MIMO_PROT); | ||
148 | break; | ||
149 | case IEEE80211_SMPS_OFF: | ||
150 | /* nothing */ | ||
151 | break; | ||
152 | } | ||
106 | 153 | ||
107 | if (sta->ht_cap.ht_supported) { | 154 | if (sta->ht_cap.ht_supported) { |
108 | add_sta_cmd.station_flags_msk |= | 155 | add_sta_cmd.station_flags_msk |= |
@@ -340,6 +387,9 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm, | |||
340 | 387 | ||
341 | if (vif->type == NL80211_IFTYPE_STATION && | 388 | if (vif->type == NL80211_IFTYPE_STATION && |
342 | mvmvif->ap_sta_id == mvm_sta->sta_id) { | 389 | mvmvif->ap_sta_id == mvm_sta->sta_id) { |
390 | /* flush its queues here since we are freeing mvm_sta */ | ||
391 | ret = iwl_mvm_flush_tx_path(mvm, mvm_sta->tfd_queue_msk, true); | ||
392 | |||
343 | /* | 393 | /* |
344 | * Put a non-NULL since the fw station isn't removed. | 394 | * Put a non-NULL since the fw station isn't removed. |
345 | * It will be removed after the MAC will be set as | 395 | * It will be removed after the MAC will be set as |
@@ -348,9 +398,6 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm, | |||
348 | rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id], | 398 | rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id], |
349 | ERR_PTR(-EINVAL)); | 399 | ERR_PTR(-EINVAL)); |
350 | 400 | ||
351 | /* flush its queues here since we are freeing mvm_sta */ | ||
352 | ret = iwl_mvm_flush_tx_path(mvm, mvm_sta->tfd_queue_msk, true); | ||
353 | |||
354 | /* if we are associated - we can't remove the AP STA now */ | 401 | /* if we are associated - we can't remove the AP STA now */ |
355 | if (vif->bss_conf.assoc) | 402 | if (vif->bss_conf.assoc) |
356 | return ret; | 403 | return ret; |
@@ -686,7 +733,7 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
686 | 733 | ||
687 | spin_lock_bh(&mvmsta->lock); | 734 | spin_lock_bh(&mvmsta->lock); |
688 | tid_data = &mvmsta->tid_data[tid]; | 735 | tid_data = &mvmsta->tid_data[tid]; |
689 | tid_data->ssn = SEQ_TO_SN(tid_data->seq_number); | 736 | tid_data->ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number); |
690 | tid_data->txq_id = txq_id; | 737 | tid_data->txq_id = txq_id; |
691 | *ssn = tid_data->ssn; | 738 | *ssn = tid_data->ssn; |
692 | 739 | ||
@@ -789,7 +836,7 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
789 | 836 | ||
790 | switch (tid_data->state) { | 837 | switch (tid_data->state) { |
791 | case IWL_AGG_ON: | 838 | case IWL_AGG_ON: |
792 | tid_data->ssn = SEQ_TO_SN(tid_data->seq_number); | 839 | tid_data->ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number); |
793 | 840 | ||
794 | IWL_DEBUG_TX_QUEUES(mvm, | 841 | IWL_DEBUG_TX_QUEUES(mvm, |
795 | "ssn = %d, next_recl = %d\n", | 842 | "ssn = %d, next_recl = %d\n", |
@@ -834,6 +881,34 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
834 | return err; | 881 | return err; |
835 | } | 882 | } |
836 | 883 | ||
884 | int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | ||
885 | struct ieee80211_sta *sta, u16 tid) | ||
886 | { | ||
887 | struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv; | ||
888 | struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid]; | ||
889 | u16 txq_id; | ||
890 | |||
891 | /* | ||
892 | * First set the agg state to OFF to avoid calling | ||
893 | * ieee80211_stop_tx_ba_cb in iwl_mvm_check_ratid_empty. | ||
894 | */ | ||
895 | spin_lock_bh(&mvmsta->lock); | ||
896 | txq_id = tid_data->txq_id; | ||
897 | IWL_DEBUG_TX_QUEUES(mvm, "Flush AGG: sta %d tid %d q %d state %d\n", | ||
898 | mvmsta->sta_id, tid, txq_id, tid_data->state); | ||
899 | tid_data->state = IWL_AGG_OFF; | ||
900 | spin_unlock_bh(&mvmsta->lock); | ||
901 | |||
902 | if (iwl_mvm_flush_tx_path(mvm, BIT(txq_id), true)) | ||
903 | IWL_ERR(mvm, "Couldn't flush the AGG queue\n"); | ||
904 | |||
905 | iwl_trans_txq_disable(mvm->trans, tid_data->txq_id); | ||
906 | mvm->queue_to_mac80211[tid_data->txq_id] = | ||
907 | IWL_INVALID_MAC80211_QUEUE; | ||
908 | |||
909 | return 0; | ||
910 | } | ||
911 | |||
837 | static int iwl_mvm_set_fw_key_idx(struct iwl_mvm *mvm) | 912 | static int iwl_mvm_set_fw_key_idx(struct iwl_mvm *mvm) |
838 | { | 913 | { |
839 | int i; | 914 | int i; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.h b/drivers/net/wireless/iwlwifi/mvm/sta.h index 896f88ac8145..b0352df981e4 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.h +++ b/drivers/net/wireless/iwlwifi/mvm/sta.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -348,6 +348,8 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
348 | struct ieee80211_sta *sta, u16 tid, u8 buf_size); | 348 | struct ieee80211_sta *sta, u16 tid, u8 buf_size); |
349 | int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 349 | int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
350 | struct ieee80211_sta *sta, u16 tid); | 350 | struct ieee80211_sta *sta, u16 tid); |
351 | int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | ||
352 | struct ieee80211_sta *sta, u16 tid); | ||
351 | 353 | ||
352 | int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm); | 354 | int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm); |
353 | int iwl_mvm_allocate_int_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *sta, | 355 | int iwl_mvm_allocate_int_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *sta, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c index e437e02c7149..c2c7f5176027 100644 --- a/drivers/net/wireless/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.h b/drivers/net/wireless/iwlwifi/mvm/time-event.h index 64fb57a5ab43..b36424eda361 100644 --- a/drivers/net/wireless/iwlwifi/mvm/time-event.h +++ b/drivers/net/wireless/iwlwifi/mvm/time-event.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c index 6645efe5c03e..0556d5e16f4e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/iwlwifi/mvm/tx.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -637,7 +637,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, | |||
637 | next_reclaimed = ssn; | 637 | next_reclaimed = ssn; |
638 | } else { | 638 | } else { |
639 | /* The next packet to be reclaimed is the one after this one */ | 639 | /* The next packet to be reclaimed is the one after this one */ |
640 | next_reclaimed = SEQ_TO_SN(seq_ctl + 0x10); | 640 | next_reclaimed = IEEE80211_SEQ_TO_SN(seq_ctl + 0x10); |
641 | } | 641 | } |
642 | 642 | ||
643 | IWL_DEBUG_TX_REPLY(mvm, | 643 | IWL_DEBUG_TX_REPLY(mvm, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c index 000e842c2edd..e308ad93aa9e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/iwlwifi/mvm/utils.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
diff --git a/drivers/net/wireless/iwlwifi/pcie/cfg.h b/drivers/net/wireless/iwlwifi/pcie/cfg.h deleted file mode 100644 index c6f8e83c3551..000000000000 --- a/drivers/net/wireless/iwlwifi/pcie/cfg.h +++ /dev/null | |||
@@ -1,115 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2007 - 2013 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | * | ||
62 | *****************************************************************************/ | ||
63 | #ifndef __iwl_pci_h__ | ||
64 | #define __iwl_pci_h__ | ||
65 | |||
66 | |||
67 | /* | ||
68 | * This file declares the config structures for all devices. | ||
69 | */ | ||
70 | |||
71 | extern const struct iwl_cfg iwl5300_agn_cfg; | ||
72 | extern const struct iwl_cfg iwl5100_agn_cfg; | ||
73 | extern const struct iwl_cfg iwl5350_agn_cfg; | ||
74 | extern const struct iwl_cfg iwl5100_bgn_cfg; | ||
75 | extern const struct iwl_cfg iwl5100_abg_cfg; | ||
76 | extern const struct iwl_cfg iwl5150_agn_cfg; | ||
77 | extern const struct iwl_cfg iwl5150_abg_cfg; | ||
78 | extern const struct iwl_cfg iwl6005_2agn_cfg; | ||
79 | extern const struct iwl_cfg iwl6005_2abg_cfg; | ||
80 | extern const struct iwl_cfg iwl6005_2bg_cfg; | ||
81 | extern const struct iwl_cfg iwl6005_2agn_sff_cfg; | ||
82 | extern const struct iwl_cfg iwl6005_2agn_d_cfg; | ||
83 | extern const struct iwl_cfg iwl6005_2agn_mow1_cfg; | ||
84 | extern const struct iwl_cfg iwl6005_2agn_mow2_cfg; | ||
85 | extern const struct iwl_cfg iwl1030_bgn_cfg; | ||
86 | extern const struct iwl_cfg iwl1030_bg_cfg; | ||
87 | extern const struct iwl_cfg iwl6030_2agn_cfg; | ||
88 | extern const struct iwl_cfg iwl6030_2abg_cfg; | ||
89 | extern const struct iwl_cfg iwl6030_2bgn_cfg; | ||
90 | extern const struct iwl_cfg iwl6030_2bg_cfg; | ||
91 | extern const struct iwl_cfg iwl6000i_2agn_cfg; | ||
92 | extern const struct iwl_cfg iwl6000i_2abg_cfg; | ||
93 | extern const struct iwl_cfg iwl6000i_2bg_cfg; | ||
94 | extern const struct iwl_cfg iwl6000_3agn_cfg; | ||
95 | extern const struct iwl_cfg iwl6050_2agn_cfg; | ||
96 | extern const struct iwl_cfg iwl6050_2abg_cfg; | ||
97 | extern const struct iwl_cfg iwl6150_bgn_cfg; | ||
98 | extern const struct iwl_cfg iwl6150_bg_cfg; | ||
99 | extern const struct iwl_cfg iwl1000_bgn_cfg; | ||
100 | extern const struct iwl_cfg iwl1000_bg_cfg; | ||
101 | extern const struct iwl_cfg iwl100_bgn_cfg; | ||
102 | extern const struct iwl_cfg iwl100_bg_cfg; | ||
103 | extern const struct iwl_cfg iwl130_bgn_cfg; | ||
104 | extern const struct iwl_cfg iwl130_bg_cfg; | ||
105 | extern const struct iwl_cfg iwl2000_2bgn_cfg; | ||
106 | extern const struct iwl_cfg iwl2000_2bgn_d_cfg; | ||
107 | extern const struct iwl_cfg iwl2030_2bgn_cfg; | ||
108 | extern const struct iwl_cfg iwl6035_2agn_cfg; | ||
109 | extern const struct iwl_cfg iwl105_bgn_cfg; | ||
110 | extern const struct iwl_cfg iwl105_bgn_d_cfg; | ||
111 | extern const struct iwl_cfg iwl135_bgn_cfg; | ||
112 | extern const struct iwl_cfg iwl7260_2ac_cfg; | ||
113 | extern const struct iwl_cfg iwl3160_ac_cfg; | ||
114 | |||
115 | #endif /* __iwl_pci_h__ */ | ||
diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c index 7bc0fb9128dd..46ca91f77c9c 100644 --- a/drivers/net/wireless/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/iwlwifi/pcie/drv.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -69,8 +69,6 @@ | |||
69 | 69 | ||
70 | #include "iwl-trans.h" | 70 | #include "iwl-trans.h" |
71 | #include "iwl-drv.h" | 71 | #include "iwl-drv.h" |
72 | |||
73 | #include "cfg.h" | ||
74 | #include "internal.h" | 72 | #include "internal.h" |
75 | 73 | ||
76 | #define IWL_PCI_DEVICE(dev, subdev, cfg) \ | 74 | #define IWL_PCI_DEVICE(dev, subdev, cfg) \ |
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index 17bedc50e753..6649e377e9cd 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * USA | 22 | * USA |
23 | * | 23 | * |
24 | * The full GNU General Public License is included in this distribution | 24 | * The full GNU General Public License is included in this distribution |
25 | * in the file called LICENSE.GPL. | 25 | * in the file called COPYING. |
26 | * | 26 | * |
27 | * Contact Information: | 27 | * Contact Information: |
28 | * Intel Linux Wireless <ilw@linux.intel.com> | 28 | * Intel Linux Wireless <ilw@linux.intel.com> |
@@ -715,7 +715,8 @@ static u32 iwl_trans_pcie_read32(struct iwl_trans *trans, u32 ofs) | |||
715 | 715 | ||
716 | static u32 iwl_trans_pcie_read_prph(struct iwl_trans *trans, u32 reg) | 716 | static u32 iwl_trans_pcie_read_prph(struct iwl_trans *trans, u32 reg) |
717 | { | 717 | { |
718 | iwl_trans_pcie_write32(trans, HBUS_TARG_PRPH_RADDR, reg | (3 << 24)); | 718 | iwl_trans_pcie_write32(trans, HBUS_TARG_PRPH_RADDR, |
719 | ((reg & 0x000FFFFF) | (3 << 24))); | ||
719 | return iwl_trans_pcie_read32(trans, HBUS_TARG_PRPH_RDAT); | 720 | return iwl_trans_pcie_read32(trans, HBUS_TARG_PRPH_RDAT); |
720 | } | 721 | } |
721 | 722 | ||
@@ -723,7 +724,7 @@ static void iwl_trans_pcie_write_prph(struct iwl_trans *trans, u32 addr, | |||
723 | u32 val) | 724 | u32 val) |
724 | { | 725 | { |
725 | iwl_trans_pcie_write32(trans, HBUS_TARG_PRPH_WADDR, | 726 | iwl_trans_pcie_write32(trans, HBUS_TARG_PRPH_WADDR, |
726 | ((addr & 0x0000FFFF) | (3 << 24))); | 727 | ((addr & 0x000FFFFF) | (3 << 24))); |
727 | iwl_trans_pcie_write32(trans, HBUS_TARG_PRPH_WDAT, val); | 728 | iwl_trans_pcie_write32(trans, HBUS_TARG_PRPH_WDAT, val); |
728 | } | 729 | } |
729 | 730 | ||
@@ -1370,28 +1371,11 @@ static ssize_t iwl_dbgfs_fh_reg_read(struct file *file, | |||
1370 | return ret; | 1371 | return ret; |
1371 | } | 1372 | } |
1372 | 1373 | ||
1373 | static ssize_t iwl_dbgfs_fw_restart_write(struct file *file, | ||
1374 | const char __user *user_buf, | ||
1375 | size_t count, loff_t *ppos) | ||
1376 | { | ||
1377 | struct iwl_trans *trans = file->private_data; | ||
1378 | |||
1379 | if (!trans->op_mode) | ||
1380 | return -EAGAIN; | ||
1381 | |||
1382 | local_bh_disable(); | ||
1383 | iwl_op_mode_nic_error(trans->op_mode); | ||
1384 | local_bh_enable(); | ||
1385 | |||
1386 | return count; | ||
1387 | } | ||
1388 | |||
1389 | DEBUGFS_READ_WRITE_FILE_OPS(interrupt); | 1374 | DEBUGFS_READ_WRITE_FILE_OPS(interrupt); |
1390 | DEBUGFS_READ_FILE_OPS(fh_reg); | 1375 | DEBUGFS_READ_FILE_OPS(fh_reg); |
1391 | DEBUGFS_READ_FILE_OPS(rx_queue); | 1376 | DEBUGFS_READ_FILE_OPS(rx_queue); |
1392 | DEBUGFS_READ_FILE_OPS(tx_queue); | 1377 | DEBUGFS_READ_FILE_OPS(tx_queue); |
1393 | DEBUGFS_WRITE_FILE_OPS(csr); | 1378 | DEBUGFS_WRITE_FILE_OPS(csr); |
1394 | DEBUGFS_WRITE_FILE_OPS(fw_restart); | ||
1395 | 1379 | ||
1396 | /* | 1380 | /* |
1397 | * Create the debugfs files and directories | 1381 | * Create the debugfs files and directories |
@@ -1405,7 +1389,6 @@ static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, | |||
1405 | DEBUGFS_ADD_FILE(interrupt, dir, S_IWUSR | S_IRUSR); | 1389 | DEBUGFS_ADD_FILE(interrupt, dir, S_IWUSR | S_IRUSR); |
1406 | DEBUGFS_ADD_FILE(csr, dir, S_IWUSR); | 1390 | DEBUGFS_ADD_FILE(csr, dir, S_IWUSR); |
1407 | DEBUGFS_ADD_FILE(fh_reg, dir, S_IRUSR); | 1391 | DEBUGFS_ADD_FILE(fh_reg, dir, S_IRUSR); |
1408 | DEBUGFS_ADD_FILE(fw_restart, dir, S_IWUSR); | ||
1409 | return 0; | 1392 | return 0; |
1410 | 1393 | ||
1411 | err: | 1394 | err: |
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index 7a508d835f5a..005e2cfb2f41 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c | |||
@@ -1607,7 +1607,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, | |||
1607 | * Check here that the packets are in the right place on the ring. | 1607 | * Check here that the packets are in the right place on the ring. |
1608 | */ | 1608 | */ |
1609 | #ifdef CONFIG_IWLWIFI_DEBUG | 1609 | #ifdef CONFIG_IWLWIFI_DEBUG |
1610 | wifi_seq = SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); | 1610 | wifi_seq = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); |
1611 | WARN_ONCE((iwl_read_prph(trans, SCD_AGGR_SEL) & BIT(txq_id)) && | 1611 | WARN_ONCE((iwl_read_prph(trans, SCD_AGGR_SEL) & BIT(txq_id)) && |
1612 | ((wifi_seq & 0xff) != q->write_ptr), | 1612 | ((wifi_seq & 0xff) != q->write_ptr), |
1613 | "Q: %d WiFi Seq %d tfdNum %d", | 1613 | "Q: %d WiFi Seq %d tfdNum %d", |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index cffdf4fbf161..7490c4fc7177 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -1535,7 +1535,8 @@ static void hw_roc_done(struct work_struct *work) | |||
1535 | static int mac80211_hwsim_roc(struct ieee80211_hw *hw, | 1535 | static int mac80211_hwsim_roc(struct ieee80211_hw *hw, |
1536 | struct ieee80211_vif *vif, | 1536 | struct ieee80211_vif *vif, |
1537 | struct ieee80211_channel *chan, | 1537 | struct ieee80211_channel *chan, |
1538 | int duration) | 1538 | int duration, |
1539 | enum ieee80211_roc_type type) | ||
1539 | { | 1540 | { |
1540 | struct mac80211_hwsim_data *hwsim = hw->priv; | 1541 | struct mac80211_hwsim_data *hwsim = hw->priv; |
1541 | 1542 | ||
diff --git a/drivers/net/wireless/mwifiex/Makefile b/drivers/net/wireless/mwifiex/Makefile index 97b245cbafd8..ecf28464367f 100644 --- a/drivers/net/wireless/mwifiex/Makefile +++ b/drivers/net/wireless/mwifiex/Makefile | |||
@@ -39,6 +39,7 @@ mwifiex-y += sta_tx.o | |||
39 | mwifiex-y += sta_rx.o | 39 | mwifiex-y += sta_rx.o |
40 | mwifiex-y += uap_txrx.o | 40 | mwifiex-y += uap_txrx.o |
41 | mwifiex-y += cfg80211.o | 41 | mwifiex-y += cfg80211.o |
42 | mwifiex-y += ethtool.o | ||
42 | mwifiex-$(CONFIG_DEBUG_FS) += debugfs.o | 43 | mwifiex-$(CONFIG_DEBUG_FS) += debugfs.o |
43 | obj-$(CONFIG_MWIFIEX) += mwifiex.o | 44 | obj-$(CONFIG_MWIFIEX) += mwifiex.o |
44 | 45 | ||
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index a44023a7bd57..dbf5b1289516 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
@@ -1932,66 +1932,10 @@ static void mwifiex_setup_vht_caps(struct ieee80211_sta_vht_cap *vht_info, | |||
1932 | struct mwifiex_private *priv) | 1932 | struct mwifiex_private *priv) |
1933 | { | 1933 | { |
1934 | struct mwifiex_adapter *adapter = priv->adapter; | 1934 | struct mwifiex_adapter *adapter = priv->adapter; |
1935 | u32 vht_cap = 0, cap = adapter->hw_dot_11ac_dev_cap; | ||
1936 | 1935 | ||
1937 | vht_info->vht_supported = true; | 1936 | vht_info->vht_supported = true; |
1938 | 1937 | ||
1939 | switch (GET_VHTCAP_MAXMPDULEN(cap)) { | 1938 | vht_info->cap = adapter->hw_dot_11ac_dev_cap; |
1940 | case 0x00: | ||
1941 | vht_cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895; | ||
1942 | break; | ||
1943 | case 0x01: | ||
1944 | vht_cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991; | ||
1945 | break; | ||
1946 | case 0x10: | ||
1947 | vht_cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454; | ||
1948 | break; | ||
1949 | default: | ||
1950 | dev_err(adapter->dev, "unsupported MAX MPDU len\n"); | ||
1951 | break; | ||
1952 | } | ||
1953 | |||
1954 | if (ISSUPP_11ACVHTHTCVHT(cap)) | ||
1955 | vht_cap |= IEEE80211_VHT_CAP_HTC_VHT; | ||
1956 | |||
1957 | if (ISSUPP_11ACVHTTXOPPS(cap)) | ||
1958 | vht_cap |= IEEE80211_VHT_CAP_VHT_TXOP_PS; | ||
1959 | |||
1960 | if (ISSUPP_11ACMURXBEAMFORMEE(cap)) | ||
1961 | vht_cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE; | ||
1962 | |||
1963 | if (ISSUPP_11ACMUTXBEAMFORMEE(cap)) | ||
1964 | vht_cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE; | ||
1965 | |||
1966 | if (ISSUPP_11ACSUBEAMFORMER(cap)) | ||
1967 | vht_cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE; | ||
1968 | |||
1969 | if (ISSUPP_11ACSUBEAMFORMEE(cap)) | ||
1970 | vht_cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE; | ||
1971 | |||
1972 | if (ISSUPP_11ACRXSTBC(cap)) | ||
1973 | vht_cap |= IEEE80211_VHT_CAP_RXSTBC_1; | ||
1974 | |||
1975 | if (ISSUPP_11ACTXSTBC(cap)) | ||
1976 | vht_cap |= IEEE80211_VHT_CAP_TXSTBC; | ||
1977 | |||
1978 | if (ISSUPP_11ACSGI160(cap)) | ||
1979 | vht_cap |= IEEE80211_VHT_CAP_SHORT_GI_160; | ||
1980 | |||
1981 | if (ISSUPP_11ACSGI80(cap)) | ||
1982 | vht_cap |= IEEE80211_VHT_CAP_SHORT_GI_80; | ||
1983 | |||
1984 | if (ISSUPP_11ACLDPC(cap)) | ||
1985 | vht_cap |= IEEE80211_VHT_CAP_RXLDPC; | ||
1986 | |||
1987 | if (ISSUPP_11ACBW8080(cap)) | ||
1988 | vht_cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ; | ||
1989 | |||
1990 | if (ISSUPP_11ACBW160(cap)) | ||
1991 | vht_cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ; | ||
1992 | |||
1993 | vht_info->cap = vht_cap; | ||
1994 | |||
1995 | /* Update MCS support for VHT */ | 1939 | /* Update MCS support for VHT */ |
1996 | vht_info->vht_mcs.rx_mcs_map = cpu_to_le16( | 1940 | vht_info->vht_mcs.rx_mcs_map = cpu_to_le16( |
1997 | adapter->hw_dot_11ac_mcs_support & 0xFFFF); | 1941 | adapter->hw_dot_11ac_mcs_support & 0xFFFF); |
@@ -2235,6 +2179,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
2235 | dev->flags |= IFF_BROADCAST | IFF_MULTICAST; | 2179 | dev->flags |= IFF_BROADCAST | IFF_MULTICAST; |
2236 | dev->watchdog_timeo = MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT; | 2180 | dev->watchdog_timeo = MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT; |
2237 | dev->hard_header_len += MWIFIEX_MIN_DATA_HEADER_LEN; | 2181 | dev->hard_header_len += MWIFIEX_MIN_DATA_HEADER_LEN; |
2182 | dev->ethtool_ops = &mwifiex_ethtool_ops; | ||
2238 | 2183 | ||
2239 | mdev_priv = netdev_priv(dev); | 2184 | mdev_priv = netdev_priv(dev); |
2240 | *((unsigned long *) mdev_priv) = (unsigned long) priv; | 2185 | *((unsigned long *) mdev_priv) = (unsigned long) priv; |
@@ -2293,6 +2238,152 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) | |||
2293 | } | 2238 | } |
2294 | EXPORT_SYMBOL_GPL(mwifiex_del_virtual_intf); | 2239 | EXPORT_SYMBOL_GPL(mwifiex_del_virtual_intf); |
2295 | 2240 | ||
2241 | #ifdef CONFIG_PM | ||
2242 | static bool | ||
2243 | mwifiex_is_pattern_supported(struct cfg80211_wowlan_trig_pkt_pattern *pat, | ||
2244 | s8 *byte_seq) | ||
2245 | { | ||
2246 | int j, k, valid_byte_cnt = 0; | ||
2247 | bool dont_care_byte = false; | ||
2248 | |||
2249 | for (j = 0; j < DIV_ROUND_UP(pat->pattern_len, 8); j++) { | ||
2250 | for (k = 0; k < 8; k++) { | ||
2251 | if (pat->mask[j] & 1 << k) { | ||
2252 | memcpy(byte_seq + valid_byte_cnt, | ||
2253 | &pat->pattern[j * 8 + k], 1); | ||
2254 | valid_byte_cnt++; | ||
2255 | if (dont_care_byte) | ||
2256 | return false; | ||
2257 | } else { | ||
2258 | if (valid_byte_cnt) | ||
2259 | dont_care_byte = true; | ||
2260 | } | ||
2261 | |||
2262 | if (valid_byte_cnt > MAX_BYTESEQ) | ||
2263 | return false; | ||
2264 | } | ||
2265 | } | ||
2266 | |||
2267 | byte_seq[MAX_BYTESEQ] = valid_byte_cnt; | ||
2268 | |||
2269 | return true; | ||
2270 | } | ||
2271 | |||
2272 | static int mwifiex_cfg80211_suspend(struct wiphy *wiphy, | ||
2273 | struct cfg80211_wowlan *wowlan) | ||
2274 | { | ||
2275 | struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); | ||
2276 | struct mwifiex_ds_mef_cfg mef_cfg; | ||
2277 | struct mwifiex_mef_entry *mef_entry; | ||
2278 | int i, filt_num = 0, ret; | ||
2279 | bool first_pat = true; | ||
2280 | u8 byte_seq[MAX_BYTESEQ + 1]; | ||
2281 | const u8 ipv4_mc_mac[] = {0x33, 0x33}; | ||
2282 | const u8 ipv6_mc_mac[] = {0x01, 0x00, 0x5e}; | ||
2283 | struct mwifiex_private *priv = | ||
2284 | mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA); | ||
2285 | |||
2286 | if (!wowlan) { | ||
2287 | dev_warn(adapter->dev, "None of the WOWLAN triggers enabled\n"); | ||
2288 | return 0; | ||
2289 | } | ||
2290 | |||
2291 | if (!priv->media_connected) { | ||
2292 | dev_warn(adapter->dev, | ||
2293 | "Can not configure WOWLAN in disconnected state\n"); | ||
2294 | return 0; | ||
2295 | } | ||
2296 | |||
2297 | mef_entry = kzalloc(sizeof(*mef_entry), GFP_KERNEL); | ||
2298 | if (!mef_entry) | ||
2299 | return -ENOMEM; | ||
2300 | |||
2301 | memset(&mef_cfg, 0, sizeof(mef_cfg)); | ||
2302 | mef_cfg.num_entries = 1; | ||
2303 | mef_cfg.mef_entry = mef_entry; | ||
2304 | mef_entry->mode = MEF_MODE_HOST_SLEEP; | ||
2305 | mef_entry->action = MEF_ACTION_ALLOW_AND_WAKEUP_HOST; | ||
2306 | |||
2307 | for (i = 0; i < wowlan->n_patterns; i++) { | ||
2308 | memset(byte_seq, 0, sizeof(byte_seq)); | ||
2309 | if (!mwifiex_is_pattern_supported(&wowlan->patterns[i], | ||
2310 | byte_seq)) { | ||
2311 | wiphy_err(wiphy, "Pattern not supported\n"); | ||
2312 | kfree(mef_entry); | ||
2313 | return -EOPNOTSUPP; | ||
2314 | } | ||
2315 | |||
2316 | if (!wowlan->patterns[i].pkt_offset) { | ||
2317 | if (!(byte_seq[0] & 0x01) && | ||
2318 | (byte_seq[MAX_BYTESEQ] == 1)) { | ||
2319 | mef_cfg.criteria |= MWIFIEX_CRITERIA_UNICAST; | ||
2320 | continue; | ||
2321 | } else if (is_broadcast_ether_addr(byte_seq)) { | ||
2322 | mef_cfg.criteria |= MWIFIEX_CRITERIA_BROADCAST; | ||
2323 | continue; | ||
2324 | } else if ((!memcmp(byte_seq, ipv4_mc_mac, 2) && | ||
2325 | (byte_seq[MAX_BYTESEQ] == 2)) || | ||
2326 | (!memcmp(byte_seq, ipv6_mc_mac, 3) && | ||
2327 | (byte_seq[MAX_BYTESEQ] == 3))) { | ||
2328 | mef_cfg.criteria |= MWIFIEX_CRITERIA_MULTICAST; | ||
2329 | continue; | ||
2330 | } | ||
2331 | } | ||
2332 | |||
2333 | mef_entry->filter[filt_num].repeat = 1; | ||
2334 | mef_entry->filter[filt_num].offset = | ||
2335 | wowlan->patterns[i].pkt_offset; | ||
2336 | memcpy(mef_entry->filter[filt_num].byte_seq, byte_seq, | ||
2337 | sizeof(byte_seq)); | ||
2338 | mef_entry->filter[filt_num].filt_type = TYPE_EQ; | ||
2339 | |||
2340 | if (first_pat) | ||
2341 | first_pat = false; | ||
2342 | else | ||
2343 | mef_entry->filter[filt_num].filt_action = TYPE_AND; | ||
2344 | |||
2345 | filt_num++; | ||
2346 | } | ||
2347 | |||
2348 | if (wowlan->magic_pkt) { | ||
2349 | mef_cfg.criteria |= MWIFIEX_CRITERIA_UNICAST; | ||
2350 | mef_entry->filter[filt_num].repeat = 16; | ||
2351 | memcpy(mef_entry->filter[filt_num].byte_seq, priv->curr_addr, | ||
2352 | ETH_ALEN); | ||
2353 | mef_entry->filter[filt_num].byte_seq[MAX_BYTESEQ] = ETH_ALEN; | ||
2354 | mef_entry->filter[filt_num].offset = 14; | ||
2355 | mef_entry->filter[filt_num].filt_type = TYPE_EQ; | ||
2356 | if (filt_num) | ||
2357 | mef_entry->filter[filt_num].filt_action = TYPE_OR; | ||
2358 | } | ||
2359 | |||
2360 | if (!mef_cfg.criteria) | ||
2361 | mef_cfg.criteria = MWIFIEX_CRITERIA_BROADCAST | | ||
2362 | MWIFIEX_CRITERIA_UNICAST | | ||
2363 | MWIFIEX_CRITERIA_MULTICAST; | ||
2364 | |||
2365 | ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_MEF_CFG, | ||
2366 | HostCmd_ACT_GEN_SET, 0, | ||
2367 | &mef_cfg); | ||
2368 | |||
2369 | kfree(mef_entry); | ||
2370 | return ret; | ||
2371 | } | ||
2372 | |||
2373 | static int mwifiex_cfg80211_resume(struct wiphy *wiphy) | ||
2374 | { | ||
2375 | return 0; | ||
2376 | } | ||
2377 | |||
2378 | static void mwifiex_cfg80211_set_wakeup(struct wiphy *wiphy, | ||
2379 | bool enabled) | ||
2380 | { | ||
2381 | struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); | ||
2382 | |||
2383 | device_set_wakeup_enable(adapter->dev, enabled); | ||
2384 | } | ||
2385 | #endif | ||
2386 | |||
2296 | /* station cfg80211 operations */ | 2387 | /* station cfg80211 operations */ |
2297 | static struct cfg80211_ops mwifiex_cfg80211_ops = { | 2388 | static struct cfg80211_ops mwifiex_cfg80211_ops = { |
2298 | .add_virtual_intf = mwifiex_add_virtual_intf, | 2389 | .add_virtual_intf = mwifiex_add_virtual_intf, |
@@ -2321,6 +2412,11 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { | |||
2321 | .change_beacon = mwifiex_cfg80211_change_beacon, | 2412 | .change_beacon = mwifiex_cfg80211_change_beacon, |
2322 | .set_cqm_rssi_config = mwifiex_cfg80211_set_cqm_rssi_config, | 2413 | .set_cqm_rssi_config = mwifiex_cfg80211_set_cqm_rssi_config, |
2323 | .set_antenna = mwifiex_cfg80211_set_antenna, | 2414 | .set_antenna = mwifiex_cfg80211_set_antenna, |
2415 | #ifdef CONFIG_PM | ||
2416 | .suspend = mwifiex_cfg80211_suspend, | ||
2417 | .resume = mwifiex_cfg80211_resume, | ||
2418 | .set_wakeup = mwifiex_cfg80211_set_wakeup, | ||
2419 | #endif | ||
2324 | }; | 2420 | }; |
2325 | 2421 | ||
2326 | /* | 2422 | /* |
@@ -2379,6 +2475,14 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) | |||
2379 | 2475 | ||
2380 | wiphy_apply_custom_regulatory(wiphy, &mwifiex_world_regdom_custom); | 2476 | wiphy_apply_custom_regulatory(wiphy, &mwifiex_world_regdom_custom); |
2381 | 2477 | ||
2478 | #ifdef CONFIG_PM | ||
2479 | wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT; | ||
2480 | wiphy->wowlan.n_patterns = MWIFIEX_MAX_FILTERS; | ||
2481 | wiphy->wowlan.pattern_min_len = 1; | ||
2482 | wiphy->wowlan.pattern_max_len = MWIFIEX_MAX_PATTERN_LEN; | ||
2483 | wiphy->wowlan.max_pkt_offset = MWIFIEX_MAX_OFFSET_LEN; | ||
2484 | #endif | ||
2485 | |||
2382 | wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | | 2486 | wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | |
2383 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | | 2487 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | |
2384 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P; | 2488 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P; |
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index 20a6c5555873..d19a88c47a4d 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c | |||
@@ -1139,7 +1139,7 @@ int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv, | |||
1139 | phs_cfg->params.hs_config.gpio, | 1139 | phs_cfg->params.hs_config.gpio, |
1140 | phs_cfg->params.hs_config.gap); | 1140 | phs_cfg->params.hs_config.gap); |
1141 | } | 1141 | } |
1142 | if (conditions != HOST_SLEEP_CFG_CANCEL) { | 1142 | if (conditions != HS_CFG_CANCEL) { |
1143 | adapter->is_hs_configured = true; | 1143 | adapter->is_hs_configured = true; |
1144 | if (adapter->iface_type == MWIFIEX_USB || | 1144 | if (adapter->iface_type == MWIFIEX_USB || |
1145 | adapter->iface_type == MWIFIEX_PCIE) | 1145 | adapter->iface_type == MWIFIEX_PCIE) |
diff --git a/drivers/net/wireless/mwifiex/ethtool.c b/drivers/net/wireless/mwifiex/ethtool.c new file mode 100644 index 000000000000..bfb39908b2c6 --- /dev/null +++ b/drivers/net/wireless/mwifiex/ethtool.c | |||
@@ -0,0 +1,70 @@ | |||
1 | /* | ||
2 | * Marvell Wireless LAN device driver: ethtool | ||
3 | * | ||
4 | * Copyright (C) 2013, Marvell International Ltd. | ||
5 | * | ||
6 | * This software file (the "File") is distributed by Marvell International | ||
7 | * Ltd. under the terms of the GNU General Public License Version 2, June 1991 | ||
8 | * (the "License"). You may use, redistribute and/or modify this File in | ||
9 | * accordance with the terms and conditions of the License, a copy of which | ||
10 | * is available by writing to the Free Software Foundation, Inc., | ||
11 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the | ||
12 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. | ||
13 | * | ||
14 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE | ||
15 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE | ||
16 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about | ||
17 | * this warranty disclaimer. | ||
18 | */ | ||
19 | |||
20 | #include "main.h" | ||
21 | |||
22 | static void mwifiex_ethtool_get_wol(struct net_device *dev, | ||
23 | struct ethtool_wolinfo *wol) | ||
24 | { | ||
25 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | ||
26 | u32 conditions = le32_to_cpu(priv->adapter->hs_cfg.conditions); | ||
27 | |||
28 | wol->supported = WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY; | ||
29 | |||
30 | if (conditions == HS_CFG_COND_DEF) | ||
31 | return; | ||
32 | |||
33 | if (conditions & HS_CFG_COND_UNICAST_DATA) | ||
34 | wol->wolopts |= WAKE_UCAST; | ||
35 | if (conditions & HS_CFG_COND_MULTICAST_DATA) | ||
36 | wol->wolopts |= WAKE_MCAST; | ||
37 | if (conditions & HS_CFG_COND_BROADCAST_DATA) | ||
38 | wol->wolopts |= WAKE_BCAST; | ||
39 | if (conditions & HS_CFG_COND_MAC_EVENT) | ||
40 | wol->wolopts |= WAKE_PHY; | ||
41 | } | ||
42 | |||
43 | static int mwifiex_ethtool_set_wol(struct net_device *dev, | ||
44 | struct ethtool_wolinfo *wol) | ||
45 | { | ||
46 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | ||
47 | u32 conditions = 0; | ||
48 | |||
49 | if (wol->wolopts & ~(WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY)) | ||
50 | return -EOPNOTSUPP; | ||
51 | |||
52 | if (wol->wolopts & WAKE_UCAST) | ||
53 | conditions |= HS_CFG_COND_UNICAST_DATA; | ||
54 | if (wol->wolopts & WAKE_MCAST) | ||
55 | conditions |= HS_CFG_COND_MULTICAST_DATA; | ||
56 | if (wol->wolopts & WAKE_BCAST) | ||
57 | conditions |= HS_CFG_COND_BROADCAST_DATA; | ||
58 | if (wol->wolopts & WAKE_PHY) | ||
59 | conditions |= HS_CFG_COND_MAC_EVENT; | ||
60 | if (wol->wolopts == 0) | ||
61 | conditions |= HS_CFG_COND_DEF; | ||
62 | priv->adapter->hs_cfg.conditions = cpu_to_le32(conditions); | ||
63 | |||
64 | return 0; | ||
65 | } | ||
66 | |||
67 | const struct ethtool_ops mwifiex_ethtool_ops = { | ||
68 | .get_wol = mwifiex_ethtool_get_wol, | ||
69 | .set_wol = mwifiex_ethtool_set_wol, | ||
70 | }; | ||
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 25acb0682c56..57c5defe1f9d 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h | |||
@@ -230,40 +230,12 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
230 | 230 | ||
231 | #define ISSUPP_11ACENABLED(fw_cap_info) (fw_cap_info & (BIT(13)|BIT(14))) | 231 | #define ISSUPP_11ACENABLED(fw_cap_info) (fw_cap_info & (BIT(13)|BIT(14))) |
232 | 232 | ||
233 | #define GET_VHTCAP_MAXMPDULEN(vht_cap_info) (vht_cap_info & 0x3) | ||
234 | #define GET_VHTCAP_CHWDSET(vht_cap_info) ((vht_cap_info >> 2) & 0x3) | 233 | #define GET_VHTCAP_CHWDSET(vht_cap_info) ((vht_cap_info >> 2) & 0x3) |
235 | #define GET_VHTNSSMCS(mcs_mapset, nss) ((mcs_mapset >> (2 * (nss - 1))) & 0x3) | 234 | #define GET_VHTNSSMCS(mcs_mapset, nss) ((mcs_mapset >> (2 * (nss - 1))) & 0x3) |
236 | #define SET_VHTNSSMCS(mcs_mapset, nss, value) (mcs_mapset |= (value & 0x3) << \ | 235 | #define SET_VHTNSSMCS(mcs_mapset, nss, value) (mcs_mapset |= (value & 0x3) << \ |
237 | (2 * (nss - 1))) | 236 | (2 * (nss - 1))) |
238 | #define NO_NSS_SUPPORT 0x3 | 237 | #define NO_NSS_SUPPORT 0x3 |
239 | 238 | ||
240 | /* HW_SPEC: HTC-VHT supported */ | ||
241 | #define ISSUPP_11ACVHTHTCVHT(Dot11acDevCap) (Dot11acDevCap & BIT(22)) | ||
242 | /* HW_SPEC: VHT TXOP PS support */ | ||
243 | #define ISSUPP_11ACVHTTXOPPS(Dot11acDevCap) (Dot11acDevCap & BIT(21)) | ||
244 | /* HW_SPEC: MU RX beamformee support */ | ||
245 | #define ISSUPP_11ACMURXBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap & BIT(20)) | ||
246 | /* HW_SPEC: MU TX beamformee support */ | ||
247 | #define ISSUPP_11ACMUTXBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap & BIT(19)) | ||
248 | /* HW_SPEC: SU Beamformee support */ | ||
249 | #define ISSUPP_11ACSUBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap & BIT(10)) | ||
250 | /* HW_SPEC: SU Beamformer support */ | ||
251 | #define ISSUPP_11ACSUBEAMFORMER(Dot11acDevCap) (Dot11acDevCap & BIT(9)) | ||
252 | /* HW_SPEC: Rx STBC support */ | ||
253 | #define ISSUPP_11ACRXSTBC(Dot11acDevCap) (Dot11acDevCap & BIT(8)) | ||
254 | /* HW_SPEC: Tx STBC support */ | ||
255 | #define ISSUPP_11ACTXSTBC(Dot11acDevCap) (Dot11acDevCap & BIT(7)) | ||
256 | /* HW_SPEC: Short GI support for 160MHz BW */ | ||
257 | #define ISSUPP_11ACSGI160(Dot11acDevCap) (Dot11acDevCap & BIT(6)) | ||
258 | /* HW_SPEC: Short GI support for 80MHz BW */ | ||
259 | #define ISSUPP_11ACSGI80(Dot11acDevCap) (Dot11acDevCap & BIT(5)) | ||
260 | /* HW_SPEC: LDPC coding support */ | ||
261 | #define ISSUPP_11ACLDPC(Dot11acDevCap) (Dot11acDevCap & BIT(4)) | ||
262 | /* HW_SPEC: Channel BW 20/40/80/160/80+80 MHz support */ | ||
263 | #define ISSUPP_11ACBW8080(Dot11acDevCap) (Dot11acDevCap & BIT(3)) | ||
264 | /* HW_SPEC: Channel BW 20/40/80/160 MHz support */ | ||
265 | #define ISSUPP_11ACBW160(Dot11acDevCap) (Dot11acDevCap & BIT(2)) | ||
266 | |||
267 | #define GET_DEVTXMCSMAP(dev_mcs_map) (dev_mcs_map >> 16) | 239 | #define GET_DEVTXMCSMAP(dev_mcs_map) (dev_mcs_map >> 16) |
268 | #define GET_DEVRXMCSMAP(dev_mcs_map) (dev_mcs_map & 0xFFFF) | 240 | #define GET_DEVRXMCSMAP(dev_mcs_map) (dev_mcs_map & 0xFFFF) |
269 | 241 | ||
@@ -300,6 +272,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
300 | #define HostCmd_CMD_802_11_TX_RATE_QUERY 0x007f | 272 | #define HostCmd_CMD_802_11_TX_RATE_QUERY 0x007f |
301 | #define HostCmd_CMD_802_11_IBSS_COALESCING_STATUS 0x0083 | 273 | #define HostCmd_CMD_802_11_IBSS_COALESCING_STATUS 0x0083 |
302 | #define HostCmd_CMD_VERSION_EXT 0x0097 | 274 | #define HostCmd_CMD_VERSION_EXT 0x0097 |
275 | #define HostCmd_CMD_MEF_CFG 0x009a | ||
303 | #define HostCmd_CMD_RSSI_INFO 0x00a4 | 276 | #define HostCmd_CMD_RSSI_INFO 0x00a4 |
304 | #define HostCmd_CMD_FUNC_INIT 0x00a9 | 277 | #define HostCmd_CMD_FUNC_INIT 0x00a9 |
305 | #define HostCmd_CMD_FUNC_SHUTDOWN 0x00aa | 278 | #define HostCmd_CMD_FUNC_SHUTDOWN 0x00aa |
@@ -376,10 +349,14 @@ enum P2P_MODES { | |||
376 | #define HostCmd_SCAN_RADIO_TYPE_BG 0 | 349 | #define HostCmd_SCAN_RADIO_TYPE_BG 0 |
377 | #define HostCmd_SCAN_RADIO_TYPE_A 1 | 350 | #define HostCmd_SCAN_RADIO_TYPE_A 1 |
378 | 351 | ||
379 | #define HOST_SLEEP_CFG_CANCEL 0xffffffff | 352 | #define HS_CFG_CANCEL 0xffffffff |
380 | #define HOST_SLEEP_CFG_COND_DEF 0x00000000 | 353 | #define HS_CFG_COND_DEF 0x00000000 |
381 | #define HOST_SLEEP_CFG_GPIO_DEF 0xff | 354 | #define HS_CFG_GPIO_DEF 0xff |
382 | #define HOST_SLEEP_CFG_GAP_DEF 0 | 355 | #define HS_CFG_GAP_DEF 0 |
356 | #define HS_CFG_COND_BROADCAST_DATA 0x00000001 | ||
357 | #define HS_CFG_COND_UNICAST_DATA 0x00000002 | ||
358 | #define HS_CFG_COND_MAC_EVENT 0x00000004 | ||
359 | #define HS_CFG_COND_MULTICAST_DATA 0x00000008 | ||
383 | 360 | ||
384 | #define MWIFIEX_TIMEOUT_FOR_AP_RESP 0xfffc | 361 | #define MWIFIEX_TIMEOUT_FOR_AP_RESP 0xfffc |
385 | #define MWIFIEX_STATUS_CODE_AUTH_TIMEOUT 2 | 362 | #define MWIFIEX_STATUS_CODE_AUTH_TIMEOUT 2 |
@@ -469,6 +446,23 @@ enum P2P_MODES { | |||
469 | #define EVENT_GET_BSS_TYPE(event_cause) \ | 446 | #define EVENT_GET_BSS_TYPE(event_cause) \ |
470 | (((event_cause) >> 24) & 0x00ff) | 447 | (((event_cause) >> 24) & 0x00ff) |
471 | 448 | ||
449 | #define MWIFIEX_MAX_PATTERN_LEN 20 | ||
450 | #define MWIFIEX_MAX_OFFSET_LEN 50 | ||
451 | #define STACK_NBYTES 100 | ||
452 | #define TYPE_DNUM 1 | ||
453 | #define TYPE_BYTESEQ 2 | ||
454 | #define MAX_OPERAND 0x40 | ||
455 | #define TYPE_EQ (MAX_OPERAND+1) | ||
456 | #define TYPE_EQ_DNUM (MAX_OPERAND+2) | ||
457 | #define TYPE_EQ_BIT (MAX_OPERAND+3) | ||
458 | #define TYPE_AND (MAX_OPERAND+4) | ||
459 | #define TYPE_OR (MAX_OPERAND+5) | ||
460 | #define MEF_MODE_HOST_SLEEP 1 | ||
461 | #define MEF_ACTION_ALLOW_AND_WAKEUP_HOST 3 | ||
462 | #define MWIFIEX_CRITERIA_BROADCAST BIT(0) | ||
463 | #define MWIFIEX_CRITERIA_UNICAST BIT(1) | ||
464 | #define MWIFIEX_CRITERIA_MULTICAST BIT(3) | ||
465 | |||
472 | struct mwifiex_ie_types_header { | 466 | struct mwifiex_ie_types_header { |
473 | __le16 type; | 467 | __le16 type; |
474 | __le16 len; | 468 | __le16 len; |
@@ -1499,6 +1493,19 @@ struct host_cmd_ds_802_11_ibss_status { | |||
1499 | __le16 use_g_rate_protect; | 1493 | __le16 use_g_rate_protect; |
1500 | } __packed; | 1494 | } __packed; |
1501 | 1495 | ||
1496 | struct mwifiex_fw_mef_entry { | ||
1497 | u8 mode; | ||
1498 | u8 action; | ||
1499 | __le16 exprsize; | ||
1500 | u8 expr[0]; | ||
1501 | } __packed; | ||
1502 | |||
1503 | struct host_cmd_ds_mef_cfg { | ||
1504 | __le32 criteria; | ||
1505 | __le16 num_entries; | ||
1506 | struct mwifiex_fw_mef_entry mef_entry[0]; | ||
1507 | } __packed; | ||
1508 | |||
1502 | #define CONNECTION_TYPE_INFRA 0 | 1509 | #define CONNECTION_TYPE_INFRA 0 |
1503 | #define CONNECTION_TYPE_ADHOC 1 | 1510 | #define CONNECTION_TYPE_ADHOC 1 |
1504 | #define CONNECTION_TYPE_AP 2 | 1511 | #define CONNECTION_TYPE_AP 2 |
@@ -1603,6 +1610,7 @@ struct host_cmd_ds_command { | |||
1603 | struct host_cmd_ds_remain_on_chan roc_cfg; | 1610 | struct host_cmd_ds_remain_on_chan roc_cfg; |
1604 | struct host_cmd_ds_p2p_mode_cfg mode_cfg; | 1611 | struct host_cmd_ds_p2p_mode_cfg mode_cfg; |
1605 | struct host_cmd_ds_802_11_ibss_status ibss_coalescing; | 1612 | struct host_cmd_ds_802_11_ibss_status ibss_coalescing; |
1613 | struct host_cmd_ds_mef_cfg mef_cfg; | ||
1606 | struct host_cmd_ds_mac_reg_access mac_reg; | 1614 | struct host_cmd_ds_mac_reg_access mac_reg; |
1607 | struct host_cmd_ds_bbp_reg_access bbp_reg; | 1615 | struct host_cmd_ds_bbp_reg_access bbp_reg; |
1608 | struct host_cmd_ds_rf_reg_access rf_reg; | 1616 | struct host_cmd_ds_rf_reg_access rf_reg; |
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index e38aa9b3663d..cab3434d0d52 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c | |||
@@ -318,9 +318,9 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter) | |||
318 | adapter->curr_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; | 318 | adapter->curr_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; |
319 | 319 | ||
320 | adapter->is_hs_configured = false; | 320 | adapter->is_hs_configured = false; |
321 | adapter->hs_cfg.conditions = cpu_to_le32(HOST_SLEEP_CFG_COND_DEF); | 321 | adapter->hs_cfg.conditions = cpu_to_le32(HS_CFG_COND_DEF); |
322 | adapter->hs_cfg.gpio = HOST_SLEEP_CFG_GPIO_DEF; | 322 | adapter->hs_cfg.gpio = HS_CFG_GPIO_DEF; |
323 | adapter->hs_cfg.gap = HOST_SLEEP_CFG_GAP_DEF; | 323 | adapter->hs_cfg.gap = HS_CFG_GAP_DEF; |
324 | adapter->hs_activated = false; | 324 | adapter->hs_activated = false; |
325 | 325 | ||
326 | memset(adapter->event_body, 0, sizeof(adapter->event_body)); | 326 | memset(adapter->event_body, 0, sizeof(adapter->event_body)); |
diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h index d85e6eb1f58a..91d522c746ed 100644 --- a/drivers/net/wireless/mwifiex/ioctl.h +++ b/drivers/net/wireless/mwifiex/ioctl.h | |||
@@ -354,6 +354,29 @@ struct mwifiex_ds_misc_subsc_evt { | |||
354 | struct subsc_evt_cfg bcn_h_rssi_cfg; | 354 | struct subsc_evt_cfg bcn_h_rssi_cfg; |
355 | }; | 355 | }; |
356 | 356 | ||
357 | #define MAX_BYTESEQ 6 /* non-adjustable */ | ||
358 | #define MWIFIEX_MAX_FILTERS 10 | ||
359 | |||
360 | struct mwifiex_mef_filter { | ||
361 | u16 repeat; | ||
362 | u16 offset; | ||
363 | s8 byte_seq[MAX_BYTESEQ + 1]; | ||
364 | u8 filt_type; | ||
365 | u8 filt_action; | ||
366 | }; | ||
367 | |||
368 | struct mwifiex_mef_entry { | ||
369 | u8 mode; | ||
370 | u8 action; | ||
371 | struct mwifiex_mef_filter filter[MWIFIEX_MAX_FILTERS]; | ||
372 | }; | ||
373 | |||
374 | struct mwifiex_ds_mef_cfg { | ||
375 | u32 criteria; | ||
376 | u16 num_entries; | ||
377 | struct mwifiex_mef_entry *mef_entry; | ||
378 | }; | ||
379 | |||
357 | #define MWIFIEX_MAX_VSIE_LEN (256) | 380 | #define MWIFIEX_MAX_VSIE_LEN (256) |
358 | #define MWIFIEX_MAX_VSIE_NUM (8) | 381 | #define MWIFIEX_MAX_VSIE_NUM (8) |
359 | #define MWIFIEX_VSIE_MASK_CLEAR 0x00 | 382 | #define MWIFIEX_VSIE_MASK_CLEAR 0x00 |
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 9c802ede9c3b..121443a0f2a1 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c | |||
@@ -588,10 +588,19 @@ mwifiex_tx_timeout(struct net_device *dev) | |||
588 | { | 588 | { |
589 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | 589 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); |
590 | 590 | ||
591 | dev_err(priv->adapter->dev, "%lu : Tx timeout, bss_type-num = %d-%d\n", | ||
592 | jiffies, priv->bss_type, priv->bss_num); | ||
593 | mwifiex_set_trans_start(dev); | ||
594 | priv->num_tx_timeout++; | 591 | priv->num_tx_timeout++; |
592 | priv->tx_timeout_cnt++; | ||
593 | dev_err(priv->adapter->dev, | ||
594 | "%lu : Tx timeout(#%d), bss_type-num = %d-%d\n", | ||
595 | jiffies, priv->tx_timeout_cnt, priv->bss_type, priv->bss_num); | ||
596 | mwifiex_set_trans_start(dev); | ||
597 | |||
598 | if (priv->tx_timeout_cnt > TX_TIMEOUT_THRESHOLD && | ||
599 | priv->adapter->if_ops.card_reset) { | ||
600 | dev_err(priv->adapter->dev, | ||
601 | "tx_timeout_cnt exceeds threshold. Triggering card reset!\n"); | ||
602 | priv->adapter->if_ops.card_reset(priv->adapter); | ||
603 | } | ||
595 | } | 604 | } |
596 | 605 | ||
597 | /* | 606 | /* |
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 553adfb0aa81..920657587fff 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h | |||
@@ -130,6 +130,9 @@ enum { | |||
130 | #define MWIFIEX_USB_TYPE_DATA 0xBEADC0DE | 130 | #define MWIFIEX_USB_TYPE_DATA 0xBEADC0DE |
131 | #define MWIFIEX_USB_TYPE_EVENT 0xBEEFFACE | 131 | #define MWIFIEX_USB_TYPE_EVENT 0xBEEFFACE |
132 | 132 | ||
133 | /* Threshold for tx_timeout_cnt before we trigger a card reset */ | ||
134 | #define TX_TIMEOUT_THRESHOLD 6 | ||
135 | |||
133 | struct mwifiex_dbg { | 136 | struct mwifiex_dbg { |
134 | u32 num_cmd_host_to_card_failure; | 137 | u32 num_cmd_host_to_card_failure; |
135 | u32 num_cmd_sleep_cfm_host_to_card_failure; | 138 | u32 num_cmd_sleep_cfm_host_to_card_failure; |
@@ -394,6 +397,8 @@ struct mwifiex_private { | |||
394 | u8 curr_addr[ETH_ALEN]; | 397 | u8 curr_addr[ETH_ALEN]; |
395 | u8 media_connected; | 398 | u8 media_connected; |
396 | u32 num_tx_timeout; | 399 | u32 num_tx_timeout; |
400 | /* track consecutive timeout */ | ||
401 | u8 tx_timeout_cnt; | ||
397 | struct net_device *netdev; | 402 | struct net_device *netdev; |
398 | struct net_device_stats stats; | 403 | struct net_device_stats stats; |
399 | u16 curr_pkt_filter; | 404 | u16 curr_pkt_filter; |
@@ -1098,11 +1103,15 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev); | |||
1098 | 1103 | ||
1099 | void mwifiex_set_sys_config_invalid_data(struct mwifiex_uap_bss_param *config); | 1104 | void mwifiex_set_sys_config_invalid_data(struct mwifiex_uap_bss_param *config); |
1100 | 1105 | ||
1106 | int mwifiex_add_wowlan_magic_pkt_filter(struct mwifiex_adapter *adapter); | ||
1107 | |||
1101 | int mwifiex_set_mgmt_ies(struct mwifiex_private *priv, | 1108 | int mwifiex_set_mgmt_ies(struct mwifiex_private *priv, |
1102 | struct cfg80211_beacon_data *data); | 1109 | struct cfg80211_beacon_data *data); |
1103 | int mwifiex_del_mgmt_ies(struct mwifiex_private *priv); | 1110 | int mwifiex_del_mgmt_ies(struct mwifiex_private *priv); |
1104 | u8 *mwifiex_11d_code_2_region(u8 code); | 1111 | u8 *mwifiex_11d_code_2_region(u8 code); |
1105 | 1112 | ||
1113 | extern const struct ethtool_ops mwifiex_ethtool_ops; | ||
1114 | |||
1106 | #ifdef CONFIG_DEBUG_FS | 1115 | #ifdef CONFIG_DEBUG_FS |
1107 | void mwifiex_debugfs_init(void); | 1116 | void mwifiex_debugfs_init(void); |
1108 | void mwifiex_debugfs_remove(void); | 1117 | void mwifiex_debugfs_remove(void); |
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c index 5c395e2e6a2b..6283294398bf 100644 --- a/drivers/net/wireless/mwifiex/pcie.c +++ b/drivers/net/wireless/mwifiex/pcie.c | |||
@@ -36,8 +36,6 @@ static u8 user_rmmod; | |||
36 | static struct mwifiex_if_ops pcie_ops; | 36 | static struct mwifiex_if_ops pcie_ops; |
37 | 37 | ||
38 | static struct semaphore add_remove_card_sem; | 38 | static struct semaphore add_remove_card_sem; |
39 | static int mwifiex_pcie_enable_host_int(struct mwifiex_adapter *adapter); | ||
40 | static int mwifiex_pcie_resume(struct pci_dev *pdev); | ||
41 | 39 | ||
42 | static int | 40 | static int |
43 | mwifiex_map_pci_memory(struct mwifiex_adapter *adapter, struct sk_buff *skb, | 41 | mwifiex_map_pci_memory(struct mwifiex_adapter *adapter, struct sk_buff *skb, |
@@ -78,6 +76,82 @@ static bool mwifiex_pcie_ok_to_access_hw(struct mwifiex_adapter *adapter) | |||
78 | return false; | 76 | return false; |
79 | } | 77 | } |
80 | 78 | ||
79 | #ifdef CONFIG_PM | ||
80 | /* | ||
81 | * Kernel needs to suspend all functions separately. Therefore all | ||
82 | * registered functions must have drivers with suspend and resume | ||
83 | * methods. Failing that the kernel simply removes the whole card. | ||
84 | * | ||
85 | * If already not suspended, this function allocates and sends a host | ||
86 | * sleep activate request to the firmware and turns off the traffic. | ||
87 | */ | ||
88 | static int mwifiex_pcie_suspend(struct pci_dev *pdev, pm_message_t state) | ||
89 | { | ||
90 | struct mwifiex_adapter *adapter; | ||
91 | struct pcie_service_card *card; | ||
92 | int hs_actived; | ||
93 | |||
94 | if (pdev) { | ||
95 | card = (struct pcie_service_card *) pci_get_drvdata(pdev); | ||
96 | if (!card || !card->adapter) { | ||
97 | pr_err("Card or adapter structure is not valid\n"); | ||
98 | return 0; | ||
99 | } | ||
100 | } else { | ||
101 | pr_err("PCIE device is not specified\n"); | ||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | adapter = card->adapter; | ||
106 | |||
107 | hs_actived = mwifiex_enable_hs(adapter); | ||
108 | |||
109 | /* Indicate device suspended */ | ||
110 | adapter->is_suspended = true; | ||
111 | |||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | /* | ||
116 | * Kernel needs to suspend all functions separately. Therefore all | ||
117 | * registered functions must have drivers with suspend and resume | ||
118 | * methods. Failing that the kernel simply removes the whole card. | ||
119 | * | ||
120 | * If already not resumed, this function turns on the traffic and | ||
121 | * sends a host sleep cancel request to the firmware. | ||
122 | */ | ||
123 | static int mwifiex_pcie_resume(struct pci_dev *pdev) | ||
124 | { | ||
125 | struct mwifiex_adapter *adapter; | ||
126 | struct pcie_service_card *card; | ||
127 | |||
128 | if (pdev) { | ||
129 | card = (struct pcie_service_card *) pci_get_drvdata(pdev); | ||
130 | if (!card || !card->adapter) { | ||
131 | pr_err("Card or adapter structure is not valid\n"); | ||
132 | return 0; | ||
133 | } | ||
134 | } else { | ||
135 | pr_err("PCIE device is not specified\n"); | ||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | adapter = card->adapter; | ||
140 | |||
141 | if (!adapter->is_suspended) { | ||
142 | dev_warn(adapter->dev, "Device already resumed\n"); | ||
143 | return 0; | ||
144 | } | ||
145 | |||
146 | adapter->is_suspended = false; | ||
147 | |||
148 | mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA), | ||
149 | MWIFIEX_ASYNC_CMD); | ||
150 | |||
151 | return 0; | ||
152 | } | ||
153 | #endif | ||
154 | |||
81 | /* | 155 | /* |
82 | * This function probes an mwifiex device and registers it. It allocates | 156 | * This function probes an mwifiex device and registers it. It allocates |
83 | * the card structure, enables PCIE function number and initiates the | 157 | * the card structure, enables PCIE function number and initiates the |
@@ -159,80 +233,6 @@ static void mwifiex_pcie_remove(struct pci_dev *pdev) | |||
159 | kfree(card); | 233 | kfree(card); |
160 | } | 234 | } |
161 | 235 | ||
162 | /* | ||
163 | * Kernel needs to suspend all functions separately. Therefore all | ||
164 | * registered functions must have drivers with suspend and resume | ||
165 | * methods. Failing that the kernel simply removes the whole card. | ||
166 | * | ||
167 | * If already not suspended, this function allocates and sends a host | ||
168 | * sleep activate request to the firmware and turns off the traffic. | ||
169 | */ | ||
170 | static int mwifiex_pcie_suspend(struct pci_dev *pdev, pm_message_t state) | ||
171 | { | ||
172 | struct mwifiex_adapter *adapter; | ||
173 | struct pcie_service_card *card; | ||
174 | int hs_actived; | ||
175 | |||
176 | if (pdev) { | ||
177 | card = (struct pcie_service_card *) pci_get_drvdata(pdev); | ||
178 | if (!card || !card->adapter) { | ||
179 | pr_err("Card or adapter structure is not valid\n"); | ||
180 | return 0; | ||
181 | } | ||
182 | } else { | ||
183 | pr_err("PCIE device is not specified\n"); | ||
184 | return 0; | ||
185 | } | ||
186 | |||
187 | adapter = card->adapter; | ||
188 | |||
189 | hs_actived = mwifiex_enable_hs(adapter); | ||
190 | |||
191 | /* Indicate device suspended */ | ||
192 | adapter->is_suspended = true; | ||
193 | |||
194 | return 0; | ||
195 | } | ||
196 | |||
197 | /* | ||
198 | * Kernel needs to suspend all functions separately. Therefore all | ||
199 | * registered functions must have drivers with suspend and resume | ||
200 | * methods. Failing that the kernel simply removes the whole card. | ||
201 | * | ||
202 | * If already not resumed, this function turns on the traffic and | ||
203 | * sends a host sleep cancel request to the firmware. | ||
204 | */ | ||
205 | static int mwifiex_pcie_resume(struct pci_dev *pdev) | ||
206 | { | ||
207 | struct mwifiex_adapter *adapter; | ||
208 | struct pcie_service_card *card; | ||
209 | |||
210 | if (pdev) { | ||
211 | card = (struct pcie_service_card *) pci_get_drvdata(pdev); | ||
212 | if (!card || !card->adapter) { | ||
213 | pr_err("Card or adapter structure is not valid\n"); | ||
214 | return 0; | ||
215 | } | ||
216 | } else { | ||
217 | pr_err("PCIE device is not specified\n"); | ||
218 | return 0; | ||
219 | } | ||
220 | |||
221 | adapter = card->adapter; | ||
222 | |||
223 | if (!adapter->is_suspended) { | ||
224 | dev_warn(adapter->dev, "Device already resumed\n"); | ||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | adapter->is_suspended = false; | ||
229 | |||
230 | mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA), | ||
231 | MWIFIEX_ASYNC_CMD); | ||
232 | |||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | static DEFINE_PCI_DEVICE_TABLE(mwifiex_ids) = { | 236 | static DEFINE_PCI_DEVICE_TABLE(mwifiex_ids) = { |
237 | { | 237 | { |
238 | PCIE_VENDOR_ID_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8766P, | 238 | 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, | |||
1030 | u32 wrindx, num_tx_buffs, rx_val; | 1030 | u32 wrindx, num_tx_buffs, rx_val; |
1031 | int ret; | 1031 | int ret; |
1032 | dma_addr_t buf_pa; | 1032 | dma_addr_t buf_pa; |
1033 | struct mwifiex_pcie_buf_desc *desc; | 1033 | struct mwifiex_pcie_buf_desc *desc = NULL; |
1034 | struct mwifiex_pfu_buf_desc *desc2; | 1034 | struct mwifiex_pfu_buf_desc *desc2 = NULL; |
1035 | __le16 *tmp; | 1035 | __le16 *tmp; |
1036 | 1036 | ||
1037 | if (!(skb->data && skb->len)) { | 1037 | if (!(skb->data && skb->len)) { |
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index c55c5bb93134..a2ae690a0a67 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c | |||
@@ -334,7 +334,7 @@ mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv, | |||
334 | cmd->command = cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH); | 334 | cmd->command = cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH); |
335 | 335 | ||
336 | if (!hs_activate && | 336 | if (!hs_activate && |
337 | (hscfg_param->conditions != cpu_to_le32(HOST_SLEEP_CFG_CANCEL)) && | 337 | (hscfg_param->conditions != cpu_to_le32(HS_CFG_CANCEL)) && |
338 | ((adapter->arp_filter_size > 0) && | 338 | ((adapter->arp_filter_size > 0) && |
339 | (adapter->arp_filter_size <= ARP_FILTER_MAX_BUF_SIZE))) { | 339 | (adapter->arp_filter_size <= ARP_FILTER_MAX_BUF_SIZE))) { |
340 | dev_dbg(adapter->dev, | 340 | dev_dbg(adapter->dev, |
@@ -1059,6 +1059,80 @@ mwifiex_cmd_802_11_subsc_evt(struct mwifiex_private *priv, | |||
1059 | return 0; | 1059 | return 0; |
1060 | } | 1060 | } |
1061 | 1061 | ||
1062 | static int | ||
1063 | mwifiex_cmd_append_rpn_expression(struct mwifiex_private *priv, | ||
1064 | struct mwifiex_mef_entry *mef_entry, | ||
1065 | u8 **buffer) | ||
1066 | { | ||
1067 | struct mwifiex_mef_filter *filter = mef_entry->filter; | ||
1068 | int i, byte_len; | ||
1069 | u8 *stack_ptr = *buffer; | ||
1070 | |||
1071 | for (i = 0; i < MWIFIEX_MAX_FILTERS; i++) { | ||
1072 | filter = &mef_entry->filter[i]; | ||
1073 | if (!filter->filt_type) | ||
1074 | break; | ||
1075 | *(__le32 *)stack_ptr = cpu_to_le32((u32)filter->repeat); | ||
1076 | stack_ptr += 4; | ||
1077 | *stack_ptr = TYPE_DNUM; | ||
1078 | stack_ptr += 1; | ||
1079 | |||
1080 | byte_len = filter->byte_seq[MAX_BYTESEQ]; | ||
1081 | memcpy(stack_ptr, filter->byte_seq, byte_len); | ||
1082 | stack_ptr += byte_len; | ||
1083 | *stack_ptr = byte_len; | ||
1084 | stack_ptr += 1; | ||
1085 | *stack_ptr = TYPE_BYTESEQ; | ||
1086 | stack_ptr += 1; | ||
1087 | |||
1088 | *(__le32 *)stack_ptr = cpu_to_le32((u32)filter->offset); | ||
1089 | stack_ptr += 4; | ||
1090 | *stack_ptr = TYPE_DNUM; | ||
1091 | stack_ptr += 1; | ||
1092 | |||
1093 | *stack_ptr = filter->filt_type; | ||
1094 | stack_ptr += 1; | ||
1095 | |||
1096 | if (filter->filt_action) { | ||
1097 | *stack_ptr = filter->filt_action; | ||
1098 | stack_ptr += 1; | ||
1099 | } | ||
1100 | |||
1101 | if (stack_ptr - *buffer > STACK_NBYTES) | ||
1102 | return -1; | ||
1103 | } | ||
1104 | |||
1105 | *buffer = stack_ptr; | ||
1106 | return 0; | ||
1107 | } | ||
1108 | |||
1109 | static int | ||
1110 | mwifiex_cmd_mef_cfg(struct mwifiex_private *priv, | ||
1111 | struct host_cmd_ds_command *cmd, | ||
1112 | struct mwifiex_ds_mef_cfg *mef) | ||
1113 | { | ||
1114 | struct host_cmd_ds_mef_cfg *mef_cfg = &cmd->params.mef_cfg; | ||
1115 | u8 *pos = (u8 *)mef_cfg; | ||
1116 | |||
1117 | cmd->command = cpu_to_le16(HostCmd_CMD_MEF_CFG); | ||
1118 | |||
1119 | mef_cfg->criteria = cpu_to_le32(mef->criteria); | ||
1120 | mef_cfg->num_entries = cpu_to_le16(mef->num_entries); | ||
1121 | pos += sizeof(*mef_cfg); | ||
1122 | mef_cfg->mef_entry->mode = mef->mef_entry->mode; | ||
1123 | mef_cfg->mef_entry->action = mef->mef_entry->action; | ||
1124 | pos += sizeof(*(mef_cfg->mef_entry)); | ||
1125 | |||
1126 | if (mwifiex_cmd_append_rpn_expression(priv, mef->mef_entry, &pos)) | ||
1127 | return -1; | ||
1128 | |||
1129 | mef_cfg->mef_entry->exprsize = | ||
1130 | cpu_to_le16(pos - mef_cfg->mef_entry->expr); | ||
1131 | cmd->size = cpu_to_le16((u16) (pos - (u8 *)mef_cfg) + S_DS_GEN); | ||
1132 | |||
1133 | return 0; | ||
1134 | } | ||
1135 | |||
1062 | /* | 1136 | /* |
1063 | * This function prepares the commands before sending them to the firmware. | 1137 | * This function prepares the commands before sending them to the firmware. |
1064 | * | 1138 | * |
@@ -1273,6 +1347,9 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, | |||
1273 | case HostCmd_CMD_802_11_SUBSCRIBE_EVENT: | 1347 | case HostCmd_CMD_802_11_SUBSCRIBE_EVENT: |
1274 | ret = mwifiex_cmd_802_11_subsc_evt(priv, cmd_ptr, data_buf); | 1348 | ret = mwifiex_cmd_802_11_subsc_evt(priv, cmd_ptr, data_buf); |
1275 | break; | 1349 | break; |
1350 | case HostCmd_CMD_MEF_CFG: | ||
1351 | ret = mwifiex_cmd_mef_cfg(priv, cmd_ptr, data_buf); | ||
1352 | break; | ||
1276 | default: | 1353 | default: |
1277 | dev_err(priv->adapter->dev, | 1354 | dev_err(priv->adapter->dev, |
1278 | "PREP_CMD: unknown cmd- %#x\n", cmd_no); | 1355 | "PREP_CMD: unknown cmd- %#x\n", cmd_no); |
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index 4669f8d9389f..80b9f2238001 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c | |||
@@ -976,6 +976,8 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, | |||
976 | case HostCmd_CMD_UAP_BSS_STOP: | 976 | case HostCmd_CMD_UAP_BSS_STOP: |
977 | priv->bss_started = 0; | 977 | priv->bss_started = 0; |
978 | break; | 978 | break; |
979 | case HostCmd_CMD_MEF_CFG: | ||
980 | break; | ||
979 | default: | 981 | default: |
980 | dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n", | 982 | dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n", |
981 | resp->command); | 983 | resp->command); |
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 9f33c92c90f5..76d31deb7b1b 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c | |||
@@ -388,7 +388,7 @@ static int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action, | |||
388 | break; | 388 | break; |
389 | } | 389 | } |
390 | if (hs_cfg->is_invoke_hostcmd) { | 390 | if (hs_cfg->is_invoke_hostcmd) { |
391 | if (hs_cfg->conditions == HOST_SLEEP_CFG_CANCEL) { | 391 | if (hs_cfg->conditions == HS_CFG_CANCEL) { |
392 | if (!adapter->is_hs_configured) | 392 | if (!adapter->is_hs_configured) |
393 | /* Already cancelled */ | 393 | /* Already cancelled */ |
394 | break; | 394 | break; |
@@ -403,8 +403,8 @@ static int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action, | |||
403 | adapter->hs_cfg.gpio = (u8)hs_cfg->gpio; | 403 | adapter->hs_cfg.gpio = (u8)hs_cfg->gpio; |
404 | if (hs_cfg->gap) | 404 | if (hs_cfg->gap) |
405 | adapter->hs_cfg.gap = (u8)hs_cfg->gap; | 405 | adapter->hs_cfg.gap = (u8)hs_cfg->gap; |
406 | } else if (adapter->hs_cfg.conditions | 406 | } else if (adapter->hs_cfg.conditions == |
407 | == cpu_to_le32(HOST_SLEEP_CFG_CANCEL)) { | 407 | cpu_to_le32(HS_CFG_CANCEL)) { |
408 | /* Return failure if no parameters for HS | 408 | /* Return failure if no parameters for HS |
409 | enable */ | 409 | enable */ |
410 | status = -1; | 410 | status = -1; |
@@ -420,7 +420,7 @@ static int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action, | |||
420 | HostCmd_CMD_802_11_HS_CFG_ENH, | 420 | HostCmd_CMD_802_11_HS_CFG_ENH, |
421 | HostCmd_ACT_GEN_SET, 0, | 421 | HostCmd_ACT_GEN_SET, 0, |
422 | &adapter->hs_cfg); | 422 | &adapter->hs_cfg); |
423 | if (hs_cfg->conditions == HOST_SLEEP_CFG_CANCEL) | 423 | if (hs_cfg->conditions == HS_CFG_CANCEL) |
424 | /* Restore previous condition */ | 424 | /* Restore previous condition */ |
425 | adapter->hs_cfg.conditions = | 425 | adapter->hs_cfg.conditions = |
426 | cpu_to_le32(prev_cond); | 426 | cpu_to_le32(prev_cond); |
@@ -454,7 +454,7 @@ int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type) | |||
454 | { | 454 | { |
455 | struct mwifiex_ds_hs_cfg hscfg; | 455 | struct mwifiex_ds_hs_cfg hscfg; |
456 | 456 | ||
457 | hscfg.conditions = HOST_SLEEP_CFG_CANCEL; | 457 | hscfg.conditions = HS_CFG_CANCEL; |
458 | hscfg.is_invoke_hostcmd = true; | 458 | hscfg.is_invoke_hostcmd = true; |
459 | 459 | ||
460 | return mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET, | 460 | return mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET, |
diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c index 296faec14365..8f923d0d2ba6 100644 --- a/drivers/net/wireless/mwifiex/txrx.c +++ b/drivers/net/wireless/mwifiex/txrx.c | |||
@@ -169,6 +169,8 @@ int mwifiex_write_data_complete(struct mwifiex_adapter *adapter, | |||
169 | if (!status) { | 169 | if (!status) { |
170 | priv->stats.tx_packets++; | 170 | priv->stats.tx_packets++; |
171 | priv->stats.tx_bytes += skb->len; | 171 | priv->stats.tx_bytes += skb->len; |
172 | if (priv->tx_timeout_cnt) | ||
173 | priv->tx_timeout_cnt = 0; | ||
172 | } else { | 174 | } else { |
173 | priv->stats.tx_errors++; | 175 | priv->stats.tx_errors++; |
174 | } | 176 | } |
diff --git a/drivers/net/wireless/mwifiex/util.c b/drivers/net/wireless/mwifiex/util.c index 21553976b550..54667e65ca47 100644 --- a/drivers/net/wireless/mwifiex/util.c +++ b/drivers/net/wireless/mwifiex/util.c | |||
@@ -195,7 +195,7 @@ int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb) | |||
195 | skb->protocol = eth_type_trans(skb, priv->netdev); | 195 | skb->protocol = eth_type_trans(skb, priv->netdev); |
196 | skb->ip_summed = CHECKSUM_NONE; | 196 | skb->ip_summed = CHECKSUM_NONE; |
197 | 197 | ||
198 | /* This is required only in case of 11n and USB as we alloc | 198 | /* This is required only in case of 11n and USB/PCIE as we alloc |
199 | * a buffer of 4K only if its 11N (to be able to receive 4K | 199 | * a buffer of 4K only if its 11N (to be able to receive 4K |
200 | * AMSDU packets). In case of SD we allocate buffers based | 200 | * AMSDU packets). In case of SD we allocate buffers based |
201 | * on the size of packet and hence this is not needed. | 201 | * on the size of packet and hence this is not needed. |
@@ -212,7 +212,8 @@ int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb) | |||
212 | * fragments. Currently we fail the Filesndl-ht.scr script | 212 | * fragments. Currently we fail the Filesndl-ht.scr script |
213 | * for UDP, hence this fix | 213 | * for UDP, hence this fix |
214 | */ | 214 | */ |
215 | if ((priv->adapter->iface_type == MWIFIEX_USB) && | 215 | if ((priv->adapter->iface_type == MWIFIEX_USB || |
216 | priv->adapter->iface_type == MWIFIEX_PCIE) && | ||
216 | (skb->truesize > MWIFIEX_RX_DATA_BUF_SIZE)) | 217 | (skb->truesize > MWIFIEX_RX_DATA_BUF_SIZE)) |
217 | skb->truesize += (skb->len - MWIFIEX_RX_DATA_BUF_SIZE); | 218 | skb->truesize += (skb->len - MWIFIEX_RX_DATA_BUF_SIZE); |
218 | 219 | ||
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 091d9a64080a..0640e7d7f0c2 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c | |||
@@ -232,6 +232,7 @@ struct mwl8k_priv { | |||
232 | u16 num_mcaddrs; | 232 | u16 num_mcaddrs; |
233 | u8 hw_rev; | 233 | u8 hw_rev; |
234 | u32 fw_rev; | 234 | u32 fw_rev; |
235 | u32 caps; | ||
235 | 236 | ||
236 | /* | 237 | /* |
237 | * Running count of TX packets in flight, to avoid | 238 | * Running count of TX packets in flight, to avoid |
@@ -284,6 +285,7 @@ struct mwl8k_priv { | |||
284 | unsigned fw_state; | 285 | unsigned fw_state; |
285 | char *fw_pref; | 286 | char *fw_pref; |
286 | char *fw_alt; | 287 | char *fw_alt; |
288 | bool is_8764; | ||
287 | struct completion firmware_loading_complete; | 289 | struct completion firmware_loading_complete; |
288 | 290 | ||
289 | /* bitmap of running BSSes */ | 291 | /* bitmap of running BSSes */ |
@@ -600,13 +602,18 @@ mwl8k_send_fw_load_cmd(struct mwl8k_priv *priv, void *data, int length) | |||
600 | loops = 1000; | 602 | loops = 1000; |
601 | do { | 603 | do { |
602 | u32 int_code; | 604 | u32 int_code; |
603 | 605 | if (priv->is_8764) { | |
604 | int_code = ioread32(regs + MWL8K_HIU_INT_CODE); | 606 | int_code = ioread32(regs + |
605 | if (int_code == MWL8K_INT_CODE_CMD_FINISHED) { | 607 | MWL8K_HIU_H2A_INTERRUPT_STATUS); |
606 | iowrite32(0, regs + MWL8K_HIU_INT_CODE); | 608 | if (int_code == 0) |
607 | break; | 609 | break; |
610 | } else { | ||
611 | int_code = ioread32(regs + MWL8K_HIU_INT_CODE); | ||
612 | if (int_code == MWL8K_INT_CODE_CMD_FINISHED) { | ||
613 | iowrite32(0, regs + MWL8K_HIU_INT_CODE); | ||
614 | break; | ||
615 | } | ||
608 | } | 616 | } |
609 | |||
610 | cond_resched(); | 617 | cond_resched(); |
611 | udelay(1); | 618 | udelay(1); |
612 | } while (--loops); | 619 | } while (--loops); |
@@ -724,7 +731,7 @@ static int mwl8k_load_firmware(struct ieee80211_hw *hw) | |||
724 | int rc; | 731 | int rc; |
725 | int loops; | 732 | int loops; |
726 | 733 | ||
727 | if (!memcmp(fw->data, "\x01\x00\x00\x00", 4)) { | 734 | if (!memcmp(fw->data, "\x01\x00\x00\x00", 4) && !priv->is_8764) { |
728 | const struct firmware *helper = priv->fw_helper; | 735 | const struct firmware *helper = priv->fw_helper; |
729 | 736 | ||
730 | if (helper == NULL) { | 737 | if (helper == NULL) { |
@@ -743,7 +750,10 @@ static int mwl8k_load_firmware(struct ieee80211_hw *hw) | |||
743 | 750 | ||
744 | rc = mwl8k_feed_fw_image(priv, fw->data, fw->size); | 751 | rc = mwl8k_feed_fw_image(priv, fw->data, fw->size); |
745 | } else { | 752 | } else { |
746 | rc = mwl8k_load_fw_image(priv, fw->data, fw->size); | 753 | if (priv->is_8764) |
754 | rc = mwl8k_feed_fw_image(priv, fw->data, fw->size); | ||
755 | else | ||
756 | rc = mwl8k_load_fw_image(priv, fw->data, fw->size); | ||
747 | } | 757 | } |
748 | 758 | ||
749 | if (rc) { | 759 | if (rc) { |
@@ -908,9 +918,9 @@ static void mwl8k_encapsulate_tx_frame(struct mwl8k_priv *priv, | |||
908 | } | 918 | } |
909 | 919 | ||
910 | /* | 920 | /* |
911 | * Packet reception for 88w8366 AP firmware. | 921 | * Packet reception for 88w8366/88w8764 AP firmware. |
912 | */ | 922 | */ |
913 | struct mwl8k_rxd_8366_ap { | 923 | struct mwl8k_rxd_ap { |
914 | __le16 pkt_len; | 924 | __le16 pkt_len; |
915 | __u8 sq2; | 925 | __u8 sq2; |
916 | __u8 rate; | 926 | __u8 rate; |
@@ -928,30 +938,30 @@ struct mwl8k_rxd_8366_ap { | |||
928 | __u8 rx_ctrl; | 938 | __u8 rx_ctrl; |
929 | } __packed; | 939 | } __packed; |
930 | 940 | ||
931 | #define MWL8K_8366_AP_RATE_INFO_MCS_FORMAT 0x80 | 941 | #define MWL8K_AP_RATE_INFO_MCS_FORMAT 0x80 |
932 | #define MWL8K_8366_AP_RATE_INFO_40MHZ 0x40 | 942 | #define MWL8K_AP_RATE_INFO_40MHZ 0x40 |
933 | #define MWL8K_8366_AP_RATE_INFO_RATEID(x) ((x) & 0x3f) | 943 | #define MWL8K_AP_RATE_INFO_RATEID(x) ((x) & 0x3f) |
934 | 944 | ||
935 | #define MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST 0x80 | 945 | #define MWL8K_AP_RX_CTRL_OWNED_BY_HOST 0x80 |
936 | 946 | ||
937 | /* 8366 AP rx_status bits */ | 947 | /* 8366/8764 AP rx_status bits */ |
938 | #define MWL8K_8366_AP_RXSTAT_DECRYPT_ERR_MASK 0x80 | 948 | #define MWL8K_AP_RXSTAT_DECRYPT_ERR_MASK 0x80 |
939 | #define MWL8K_8366_AP_RXSTAT_GENERAL_DECRYPT_ERR 0xFF | 949 | #define MWL8K_AP_RXSTAT_GENERAL_DECRYPT_ERR 0xFF |
940 | #define MWL8K_8366_AP_RXSTAT_TKIP_DECRYPT_MIC_ERR 0x02 | 950 | #define MWL8K_AP_RXSTAT_TKIP_DECRYPT_MIC_ERR 0x02 |
941 | #define MWL8K_8366_AP_RXSTAT_WEP_DECRYPT_ICV_ERR 0x04 | 951 | #define MWL8K_AP_RXSTAT_WEP_DECRYPT_ICV_ERR 0x04 |
942 | #define MWL8K_8366_AP_RXSTAT_TKIP_DECRYPT_ICV_ERR 0x08 | 952 | #define MWL8K_AP_RXSTAT_TKIP_DECRYPT_ICV_ERR 0x08 |
943 | 953 | ||
944 | static void mwl8k_rxd_8366_ap_init(void *_rxd, dma_addr_t next_dma_addr) | 954 | static void mwl8k_rxd_ap_init(void *_rxd, dma_addr_t next_dma_addr) |
945 | { | 955 | { |
946 | struct mwl8k_rxd_8366_ap *rxd = _rxd; | 956 | struct mwl8k_rxd_ap *rxd = _rxd; |
947 | 957 | ||
948 | rxd->next_rxd_phys_addr = cpu_to_le32(next_dma_addr); | 958 | rxd->next_rxd_phys_addr = cpu_to_le32(next_dma_addr); |
949 | rxd->rx_ctrl = MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST; | 959 | rxd->rx_ctrl = MWL8K_AP_RX_CTRL_OWNED_BY_HOST; |
950 | } | 960 | } |
951 | 961 | ||
952 | static void mwl8k_rxd_8366_ap_refill(void *_rxd, dma_addr_t addr, int len) | 962 | static void mwl8k_rxd_ap_refill(void *_rxd, dma_addr_t addr, int len) |
953 | { | 963 | { |
954 | struct mwl8k_rxd_8366_ap *rxd = _rxd; | 964 | struct mwl8k_rxd_ap *rxd = _rxd; |
955 | 965 | ||
956 | rxd->pkt_len = cpu_to_le16(len); | 966 | rxd->pkt_len = cpu_to_le16(len); |
957 | rxd->pkt_phys_addr = cpu_to_le32(addr); | 967 | rxd->pkt_phys_addr = cpu_to_le32(addr); |
@@ -960,12 +970,12 @@ static void mwl8k_rxd_8366_ap_refill(void *_rxd, dma_addr_t addr, int len) | |||
960 | } | 970 | } |
961 | 971 | ||
962 | static int | 972 | static int |
963 | mwl8k_rxd_8366_ap_process(void *_rxd, struct ieee80211_rx_status *status, | 973 | mwl8k_rxd_ap_process(void *_rxd, struct ieee80211_rx_status *status, |
964 | __le16 *qos, s8 *noise) | 974 | __le16 *qos, s8 *noise) |
965 | { | 975 | { |
966 | struct mwl8k_rxd_8366_ap *rxd = _rxd; | 976 | struct mwl8k_rxd_ap *rxd = _rxd; |
967 | 977 | ||
968 | if (!(rxd->rx_ctrl & MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST)) | 978 | if (!(rxd->rx_ctrl & MWL8K_AP_RX_CTRL_OWNED_BY_HOST)) |
969 | return -1; | 979 | return -1; |
970 | rmb(); | 980 | rmb(); |
971 | 981 | ||
@@ -974,11 +984,11 @@ mwl8k_rxd_8366_ap_process(void *_rxd, struct ieee80211_rx_status *status, | |||
974 | status->signal = -rxd->rssi; | 984 | status->signal = -rxd->rssi; |
975 | *noise = -rxd->noise_floor; | 985 | *noise = -rxd->noise_floor; |
976 | 986 | ||
977 | if (rxd->rate & MWL8K_8366_AP_RATE_INFO_MCS_FORMAT) { | 987 | if (rxd->rate & MWL8K_AP_RATE_INFO_MCS_FORMAT) { |
978 | status->flag |= RX_FLAG_HT; | 988 | status->flag |= RX_FLAG_HT; |
979 | if (rxd->rate & MWL8K_8366_AP_RATE_INFO_40MHZ) | 989 | if (rxd->rate & MWL8K_AP_RATE_INFO_40MHZ) |
980 | status->flag |= RX_FLAG_40MHZ; | 990 | status->flag |= RX_FLAG_40MHZ; |
981 | status->rate_idx = MWL8K_8366_AP_RATE_INFO_RATEID(rxd->rate); | 991 | status->rate_idx = MWL8K_AP_RATE_INFO_RATEID(rxd->rate); |
982 | } else { | 992 | } else { |
983 | int i; | 993 | int i; |
984 | 994 | ||
@@ -1002,19 +1012,19 @@ mwl8k_rxd_8366_ap_process(void *_rxd, struct ieee80211_rx_status *status, | |||
1002 | 1012 | ||
1003 | *qos = rxd->qos_control; | 1013 | *qos = rxd->qos_control; |
1004 | 1014 | ||
1005 | if ((rxd->rx_status != MWL8K_8366_AP_RXSTAT_GENERAL_DECRYPT_ERR) && | 1015 | if ((rxd->rx_status != MWL8K_AP_RXSTAT_GENERAL_DECRYPT_ERR) && |
1006 | (rxd->rx_status & MWL8K_8366_AP_RXSTAT_DECRYPT_ERR_MASK) && | 1016 | (rxd->rx_status & MWL8K_AP_RXSTAT_DECRYPT_ERR_MASK) && |
1007 | (rxd->rx_status & MWL8K_8366_AP_RXSTAT_TKIP_DECRYPT_MIC_ERR)) | 1017 | (rxd->rx_status & MWL8K_AP_RXSTAT_TKIP_DECRYPT_MIC_ERR)) |
1008 | status->flag |= RX_FLAG_MMIC_ERROR; | 1018 | status->flag |= RX_FLAG_MMIC_ERROR; |
1009 | 1019 | ||
1010 | return le16_to_cpu(rxd->pkt_len); | 1020 | return le16_to_cpu(rxd->pkt_len); |
1011 | } | 1021 | } |
1012 | 1022 | ||
1013 | static struct rxd_ops rxd_8366_ap_ops = { | 1023 | static struct rxd_ops rxd_ap_ops = { |
1014 | .rxd_size = sizeof(struct mwl8k_rxd_8366_ap), | 1024 | .rxd_size = sizeof(struct mwl8k_rxd_ap), |
1015 | .rxd_init = mwl8k_rxd_8366_ap_init, | 1025 | .rxd_init = mwl8k_rxd_ap_init, |
1016 | .rxd_refill = mwl8k_rxd_8366_ap_refill, | 1026 | .rxd_refill = mwl8k_rxd_ap_refill, |
1017 | .rxd_process = mwl8k_rxd_8366_ap_process, | 1027 | .rxd_process = mwl8k_rxd_ap_process, |
1018 | }; | 1028 | }; |
1019 | 1029 | ||
1020 | /* | 1030 | /* |
@@ -2401,6 +2411,9 @@ mwl8k_set_caps(struct ieee80211_hw *hw, u32 caps) | |||
2401 | { | 2411 | { |
2402 | struct mwl8k_priv *priv = hw->priv; | 2412 | struct mwl8k_priv *priv = hw->priv; |
2403 | 2413 | ||
2414 | if (priv->caps) | ||
2415 | return; | ||
2416 | |||
2404 | if ((caps & MWL8K_CAP_2GHZ4) || !(caps & MWL8K_CAP_BAND_MASK)) { | 2417 | if ((caps & MWL8K_CAP_2GHZ4) || !(caps & MWL8K_CAP_BAND_MASK)) { |
2405 | mwl8k_setup_2ghz_band(hw); | 2418 | mwl8k_setup_2ghz_band(hw); |
2406 | if (caps & MWL8K_CAP_MIMO) | 2419 | if (caps & MWL8K_CAP_MIMO) |
@@ -2412,6 +2425,8 @@ mwl8k_set_caps(struct ieee80211_hw *hw, u32 caps) | |||
2412 | if (caps & MWL8K_CAP_MIMO) | 2425 | if (caps & MWL8K_CAP_MIMO) |
2413 | mwl8k_set_ht_caps(hw, &priv->band_50, caps); | 2426 | mwl8k_set_ht_caps(hw, &priv->band_50, caps); |
2414 | } | 2427 | } |
2428 | |||
2429 | priv->caps = caps; | ||
2415 | } | 2430 | } |
2416 | 2431 | ||
2417 | static int mwl8k_cmd_get_hw_spec_sta(struct ieee80211_hw *hw) | 2432 | static int mwl8k_cmd_get_hw_spec_sta(struct ieee80211_hw *hw) |
@@ -5429,12 +5444,17 @@ enum { | |||
5429 | MWL8363 = 0, | 5444 | MWL8363 = 0, |
5430 | MWL8687, | 5445 | MWL8687, |
5431 | MWL8366, | 5446 | MWL8366, |
5447 | MWL8764, | ||
5432 | }; | 5448 | }; |
5433 | 5449 | ||
5434 | #define MWL8K_8366_AP_FW_API 3 | 5450 | #define MWL8K_8366_AP_FW_API 3 |
5435 | #define _MWL8K_8366_AP_FW(api) "mwl8k/fmimage_8366_ap-" #api ".fw" | 5451 | #define _MWL8K_8366_AP_FW(api) "mwl8k/fmimage_8366_ap-" #api ".fw" |
5436 | #define MWL8K_8366_AP_FW(api) _MWL8K_8366_AP_FW(api) | 5452 | #define MWL8K_8366_AP_FW(api) _MWL8K_8366_AP_FW(api) |
5437 | 5453 | ||
5454 | #define MWL8K_8764_AP_FW_API 1 | ||
5455 | #define _MWL8K_8764_AP_FW(api) "mwl8k/fmimage_8764_ap-" #api ".fw" | ||
5456 | #define MWL8K_8764_AP_FW(api) _MWL8K_8764_AP_FW(api) | ||
5457 | |||
5438 | static struct mwl8k_device_info mwl8k_info_tbl[] = { | 5458 | static struct mwl8k_device_info mwl8k_info_tbl[] = { |
5439 | [MWL8363] = { | 5459 | [MWL8363] = { |
5440 | .part_name = "88w8363", | 5460 | .part_name = "88w8363", |
@@ -5452,7 +5472,13 @@ static struct mwl8k_device_info mwl8k_info_tbl[] = { | |||
5452 | .fw_image_sta = "mwl8k/fmimage_8366.fw", | 5472 | .fw_image_sta = "mwl8k/fmimage_8366.fw", |
5453 | .fw_image_ap = MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API), | 5473 | .fw_image_ap = MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API), |
5454 | .fw_api_ap = MWL8K_8366_AP_FW_API, | 5474 | .fw_api_ap = MWL8K_8366_AP_FW_API, |
5455 | .ap_rxd_ops = &rxd_8366_ap_ops, | 5475 | .ap_rxd_ops = &rxd_ap_ops, |
5476 | }, | ||
5477 | [MWL8764] = { | ||
5478 | .part_name = "88w8764", | ||
5479 | .fw_image_ap = MWL8K_8764_AP_FW(MWL8K_8764_AP_FW_API), | ||
5480 | .fw_api_ap = MWL8K_8764_AP_FW_API, | ||
5481 | .ap_rxd_ops = &rxd_ap_ops, | ||
5456 | }, | 5482 | }, |
5457 | }; | 5483 | }; |
5458 | 5484 | ||
@@ -5474,6 +5500,7 @@ static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = { | |||
5474 | { PCI_VDEVICE(MARVELL, 0x2a41), .driver_data = MWL8366, }, | 5500 | { PCI_VDEVICE(MARVELL, 0x2a41), .driver_data = MWL8366, }, |
5475 | { PCI_VDEVICE(MARVELL, 0x2a42), .driver_data = MWL8366, }, | 5501 | { PCI_VDEVICE(MARVELL, 0x2a42), .driver_data = MWL8366, }, |
5476 | { PCI_VDEVICE(MARVELL, 0x2a43), .driver_data = MWL8366, }, | 5502 | { PCI_VDEVICE(MARVELL, 0x2a43), .driver_data = MWL8366, }, |
5503 | { PCI_VDEVICE(MARVELL, 0x2b36), .driver_data = MWL8764, }, | ||
5477 | { }, | 5504 | { }, |
5478 | }; | 5505 | }; |
5479 | MODULE_DEVICE_TABLE(pci, mwl8k_pci_id_table); | 5506 | MODULE_DEVICE_TABLE(pci, mwl8k_pci_id_table); |
@@ -5995,6 +6022,8 @@ static int mwl8k_probe(struct pci_dev *pdev, | |||
5995 | priv->pdev = pdev; | 6022 | priv->pdev = pdev; |
5996 | priv->device_info = &mwl8k_info_tbl[id->driver_data]; | 6023 | priv->device_info = &mwl8k_info_tbl[id->driver_data]; |
5997 | 6024 | ||
6025 | if (id->driver_data == MWL8764) | ||
6026 | priv->is_8764 = true; | ||
5998 | 6027 | ||
5999 | priv->sram = pci_iomap(pdev, 0, 0x10000); | 6028 | priv->sram = pci_iomap(pdev, 0, 0x10000); |
6000 | if (priv->sram == NULL) { | 6029 | if (priv->sram == NULL) { |
diff --git a/drivers/net/wireless/orinoco/orinoco_usb.c b/drivers/net/wireless/orinoco/orinoco_usb.c index 7744f42de1ea..1f9cb55c3360 100644 --- a/drivers/net/wireless/orinoco/orinoco_usb.c +++ b/drivers/net/wireless/orinoco/orinoco_usb.c | |||
@@ -1584,7 +1584,7 @@ static int ezusb_probe(struct usb_interface *interface, | |||
1584 | struct ezusb_priv *upriv = NULL; | 1584 | struct ezusb_priv *upriv = NULL; |
1585 | struct usb_interface_descriptor *iface_desc; | 1585 | struct usb_interface_descriptor *iface_desc; |
1586 | struct usb_endpoint_descriptor *ep; | 1586 | struct usb_endpoint_descriptor *ep; |
1587 | const struct firmware *fw_entry; | 1587 | const struct firmware *fw_entry = NULL; |
1588 | int retval = 0; | 1588 | int retval = 0; |
1589 | int i; | 1589 | int i; |
1590 | 1590 | ||
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 3109c0db66e1..4775b5d172d5 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c | |||
@@ -144,7 +144,7 @@ static int psm; | |||
144 | static char *essid; | 144 | static char *essid; |
145 | 145 | ||
146 | /* Default to encapsulation unless translation requested */ | 146 | /* Default to encapsulation unless translation requested */ |
147 | static int translate = 1; | 147 | static bool translate = 1; |
148 | 148 | ||
149 | static int country = USA; | 149 | static int country = USA; |
150 | 150 | ||
@@ -178,7 +178,7 @@ module_param(hop_dwell, int, 0); | |||
178 | module_param(beacon_period, int, 0); | 178 | module_param(beacon_period, int, 0); |
179 | module_param(psm, int, 0); | 179 | module_param(psm, int, 0); |
180 | module_param(essid, charp, 0); | 180 | module_param(essid, charp, 0); |
181 | module_param(translate, int, 0); | 181 | module_param(translate, bool, 0); |
182 | module_param(country, int, 0); | 182 | module_param(country, int, 0); |
183 | module_param(sniffer, int, 0); | 183 | module_param(sniffer, int, 0); |
184 | module_param(bc, int, 0); | 184 | module_param(bc, int, 0); |
@@ -1353,7 +1353,7 @@ static int ray_get_range(struct net_device *dev, struct iw_request_info *info, | |||
1353 | static int ray_set_framing(struct net_device *dev, struct iw_request_info *info, | 1353 | static int ray_set_framing(struct net_device *dev, struct iw_request_info *info, |
1354 | union iwreq_data *wrqu, char *extra) | 1354 | union iwreq_data *wrqu, char *extra) |
1355 | { | 1355 | { |
1356 | translate = *(extra); /* Set framing mode */ | 1356 | translate = !!*(extra); /* Set framing mode */ |
1357 | 1357 | ||
1358 | return 0; | 1358 | return 0; |
1359 | } | 1359 | } |
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 525fd7521dff..8169a85c4498 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * Driver for RNDIS based wireless USB devices. | 2 | * Driver for RNDIS based wireless USB devices. |
3 | * | 3 | * |
4 | * Copyright (C) 2007 by Bjorge Dijkstra <bjd@jooz.net> | 4 | * Copyright (C) 2007 by Bjorge Dijkstra <bjd@jooz.net> |
5 | * Copyright (C) 2008-2009 by Jussi Kivilinna <jussi.kivilinna@mbnet.fi> | 5 | * Copyright (C) 2008-2009 by Jussi Kivilinna <jussi.kivilinna@iki.fi> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published by | 8 | * it under the terms of the GNU General Public License as published by |
@@ -2839,8 +2839,7 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev) | |||
2839 | } else if (priv->infra_mode == NDIS_80211_INFRA_ADHOC) | 2839 | } else if (priv->infra_mode == NDIS_80211_INFRA_ADHOC) |
2840 | cfg80211_ibss_joined(usbdev->net, bssid, GFP_KERNEL); | 2840 | cfg80211_ibss_joined(usbdev->net, bssid, GFP_KERNEL); |
2841 | 2841 | ||
2842 | if (info != NULL) | 2842 | kfree(info); |
2843 | kfree(info); | ||
2844 | 2843 | ||
2845 | priv->connected = true; | 2844 | priv->connected = true; |
2846 | memcpy(priv->bssid, bssid, ETH_ALEN); | 2845 | memcpy(priv->bssid, bssid, ETH_ALEN); |
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index 2bf4efa33186..ffe61d53e3fe 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig | |||
@@ -169,6 +169,13 @@ config RT2800USB_RT53XX | |||
169 | rt2800usb driver. | 169 | rt2800usb driver. |
170 | Supported chips: RT5370 | 170 | Supported chips: RT5370 |
171 | 171 | ||
172 | config RT2800USB_RT55XX | ||
173 | bool "rt2800usb - Include support for rt55xx devices (EXPERIMENTAL)" | ||
174 | ---help--- | ||
175 | This adds support for rt55xx wireless chipset family to the | ||
176 | rt2800usb driver. | ||
177 | Supported chips: RT5572 | ||
178 | |||
172 | config RT2800USB_UNKNOWN | 179 | config RT2800USB_UNKNOWN |
173 | bool "rt2800usb - Include support for unknown (USB) devices" | 180 | bool "rt2800usb - Include support for unknown (USB) devices" |
174 | default n | 181 | default n |
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index 4db1088a847f..a7630d5ec892 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h | |||
@@ -51,6 +51,7 @@ | |||
51 | * RF3320 2.4G 1T1R(RT3350/RT3370/RT3390) | 51 | * RF3320 2.4G 1T1R(RT3350/RT3370/RT3390) |
52 | * RF3322 2.4G 2T2R(RT3352/RT3371/RT3372/RT3391/RT3392) | 52 | * RF3322 2.4G 2T2R(RT3352/RT3371/RT3372/RT3391/RT3392) |
53 | * RF3053 2.4G/5G 3T3R(RT3883/RT3563/RT3573/RT3593/RT3662) | 53 | * RF3053 2.4G/5G 3T3R(RT3883/RT3563/RT3573/RT3593/RT3662) |
54 | * RF5592 2.4G/5G 2T2R | ||
54 | * RF5360 2.4G 1T1R | 55 | * RF5360 2.4G 1T1R |
55 | * RF5370 2.4G 1T1R | 56 | * RF5370 2.4G 1T1R |
56 | * RF5390 2.4G 1T1R | 57 | * RF5390 2.4G 1T1R |
@@ -68,6 +69,7 @@ | |||
68 | #define RF3320 0x000b | 69 | #define RF3320 0x000b |
69 | #define RF3322 0x000c | 70 | #define RF3322 0x000c |
70 | #define RF3053 0x000d | 71 | #define RF3053 0x000d |
72 | #define RF5592 0x000f | ||
71 | #define RF3290 0x3290 | 73 | #define RF3290 0x3290 |
72 | #define RF5360 0x5360 | 74 | #define RF5360 0x5360 |
73 | #define RF5370 0x5370 | 75 | #define RF5370 0x5370 |
@@ -88,11 +90,8 @@ | |||
88 | #define REV_RT3390E 0x0211 | 90 | #define REV_RT3390E 0x0211 |
89 | #define REV_RT5390F 0x0502 | 91 | #define REV_RT5390F 0x0502 |
90 | #define REV_RT5390R 0x1502 | 92 | #define REV_RT5390R 0x1502 |
93 | #define REV_RT5592C 0x0221 | ||
91 | 94 | ||
92 | /* | ||
93 | * Signal information. | ||
94 | * Default offset is required for RSSI <-> dBm conversion. | ||
95 | */ | ||
96 | #define DEFAULT_RSSI_OFFSET 120 | 95 | #define DEFAULT_RSSI_OFFSET 120 |
97 | 96 | ||
98 | /* | 97 | /* |
@@ -690,6 +689,12 @@ | |||
690 | #define GPIO_SWITCH_7 FIELD32(0x00000080) | 689 | #define GPIO_SWITCH_7 FIELD32(0x00000080) |
691 | 690 | ||
692 | /* | 691 | /* |
692 | * FIXME: where the DEBUG_INDEX name come from? | ||
693 | */ | ||
694 | #define MAC_DEBUG_INDEX 0x05e8 | ||
695 | #define MAC_DEBUG_INDEX_XTAL FIELD32(0x80000000) | ||
696 | |||
697 | /* | ||
693 | * MAC Control/Status Registers(CSR). | 698 | * MAC Control/Status Registers(CSR). |
694 | * Some values are set in TU, whereas 1 TU == 1024 us. | 699 | * Some values are set in TU, whereas 1 TU == 1024 us. |
695 | */ | 700 | */ |
@@ -1934,6 +1939,9 @@ struct mac_iveiv_entry { | |||
1934 | #define BBP4_BANDWIDTH FIELD8(0x18) | 1939 | #define BBP4_BANDWIDTH FIELD8(0x18) |
1935 | #define BBP4_MAC_IF_CTRL FIELD8(0x40) | 1940 | #define BBP4_MAC_IF_CTRL FIELD8(0x40) |
1936 | 1941 | ||
1942 | /* BBP27 */ | ||
1943 | #define BBP27_RX_CHAIN_SEL FIELD8(0x60) | ||
1944 | |||
1937 | /* | 1945 | /* |
1938 | * BBP 47: Bandwidth | 1946 | * BBP 47: Bandwidth |
1939 | */ | 1947 | */ |
@@ -1948,6 +1956,20 @@ struct mac_iveiv_entry { | |||
1948 | #define BBP49_UPDATE_FLAG FIELD8(0x01) | 1956 | #define BBP49_UPDATE_FLAG FIELD8(0x01) |
1949 | 1957 | ||
1950 | /* | 1958 | /* |
1959 | * BBP 105: | ||
1960 | * - bit0: detect SIG on primary channel only (on 40MHz bandwidth) | ||
1961 | * - bit1: FEQ (Feed Forward Compensation) for independend streams | ||
1962 | * - bit2: MLD (Maximum Likehood Detection) for 2 streams (reserved on single | ||
1963 | * stream) | ||
1964 | * - bit4: channel estimation updates based on remodulation of | ||
1965 | * L-SIG and HT-SIG symbols | ||
1966 | */ | ||
1967 | #define BBP105_DETECT_SIG_ON_PRIMARY FIELD8(0x01) | ||
1968 | #define BBP105_FEQ FIELD8(0x02) | ||
1969 | #define BBP105_MLD FIELD8(0x04) | ||
1970 | #define BBP105_SIG_REMODULATION FIELD8(0x08) | ||
1971 | |||
1972 | /* | ||
1951 | * BBP 109 | 1973 | * BBP 109 |
1952 | */ | 1974 | */ |
1953 | #define BBP109_TX0_POWER FIELD8(0x0f) | 1975 | #define BBP109_TX0_POWER FIELD8(0x0f) |
@@ -1967,6 +1989,11 @@ struct mac_iveiv_entry { | |||
1967 | #define BBP152_RX_DEFAULT_ANT FIELD8(0x80) | 1989 | #define BBP152_RX_DEFAULT_ANT FIELD8(0x80) |
1968 | 1990 | ||
1969 | /* | 1991 | /* |
1992 | * BBP 254: unknown | ||
1993 | */ | ||
1994 | #define BBP254_BIT7 FIELD8(0x80) | ||
1995 | |||
1996 | /* | ||
1970 | * RFCSR registers | 1997 | * RFCSR registers |
1971 | * The wordsize of the RFCSR is 8 bits. | 1998 | * The wordsize of the RFCSR is 8 bits. |
1972 | */ | 1999 | */ |
@@ -2022,9 +2049,18 @@ struct mac_iveiv_entry { | |||
2022 | #define RFCSR7_BITS67 FIELD8(0xc0) | 2049 | #define RFCSR7_BITS67 FIELD8(0xc0) |
2023 | 2050 | ||
2024 | /* | 2051 | /* |
2052 | * RFCSR 9: | ||
2053 | */ | ||
2054 | #define RFCSR9_K FIELD8(0x0f) | ||
2055 | #define RFCSR9_N FIELD8(0x10) | ||
2056 | #define RFCSR9_UNKNOWN FIELD8(0x60) | ||
2057 | #define RFCSR9_MOD FIELD8(0x80) | ||
2058 | |||
2059 | /* | ||
2025 | * RFCSR 11: | 2060 | * RFCSR 11: |
2026 | */ | 2061 | */ |
2027 | #define RFCSR11_R FIELD8(0x03) | 2062 | #define RFCSR11_R FIELD8(0x03) |
2063 | #define RFCSR11_MOD FIELD8(0xc0) | ||
2028 | 2064 | ||
2029 | /* | 2065 | /* |
2030 | * RFCSR 12: | 2066 | * RFCSR 12: |
@@ -2130,11 +2166,13 @@ struct mac_iveiv_entry { | |||
2130 | * RFCSR 49: | 2166 | * RFCSR 49: |
2131 | */ | 2167 | */ |
2132 | #define RFCSR49_TX FIELD8(0x3f) | 2168 | #define RFCSR49_TX FIELD8(0x3f) |
2169 | #define RFCSR49_EP FIELD8(0xc0) | ||
2133 | 2170 | ||
2134 | /* | 2171 | /* |
2135 | * RFCSR 50: | 2172 | * RFCSR 50: |
2136 | */ | 2173 | */ |
2137 | #define RFCSR50_TX FIELD8(0x3f) | 2174 | #define RFCSR50_TX FIELD8(0x3f) |
2175 | #define RFCSR50_EP FIELD8(0xc0) | ||
2138 | 2176 | ||
2139 | /* | 2177 | /* |
2140 | * RF registers | 2178 | * RF registers |
@@ -2497,6 +2535,61 @@ struct mac_iveiv_entry { | |||
2497 | #define EEPROM_BBP_REG_ID FIELD16(0xff00) | 2535 | #define EEPROM_BBP_REG_ID FIELD16(0xff00) |
2498 | 2536 | ||
2499 | /* | 2537 | /* |
2538 | * EEPROM IQ Calibration, unlike other entries those are byte addresses. | ||
2539 | */ | ||
2540 | |||
2541 | #define EEPROM_IQ_GAIN_CAL_TX0_2G 0x130 | ||
2542 | #define EEPROM_IQ_PHASE_CAL_TX0_2G 0x131 | ||
2543 | #define EEPROM_IQ_GROUPDELAY_CAL_TX0_2G 0x132 | ||
2544 | #define EEPROM_IQ_GAIN_CAL_TX1_2G 0x133 | ||
2545 | #define EEPROM_IQ_PHASE_CAL_TX1_2G 0x134 | ||
2546 | #define EEPROM_IQ_GROUPDELAY_CAL_TX1_2G 0x135 | ||
2547 | #define EEPROM_IQ_GAIN_CAL_RX0_2G 0x136 | ||
2548 | #define EEPROM_IQ_PHASE_CAL_RX0_2G 0x137 | ||
2549 | #define EEPROM_IQ_GROUPDELAY_CAL_RX0_2G 0x138 | ||
2550 | #define EEPROM_IQ_GAIN_CAL_RX1_2G 0x139 | ||
2551 | #define EEPROM_IQ_PHASE_CAL_RX1_2G 0x13A | ||
2552 | #define EEPROM_IQ_GROUPDELAY_CAL_RX1_2G 0x13B | ||
2553 | #define EEPROM_RF_IQ_COMPENSATION_CONTROL 0x13C | ||
2554 | #define EEPROM_RF_IQ_IMBALANCE_COMPENSATION_CONTROL 0x13D | ||
2555 | #define EEPROM_IQ_GAIN_CAL_TX0_CH36_TO_CH64_5G 0x144 | ||
2556 | #define EEPROM_IQ_PHASE_CAL_TX0_CH36_TO_CH64_5G 0x145 | ||
2557 | #define EEPROM_IQ_GAIN_CAL_TX0_CH100_TO_CH138_5G 0X146 | ||
2558 | #define EEPROM_IQ_PHASE_CAL_TX0_CH100_TO_CH138_5G 0x147 | ||
2559 | #define EEPROM_IQ_GAIN_CAL_TX0_CH140_TO_CH165_5G 0x148 | ||
2560 | #define EEPROM_IQ_PHASE_CAL_TX0_CH140_TO_CH165_5G 0x149 | ||
2561 | #define EEPROM_IQ_GAIN_CAL_TX1_CH36_TO_CH64_5G 0x14A | ||
2562 | #define EEPROM_IQ_PHASE_CAL_TX1_CH36_TO_CH64_5G 0x14B | ||
2563 | #define EEPROM_IQ_GAIN_CAL_TX1_CH100_TO_CH138_5G 0X14C | ||
2564 | #define EEPROM_IQ_PHASE_CAL_TX1_CH100_TO_CH138_5G 0x14D | ||
2565 | #define EEPROM_IQ_GAIN_CAL_TX1_CH140_TO_CH165_5G 0x14E | ||
2566 | #define EEPROM_IQ_PHASE_CAL_TX1_CH140_TO_CH165_5G 0x14F | ||
2567 | #define EEPROM_IQ_GROUPDELAY_CAL_TX0_CH36_TO_CH64_5G 0x150 | ||
2568 | #define EEPROM_IQ_GROUPDELAY_CAL_TX1_CH36_TO_CH64_5G 0x151 | ||
2569 | #define EEPROM_IQ_GROUPDELAY_CAL_TX0_CH100_TO_CH138_5G 0x152 | ||
2570 | #define EEPROM_IQ_GROUPDELAY_CAL_TX1_CH100_TO_CH138_5G 0x153 | ||
2571 | #define EEPROM_IQ_GROUPDELAY_CAL_TX0_CH140_TO_CH165_5G 0x154 | ||
2572 | #define EEPROM_IQ_GROUPDELAY_CAL_TX1_CH140_TO_CH165_5G 0x155 | ||
2573 | #define EEPROM_IQ_GAIN_CAL_RX0_CH36_TO_CH64_5G 0x156 | ||
2574 | #define EEPROM_IQ_PHASE_CAL_RX0_CH36_TO_CH64_5G 0x157 | ||
2575 | #define EEPROM_IQ_GAIN_CAL_RX0_CH100_TO_CH138_5G 0X158 | ||
2576 | #define EEPROM_IQ_PHASE_CAL_RX0_CH100_TO_CH138_5G 0x159 | ||
2577 | #define EEPROM_IQ_GAIN_CAL_RX0_CH140_TO_CH165_5G 0x15A | ||
2578 | #define EEPROM_IQ_PHASE_CAL_RX0_CH140_TO_CH165_5G 0x15B | ||
2579 | #define EEPROM_IQ_GAIN_CAL_RX1_CH36_TO_CH64_5G 0x15C | ||
2580 | #define EEPROM_IQ_PHASE_CAL_RX1_CH36_TO_CH64_5G 0x15D | ||
2581 | #define EEPROM_IQ_GAIN_CAL_RX1_CH100_TO_CH138_5G 0X15E | ||
2582 | #define EEPROM_IQ_PHASE_CAL_RX1_CH100_TO_CH138_5G 0x15F | ||
2583 | #define EEPROM_IQ_GAIN_CAL_RX1_CH140_TO_CH165_5G 0x160 | ||
2584 | #define EEPROM_IQ_PHASE_CAL_RX1_CH140_TO_CH165_5G 0x161 | ||
2585 | #define EEPROM_IQ_GROUPDELAY_CAL_RX0_CH36_TO_CH64_5G 0x162 | ||
2586 | #define EEPROM_IQ_GROUPDELAY_CAL_RX1_CH36_TO_CH64_5G 0x163 | ||
2587 | #define EEPROM_IQ_GROUPDELAY_CAL_RX0_CH100_TO_CH138_5G 0x164 | ||
2588 | #define EEPROM_IQ_GROUPDELAY_CAL_RX1_CH100_TO_CH138_5G 0x165 | ||
2589 | #define EEPROM_IQ_GROUPDELAY_CAL_RX0_CH140_TO_CH165_5G 0x166 | ||
2590 | #define EEPROM_IQ_GROUPDELAY_CAL_RX1_CH140_TO_CH165_5G 0x167 | ||
2591 | |||
2592 | /* | ||
2500 | * MCU mailbox commands. | 2593 | * MCU mailbox commands. |
2501 | * MCU_SLEEP - go to power-save mode. | 2594 | * MCU_SLEEP - go to power-save mode. |
2502 | * arg1: 1: save as much power as possible, 0: save less power. | 2595 | * arg1: 1: save as much power as possible, 0: save less power. |
@@ -2535,6 +2628,8 @@ struct mac_iveiv_entry { | |||
2535 | #define TXWI_DESC_SIZE (4 * sizeof(__le32)) | 2628 | #define TXWI_DESC_SIZE (4 * sizeof(__le32)) |
2536 | #define RXWI_DESC_SIZE (4 * sizeof(__le32)) | 2629 | #define RXWI_DESC_SIZE (4 * sizeof(__le32)) |
2537 | 2630 | ||
2631 | #define TXWI_DESC_SIZE_5592 (5 * sizeof(__le32)) | ||
2632 | #define RXWI_DESC_SIZE_5592 (6 * sizeof(__le32)) | ||
2538 | /* | 2633 | /* |
2539 | * TX WI structure | 2634 | * TX WI structure |
2540 | */ | 2635 | */ |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index a658b4bc7da2..f08a0424fe4d 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | |||
@@ -527,8 +527,10 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev, | |||
527 | */ | 527 | */ |
528 | rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0); | 528 | rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0); |
529 | rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); | 529 | rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); |
530 | if (rt2x00_is_usb(rt2x00dev)) | 530 | if (rt2x00_is_usb(rt2x00dev)) { |
531 | rt2800_register_write(rt2x00dev, H2M_INT_SRC, 0); | 531 | rt2800_register_write(rt2x00dev, H2M_INT_SRC, 0); |
532 | rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0); | ||
533 | } | ||
532 | msleep(1); | 534 | msleep(1); |
533 | 535 | ||
534 | return 0; | 536 | return 0; |
@@ -674,11 +676,6 @@ void rt2800_process_rxwi(struct queue_entry *entry, | |||
674 | * Convert descriptor AGC value to RSSI value. | 676 | * Convert descriptor AGC value to RSSI value. |
675 | */ | 677 | */ |
676 | rxdesc->rssi = rt2800_agc_to_rssi(entry->queue->rt2x00dev, word); | 678 | rxdesc->rssi = rt2800_agc_to_rssi(entry->queue->rt2x00dev, word); |
677 | |||
678 | /* | ||
679 | * Remove RXWI descriptor from start of buffer. | ||
680 | */ | ||
681 | skb_pull(entry->skb, RXWI_DESC_SIZE); | ||
682 | } | 679 | } |
683 | EXPORT_SYMBOL_GPL(rt2800_process_rxwi); | 680 | EXPORT_SYMBOL_GPL(rt2800_process_rxwi); |
684 | 681 | ||
@@ -1988,8 +1985,21 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev, | |||
1988 | } | 1985 | } |
1989 | 1986 | ||
1990 | #define POWER_BOUND 0x27 | 1987 | #define POWER_BOUND 0x27 |
1988 | #define POWER_BOUND_5G 0x2b | ||
1991 | #define FREQ_OFFSET_BOUND 0x5f | 1989 | #define FREQ_OFFSET_BOUND 0x5f |
1992 | 1990 | ||
1991 | static void rt2800_adjust_freq_offset(struct rt2x00_dev *rt2x00dev) | ||
1992 | { | ||
1993 | u8 rfcsr; | ||
1994 | |||
1995 | rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr); | ||
1996 | if (rt2x00dev->freq_offset > FREQ_OFFSET_BOUND) | ||
1997 | rt2x00_set_field8(&rfcsr, RFCSR17_CODE, FREQ_OFFSET_BOUND); | ||
1998 | else | ||
1999 | rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset); | ||
2000 | rt2800_rfcsr_write(rt2x00dev, 17, rfcsr); | ||
2001 | } | ||
2002 | |||
1993 | static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev, | 2003 | static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev, |
1994 | struct ieee80211_conf *conf, | 2004 | struct ieee80211_conf *conf, |
1995 | struct rf_channel *rf, | 2005 | struct rf_channel *rf, |
@@ -2010,12 +2020,7 @@ static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev, | |||
2010 | rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1); | 2020 | rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1); |
2011 | rt2800_rfcsr_write(rt2x00dev, 49, rfcsr); | 2021 | rt2800_rfcsr_write(rt2x00dev, 49, rfcsr); |
2012 | 2022 | ||
2013 | rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr); | 2023 | rt2800_adjust_freq_offset(rt2x00dev); |
2014 | if (rt2x00dev->freq_offset > FREQ_OFFSET_BOUND) | ||
2015 | rt2x00_set_field8(&rfcsr, RFCSR17_CODE, FREQ_OFFSET_BOUND); | ||
2016 | else | ||
2017 | rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset); | ||
2018 | rt2800_rfcsr_write(rt2x00dev, 17, rfcsr); | ||
2019 | 2024 | ||
2020 | if (rf->channel <= 14) { | 2025 | if (rf->channel <= 14) { |
2021 | if (rf->channel == 6) | 2026 | if (rf->channel == 6) |
@@ -2056,13 +2061,7 @@ static void rt2800_config_channel_rf3322(struct rt2x00_dev *rt2x00dev, | |||
2056 | else | 2061 | else |
2057 | rt2800_rfcsr_write(rt2x00dev, 48, info->default_power2); | 2062 | rt2800_rfcsr_write(rt2x00dev, 48, info->default_power2); |
2058 | 2063 | ||
2059 | rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr); | 2064 | rt2800_adjust_freq_offset(rt2x00dev); |
2060 | if (rt2x00dev->freq_offset > FREQ_OFFSET_BOUND) | ||
2061 | rt2x00_set_field8(&rfcsr, RFCSR17_CODE, FREQ_OFFSET_BOUND); | ||
2062 | else | ||
2063 | rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset); | ||
2064 | |||
2065 | rt2800_rfcsr_write(rt2x00dev, 17, rfcsr); | ||
2066 | 2065 | ||
2067 | rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); | 2066 | rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); |
2068 | rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1); | 2067 | rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1); |
@@ -2127,12 +2126,7 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev, | |||
2127 | rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1); | 2126 | rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1); |
2128 | rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); | 2127 | rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); |
2129 | 2128 | ||
2130 | rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr); | 2129 | rt2800_adjust_freq_offset(rt2x00dev); |
2131 | if (rt2x00dev->freq_offset > FREQ_OFFSET_BOUND) | ||
2132 | rt2x00_set_field8(&rfcsr, RFCSR17_CODE, FREQ_OFFSET_BOUND); | ||
2133 | else | ||
2134 | rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset); | ||
2135 | rt2800_rfcsr_write(rt2x00dev, 17, rfcsr); | ||
2136 | 2130 | ||
2137 | if (rf->channel <= 14) { | 2131 | if (rf->channel <= 14) { |
2138 | int idx = rf->channel-1; | 2132 | int idx = rf->channel-1; |
@@ -2184,6 +2178,382 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev, | |||
2184 | } | 2178 | } |
2185 | } | 2179 | } |
2186 | 2180 | ||
2181 | static void rt2800_config_channel_rf55xx(struct rt2x00_dev *rt2x00dev, | ||
2182 | struct ieee80211_conf *conf, | ||
2183 | struct rf_channel *rf, | ||
2184 | struct channel_info *info) | ||
2185 | { | ||
2186 | u8 rfcsr, ep_reg; | ||
2187 | u32 reg; | ||
2188 | int power_bound; | ||
2189 | |||
2190 | /* TODO */ | ||
2191 | const bool is_11b = false; | ||
2192 | const bool is_type_ep = false; | ||
2193 | |||
2194 | rt2800_register_read(rt2x00dev, LDO_CFG0, ®); | ||
2195 | rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, | ||
2196 | (rf->channel > 14 || conf_is_ht40(conf)) ? 5 : 0); | ||
2197 | rt2800_register_write(rt2x00dev, LDO_CFG0, reg); | ||
2198 | |||
2199 | /* Order of values on rf_channel entry: N, K, mod, R */ | ||
2200 | rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1 & 0xff); | ||
2201 | |||
2202 | rt2800_rfcsr_read(rt2x00dev, 9, &rfcsr); | ||
2203 | rt2x00_set_field8(&rfcsr, RFCSR9_K, rf->rf2 & 0xf); | ||
2204 | rt2x00_set_field8(&rfcsr, RFCSR9_N, (rf->rf1 & 0x100) >> 8); | ||
2205 | rt2x00_set_field8(&rfcsr, RFCSR9_MOD, ((rf->rf3 - 8) & 0x4) >> 2); | ||
2206 | rt2800_rfcsr_write(rt2x00dev, 9, rfcsr); | ||
2207 | |||
2208 | rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr); | ||
2209 | rt2x00_set_field8(&rfcsr, RFCSR11_R, rf->rf4 - 1); | ||
2210 | rt2x00_set_field8(&rfcsr, RFCSR11_MOD, (rf->rf3 - 8) & 0x3); | ||
2211 | rt2800_rfcsr_write(rt2x00dev, 11, rfcsr); | ||
2212 | |||
2213 | if (rf->channel <= 14) { | ||
2214 | rt2800_rfcsr_write(rt2x00dev, 10, 0x90); | ||
2215 | /* FIXME: RF11 owerwrite ? */ | ||
2216 | rt2800_rfcsr_write(rt2x00dev, 11, 0x4A); | ||
2217 | rt2800_rfcsr_write(rt2x00dev, 12, 0x52); | ||
2218 | rt2800_rfcsr_write(rt2x00dev, 13, 0x42); | ||
2219 | rt2800_rfcsr_write(rt2x00dev, 22, 0x40); | ||
2220 | rt2800_rfcsr_write(rt2x00dev, 24, 0x4A); | ||
2221 | rt2800_rfcsr_write(rt2x00dev, 25, 0x80); | ||
2222 | rt2800_rfcsr_write(rt2x00dev, 27, 0x42); | ||
2223 | rt2800_rfcsr_write(rt2x00dev, 36, 0x80); | ||
2224 | rt2800_rfcsr_write(rt2x00dev, 37, 0x08); | ||
2225 | rt2800_rfcsr_write(rt2x00dev, 38, 0x89); | ||
2226 | rt2800_rfcsr_write(rt2x00dev, 39, 0x1B); | ||
2227 | rt2800_rfcsr_write(rt2x00dev, 40, 0x0D); | ||
2228 | rt2800_rfcsr_write(rt2x00dev, 41, 0x9B); | ||
2229 | rt2800_rfcsr_write(rt2x00dev, 42, 0xD5); | ||
2230 | rt2800_rfcsr_write(rt2x00dev, 43, 0x72); | ||
2231 | rt2800_rfcsr_write(rt2x00dev, 44, 0x0E); | ||
2232 | rt2800_rfcsr_write(rt2x00dev, 45, 0xA2); | ||
2233 | rt2800_rfcsr_write(rt2x00dev, 46, 0x6B); | ||
2234 | rt2800_rfcsr_write(rt2x00dev, 48, 0x10); | ||
2235 | rt2800_rfcsr_write(rt2x00dev, 51, 0x3E); | ||
2236 | rt2800_rfcsr_write(rt2x00dev, 52, 0x48); | ||
2237 | rt2800_rfcsr_write(rt2x00dev, 54, 0x38); | ||
2238 | rt2800_rfcsr_write(rt2x00dev, 56, 0xA1); | ||
2239 | rt2800_rfcsr_write(rt2x00dev, 57, 0x00); | ||
2240 | rt2800_rfcsr_write(rt2x00dev, 58, 0x39); | ||
2241 | rt2800_rfcsr_write(rt2x00dev, 60, 0x45); | ||
2242 | rt2800_rfcsr_write(rt2x00dev, 61, 0x91); | ||
2243 | rt2800_rfcsr_write(rt2x00dev, 62, 0x39); | ||
2244 | |||
2245 | /* TODO RF27 <- tssi */ | ||
2246 | |||
2247 | rfcsr = rf->channel <= 10 ? 0x07 : 0x06; | ||
2248 | rt2800_rfcsr_write(rt2x00dev, 23, rfcsr); | ||
2249 | rt2800_rfcsr_write(rt2x00dev, 59, rfcsr); | ||
2250 | |||
2251 | if (is_11b) { | ||
2252 | /* CCK */ | ||
2253 | rt2800_rfcsr_write(rt2x00dev, 31, 0xF8); | ||
2254 | rt2800_rfcsr_write(rt2x00dev, 32, 0xC0); | ||
2255 | if (is_type_ep) | ||
2256 | rt2800_rfcsr_write(rt2x00dev, 55, 0x06); | ||
2257 | else | ||
2258 | rt2800_rfcsr_write(rt2x00dev, 55, 0x47); | ||
2259 | } else { | ||
2260 | /* OFDM */ | ||
2261 | if (is_type_ep) | ||
2262 | rt2800_rfcsr_write(rt2x00dev, 55, 0x03); | ||
2263 | else | ||
2264 | rt2800_rfcsr_write(rt2x00dev, 55, 0x43); | ||
2265 | } | ||
2266 | |||
2267 | power_bound = POWER_BOUND; | ||
2268 | ep_reg = 0x2; | ||
2269 | } else { | ||
2270 | rt2800_rfcsr_write(rt2x00dev, 10, 0x97); | ||
2271 | /* FIMXE: RF11 overwrite */ | ||
2272 | rt2800_rfcsr_write(rt2x00dev, 11, 0x40); | ||
2273 | rt2800_rfcsr_write(rt2x00dev, 25, 0xBF); | ||
2274 | rt2800_rfcsr_write(rt2x00dev, 27, 0x42); | ||
2275 | rt2800_rfcsr_write(rt2x00dev, 36, 0x00); | ||
2276 | rt2800_rfcsr_write(rt2x00dev, 37, 0x04); | ||
2277 | rt2800_rfcsr_write(rt2x00dev, 38, 0x85); | ||
2278 | rt2800_rfcsr_write(rt2x00dev, 40, 0x42); | ||
2279 | rt2800_rfcsr_write(rt2x00dev, 41, 0xBB); | ||
2280 | rt2800_rfcsr_write(rt2x00dev, 42, 0xD7); | ||
2281 | rt2800_rfcsr_write(rt2x00dev, 45, 0x41); | ||
2282 | rt2800_rfcsr_write(rt2x00dev, 48, 0x00); | ||
2283 | rt2800_rfcsr_write(rt2x00dev, 57, 0x77); | ||
2284 | rt2800_rfcsr_write(rt2x00dev, 60, 0x05); | ||
2285 | rt2800_rfcsr_write(rt2x00dev, 61, 0x01); | ||
2286 | |||
2287 | /* TODO RF27 <- tssi */ | ||
2288 | |||
2289 | if (rf->channel >= 36 && rf->channel <= 64) { | ||
2290 | |||
2291 | rt2800_rfcsr_write(rt2x00dev, 12, 0x2E); | ||
2292 | rt2800_rfcsr_write(rt2x00dev, 13, 0x22); | ||
2293 | rt2800_rfcsr_write(rt2x00dev, 22, 0x60); | ||
2294 | rt2800_rfcsr_write(rt2x00dev, 23, 0x7F); | ||
2295 | if (rf->channel <= 50) | ||
2296 | rt2800_rfcsr_write(rt2x00dev, 24, 0x09); | ||
2297 | else if (rf->channel >= 52) | ||
2298 | rt2800_rfcsr_write(rt2x00dev, 24, 0x07); | ||
2299 | rt2800_rfcsr_write(rt2x00dev, 39, 0x1C); | ||
2300 | rt2800_rfcsr_write(rt2x00dev, 43, 0x5B); | ||
2301 | rt2800_rfcsr_write(rt2x00dev, 44, 0X40); | ||
2302 | rt2800_rfcsr_write(rt2x00dev, 46, 0X00); | ||
2303 | rt2800_rfcsr_write(rt2x00dev, 51, 0xFE); | ||
2304 | rt2800_rfcsr_write(rt2x00dev, 52, 0x0C); | ||
2305 | rt2800_rfcsr_write(rt2x00dev, 54, 0xF8); | ||
2306 | if (rf->channel <= 50) { | ||
2307 | rt2800_rfcsr_write(rt2x00dev, 55, 0x06), | ||
2308 | rt2800_rfcsr_write(rt2x00dev, 56, 0xD3); | ||
2309 | } else if (rf->channel >= 52) { | ||
2310 | rt2800_rfcsr_write(rt2x00dev, 55, 0x04); | ||
2311 | rt2800_rfcsr_write(rt2x00dev, 56, 0xBB); | ||
2312 | } | ||
2313 | |||
2314 | rt2800_rfcsr_write(rt2x00dev, 58, 0x15); | ||
2315 | rt2800_rfcsr_write(rt2x00dev, 59, 0x7F); | ||
2316 | rt2800_rfcsr_write(rt2x00dev, 62, 0x15); | ||
2317 | |||
2318 | } else if (rf->channel >= 100 && rf->channel <= 165) { | ||
2319 | |||
2320 | rt2800_rfcsr_write(rt2x00dev, 12, 0x0E); | ||
2321 | rt2800_rfcsr_write(rt2x00dev, 13, 0x42); | ||
2322 | rt2800_rfcsr_write(rt2x00dev, 22, 0x40); | ||
2323 | if (rf->channel <= 153) { | ||
2324 | rt2800_rfcsr_write(rt2x00dev, 23, 0x3C); | ||
2325 | rt2800_rfcsr_write(rt2x00dev, 24, 0x06); | ||
2326 | } else if (rf->channel >= 155) { | ||
2327 | rt2800_rfcsr_write(rt2x00dev, 23, 0x38); | ||
2328 | rt2800_rfcsr_write(rt2x00dev, 24, 0x05); | ||
2329 | } | ||
2330 | if (rf->channel <= 138) { | ||
2331 | rt2800_rfcsr_write(rt2x00dev, 39, 0x1A); | ||
2332 | rt2800_rfcsr_write(rt2x00dev, 43, 0x3B); | ||
2333 | rt2800_rfcsr_write(rt2x00dev, 44, 0x20); | ||
2334 | rt2800_rfcsr_write(rt2x00dev, 46, 0x18); | ||
2335 | } else if (rf->channel >= 140) { | ||
2336 | rt2800_rfcsr_write(rt2x00dev, 39, 0x18); | ||
2337 | rt2800_rfcsr_write(rt2x00dev, 43, 0x1B); | ||
2338 | rt2800_rfcsr_write(rt2x00dev, 44, 0x10); | ||
2339 | rt2800_rfcsr_write(rt2x00dev, 46, 0X08); | ||
2340 | } | ||
2341 | if (rf->channel <= 124) | ||
2342 | rt2800_rfcsr_write(rt2x00dev, 51, 0xFC); | ||
2343 | else if (rf->channel >= 126) | ||
2344 | rt2800_rfcsr_write(rt2x00dev, 51, 0xEC); | ||
2345 | if (rf->channel <= 138) | ||
2346 | rt2800_rfcsr_write(rt2x00dev, 52, 0x06); | ||
2347 | else if (rf->channel >= 140) | ||
2348 | rt2800_rfcsr_write(rt2x00dev, 52, 0x06); | ||
2349 | rt2800_rfcsr_write(rt2x00dev, 54, 0xEB); | ||
2350 | if (rf->channel <= 138) | ||
2351 | rt2800_rfcsr_write(rt2x00dev, 55, 0x01); | ||
2352 | else if (rf->channel >= 140) | ||
2353 | rt2800_rfcsr_write(rt2x00dev, 55, 0x00); | ||
2354 | if (rf->channel <= 128) | ||
2355 | rt2800_rfcsr_write(rt2x00dev, 56, 0xBB); | ||
2356 | else if (rf->channel >= 130) | ||
2357 | rt2800_rfcsr_write(rt2x00dev, 56, 0xAB); | ||
2358 | if (rf->channel <= 116) | ||
2359 | rt2800_rfcsr_write(rt2x00dev, 58, 0x1D); | ||
2360 | else if (rf->channel >= 118) | ||
2361 | rt2800_rfcsr_write(rt2x00dev, 58, 0x15); | ||
2362 | if (rf->channel <= 138) | ||
2363 | rt2800_rfcsr_write(rt2x00dev, 59, 0x3F); | ||
2364 | else if (rf->channel >= 140) | ||
2365 | rt2800_rfcsr_write(rt2x00dev, 59, 0x7C); | ||
2366 | if (rf->channel <= 116) | ||
2367 | rt2800_rfcsr_write(rt2x00dev, 62, 0x1D); | ||
2368 | else if (rf->channel >= 118) | ||
2369 | rt2800_rfcsr_write(rt2x00dev, 62, 0x15); | ||
2370 | } | ||
2371 | |||
2372 | power_bound = POWER_BOUND_5G; | ||
2373 | ep_reg = 0x3; | ||
2374 | } | ||
2375 | |||
2376 | rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr); | ||
2377 | if (info->default_power1 > power_bound) | ||
2378 | rt2x00_set_field8(&rfcsr, RFCSR49_TX, power_bound); | ||
2379 | else | ||
2380 | rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1); | ||
2381 | if (is_type_ep) | ||
2382 | rt2x00_set_field8(&rfcsr, RFCSR49_EP, ep_reg); | ||
2383 | rt2800_rfcsr_write(rt2x00dev, 49, rfcsr); | ||
2384 | |||
2385 | rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr); | ||
2386 | if (info->default_power1 > power_bound) | ||
2387 | rt2x00_set_field8(&rfcsr, RFCSR50_TX, power_bound); | ||
2388 | else | ||
2389 | rt2x00_set_field8(&rfcsr, RFCSR50_TX, info->default_power2); | ||
2390 | if (is_type_ep) | ||
2391 | rt2x00_set_field8(&rfcsr, RFCSR50_EP, ep_reg); | ||
2392 | rt2800_rfcsr_write(rt2x00dev, 50, rfcsr); | ||
2393 | |||
2394 | rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); | ||
2395 | rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1); | ||
2396 | rt2x00_set_field8(&rfcsr, RFCSR1_PLL_PD, 1); | ||
2397 | |||
2398 | rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, | ||
2399 | rt2x00dev->default_ant.tx_chain_num >= 1); | ||
2400 | rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, | ||
2401 | rt2x00dev->default_ant.tx_chain_num == 2); | ||
2402 | rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0); | ||
2403 | |||
2404 | rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, | ||
2405 | rt2x00dev->default_ant.rx_chain_num >= 1); | ||
2406 | rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, | ||
2407 | rt2x00dev->default_ant.rx_chain_num == 2); | ||
2408 | rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0); | ||
2409 | |||
2410 | rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); | ||
2411 | rt2800_rfcsr_write(rt2x00dev, 6, 0xe4); | ||
2412 | |||
2413 | if (conf_is_ht40(conf)) | ||
2414 | rt2800_rfcsr_write(rt2x00dev, 30, 0x16); | ||
2415 | else | ||
2416 | rt2800_rfcsr_write(rt2x00dev, 30, 0x10); | ||
2417 | |||
2418 | if (!is_11b) { | ||
2419 | rt2800_rfcsr_write(rt2x00dev, 31, 0x80); | ||
2420 | rt2800_rfcsr_write(rt2x00dev, 32, 0x80); | ||
2421 | } | ||
2422 | |||
2423 | /* TODO proper frequency adjustment */ | ||
2424 | rt2800_adjust_freq_offset(rt2x00dev); | ||
2425 | |||
2426 | /* TODO merge with others */ | ||
2427 | rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr); | ||
2428 | rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1); | ||
2429 | rt2800_rfcsr_write(rt2x00dev, 3, rfcsr); | ||
2430 | |||
2431 | /* BBP settings */ | ||
2432 | rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain); | ||
2433 | rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); | ||
2434 | rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain); | ||
2435 | |||
2436 | rt2800_bbp_write(rt2x00dev, 79, (rf->channel <= 14) ? 0x1C : 0x18); | ||
2437 | rt2800_bbp_write(rt2x00dev, 80, (rf->channel <= 14) ? 0x0E : 0x08); | ||
2438 | rt2800_bbp_write(rt2x00dev, 81, (rf->channel <= 14) ? 0x3A : 0x38); | ||
2439 | rt2800_bbp_write(rt2x00dev, 82, (rf->channel <= 14) ? 0x62 : 0x92); | ||
2440 | |||
2441 | /* GLRT band configuration */ | ||
2442 | rt2800_bbp_write(rt2x00dev, 195, 128); | ||
2443 | rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0xE0 : 0xF0); | ||
2444 | rt2800_bbp_write(rt2x00dev, 195, 129); | ||
2445 | rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x1F : 0x1E); | ||
2446 | rt2800_bbp_write(rt2x00dev, 195, 130); | ||
2447 | rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x38 : 0x28); | ||
2448 | rt2800_bbp_write(rt2x00dev, 195, 131); | ||
2449 | rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x32 : 0x20); | ||
2450 | rt2800_bbp_write(rt2x00dev, 195, 133); | ||
2451 | rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x28 : 0x7F); | ||
2452 | rt2800_bbp_write(rt2x00dev, 195, 124); | ||
2453 | rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x19 : 0x7F); | ||
2454 | } | ||
2455 | |||
2456 | static void rt2800_bbp_write_with_rx_chain(struct rt2x00_dev *rt2x00dev, | ||
2457 | const unsigned int word, | ||
2458 | const u8 value) | ||
2459 | { | ||
2460 | u8 chain, reg; | ||
2461 | |||
2462 | for (chain = 0; chain < rt2x00dev->default_ant.rx_chain_num; chain++) { | ||
2463 | rt2800_bbp_read(rt2x00dev, 27, ®); | ||
2464 | rt2x00_set_field8(®, BBP27_RX_CHAIN_SEL, chain); | ||
2465 | rt2800_bbp_write(rt2x00dev, 27, reg); | ||
2466 | |||
2467 | rt2800_bbp_write(rt2x00dev, word, value); | ||
2468 | } | ||
2469 | } | ||
2470 | |||
2471 | static void rt2800_iq_calibrate(struct rt2x00_dev *rt2x00dev, int channel) | ||
2472 | { | ||
2473 | u8 cal; | ||
2474 | |||
2475 | /* TX0 IQ Gain */ | ||
2476 | rt2800_bbp_write(rt2x00dev, 158, 0x2c); | ||
2477 | if (channel <= 14) | ||
2478 | cal = rt2x00_eeprom_byte(rt2x00dev, EEPROM_IQ_GAIN_CAL_TX0_2G); | ||
2479 | else if (channel >= 36 && channel <= 64) | ||
2480 | cal = rt2x00_eeprom_byte(rt2x00dev, | ||
2481 | EEPROM_IQ_GAIN_CAL_TX0_CH36_TO_CH64_5G); | ||
2482 | else if (channel >= 100 && channel <= 138) | ||
2483 | cal = rt2x00_eeprom_byte(rt2x00dev, | ||
2484 | EEPROM_IQ_GAIN_CAL_TX0_CH100_TO_CH138_5G); | ||
2485 | else if (channel >= 140 && channel <= 165) | ||
2486 | cal = rt2x00_eeprom_byte(rt2x00dev, | ||
2487 | EEPROM_IQ_GAIN_CAL_TX0_CH140_TO_CH165_5G); | ||
2488 | else | ||
2489 | cal = 0; | ||
2490 | rt2800_bbp_write(rt2x00dev, 159, cal); | ||
2491 | |||
2492 | /* TX0 IQ Phase */ | ||
2493 | rt2800_bbp_write(rt2x00dev, 158, 0x2d); | ||
2494 | if (channel <= 14) | ||
2495 | cal = rt2x00_eeprom_byte(rt2x00dev, EEPROM_IQ_PHASE_CAL_TX0_2G); | ||
2496 | else if (channel >= 36 && channel <= 64) | ||
2497 | cal = rt2x00_eeprom_byte(rt2x00dev, | ||
2498 | EEPROM_IQ_PHASE_CAL_TX0_CH36_TO_CH64_5G); | ||
2499 | else if (channel >= 100 && channel <= 138) | ||
2500 | cal = rt2x00_eeprom_byte(rt2x00dev, | ||
2501 | EEPROM_IQ_PHASE_CAL_TX0_CH100_TO_CH138_5G); | ||
2502 | else if (channel >= 140 && channel <= 165) | ||
2503 | cal = rt2x00_eeprom_byte(rt2x00dev, | ||
2504 | EEPROM_IQ_PHASE_CAL_TX0_CH140_TO_CH165_5G); | ||
2505 | else | ||
2506 | cal = 0; | ||
2507 | rt2800_bbp_write(rt2x00dev, 159, cal); | ||
2508 | |||
2509 | /* TX1 IQ Gain */ | ||
2510 | rt2800_bbp_write(rt2x00dev, 158, 0x4a); | ||
2511 | if (channel <= 14) | ||
2512 | cal = rt2x00_eeprom_byte(rt2x00dev, EEPROM_IQ_GAIN_CAL_TX1_2G); | ||
2513 | else if (channel >= 36 && channel <= 64) | ||
2514 | cal = rt2x00_eeprom_byte(rt2x00dev, | ||
2515 | EEPROM_IQ_GAIN_CAL_TX1_CH36_TO_CH64_5G); | ||
2516 | else if (channel >= 100 && channel <= 138) | ||
2517 | cal = rt2x00_eeprom_byte(rt2x00dev, | ||
2518 | EEPROM_IQ_GAIN_CAL_TX1_CH100_TO_CH138_5G); | ||
2519 | else if (channel >= 140 && channel <= 165) | ||
2520 | cal = rt2x00_eeprom_byte(rt2x00dev, | ||
2521 | EEPROM_IQ_GAIN_CAL_TX1_CH140_TO_CH165_5G); | ||
2522 | else | ||
2523 | cal = 0; | ||
2524 | rt2800_bbp_write(rt2x00dev, 159, cal); | ||
2525 | |||
2526 | /* TX1 IQ Phase */ | ||
2527 | rt2800_bbp_write(rt2x00dev, 158, 0x4b); | ||
2528 | if (channel <= 14) | ||
2529 | cal = rt2x00_eeprom_byte(rt2x00dev, EEPROM_IQ_PHASE_CAL_TX1_2G); | ||
2530 | else if (channel >= 36 && channel <= 64) | ||
2531 | cal = rt2x00_eeprom_byte(rt2x00dev, | ||
2532 | EEPROM_IQ_PHASE_CAL_TX1_CH36_TO_CH64_5G); | ||
2533 | else if (channel >= 100 && channel <= 138) | ||
2534 | cal = rt2x00_eeprom_byte(rt2x00dev, | ||
2535 | EEPROM_IQ_PHASE_CAL_TX1_CH100_TO_CH138_5G); | ||
2536 | else if (channel >= 140 && channel <= 165) | ||
2537 | cal = rt2x00_eeprom_byte(rt2x00dev, | ||
2538 | EEPROM_IQ_PHASE_CAL_TX1_CH140_TO_CH165_5G); | ||
2539 | else | ||
2540 | cal = 0; | ||
2541 | rt2800_bbp_write(rt2x00dev, 159, cal); | ||
2542 | |||
2543 | /* FIXME: possible RX0, RX1 callibration ? */ | ||
2544 | |||
2545 | /* RF IQ compensation control */ | ||
2546 | rt2800_bbp_write(rt2x00dev, 158, 0x04); | ||
2547 | cal = rt2x00_eeprom_byte(rt2x00dev, EEPROM_RF_IQ_COMPENSATION_CONTROL); | ||
2548 | rt2800_bbp_write(rt2x00dev, 159, cal != 0xff ? cal : 0); | ||
2549 | |||
2550 | /* RF IQ imbalance compensation control */ | ||
2551 | rt2800_bbp_write(rt2x00dev, 158, 0x03); | ||
2552 | cal = rt2x00_eeprom_byte(rt2x00dev, | ||
2553 | EEPROM_RF_IQ_IMBALANCE_COMPENSATION_CONTROL); | ||
2554 | rt2800_bbp_write(rt2x00dev, 159, cal != 0xff ? cal : 0); | ||
2555 | } | ||
2556 | |||
2187 | static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, | 2557 | static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, |
2188 | struct ieee80211_conf *conf, | 2558 | struct ieee80211_conf *conf, |
2189 | struct rf_channel *rf, | 2559 | struct rf_channel *rf, |
@@ -2225,6 +2595,9 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, | |||
2225 | case RF5392: | 2595 | case RF5392: |
2226 | rt2800_config_channel_rf53xx(rt2x00dev, conf, rf, info); | 2596 | rt2800_config_channel_rf53xx(rt2x00dev, conf, rf, info); |
2227 | break; | 2597 | break; |
2598 | case RF5592: | ||
2599 | rt2800_config_channel_rf55xx(rt2x00dev, conf, rf, info); | ||
2600 | break; | ||
2228 | default: | 2601 | default: |
2229 | rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info); | 2602 | rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info); |
2230 | } | 2603 | } |
@@ -2326,6 +2699,17 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, | |||
2326 | if (rt2x00_rt(rt2x00dev, RT3572)) | 2699 | if (rt2x00_rt(rt2x00dev, RT3572)) |
2327 | rt2800_rfcsr_write(rt2x00dev, 8, 0x80); | 2700 | rt2800_rfcsr_write(rt2x00dev, 8, 0x80); |
2328 | 2701 | ||
2702 | if (rt2x00_rt(rt2x00dev, RT5592)) { | ||
2703 | rt2800_bbp_write(rt2x00dev, 195, 141); | ||
2704 | rt2800_bbp_write(rt2x00dev, 196, conf_is_ht40(conf) ? 0x10 : 0x1a); | ||
2705 | |||
2706 | /* AGC init */ | ||
2707 | reg = (rf->channel <= 14 ? 0x1c : 0x24) + 2 * rt2x00dev->lna_gain; | ||
2708 | rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg); | ||
2709 | |||
2710 | rt2800_iq_calibrate(rt2x00dev, rf->channel); | ||
2711 | } | ||
2712 | |||
2329 | rt2800_bbp_read(rt2x00dev, 4, &bbp); | 2713 | rt2800_bbp_read(rt2x00dev, 4, &bbp); |
2330 | rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf)); | 2714 | rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf)); |
2331 | rt2800_bbp_write(rt2x00dev, 4, bbp); | 2715 | rt2800_bbp_write(rt2x00dev, 4, bbp); |
@@ -2938,13 +3322,16 @@ static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev) | |||
2938 | rt2x00_rt(rt2x00dev, RT3390) || | 3322 | rt2x00_rt(rt2x00dev, RT3390) || |
2939 | rt2x00_rt(rt2x00dev, RT3572) || | 3323 | rt2x00_rt(rt2x00dev, RT3572) || |
2940 | rt2x00_rt(rt2x00dev, RT5390) || | 3324 | rt2x00_rt(rt2x00dev, RT5390) || |
2941 | rt2x00_rt(rt2x00dev, RT5392)) | 3325 | rt2x00_rt(rt2x00dev, RT5392) || |
3326 | rt2x00_rt(rt2x00dev, RT5592)) | ||
2942 | vgc = 0x1c + (2 * rt2x00dev->lna_gain); | 3327 | vgc = 0x1c + (2 * rt2x00dev->lna_gain); |
2943 | else | 3328 | else |
2944 | vgc = 0x2e + rt2x00dev->lna_gain; | 3329 | vgc = 0x2e + rt2x00dev->lna_gain; |
2945 | } else { /* 5GHZ band */ | 3330 | } else { /* 5GHZ band */ |
2946 | if (rt2x00_rt(rt2x00dev, RT3572)) | 3331 | if (rt2x00_rt(rt2x00dev, RT3572)) |
2947 | vgc = 0x22 + (rt2x00dev->lna_gain * 5) / 3; | 3332 | vgc = 0x22 + (rt2x00dev->lna_gain * 5) / 3; |
3333 | else if (rt2x00_rt(rt2x00dev, RT5592)) | ||
3334 | vgc = 0x24 + (2 * rt2x00dev->lna_gain); | ||
2948 | else { | 3335 | else { |
2949 | if (!test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) | 3336 | if (!test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) |
2950 | vgc = 0x32 + (rt2x00dev->lna_gain * 5) / 3; | 3337 | vgc = 0x32 + (rt2x00dev->lna_gain * 5) / 3; |
@@ -2960,7 +3347,11 @@ static inline void rt2800_set_vgc(struct rt2x00_dev *rt2x00dev, | |||
2960 | struct link_qual *qual, u8 vgc_level) | 3347 | struct link_qual *qual, u8 vgc_level) |
2961 | { | 3348 | { |
2962 | if (qual->vgc_level != vgc_level) { | 3349 | if (qual->vgc_level != vgc_level) { |
2963 | rt2800_bbp_write(rt2x00dev, 66, vgc_level); | 3350 | if (rt2x00_rt(rt2x00dev, RT5592)) { |
3351 | rt2800_bbp_write(rt2x00dev, 83, qual->rssi > -65 ? 0x4a : 0x7a); | ||
3352 | rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, vgc_level); | ||
3353 | } else | ||
3354 | rt2800_bbp_write(rt2x00dev, 66, vgc_level); | ||
2964 | qual->vgc_level = vgc_level; | 3355 | qual->vgc_level = vgc_level; |
2965 | qual->vgc_level_reg = vgc_level; | 3356 | qual->vgc_level_reg = vgc_level; |
2966 | } | 3357 | } |
@@ -2975,15 +3366,23 @@ EXPORT_SYMBOL_GPL(rt2800_reset_tuner); | |||
2975 | void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual, | 3366 | void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual, |
2976 | const u32 count) | 3367 | const u32 count) |
2977 | { | 3368 | { |
3369 | u8 vgc; | ||
3370 | |||
2978 | if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) | 3371 | if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) |
2979 | return; | 3372 | return; |
2980 | |||
2981 | /* | 3373 | /* |
2982 | * When RSSI is better then -80 increase VGC level with 0x10 | 3374 | * When RSSI is better then -80 increase VGC level with 0x10, except |
3375 | * for rt5592 chip. | ||
2983 | */ | 3376 | */ |
2984 | rt2800_set_vgc(rt2x00dev, qual, | 3377 | |
2985 | rt2800_get_default_vgc(rt2x00dev) + | 3378 | vgc = rt2800_get_default_vgc(rt2x00dev); |
2986 | ((qual->rssi > -80) * 0x10)); | 3379 | |
3380 | if (rt2x00_rt(rt2x00dev, RT5592) && qual->rssi > -65) | ||
3381 | vgc += 0x20; | ||
3382 | else if (qual->rssi > -80) | ||
3383 | vgc += 0x10; | ||
3384 | |||
3385 | rt2800_set_vgc(rt2x00dev, qual, vgc); | ||
2987 | } | 3386 | } |
2988 | EXPORT_SYMBOL_GPL(rt2800_link_tuner); | 3387 | EXPORT_SYMBOL_GPL(rt2800_link_tuner); |
2989 | 3388 | ||
@@ -3122,7 +3521,8 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
3122 | rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); | 3521 | rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); |
3123 | rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); | 3522 | rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); |
3124 | } else if (rt2x00_rt(rt2x00dev, RT5390) || | 3523 | } else if (rt2x00_rt(rt2x00dev, RT5390) || |
3125 | rt2x00_rt(rt2x00dev, RT5392)) { | 3524 | rt2x00_rt(rt2x00dev, RT5392) || |
3525 | rt2x00_rt(rt2x00dev, RT5592)) { | ||
3126 | rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404); | 3526 | rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404); |
3127 | rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); | 3527 | rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); |
3128 | rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); | 3528 | rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); |
@@ -3302,7 +3702,8 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
3302 | rt2x00_set_field32(®, TXOP_CTRL_CFG_EXT_CWMIN, 0); | 3702 | rt2x00_set_field32(®, TXOP_CTRL_CFG_EXT_CWMIN, 0); |
3303 | rt2800_register_write(rt2x00dev, TXOP_CTRL_CFG, reg); | 3703 | rt2800_register_write(rt2x00dev, TXOP_CTRL_CFG, reg); |
3304 | 3704 | ||
3305 | rt2800_register_write(rt2x00dev, TXOP_HLDR_ET, 0x00000002); | 3705 | reg = rt2x00_rt(rt2x00dev, RT5592) ? 0x00000082 : 0x00000002; |
3706 | rt2800_register_write(rt2x00dev, TXOP_HLDR_ET, reg); | ||
3306 | 3707 | ||
3307 | rt2800_register_read(rt2x00dev, TX_RTS_CFG, ®); | 3708 | rt2800_register_read(rt2x00dev, TX_RTS_CFG, ®); |
3308 | rt2x00_set_field32(®, TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT, 32); | 3709 | rt2x00_set_field32(®, TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT, 32); |
@@ -3487,6 +3888,136 @@ static int rt2800_wait_bbp_ready(struct rt2x00_dev *rt2x00dev) | |||
3487 | return -EACCES; | 3888 | return -EACCES; |
3488 | } | 3889 | } |
3489 | 3890 | ||
3891 | static void rt2800_bbp4_mac_if_ctrl(struct rt2x00_dev *rt2x00dev) | ||
3892 | { | ||
3893 | u8 value; | ||
3894 | |||
3895 | rt2800_bbp_read(rt2x00dev, 4, &value); | ||
3896 | rt2x00_set_field8(&value, BBP4_MAC_IF_CTRL, 1); | ||
3897 | rt2800_bbp_write(rt2x00dev, 4, value); | ||
3898 | } | ||
3899 | |||
3900 | static void rt2800_init_freq_calibration(struct rt2x00_dev *rt2x00dev) | ||
3901 | { | ||
3902 | rt2800_bbp_write(rt2x00dev, 142, 1); | ||
3903 | rt2800_bbp_write(rt2x00dev, 143, 57); | ||
3904 | } | ||
3905 | |||
3906 | static void rt2800_init_bbp_5592_glrt(struct rt2x00_dev *rt2x00dev) | ||
3907 | { | ||
3908 | const u8 glrt_table[] = { | ||
3909 | 0xE0, 0x1F, 0X38, 0x32, 0x08, 0x28, 0x19, 0x0A, 0xFF, 0x00, /* 128 ~ 137 */ | ||
3910 | 0x16, 0x10, 0x10, 0x0B, 0x36, 0x2C, 0x26, 0x24, 0x42, 0x36, /* 138 ~ 147 */ | ||
3911 | 0x30, 0x2D, 0x4C, 0x46, 0x3D, 0x40, 0x3E, 0x42, 0x3D, 0x40, /* 148 ~ 157 */ | ||
3912 | 0X3C, 0x34, 0x2C, 0x2F, 0x3C, 0x35, 0x2E, 0x2A, 0x49, 0x41, /* 158 ~ 167 */ | ||
3913 | 0x36, 0x31, 0x30, 0x30, 0x0E, 0x0D, 0x28, 0x21, 0x1C, 0x16, /* 168 ~ 177 */ | ||
3914 | 0x50, 0x4A, 0x43, 0x40, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, /* 178 ~ 187 */ | ||
3915 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 188 ~ 197 */ | ||
3916 | 0x00, 0x00, 0x7D, 0x14, 0x32, 0x2C, 0x36, 0x4C, 0x43, 0x2C, /* 198 ~ 207 */ | ||
3917 | 0x2E, 0x36, 0x30, 0x6E, /* 208 ~ 211 */ | ||
3918 | }; | ||
3919 | int i; | ||
3920 | |||
3921 | for (i = 0; i < ARRAY_SIZE(glrt_table); i++) { | ||
3922 | rt2800_bbp_write(rt2x00dev, 195, 128 + i); | ||
3923 | rt2800_bbp_write(rt2x00dev, 196, glrt_table[i]); | ||
3924 | } | ||
3925 | }; | ||
3926 | |||
3927 | static void rt2800_init_bbb_early(struct rt2x00_dev *rt2x00dev) | ||
3928 | { | ||
3929 | rt2800_bbp_write(rt2x00dev, 65, 0x2C); | ||
3930 | rt2800_bbp_write(rt2x00dev, 66, 0x38); | ||
3931 | rt2800_bbp_write(rt2x00dev, 68, 0x0B); | ||
3932 | rt2800_bbp_write(rt2x00dev, 69, 0x12); | ||
3933 | rt2800_bbp_write(rt2x00dev, 70, 0x0a); | ||
3934 | rt2800_bbp_write(rt2x00dev, 73, 0x10); | ||
3935 | rt2800_bbp_write(rt2x00dev, 81, 0x37); | ||
3936 | rt2800_bbp_write(rt2x00dev, 82, 0x62); | ||
3937 | rt2800_bbp_write(rt2x00dev, 83, 0x6A); | ||
3938 | rt2800_bbp_write(rt2x00dev, 84, 0x99); | ||
3939 | rt2800_bbp_write(rt2x00dev, 86, 0x00); | ||
3940 | rt2800_bbp_write(rt2x00dev, 91, 0x04); | ||
3941 | rt2800_bbp_write(rt2x00dev, 92, 0x00); | ||
3942 | rt2800_bbp_write(rt2x00dev, 103, 0x00); | ||
3943 | rt2800_bbp_write(rt2x00dev, 105, 0x05); | ||
3944 | rt2800_bbp_write(rt2x00dev, 106, 0x35); | ||
3945 | } | ||
3946 | |||
3947 | static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev) | ||
3948 | { | ||
3949 | int ant, div_mode; | ||
3950 | u16 eeprom; | ||
3951 | u8 value; | ||
3952 | |||
3953 | rt2800_init_bbb_early(rt2x00dev); | ||
3954 | |||
3955 | rt2800_bbp_read(rt2x00dev, 105, &value); | ||
3956 | rt2x00_set_field8(&value, BBP105_MLD, | ||
3957 | rt2x00dev->default_ant.rx_chain_num == 2); | ||
3958 | rt2800_bbp_write(rt2x00dev, 105, value); | ||
3959 | |||
3960 | rt2800_bbp4_mac_if_ctrl(rt2x00dev); | ||
3961 | |||
3962 | rt2800_bbp_write(rt2x00dev, 20, 0x06); | ||
3963 | rt2800_bbp_write(rt2x00dev, 31, 0x08); | ||
3964 | rt2800_bbp_write(rt2x00dev, 65, 0x2C); | ||
3965 | rt2800_bbp_write(rt2x00dev, 68, 0xDD); | ||
3966 | rt2800_bbp_write(rt2x00dev, 69, 0x1A); | ||
3967 | rt2800_bbp_write(rt2x00dev, 70, 0x05); | ||
3968 | rt2800_bbp_write(rt2x00dev, 73, 0x13); | ||
3969 | rt2800_bbp_write(rt2x00dev, 74, 0x0F); | ||
3970 | rt2800_bbp_write(rt2x00dev, 75, 0x4F); | ||
3971 | rt2800_bbp_write(rt2x00dev, 76, 0x28); | ||
3972 | rt2800_bbp_write(rt2x00dev, 77, 0x59); | ||
3973 | rt2800_bbp_write(rt2x00dev, 84, 0x9A); | ||
3974 | rt2800_bbp_write(rt2x00dev, 86, 0x38); | ||
3975 | rt2800_bbp_write(rt2x00dev, 88, 0x90); | ||
3976 | rt2800_bbp_write(rt2x00dev, 91, 0x04); | ||
3977 | rt2800_bbp_write(rt2x00dev, 92, 0x02); | ||
3978 | rt2800_bbp_write(rt2x00dev, 95, 0x9a); | ||
3979 | rt2800_bbp_write(rt2x00dev, 98, 0x12); | ||
3980 | rt2800_bbp_write(rt2x00dev, 103, 0xC0); | ||
3981 | rt2800_bbp_write(rt2x00dev, 104, 0x92); | ||
3982 | /* FIXME BBP105 owerwrite */ | ||
3983 | rt2800_bbp_write(rt2x00dev, 105, 0x3C); | ||
3984 | rt2800_bbp_write(rt2x00dev, 106, 0x35); | ||
3985 | rt2800_bbp_write(rt2x00dev, 128, 0x12); | ||
3986 | rt2800_bbp_write(rt2x00dev, 134, 0xD0); | ||
3987 | rt2800_bbp_write(rt2x00dev, 135, 0xF6); | ||
3988 | rt2800_bbp_write(rt2x00dev, 137, 0x0F); | ||
3989 | |||
3990 | /* Initialize GLRT (Generalized Likehood Radio Test) */ | ||
3991 | rt2800_init_bbp_5592_glrt(rt2x00dev); | ||
3992 | |||
3993 | rt2800_bbp4_mac_if_ctrl(rt2x00dev); | ||
3994 | |||
3995 | rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); | ||
3996 | div_mode = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_ANT_DIVERSITY); | ||
3997 | ant = (div_mode == 3) ? 1 : 0; | ||
3998 | rt2800_bbp_read(rt2x00dev, 152, &value); | ||
3999 | if (ant == 0) { | ||
4000 | /* Main antenna */ | ||
4001 | rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 1); | ||
4002 | } else { | ||
4003 | /* Auxiliary antenna */ | ||
4004 | rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 0); | ||
4005 | } | ||
4006 | rt2800_bbp_write(rt2x00dev, 152, value); | ||
4007 | |||
4008 | if (rt2x00_rt_rev_gte(rt2x00dev, RT5592, REV_RT5592C)) { | ||
4009 | rt2800_bbp_read(rt2x00dev, 254, &value); | ||
4010 | rt2x00_set_field8(&value, BBP254_BIT7, 1); | ||
4011 | rt2800_bbp_write(rt2x00dev, 254, value); | ||
4012 | } | ||
4013 | |||
4014 | rt2800_init_freq_calibration(rt2x00dev); | ||
4015 | |||
4016 | rt2800_bbp_write(rt2x00dev, 84, 0x19); | ||
4017 | if (rt2x00_rt_rev_gte(rt2x00dev, RT5592, REV_RT5592C)) | ||
4018 | rt2800_bbp_write(rt2x00dev, 103, 0xc0); | ||
4019 | } | ||
4020 | |||
3490 | static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) | 4021 | static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) |
3491 | { | 4022 | { |
3492 | unsigned int i; | 4023 | unsigned int i; |
@@ -3498,6 +4029,11 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) | |||
3498 | rt2800_wait_bbp_ready(rt2x00dev))) | 4029 | rt2800_wait_bbp_ready(rt2x00dev))) |
3499 | return -EACCES; | 4030 | return -EACCES; |
3500 | 4031 | ||
4032 | if (rt2x00_rt(rt2x00dev, RT5592)) { | ||
4033 | rt2800_init_bbp_5592(rt2x00dev); | ||
4034 | return 0; | ||
4035 | } | ||
4036 | |||
3501 | if (rt2x00_rt(rt2x00dev, RT3352)) { | 4037 | if (rt2x00_rt(rt2x00dev, RT3352)) { |
3502 | rt2800_bbp_write(rt2x00dev, 3, 0x00); | 4038 | rt2800_bbp_write(rt2x00dev, 3, 0x00); |
3503 | rt2800_bbp_write(rt2x00dev, 4, 0x50); | 4039 | rt2800_bbp_write(rt2x00dev, 4, 0x50); |
@@ -3505,11 +4041,8 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) | |||
3505 | 4041 | ||
3506 | if (rt2x00_rt(rt2x00dev, RT3290) || | 4042 | if (rt2x00_rt(rt2x00dev, RT3290) || |
3507 | rt2x00_rt(rt2x00dev, RT5390) || | 4043 | rt2x00_rt(rt2x00dev, RT5390) || |
3508 | rt2x00_rt(rt2x00dev, RT5392)) { | 4044 | rt2x00_rt(rt2x00dev, RT5392)) |
3509 | rt2800_bbp_read(rt2x00dev, 4, &value); | 4045 | rt2800_bbp4_mac_if_ctrl(rt2x00dev); |
3510 | rt2x00_set_field8(&value, BBP4_MAC_IF_CTRL, 1); | ||
3511 | rt2800_bbp_write(rt2x00dev, 4, value); | ||
3512 | } | ||
3513 | 4046 | ||
3514 | if (rt2800_is_305x_soc(rt2x00dev) || | 4047 | if (rt2800_is_305x_soc(rt2x00dev) || |
3515 | rt2x00_rt(rt2x00dev, RT3290) || | 4048 | rt2x00_rt(rt2x00dev, RT3290) || |
@@ -3783,9 +4316,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) | |||
3783 | rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 0); | 4316 | rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 0); |
3784 | rt2800_bbp_write(rt2x00dev, 152, value); | 4317 | rt2800_bbp_write(rt2x00dev, 152, value); |
3785 | 4318 | ||
3786 | /* Init frequency calibration */ | 4319 | rt2800_init_freq_calibration(rt2x00dev); |
3787 | rt2800_bbp_write(rt2x00dev, 142, 1); | ||
3788 | rt2800_bbp_write(rt2x00dev, 143, 57); | ||
3789 | } | 4320 | } |
3790 | 4321 | ||
3791 | for (i = 0; i < EEPROM_BBP_SIZE; i++) { | 4322 | for (i = 0; i < EEPROM_BBP_SIZE; i++) { |
@@ -4259,6 +4790,69 @@ static void rt2800_init_rfcsr_5392(struct rt2x00_dev *rt2x00dev) | |||
4259 | rt2800_rfcsr_write(rt2x00dev, 63, 0x07); | 4790 | rt2800_rfcsr_write(rt2x00dev, 63, 0x07); |
4260 | } | 4791 | } |
4261 | 4792 | ||
4793 | static void rt2800_init_rfcsr_5592(struct rt2x00_dev *rt2x00dev) | ||
4794 | { | ||
4795 | u8 reg; | ||
4796 | u16 eeprom; | ||
4797 | |||
4798 | rt2800_rfcsr_write(rt2x00dev, 1, 0x3F); | ||
4799 | rt2800_rfcsr_write(rt2x00dev, 3, 0x08); | ||
4800 | rt2800_rfcsr_write(rt2x00dev, 3, 0x08); | ||
4801 | rt2800_rfcsr_write(rt2x00dev, 5, 0x10); | ||
4802 | rt2800_rfcsr_write(rt2x00dev, 6, 0xE4); | ||
4803 | rt2800_rfcsr_write(rt2x00dev, 7, 0x00); | ||
4804 | rt2800_rfcsr_write(rt2x00dev, 14, 0x00); | ||
4805 | rt2800_rfcsr_write(rt2x00dev, 15, 0x00); | ||
4806 | rt2800_rfcsr_write(rt2x00dev, 16, 0x00); | ||
4807 | rt2800_rfcsr_write(rt2x00dev, 18, 0x03); | ||
4808 | rt2800_rfcsr_write(rt2x00dev, 19, 0x4D); | ||
4809 | rt2800_rfcsr_write(rt2x00dev, 20, 0x10); | ||
4810 | rt2800_rfcsr_write(rt2x00dev, 21, 0x8D); | ||
4811 | rt2800_rfcsr_write(rt2x00dev, 26, 0x82); | ||
4812 | rt2800_rfcsr_write(rt2x00dev, 28, 0x00); | ||
4813 | rt2800_rfcsr_write(rt2x00dev, 29, 0x10); | ||
4814 | rt2800_rfcsr_write(rt2x00dev, 33, 0xC0); | ||
4815 | rt2800_rfcsr_write(rt2x00dev, 34, 0x07); | ||
4816 | rt2800_rfcsr_write(rt2x00dev, 35, 0x12); | ||
4817 | rt2800_rfcsr_write(rt2x00dev, 47, 0x0C); | ||
4818 | rt2800_rfcsr_write(rt2x00dev, 53, 0x22); | ||
4819 | rt2800_rfcsr_write(rt2x00dev, 63, 0x07); | ||
4820 | |||
4821 | rt2800_rfcsr_write(rt2x00dev, 2, 0x80); | ||
4822 | msleep(1); | ||
4823 | |||
4824 | rt2800_adjust_freq_offset(rt2x00dev); | ||
4825 | |||
4826 | rt2800_bbp_read(rt2x00dev, 138, ®); | ||
4827 | |||
4828 | /* Turn off unused DAC1 and ADC1 to reduce power consumption */ | ||
4829 | rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); | ||
4830 | if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1) | ||
4831 | rt2x00_set_field8(®, BBP138_RX_ADC1, 0); | ||
4832 | if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1) | ||
4833 | rt2x00_set_field8(®, BBP138_TX_DAC1, 1); | ||
4834 | |||
4835 | rt2800_bbp_write(rt2x00dev, 138, reg); | ||
4836 | |||
4837 | /* Enable DC filter */ | ||
4838 | if (rt2x00_rt_rev_gte(rt2x00dev, RT5592, REV_RT5592C)) | ||
4839 | rt2800_bbp_write(rt2x00dev, 103, 0xc0); | ||
4840 | |||
4841 | rt2800_rfcsr_read(rt2x00dev, 38, ®); | ||
4842 | rt2x00_set_field8(®, RFCSR38_RX_LO1_EN, 0); | ||
4843 | rt2800_rfcsr_write(rt2x00dev, 38, reg); | ||
4844 | |||
4845 | rt2800_rfcsr_read(rt2x00dev, 39, ®); | ||
4846 | rt2x00_set_field8(®, RFCSR39_RX_LO2_EN, 0); | ||
4847 | rt2800_rfcsr_write(rt2x00dev, 39, reg); | ||
4848 | |||
4849 | rt2800_bbp4_mac_if_ctrl(rt2x00dev); | ||
4850 | |||
4851 | rt2800_rfcsr_read(rt2x00dev, 30, ®); | ||
4852 | rt2x00_set_field8(®, RFCSR30_RX_VCM, 2); | ||
4853 | rt2800_rfcsr_write(rt2x00dev, 30, reg); | ||
4854 | } | ||
4855 | |||
4262 | static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | 4856 | static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) |
4263 | { | 4857 | { |
4264 | struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; | 4858 | struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; |
@@ -4276,6 +4870,8 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | |||
4276 | !rt2x00_rt(rt2x00dev, RT3572) && | 4870 | !rt2x00_rt(rt2x00dev, RT3572) && |
4277 | !rt2x00_rt(rt2x00dev, RT5390) && | 4871 | !rt2x00_rt(rt2x00dev, RT5390) && |
4278 | !rt2x00_rt(rt2x00dev, RT5392) && | 4872 | !rt2x00_rt(rt2x00dev, RT5392) && |
4873 | !rt2x00_rt(rt2x00dev, RT5392) && | ||
4874 | !rt2x00_rt(rt2x00dev, RT5592) && | ||
4279 | !rt2800_is_305x_soc(rt2x00dev)) | 4875 | !rt2800_is_305x_soc(rt2x00dev)) |
4280 | return 0; | 4876 | return 0; |
4281 | 4877 | ||
@@ -4330,6 +4926,9 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | |||
4330 | case RT5392: | 4926 | case RT5392: |
4331 | rt2800_init_rfcsr_5392(rt2x00dev); | 4927 | rt2800_init_rfcsr_5392(rt2x00dev); |
4332 | break; | 4928 | break; |
4929 | case RT5592: | ||
4930 | rt2800_init_rfcsr_5592(rt2x00dev); | ||
4931 | return 0; | ||
4333 | } | 4932 | } |
4334 | 4933 | ||
4335 | if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) { | 4934 | if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) { |
@@ -4427,7 +5026,8 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | |||
4427 | if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F) || | 5026 | if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F) || |
4428 | rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || | 5027 | rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || |
4429 | rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) || | 5028 | rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) || |
4430 | rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) | 5029 | rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E) || |
5030 | rt2x00_rt_rev_lt(rt2x00dev, RT5592, REV_RT5592C)) | ||
4431 | rt2800_rfcsr_write(rt2x00dev, 27, 0x03); | 5031 | rt2800_rfcsr_write(rt2x00dev, 27, 0x03); |
4432 | 5032 | ||
4433 | rt2800_register_read(rt2x00dev, OPT_14_CSR, ®); | 5033 | rt2800_register_read(rt2x00dev, OPT_14_CSR, ®); |
@@ -4451,7 +5051,8 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | |||
4451 | rt2800_rfcsr_write(rt2x00dev, 17, rfcsr); | 5051 | rt2800_rfcsr_write(rt2x00dev, 17, rfcsr); |
4452 | } | 5052 | } |
4453 | 5053 | ||
4454 | if (rt2x00_rt(rt2x00dev, RT3090)) { | 5054 | if (rt2x00_rt(rt2x00dev, RT3090) || |
5055 | rt2x00_rt(rt2x00dev, RT5592)) { | ||
4455 | rt2800_bbp_read(rt2x00dev, 138, &bbp); | 5056 | rt2800_bbp_read(rt2x00dev, 138, &bbp); |
4456 | 5057 | ||
4457 | /* Turn off unused DAC1 and ADC1 to reduce power consumption */ | 5058 | /* Turn off unused DAC1 and ADC1 to reduce power consumption */ |
@@ -4507,7 +5108,8 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | |||
4507 | } | 5108 | } |
4508 | 5109 | ||
4509 | if (rt2x00_rt(rt2x00dev, RT5390) || | 5110 | if (rt2x00_rt(rt2x00dev, RT5390) || |
4510 | rt2x00_rt(rt2x00dev, RT5392)) { | 5111 | rt2x00_rt(rt2x00dev, RT5392) || |
5112 | rt2x00_rt(rt2x00dev, RT5592)) { | ||
4511 | rt2800_rfcsr_read(rt2x00dev, 38, &rfcsr); | 5113 | rt2800_rfcsr_read(rt2x00dev, 38, &rfcsr); |
4512 | rt2x00_set_field8(&rfcsr, RFCSR38_RX_LO1_EN, 0); | 5114 | rt2x00_set_field8(&rfcsr, RFCSR38_RX_LO1_EN, 0); |
4513 | rt2800_rfcsr_write(rt2x00dev, 38, rfcsr); | 5115 | rt2800_rfcsr_write(rt2x00dev, 38, rfcsr); |
@@ -4533,15 +5135,23 @@ int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev) | |||
4533 | * Initialize all registers. | 5135 | * Initialize all registers. |
4534 | */ | 5136 | */ |
4535 | if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev) || | 5137 | if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev) || |
4536 | rt2800_init_registers(rt2x00dev) || | 5138 | rt2800_init_registers(rt2x00dev))) |
4537 | rt2800_init_bbp(rt2x00dev) || | ||
4538 | rt2800_init_rfcsr(rt2x00dev))) | ||
4539 | return -EIO; | 5139 | return -EIO; |
4540 | 5140 | ||
4541 | /* | 5141 | /* |
4542 | * Send signal to firmware during boot time. | 5142 | * Send signal to firmware during boot time. |
4543 | */ | 5143 | */ |
4544 | rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0); | 5144 | rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0); |
5145 | rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); | ||
5146 | if (rt2x00_is_usb(rt2x00dev)) { | ||
5147 | rt2800_register_write(rt2x00dev, H2M_INT_SRC, 0); | ||
5148 | rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0); | ||
5149 | } | ||
5150 | msleep(1); | ||
5151 | |||
5152 | if (unlikely(rt2800_init_bbp(rt2x00dev) || | ||
5153 | rt2800_init_rfcsr(rt2x00dev))) | ||
5154 | return -EIO; | ||
4545 | 5155 | ||
4546 | if (rt2x00_is_usb(rt2x00dev) && | 5156 | if (rt2x00_is_usb(rt2x00dev) && |
4547 | (rt2x00_rt(rt2x00dev, RT3070) || | 5157 | (rt2x00_rt(rt2x00dev, RT3070) || |
@@ -4863,6 +5473,7 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
4863 | case RT3572: | 5473 | case RT3572: |
4864 | case RT5390: | 5474 | case RT5390: |
4865 | case RT5392: | 5475 | case RT5392: |
5476 | case RT5592: | ||
4866 | break; | 5477 | break; |
4867 | default: | 5478 | default: |
4868 | ERROR(rt2x00dev, "Invalid RT chipset 0x%04x detected.\n", rt2x00dev->chip.rt); | 5479 | ERROR(rt2x00dev, "Invalid RT chipset 0x%04x detected.\n", rt2x00dev->chip.rt); |
@@ -4887,6 +5498,7 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
4887 | case RF5372: | 5498 | case RF5372: |
4888 | case RF5390: | 5499 | case RF5390: |
4889 | case RF5392: | 5500 | case RF5392: |
5501 | case RF5592: | ||
4890 | break; | 5502 | break; |
4891 | default: | 5503 | default: |
4892 | ERROR(rt2x00dev, "Invalid RF chipset 0x%04x detected.\n", | 5504 | ERROR(rt2x00dev, "Invalid RF chipset 0x%04x detected.\n", |
@@ -5122,6 +5734,138 @@ static const struct rf_channel rf_vals_3x[] = { | |||
5122 | {173, 0x61, 0, 9}, | 5734 | {173, 0x61, 0, 9}, |
5123 | }; | 5735 | }; |
5124 | 5736 | ||
5737 | static const struct rf_channel rf_vals_5592_xtal20[] = { | ||
5738 | /* Channel, N, K, mod, R */ | ||
5739 | {1, 482, 4, 10, 3}, | ||
5740 | {2, 483, 4, 10, 3}, | ||
5741 | {3, 484, 4, 10, 3}, | ||
5742 | {4, 485, 4, 10, 3}, | ||
5743 | {5, 486, 4, 10, 3}, | ||
5744 | {6, 487, 4, 10, 3}, | ||
5745 | {7, 488, 4, 10, 3}, | ||
5746 | {8, 489, 4, 10, 3}, | ||
5747 | {9, 490, 4, 10, 3}, | ||
5748 | {10, 491, 4, 10, 3}, | ||
5749 | {11, 492, 4, 10, 3}, | ||
5750 | {12, 493, 4, 10, 3}, | ||
5751 | {13, 494, 4, 10, 3}, | ||
5752 | {14, 496, 8, 10, 3}, | ||
5753 | {36, 172, 8, 12, 1}, | ||
5754 | {38, 173, 0, 12, 1}, | ||
5755 | {40, 173, 4, 12, 1}, | ||
5756 | {42, 173, 8, 12, 1}, | ||
5757 | {44, 174, 0, 12, 1}, | ||
5758 | {46, 174, 4, 12, 1}, | ||
5759 | {48, 174, 8, 12, 1}, | ||
5760 | {50, 175, 0, 12, 1}, | ||
5761 | {52, 175, 4, 12, 1}, | ||
5762 | {54, 175, 8, 12, 1}, | ||
5763 | {56, 176, 0, 12, 1}, | ||
5764 | {58, 176, 4, 12, 1}, | ||
5765 | {60, 176, 8, 12, 1}, | ||
5766 | {62, 177, 0, 12, 1}, | ||
5767 | {64, 177, 4, 12, 1}, | ||
5768 | {100, 183, 4, 12, 1}, | ||
5769 | {102, 183, 8, 12, 1}, | ||
5770 | {104, 184, 0, 12, 1}, | ||
5771 | {106, 184, 4, 12, 1}, | ||
5772 | {108, 184, 8, 12, 1}, | ||
5773 | {110, 185, 0, 12, 1}, | ||
5774 | {112, 185, 4, 12, 1}, | ||
5775 | {114, 185, 8, 12, 1}, | ||
5776 | {116, 186, 0, 12, 1}, | ||
5777 | {118, 186, 4, 12, 1}, | ||
5778 | {120, 186, 8, 12, 1}, | ||
5779 | {122, 187, 0, 12, 1}, | ||
5780 | {124, 187, 4, 12, 1}, | ||
5781 | {126, 187, 8, 12, 1}, | ||
5782 | {128, 188, 0, 12, 1}, | ||
5783 | {130, 188, 4, 12, 1}, | ||
5784 | {132, 188, 8, 12, 1}, | ||
5785 | {134, 189, 0, 12, 1}, | ||
5786 | {136, 189, 4, 12, 1}, | ||
5787 | {138, 189, 8, 12, 1}, | ||
5788 | {140, 190, 0, 12, 1}, | ||
5789 | {149, 191, 6, 12, 1}, | ||
5790 | {151, 191, 10, 12, 1}, | ||
5791 | {153, 192, 2, 12, 1}, | ||
5792 | {155, 192, 6, 12, 1}, | ||
5793 | {157, 192, 10, 12, 1}, | ||
5794 | {159, 193, 2, 12, 1}, | ||
5795 | {161, 193, 6, 12, 1}, | ||
5796 | {165, 194, 2, 12, 1}, | ||
5797 | {184, 164, 0, 12, 1}, | ||
5798 | {188, 164, 4, 12, 1}, | ||
5799 | {192, 165, 8, 12, 1}, | ||
5800 | {196, 166, 0, 12, 1}, | ||
5801 | }; | ||
5802 | |||
5803 | static const struct rf_channel rf_vals_5592_xtal40[] = { | ||
5804 | /* Channel, N, K, mod, R */ | ||
5805 | {1, 241, 2, 10, 3}, | ||
5806 | {2, 241, 7, 10, 3}, | ||
5807 | {3, 242, 2, 10, 3}, | ||
5808 | {4, 242, 7, 10, 3}, | ||
5809 | {5, 243, 2, 10, 3}, | ||
5810 | {6, 243, 7, 10, 3}, | ||
5811 | {7, 244, 2, 10, 3}, | ||
5812 | {8, 244, 7, 10, 3}, | ||
5813 | {9, 245, 2, 10, 3}, | ||
5814 | {10, 245, 7, 10, 3}, | ||
5815 | {11, 246, 2, 10, 3}, | ||
5816 | {12, 246, 7, 10, 3}, | ||
5817 | {13, 247, 2, 10, 3}, | ||
5818 | {14, 248, 4, 10, 3}, | ||
5819 | {36, 86, 4, 12, 1}, | ||
5820 | {38, 86, 6, 12, 1}, | ||
5821 | {40, 86, 8, 12, 1}, | ||
5822 | {42, 86, 10, 12, 1}, | ||
5823 | {44, 87, 0, 12, 1}, | ||
5824 | {46, 87, 2, 12, 1}, | ||
5825 | {48, 87, 4, 12, 1}, | ||
5826 | {50, 87, 6, 12, 1}, | ||
5827 | {52, 87, 8, 12, 1}, | ||
5828 | {54, 87, 10, 12, 1}, | ||
5829 | {56, 88, 0, 12, 1}, | ||
5830 | {58, 88, 2, 12, 1}, | ||
5831 | {60, 88, 4, 12, 1}, | ||
5832 | {62, 88, 6, 12, 1}, | ||
5833 | {64, 88, 8, 12, 1}, | ||
5834 | {100, 91, 8, 12, 1}, | ||
5835 | {102, 91, 10, 12, 1}, | ||
5836 | {104, 92, 0, 12, 1}, | ||
5837 | {106, 92, 2, 12, 1}, | ||
5838 | {108, 92, 4, 12, 1}, | ||
5839 | {110, 92, 6, 12, 1}, | ||
5840 | {112, 92, 8, 12, 1}, | ||
5841 | {114, 92, 10, 12, 1}, | ||
5842 | {116, 93, 0, 12, 1}, | ||
5843 | {118, 93, 2, 12, 1}, | ||
5844 | {120, 93, 4, 12, 1}, | ||
5845 | {122, 93, 6, 12, 1}, | ||
5846 | {124, 93, 8, 12, 1}, | ||
5847 | {126, 93, 10, 12, 1}, | ||
5848 | {128, 94, 0, 12, 1}, | ||
5849 | {130, 94, 2, 12, 1}, | ||
5850 | {132, 94, 4, 12, 1}, | ||
5851 | {134, 94, 6, 12, 1}, | ||
5852 | {136, 94, 8, 12, 1}, | ||
5853 | {138, 94, 10, 12, 1}, | ||
5854 | {140, 95, 0, 12, 1}, | ||
5855 | {149, 95, 9, 12, 1}, | ||
5856 | {151, 95, 11, 12, 1}, | ||
5857 | {153, 96, 1, 12, 1}, | ||
5858 | {155, 96, 3, 12, 1}, | ||
5859 | {157, 96, 5, 12, 1}, | ||
5860 | {159, 96, 7, 12, 1}, | ||
5861 | {161, 96, 9, 12, 1}, | ||
5862 | {165, 97, 1, 12, 1}, | ||
5863 | {184, 82, 0, 12, 1}, | ||
5864 | {188, 82, 4, 12, 1}, | ||
5865 | {192, 82, 8, 12, 1}, | ||
5866 | {196, 83, 0, 12, 1}, | ||
5867 | }; | ||
5868 | |||
5125 | static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | 5869 | static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) |
5126 | { | 5870 | { |
5127 | struct hw_mode_spec *spec = &rt2x00dev->spec; | 5871 | struct hw_mode_spec *spec = &rt2x00dev->spec; |
@@ -5130,6 +5874,7 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
5130 | char *default_power2; | 5874 | char *default_power2; |
5131 | unsigned int i; | 5875 | unsigned int i; |
5132 | u16 eeprom; | 5876 | u16 eeprom; |
5877 | u32 reg; | ||
5133 | 5878 | ||
5134 | /* | 5879 | /* |
5135 | * Disable powersaving as default on PCI devices. | 5880 | * Disable powersaving as default on PCI devices. |
@@ -5211,8 +5956,22 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
5211 | spec->supported_bands |= SUPPORT_BAND_5GHZ; | 5956 | spec->supported_bands |= SUPPORT_BAND_5GHZ; |
5212 | spec->num_channels = ARRAY_SIZE(rf_vals_3x); | 5957 | spec->num_channels = ARRAY_SIZE(rf_vals_3x); |
5213 | spec->channels = rf_vals_3x; | 5958 | spec->channels = rf_vals_3x; |
5959 | } else if (rt2x00_rf(rt2x00dev, RF5592)) { | ||
5960 | spec->supported_bands |= SUPPORT_BAND_5GHZ; | ||
5961 | |||
5962 | rt2800_register_read(rt2x00dev, MAC_DEBUG_INDEX, ®); | ||
5963 | if (rt2x00_get_field32(reg, MAC_DEBUG_INDEX_XTAL)) { | ||
5964 | spec->num_channels = ARRAY_SIZE(rf_vals_5592_xtal40); | ||
5965 | spec->channels = rf_vals_5592_xtal40; | ||
5966 | } else { | ||
5967 | spec->num_channels = ARRAY_SIZE(rf_vals_5592_xtal20); | ||
5968 | spec->channels = rf_vals_5592_xtal20; | ||
5969 | } | ||
5214 | } | 5970 | } |
5215 | 5971 | ||
5972 | if (WARN_ON_ONCE(!spec->channels)) | ||
5973 | return -ENODEV; | ||
5974 | |||
5216 | /* | 5975 | /* |
5217 | * Initialize HT information. | 5976 | * Initialize HT information. |
5218 | */ | 5977 | */ |
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index ded73da4de0b..f732ded8f1ba 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c | |||
@@ -729,6 +729,11 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry, | |||
729 | * Process the RXWI structure that is at the start of the buffer. | 729 | * Process the RXWI structure that is at the start of the buffer. |
730 | */ | 730 | */ |
731 | rt2800_process_rxwi(entry, rxdesc); | 731 | rt2800_process_rxwi(entry, rxdesc); |
732 | |||
733 | /* | ||
734 | * Remove RXWI descriptor from start of buffer. | ||
735 | */ | ||
736 | skb_pull(entry->skb, RXWI_DESC_SIZE); | ||
732 | } | 737 | } |
733 | 738 | ||
734 | /* | 739 | /* |
@@ -742,10 +747,90 @@ static void rt2800pci_wakeup(struct rt2x00_dev *rt2x00dev) | |||
742 | rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS); | 747 | rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS); |
743 | } | 748 | } |
744 | 749 | ||
750 | static bool rt2800pci_txdone_entry_check(struct queue_entry *entry, u32 status) | ||
751 | { | ||
752 | __le32 *txwi; | ||
753 | u32 word; | ||
754 | int wcid, tx_wcid; | ||
755 | |||
756 | wcid = rt2x00_get_field32(status, TX_STA_FIFO_WCID); | ||
757 | |||
758 | txwi = rt2800_drv_get_txwi(entry); | ||
759 | rt2x00_desc_read(txwi, 1, &word); | ||
760 | tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID); | ||
761 | |||
762 | return (tx_wcid == wcid); | ||
763 | } | ||
764 | |||
765 | static bool rt2800pci_txdone_find_entry(struct queue_entry *entry, void *data) | ||
766 | { | ||
767 | u32 status = *(u32 *)data; | ||
768 | |||
769 | /* | ||
770 | * rt2800pci hardware might reorder frames when exchanging traffic | ||
771 | * with multiple BA enabled STAs. | ||
772 | * | ||
773 | * For example, a tx queue | ||
774 | * [ STA1 | STA2 | STA1 | STA2 ] | ||
775 | * can result in tx status reports | ||
776 | * [ STA1 | STA1 | STA2 | STA2 ] | ||
777 | * when the hw decides to aggregate the frames for STA1 into one AMPDU. | ||
778 | * | ||
779 | * To mitigate this effect, associate the tx status to the first frame | ||
780 | * in the tx queue with a matching wcid. | ||
781 | */ | ||
782 | if (rt2800pci_txdone_entry_check(entry, status) && | ||
783 | !test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) { | ||
784 | /* | ||
785 | * Got a matching frame, associate the tx status with | ||
786 | * the frame | ||
787 | */ | ||
788 | entry->status = status; | ||
789 | set_bit(ENTRY_DATA_STATUS_SET, &entry->flags); | ||
790 | return true; | ||
791 | } | ||
792 | |||
793 | /* Check the next frame */ | ||
794 | return false; | ||
795 | } | ||
796 | |||
797 | static bool rt2800pci_txdone_match_first(struct queue_entry *entry, void *data) | ||
798 | { | ||
799 | u32 status = *(u32 *)data; | ||
800 | |||
801 | /* | ||
802 | * Find the first frame without tx status and assign this status to it | ||
803 | * regardless if it matches or not. | ||
804 | */ | ||
805 | if (!test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) { | ||
806 | /* | ||
807 | * Got a matching frame, associate the tx status with | ||
808 | * the frame | ||
809 | */ | ||
810 | entry->status = status; | ||
811 | set_bit(ENTRY_DATA_STATUS_SET, &entry->flags); | ||
812 | return true; | ||
813 | } | ||
814 | |||
815 | /* Check the next frame */ | ||
816 | return false; | ||
817 | } | ||
818 | static bool rt2800pci_txdone_release_entries(struct queue_entry *entry, | ||
819 | void *data) | ||
820 | { | ||
821 | if (test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) { | ||
822 | rt2800_txdone_entry(entry, entry->status, | ||
823 | rt2800pci_get_txwi(entry)); | ||
824 | return false; | ||
825 | } | ||
826 | |||
827 | /* No more frames to release */ | ||
828 | return true; | ||
829 | } | ||
830 | |||
745 | static bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) | 831 | static bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) |
746 | { | 832 | { |
747 | struct data_queue *queue; | 833 | struct data_queue *queue; |
748 | struct queue_entry *entry; | ||
749 | u32 status; | 834 | u32 status; |
750 | u8 qid; | 835 | u8 qid; |
751 | int max_tx_done = 16; | 836 | int max_tx_done = 16; |
@@ -783,8 +868,33 @@ static bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) | |||
783 | break; | 868 | break; |
784 | } | 869 | } |
785 | 870 | ||
786 | entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); | 871 | /* |
787 | rt2800_txdone_entry(entry, status, rt2800pci_get_txwi(entry)); | 872 | * Let's associate this tx status with the first |
873 | * matching frame. | ||
874 | */ | ||
875 | if (!rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, | ||
876 | Q_INDEX, &status, | ||
877 | rt2800pci_txdone_find_entry)) { | ||
878 | /* | ||
879 | * We cannot match the tx status to any frame, so just | ||
880 | * use the first one. | ||
881 | */ | ||
882 | if (!rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, | ||
883 | Q_INDEX, &status, | ||
884 | rt2800pci_txdone_match_first)) { | ||
885 | WARNING(rt2x00dev, "No frame found for TX " | ||
886 | "status on queue %u, dropping\n", | ||
887 | qid); | ||
888 | break; | ||
889 | } | ||
890 | } | ||
891 | |||
892 | /* | ||
893 | * Release all frames with a valid tx status. | ||
894 | */ | ||
895 | rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, | ||
896 | Q_INDEX, NULL, | ||
897 | rt2800pci_txdone_release_entries); | ||
788 | 898 | ||
789 | if (--max_tx_done == 0) | 899 | if (--max_tx_done == 0) |
790 | break; | 900 | break; |
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 098613ed93fb..f32282009146 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c | |||
@@ -485,7 +485,7 @@ static void rt2800usb_write_tx_desc(struct queue_entry *entry, | |||
485 | */ | 485 | */ |
486 | skbdesc->flags |= SKBDESC_DESC_IN_SKB; | 486 | skbdesc->flags |= SKBDESC_DESC_IN_SKB; |
487 | skbdesc->desc = txi; | 487 | skbdesc->desc = txi; |
488 | skbdesc->desc_len = TXINFO_DESC_SIZE + TXWI_DESC_SIZE; | 488 | skbdesc->desc_len = entry->queue->desc_size; |
489 | } | 489 | } |
490 | 490 | ||
491 | /* | 491 | /* |
@@ -730,6 +730,11 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry, | |||
730 | * Process the RXWI structure. | 730 | * Process the RXWI structure. |
731 | */ | 731 | */ |
732 | rt2800_process_rxwi(entry, rxdesc); | 732 | rt2800_process_rxwi(entry, rxdesc); |
733 | |||
734 | /* | ||
735 | * Remove RXWI descriptor from start of buffer. | ||
736 | */ | ||
737 | skb_pull(entry->skb, entry->queue->desc_size - RXINFO_DESC_SIZE); | ||
733 | } | 738 | } |
734 | 739 | ||
735 | /* | 740 | /* |
@@ -890,6 +895,47 @@ static const struct rt2x00_ops rt2800usb_ops = { | |||
890 | #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ | 895 | #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ |
891 | }; | 896 | }; |
892 | 897 | ||
898 | static const struct data_queue_desc rt2800usb_queue_rx_5592 = { | ||
899 | .entry_num = 128, | ||
900 | .data_size = AGGREGATION_SIZE, | ||
901 | .desc_size = RXINFO_DESC_SIZE + RXWI_DESC_SIZE_5592, | ||
902 | .priv_size = sizeof(struct queue_entry_priv_usb), | ||
903 | }; | ||
904 | |||
905 | static const struct data_queue_desc rt2800usb_queue_tx_5592 = { | ||
906 | .entry_num = 16, | ||
907 | .data_size = AGGREGATION_SIZE, | ||
908 | .desc_size = TXINFO_DESC_SIZE + TXWI_DESC_SIZE_5592, | ||
909 | .priv_size = sizeof(struct queue_entry_priv_usb), | ||
910 | }; | ||
911 | |||
912 | static const struct data_queue_desc rt2800usb_queue_bcn_5592 = { | ||
913 | .entry_num = 8, | ||
914 | .data_size = MGMT_FRAME_SIZE, | ||
915 | .desc_size = TXINFO_DESC_SIZE + TXWI_DESC_SIZE_5592, | ||
916 | .priv_size = sizeof(struct queue_entry_priv_usb), | ||
917 | }; | ||
918 | |||
919 | |||
920 | static const struct rt2x00_ops rt2800usb_ops_5592 = { | ||
921 | .name = KBUILD_MODNAME, | ||
922 | .drv_data_size = sizeof(struct rt2800_drv_data), | ||
923 | .max_ap_intf = 8, | ||
924 | .eeprom_size = EEPROM_SIZE, | ||
925 | .rf_size = RF_SIZE, | ||
926 | .tx_queues = NUM_TX_QUEUES, | ||
927 | .extra_tx_headroom = TXINFO_DESC_SIZE + TXWI_DESC_SIZE_5592, | ||
928 | .rx = &rt2800usb_queue_rx_5592, | ||
929 | .tx = &rt2800usb_queue_tx_5592, | ||
930 | .bcn = &rt2800usb_queue_bcn_5592, | ||
931 | .lib = &rt2800usb_rt2x00_ops, | ||
932 | .drv = &rt2800usb_rt2800_ops, | ||
933 | .hw = &rt2800usb_mac80211_ops, | ||
934 | #ifdef CONFIG_RT2X00_LIB_DEBUGFS | ||
935 | .debugfs = &rt2800_rt2x00debug, | ||
936 | #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ | ||
937 | }; | ||
938 | |||
893 | /* | 939 | /* |
894 | * rt2800usb module information. | 940 | * rt2800usb module information. |
895 | */ | 941 | */ |
@@ -1200,6 +1246,18 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
1200 | { USB_DEVICE(0x148f, 0x5370) }, | 1246 | { USB_DEVICE(0x148f, 0x5370) }, |
1201 | { USB_DEVICE(0x148f, 0x5372) }, | 1247 | { USB_DEVICE(0x148f, 0x5372) }, |
1202 | #endif | 1248 | #endif |
1249 | #ifdef CONFIG_RT2800USB_RT55XX | ||
1250 | /* Arcadyan */ | ||
1251 | { USB_DEVICE(0x043e, 0x7a32), .driver_info = 5592 }, | ||
1252 | /* AVM GmbH */ | ||
1253 | { USB_DEVICE(0x057c, 0x8501), .driver_info = 5592 }, | ||
1254 | /* D-Link DWA-160-B2 */ | ||
1255 | { USB_DEVICE(0x2001, 0x3c1a), .driver_info = 5592 }, | ||
1256 | /* Proware */ | ||
1257 | { USB_DEVICE(0x043e, 0x7a13), .driver_info = 5592 }, | ||
1258 | /* Ralink */ | ||
1259 | { USB_DEVICE(0x148f, 0x5572), .driver_info = 5592 }, | ||
1260 | #endif | ||
1203 | #ifdef CONFIG_RT2800USB_UNKNOWN | 1261 | #ifdef CONFIG_RT2800USB_UNKNOWN |
1204 | /* | 1262 | /* |
1205 | * Unclear what kind of devices these are (they aren't supported by the | 1263 | * Unclear what kind of devices these are (they aren't supported by the |
@@ -1303,6 +1361,9 @@ MODULE_LICENSE("GPL"); | |||
1303 | static int rt2800usb_probe(struct usb_interface *usb_intf, | 1361 | static int rt2800usb_probe(struct usb_interface *usb_intf, |
1304 | const struct usb_device_id *id) | 1362 | const struct usb_device_id *id) |
1305 | { | 1363 | { |
1364 | if (id->driver_info == 5592) | ||
1365 | return rt2x00usb_probe(usb_intf, &rt2800usb_ops_5592); | ||
1366 | |||
1306 | return rt2x00usb_probe(usb_intf, &rt2800usb_ops); | 1367 | return rt2x00usb_probe(usb_intf, &rt2800usb_ops); |
1307 | } | 1368 | } |
1308 | 1369 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 086abb403a4f..51922cc179de 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -193,6 +193,7 @@ struct rt2x00_chip { | |||
193 | #define RT3883 0x3883 /* WSOC */ | 193 | #define RT3883 0x3883 /* WSOC */ |
194 | #define RT5390 0x5390 /* 2.4GHz */ | 194 | #define RT5390 0x5390 /* 2.4GHz */ |
195 | #define RT5392 0x5392 /* 2.4GHz */ | 195 | #define RT5392 0x5392 /* 2.4GHz */ |
196 | #define RT5592 0x5592 | ||
196 | 197 | ||
197 | u16 rf; | 198 | u16 rf; |
198 | u16 rev; | 199 | u16 rev; |
@@ -1064,8 +1065,7 @@ static inline void rt2x00_rf_write(struct rt2x00_dev *rt2x00dev, | |||
1064 | } | 1065 | } |
1065 | 1066 | ||
1066 | /* | 1067 | /* |
1067 | * Generic EEPROM access. | 1068 | * Generic EEPROM access. The EEPROM is being accessed by word or byte index. |
1068 | * The EEPROM is being accessed by word index. | ||
1069 | */ | 1069 | */ |
1070 | static inline void *rt2x00_eeprom_addr(struct rt2x00_dev *rt2x00dev, | 1070 | static inline void *rt2x00_eeprom_addr(struct rt2x00_dev *rt2x00dev, |
1071 | const unsigned int word) | 1071 | const unsigned int word) |
@@ -1085,6 +1085,12 @@ static inline void rt2x00_eeprom_write(struct rt2x00_dev *rt2x00dev, | |||
1085 | rt2x00dev->eeprom[word] = cpu_to_le16(data); | 1085 | rt2x00dev->eeprom[word] = cpu_to_le16(data); |
1086 | } | 1086 | } |
1087 | 1087 | ||
1088 | static inline u8 rt2x00_eeprom_byte(struct rt2x00_dev *rt2x00dev, | ||
1089 | const unsigned int byte) | ||
1090 | { | ||
1091 | return *(((u8 *)rt2x00dev->eeprom) + byte); | ||
1092 | } | ||
1093 | |||
1088 | /* | 1094 | /* |
1089 | * Chipset handlers | 1095 | * Chipset handlers |
1090 | */ | 1096 | */ |
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 696abed3e74b..c4009eaeb697 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c | |||
@@ -52,8 +52,8 @@ int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev, | |||
52 | udelay(REGISTER_BUSY_DELAY); | 52 | udelay(REGISTER_BUSY_DELAY); |
53 | } | 53 | } |
54 | 54 | ||
55 | ERROR(rt2x00dev, "Indirect register access failed: " | 55 | printk_once(KERN_ERR "%s() Indirect register access failed: " |
56 | "offset=0x%.08x, value=0x%.08x\n", offset, *reg); | 56 | "offset=0x%.08x, value=0x%.08x\n", __func__, offset, *reg); |
57 | *reg = ~0; | 57 | *reg = ~0; |
58 | 58 | ||
59 | return 0; | 59 | return 0; |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 4d91795dc6a2..952a0490eb17 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c | |||
@@ -832,7 +832,9 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, | |||
832 | bool rt2x00queue_for_each_entry(struct data_queue *queue, | 832 | bool rt2x00queue_for_each_entry(struct data_queue *queue, |
833 | enum queue_index start, | 833 | enum queue_index start, |
834 | enum queue_index end, | 834 | enum queue_index end, |
835 | bool (*fn)(struct queue_entry *entry)) | 835 | void *data, |
836 | bool (*fn)(struct queue_entry *entry, | ||
837 | void *data)) | ||
836 | { | 838 | { |
837 | unsigned long irqflags; | 839 | unsigned long irqflags; |
838 | unsigned int index_start; | 840 | unsigned int index_start; |
@@ -863,17 +865,17 @@ bool rt2x00queue_for_each_entry(struct data_queue *queue, | |||
863 | */ | 865 | */ |
864 | if (index_start < index_end) { | 866 | if (index_start < index_end) { |
865 | for (i = index_start; i < index_end; i++) { | 867 | for (i = index_start; i < index_end; i++) { |
866 | if (fn(&queue->entries[i])) | 868 | if (fn(&queue->entries[i], data)) |
867 | return true; | 869 | return true; |
868 | } | 870 | } |
869 | } else { | 871 | } else { |
870 | for (i = index_start; i < queue->limit; i++) { | 872 | for (i = index_start; i < queue->limit; i++) { |
871 | if (fn(&queue->entries[i])) | 873 | if (fn(&queue->entries[i], data)) |
872 | return true; | 874 | return true; |
873 | } | 875 | } |
874 | 876 | ||
875 | for (i = 0; i < index_end; i++) { | 877 | for (i = 0; i < index_end; i++) { |
876 | if (fn(&queue->entries[i])) | 878 | if (fn(&queue->entries[i], data)) |
877 | return true; | 879 | return true; |
878 | } | 880 | } |
879 | } | 881 | } |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 9b8c10a86dee..3d0137193da0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h | |||
@@ -359,6 +359,7 @@ enum queue_entry_flags { | |||
359 | ENTRY_DATA_PENDING, | 359 | ENTRY_DATA_PENDING, |
360 | ENTRY_DATA_IO_FAILED, | 360 | ENTRY_DATA_IO_FAILED, |
361 | ENTRY_DATA_STATUS_PENDING, | 361 | ENTRY_DATA_STATUS_PENDING, |
362 | ENTRY_DATA_STATUS_SET, | ||
362 | }; | 363 | }; |
363 | 364 | ||
364 | /** | 365 | /** |
@@ -372,6 +373,7 @@ enum queue_entry_flags { | |||
372 | * @entry_idx: The entry index number. | 373 | * @entry_idx: The entry index number. |
373 | * @priv_data: Private data belonging to this queue entry. The pointer | 374 | * @priv_data: Private data belonging to this queue entry. The pointer |
374 | * points to data specific to a particular driver and queue type. | 375 | * points to data specific to a particular driver and queue type. |
376 | * @status: Device specific status | ||
375 | */ | 377 | */ |
376 | struct queue_entry { | 378 | struct queue_entry { |
377 | unsigned long flags; | 379 | unsigned long flags; |
@@ -383,6 +385,8 @@ struct queue_entry { | |||
383 | 385 | ||
384 | unsigned int entry_idx; | 386 | unsigned int entry_idx; |
385 | 387 | ||
388 | u32 status; | ||
389 | |||
386 | void *priv_data; | 390 | void *priv_data; |
387 | }; | 391 | }; |
388 | 392 | ||
@@ -584,6 +588,7 @@ struct data_queue_desc { | |||
584 | * @queue: Pointer to @data_queue | 588 | * @queue: Pointer to @data_queue |
585 | * @start: &enum queue_index Pointer to start index | 589 | * @start: &enum queue_index Pointer to start index |
586 | * @end: &enum queue_index Pointer to end index | 590 | * @end: &enum queue_index Pointer to end index |
591 | * @data: Data to pass to the callback function | ||
587 | * @fn: The function to call for each &struct queue_entry | 592 | * @fn: The function to call for each &struct queue_entry |
588 | * | 593 | * |
589 | * This will walk through all entries in the queue, in chronological | 594 | * This will walk through all entries in the queue, in chronological |
@@ -596,7 +601,9 @@ struct data_queue_desc { | |||
596 | bool rt2x00queue_for_each_entry(struct data_queue *queue, | 601 | bool rt2x00queue_for_each_entry(struct data_queue *queue, |
597 | enum queue_index start, | 602 | enum queue_index start, |
598 | enum queue_index end, | 603 | enum queue_index end, |
599 | bool (*fn)(struct queue_entry *entry)); | 604 | void *data, |
605 | bool (*fn)(struct queue_entry *entry, | ||
606 | void *data)); | ||
600 | 607 | ||
601 | /** | 608 | /** |
602 | * rt2x00queue_empty - Check if the queue is empty. | 609 | * rt2x00queue_empty - Check if the queue is empty. |
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 40ea80725a96..5e50d4ff9d21 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c | |||
@@ -285,7 +285,7 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) | |||
285 | queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); | 285 | queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); |
286 | } | 286 | } |
287 | 287 | ||
288 | static bool rt2x00usb_kick_tx_entry(struct queue_entry *entry) | 288 | static bool rt2x00usb_kick_tx_entry(struct queue_entry *entry, void *data) |
289 | { | 289 | { |
290 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | 290 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; |
291 | struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); | 291 | struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); |
@@ -390,7 +390,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) | |||
390 | queue_work(rt2x00dev->workqueue, &rt2x00dev->rxdone_work); | 390 | queue_work(rt2x00dev->workqueue, &rt2x00dev->rxdone_work); |
391 | } | 391 | } |
392 | 392 | ||
393 | static bool rt2x00usb_kick_rx_entry(struct queue_entry *entry) | 393 | static bool rt2x00usb_kick_rx_entry(struct queue_entry *entry, void *data) |
394 | { | 394 | { |
395 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | 395 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; |
396 | struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); | 396 | struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); |
@@ -427,12 +427,18 @@ void rt2x00usb_kick_queue(struct data_queue *queue) | |||
427 | case QID_AC_BE: | 427 | case QID_AC_BE: |
428 | case QID_AC_BK: | 428 | case QID_AC_BK: |
429 | if (!rt2x00queue_empty(queue)) | 429 | if (!rt2x00queue_empty(queue)) |
430 | rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, | 430 | rt2x00queue_for_each_entry(queue, |
431 | Q_INDEX_DONE, | ||
432 | Q_INDEX, | ||
433 | NULL, | ||
431 | rt2x00usb_kick_tx_entry); | 434 | rt2x00usb_kick_tx_entry); |
432 | break; | 435 | break; |
433 | case QID_RX: | 436 | case QID_RX: |
434 | if (!rt2x00queue_full(queue)) | 437 | if (!rt2x00queue_full(queue)) |
435 | rt2x00queue_for_each_entry(queue, Q_INDEX, Q_INDEX_DONE, | 438 | rt2x00queue_for_each_entry(queue, |
439 | Q_INDEX, | ||
440 | Q_INDEX_DONE, | ||
441 | NULL, | ||
436 | rt2x00usb_kick_rx_entry); | 442 | rt2x00usb_kick_rx_entry); |
437 | break; | 443 | break; |
438 | default: | 444 | default: |
@@ -441,7 +447,7 @@ void rt2x00usb_kick_queue(struct data_queue *queue) | |||
441 | } | 447 | } |
442 | EXPORT_SYMBOL_GPL(rt2x00usb_kick_queue); | 448 | EXPORT_SYMBOL_GPL(rt2x00usb_kick_queue); |
443 | 449 | ||
444 | static bool rt2x00usb_flush_entry(struct queue_entry *entry) | 450 | static bool rt2x00usb_flush_entry(struct queue_entry *entry, void *data) |
445 | { | 451 | { |
446 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | 452 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; |
447 | struct queue_entry_priv_usb *entry_priv = entry->priv_data; | 453 | struct queue_entry_priv_usb *entry_priv = entry->priv_data; |
@@ -468,7 +474,7 @@ void rt2x00usb_flush_queue(struct data_queue *queue, bool drop) | |||
468 | unsigned int i; | 474 | unsigned int i; |
469 | 475 | ||
470 | if (drop) | 476 | if (drop) |
471 | rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, | 477 | rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, NULL, |
472 | rt2x00usb_flush_entry); | 478 | rt2x00usb_flush_entry); |
473 | 479 | ||
474 | /* | 480 | /* |
@@ -559,7 +565,7 @@ void rt2x00usb_clear_entry(struct queue_entry *entry) | |||
559 | entry->flags = 0; | 565 | entry->flags = 0; |
560 | 566 | ||
561 | if (entry->queue->qid == QID_RX) | 567 | if (entry->queue->qid == QID_RX) |
562 | rt2x00usb_kick_rx_entry(entry); | 568 | rt2x00usb_kick_rx_entry(entry, NULL); |
563 | } | 569 | } |
564 | EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry); | 570 | EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry); |
565 | 571 | ||
diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index 156b52732f3d..b5c80b5d57ef 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c | |||
@@ -224,10 +224,9 @@ static void _usb_writeN_sync(struct rtl_priv *rtlpriv, u32 addr, void *data, | |||
224 | u8 *buffer; | 224 | u8 *buffer; |
225 | 225 | ||
226 | wvalue = (u16)(addr & 0x0000ffff); | 226 | wvalue = (u16)(addr & 0x0000ffff); |
227 | buffer = kmalloc(len, GFP_ATOMIC); | 227 | buffer = kmemdup(data, len, GFP_ATOMIC); |
228 | if (!buffer) | 228 | if (!buffer) |
229 | return; | 229 | return; |
230 | memcpy(buffer, data, len); | ||
231 | usb_control_msg(udev, pipe, request, reqtype, wvalue, | 230 | usb_control_msg(udev, pipe, request, reqtype, wvalue, |
232 | index, buffer, len, 50); | 231 | index, buffer, len, 50); |
233 | 232 | ||
diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h index f13258a8d995..c3eff32acf6c 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/rtlwifi/wifi.h | |||
@@ -2127,9 +2127,6 @@ value to host byte ordering.*/ | |||
2127 | #define WLAN_FC_GET_TYPE(fc) (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) | 2127 | #define WLAN_FC_GET_TYPE(fc) (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) |
2128 | #define WLAN_FC_GET_STYPE(fc) (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) | 2128 | #define WLAN_FC_GET_STYPE(fc) (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) |
2129 | #define WLAN_FC_MORE_DATA(fc) (le16_to_cpu(fc) & IEEE80211_FCTL_MOREDATA) | 2129 | #define WLAN_FC_MORE_DATA(fc) (le16_to_cpu(fc) & IEEE80211_FCTL_MOREDATA) |
2130 | #define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4) | ||
2131 | #define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ) | ||
2132 | #define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4) | ||
2133 | 2130 | ||
2134 | #define RT_RF_OFF_LEVL_ASPM BIT(0) /*PCI ASPM */ | 2131 | #define RT_RF_OFF_LEVL_ASPM BIT(0) /*PCI ASPM */ |
2135 | #define RT_RF_OFF_LEVL_CLK_REQ BIT(1) /*PCI clock request */ | 2132 | #define RT_RF_OFF_LEVL_CLK_REQ BIT(1) /*PCI clock request */ |
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 2c2ff3e1f849..d7e306333f6c 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c | |||
@@ -4956,7 +4956,8 @@ static void wlcore_op_flush(struct ieee80211_hw *hw, bool drop) | |||
4956 | static int wlcore_op_remain_on_channel(struct ieee80211_hw *hw, | 4956 | static int wlcore_op_remain_on_channel(struct ieee80211_hw *hw, |
4957 | struct ieee80211_vif *vif, | 4957 | struct ieee80211_vif *vif, |
4958 | struct ieee80211_channel *chan, | 4958 | struct ieee80211_channel *chan, |
4959 | int duration) | 4959 | int duration, |
4960 | enum ieee80211_roc_type type) | ||
4960 | { | 4961 | { |
4961 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | 4962 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); |
4962 | struct wl1271 *wl = hw->priv; | 4963 | struct wl1271 *wl = hw->priv; |
diff --git a/drivers/nfc/microread/mei.c b/drivers/nfc/microread/mei.c index eef38cfd812e..13bde92b1e29 100644 --- a/drivers/nfc/microread/mei.c +++ b/drivers/nfc/microread/mei.c | |||
@@ -48,7 +48,7 @@ struct mei_nfc_hdr { | |||
48 | #define MEI_NFC_MAX_READ (MEI_NFC_HEADER_SIZE + MEI_NFC_MAX_HCI_PAYLOAD) | 48 | #define MEI_NFC_MAX_READ (MEI_NFC_HEADER_SIZE + MEI_NFC_MAX_HCI_PAYLOAD) |
49 | 49 | ||
50 | struct microread_mei_phy { | 50 | struct microread_mei_phy { |
51 | struct mei_device *mei_device; | 51 | struct mei_device *device; |
52 | struct nfc_hci_dev *hdev; | 52 | struct nfc_hci_dev *hdev; |
53 | 53 | ||
54 | int powered; | 54 | int powered; |
diff --git a/drivers/ssb/driver_chipcommon.c b/drivers/ssb/driver_chipcommon.c index 71098a7b5fed..7cb7d2c8fd86 100644 --- a/drivers/ssb/driver_chipcommon.c +++ b/drivers/ssb/driver_chipcommon.c | |||
@@ -354,7 +354,7 @@ void ssb_chipcommon_init(struct ssb_chipcommon *cc) | |||
354 | 354 | ||
355 | if (cc->dev->id.revision >= 11) | 355 | if (cc->dev->id.revision >= 11) |
356 | cc->status = chipco_read32(cc, SSB_CHIPCO_CHIPSTAT); | 356 | cc->status = chipco_read32(cc, SSB_CHIPCO_CHIPSTAT); |
357 | ssb_dprintk(KERN_INFO PFX "chipcommon status is 0x%x\n", cc->status); | 357 | ssb_dbg("chipcommon status is 0x%x\n", cc->status); |
358 | 358 | ||
359 | if (cc->dev->id.revision >= 20) { | 359 | if (cc->dev->id.revision >= 20) { |
360 | chipco_write32(cc, SSB_CHIPCO_GPIOPULLUP, 0); | 360 | chipco_write32(cc, SSB_CHIPCO_GPIOPULLUP, 0); |
diff --git a/drivers/ssb/driver_chipcommon_pmu.c b/drivers/ssb/driver_chipcommon_pmu.c index 4c0f6d883dd3..791da2c0d8f6 100644 --- a/drivers/ssb/driver_chipcommon_pmu.c +++ b/drivers/ssb/driver_chipcommon_pmu.c | |||
@@ -110,8 +110,8 @@ static void ssb_pmu0_pllinit_r0(struct ssb_chipcommon *cc, | |||
110 | return; | 110 | return; |
111 | } | 111 | } |
112 | 112 | ||
113 | ssb_printk(KERN_INFO PFX "Programming PLL to %u.%03u MHz\n", | 113 | ssb_info("Programming PLL to %u.%03u MHz\n", |
114 | (crystalfreq / 1000), (crystalfreq % 1000)); | 114 | crystalfreq / 1000, crystalfreq % 1000); |
115 | 115 | ||
116 | /* First turn the PLL off. */ | 116 | /* First turn the PLL off. */ |
117 | switch (bus->chip_id) { | 117 | switch (bus->chip_id) { |
@@ -138,7 +138,7 @@ static void ssb_pmu0_pllinit_r0(struct ssb_chipcommon *cc, | |||
138 | } | 138 | } |
139 | tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST); | 139 | tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST); |
140 | if (tmp & SSB_CHIPCO_CLKCTLST_HAVEHT) | 140 | if (tmp & SSB_CHIPCO_CLKCTLST_HAVEHT) |
141 | ssb_printk(KERN_EMERG PFX "Failed to turn the PLL off!\n"); | 141 | ssb_emerg("Failed to turn the PLL off!\n"); |
142 | 142 | ||
143 | /* Set PDIV in PLL control 0. */ | 143 | /* Set PDIV in PLL control 0. */ |
144 | pllctl = ssb_chipco_pll_read(cc, SSB_PMU0_PLLCTL0); | 144 | pllctl = ssb_chipco_pll_read(cc, SSB_PMU0_PLLCTL0); |
@@ -249,8 +249,8 @@ static void ssb_pmu1_pllinit_r0(struct ssb_chipcommon *cc, | |||
249 | return; | 249 | return; |
250 | } | 250 | } |
251 | 251 | ||
252 | ssb_printk(KERN_INFO PFX "Programming PLL to %u.%03u MHz\n", | 252 | ssb_info("Programming PLL to %u.%03u MHz\n", |
253 | (crystalfreq / 1000), (crystalfreq % 1000)); | 253 | crystalfreq / 1000, crystalfreq % 1000); |
254 | 254 | ||
255 | /* First turn the PLL off. */ | 255 | /* First turn the PLL off. */ |
256 | switch (bus->chip_id) { | 256 | switch (bus->chip_id) { |
@@ -275,7 +275,7 @@ static void ssb_pmu1_pllinit_r0(struct ssb_chipcommon *cc, | |||
275 | } | 275 | } |
276 | tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST); | 276 | tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST); |
277 | if (tmp & SSB_CHIPCO_CLKCTLST_HAVEHT) | 277 | if (tmp & SSB_CHIPCO_CLKCTLST_HAVEHT) |
278 | ssb_printk(KERN_EMERG PFX "Failed to turn the PLL off!\n"); | 278 | ssb_emerg("Failed to turn the PLL off!\n"); |
279 | 279 | ||
280 | /* Set p1div and p2div. */ | 280 | /* Set p1div and p2div. */ |
281 | pllctl = ssb_chipco_pll_read(cc, SSB_PMU1_PLLCTL0); | 281 | pllctl = ssb_chipco_pll_read(cc, SSB_PMU1_PLLCTL0); |
@@ -349,9 +349,8 @@ static void ssb_pmu_pll_init(struct ssb_chipcommon *cc) | |||
349 | case 43222: | 349 | case 43222: |
350 | break; | 350 | break; |
351 | default: | 351 | default: |
352 | ssb_printk(KERN_ERR PFX | 352 | ssb_err("ERROR: PLL init unknown for device %04X\n", |
353 | "ERROR: PLL init unknown for device %04X\n", | 353 | bus->chip_id); |
354 | bus->chip_id); | ||
355 | } | 354 | } |
356 | } | 355 | } |
357 | 356 | ||
@@ -472,9 +471,8 @@ static void ssb_pmu_resources_init(struct ssb_chipcommon *cc) | |||
472 | max_msk = 0xFFFFF; | 471 | max_msk = 0xFFFFF; |
473 | break; | 472 | break; |
474 | default: | 473 | default: |
475 | ssb_printk(KERN_ERR PFX | 474 | ssb_err("ERROR: PMU resource config unknown for device %04X\n", |
476 | "ERROR: PMU resource config unknown for device %04X\n", | 475 | bus->chip_id); |
477 | bus->chip_id); | ||
478 | } | 476 | } |
479 | 477 | ||
480 | if (updown_tab) { | 478 | if (updown_tab) { |
@@ -526,8 +524,8 @@ void ssb_pmu_init(struct ssb_chipcommon *cc) | |||
526 | pmucap = chipco_read32(cc, SSB_CHIPCO_PMU_CAP); | 524 | pmucap = chipco_read32(cc, SSB_CHIPCO_PMU_CAP); |
527 | cc->pmu.rev = (pmucap & SSB_CHIPCO_PMU_CAP_REVISION); | 525 | cc->pmu.rev = (pmucap & SSB_CHIPCO_PMU_CAP_REVISION); |
528 | 526 | ||
529 | ssb_dprintk(KERN_DEBUG PFX "Found rev %u PMU (capabilities 0x%08X)\n", | 527 | ssb_dbg("Found rev %u PMU (capabilities 0x%08X)\n", |
530 | cc->pmu.rev, pmucap); | 528 | cc->pmu.rev, pmucap); |
531 | 529 | ||
532 | if (cc->pmu.rev == 1) | 530 | if (cc->pmu.rev == 1) |
533 | chipco_mask32(cc, SSB_CHIPCO_PMU_CTL, | 531 | chipco_mask32(cc, SSB_CHIPCO_PMU_CTL, |
@@ -638,9 +636,8 @@ u32 ssb_pmu_get_alp_clock(struct ssb_chipcommon *cc) | |||
638 | case 0x5354: | 636 | case 0x5354: |
639 | ssb_pmu_get_alp_clock_clk0(cc); | 637 | ssb_pmu_get_alp_clock_clk0(cc); |
640 | default: | 638 | default: |
641 | ssb_printk(KERN_ERR PFX | 639 | ssb_err("ERROR: PMU alp clock unknown for device %04X\n", |
642 | "ERROR: PMU alp clock unknown for device %04X\n", | 640 | bus->chip_id); |
643 | bus->chip_id); | ||
644 | return 0; | 641 | return 0; |
645 | } | 642 | } |
646 | } | 643 | } |
@@ -654,9 +651,8 @@ u32 ssb_pmu_get_cpu_clock(struct ssb_chipcommon *cc) | |||
654 | /* 5354 chip uses a non programmable PLL of frequency 240MHz */ | 651 | /* 5354 chip uses a non programmable PLL of frequency 240MHz */ |
655 | return 240000000; | 652 | return 240000000; |
656 | default: | 653 | default: |
657 | ssb_printk(KERN_ERR PFX | 654 | ssb_err("ERROR: PMU cpu clock unknown for device %04X\n", |
658 | "ERROR: PMU cpu clock unknown for device %04X\n", | 655 | bus->chip_id); |
659 | bus->chip_id); | ||
660 | return 0; | 656 | return 0; |
661 | } | 657 | } |
662 | } | 658 | } |
@@ -669,9 +665,8 @@ u32 ssb_pmu_get_controlclock(struct ssb_chipcommon *cc) | |||
669 | case 0x5354: | 665 | case 0x5354: |
670 | return 120000000; | 666 | return 120000000; |
671 | default: | 667 | default: |
672 | ssb_printk(KERN_ERR PFX | 668 | ssb_err("ERROR: PMU controlclock unknown for device %04X\n", |
673 | "ERROR: PMU controlclock unknown for device %04X\n", | 669 | bus->chip_id); |
674 | bus->chip_id); | ||
675 | return 0; | 670 | return 0; |
676 | } | 671 | } |
677 | } | 672 | } |
diff --git a/drivers/ssb/driver_mipscore.c b/drivers/ssb/driver_mipscore.c index 33b37dac40bd..fa385a368a56 100644 --- a/drivers/ssb/driver_mipscore.c +++ b/drivers/ssb/driver_mipscore.c | |||
@@ -167,21 +167,22 @@ static void set_irq(struct ssb_device *dev, unsigned int irq) | |||
167 | irqflag |= (ipsflag & ~ipsflag_irq_mask[irq]); | 167 | irqflag |= (ipsflag & ~ipsflag_irq_mask[irq]); |
168 | ssb_write32(mdev, SSB_IPSFLAG, irqflag); | 168 | ssb_write32(mdev, SSB_IPSFLAG, irqflag); |
169 | } | 169 | } |
170 | ssb_dprintk(KERN_INFO PFX | 170 | ssb_dbg("set_irq: core 0x%04x, irq %d => %d\n", |
171 | "set_irq: core 0x%04x, irq %d => %d\n", | 171 | dev->id.coreid, oldirq+2, irq+2); |
172 | dev->id.coreid, oldirq+2, irq+2); | ||
173 | } | 172 | } |
174 | 173 | ||
175 | static void print_irq(struct ssb_device *dev, unsigned int irq) | 174 | static void print_irq(struct ssb_device *dev, unsigned int irq) |
176 | { | 175 | { |
177 | int i; | ||
178 | static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"}; | 176 | static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"}; |
179 | ssb_dprintk(KERN_INFO PFX | 177 | ssb_dbg("core 0x%04x, irq : %s%s %s%s %s%s %s%s %s%s %s%s %s%s\n", |
180 | "core 0x%04x, irq :", dev->id.coreid); | 178 | dev->id.coreid, |
181 | for (i = 0; i <= 6; i++) { | 179 | irq_name[0], irq == 0 ? "*" : " ", |
182 | ssb_dprintk(" %s%s", irq_name[i], i==irq?"*":" "); | 180 | irq_name[1], irq == 1 ? "*" : " ", |
183 | } | 181 | irq_name[2], irq == 2 ? "*" : " ", |
184 | ssb_dprintk("\n"); | 182 | irq_name[3], irq == 3 ? "*" : " ", |
183 | irq_name[4], irq == 4 ? "*" : " ", | ||
184 | irq_name[5], irq == 5 ? "*" : " ", | ||
185 | irq_name[6], irq == 6 ? "*" : " "); | ||
185 | } | 186 | } |
186 | 187 | ||
187 | static void dump_irq(struct ssb_bus *bus) | 188 | static void dump_irq(struct ssb_bus *bus) |
@@ -286,7 +287,7 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore) | |||
286 | if (!mcore->dev) | 287 | if (!mcore->dev) |
287 | return; /* We don't have a MIPS core */ | 288 | return; /* We don't have a MIPS core */ |
288 | 289 | ||
289 | ssb_dprintk(KERN_INFO PFX "Initializing MIPS core...\n"); | 290 | ssb_dbg("Initializing MIPS core...\n"); |
290 | 291 | ||
291 | bus = mcore->dev->bus; | 292 | bus = mcore->dev->bus; |
292 | hz = ssb_clockspeed(bus); | 293 | hz = ssb_clockspeed(bus); |
@@ -334,7 +335,7 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore) | |||
334 | break; | 335 | break; |
335 | } | 336 | } |
336 | } | 337 | } |
337 | ssb_dprintk(KERN_INFO PFX "after irq reconfiguration\n"); | 338 | ssb_dbg("after irq reconfiguration\n"); |
338 | dump_irq(bus); | 339 | dump_irq(bus); |
339 | 340 | ||
340 | ssb_mips_serial_init(mcore); | 341 | ssb_mips_serial_init(mcore); |
diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c index 59801d23d7ec..d75b72ba2672 100644 --- a/drivers/ssb/driver_pcicore.c +++ b/drivers/ssb/driver_pcicore.c | |||
@@ -263,8 +263,7 @@ int ssb_pcicore_plat_dev_init(struct pci_dev *d) | |||
263 | return -ENODEV; | 263 | return -ENODEV; |
264 | } | 264 | } |
265 | 265 | ||
266 | ssb_printk(KERN_INFO "PCI: Fixing up device %s\n", | 266 | ssb_info("PCI: Fixing up device %s\n", pci_name(d)); |
267 | pci_name(d)); | ||
268 | 267 | ||
269 | /* Fix up interrupt lines */ | 268 | /* Fix up interrupt lines */ |
270 | d->irq = ssb_mips_irq(extpci_core->dev) + 2; | 269 | d->irq = ssb_mips_irq(extpci_core->dev) + 2; |
@@ -285,12 +284,12 @@ static void ssb_pcicore_fixup_pcibridge(struct pci_dev *dev) | |||
285 | if (dev->bus->number != 0 || PCI_SLOT(dev->devfn) != 0) | 284 | if (dev->bus->number != 0 || PCI_SLOT(dev->devfn) != 0) |
286 | return; | 285 | return; |
287 | 286 | ||
288 | ssb_printk(KERN_INFO "PCI: Fixing up bridge %s\n", pci_name(dev)); | 287 | ssb_info("PCI: Fixing up bridge %s\n", pci_name(dev)); |
289 | 288 | ||
290 | /* Enable PCI bridge bus mastering and memory space */ | 289 | /* Enable PCI bridge bus mastering and memory space */ |
291 | pci_set_master(dev); | 290 | pci_set_master(dev); |
292 | if (pcibios_enable_device(dev, ~0) < 0) { | 291 | if (pcibios_enable_device(dev, ~0) < 0) { |
293 | ssb_printk(KERN_ERR "PCI: SSB bridge enable failed\n"); | 292 | ssb_err("PCI: SSB bridge enable failed\n"); |
294 | return; | 293 | return; |
295 | } | 294 | } |
296 | 295 | ||
@@ -299,8 +298,8 @@ static void ssb_pcicore_fixup_pcibridge(struct pci_dev *dev) | |||
299 | 298 | ||
300 | /* Make sure our latency is high enough to handle the devices behind us */ | 299 | /* Make sure our latency is high enough to handle the devices behind us */ |
301 | lat = 168; | 300 | lat = 168; |
302 | ssb_printk(KERN_INFO "PCI: Fixing latency timer of device %s to %u\n", | 301 | ssb_info("PCI: Fixing latency timer of device %s to %u\n", |
303 | pci_name(dev), lat); | 302 | pci_name(dev), lat); |
304 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); | 303 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); |
305 | } | 304 | } |
306 | DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, ssb_pcicore_fixup_pcibridge); | 305 | DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, ssb_pcicore_fixup_pcibridge); |
@@ -323,7 +322,7 @@ static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc) | |||
323 | return; | 322 | return; |
324 | extpci_core = pc; | 323 | extpci_core = pc; |
325 | 324 | ||
326 | ssb_dprintk(KERN_INFO PFX "PCIcore in host mode found\n"); | 325 | ssb_dbg("PCIcore in host mode found\n"); |
327 | /* Reset devices on the external PCI bus */ | 326 | /* Reset devices on the external PCI bus */ |
328 | val = SSB_PCICORE_CTL_RST_OE; | 327 | val = SSB_PCICORE_CTL_RST_OE; |
329 | val |= SSB_PCICORE_CTL_CLK_OE; | 328 | val |= SSB_PCICORE_CTL_CLK_OE; |
@@ -338,7 +337,7 @@ static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc) | |||
338 | udelay(1); /* Assertion time demanded by the PCI standard */ | 337 | udelay(1); /* Assertion time demanded by the PCI standard */ |
339 | 338 | ||
340 | if (pc->dev->bus->has_cardbus_slot) { | 339 | if (pc->dev->bus->has_cardbus_slot) { |
341 | ssb_dprintk(KERN_INFO PFX "CardBus slot detected\n"); | 340 | ssb_dbg("CardBus slot detected\n"); |
342 | pc->cardbusmode = 1; | 341 | pc->cardbusmode = 1; |
343 | /* GPIO 1 resets the bridge */ | 342 | /* GPIO 1 resets the bridge */ |
344 | ssb_gpio_out(pc->dev->bus, 1, 1); | 343 | ssb_gpio_out(pc->dev->bus, 1, 1); |
diff --git a/drivers/ssb/embedded.c b/drivers/ssb/embedded.c index bb18d76f9f2c..55e101115038 100644 --- a/drivers/ssb/embedded.c +++ b/drivers/ssb/embedded.c | |||
@@ -57,9 +57,8 @@ int ssb_watchdog_register(struct ssb_bus *bus) | |||
57 | bus->busnumber, &wdt, | 57 | bus->busnumber, &wdt, |
58 | sizeof(wdt)); | 58 | sizeof(wdt)); |
59 | if (IS_ERR(pdev)) { | 59 | if (IS_ERR(pdev)) { |
60 | ssb_dprintk(KERN_INFO PFX | 60 | ssb_dbg("can not register watchdog device, err: %li\n", |
61 | "can not register watchdog device, err: %li\n", | 61 | PTR_ERR(pdev)); |
62 | PTR_ERR(pdev)); | ||
63 | return PTR_ERR(pdev); | 62 | return PTR_ERR(pdev); |
64 | } | 63 | } |
65 | 64 | ||
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index 3b645b8a261f..812775a4bfb6 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c | |||
@@ -275,8 +275,8 @@ int ssb_devices_thaw(struct ssb_freeze_context *ctx) | |||
275 | 275 | ||
276 | err = sdrv->probe(sdev, &sdev->id); | 276 | err = sdrv->probe(sdev, &sdev->id); |
277 | if (err) { | 277 | if (err) { |
278 | ssb_printk(KERN_ERR PFX "Failed to thaw device %s\n", | 278 | ssb_err("Failed to thaw device %s\n", |
279 | dev_name(sdev->dev)); | 279 | dev_name(sdev->dev)); |
280 | result = err; | 280 | result = err; |
281 | } | 281 | } |
282 | ssb_device_put(sdev); | 282 | ssb_device_put(sdev); |
@@ -447,10 +447,9 @@ void ssb_bus_unregister(struct ssb_bus *bus) | |||
447 | 447 | ||
448 | err = ssb_gpio_unregister(bus); | 448 | err = ssb_gpio_unregister(bus); |
449 | if (err == -EBUSY) | 449 | if (err == -EBUSY) |
450 | ssb_dprintk(KERN_ERR PFX "Some GPIOs are still in use.\n"); | 450 | ssb_dbg("Some GPIOs are still in use\n"); |
451 | else if (err) | 451 | else if (err) |
452 | ssb_dprintk(KERN_ERR PFX | 452 | ssb_dbg("Can not unregister GPIO driver: %i\n", err); |
453 | "Can not unregister GPIO driver: %i\n", err); | ||
454 | 453 | ||
455 | ssb_buses_lock(); | 454 | ssb_buses_lock(); |
456 | ssb_devices_unregister(bus); | 455 | ssb_devices_unregister(bus); |
@@ -497,8 +496,7 @@ static int ssb_devices_register(struct ssb_bus *bus) | |||
497 | 496 | ||
498 | devwrap = kzalloc(sizeof(*devwrap), GFP_KERNEL); | 497 | devwrap = kzalloc(sizeof(*devwrap), GFP_KERNEL); |
499 | if (!devwrap) { | 498 | if (!devwrap) { |
500 | ssb_printk(KERN_ERR PFX | 499 | ssb_err("Could not allocate device\n"); |
501 | "Could not allocate device\n"); | ||
502 | err = -ENOMEM; | 500 | err = -ENOMEM; |
503 | goto error; | 501 | goto error; |
504 | } | 502 | } |
@@ -537,9 +535,7 @@ static int ssb_devices_register(struct ssb_bus *bus) | |||
537 | sdev->dev = dev; | 535 | sdev->dev = dev; |
538 | err = device_register(dev); | 536 | err = device_register(dev); |
539 | if (err) { | 537 | if (err) { |
540 | ssb_printk(KERN_ERR PFX | 538 | ssb_err("Could not register %s\n", dev_name(dev)); |
541 | "Could not register %s\n", | ||
542 | dev_name(dev)); | ||
543 | /* Set dev to NULL to not unregister | 539 | /* Set dev to NULL to not unregister |
544 | * dev on error unwinding. */ | 540 | * dev on error unwinding. */ |
545 | sdev->dev = NULL; | 541 | sdev->dev = NULL; |
@@ -825,10 +821,9 @@ static int ssb_bus_register(struct ssb_bus *bus, | |||
825 | ssb_mipscore_init(&bus->mipscore); | 821 | ssb_mipscore_init(&bus->mipscore); |
826 | err = ssb_gpio_init(bus); | 822 | err = ssb_gpio_init(bus); |
827 | if (err == -ENOTSUPP) | 823 | if (err == -ENOTSUPP) |
828 | ssb_dprintk(KERN_DEBUG PFX "GPIO driver not activated\n"); | 824 | ssb_dbg("GPIO driver not activated\n"); |
829 | else if (err) | 825 | else if (err) |
830 | ssb_dprintk(KERN_ERR PFX | 826 | ssb_dbg("Error registering GPIO driver: %i\n", err); |
831 | "Error registering GPIO driver: %i\n", err); | ||
832 | err = ssb_fetch_invariants(bus, get_invariants); | 827 | err = ssb_fetch_invariants(bus, get_invariants); |
833 | if (err) { | 828 | if (err) { |
834 | ssb_bus_may_powerdown(bus); | 829 | ssb_bus_may_powerdown(bus); |
@@ -878,11 +873,11 @@ int ssb_bus_pcibus_register(struct ssb_bus *bus, struct pci_dev *host_pci) | |||
878 | 873 | ||
879 | err = ssb_bus_register(bus, ssb_pci_get_invariants, 0); | 874 | err = ssb_bus_register(bus, ssb_pci_get_invariants, 0); |
880 | if (!err) { | 875 | if (!err) { |
881 | ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane found on " | 876 | ssb_info("Sonics Silicon Backplane found on PCI device %s\n", |
882 | "PCI device %s\n", dev_name(&host_pci->dev)); | 877 | dev_name(&host_pci->dev)); |
883 | } else { | 878 | } else { |
884 | ssb_printk(KERN_ERR PFX "Failed to register PCI version" | 879 | ssb_err("Failed to register PCI version of SSB with error %d\n", |
885 | " of SSB with error %d\n", err); | 880 | err); |
886 | } | 881 | } |
887 | 882 | ||
888 | return err; | 883 | return err; |
@@ -903,8 +898,8 @@ int ssb_bus_pcmciabus_register(struct ssb_bus *bus, | |||
903 | 898 | ||
904 | err = ssb_bus_register(bus, ssb_pcmcia_get_invariants, baseaddr); | 899 | err = ssb_bus_register(bus, ssb_pcmcia_get_invariants, baseaddr); |
905 | if (!err) { | 900 | if (!err) { |
906 | ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane found on " | 901 | ssb_info("Sonics Silicon Backplane found on PCMCIA device %s\n", |
907 | "PCMCIA device %s\n", pcmcia_dev->devname); | 902 | pcmcia_dev->devname); |
908 | } | 903 | } |
909 | 904 | ||
910 | return err; | 905 | return err; |
@@ -925,8 +920,8 @@ int ssb_bus_sdiobus_register(struct ssb_bus *bus, struct sdio_func *func, | |||
925 | 920 | ||
926 | err = ssb_bus_register(bus, ssb_sdio_get_invariants, ~0); | 921 | err = ssb_bus_register(bus, ssb_sdio_get_invariants, ~0); |
927 | if (!err) { | 922 | if (!err) { |
928 | ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane found on " | 923 | ssb_info("Sonics Silicon Backplane found on SDIO device %s\n", |
929 | "SDIO device %s\n", sdio_func_id(func)); | 924 | sdio_func_id(func)); |
930 | } | 925 | } |
931 | 926 | ||
932 | return err; | 927 | return err; |
@@ -944,8 +939,8 @@ int ssb_bus_ssbbus_register(struct ssb_bus *bus, unsigned long baseaddr, | |||
944 | 939 | ||
945 | err = ssb_bus_register(bus, get_invariants, baseaddr); | 940 | err = ssb_bus_register(bus, get_invariants, baseaddr); |
946 | if (!err) { | 941 | if (!err) { |
947 | ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane found at " | 942 | ssb_info("Sonics Silicon Backplane found at address 0x%08lX\n", |
948 | "address 0x%08lX\n", baseaddr); | 943 | baseaddr); |
949 | } | 944 | } |
950 | 945 | ||
951 | return err; | 946 | return err; |
@@ -1339,7 +1334,7 @@ out: | |||
1339 | #endif | 1334 | #endif |
1340 | return err; | 1335 | return err; |
1341 | error: | 1336 | error: |
1342 | ssb_printk(KERN_ERR PFX "Bus powerdown failed\n"); | 1337 | ssb_err("Bus powerdown failed\n"); |
1343 | goto out; | 1338 | goto out; |
1344 | } | 1339 | } |
1345 | EXPORT_SYMBOL(ssb_bus_may_powerdown); | 1340 | EXPORT_SYMBOL(ssb_bus_may_powerdown); |
@@ -1362,7 +1357,7 @@ int ssb_bus_powerup(struct ssb_bus *bus, bool dynamic_pctl) | |||
1362 | 1357 | ||
1363 | return 0; | 1358 | return 0; |
1364 | error: | 1359 | error: |
1365 | ssb_printk(KERN_ERR PFX "Bus powerup failed\n"); | 1360 | ssb_err("Bus powerup failed\n"); |
1366 | return err; | 1361 | return err; |
1367 | } | 1362 | } |
1368 | EXPORT_SYMBOL(ssb_bus_powerup); | 1363 | EXPORT_SYMBOL(ssb_bus_powerup); |
@@ -1470,15 +1465,13 @@ static int __init ssb_modinit(void) | |||
1470 | 1465 | ||
1471 | err = b43_pci_ssb_bridge_init(); | 1466 | err = b43_pci_ssb_bridge_init(); |
1472 | if (err) { | 1467 | if (err) { |
1473 | ssb_printk(KERN_ERR "Broadcom 43xx PCI-SSB-bridge " | 1468 | ssb_err("Broadcom 43xx PCI-SSB-bridge initialization failed\n"); |
1474 | "initialization failed\n"); | ||
1475 | /* don't fail SSB init because of this */ | 1469 | /* don't fail SSB init because of this */ |
1476 | err = 0; | 1470 | err = 0; |
1477 | } | 1471 | } |
1478 | err = ssb_gige_init(); | 1472 | err = ssb_gige_init(); |
1479 | if (err) { | 1473 | if (err) { |
1480 | ssb_printk(KERN_ERR "SSB Broadcom Gigabit Ethernet " | 1474 | ssb_err("SSB Broadcom Gigabit Ethernet driver initialization failed\n"); |
1481 | "driver initialization failed\n"); | ||
1482 | /* don't fail SSB init because of this */ | 1475 | /* don't fail SSB init because of this */ |
1483 | err = 0; | 1476 | err = 0; |
1484 | } | 1477 | } |
diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c index e9d94968f394..63ff69f9d3eb 100644 --- a/drivers/ssb/pci.c +++ b/drivers/ssb/pci.c | |||
@@ -56,7 +56,7 @@ int ssb_pci_switch_coreidx(struct ssb_bus *bus, u8 coreidx) | |||
56 | } | 56 | } |
57 | return 0; | 57 | return 0; |
58 | error: | 58 | error: |
59 | ssb_printk(KERN_ERR PFX "Failed to switch to core %u\n", coreidx); | 59 | ssb_err("Failed to switch to core %u\n", coreidx); |
60 | return -ENODEV; | 60 | return -ENODEV; |
61 | } | 61 | } |
62 | 62 | ||
@@ -67,10 +67,9 @@ int ssb_pci_switch_core(struct ssb_bus *bus, | |||
67 | unsigned long flags; | 67 | unsigned long flags; |
68 | 68 | ||
69 | #if SSB_VERBOSE_PCICORESWITCH_DEBUG | 69 | #if SSB_VERBOSE_PCICORESWITCH_DEBUG |
70 | ssb_printk(KERN_INFO PFX | 70 | ssb_info("Switching to %s core, index %d\n", |
71 | "Switching to %s core, index %d\n", | 71 | ssb_core_name(dev->id.coreid), |
72 | ssb_core_name(dev->id.coreid), | 72 | dev->core_index); |
73 | dev->core_index); | ||
74 | #endif | 73 | #endif |
75 | 74 | ||
76 | spin_lock_irqsave(&bus->bar_lock, flags); | 75 | spin_lock_irqsave(&bus->bar_lock, flags); |
@@ -231,6 +230,15 @@ static inline u8 ssb_crc8(u8 crc, u8 data) | |||
231 | return t[crc ^ data]; | 230 | return t[crc ^ data]; |
232 | } | 231 | } |
233 | 232 | ||
233 | static void sprom_get_mac(char *mac, const u16 *in) | ||
234 | { | ||
235 | int i; | ||
236 | for (i = 0; i < 3; i++) { | ||
237 | *mac++ = in[i] >> 8; | ||
238 | *mac++ = in[i]; | ||
239 | } | ||
240 | } | ||
241 | |||
234 | static u8 ssb_sprom_crc(const u16 *sprom, u16 size) | 242 | static u8 ssb_sprom_crc(const u16 *sprom, u16 size) |
235 | { | 243 | { |
236 | int word; | 244 | int word; |
@@ -278,7 +286,7 @@ static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom) | |||
278 | u32 spromctl; | 286 | u32 spromctl; |
279 | u16 size = bus->sprom_size; | 287 | u16 size = bus->sprom_size; |
280 | 288 | ||
281 | ssb_printk(KERN_NOTICE PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n"); | 289 | ssb_notice("Writing SPROM. Do NOT turn off the power! Please stand by...\n"); |
282 | err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl); | 290 | err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl); |
283 | if (err) | 291 | if (err) |
284 | goto err_ctlreg; | 292 | goto err_ctlreg; |
@@ -286,17 +294,17 @@ static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom) | |||
286 | err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl); | 294 | err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl); |
287 | if (err) | 295 | if (err) |
288 | goto err_ctlreg; | 296 | goto err_ctlreg; |
289 | ssb_printk(KERN_NOTICE PFX "[ 0%%"); | 297 | ssb_notice("[ 0%%"); |
290 | msleep(500); | 298 | msleep(500); |
291 | for (i = 0; i < size; i++) { | 299 | for (i = 0; i < size; i++) { |
292 | if (i == size / 4) | 300 | if (i == size / 4) |
293 | ssb_printk("25%%"); | 301 | ssb_cont("25%%"); |
294 | else if (i == size / 2) | 302 | else if (i == size / 2) |
295 | ssb_printk("50%%"); | 303 | ssb_cont("50%%"); |
296 | else if (i == (size * 3) / 4) | 304 | else if (i == (size * 3) / 4) |
297 | ssb_printk("75%%"); | 305 | ssb_cont("75%%"); |
298 | else if (i % 2) | 306 | else if (i % 2) |
299 | ssb_printk("."); | 307 | ssb_cont("."); |
300 | writew(sprom[i], bus->mmio + bus->sprom_offset + (i * 2)); | 308 | writew(sprom[i], bus->mmio + bus->sprom_offset + (i * 2)); |
301 | mmiowb(); | 309 | mmiowb(); |
302 | msleep(20); | 310 | msleep(20); |
@@ -309,12 +317,12 @@ static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom) | |||
309 | if (err) | 317 | if (err) |
310 | goto err_ctlreg; | 318 | goto err_ctlreg; |
311 | msleep(500); | 319 | msleep(500); |
312 | ssb_printk("100%% ]\n"); | 320 | ssb_cont("100%% ]\n"); |
313 | ssb_printk(KERN_NOTICE PFX "SPROM written.\n"); | 321 | ssb_notice("SPROM written\n"); |
314 | 322 | ||
315 | return 0; | 323 | return 0; |
316 | err_ctlreg: | 324 | err_ctlreg: |
317 | ssb_printk(KERN_ERR PFX "Could not access SPROM control register.\n"); | 325 | ssb_err("Could not access SPROM control register.\n"); |
318 | return err; | 326 | return err; |
319 | } | 327 | } |
320 | 328 | ||
@@ -341,8 +349,6 @@ static s8 r123_extract_antgain(u8 sprom_revision, const u16 *in, | |||
341 | 349 | ||
342 | static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) | 350 | static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) |
343 | { | 351 | { |
344 | int i; | ||
345 | u16 v; | ||
346 | u16 loc[3]; | 352 | u16 loc[3]; |
347 | 353 | ||
348 | if (out->revision == 3) /* rev 3 moved MAC */ | 354 | if (out->revision == 3) /* rev 3 moved MAC */ |
@@ -352,19 +358,10 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) | |||
352 | loc[1] = SSB_SPROM1_ET0MAC; | 358 | loc[1] = SSB_SPROM1_ET0MAC; |
353 | loc[2] = SSB_SPROM1_ET1MAC; | 359 | loc[2] = SSB_SPROM1_ET1MAC; |
354 | } | 360 | } |
355 | for (i = 0; i < 3; i++) { | 361 | sprom_get_mac(out->il0mac, &in[SPOFF(loc[0])]); |
356 | v = in[SPOFF(loc[0]) + i]; | ||
357 | *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v); | ||
358 | } | ||
359 | if (out->revision < 3) { /* only rev 1-2 have et0, et1 */ | 362 | if (out->revision < 3) { /* only rev 1-2 have et0, et1 */ |
360 | for (i = 0; i < 3; i++) { | 363 | sprom_get_mac(out->et0mac, &in[SPOFF(loc[1])]); |
361 | v = in[SPOFF(loc[1]) + i]; | 364 | sprom_get_mac(out->et1mac, &in[SPOFF(loc[2])]); |
362 | *(((__be16 *)out->et0mac) + i) = cpu_to_be16(v); | ||
363 | } | ||
364 | for (i = 0; i < 3; i++) { | ||
365 | v = in[SPOFF(loc[2]) + i]; | ||
366 | *(((__be16 *)out->et1mac) + i) = cpu_to_be16(v); | ||
367 | } | ||
368 | } | 365 | } |
369 | SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0); | 366 | SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0); |
370 | SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A, | 367 | SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A, |
@@ -454,19 +451,15 @@ static void sprom_extract_r458(struct ssb_sprom *out, const u16 *in) | |||
454 | 451 | ||
455 | static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in) | 452 | static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in) |
456 | { | 453 | { |
457 | int i; | ||
458 | u16 v; | ||
459 | u16 il0mac_offset; | 454 | u16 il0mac_offset; |
460 | 455 | ||
461 | if (out->revision == 4) | 456 | if (out->revision == 4) |
462 | il0mac_offset = SSB_SPROM4_IL0MAC; | 457 | il0mac_offset = SSB_SPROM4_IL0MAC; |
463 | else | 458 | else |
464 | il0mac_offset = SSB_SPROM5_IL0MAC; | 459 | il0mac_offset = SSB_SPROM5_IL0MAC; |
465 | /* extract the MAC address */ | 460 | |
466 | for (i = 0; i < 3; i++) { | 461 | sprom_get_mac(out->il0mac, &in[SPOFF(il0mac_offset)]); |
467 | v = in[SPOFF(il0mac_offset) + i]; | 462 | |
468 | *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v); | ||
469 | } | ||
470 | SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0); | 463 | SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0); |
471 | SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A, | 464 | SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A, |
472 | SSB_SPROM4_ETHPHY_ET1A_SHIFT); | 465 | SSB_SPROM4_ETHPHY_ET1A_SHIFT); |
@@ -530,7 +523,7 @@ static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in) | |||
530 | static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in) | 523 | static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in) |
531 | { | 524 | { |
532 | int i; | 525 | int i; |
533 | u16 v, o; | 526 | u16 o; |
534 | u16 pwr_info_offset[] = { | 527 | u16 pwr_info_offset[] = { |
535 | SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1, | 528 | SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1, |
536 | SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3 | 529 | SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3 |
@@ -539,10 +532,8 @@ static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in) | |||
539 | ARRAY_SIZE(out->core_pwr_info)); | 532 | ARRAY_SIZE(out->core_pwr_info)); |
540 | 533 | ||
541 | /* extract the MAC address */ | 534 | /* extract the MAC address */ |
542 | for (i = 0; i < 3; i++) { | 535 | sprom_get_mac(out->il0mac, &in[SPOFF(SSB_SPROM8_IL0MAC)]); |
543 | v = in[SPOFF(SSB_SPROM8_IL0MAC) + i]; | 536 | |
544 | *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v); | ||
545 | } | ||
546 | SPEX(board_rev, SSB_SPROM8_BOARDREV, 0xFFFF, 0); | 537 | SPEX(board_rev, SSB_SPROM8_BOARDREV, 0xFFFF, 0); |
547 | SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8); | 538 | SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8); |
548 | SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0); | 539 | SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0); |
@@ -743,7 +734,7 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out, | |||
743 | memset(out, 0, sizeof(*out)); | 734 | memset(out, 0, sizeof(*out)); |
744 | 735 | ||
745 | out->revision = in[size - 1] & 0x00FF; | 736 | out->revision = in[size - 1] & 0x00FF; |
746 | ssb_dprintk(KERN_DEBUG PFX "SPROM revision %d detected.\n", out->revision); | 737 | ssb_dbg("SPROM revision %d detected\n", out->revision); |
747 | memset(out->et0mac, 0xFF, 6); /* preset et0 and et1 mac */ | 738 | memset(out->et0mac, 0xFF, 6); /* preset et0 and et1 mac */ |
748 | memset(out->et1mac, 0xFF, 6); | 739 | memset(out->et1mac, 0xFF, 6); |
749 | 740 | ||
@@ -752,7 +743,7 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out, | |||
752 | * number stored in the SPROM. | 743 | * number stored in the SPROM. |
753 | * Always extract r1. */ | 744 | * Always extract r1. */ |
754 | out->revision = 1; | 745 | out->revision = 1; |
755 | ssb_dprintk(KERN_DEBUG PFX "SPROM treated as revision %d\n", out->revision); | 746 | ssb_dbg("SPROM treated as revision %d\n", out->revision); |
756 | } | 747 | } |
757 | 748 | ||
758 | switch (out->revision) { | 749 | switch (out->revision) { |
@@ -769,9 +760,8 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out, | |||
769 | sprom_extract_r8(out, in); | 760 | sprom_extract_r8(out, in); |
770 | break; | 761 | break; |
771 | default: | 762 | default: |
772 | ssb_printk(KERN_WARNING PFX "Unsupported SPROM" | 763 | ssb_warn("Unsupported SPROM revision %d detected. Will extract v1\n", |
773 | " revision %d detected. Will extract" | 764 | out->revision); |
774 | " v1\n", out->revision); | ||
775 | out->revision = 1; | 765 | out->revision = 1; |
776 | sprom_extract_r123(out, in); | 766 | sprom_extract_r123(out, in); |
777 | } | 767 | } |
@@ -791,7 +781,7 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus, | |||
791 | u16 *buf; | 781 | u16 *buf; |
792 | 782 | ||
793 | if (!ssb_is_sprom_available(bus)) { | 783 | if (!ssb_is_sprom_available(bus)) { |
794 | ssb_printk(KERN_ERR PFX "No SPROM available!\n"); | 784 | ssb_err("No SPROM available!\n"); |
795 | return -ENODEV; | 785 | return -ENODEV; |
796 | } | 786 | } |
797 | if (bus->chipco.dev) { /* can be unavailable! */ | 787 | if (bus->chipco.dev) { /* can be unavailable! */ |
@@ -810,7 +800,7 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus, | |||
810 | } else { | 800 | } else { |
811 | bus->sprom_offset = SSB_SPROM_BASE1; | 801 | bus->sprom_offset = SSB_SPROM_BASE1; |
812 | } | 802 | } |
813 | ssb_dprintk(KERN_INFO PFX "SPROM offset is 0x%x\n", bus->sprom_offset); | 803 | ssb_dbg("SPROM offset is 0x%x\n", bus->sprom_offset); |
814 | 804 | ||
815 | buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL); | 805 | buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL); |
816 | if (!buf) | 806 | if (!buf) |
@@ -835,18 +825,15 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus, | |||
835 | * available for this device in some other storage */ | 825 | * available for this device in some other storage */ |
836 | err = ssb_fill_sprom_with_fallback(bus, sprom); | 826 | err = ssb_fill_sprom_with_fallback(bus, sprom); |
837 | if (err) { | 827 | if (err) { |
838 | ssb_printk(KERN_WARNING PFX "WARNING: Using" | 828 | ssb_warn("WARNING: Using fallback SPROM failed (err %d)\n", |
839 | " fallback SPROM failed (err %d)\n", | 829 | err); |
840 | err); | ||
841 | } else { | 830 | } else { |
842 | ssb_dprintk(KERN_DEBUG PFX "Using SPROM" | 831 | ssb_dbg("Using SPROM revision %d provided by platform\n", |
843 | " revision %d provided by" | 832 | sprom->revision); |
844 | " platform.\n", sprom->revision); | ||
845 | err = 0; | 833 | err = 0; |
846 | goto out_free; | 834 | goto out_free; |
847 | } | 835 | } |
848 | ssb_printk(KERN_WARNING PFX "WARNING: Invalid" | 836 | ssb_warn("WARNING: Invalid SPROM CRC (corrupt SPROM)\n"); |
849 | " SPROM CRC (corrupt SPROM)\n"); | ||
850 | } | 837 | } |
851 | } | 838 | } |
852 | err = sprom_extract(bus, sprom, buf, bus->sprom_size); | 839 | err = sprom_extract(bus, sprom, buf, bus->sprom_size); |
diff --git a/drivers/ssb/pcmcia.c b/drivers/ssb/pcmcia.c index fbafed5b729b..b413e0187087 100644 --- a/drivers/ssb/pcmcia.c +++ b/drivers/ssb/pcmcia.c | |||
@@ -143,7 +143,7 @@ int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus, | |||
143 | 143 | ||
144 | return 0; | 144 | return 0; |
145 | error: | 145 | error: |
146 | ssb_printk(KERN_ERR PFX "Failed to switch to core %u\n", coreidx); | 146 | ssb_err("Failed to switch to core %u\n", coreidx); |
147 | return err; | 147 | return err; |
148 | } | 148 | } |
149 | 149 | ||
@@ -153,10 +153,9 @@ int ssb_pcmcia_switch_core(struct ssb_bus *bus, | |||
153 | int err; | 153 | int err; |
154 | 154 | ||
155 | #if SSB_VERBOSE_PCMCIACORESWITCH_DEBUG | 155 | #if SSB_VERBOSE_PCMCIACORESWITCH_DEBUG |
156 | ssb_printk(KERN_INFO PFX | 156 | ssb_info("Switching to %s core, index %d\n", |
157 | "Switching to %s core, index %d\n", | 157 | ssb_core_name(dev->id.coreid), |
158 | ssb_core_name(dev->id.coreid), | 158 | dev->core_index); |
159 | dev->core_index); | ||
160 | #endif | 159 | #endif |
161 | 160 | ||
162 | err = ssb_pcmcia_switch_coreidx(bus, dev->core_index); | 161 | err = ssb_pcmcia_switch_coreidx(bus, dev->core_index); |
@@ -192,7 +191,7 @@ int ssb_pcmcia_switch_segment(struct ssb_bus *bus, u8 seg) | |||
192 | 191 | ||
193 | return 0; | 192 | return 0; |
194 | error: | 193 | error: |
195 | ssb_printk(KERN_ERR PFX "Failed to switch pcmcia segment\n"); | 194 | ssb_err("Failed to switch pcmcia segment\n"); |
196 | return err; | 195 | return err; |
197 | } | 196 | } |
198 | 197 | ||
@@ -549,44 +548,39 @@ static int ssb_pcmcia_sprom_write_all(struct ssb_bus *bus, const u16 *sprom) | |||
549 | bool failed = 0; | 548 | bool failed = 0; |
550 | size_t size = SSB_PCMCIA_SPROM_SIZE; | 549 | size_t size = SSB_PCMCIA_SPROM_SIZE; |
551 | 550 | ||
552 | ssb_printk(KERN_NOTICE PFX | 551 | ssb_notice("Writing SPROM. Do NOT turn off the power! Please stand by...\n"); |
553 | "Writing SPROM. Do NOT turn off the power! " | ||
554 | "Please stand by...\n"); | ||
555 | err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEEN); | 552 | err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEEN); |
556 | if (err) { | 553 | if (err) { |
557 | ssb_printk(KERN_NOTICE PFX | 554 | ssb_notice("Could not enable SPROM write access\n"); |
558 | "Could not enable SPROM write access.\n"); | ||
559 | return -EBUSY; | 555 | return -EBUSY; |
560 | } | 556 | } |
561 | ssb_printk(KERN_NOTICE PFX "[ 0%%"); | 557 | ssb_notice("[ 0%%"); |
562 | msleep(500); | 558 | msleep(500); |
563 | for (i = 0; i < size; i++) { | 559 | for (i = 0; i < size; i++) { |
564 | if (i == size / 4) | 560 | if (i == size / 4) |
565 | ssb_printk("25%%"); | 561 | ssb_cont("25%%"); |
566 | else if (i == size / 2) | 562 | else if (i == size / 2) |
567 | ssb_printk("50%%"); | 563 | ssb_cont("50%%"); |
568 | else if (i == (size * 3) / 4) | 564 | else if (i == (size * 3) / 4) |
569 | ssb_printk("75%%"); | 565 | ssb_cont("75%%"); |
570 | else if (i % 2) | 566 | else if (i % 2) |
571 | ssb_printk("."); | 567 | ssb_cont("."); |
572 | err = ssb_pcmcia_sprom_write(bus, i, sprom[i]); | 568 | err = ssb_pcmcia_sprom_write(bus, i, sprom[i]); |
573 | if (err) { | 569 | if (err) { |
574 | ssb_printk(KERN_NOTICE PFX | 570 | ssb_notice("Failed to write to SPROM\n"); |
575 | "Failed to write to SPROM.\n"); | ||
576 | failed = 1; | 571 | failed = 1; |
577 | break; | 572 | break; |
578 | } | 573 | } |
579 | } | 574 | } |
580 | err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEDIS); | 575 | err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEDIS); |
581 | if (err) { | 576 | if (err) { |
582 | ssb_printk(KERN_NOTICE PFX | 577 | ssb_notice("Could not disable SPROM write access\n"); |
583 | "Could not disable SPROM write access.\n"); | ||
584 | failed = 1; | 578 | failed = 1; |
585 | } | 579 | } |
586 | msleep(500); | 580 | msleep(500); |
587 | if (!failed) { | 581 | if (!failed) { |
588 | ssb_printk("100%% ]\n"); | 582 | ssb_cont("100%% ]\n"); |
589 | ssb_printk(KERN_NOTICE PFX "SPROM written.\n"); | 583 | ssb_notice("SPROM written\n"); |
590 | } | 584 | } |
591 | 585 | ||
592 | return failed ? -EBUSY : 0; | 586 | return failed ? -EBUSY : 0; |
@@ -700,7 +694,7 @@ static int ssb_pcmcia_do_get_invariants(struct pcmcia_device *p_dev, | |||
700 | return -ENOSPC; /* continue with next entry */ | 694 | return -ENOSPC; /* continue with next entry */ |
701 | 695 | ||
702 | error: | 696 | error: |
703 | ssb_printk(KERN_ERR PFX | 697 | ssb_err( |
704 | "PCMCIA: Failed to fetch device invariants: %s\n", | 698 | "PCMCIA: Failed to fetch device invariants: %s\n", |
705 | error_description); | 699 | error_description); |
706 | return -ENODEV; | 700 | return -ENODEV; |
@@ -722,7 +716,7 @@ int ssb_pcmcia_get_invariants(struct ssb_bus *bus, | |||
722 | res = pcmcia_loop_tuple(bus->host_pcmcia, CISTPL_FUNCE, | 716 | res = pcmcia_loop_tuple(bus->host_pcmcia, CISTPL_FUNCE, |
723 | ssb_pcmcia_get_mac, sprom); | 717 | ssb_pcmcia_get_mac, sprom); |
724 | if (res != 0) { | 718 | if (res != 0) { |
725 | ssb_printk(KERN_ERR PFX | 719 | ssb_err( |
726 | "PCMCIA: Failed to fetch MAC address\n"); | 720 | "PCMCIA: Failed to fetch MAC address\n"); |
727 | return -ENODEV; | 721 | return -ENODEV; |
728 | } | 722 | } |
@@ -733,7 +727,7 @@ int ssb_pcmcia_get_invariants(struct ssb_bus *bus, | |||
733 | if ((res == 0) || (res == -ENOSPC)) | 727 | if ((res == 0) || (res == -ENOSPC)) |
734 | return 0; | 728 | return 0; |
735 | 729 | ||
736 | ssb_printk(KERN_ERR PFX | 730 | ssb_err( |
737 | "PCMCIA: Failed to fetch device invariants\n"); | 731 | "PCMCIA: Failed to fetch device invariants\n"); |
738 | return -ENODEV; | 732 | return -ENODEV; |
739 | } | 733 | } |
@@ -843,6 +837,6 @@ int ssb_pcmcia_init(struct ssb_bus *bus) | |||
843 | 837 | ||
844 | return 0; | 838 | return 0; |
845 | error: | 839 | error: |
846 | ssb_printk(KERN_ERR PFX "Failed to initialize PCMCIA host device\n"); | 840 | ssb_err("Failed to initialize PCMCIA host device\n"); |
847 | return err; | 841 | return err; |
848 | } | 842 | } |
diff --git a/drivers/ssb/scan.c b/drivers/ssb/scan.c index ab4627cf1114..b9429df583eb 100644 --- a/drivers/ssb/scan.c +++ b/drivers/ssb/scan.c | |||
@@ -125,8 +125,7 @@ static u16 pcidev_to_chipid(struct pci_dev *pci_dev) | |||
125 | chipid_fallback = 0x4401; | 125 | chipid_fallback = 0x4401; |
126 | break; | 126 | break; |
127 | default: | 127 | default: |
128 | ssb_printk(KERN_ERR PFX | 128 | ssb_err("PCI-ID not in fallback list\n"); |
129 | "PCI-ID not in fallback list\n"); | ||
130 | } | 129 | } |
131 | 130 | ||
132 | return chipid_fallback; | 131 | return chipid_fallback; |
@@ -152,8 +151,7 @@ static u8 chipid_to_nrcores(u16 chipid) | |||
152 | case 0x4704: | 151 | case 0x4704: |
153 | return 9; | 152 | return 9; |
154 | default: | 153 | default: |
155 | ssb_printk(KERN_ERR PFX | 154 | ssb_err("CHIPID not in nrcores fallback list\n"); |
156 | "CHIPID not in nrcores fallback list\n"); | ||
157 | } | 155 | } |
158 | 156 | ||
159 | return 1; | 157 | return 1; |
@@ -320,15 +318,13 @@ int ssb_bus_scan(struct ssb_bus *bus, | |||
320 | bus->chip_package = 0; | 318 | bus->chip_package = 0; |
321 | } | 319 | } |
322 | } | 320 | } |
323 | ssb_printk(KERN_INFO PFX "Found chip with id 0x%04X, rev 0x%02X and " | 321 | ssb_info("Found chip with id 0x%04X, rev 0x%02X and package 0x%02X\n", |
324 | "package 0x%02X\n", bus->chip_id, bus->chip_rev, | 322 | bus->chip_id, bus->chip_rev, bus->chip_package); |
325 | bus->chip_package); | ||
326 | if (!bus->nr_devices) | 323 | if (!bus->nr_devices) |
327 | bus->nr_devices = chipid_to_nrcores(bus->chip_id); | 324 | bus->nr_devices = chipid_to_nrcores(bus->chip_id); |
328 | if (bus->nr_devices > ARRAY_SIZE(bus->devices)) { | 325 | if (bus->nr_devices > ARRAY_SIZE(bus->devices)) { |
329 | ssb_printk(KERN_ERR PFX | 326 | ssb_err("More than %d ssb cores found (%d)\n", |
330 | "More than %d ssb cores found (%d)\n", | 327 | SSB_MAX_NR_CORES, bus->nr_devices); |
331 | SSB_MAX_NR_CORES, bus->nr_devices); | ||
332 | goto err_unmap; | 328 | goto err_unmap; |
333 | } | 329 | } |
334 | if (bus->bustype == SSB_BUSTYPE_SSB) { | 330 | if (bus->bustype == SSB_BUSTYPE_SSB) { |
@@ -370,8 +366,7 @@ int ssb_bus_scan(struct ssb_bus *bus, | |||
370 | nr_80211_cores++; | 366 | nr_80211_cores++; |
371 | if (nr_80211_cores > 1) { | 367 | if (nr_80211_cores > 1) { |
372 | if (!we_support_multiple_80211_cores(bus)) { | 368 | if (!we_support_multiple_80211_cores(bus)) { |
373 | ssb_dprintk(KERN_INFO PFX "Ignoring additional " | 369 | ssb_dbg("Ignoring additional 802.11 core\n"); |
374 | "802.11 core\n"); | ||
375 | continue; | 370 | continue; |
376 | } | 371 | } |
377 | } | 372 | } |
@@ -379,8 +374,7 @@ int ssb_bus_scan(struct ssb_bus *bus, | |||
379 | case SSB_DEV_EXTIF: | 374 | case SSB_DEV_EXTIF: |
380 | #ifdef CONFIG_SSB_DRIVER_EXTIF | 375 | #ifdef CONFIG_SSB_DRIVER_EXTIF |
381 | if (bus->extif.dev) { | 376 | if (bus->extif.dev) { |
382 | ssb_printk(KERN_WARNING PFX | 377 | ssb_warn("WARNING: Multiple EXTIFs found\n"); |
383 | "WARNING: Multiple EXTIFs found\n"); | ||
384 | break; | 378 | break; |
385 | } | 379 | } |
386 | bus->extif.dev = dev; | 380 | bus->extif.dev = dev; |
@@ -388,8 +382,7 @@ int ssb_bus_scan(struct ssb_bus *bus, | |||
388 | break; | 382 | break; |
389 | case SSB_DEV_CHIPCOMMON: | 383 | case SSB_DEV_CHIPCOMMON: |
390 | if (bus->chipco.dev) { | 384 | if (bus->chipco.dev) { |
391 | ssb_printk(KERN_WARNING PFX | 385 | ssb_warn("WARNING: Multiple ChipCommon found\n"); |
392 | "WARNING: Multiple ChipCommon found\n"); | ||
393 | break; | 386 | break; |
394 | } | 387 | } |
395 | bus->chipco.dev = dev; | 388 | bus->chipco.dev = dev; |
@@ -398,8 +391,7 @@ int ssb_bus_scan(struct ssb_bus *bus, | |||
398 | case SSB_DEV_MIPS_3302: | 391 | case SSB_DEV_MIPS_3302: |
399 | #ifdef CONFIG_SSB_DRIVER_MIPS | 392 | #ifdef CONFIG_SSB_DRIVER_MIPS |
400 | if (bus->mipscore.dev) { | 393 | if (bus->mipscore.dev) { |
401 | ssb_printk(KERN_WARNING PFX | 394 | ssb_warn("WARNING: Multiple MIPS cores found\n"); |
402 | "WARNING: Multiple MIPS cores found\n"); | ||
403 | break; | 395 | break; |
404 | } | 396 | } |
405 | bus->mipscore.dev = dev; | 397 | bus->mipscore.dev = dev; |
@@ -420,8 +412,7 @@ int ssb_bus_scan(struct ssb_bus *bus, | |||
420 | } | 412 | } |
421 | } | 413 | } |
422 | if (bus->pcicore.dev) { | 414 | if (bus->pcicore.dev) { |
423 | ssb_printk(KERN_WARNING PFX | 415 | ssb_warn("WARNING: Multiple PCI(E) cores found\n"); |
424 | "WARNING: Multiple PCI(E) cores found\n"); | ||
425 | break; | 416 | break; |
426 | } | 417 | } |
427 | bus->pcicore.dev = dev; | 418 | bus->pcicore.dev = dev; |
diff --git a/drivers/ssb/sprom.c b/drivers/ssb/sprom.c index 80d366fcf8d3..a3b23644b0fb 100644 --- a/drivers/ssb/sprom.c +++ b/drivers/ssb/sprom.c | |||
@@ -127,13 +127,13 @@ ssize_t ssb_attr_sprom_store(struct ssb_bus *bus, | |||
127 | goto out_kfree; | 127 | goto out_kfree; |
128 | err = ssb_devices_freeze(bus, &freeze); | 128 | err = ssb_devices_freeze(bus, &freeze); |
129 | if (err) { | 129 | if (err) { |
130 | ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze all devices\n"); | 130 | ssb_err("SPROM write: Could not freeze all devices\n"); |
131 | goto out_unlock; | 131 | goto out_unlock; |
132 | } | 132 | } |
133 | res = sprom_write(bus, sprom); | 133 | res = sprom_write(bus, sprom); |
134 | err = ssb_devices_thaw(&freeze); | 134 | err = ssb_devices_thaw(&freeze); |
135 | if (err) | 135 | if (err) |
136 | ssb_printk(KERN_ERR PFX "SPROM write: Could not thaw all devices\n"); | 136 | ssb_err("SPROM write: Could not thaw all devices\n"); |
137 | out_unlock: | 137 | out_unlock: |
138 | mutex_unlock(&bus->sprom_mutex); | 138 | mutex_unlock(&bus->sprom_mutex); |
139 | out_kfree: | 139 | out_kfree: |
diff --git a/drivers/ssb/ssb_private.h b/drivers/ssb/ssb_private.h index 466171b77f68..4671f17f09af 100644 --- a/drivers/ssb/ssb_private.h +++ b/drivers/ssb/ssb_private.h | |||
@@ -9,16 +9,27 @@ | |||
9 | #define PFX "ssb: " | 9 | #define PFX "ssb: " |
10 | 10 | ||
11 | #ifdef CONFIG_SSB_SILENT | 11 | #ifdef CONFIG_SSB_SILENT |
12 | # define ssb_printk(fmt, x...) do { /* nothing */ } while (0) | 12 | # define ssb_printk(fmt, ...) \ |
13 | do { if (0) printk(fmt, ##__VA_ARGS__); } while (0) | ||
13 | #else | 14 | #else |
14 | # define ssb_printk printk | 15 | # define ssb_printk(fmt, ...) \ |
16 | printk(fmt, ##__VA_ARGS__) | ||
15 | #endif /* CONFIG_SSB_SILENT */ | 17 | #endif /* CONFIG_SSB_SILENT */ |
16 | 18 | ||
19 | #define ssb_emerg(fmt, ...) ssb_printk(KERN_EMERG PFX fmt, ##__VA_ARGS__) | ||
20 | #define ssb_err(fmt, ...) ssb_printk(KERN_ERR PFX fmt, ##__VA_ARGS__) | ||
21 | #define ssb_warn(fmt, ...) ssb_printk(KERN_WARNING PFX fmt, ##__VA_ARGS__) | ||
22 | #define ssb_notice(fmt, ...) ssb_printk(KERN_NOTICE PFX fmt, ##__VA_ARGS__) | ||
23 | #define ssb_info(fmt, ...) ssb_printk(KERN_INFO PFX fmt, ##__VA_ARGS__) | ||
24 | #define ssb_cont(fmt, ...) ssb_printk(KERN_CONT fmt, ##__VA_ARGS__) | ||
25 | |||
17 | /* dprintk: Debugging printk; vanishes for non-debug compilation */ | 26 | /* dprintk: Debugging printk; vanishes for non-debug compilation */ |
18 | #ifdef CONFIG_SSB_DEBUG | 27 | #ifdef CONFIG_SSB_DEBUG |
19 | # define ssb_dprintk(fmt, x...) ssb_printk(fmt , ##x) | 28 | # define ssb_dbg(fmt, ...) \ |
29 | ssb_printk(KERN_DEBUG PFX fmt, ##__VA_ARGS__) | ||
20 | #else | 30 | #else |
21 | # define ssb_dprintk(fmt, x...) do { /* nothing */ } while (0) | 31 | # define ssb_dbg(fmt, ...) \ |
32 | do { if (0) printk(KERN_DEBUG PFX fmt, ##__VA_ARGS__); } while (0) | ||
22 | #endif | 33 | #endif |
23 | 34 | ||
24 | #ifdef CONFIG_SSB_DEBUG | 35 | #ifdef CONFIG_SSB_DEBUG |
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 7e24fe0cfbcd..4cf0c9e4dd99 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h | |||
@@ -113,6 +113,34 @@ | |||
113 | #define IEEE80211_CTL_EXT_SSW_FBACK 0x9000 | 113 | #define IEEE80211_CTL_EXT_SSW_FBACK 0x9000 |
114 | #define IEEE80211_CTL_EXT_SSW_ACK 0xa000 | 114 | #define IEEE80211_CTL_EXT_SSW_ACK 0xa000 |
115 | 115 | ||
116 | |||
117 | #define IEEE80211_SN_MASK ((IEEE80211_SCTL_SEQ) >> 4) | ||
118 | #define IEEE80211_MAX_SN IEEE80211_SN_MASK | ||
119 | #define IEEE80211_SN_MODULO (IEEE80211_MAX_SN + 1) | ||
120 | |||
121 | static inline int ieee80211_sn_less(u16 sn1, u16 sn2) | ||
122 | { | ||
123 | return ((sn1 - sn2) & IEEE80211_SN_MASK) > (IEEE80211_SN_MODULO >> 1); | ||
124 | } | ||
125 | |||
126 | static inline u16 ieee80211_sn_add(u16 sn1, u16 sn2) | ||
127 | { | ||
128 | return (sn1 + sn2) & IEEE80211_SN_MASK; | ||
129 | } | ||
130 | |||
131 | static inline u16 ieee80211_sn_inc(u16 sn) | ||
132 | { | ||
133 | return ieee80211_sn_add(sn, 1); | ||
134 | } | ||
135 | |||
136 | static inline u16 ieee80211_sn_sub(u16 sn1, u16 sn2) | ||
137 | { | ||
138 | return (sn1 - sn2) & IEEE80211_SN_MASK; | ||
139 | } | ||
140 | |||
141 | #define IEEE80211_SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4) | ||
142 | #define IEEE80211_SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ) | ||
143 | |||
116 | /* miscellaneous IEEE 802.11 constants */ | 144 | /* miscellaneous IEEE 802.11 constants */ |
117 | #define IEEE80211_MAX_FRAG_THRESHOLD 2352 | 145 | #define IEEE80211_MAX_FRAG_THRESHOLD 2352 |
118 | #define IEEE80211_MAX_RTS_THRESHOLD 2353 | 146 | #define IEEE80211_MAX_RTS_THRESHOLD 2353 |
@@ -185,7 +213,7 @@ struct ieee80211_hdr { | |||
185 | u8 addr3[6]; | 213 | u8 addr3[6]; |
186 | __le16 seq_ctrl; | 214 | __le16 seq_ctrl; |
187 | u8 addr4[6]; | 215 | u8 addr4[6]; |
188 | } __packed; | 216 | } __packed __aligned(2); |
189 | 217 | ||
190 | struct ieee80211_hdr_3addr { | 218 | struct ieee80211_hdr_3addr { |
191 | __le16 frame_control; | 219 | __le16 frame_control; |
@@ -194,7 +222,7 @@ struct ieee80211_hdr_3addr { | |||
194 | u8 addr2[6]; | 222 | u8 addr2[6]; |
195 | u8 addr3[6]; | 223 | u8 addr3[6]; |
196 | __le16 seq_ctrl; | 224 | __le16 seq_ctrl; |
197 | } __packed; | 225 | } __packed __aligned(2); |
198 | 226 | ||
199 | struct ieee80211_qos_hdr { | 227 | struct ieee80211_qos_hdr { |
200 | __le16 frame_control; | 228 | __le16 frame_control; |
@@ -204,7 +232,7 @@ struct ieee80211_qos_hdr { | |||
204 | u8 addr3[6]; | 232 | u8 addr3[6]; |
205 | __le16 seq_ctrl; | 233 | __le16 seq_ctrl; |
206 | __le16 qos_ctrl; | 234 | __le16 qos_ctrl; |
207 | } __packed; | 235 | } __packed __aligned(2); |
208 | 236 | ||
209 | /** | 237 | /** |
210 | * ieee80211_has_tods - check if IEEE80211_FCTL_TODS is set | 238 | * ieee80211_has_tods - check if IEEE80211_FCTL_TODS is set |
@@ -581,7 +609,7 @@ struct ieee80211s_hdr { | |||
581 | __le32 seqnum; | 609 | __le32 seqnum; |
582 | u8 eaddr1[6]; | 610 | u8 eaddr1[6]; |
583 | u8 eaddr2[6]; | 611 | u8 eaddr2[6]; |
584 | } __packed; | 612 | } __packed __aligned(2); |
585 | 613 | ||
586 | /* Mesh flags */ | 614 | /* Mesh flags */ |
587 | #define MESH_FLAGS_AE_A4 0x1 | 615 | #define MESH_FLAGS_AE_A4 0x1 |
@@ -875,7 +903,7 @@ struct ieee80211_mgmt { | |||
875 | } u; | 903 | } u; |
876 | } __packed action; | 904 | } __packed action; |
877 | } u; | 905 | } u; |
878 | } __packed; | 906 | } __packed __aligned(2); |
879 | 907 | ||
880 | /* Supported Rates value encodings in 802.11n-2009 7.3.2.2 */ | 908 | /* Supported Rates value encodings in 802.11n-2009 7.3.2.2 */ |
881 | #define BSS_MEMBERSHIP_SELECTOR_HT_PHY 127 | 909 | #define BSS_MEMBERSHIP_SELECTOR_HT_PHY 127 |
@@ -906,20 +934,20 @@ struct ieee80211_rts { | |||
906 | __le16 duration; | 934 | __le16 duration; |
907 | u8 ra[6]; | 935 | u8 ra[6]; |
908 | u8 ta[6]; | 936 | u8 ta[6]; |
909 | } __packed; | 937 | } __packed __aligned(2); |
910 | 938 | ||
911 | struct ieee80211_cts { | 939 | struct ieee80211_cts { |
912 | __le16 frame_control; | 940 | __le16 frame_control; |
913 | __le16 duration; | 941 | __le16 duration; |
914 | u8 ra[6]; | 942 | u8 ra[6]; |
915 | } __packed; | 943 | } __packed __aligned(2); |
916 | 944 | ||
917 | struct ieee80211_pspoll { | 945 | struct ieee80211_pspoll { |
918 | __le16 frame_control; | 946 | __le16 frame_control; |
919 | __le16 aid; | 947 | __le16 aid; |
920 | u8 bssid[6]; | 948 | u8 bssid[6]; |
921 | u8 ta[6]; | 949 | u8 ta[6]; |
922 | } __packed; | 950 | } __packed __aligned(2); |
923 | 951 | ||
924 | /* TDLS */ | 952 | /* TDLS */ |
925 | 953 | ||
@@ -1290,11 +1318,6 @@ struct ieee80211_vht_operation { | |||
1290 | } __packed; | 1318 | } __packed; |
1291 | 1319 | ||
1292 | 1320 | ||
1293 | #define IEEE80211_VHT_MCS_ZERO_TO_SEVEN_SUPPORT 0 | ||
1294 | #define IEEE80211_VHT_MCS_ZERO_TO_EIGHT_SUPPORT 1 | ||
1295 | #define IEEE80211_VHT_MCS_ZERO_TO_NINE_SUPPORT 2 | ||
1296 | #define IEEE80211_VHT_MCS_NOT_SUPPORTED 3 | ||
1297 | |||
1298 | /* 802.11ac VHT Capabilities */ | 1321 | /* 802.11ac VHT Capabilities */ |
1299 | #define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 0x00000000 | 1322 | #define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 0x00000000 |
1300 | #define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 0x00000001 | 1323 | #define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 0x00000001 |
@@ -1310,10 +1333,11 @@ struct ieee80211_vht_operation { | |||
1310 | #define IEEE80211_VHT_CAP_RXSTBC_2 0x00000200 | 1333 | #define IEEE80211_VHT_CAP_RXSTBC_2 0x00000200 |
1311 | #define IEEE80211_VHT_CAP_RXSTBC_3 0x00000300 | 1334 | #define IEEE80211_VHT_CAP_RXSTBC_3 0x00000300 |
1312 | #define IEEE80211_VHT_CAP_RXSTBC_4 0x00000400 | 1335 | #define IEEE80211_VHT_CAP_RXSTBC_4 0x00000400 |
1336 | #define IEEE80211_VHT_CAP_RXSTBC_MASK 0x00000700 | ||
1313 | #define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE 0x00000800 | 1337 | #define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE 0x00000800 |
1314 | #define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE 0x00001000 | 1338 | #define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE 0x00001000 |
1315 | #define IEEE80211_VHT_CAP_BEAMFORMER_ANTENNAS_MAX 0x00006000 | 1339 | #define IEEE80211_VHT_CAP_BEAMFORMER_ANTENNAS_MAX 0x00006000 |
1316 | #define IEEE80211_VHT_CAP_SOUNDING_DIMENTION_MAX 0x00030000 | 1340 | #define IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MAX 0x00030000 |
1317 | #define IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE 0x00080000 | 1341 | #define IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE 0x00080000 |
1318 | #define IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE 0x00100000 | 1342 | #define IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE 0x00100000 |
1319 | #define IEEE80211_VHT_CAP_VHT_TXOP_PS 0x00200000 | 1343 | #define IEEE80211_VHT_CAP_VHT_TXOP_PS 0x00200000 |
diff --git a/include/linux/socket.h b/include/linux/socket.h index 2b9f74b0ffea..428c37a1f95c 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h | |||
@@ -298,6 +298,7 @@ struct ucred { | |||
298 | #define SOL_IUCV 277 | 298 | #define SOL_IUCV 277 |
299 | #define SOL_CAIF 278 | 299 | #define SOL_CAIF 278 |
300 | #define SOL_ALG 279 | 300 | #define SOL_ALG 279 |
301 | #define SOL_NFC 280 | ||
301 | 302 | ||
302 | /* IPX options */ | 303 | /* IPX options */ |
303 | #define IPX_TYPE 1 | 304 | #define IPX_TYPE 1 |
diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h index 22958d68ecfe..8b1322296fed 100644 --- a/include/linux/ssb/ssb.h +++ b/include/linux/ssb/ssb.h | |||
@@ -26,9 +26,9 @@ struct ssb_sprom_core_pwr_info { | |||
26 | 26 | ||
27 | struct ssb_sprom { | 27 | struct ssb_sprom { |
28 | u8 revision; | 28 | u8 revision; |
29 | u8 il0mac[6]; /* MAC address for 802.11b/g */ | 29 | u8 il0mac[6] __aligned(sizeof(u16)); /* MAC address for 802.11b/g */ |
30 | u8 et0mac[6]; /* MAC address for Ethernet */ | 30 | u8 et0mac[6] __aligned(sizeof(u16)); /* MAC address for Ethernet */ |
31 | u8 et1mac[6]; /* MAC address for 802.11a */ | 31 | u8 et1mac[6] __aligned(sizeof(u16)); /* MAC address for 802.11a */ |
32 | u8 et0phyaddr; /* MII address for enet0 */ | 32 | u8 et0phyaddr; /* MII address for enet0 */ |
33 | u8 et1phyaddr; /* MII address for enet1 */ | 33 | u8 et1phyaddr; /* MII address for enet1 */ |
34 | u8 et0mdcport; /* MDIO for enet0 */ | 34 | u8 et0mdcport; /* MDIO for enet0 */ |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index d581c6de5d64..bdba9b619064 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -611,22 +611,10 @@ struct cfg80211_ap_settings { | |||
611 | }; | 611 | }; |
612 | 612 | ||
613 | /** | 613 | /** |
614 | * enum plink_action - actions to perform in mesh peers | ||
615 | * | ||
616 | * @PLINK_ACTION_INVALID: action 0 is reserved | ||
617 | * @PLINK_ACTION_OPEN: start mesh peer link establishment | ||
618 | * @PLINK_ACTION_BLOCK: block traffic from this mesh peer | ||
619 | */ | ||
620 | enum plink_actions { | ||
621 | PLINK_ACTION_INVALID, | ||
622 | PLINK_ACTION_OPEN, | ||
623 | PLINK_ACTION_BLOCK, | ||
624 | }; | ||
625 | |||
626 | /** | ||
627 | * enum station_parameters_apply_mask - station parameter values to apply | 614 | * enum station_parameters_apply_mask - station parameter values to apply |
628 | * @STATION_PARAM_APPLY_UAPSD: apply new uAPSD parameters (uapsd_queues, max_sp) | 615 | * @STATION_PARAM_APPLY_UAPSD: apply new uAPSD parameters (uapsd_queues, max_sp) |
629 | * @STATION_PARAM_APPLY_CAPABILITY: apply new capability | 616 | * @STATION_PARAM_APPLY_CAPABILITY: apply new capability |
617 | * @STATION_PARAM_APPLY_PLINK_STATE: apply new plink state | ||
630 | * | 618 | * |
631 | * Not all station parameters have in-band "no change" signalling, | 619 | * Not all station parameters have in-band "no change" signalling, |
632 | * for those that don't these flags will are used. | 620 | * for those that don't these flags will are used. |
@@ -634,6 +622,7 @@ enum plink_actions { | |||
634 | enum station_parameters_apply_mask { | 622 | enum station_parameters_apply_mask { |
635 | STATION_PARAM_APPLY_UAPSD = BIT(0), | 623 | STATION_PARAM_APPLY_UAPSD = BIT(0), |
636 | STATION_PARAM_APPLY_CAPABILITY = BIT(1), | 624 | STATION_PARAM_APPLY_CAPABILITY = BIT(1), |
625 | STATION_PARAM_APPLY_PLINK_STATE = BIT(2), | ||
637 | }; | 626 | }; |
638 | 627 | ||
639 | /** | 628 | /** |
@@ -669,7 +658,7 @@ enum station_parameters_apply_mask { | |||
669 | * @ext_capab_len: number of extended capabilities | 658 | * @ext_capab_len: number of extended capabilities |
670 | */ | 659 | */ |
671 | struct station_parameters { | 660 | struct station_parameters { |
672 | u8 *supported_rates; | 661 | const u8 *supported_rates; |
673 | struct net_device *vlan; | 662 | struct net_device *vlan; |
674 | u32 sta_flags_mask, sta_flags_set; | 663 | u32 sta_flags_mask, sta_flags_set; |
675 | u32 sta_modify_mask; | 664 | u32 sta_modify_mask; |
@@ -678,17 +667,60 @@ struct station_parameters { | |||
678 | u8 supported_rates_len; | 667 | u8 supported_rates_len; |
679 | u8 plink_action; | 668 | u8 plink_action; |
680 | u8 plink_state; | 669 | u8 plink_state; |
681 | struct ieee80211_ht_cap *ht_capa; | 670 | const struct ieee80211_ht_cap *ht_capa; |
682 | struct ieee80211_vht_cap *vht_capa; | 671 | const struct ieee80211_vht_cap *vht_capa; |
683 | u8 uapsd_queues; | 672 | u8 uapsd_queues; |
684 | u8 max_sp; | 673 | u8 max_sp; |
685 | enum nl80211_mesh_power_mode local_pm; | 674 | enum nl80211_mesh_power_mode local_pm; |
686 | u16 capability; | 675 | u16 capability; |
687 | u8 *ext_capab; | 676 | const u8 *ext_capab; |
688 | u8 ext_capab_len; | 677 | u8 ext_capab_len; |
689 | }; | 678 | }; |
690 | 679 | ||
691 | /** | 680 | /** |
681 | * enum cfg80211_station_type - the type of station being modified | ||
682 | * @CFG80211_STA_AP_CLIENT: client of an AP interface | ||
683 | * @CFG80211_STA_AP_MLME_CLIENT: client of an AP interface that has | ||
684 | * the AP MLME in the device | ||
685 | * @CFG80211_STA_AP_STA: AP station on managed interface | ||
686 | * @CFG80211_STA_IBSS: IBSS station | ||
687 | * @CFG80211_STA_TDLS_PEER_SETUP: TDLS peer on managed interface (dummy entry | ||
688 | * while TDLS setup is in progress, it moves out of this state when | ||
689 | * being marked authorized; use this only if TDLS with external setup is | ||
690 | * supported/used) | ||
691 | * @CFG80211_STA_TDLS_PEER_ACTIVE: TDLS peer on managed interface (active | ||
692 | * entry that is operating, has been marked authorized by userspace) | ||
693 | * @CFG80211_STA_MESH_PEER_KERNEL: peer on mesh interface (kernel managed) | ||
694 | * @CFG80211_STA_MESH_PEER_USER: peer on mesh interface (user managed) | ||
695 | */ | ||
696 | enum cfg80211_station_type { | ||
697 | CFG80211_STA_AP_CLIENT, | ||
698 | CFG80211_STA_AP_MLME_CLIENT, | ||
699 | CFG80211_STA_AP_STA, | ||
700 | CFG80211_STA_IBSS, | ||
701 | CFG80211_STA_TDLS_PEER_SETUP, | ||
702 | CFG80211_STA_TDLS_PEER_ACTIVE, | ||
703 | CFG80211_STA_MESH_PEER_KERNEL, | ||
704 | CFG80211_STA_MESH_PEER_USER, | ||
705 | }; | ||
706 | |||
707 | /** | ||
708 | * cfg80211_check_station_change - validate parameter changes | ||
709 | * @wiphy: the wiphy this operates on | ||
710 | * @params: the new parameters for a station | ||
711 | * @statype: the type of station being modified | ||
712 | * | ||
713 | * Utility function for the @change_station driver method. Call this function | ||
714 | * with the appropriate station type looking up the station (and checking that | ||
715 | * it exists). It will verify whether the station change is acceptable, and if | ||
716 | * not will return an error code. Note that it may modify the parameters for | ||
717 | * backward compatibility reasons, so don't use them before calling this. | ||
718 | */ | ||
719 | int cfg80211_check_station_change(struct wiphy *wiphy, | ||
720 | struct station_parameters *params, | ||
721 | enum cfg80211_station_type statype); | ||
722 | |||
723 | /** | ||
692 | * enum station_info_flags - station information flags | 724 | * enum station_info_flags - station information flags |
693 | * | 725 | * |
694 | * Used by the driver to indicate which info in &struct station_info | 726 | * Used by the driver to indicate which info in &struct station_info |
@@ -1119,6 +1151,7 @@ struct mesh_config { | |||
1119 | * @ie_len: length of vendor information elements | 1151 | * @ie_len: length of vendor information elements |
1120 | * @is_authenticated: this mesh requires authentication | 1152 | * @is_authenticated: this mesh requires authentication |
1121 | * @is_secure: this mesh uses security | 1153 | * @is_secure: this mesh uses security |
1154 | * @user_mpm: userspace handles all MPM functions | ||
1122 | * @dtim_period: DTIM period to use | 1155 | * @dtim_period: DTIM period to use |
1123 | * @beacon_interval: beacon interval to use | 1156 | * @beacon_interval: beacon interval to use |
1124 | * @mcast_rate: multicat rate for Mesh Node [6Mbps is the default for 802.11a] | 1157 | * @mcast_rate: multicat rate for Mesh Node [6Mbps is the default for 802.11a] |
@@ -1136,6 +1169,7 @@ struct mesh_setup { | |||
1136 | u8 ie_len; | 1169 | u8 ie_len; |
1137 | bool is_authenticated; | 1170 | bool is_authenticated; |
1138 | bool is_secure; | 1171 | bool is_secure; |
1172 | bool user_mpm; | ||
1139 | u8 dtim_period; | 1173 | u8 dtim_period; |
1140 | u16 beacon_interval; | 1174 | u16 beacon_interval; |
1141 | int mcast_rate[IEEE80211_NUM_BANDS]; | 1175 | int mcast_rate[IEEE80211_NUM_BANDS]; |
@@ -1398,9 +1432,11 @@ struct cfg80211_auth_request { | |||
1398 | * enum cfg80211_assoc_req_flags - Over-ride default behaviour in association. | 1432 | * enum cfg80211_assoc_req_flags - Over-ride default behaviour in association. |
1399 | * | 1433 | * |
1400 | * @ASSOC_REQ_DISABLE_HT: Disable HT (802.11n) | 1434 | * @ASSOC_REQ_DISABLE_HT: Disable HT (802.11n) |
1435 | * @ASSOC_REQ_DISABLE_VHT: Disable VHT | ||
1401 | */ | 1436 | */ |
1402 | enum cfg80211_assoc_req_flags { | 1437 | enum cfg80211_assoc_req_flags { |
1403 | ASSOC_REQ_DISABLE_HT = BIT(0), | 1438 | ASSOC_REQ_DISABLE_HT = BIT(0), |
1439 | ASSOC_REQ_DISABLE_VHT = BIT(1), | ||
1404 | }; | 1440 | }; |
1405 | 1441 | ||
1406 | /** | 1442 | /** |
@@ -1422,6 +1458,8 @@ enum cfg80211_assoc_req_flags { | |||
1422 | * @ht_capa: HT Capabilities over-rides. Values set in ht_capa_mask | 1458 | * @ht_capa: HT Capabilities over-rides. Values set in ht_capa_mask |
1423 | * will be used in ht_capa. Un-supported values will be ignored. | 1459 | * will be used in ht_capa. Un-supported values will be ignored. |
1424 | * @ht_capa_mask: The bits of ht_capa which are to be used. | 1460 | * @ht_capa_mask: The bits of ht_capa which are to be used. |
1461 | * @vht_capa: VHT capability override | ||
1462 | * @vht_capa_mask: VHT capability mask indicating which fields to use | ||
1425 | */ | 1463 | */ |
1426 | struct cfg80211_assoc_request { | 1464 | struct cfg80211_assoc_request { |
1427 | struct cfg80211_bss *bss; | 1465 | struct cfg80211_bss *bss; |
@@ -1432,6 +1470,7 @@ struct cfg80211_assoc_request { | |||
1432 | u32 flags; | 1470 | u32 flags; |
1433 | struct ieee80211_ht_cap ht_capa; | 1471 | struct ieee80211_ht_cap ht_capa; |
1434 | struct ieee80211_ht_cap ht_capa_mask; | 1472 | struct ieee80211_ht_cap ht_capa_mask; |
1473 | struct ieee80211_vht_cap vht_capa, vht_capa_mask; | ||
1435 | }; | 1474 | }; |
1436 | 1475 | ||
1437 | /** | 1476 | /** |
@@ -1542,6 +1581,8 @@ struct cfg80211_ibss_params { | |||
1542 | * @ht_capa: HT Capabilities over-rides. Values set in ht_capa_mask | 1581 | * @ht_capa: HT Capabilities over-rides. Values set in ht_capa_mask |
1543 | * will be used in ht_capa. Un-supported values will be ignored. | 1582 | * will be used in ht_capa. Un-supported values will be ignored. |
1544 | * @ht_capa_mask: The bits of ht_capa which are to be used. | 1583 | * @ht_capa_mask: The bits of ht_capa which are to be used. |
1584 | * @vht_capa: VHT Capability overrides | ||
1585 | * @vht_capa_mask: The bits of vht_capa which are to be used. | ||
1545 | */ | 1586 | */ |
1546 | struct cfg80211_connect_params { | 1587 | struct cfg80211_connect_params { |
1547 | struct ieee80211_channel *channel; | 1588 | struct ieee80211_channel *channel; |
@@ -1560,6 +1601,8 @@ struct cfg80211_connect_params { | |||
1560 | int bg_scan_period; | 1601 | int bg_scan_period; |
1561 | struct ieee80211_ht_cap ht_capa; | 1602 | struct ieee80211_ht_cap ht_capa; |
1562 | struct ieee80211_ht_cap ht_capa_mask; | 1603 | struct ieee80211_ht_cap ht_capa_mask; |
1604 | struct ieee80211_vht_cap vht_capa; | ||
1605 | struct ieee80211_vht_cap vht_capa_mask; | ||
1563 | }; | 1606 | }; |
1564 | 1607 | ||
1565 | /** | 1608 | /** |
@@ -1722,6 +1765,21 @@ struct cfg80211_gtk_rekey_data { | |||
1722 | }; | 1765 | }; |
1723 | 1766 | ||
1724 | /** | 1767 | /** |
1768 | * struct cfg80211_update_ft_ies_params - FT IE Information | ||
1769 | * | ||
1770 | * This structure provides information needed to update the fast transition IE | ||
1771 | * | ||
1772 | * @md: The Mobility Domain ID, 2 Octet value | ||
1773 | * @ie: Fast Transition IEs | ||
1774 | * @ie_len: Length of ft_ie in octets | ||
1775 | */ | ||
1776 | struct cfg80211_update_ft_ies_params { | ||
1777 | u16 md; | ||
1778 | const u8 *ie; | ||
1779 | size_t ie_len; | ||
1780 | }; | ||
1781 | |||
1782 | /** | ||
1725 | * struct cfg80211_ops - backend description for wireless configuration | 1783 | * struct cfg80211_ops - backend description for wireless configuration |
1726 | * | 1784 | * |
1727 | * This struct is registered by fullmac card drivers and/or wireless stacks | 1785 | * This struct is registered by fullmac card drivers and/or wireless stacks |
@@ -1781,9 +1839,8 @@ struct cfg80211_gtk_rekey_data { | |||
1781 | * @change_station: Modify a given station. Note that flags changes are not much | 1839 | * @change_station: Modify a given station. Note that flags changes are not much |
1782 | * validated in cfg80211, in particular the auth/assoc/authorized flags | 1840 | * validated in cfg80211, in particular the auth/assoc/authorized flags |
1783 | * might come to the driver in invalid combinations -- make sure to check | 1841 | * might come to the driver in invalid combinations -- make sure to check |
1784 | * them, also against the existing state! Also, supported_rates changes are | 1842 | * them, also against the existing state! Drivers must call |
1785 | * not checked in station mode -- drivers need to reject (or ignore) them | 1843 | * cfg80211_check_station_change() to validate the information. |
1786 | * for anything but TDLS peers. | ||
1787 | * @get_station: get station information for the station identified by @mac | 1844 | * @get_station: get station information for the station identified by @mac |
1788 | * @dump_station: dump station callback -- resume dump at index @idx | 1845 | * @dump_station: dump station callback -- resume dump at index @idx |
1789 | * | 1846 | * |
@@ -2168,6 +2225,8 @@ struct cfg80211_ops { | |||
2168 | int (*start_radar_detection)(struct wiphy *wiphy, | 2225 | int (*start_radar_detection)(struct wiphy *wiphy, |
2169 | struct net_device *dev, | 2226 | struct net_device *dev, |
2170 | struct cfg80211_chan_def *chandef); | 2227 | struct cfg80211_chan_def *chandef); |
2228 | int (*update_ft_ies)(struct wiphy *wiphy, struct net_device *dev, | ||
2229 | struct cfg80211_update_ft_ies_params *ftie); | ||
2171 | }; | 2230 | }; |
2172 | 2231 | ||
2173 | /* | 2232 | /* |
@@ -2485,6 +2544,8 @@ struct wiphy_wowlan_support { | |||
2485 | * @ap_sme_capa: AP SME capabilities, flags from &enum nl80211_ap_sme_features. | 2544 | * @ap_sme_capa: AP SME capabilities, flags from &enum nl80211_ap_sme_features. |
2486 | * @ht_capa_mod_mask: Specify what ht_cap values can be over-ridden. | 2545 | * @ht_capa_mod_mask: Specify what ht_cap values can be over-ridden. |
2487 | * If null, then none can be over-ridden. | 2546 | * If null, then none can be over-ridden. |
2547 | * @vht_capa_mod_mask: Specify what VHT capabilities can be over-ridden. | ||
2548 | * If null, then none can be over-ridden. | ||
2488 | * | 2549 | * |
2489 | * @max_acl_mac_addrs: Maximum number of MAC addresses that the device | 2550 | * @max_acl_mac_addrs: Maximum number of MAC addresses that the device |
2490 | * supports for ACL. | 2551 | * supports for ACL. |
@@ -2593,6 +2654,7 @@ struct wiphy { | |||
2593 | struct dentry *debugfsdir; | 2654 | struct dentry *debugfsdir; |
2594 | 2655 | ||
2595 | const struct ieee80211_ht_cap *ht_capa_mod_mask; | 2656 | const struct ieee80211_ht_cap *ht_capa_mod_mask; |
2657 | const struct ieee80211_vht_cap *vht_capa_mod_mask; | ||
2596 | 2658 | ||
2597 | #ifdef CONFIG_NET_NS | 2659 | #ifdef CONFIG_NET_NS |
2598 | /* the network namespace this phy lives in currently */ | 2660 | /* the network namespace this phy lives in currently */ |
@@ -4002,6 +4064,30 @@ u32 cfg80211_calculate_bitrate(struct rate_info *rate); | |||
4002 | void cfg80211_unregister_wdev(struct wireless_dev *wdev); | 4064 | void cfg80211_unregister_wdev(struct wireless_dev *wdev); |
4003 | 4065 | ||
4004 | /** | 4066 | /** |
4067 | * struct cfg80211_ft_event - FT Information Elements | ||
4068 | * @ies: FT IEs | ||
4069 | * @ies_len: length of the FT IE in bytes | ||
4070 | * @target_ap: target AP's MAC address | ||
4071 | * @ric_ies: RIC IE | ||
4072 | * @ric_ies_len: length of the RIC IE in bytes | ||
4073 | */ | ||
4074 | struct cfg80211_ft_event_params { | ||
4075 | const u8 *ies; | ||
4076 | size_t ies_len; | ||
4077 | const u8 *target_ap; | ||
4078 | const u8 *ric_ies; | ||
4079 | size_t ric_ies_len; | ||
4080 | }; | ||
4081 | |||
4082 | /** | ||
4083 | * cfg80211_ft_event - notify userspace about FT IE and RIC IE | ||
4084 | * @netdev: network device | ||
4085 | * @ft_event: IE information | ||
4086 | */ | ||
4087 | void cfg80211_ft_event(struct net_device *netdev, | ||
4088 | struct cfg80211_ft_event_params *ft_event); | ||
4089 | |||
4090 | /** | ||
4005 | * cfg80211_get_p2p_attr - find and copy a P2P attribute from IE buffer | 4091 | * cfg80211_get_p2p_attr - find and copy a P2P attribute from IE buffer |
4006 | * @ies: the input IE buffer | 4092 | * @ies: the input IE buffer |
4007 | * @len: the input length | 4093 | * @len: the input length |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index f7eba1300d82..cdd7cea1fd4c 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -1101,8 +1101,6 @@ static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif) | |||
1101 | * These flags are used for communication about keys between the driver | 1101 | * These flags are used for communication about keys between the driver |
1102 | * and mac80211, with the @flags parameter of &struct ieee80211_key_conf. | 1102 | * and mac80211, with the @flags parameter of &struct ieee80211_key_conf. |
1103 | * | 1103 | * |
1104 | * @IEEE80211_KEY_FLAG_WMM_STA: Set by mac80211, this flag indicates | ||
1105 | * that the STA this key will be used with could be using QoS. | ||
1106 | * @IEEE80211_KEY_FLAG_GENERATE_IV: This flag should be set by the | 1104 | * @IEEE80211_KEY_FLAG_GENERATE_IV: This flag should be set by the |
1107 | * driver to indicate that it requires IV generation for this | 1105 | * driver to indicate that it requires IV generation for this |
1108 | * particular key. | 1106 | * particular key. |
@@ -1127,7 +1125,6 @@ static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif) | |||
1127 | * %IEEE80211_KEY_FLAG_SW_MGMT_TX flag to encrypt such frames in SW. | 1125 | * %IEEE80211_KEY_FLAG_SW_MGMT_TX flag to encrypt such frames in SW. |
1128 | */ | 1126 | */ |
1129 | enum ieee80211_key_flags { | 1127 | enum ieee80211_key_flags { |
1130 | IEEE80211_KEY_FLAG_WMM_STA = 1<<0, | ||
1131 | IEEE80211_KEY_FLAG_GENERATE_IV = 1<<1, | 1128 | IEEE80211_KEY_FLAG_GENERATE_IV = 1<<1, |
1132 | IEEE80211_KEY_FLAG_GENERATE_MMIC= 1<<2, | 1129 | IEEE80211_KEY_FLAG_GENERATE_MMIC= 1<<2, |
1133 | IEEE80211_KEY_FLAG_PAIRWISE = 1<<3, | 1130 | IEEE80211_KEY_FLAG_PAIRWISE = 1<<3, |
@@ -1231,9 +1228,8 @@ enum ieee80211_sta_rx_bandwidth { | |||
1231 | * @addr: MAC address | 1228 | * @addr: MAC address |
1232 | * @aid: AID we assigned to the station if we're an AP | 1229 | * @aid: AID we assigned to the station if we're an AP |
1233 | * @supp_rates: Bitmap of supported rates (per band) | 1230 | * @supp_rates: Bitmap of supported rates (per band) |
1234 | * @ht_cap: HT capabilities of this STA; restricted to our own TX capabilities | 1231 | * @ht_cap: HT capabilities of this STA; restricted to our own capabilities |
1235 | * @vht_cap: VHT capabilities of this STA; Not restricting any capabilities | 1232 | * @vht_cap: VHT capabilities of this STA; restricted to our own capabilities |
1236 | * of remote STA. Taking as is. | ||
1237 | * @wme: indicates whether the STA supports WME. Only valid during AP-mode. | 1233 | * @wme: indicates whether the STA supports WME. Only valid during AP-mode. |
1238 | * @drv_priv: data area for driver use, will always be aligned to | 1234 | * @drv_priv: data area for driver use, will always be aligned to |
1239 | * sizeof(void *), size is determined in hw information. | 1235 | * sizeof(void *), size is determined in hw information. |
@@ -2135,6 +2131,24 @@ enum ieee80211_rate_control_changed { | |||
2135 | }; | 2131 | }; |
2136 | 2132 | ||
2137 | /** | 2133 | /** |
2134 | * enum ieee80211_roc_type - remain on channel type | ||
2135 | * | ||
2136 | * With the support for multi channel contexts and multi channel operations, | ||
2137 | * remain on channel operations might be limited/deferred/aborted by other | ||
2138 | * flows/operations which have higher priority (and vise versa). | ||
2139 | * Specifying the ROC type can be used by devices to prioritize the ROC | ||
2140 | * operations compared to other operations/flows. | ||
2141 | * | ||
2142 | * @IEEE80211_ROC_TYPE_NORMAL: There are no special requirements for this ROC. | ||
2143 | * @IEEE80211_ROC_TYPE_MGMT_TX: The remain on channel request is required | ||
2144 | * for sending managment frames offchannel. | ||
2145 | */ | ||
2146 | enum ieee80211_roc_type { | ||
2147 | IEEE80211_ROC_TYPE_NORMAL = 0, | ||
2148 | IEEE80211_ROC_TYPE_MGMT_TX, | ||
2149 | }; | ||
2150 | |||
2151 | /** | ||
2138 | * struct ieee80211_ops - callbacks from mac80211 to the driver | 2152 | * struct ieee80211_ops - callbacks from mac80211 to the driver |
2139 | * | 2153 | * |
2140 | * This structure contains various callbacks that the driver may | 2154 | * This structure contains various callbacks that the driver may |
@@ -2687,7 +2701,8 @@ struct ieee80211_ops { | |||
2687 | int (*remain_on_channel)(struct ieee80211_hw *hw, | 2701 | int (*remain_on_channel)(struct ieee80211_hw *hw, |
2688 | struct ieee80211_vif *vif, | 2702 | struct ieee80211_vif *vif, |
2689 | struct ieee80211_channel *chan, | 2703 | struct ieee80211_channel *chan, |
2690 | int duration); | 2704 | int duration, |
2705 | enum ieee80211_roc_type type); | ||
2691 | int (*cancel_remain_on_channel)(struct ieee80211_hw *hw); | 2706 | int (*cancel_remain_on_channel)(struct ieee80211_hw *hw); |
2692 | int (*set_ringparam)(struct ieee80211_hw *hw, u32 tx, u32 rx); | 2707 | int (*set_ringparam)(struct ieee80211_hw *hw, u32 tx, u32 rx); |
2693 | void (*get_ringparam)(struct ieee80211_hw *hw, | 2708 | void (*get_ringparam)(struct ieee80211_hw *hw, |
diff --git a/include/uapi/linux/nfc.h b/include/uapi/linux/nfc.h index 7969f46f1bb3..7440bc81a04b 100644 --- a/include/uapi/linux/nfc.h +++ b/include/uapi/linux/nfc.h | |||
@@ -90,6 +90,8 @@ enum nfc_commands { | |||
90 | NFC_CMD_LLC_SET_PARAMS, | 90 | NFC_CMD_LLC_SET_PARAMS, |
91 | NFC_CMD_ENABLE_SE, | 91 | NFC_CMD_ENABLE_SE, |
92 | NFC_CMD_DISABLE_SE, | 92 | NFC_CMD_DISABLE_SE, |
93 | NFC_CMD_LLC_SDREQ, | ||
94 | NFC_EVENT_LLC_SDRES, | ||
93 | /* private: internal use only */ | 95 | /* private: internal use only */ |
94 | __NFC_CMD_AFTER_LAST | 96 | __NFC_CMD_AFTER_LAST |
95 | }; | 97 | }; |
@@ -140,11 +142,21 @@ enum nfc_attrs { | |||
140 | NFC_ATTR_LLC_PARAM_RW, | 142 | NFC_ATTR_LLC_PARAM_RW, |
141 | NFC_ATTR_LLC_PARAM_MIUX, | 143 | NFC_ATTR_LLC_PARAM_MIUX, |
142 | NFC_ATTR_SE, | 144 | NFC_ATTR_SE, |
145 | NFC_ATTR_LLC_SDP, | ||
143 | /* private: internal use only */ | 146 | /* private: internal use only */ |
144 | __NFC_ATTR_AFTER_LAST | 147 | __NFC_ATTR_AFTER_LAST |
145 | }; | 148 | }; |
146 | #define NFC_ATTR_MAX (__NFC_ATTR_AFTER_LAST - 1) | 149 | #define NFC_ATTR_MAX (__NFC_ATTR_AFTER_LAST - 1) |
147 | 150 | ||
151 | enum nfc_sdp_attr { | ||
152 | NFC_SDP_ATTR_UNSPEC, | ||
153 | NFC_SDP_ATTR_URI, | ||
154 | NFC_SDP_ATTR_SAP, | ||
155 | /* private: internal use only */ | ||
156 | __NFC_SDP_ATTR_AFTER_LAST | ||
157 | }; | ||
158 | #define NFC_SDP_ATTR_MAX (__NFC_SDP_ATTR_AFTER_LAST - 1) | ||
159 | |||
148 | #define NFC_DEVICE_NAME_MAXSIZE 8 | 160 | #define NFC_DEVICE_NAME_MAXSIZE 8 |
149 | #define NFC_NFCID1_MAXSIZE 10 | 161 | #define NFC_NFCID1_MAXSIZE 10 |
150 | #define NFC_SENSB_RES_MAXSIZE 12 | 162 | #define NFC_SENSB_RES_MAXSIZE 12 |
@@ -220,4 +232,8 @@ struct sockaddr_nfc_llcp { | |||
220 | #define NFC_LLCP_DIRECTION_RX 0x00 | 232 | #define NFC_LLCP_DIRECTION_RX 0x00 |
221 | #define NFC_LLCP_DIRECTION_TX 0x01 | 233 | #define NFC_LLCP_DIRECTION_TX 0x01 |
222 | 234 | ||
235 | /* socket option names */ | ||
236 | #define NFC_LLCP_RW 0 | ||
237 | #define NFC_LLCP_MIUX 1 | ||
238 | |||
223 | #endif /*__LINUX_NFC_H */ | 239 | #endif /*__LINUX_NFC_H */ |
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index c46bb016f4e4..79da8710448e 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h | |||
@@ -36,7 +36,21 @@ | |||
36 | * The station is still assumed to belong to the AP interface it was added | 36 | * The station is still assumed to belong to the AP interface it was added |
37 | * to. | 37 | * to. |
38 | * | 38 | * |
39 | * TODO: need more info? | 39 | * Station handling varies per interface type and depending on the driver's |
40 | * capabilities. | ||
41 | * | ||
42 | * For drivers supporting TDLS with external setup (WIPHY_FLAG_SUPPORTS_TDLS | ||
43 | * and WIPHY_FLAG_TDLS_EXTERNAL_SETUP), the station lifetime is as follows: | ||
44 | * - a setup station entry is added, not yet authorized, without any rate | ||
45 | * or capability information, this just exists to avoid race conditions | ||
46 | * - when the TDLS setup is done, a single NL80211_CMD_SET_STATION is valid | ||
47 | * to add rate and capability information to the station and at the same | ||
48 | * time mark it authorized. | ||
49 | * - %NL80211_TDLS_ENABLE_LINK is then used | ||
50 | * - after this, the only valid operation is to remove it by tearing down | ||
51 | * the TDLS link (%NL80211_TDLS_DISABLE_LINK) | ||
52 | * | ||
53 | * TODO: need more info for other interface types | ||
40 | */ | 54 | */ |
41 | 55 | ||
42 | /** | 56 | /** |
@@ -499,9 +513,11 @@ | |||
499 | * @NL80211_CMD_NEW_PEER_CANDIDATE: Notification on the reception of a | 513 | * @NL80211_CMD_NEW_PEER_CANDIDATE: Notification on the reception of a |
500 | * beacon or probe response from a compatible mesh peer. This is only | 514 | * beacon or probe response from a compatible mesh peer. This is only |
501 | * sent while no station information (sta_info) exists for the new peer | 515 | * sent while no station information (sta_info) exists for the new peer |
502 | * candidate and when @NL80211_MESH_SETUP_USERSPACE_AUTH is set. On | 516 | * candidate and when @NL80211_MESH_SETUP_USERSPACE_AUTH, |
503 | * reception of this notification, userspace may decide to create a new | 517 | * @NL80211_MESH_SETUP_USERSPACE_AMPE, or |
504 | * station (@NL80211_CMD_NEW_STATION). To stop this notification from | 518 | * @NL80211_MESH_SETUP_USERSPACE_MPM is set. On reception of this |
519 | * notification, userspace may decide to create a new station | ||
520 | * (@NL80211_CMD_NEW_STATION). To stop this notification from | ||
505 | * reoccurring, the userspace authentication daemon may want to create the | 521 | * reoccurring, the userspace authentication daemon may want to create the |
506 | * new station with the AUTHENTICATED flag unset and maybe change it later | 522 | * new station with the AUTHENTICATED flag unset and maybe change it later |
507 | * depending on the authentication result. | 523 | * depending on the authentication result. |
@@ -611,6 +627,18 @@ | |||
611 | * %NL80211_ATTR_RADAR_EVENT is used to inform about the type of the | 627 | * %NL80211_ATTR_RADAR_EVENT is used to inform about the type of the |
612 | * event. | 628 | * event. |
613 | * | 629 | * |
630 | * @NL80211_CMD_GET_PROTOCOL_FEATURES: Get global nl80211 protocol features, | ||
631 | * i.e. features for the nl80211 protocol rather than device features. | ||
632 | * Returns the features in the %NL80211_ATTR_PROTOCOL_FEATURES bitmap. | ||
633 | * | ||
634 | * @NL80211_CMD_UPDATE_FT_IES: Pass down the most up-to-date Fast Transition | ||
635 | * Information Element to the WLAN driver | ||
636 | * | ||
637 | * @NL80211_CMD_FT_EVENT: Send a Fast transition event from the WLAN driver | ||
638 | * to the supplicant. This will carry the target AP's MAC address along | ||
639 | * with the relevant Information Elements. This event is used to report | ||
640 | * received FT IEs (MDIE, FTIE, RSN IE, TIE, RICIE). | ||
641 | * | ||
614 | * @NL80211_CMD_MAX: highest used command number | 642 | * @NL80211_CMD_MAX: highest used command number |
615 | * @__NL80211_CMD_AFTER_LAST: internal use | 643 | * @__NL80211_CMD_AFTER_LAST: internal use |
616 | */ | 644 | */ |
@@ -765,6 +793,11 @@ enum nl80211_commands { | |||
765 | 793 | ||
766 | NL80211_CMD_RADAR_DETECT, | 794 | NL80211_CMD_RADAR_DETECT, |
767 | 795 | ||
796 | NL80211_CMD_GET_PROTOCOL_FEATURES, | ||
797 | |||
798 | NL80211_CMD_UPDATE_FT_IES, | ||
799 | NL80211_CMD_FT_EVENT, | ||
800 | |||
768 | /* add new commands above here */ | 801 | /* add new commands above here */ |
769 | 802 | ||
770 | /* used to define NL80211_CMD_MAX below */ | 803 | /* used to define NL80211_CMD_MAX below */ |
@@ -884,7 +917,8 @@ enum nl80211_commands { | |||
884 | * consisting of a nested array. | 917 | * consisting of a nested array. |
885 | * | 918 | * |
886 | * @NL80211_ATTR_MESH_ID: mesh id (1-32 bytes). | 919 | * @NL80211_ATTR_MESH_ID: mesh id (1-32 bytes). |
887 | * @NL80211_ATTR_STA_PLINK_ACTION: action to perform on the mesh peer link. | 920 | * @NL80211_ATTR_STA_PLINK_ACTION: action to perform on the mesh peer link |
921 | * (see &enum nl80211_plink_action). | ||
888 | * @NL80211_ATTR_MPATH_NEXT_HOP: MAC address of the next hop for a mesh path. | 922 | * @NL80211_ATTR_MPATH_NEXT_HOP: MAC address of the next hop for a mesh path. |
889 | * @NL80211_ATTR_MPATH_INFO: information about a mesh_path, part of mesh path | 923 | * @NL80211_ATTR_MPATH_INFO: information about a mesh_path, part of mesh path |
890 | * info given for %NL80211_CMD_GET_MPATH, nested attribute described at | 924 | * info given for %NL80211_CMD_GET_MPATH, nested attribute described at |
@@ -1167,10 +1201,10 @@ enum nl80211_commands { | |||
1167 | * @NL80211_ATTR_SUPPORT_MESH_AUTH: Currently, this means the underlying driver | 1201 | * @NL80211_ATTR_SUPPORT_MESH_AUTH: Currently, this means the underlying driver |
1168 | * allows auth frames in a mesh to be passed to userspace for processing via | 1202 | * allows auth frames in a mesh to be passed to userspace for processing via |
1169 | * the @NL80211_MESH_SETUP_USERSPACE_AUTH flag. | 1203 | * the @NL80211_MESH_SETUP_USERSPACE_AUTH flag. |
1170 | * @NL80211_ATTR_STA_PLINK_STATE: The state of a mesh peer link as | 1204 | * @NL80211_ATTR_STA_PLINK_STATE: The state of a mesh peer link as defined in |
1171 | * defined in &enum nl80211_plink_state. Used when userspace is | 1205 | * &enum nl80211_plink_state. Used when userspace is driving the peer link |
1172 | * driving the peer link management state machine. | 1206 | * management state machine. @NL80211_MESH_SETUP_USERSPACE_AMPE or |
1173 | * @NL80211_MESH_SETUP_USERSPACE_AMPE must be enabled. | 1207 | * @NL80211_MESH_SETUP_USERSPACE_MPM must be enabled. |
1174 | * | 1208 | * |
1175 | * @NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED: indicates, as part of the wiphy | 1209 | * @NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED: indicates, as part of the wiphy |
1176 | * capabilities, the supported WoWLAN triggers | 1210 | * capabilities, the supported WoWLAN triggers |
@@ -1368,6 +1402,18 @@ enum nl80211_commands { | |||
1368 | * advertised to the driver, e.g., to enable TDLS off channel operations | 1402 | * advertised to the driver, e.g., to enable TDLS off channel operations |
1369 | * and PU-APSD. | 1403 | * and PU-APSD. |
1370 | * | 1404 | * |
1405 | * @NL80211_ATTR_PROTOCOL_FEATURES: global nl80211 feature flags, see | ||
1406 | * &enum nl80211_protocol_features, the attribute is a u32. | ||
1407 | * | ||
1408 | * @NL80211_ATTR_SPLIT_WIPHY_DUMP: flag attribute, userspace supports | ||
1409 | * receiving the data for a single wiphy split across multiple | ||
1410 | * messages, given with wiphy dump message | ||
1411 | * | ||
1412 | * @NL80211_ATTR_MDID: Mobility Domain Identifier | ||
1413 | * | ||
1414 | * @NL80211_ATTR_IE_RIC: Resource Information Container Information | ||
1415 | * Element | ||
1416 | * | ||
1371 | * @NL80211_ATTR_MAX: highest attribute number currently defined | 1417 | * @NL80211_ATTR_MAX: highest attribute number currently defined |
1372 | * @__NL80211_ATTR_AFTER_LAST: internal use | 1418 | * @__NL80211_ATTR_AFTER_LAST: internal use |
1373 | */ | 1419 | */ |
@@ -1654,6 +1700,15 @@ enum nl80211_attrs { | |||
1654 | NL80211_ATTR_STA_CAPABILITY, | 1700 | NL80211_ATTR_STA_CAPABILITY, |
1655 | NL80211_ATTR_STA_EXT_CAPABILITY, | 1701 | NL80211_ATTR_STA_EXT_CAPABILITY, |
1656 | 1702 | ||
1703 | NL80211_ATTR_PROTOCOL_FEATURES, | ||
1704 | NL80211_ATTR_SPLIT_WIPHY_DUMP, | ||
1705 | |||
1706 | NL80211_ATTR_DISABLE_VHT, | ||
1707 | NL80211_ATTR_VHT_CAPABILITY_MASK, | ||
1708 | |||
1709 | NL80211_ATTR_MDID, | ||
1710 | NL80211_ATTR_IE_RIC, | ||
1711 | |||
1657 | /* add attributes here, update the policy in nl80211.c */ | 1712 | /* add attributes here, update the policy in nl80211.c */ |
1658 | 1713 | ||
1659 | __NL80211_ATTR_AFTER_LAST, | 1714 | __NL80211_ATTR_AFTER_LAST, |
@@ -2412,8 +2467,10 @@ enum nl80211_mesh_power_mode { | |||
2412 | * @NL80211_MESHCONF_TTL: specifies the value of TTL field set at a source mesh | 2467 | * @NL80211_MESHCONF_TTL: specifies the value of TTL field set at a source mesh |
2413 | * point. | 2468 | * point. |
2414 | * | 2469 | * |
2415 | * @NL80211_MESHCONF_AUTO_OPEN_PLINKS: whether we should automatically | 2470 | * @NL80211_MESHCONF_AUTO_OPEN_PLINKS: whether we should automatically open |
2416 | * open peer links when we detect compatible mesh peers. | 2471 | * peer links when we detect compatible mesh peers. Disabled if |
2472 | * @NL80211_MESH_SETUP_USERSPACE_MPM or @NL80211_MESH_SETUP_USERSPACE_AMPE are | ||
2473 | * set. | ||
2417 | * | 2474 | * |
2418 | * @NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES: the number of action frames | 2475 | * @NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES: the number of action frames |
2419 | * containing a PREQ that an MP can send to a particular destination (path | 2476 | * containing a PREQ that an MP can send to a particular destination (path |
@@ -2559,6 +2616,9 @@ enum nl80211_meshconf_params { | |||
2559 | * vendor specific synchronization method or disable it to use the default | 2616 | * vendor specific synchronization method or disable it to use the default |
2560 | * neighbor offset synchronization | 2617 | * neighbor offset synchronization |
2561 | * | 2618 | * |
2619 | * @NL80211_MESH_SETUP_USERSPACE_MPM: Enable this option if userspace will | ||
2620 | * implement an MPM which handles peer allocation and state. | ||
2621 | * | ||
2562 | * @NL80211_MESH_SETUP_ATTR_MAX: highest possible mesh setup attribute number | 2622 | * @NL80211_MESH_SETUP_ATTR_MAX: highest possible mesh setup attribute number |
2563 | * | 2623 | * |
2564 | * @__NL80211_MESH_SETUP_ATTR_AFTER_LAST: Internal use | 2624 | * @__NL80211_MESH_SETUP_ATTR_AFTER_LAST: Internal use |
@@ -2571,6 +2631,7 @@ enum nl80211_mesh_setup_params { | |||
2571 | NL80211_MESH_SETUP_USERSPACE_AUTH, | 2631 | NL80211_MESH_SETUP_USERSPACE_AUTH, |
2572 | NL80211_MESH_SETUP_USERSPACE_AMPE, | 2632 | NL80211_MESH_SETUP_USERSPACE_AMPE, |
2573 | NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC, | 2633 | NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC, |
2634 | NL80211_MESH_SETUP_USERSPACE_MPM, | ||
2574 | 2635 | ||
2575 | /* keep last */ | 2636 | /* keep last */ |
2576 | __NL80211_MESH_SETUP_ATTR_AFTER_LAST, | 2637 | __NL80211_MESH_SETUP_ATTR_AFTER_LAST, |
@@ -3307,6 +3368,23 @@ enum nl80211_plink_state { | |||
3307 | MAX_NL80211_PLINK_STATES = NUM_NL80211_PLINK_STATES - 1 | 3368 | MAX_NL80211_PLINK_STATES = NUM_NL80211_PLINK_STATES - 1 |
3308 | }; | 3369 | }; |
3309 | 3370 | ||
3371 | /** | ||
3372 | * enum nl80211_plink_action - actions to perform in mesh peers | ||
3373 | * | ||
3374 | * @NL80211_PLINK_ACTION_NO_ACTION: perform no action | ||
3375 | * @NL80211_PLINK_ACTION_OPEN: start mesh peer link establishment | ||
3376 | * @NL80211_PLINK_ACTION_BLOCK: block traffic from this mesh peer | ||
3377 | * @NUM_NL80211_PLINK_ACTIONS: number of possible actions | ||
3378 | */ | ||
3379 | enum plink_actions { | ||
3380 | NL80211_PLINK_ACTION_NO_ACTION, | ||
3381 | NL80211_PLINK_ACTION_OPEN, | ||
3382 | NL80211_PLINK_ACTION_BLOCK, | ||
3383 | |||
3384 | NUM_NL80211_PLINK_ACTIONS, | ||
3385 | }; | ||
3386 | |||
3387 | |||
3310 | #define NL80211_KCK_LEN 16 | 3388 | #define NL80211_KCK_LEN 16 |
3311 | #define NL80211_KEK_LEN 16 | 3389 | #define NL80211_KEK_LEN 16 |
3312 | #define NL80211_REPLAY_CTR_LEN 8 | 3390 | #define NL80211_REPLAY_CTR_LEN 8 |
@@ -3456,6 +3534,10 @@ enum nl80211_ap_sme_features { | |||
3456 | * stations the authenticated/associated bits have to be set in the mask. | 3534 | * stations the authenticated/associated bits have to be set in the mask. |
3457 | * @NL80211_FEATURE_ADVERTISE_CHAN_LIMITS: cfg80211 advertises channel limits | 3535 | * @NL80211_FEATURE_ADVERTISE_CHAN_LIMITS: cfg80211 advertises channel limits |
3458 | * (HT40, VHT 80/160 MHz) if this flag is set | 3536 | * (HT40, VHT 80/160 MHz) if this flag is set |
3537 | * @NL80211_FEATURE_USERSPACE_MPM: This driver supports a userspace Mesh | ||
3538 | * Peering Management entity which may be implemented by registering for | ||
3539 | * beacons or NL80211_CMD_NEW_PEER_CANDIDATE events. The mesh beacon is | ||
3540 | * still generated by the driver. | ||
3459 | */ | 3541 | */ |
3460 | enum nl80211_feature_flags { | 3542 | enum nl80211_feature_flags { |
3461 | NL80211_FEATURE_SK_TX_STATUS = 1 << 0, | 3543 | NL80211_FEATURE_SK_TX_STATUS = 1 << 0, |
@@ -3474,6 +3556,7 @@ enum nl80211_feature_flags { | |||
3474 | /* bit 13 is reserved */ | 3556 | /* bit 13 is reserved */ |
3475 | NL80211_FEATURE_ADVERTISE_CHAN_LIMITS = 1 << 14, | 3557 | NL80211_FEATURE_ADVERTISE_CHAN_LIMITS = 1 << 14, |
3476 | NL80211_FEATURE_FULL_AP_CLIENT_STATE = 1 << 15, | 3558 | NL80211_FEATURE_FULL_AP_CLIENT_STATE = 1 << 15, |
3559 | NL80211_FEATURE_USERSPACE_MPM = 1 << 16, | ||
3477 | }; | 3560 | }; |
3478 | 3561 | ||
3479 | /** | 3562 | /** |
@@ -3587,4 +3670,16 @@ enum nl80211_dfs_state { | |||
3587 | NL80211_DFS_AVAILABLE, | 3670 | NL80211_DFS_AVAILABLE, |
3588 | }; | 3671 | }; |
3589 | 3672 | ||
3673 | /** | ||
3674 | * enum enum nl80211_protocol_features - nl80211 protocol features | ||
3675 | * @NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP: nl80211 supports splitting | ||
3676 | * wiphy dumps (if requested by the application with the attribute | ||
3677 | * %NL80211_ATTR_SPLIT_WIPHY_DUMP. Also supported is filtering the | ||
3678 | * wiphy dump by %NL80211_ATTR_WIPHY, %NL80211_ATTR_IFINDEX or | ||
3679 | * %NL80211_ATTR_WDEV. | ||
3680 | */ | ||
3681 | enum nl80211_protocol_features { | ||
3682 | NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP = 1 << 0, | ||
3683 | }; | ||
3684 | |||
3590 | #endif /* __LINUX_NL80211_H */ | 3685 | #endif /* __LINUX_NL80211_H */ |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index fb306814576a..1d1ddabd89ca 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -254,7 +254,7 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, | |||
254 | goto out_unlock; | 254 | goto out_unlock; |
255 | } | 255 | } |
256 | 256 | ||
257 | __ieee80211_key_free(key); | 257 | __ieee80211_key_free(key, true); |
258 | 258 | ||
259 | ret = 0; | 259 | ret = 0; |
260 | out_unlock: | 260 | out_unlock: |
@@ -1035,9 +1035,12 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) | |||
1035 | sta_info_flush_defer(vlan); | 1035 | sta_info_flush_defer(vlan); |
1036 | sta_info_flush_defer(sdata); | 1036 | sta_info_flush_defer(sdata); |
1037 | rcu_barrier(); | 1037 | rcu_barrier(); |
1038 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) | 1038 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) { |
1039 | sta_info_flush_cleanup(vlan); | 1039 | sta_info_flush_cleanup(vlan); |
1040 | ieee80211_free_keys(vlan); | ||
1041 | } | ||
1040 | sta_info_flush_cleanup(sdata); | 1042 | sta_info_flush_cleanup(sdata); |
1043 | ieee80211_free_keys(sdata); | ||
1041 | 1044 | ||
1042 | sdata->vif.bss_conf.enable_beacon = false; | 1045 | sdata->vif.bss_conf.enable_beacon = false; |
1043 | clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state); | 1046 | clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state); |
@@ -1177,6 +1180,18 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
1177 | mask |= BIT(NL80211_STA_FLAG_ASSOCIATED); | 1180 | mask |= BIT(NL80211_STA_FLAG_ASSOCIATED); |
1178 | if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) | 1181 | if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) |
1179 | set |= BIT(NL80211_STA_FLAG_ASSOCIATED); | 1182 | set |= BIT(NL80211_STA_FLAG_ASSOCIATED); |
1183 | } else if (test_sta_flag(sta, WLAN_STA_TDLS_PEER)) { | ||
1184 | /* | ||
1185 | * TDLS -- everything follows authorized, but | ||
1186 | * only becoming authorized is possible, not | ||
1187 | * going back | ||
1188 | */ | ||
1189 | if (set & BIT(NL80211_STA_FLAG_AUTHORIZED)) { | ||
1190 | set |= BIT(NL80211_STA_FLAG_AUTHENTICATED) | | ||
1191 | BIT(NL80211_STA_FLAG_ASSOCIATED); | ||
1192 | mask |= BIT(NL80211_STA_FLAG_AUTHENTICATED) | | ||
1193 | BIT(NL80211_STA_FLAG_ASSOCIATED); | ||
1194 | } | ||
1180 | } | 1195 | } |
1181 | 1196 | ||
1182 | ret = sta_apply_auth_flags(local, sta, mask, set); | 1197 | ret = sta_apply_auth_flags(local, sta, mask, set); |
@@ -1261,7 +1276,8 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
1261 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | 1276 | if (ieee80211_vif_is_mesh(&sdata->vif)) { |
1262 | #ifdef CONFIG_MAC80211_MESH | 1277 | #ifdef CONFIG_MAC80211_MESH |
1263 | u32 changed = 0; | 1278 | u32 changed = 0; |
1264 | if (sdata->u.mesh.security & IEEE80211_MESH_SEC_SECURED) { | 1279 | |
1280 | if (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE) { | ||
1265 | switch (params->plink_state) { | 1281 | switch (params->plink_state) { |
1266 | case NL80211_PLINK_ESTAB: | 1282 | case NL80211_PLINK_ESTAB: |
1267 | if (sta->plink_state != NL80211_PLINK_ESTAB) | 1283 | if (sta->plink_state != NL80211_PLINK_ESTAB) |
@@ -1292,15 +1308,18 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
1292 | /* nothing */ | 1308 | /* nothing */ |
1293 | break; | 1309 | break; |
1294 | } | 1310 | } |
1295 | } else { | 1311 | } |
1296 | switch (params->plink_action) { | 1312 | |
1297 | case PLINK_ACTION_OPEN: | 1313 | switch (params->plink_action) { |
1298 | changed |= mesh_plink_open(sta); | 1314 | case NL80211_PLINK_ACTION_NO_ACTION: |
1299 | break; | 1315 | /* nothing */ |
1300 | case PLINK_ACTION_BLOCK: | 1316 | break; |
1301 | changed |= mesh_plink_block(sta); | 1317 | case NL80211_PLINK_ACTION_OPEN: |
1302 | break; | 1318 | changed |= mesh_plink_open(sta); |
1303 | } | 1319 | break; |
1320 | case NL80211_PLINK_ACTION_BLOCK: | ||
1321 | changed |= mesh_plink_block(sta); | ||
1322 | break; | ||
1304 | } | 1323 | } |
1305 | 1324 | ||
1306 | if (params->local_pm) | 1325 | if (params->local_pm) |
@@ -1346,8 +1365,10 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
1346 | * defaults -- if userspace wants something else we'll | 1365 | * defaults -- if userspace wants something else we'll |
1347 | * change it accordingly in sta_apply_parameters() | 1366 | * change it accordingly in sta_apply_parameters() |
1348 | */ | 1367 | */ |
1349 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); | 1368 | if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) { |
1350 | sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); | 1369 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); |
1370 | sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); | ||
1371 | } | ||
1351 | 1372 | ||
1352 | err = sta_apply_parameters(local, sta, params); | 1373 | err = sta_apply_parameters(local, sta, params); |
1353 | if (err) { | 1374 | if (err) { |
@@ -1356,8 +1377,8 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
1356 | } | 1377 | } |
1357 | 1378 | ||
1358 | /* | 1379 | /* |
1359 | * for TDLS, rate control should be initialized only when supported | 1380 | * for TDLS, rate control should be initialized only when |
1360 | * rates are known. | 1381 | * rates are known and station is marked authorized |
1361 | */ | 1382 | */ |
1362 | if (!test_sta_flag(sta, WLAN_STA_TDLS_PEER)) | 1383 | if (!test_sta_flag(sta, WLAN_STA_TDLS_PEER)) |
1363 | rate_control_rate_init(sta); | 1384 | rate_control_rate_init(sta); |
@@ -1394,50 +1415,67 @@ static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, | |||
1394 | } | 1415 | } |
1395 | 1416 | ||
1396 | static int ieee80211_change_station(struct wiphy *wiphy, | 1417 | static int ieee80211_change_station(struct wiphy *wiphy, |
1397 | struct net_device *dev, | 1418 | struct net_device *dev, u8 *mac, |
1398 | u8 *mac, | ||
1399 | struct station_parameters *params) | 1419 | struct station_parameters *params) |
1400 | { | 1420 | { |
1401 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1421 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1402 | struct ieee80211_local *local = wiphy_priv(wiphy); | 1422 | struct ieee80211_local *local = wiphy_priv(wiphy); |
1403 | struct sta_info *sta; | 1423 | struct sta_info *sta; |
1404 | struct ieee80211_sub_if_data *vlansdata; | 1424 | struct ieee80211_sub_if_data *vlansdata; |
1425 | enum cfg80211_station_type statype; | ||
1405 | int err; | 1426 | int err; |
1406 | 1427 | ||
1407 | mutex_lock(&local->sta_mtx); | 1428 | mutex_lock(&local->sta_mtx); |
1408 | 1429 | ||
1409 | sta = sta_info_get_bss(sdata, mac); | 1430 | sta = sta_info_get_bss(sdata, mac); |
1410 | if (!sta) { | 1431 | if (!sta) { |
1411 | mutex_unlock(&local->sta_mtx); | 1432 | err = -ENOENT; |
1412 | return -ENOENT; | 1433 | goto out_err; |
1413 | } | 1434 | } |
1414 | 1435 | ||
1415 | /* in station mode, some updates are only valid with TDLS */ | 1436 | switch (sdata->vif.type) { |
1416 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | 1437 | case NL80211_IFTYPE_MESH_POINT: |
1417 | (params->supported_rates || params->ht_capa || params->vht_capa || | 1438 | if (sdata->u.mesh.user_mpm) |
1418 | params->sta_modify_mask || | 1439 | statype = CFG80211_STA_MESH_PEER_USER; |
1419 | (params->sta_flags_mask & BIT(NL80211_STA_FLAG_WME))) && | 1440 | else |
1420 | !test_sta_flag(sta, WLAN_STA_TDLS_PEER)) { | 1441 | statype = CFG80211_STA_MESH_PEER_KERNEL; |
1421 | mutex_unlock(&local->sta_mtx); | 1442 | break; |
1422 | return -EINVAL; | 1443 | case NL80211_IFTYPE_ADHOC: |
1444 | statype = CFG80211_STA_IBSS; | ||
1445 | break; | ||
1446 | case NL80211_IFTYPE_STATION: | ||
1447 | if (!test_sta_flag(sta, WLAN_STA_TDLS_PEER)) { | ||
1448 | statype = CFG80211_STA_AP_STA; | ||
1449 | break; | ||
1450 | } | ||
1451 | if (test_sta_flag(sta, WLAN_STA_AUTHORIZED)) | ||
1452 | statype = CFG80211_STA_TDLS_PEER_ACTIVE; | ||
1453 | else | ||
1454 | statype = CFG80211_STA_TDLS_PEER_SETUP; | ||
1455 | break; | ||
1456 | case NL80211_IFTYPE_AP: | ||
1457 | case NL80211_IFTYPE_AP_VLAN: | ||
1458 | statype = CFG80211_STA_AP_CLIENT; | ||
1459 | break; | ||
1460 | default: | ||
1461 | err = -EOPNOTSUPP; | ||
1462 | goto out_err; | ||
1423 | } | 1463 | } |
1424 | 1464 | ||
1465 | err = cfg80211_check_station_change(wiphy, params, statype); | ||
1466 | if (err) | ||
1467 | goto out_err; | ||
1468 | |||
1425 | if (params->vlan && params->vlan != sta->sdata->dev) { | 1469 | if (params->vlan && params->vlan != sta->sdata->dev) { |
1426 | bool prev_4addr = false; | 1470 | bool prev_4addr = false; |
1427 | bool new_4addr = false; | 1471 | bool new_4addr = false; |
1428 | 1472 | ||
1429 | vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); | 1473 | vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); |
1430 | 1474 | ||
1431 | if (vlansdata->vif.type != NL80211_IFTYPE_AP_VLAN && | ||
1432 | vlansdata->vif.type != NL80211_IFTYPE_AP) { | ||
1433 | mutex_unlock(&local->sta_mtx); | ||
1434 | return -EINVAL; | ||
1435 | } | ||
1436 | |||
1437 | if (params->vlan->ieee80211_ptr->use_4addr) { | 1475 | if (params->vlan->ieee80211_ptr->use_4addr) { |
1438 | if (vlansdata->u.vlan.sta) { | 1476 | if (vlansdata->u.vlan.sta) { |
1439 | mutex_unlock(&local->sta_mtx); | 1477 | err = -EBUSY; |
1440 | return -EBUSY; | 1478 | goto out_err; |
1441 | } | 1479 | } |
1442 | 1480 | ||
1443 | rcu_assign_pointer(vlansdata->u.vlan.sta, sta); | 1481 | rcu_assign_pointer(vlansdata->u.vlan.sta, sta); |
@@ -1464,12 +1502,12 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
1464 | } | 1502 | } |
1465 | 1503 | ||
1466 | err = sta_apply_parameters(local, sta, params); | 1504 | err = sta_apply_parameters(local, sta, params); |
1467 | if (err) { | 1505 | if (err) |
1468 | mutex_unlock(&local->sta_mtx); | 1506 | goto out_err; |
1469 | return err; | ||
1470 | } | ||
1471 | 1507 | ||
1472 | if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) && params->supported_rates) | 1508 | /* When peer becomes authorized, init rate control as well */ |
1509 | if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) && | ||
1510 | test_sta_flag(sta, WLAN_STA_AUTHORIZED)) | ||
1473 | rate_control_rate_init(sta); | 1511 | rate_control_rate_init(sta); |
1474 | 1512 | ||
1475 | mutex_unlock(&local->sta_mtx); | 1513 | mutex_unlock(&local->sta_mtx); |
@@ -1479,7 +1517,11 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
1479 | ieee80211_recalc_ps(local, -1); | 1517 | ieee80211_recalc_ps(local, -1); |
1480 | ieee80211_recalc_ps_vif(sdata); | 1518 | ieee80211_recalc_ps_vif(sdata); |
1481 | } | 1519 | } |
1520 | |||
1482 | return 0; | 1521 | return 0; |
1522 | out_err: | ||
1523 | mutex_unlock(&local->sta_mtx); | ||
1524 | return err; | ||
1483 | } | 1525 | } |
1484 | 1526 | ||
1485 | #ifdef CONFIG_MAC80211_MESH | 1527 | #ifdef CONFIG_MAC80211_MESH |
@@ -1687,6 +1729,7 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh, | |||
1687 | ifmsh->mesh_sp_id = setup->sync_method; | 1729 | ifmsh->mesh_sp_id = setup->sync_method; |
1688 | ifmsh->mesh_pp_id = setup->path_sel_proto; | 1730 | ifmsh->mesh_pp_id = setup->path_sel_proto; |
1689 | ifmsh->mesh_pm_id = setup->path_metric; | 1731 | ifmsh->mesh_pm_id = setup->path_metric; |
1732 | ifmsh->user_mpm = setup->user_mpm; | ||
1690 | ifmsh->security = IEEE80211_MESH_SEC_NONE; | 1733 | ifmsh->security = IEEE80211_MESH_SEC_NONE; |
1691 | if (setup->is_authenticated) | 1734 | if (setup->is_authenticated) |
1692 | ifmsh->security |= IEEE80211_MESH_SEC_AUTHED; | 1735 | ifmsh->security |= IEEE80211_MESH_SEC_AUTHED; |
@@ -1730,8 +1773,11 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy, | |||
1730 | conf->dot11MeshTTL = nconf->dot11MeshTTL; | 1773 | conf->dot11MeshTTL = nconf->dot11MeshTTL; |
1731 | if (_chg_mesh_attr(NL80211_MESHCONF_ELEMENT_TTL, mask)) | 1774 | if (_chg_mesh_attr(NL80211_MESHCONF_ELEMENT_TTL, mask)) |
1732 | conf->element_ttl = nconf->element_ttl; | 1775 | conf->element_ttl = nconf->element_ttl; |
1733 | if (_chg_mesh_attr(NL80211_MESHCONF_AUTO_OPEN_PLINKS, mask)) | 1776 | if (_chg_mesh_attr(NL80211_MESHCONF_AUTO_OPEN_PLINKS, mask)) { |
1777 | if (ifmsh->user_mpm) | ||
1778 | return -EBUSY; | ||
1734 | conf->auto_open_plinks = nconf->auto_open_plinks; | 1779 | conf->auto_open_plinks = nconf->auto_open_plinks; |
1780 | } | ||
1735 | if (_chg_mesh_attr(NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR, mask)) | 1781 | if (_chg_mesh_attr(NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR, mask)) |
1736 | conf->dot11MeshNbrOffsetMaxNeighbor = | 1782 | conf->dot11MeshNbrOffsetMaxNeighbor = |
1737 | nconf->dot11MeshNbrOffsetMaxNeighbor; | 1783 | nconf->dot11MeshNbrOffsetMaxNeighbor; |
@@ -2371,7 +2417,8 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
2371 | struct ieee80211_sub_if_data *sdata, | 2417 | struct ieee80211_sub_if_data *sdata, |
2372 | struct ieee80211_channel *channel, | 2418 | struct ieee80211_channel *channel, |
2373 | unsigned int duration, u64 *cookie, | 2419 | unsigned int duration, u64 *cookie, |
2374 | struct sk_buff *txskb) | 2420 | struct sk_buff *txskb, |
2421 | enum ieee80211_roc_type type) | ||
2375 | { | 2422 | { |
2376 | struct ieee80211_roc_work *roc, *tmp; | 2423 | struct ieee80211_roc_work *roc, *tmp; |
2377 | bool queued = false; | 2424 | bool queued = false; |
@@ -2390,6 +2437,7 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
2390 | roc->duration = duration; | 2437 | roc->duration = duration; |
2391 | roc->req_duration = duration; | 2438 | roc->req_duration = duration; |
2392 | roc->frame = txskb; | 2439 | roc->frame = txskb; |
2440 | roc->type = type; | ||
2393 | roc->mgmt_tx_cookie = (unsigned long)txskb; | 2441 | roc->mgmt_tx_cookie = (unsigned long)txskb; |
2394 | roc->sdata = sdata; | 2442 | roc->sdata = sdata; |
2395 | INIT_DELAYED_WORK(&roc->work, ieee80211_sw_roc_work); | 2443 | INIT_DELAYED_WORK(&roc->work, ieee80211_sw_roc_work); |
@@ -2420,7 +2468,7 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
2420 | if (!duration) | 2468 | if (!duration) |
2421 | duration = 10; | 2469 | duration = 10; |
2422 | 2470 | ||
2423 | ret = drv_remain_on_channel(local, sdata, channel, duration); | 2471 | ret = drv_remain_on_channel(local, sdata, channel, duration, type); |
2424 | if (ret) { | 2472 | if (ret) { |
2425 | kfree(roc); | 2473 | kfree(roc); |
2426 | return ret; | 2474 | return ret; |
@@ -2439,10 +2487,13 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
2439 | * | 2487 | * |
2440 | * If it hasn't started yet, just increase the duration | 2488 | * If it hasn't started yet, just increase the duration |
2441 | * and add the new one to the list of dependents. | 2489 | * and add the new one to the list of dependents. |
2490 | * If the type of the new ROC has higher priority, modify the | ||
2491 | * type of the previous one to match that of the new one. | ||
2442 | */ | 2492 | */ |
2443 | if (!tmp->started) { | 2493 | if (!tmp->started) { |
2444 | list_add_tail(&roc->list, &tmp->dependents); | 2494 | list_add_tail(&roc->list, &tmp->dependents); |
2445 | tmp->duration = max(tmp->duration, roc->duration); | 2495 | tmp->duration = max(tmp->duration, roc->duration); |
2496 | tmp->type = max(tmp->type, roc->type); | ||
2446 | queued = true; | 2497 | queued = true; |
2447 | break; | 2498 | break; |
2448 | } | 2499 | } |
@@ -2454,16 +2505,18 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
2454 | /* | 2505 | /* |
2455 | * In the offloaded ROC case, if it hasn't begun, add | 2506 | * In the offloaded ROC case, if it hasn't begun, add |
2456 | * this new one to the dependent list to be handled | 2507 | * this new one to the dependent list to be handled |
2457 | * when the the master one begins. If it has begun, | 2508 | * when the master one begins. If it has begun, |
2458 | * check that there's still a minimum time left and | 2509 | * check that there's still a minimum time left and |
2459 | * if so, start this one, transmitting the frame, but | 2510 | * if so, start this one, transmitting the frame, but |
2460 | * add it to the list directly after this one with a | 2511 | * add it to the list directly after this one with |
2461 | * a reduced time so we'll ask the driver to execute | 2512 | * a reduced time so we'll ask the driver to execute |
2462 | * it right after finishing the previous one, in the | 2513 | * it right after finishing the previous one, in the |
2463 | * hope that it'll also be executed right afterwards, | 2514 | * hope that it'll also be executed right afterwards, |
2464 | * effectively extending the old one. | 2515 | * effectively extending the old one. |
2465 | * If there's no minimum time left, just add it to the | 2516 | * If there's no minimum time left, just add it to the |
2466 | * normal list. | 2517 | * normal list. |
2518 | * TODO: the ROC type is ignored here, assuming that it | ||
2519 | * is better to immediately use the current ROC. | ||
2467 | */ | 2520 | */ |
2468 | if (!tmp->hw_begun) { | 2521 | if (!tmp->hw_begun) { |
2469 | list_add_tail(&roc->list, &tmp->dependents); | 2522 | list_add_tail(&roc->list, &tmp->dependents); |
@@ -2557,7 +2610,8 @@ static int ieee80211_remain_on_channel(struct wiphy *wiphy, | |||
2557 | 2610 | ||
2558 | mutex_lock(&local->mtx); | 2611 | mutex_lock(&local->mtx); |
2559 | ret = ieee80211_start_roc_work(local, sdata, chan, | 2612 | ret = ieee80211_start_roc_work(local, sdata, chan, |
2560 | duration, cookie, NULL); | 2613 | duration, cookie, NULL, |
2614 | IEEE80211_ROC_TYPE_NORMAL); | ||
2561 | mutex_unlock(&local->mtx); | 2615 | mutex_unlock(&local->mtx); |
2562 | 2616 | ||
2563 | return ret; | 2617 | return ret; |
@@ -2790,7 +2844,8 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
2790 | 2844 | ||
2791 | /* This will handle all kinds of coalescing and immediate TX */ | 2845 | /* This will handle all kinds of coalescing and immediate TX */ |
2792 | ret = ieee80211_start_roc_work(local, sdata, chan, | 2846 | ret = ieee80211_start_roc_work(local, sdata, chan, |
2793 | wait, cookie, skb); | 2847 | wait, cookie, skb, |
2848 | IEEE80211_ROC_TYPE_MGMT_TX); | ||
2794 | if (ret) | 2849 | if (ret) |
2795 | kfree_skb(skb); | 2850 | kfree_skb(skb); |
2796 | out_unlock: | 2851 | out_unlock: |
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index c7591f73dbc3..4f841fe559df 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
@@ -325,6 +325,36 @@ static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf, | |||
325 | } | 325 | } |
326 | STA_OPS(ht_capa); | 326 | STA_OPS(ht_capa); |
327 | 327 | ||
328 | static ssize_t sta_vht_capa_read(struct file *file, char __user *userbuf, | ||
329 | size_t count, loff_t *ppos) | ||
330 | { | ||
331 | char buf[128], *p = buf; | ||
332 | struct sta_info *sta = file->private_data; | ||
333 | struct ieee80211_sta_vht_cap *vhtc = &sta->sta.vht_cap; | ||
334 | |||
335 | p += scnprintf(p, sizeof(buf) + buf - p, "VHT %ssupported\n", | ||
336 | vhtc->vht_supported ? "" : "not "); | ||
337 | if (vhtc->vht_supported) { | ||
338 | p += scnprintf(p, sizeof(buf)+buf-p, "cap: %#.8x\n", vhtc->cap); | ||
339 | |||
340 | p += scnprintf(p, sizeof(buf)+buf-p, "RX MCS: %.4x\n", | ||
341 | le16_to_cpu(vhtc->vht_mcs.rx_mcs_map)); | ||
342 | if (vhtc->vht_mcs.rx_highest) | ||
343 | p += scnprintf(p, sizeof(buf)+buf-p, | ||
344 | "MCS RX highest: %d Mbps\n", | ||
345 | le16_to_cpu(vhtc->vht_mcs.rx_highest)); | ||
346 | p += scnprintf(p, sizeof(buf)+buf-p, "TX MCS: %.4x\n", | ||
347 | le16_to_cpu(vhtc->vht_mcs.tx_mcs_map)); | ||
348 | if (vhtc->vht_mcs.tx_highest) | ||
349 | p += scnprintf(p, sizeof(buf)+buf-p, | ||
350 | "MCS TX highest: %d Mbps\n", | ||
351 | le16_to_cpu(vhtc->vht_mcs.tx_highest)); | ||
352 | } | ||
353 | |||
354 | return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf); | ||
355 | } | ||
356 | STA_OPS(vht_capa); | ||
357 | |||
328 | static ssize_t sta_current_tx_rate_read(struct file *file, char __user *userbuf, | 358 | static ssize_t sta_current_tx_rate_read(struct file *file, char __user *userbuf, |
329 | size_t count, loff_t *ppos) | 359 | size_t count, loff_t *ppos) |
330 | { | 360 | { |
@@ -405,6 +435,7 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta) | |||
405 | DEBUGFS_ADD(dev); | 435 | DEBUGFS_ADD(dev); |
406 | DEBUGFS_ADD(last_signal); | 436 | DEBUGFS_ADD(last_signal); |
407 | DEBUGFS_ADD(ht_capa); | 437 | DEBUGFS_ADD(ht_capa); |
438 | DEBUGFS_ADD(vht_capa); | ||
408 | DEBUGFS_ADD(last_ack_signal); | 439 | DEBUGFS_ADD(last_ack_signal); |
409 | DEBUGFS_ADD(current_tx_rate); | 440 | DEBUGFS_ADD(current_tx_rate); |
410 | DEBUGFS_ADD(last_rx_rate); | 441 | DEBUGFS_ADD(last_rx_rate); |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index ee56d0779d8b..832acea4a5cb 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -787,15 +787,16 @@ static inline int drv_get_antenna(struct ieee80211_local *local, | |||
787 | static inline int drv_remain_on_channel(struct ieee80211_local *local, | 787 | static inline int drv_remain_on_channel(struct ieee80211_local *local, |
788 | struct ieee80211_sub_if_data *sdata, | 788 | struct ieee80211_sub_if_data *sdata, |
789 | struct ieee80211_channel *chan, | 789 | struct ieee80211_channel *chan, |
790 | unsigned int duration) | 790 | unsigned int duration, |
791 | enum ieee80211_roc_type type) | ||
791 | { | 792 | { |
792 | int ret; | 793 | int ret; |
793 | 794 | ||
794 | might_sleep(); | 795 | might_sleep(); |
795 | 796 | ||
796 | trace_drv_remain_on_channel(local, sdata, chan, duration); | 797 | trace_drv_remain_on_channel(local, sdata, chan, duration, type); |
797 | ret = local->ops->remain_on_channel(&local->hw, &sdata->vif, | 798 | ret = local->ops->remain_on_channel(&local->hw, &sdata->vif, |
798 | chan, duration); | 799 | chan, duration, type); |
799 | trace_drv_return_int(local, ret); | 800 | trace_drv_return_int(local, ret); |
800 | 801 | ||
801 | return ret; | 802 | return ret; |
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 0db25d4bb223..af8cee06e4f3 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
@@ -40,13 +40,6 @@ void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata, | |||
40 | if (!ht_cap->ht_supported) | 40 | if (!ht_cap->ht_supported) |
41 | return; | 41 | return; |
42 | 42 | ||
43 | if (sdata->vif.type != NL80211_IFTYPE_STATION) { | ||
44 | /* AP interfaces call this code when adding new stations, | ||
45 | * so just silently ignore non station interfaces. | ||
46 | */ | ||
47 | return; | ||
48 | } | ||
49 | |||
50 | /* NOTE: If you add more over-rides here, update register_hw | 43 | /* NOTE: If you add more over-rides here, update register_hw |
51 | * ht_capa_mod_msk logic in main.c as well. | 44 | * ht_capa_mod_msk logic in main.c as well. |
52 | * And, if this method can ever change ht_cap.ht_supported, fix | 45 | * And, if this method can ever change ht_cap.ht_supported, fix |
@@ -97,7 +90,7 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata, | |||
97 | const struct ieee80211_ht_cap *ht_cap_ie, | 90 | const struct ieee80211_ht_cap *ht_cap_ie, |
98 | struct sta_info *sta) | 91 | struct sta_info *sta) |
99 | { | 92 | { |
100 | struct ieee80211_sta_ht_cap ht_cap; | 93 | struct ieee80211_sta_ht_cap ht_cap, own_cap; |
101 | u8 ampdu_info, tx_mcs_set_cap; | 94 | u8 ampdu_info, tx_mcs_set_cap; |
102 | int i, max_tx_streams; | 95 | int i, max_tx_streams; |
103 | bool changed; | 96 | bool changed; |
@@ -111,6 +104,18 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata, | |||
111 | 104 | ||
112 | ht_cap.ht_supported = true; | 105 | ht_cap.ht_supported = true; |
113 | 106 | ||
107 | own_cap = sband->ht_cap; | ||
108 | |||
109 | /* | ||
110 | * If user has specified capability over-rides, take care | ||
111 | * of that if the station we're setting up is the AP that | ||
112 | * we advertised a restricted capability set to. Override | ||
113 | * our own capabilities and then use those below. | ||
114 | */ | ||
115 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | ||
116 | !test_sta_flag(sta, WLAN_STA_TDLS_PEER)) | ||
117 | ieee80211_apply_htcap_overrides(sdata, &own_cap); | ||
118 | |||
114 | /* | 119 | /* |
115 | * The bits listed in this expression should be | 120 | * The bits listed in this expression should be |
116 | * the same for the peer and us, if the station | 121 | * the same for the peer and us, if the station |
@@ -118,21 +123,20 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata, | |||
118 | * we mask them out. | 123 | * we mask them out. |
119 | */ | 124 | */ |
120 | ht_cap.cap = le16_to_cpu(ht_cap_ie->cap_info) & | 125 | ht_cap.cap = le16_to_cpu(ht_cap_ie->cap_info) & |
121 | (sband->ht_cap.cap | | 126 | (own_cap.cap | ~(IEEE80211_HT_CAP_LDPC_CODING | |
122 | ~(IEEE80211_HT_CAP_LDPC_CODING | | 127 | IEEE80211_HT_CAP_SUP_WIDTH_20_40 | |
123 | IEEE80211_HT_CAP_SUP_WIDTH_20_40 | | 128 | IEEE80211_HT_CAP_GRN_FLD | |
124 | IEEE80211_HT_CAP_GRN_FLD | | 129 | IEEE80211_HT_CAP_SGI_20 | |
125 | IEEE80211_HT_CAP_SGI_20 | | 130 | IEEE80211_HT_CAP_SGI_40 | |
126 | IEEE80211_HT_CAP_SGI_40 | | 131 | IEEE80211_HT_CAP_DSSSCCK40)); |
127 | IEEE80211_HT_CAP_DSSSCCK40)); | ||
128 | 132 | ||
129 | /* | 133 | /* |
130 | * The STBC bits are asymmetric -- if we don't have | 134 | * The STBC bits are asymmetric -- if we don't have |
131 | * TX then mask out the peer's RX and vice versa. | 135 | * TX then mask out the peer's RX and vice versa. |
132 | */ | 136 | */ |
133 | if (!(sband->ht_cap.cap & IEEE80211_HT_CAP_TX_STBC)) | 137 | if (!(own_cap.cap & IEEE80211_HT_CAP_TX_STBC)) |
134 | ht_cap.cap &= ~IEEE80211_HT_CAP_RX_STBC; | 138 | ht_cap.cap &= ~IEEE80211_HT_CAP_RX_STBC; |
135 | if (!(sband->ht_cap.cap & IEEE80211_HT_CAP_RX_STBC)) | 139 | if (!(own_cap.cap & IEEE80211_HT_CAP_RX_STBC)) |
136 | ht_cap.cap &= ~IEEE80211_HT_CAP_TX_STBC; | 140 | ht_cap.cap &= ~IEEE80211_HT_CAP_TX_STBC; |
137 | 141 | ||
138 | ampdu_info = ht_cap_ie->ampdu_params_info; | 142 | ampdu_info = ht_cap_ie->ampdu_params_info; |
@@ -142,7 +146,7 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata, | |||
142 | (ampdu_info & IEEE80211_HT_AMPDU_PARM_DENSITY) >> 2; | 146 | (ampdu_info & IEEE80211_HT_AMPDU_PARM_DENSITY) >> 2; |
143 | 147 | ||
144 | /* own MCS TX capabilities */ | 148 | /* own MCS TX capabilities */ |
145 | tx_mcs_set_cap = sband->ht_cap.mcs.tx_params; | 149 | tx_mcs_set_cap = own_cap.mcs.tx_params; |
146 | 150 | ||
147 | /* Copy peer MCS TX capabilities, the driver might need them. */ | 151 | /* Copy peer MCS TX capabilities, the driver might need them. */ |
148 | ht_cap.mcs.tx_params = ht_cap_ie->mcs.tx_params; | 152 | ht_cap.mcs.tx_params = ht_cap_ie->mcs.tx_params; |
@@ -168,26 +172,20 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata, | |||
168 | */ | 172 | */ |
169 | for (i = 0; i < max_tx_streams; i++) | 173 | for (i = 0; i < max_tx_streams; i++) |
170 | ht_cap.mcs.rx_mask[i] = | 174 | ht_cap.mcs.rx_mask[i] = |
171 | sband->ht_cap.mcs.rx_mask[i] & ht_cap_ie->mcs.rx_mask[i]; | 175 | own_cap.mcs.rx_mask[i] & ht_cap_ie->mcs.rx_mask[i]; |
172 | 176 | ||
173 | if (tx_mcs_set_cap & IEEE80211_HT_MCS_TX_UNEQUAL_MODULATION) | 177 | if (tx_mcs_set_cap & IEEE80211_HT_MCS_TX_UNEQUAL_MODULATION) |
174 | for (i = IEEE80211_HT_MCS_UNEQUAL_MODULATION_START_BYTE; | 178 | for (i = IEEE80211_HT_MCS_UNEQUAL_MODULATION_START_BYTE; |
175 | i < IEEE80211_HT_MCS_MASK_LEN; i++) | 179 | i < IEEE80211_HT_MCS_MASK_LEN; i++) |
176 | ht_cap.mcs.rx_mask[i] = | 180 | ht_cap.mcs.rx_mask[i] = |
177 | sband->ht_cap.mcs.rx_mask[i] & | 181 | own_cap.mcs.rx_mask[i] & |
178 | ht_cap_ie->mcs.rx_mask[i]; | 182 | ht_cap_ie->mcs.rx_mask[i]; |
179 | 183 | ||
180 | /* handle MCS rate 32 too */ | 184 | /* handle MCS rate 32 too */ |
181 | if (sband->ht_cap.mcs.rx_mask[32/8] & ht_cap_ie->mcs.rx_mask[32/8] & 1) | 185 | if (own_cap.mcs.rx_mask[32/8] & ht_cap_ie->mcs.rx_mask[32/8] & 1) |
182 | ht_cap.mcs.rx_mask[32/8] |= 1; | 186 | ht_cap.mcs.rx_mask[32/8] |= 1; |
183 | 187 | ||
184 | apply: | 188 | apply: |
185 | /* | ||
186 | * If user has specified capability over-rides, take care | ||
187 | * of that here. | ||
188 | */ | ||
189 | ieee80211_apply_htcap_overrides(sdata, &ht_cap); | ||
190 | |||
191 | changed = memcmp(&sta->sta.ht_cap, &ht_cap, sizeof(ht_cap)); | 189 | changed = memcmp(&sta->sta.ht_cap, &ht_cap, sizeof(ht_cap)); |
192 | 190 | ||
193 | memcpy(&sta->sta.ht_cap, &ht_cap, sizeof(ht_cap)); | 191 | memcpy(&sta->sta.ht_cap, &ht_cap, sizeof(ht_cap)); |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 40b71dfcc79d..539d4a11b47b 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -985,36 +985,9 @@ static void ieee80211_ibss_timer(unsigned long data) | |||
985 | { | 985 | { |
986 | struct ieee80211_sub_if_data *sdata = | 986 | struct ieee80211_sub_if_data *sdata = |
987 | (struct ieee80211_sub_if_data *) data; | 987 | (struct ieee80211_sub_if_data *) data; |
988 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | ||
989 | struct ieee80211_local *local = sdata->local; | ||
990 | |||
991 | if (local->quiescing) { | ||
992 | ifibss->timer_running = true; | ||
993 | return; | ||
994 | } | ||
995 | |||
996 | ieee80211_queue_work(&local->hw, &sdata->work); | ||
997 | } | ||
998 | |||
999 | #ifdef CONFIG_PM | ||
1000 | void ieee80211_ibss_quiesce(struct ieee80211_sub_if_data *sdata) | ||
1001 | { | ||
1002 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | ||
1003 | 988 | ||
1004 | if (del_timer_sync(&ifibss->timer)) | 989 | ieee80211_queue_work(&sdata->local->hw, &sdata->work); |
1005 | ifibss->timer_running = true; | ||
1006 | } | ||
1007 | |||
1008 | void ieee80211_ibss_restart(struct ieee80211_sub_if_data *sdata) | ||
1009 | { | ||
1010 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | ||
1011 | |||
1012 | if (ifibss->timer_running) { | ||
1013 | add_timer(&ifibss->timer); | ||
1014 | ifibss->timer_running = false; | ||
1015 | } | ||
1016 | } | 990 | } |
1017 | #endif | ||
1018 | 991 | ||
1019 | void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata) | 992 | void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata) |
1020 | { | 993 | { |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 388580a1bada..f4433f081e77 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -315,6 +315,7 @@ struct ieee80211_roc_work { | |||
315 | u32 duration, req_duration; | 315 | u32 duration, req_duration; |
316 | struct sk_buff *frame; | 316 | struct sk_buff *frame; |
317 | u64 cookie, mgmt_tx_cookie; | 317 | u64 cookie, mgmt_tx_cookie; |
318 | enum ieee80211_roc_type type; | ||
318 | }; | 319 | }; |
319 | 320 | ||
320 | /* flags used in struct ieee80211_if_managed.flags */ | 321 | /* flags used in struct ieee80211_if_managed.flags */ |
@@ -400,7 +401,6 @@ struct ieee80211_if_managed { | |||
400 | 401 | ||
401 | u16 aid; | 402 | u16 aid; |
402 | 403 | ||
403 | unsigned long timers_running; /* used for quiesce/restart */ | ||
404 | bool powersave; /* powersave requested for this iface */ | 404 | bool powersave; /* powersave requested for this iface */ |
405 | bool broken_ap; /* AP is broken -- turn off powersave */ | 405 | bool broken_ap; /* AP is broken -- turn off powersave */ |
406 | u8 dtim_period; | 406 | u8 dtim_period; |
@@ -479,6 +479,8 @@ struct ieee80211_if_managed { | |||
479 | 479 | ||
480 | struct ieee80211_ht_cap ht_capa; /* configured ht-cap over-rides */ | 480 | struct ieee80211_ht_cap ht_capa; /* configured ht-cap over-rides */ |
481 | struct ieee80211_ht_cap ht_capa_mask; /* Valid parts of ht_capa */ | 481 | struct ieee80211_ht_cap ht_capa_mask; /* Valid parts of ht_capa */ |
482 | struct ieee80211_vht_cap vht_capa; /* configured VHT overrides */ | ||
483 | struct ieee80211_vht_cap vht_capa_mask; /* Valid parts of vht_capa */ | ||
482 | }; | 484 | }; |
483 | 485 | ||
484 | struct ieee80211_if_ibss { | 486 | struct ieee80211_if_ibss { |
@@ -490,8 +492,6 @@ struct ieee80211_if_ibss { | |||
490 | 492 | ||
491 | u32 basic_rates; | 493 | u32 basic_rates; |
492 | 494 | ||
493 | bool timer_running; | ||
494 | |||
495 | bool fixed_bssid; | 495 | bool fixed_bssid; |
496 | bool fixed_channel; | 496 | bool fixed_channel; |
497 | bool privacy; | 497 | bool privacy; |
@@ -543,8 +543,6 @@ struct ieee80211_if_mesh { | |||
543 | struct timer_list mesh_path_timer; | 543 | struct timer_list mesh_path_timer; |
544 | struct timer_list mesh_path_root_timer; | 544 | struct timer_list mesh_path_root_timer; |
545 | 545 | ||
546 | unsigned long timers_running; | ||
547 | |||
548 | unsigned long wrkq_flags; | 546 | unsigned long wrkq_flags; |
549 | 547 | ||
550 | u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN]; | 548 | u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN]; |
@@ -590,6 +588,7 @@ struct ieee80211_if_mesh { | |||
590 | IEEE80211_MESH_SEC_AUTHED = 0x1, | 588 | IEEE80211_MESH_SEC_AUTHED = 0x1, |
591 | IEEE80211_MESH_SEC_SECURED = 0x2, | 589 | IEEE80211_MESH_SEC_SECURED = 0x2, |
592 | } security; | 590 | } security; |
591 | bool user_mpm; | ||
593 | /* Extensible Synchronization Framework */ | 592 | /* Extensible Synchronization Framework */ |
594 | const struct ieee80211_mesh_sync_ops *sync_ops; | 593 | const struct ieee80211_mesh_sync_ops *sync_ops; |
595 | s64 sync_offset_clockdrift_max; | 594 | s64 sync_offset_clockdrift_max; |
@@ -682,6 +681,8 @@ struct ieee80211_sub_if_data { | |||
682 | 681 | ||
683 | /* count for keys needing tailroom space allocation */ | 682 | /* count for keys needing tailroom space allocation */ |
684 | int crypto_tx_tailroom_needed_cnt; | 683 | int crypto_tx_tailroom_needed_cnt; |
684 | int crypto_tx_tailroom_pending_dec; | ||
685 | struct delayed_work dec_tailroom_needed_wk; | ||
685 | 686 | ||
686 | struct net_device *dev; | 687 | struct net_device *dev; |
687 | struct ieee80211_local *local; | 688 | struct ieee80211_local *local; |
@@ -765,10 +766,6 @@ struct ieee80211_sub_if_data { | |||
765 | } debugfs; | 766 | } debugfs; |
766 | #endif | 767 | #endif |
767 | 768 | ||
768 | #ifdef CONFIG_PM | ||
769 | struct ieee80211_bss_conf suspend_bss_conf; | ||
770 | #endif | ||
771 | |||
772 | /* must be last, dynamically sized area in this! */ | 769 | /* must be last, dynamically sized area in this! */ |
773 | struct ieee80211_vif vif; | 770 | struct ieee80211_vif vif; |
774 | }; | 771 | }; |
@@ -1136,11 +1133,6 @@ struct ieee80211_local { | |||
1136 | 1133 | ||
1137 | struct ieee80211_sub_if_data __rcu *p2p_sdata; | 1134 | struct ieee80211_sub_if_data __rcu *p2p_sdata; |
1138 | 1135 | ||
1139 | /* dummy netdev for use w/ NAPI */ | ||
1140 | struct net_device napi_dev; | ||
1141 | |||
1142 | struct napi_struct napi; | ||
1143 | |||
1144 | /* virtual monitor interface */ | 1136 | /* virtual monitor interface */ |
1145 | struct ieee80211_sub_if_data __rcu *monitor_sdata; | 1137 | struct ieee80211_sub_if_data __rcu *monitor_sdata; |
1146 | struct cfg80211_chan_def monitor_chandef; | 1138 | struct cfg80211_chan_def monitor_chandef; |
@@ -1283,8 +1275,6 @@ void | |||
1283 | ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | 1275 | ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, |
1284 | const struct ieee80211_channel_sw_ie *sw_elem, | 1276 | const struct ieee80211_channel_sw_ie *sw_elem, |
1285 | struct ieee80211_bss *bss, u64 timestamp); | 1277 | struct ieee80211_bss *bss, u64 timestamp); |
1286 | void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata); | ||
1287 | void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata); | ||
1288 | void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata); | 1278 | void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata); |
1289 | void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | 1279 | void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, |
1290 | struct sk_buff *skb); | 1280 | struct sk_buff *skb); |
@@ -1302,8 +1292,6 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata, | |||
1302 | int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | 1292 | int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, |
1303 | struct cfg80211_ibss_params *params); | 1293 | struct cfg80211_ibss_params *params); |
1304 | int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata); | 1294 | int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata); |
1305 | void ieee80211_ibss_quiesce(struct ieee80211_sub_if_data *sdata); | ||
1306 | void ieee80211_ibss_restart(struct ieee80211_sub_if_data *sdata); | ||
1307 | void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata); | 1295 | void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata); |
1308 | void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | 1296 | void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, |
1309 | struct sk_buff *skb); | 1297 | struct sk_buff *skb); |
@@ -1441,6 +1429,8 @@ void ieee80211_sta_set_rx_nss(struct sta_info *sta); | |||
1441 | void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, | 1429 | void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, |
1442 | struct sta_info *sta, u8 opmode, | 1430 | struct sta_info *sta, u8 opmode, |
1443 | enum ieee80211_band band, bool nss_only); | 1431 | enum ieee80211_band band, bool nss_only); |
1432 | void ieee80211_apply_vhtcap_overrides(struct ieee80211_sub_if_data *sdata, | ||
1433 | struct ieee80211_sta_vht_cap *vht_cap); | ||
1444 | 1434 | ||
1445 | /* Spectrum management */ | 1435 | /* Spectrum management */ |
1446 | void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, | 1436 | void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index baaa8608e52d..d85282f64405 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -485,8 +485,6 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) | |||
485 | res = drv_start(local); | 485 | res = drv_start(local); |
486 | if (res) | 486 | if (res) |
487 | goto err_del_bss; | 487 | goto err_del_bss; |
488 | if (local->ops->napi_poll) | ||
489 | napi_enable(&local->napi); | ||
490 | /* we're brought up, everything changes */ | 488 | /* we're brought up, everything changes */ |
491 | hw_reconf_flags = ~0; | 489 | hw_reconf_flags = ~0; |
492 | ieee80211_led_radio(local, true); | 490 | ieee80211_led_radio(local, true); |
@@ -838,14 +836,16 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
838 | rcu_barrier(); | 836 | rcu_barrier(); |
839 | sta_info_flush_cleanup(sdata); | 837 | sta_info_flush_cleanup(sdata); |
840 | 838 | ||
841 | skb_queue_purge(&sdata->skb_queue); | ||
842 | |||
843 | /* | 839 | /* |
844 | * Free all remaining keys, there shouldn't be any, | 840 | * Free all remaining keys, there shouldn't be any, |
845 | * except maybe group keys in AP more or WDS? | 841 | * except maybe in WDS mode? |
846 | */ | 842 | */ |
847 | ieee80211_free_keys(sdata); | 843 | ieee80211_free_keys(sdata); |
848 | 844 | ||
845 | /* fall through */ | ||
846 | case NL80211_IFTYPE_AP: | ||
847 | skb_queue_purge(&sdata->skb_queue); | ||
848 | |||
849 | drv_remove_interface_debugfs(local, sdata); | 849 | drv_remove_interface_debugfs(local, sdata); |
850 | 850 | ||
851 | if (going_down) | 851 | if (going_down) |
@@ -857,8 +857,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
857 | ieee80211_recalc_ps(local, -1); | 857 | ieee80211_recalc_ps(local, -1); |
858 | 858 | ||
859 | if (local->open_count == 0) { | 859 | if (local->open_count == 0) { |
860 | if (local->ops->napi_poll) | ||
861 | napi_disable(&local->napi); | ||
862 | ieee80211_clear_tx_pending(local); | 860 | ieee80211_clear_tx_pending(local); |
863 | ieee80211_stop_device(local); | 861 | ieee80211_stop_device(local); |
864 | 862 | ||
@@ -1547,6 +1545,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1547 | INIT_WORK(&sdata->cleanup_stations_wk, ieee80211_cleanup_sdata_stas_wk); | 1545 | INIT_WORK(&sdata->cleanup_stations_wk, ieee80211_cleanup_sdata_stas_wk); |
1548 | INIT_DELAYED_WORK(&sdata->dfs_cac_timer_work, | 1546 | INIT_DELAYED_WORK(&sdata->dfs_cac_timer_work, |
1549 | ieee80211_dfs_cac_timer_work); | 1547 | ieee80211_dfs_cac_timer_work); |
1548 | INIT_DELAYED_WORK(&sdata->dec_tailroom_needed_wk, | ||
1549 | ieee80211_delayed_tailroom_dec); | ||
1550 | 1550 | ||
1551 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { | 1551 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { |
1552 | struct ieee80211_supported_band *sband; | 1552 | struct ieee80211_supported_band *sband; |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index ef252eb58c36..99e9f6ae6a54 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -397,7 +397,8 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, | |||
397 | return key; | 397 | return key; |
398 | } | 398 | } |
399 | 399 | ||
400 | static void __ieee80211_key_destroy(struct ieee80211_key *key) | 400 | static void __ieee80211_key_destroy(struct ieee80211_key *key, |
401 | bool delay_tailroom) | ||
401 | { | 402 | { |
402 | if (!key) | 403 | if (!key) |
403 | return; | 404 | return; |
@@ -416,8 +417,18 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key) | |||
416 | if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC) | 417 | if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC) |
417 | ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm); | 418 | ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm); |
418 | if (key->local) { | 419 | if (key->local) { |
420 | struct ieee80211_sub_if_data *sdata = key->sdata; | ||
421 | |||
419 | ieee80211_debugfs_key_remove(key); | 422 | ieee80211_debugfs_key_remove(key); |
420 | key->sdata->crypto_tx_tailroom_needed_cnt--; | 423 | |
424 | if (delay_tailroom) { | ||
425 | /* see ieee80211_delayed_tailroom_dec */ | ||
426 | sdata->crypto_tx_tailroom_pending_dec++; | ||
427 | schedule_delayed_work(&sdata->dec_tailroom_needed_wk, | ||
428 | HZ/2); | ||
429 | } else { | ||
430 | sdata->crypto_tx_tailroom_needed_cnt--; | ||
431 | } | ||
421 | } | 432 | } |
422 | 433 | ||
423 | kfree(key); | 434 | kfree(key); |
@@ -440,32 +451,6 @@ int ieee80211_key_link(struct ieee80211_key *key, | |||
440 | key->sdata = sdata; | 451 | key->sdata = sdata; |
441 | key->sta = sta; | 452 | key->sta = sta; |
442 | 453 | ||
443 | if (sta) { | ||
444 | /* | ||
445 | * some hardware cannot handle TKIP with QoS, so | ||
446 | * we indicate whether QoS could be in use. | ||
447 | */ | ||
448 | if (test_sta_flag(sta, WLAN_STA_WME)) | ||
449 | key->conf.flags |= IEEE80211_KEY_FLAG_WMM_STA; | ||
450 | } else { | ||
451 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
452 | struct sta_info *ap; | ||
453 | |||
454 | /* | ||
455 | * We're getting a sta pointer in, so must be under | ||
456 | * appropriate locking for sta_info_get(). | ||
457 | */ | ||
458 | |||
459 | /* same here, the AP could be using QoS */ | ||
460 | ap = sta_info_get(key->sdata, key->sdata->u.mgd.bssid); | ||
461 | if (ap) { | ||
462 | if (test_sta_flag(ap, WLAN_STA_WME)) | ||
463 | key->conf.flags |= | ||
464 | IEEE80211_KEY_FLAG_WMM_STA; | ||
465 | } | ||
466 | } | ||
467 | } | ||
468 | |||
469 | mutex_lock(&sdata->local->key_mtx); | 454 | mutex_lock(&sdata->local->key_mtx); |
470 | 455 | ||
471 | if (sta && pairwise) | 456 | if (sta && pairwise) |
@@ -478,7 +463,7 @@ int ieee80211_key_link(struct ieee80211_key *key, | |||
478 | increment_tailroom_need_count(sdata); | 463 | increment_tailroom_need_count(sdata); |
479 | 464 | ||
480 | __ieee80211_key_replace(sdata, sta, pairwise, old_key, key); | 465 | __ieee80211_key_replace(sdata, sta, pairwise, old_key, key); |
481 | __ieee80211_key_destroy(old_key); | 466 | __ieee80211_key_destroy(old_key, true); |
482 | 467 | ||
483 | ieee80211_debugfs_key_add(key); | 468 | ieee80211_debugfs_key_add(key); |
484 | 469 | ||
@@ -489,7 +474,7 @@ int ieee80211_key_link(struct ieee80211_key *key, | |||
489 | return ret; | 474 | return ret; |
490 | } | 475 | } |
491 | 476 | ||
492 | void __ieee80211_key_free(struct ieee80211_key *key) | 477 | void __ieee80211_key_free(struct ieee80211_key *key, bool delay_tailroom) |
493 | { | 478 | { |
494 | if (!key) | 479 | if (!key) |
495 | return; | 480 | return; |
@@ -501,14 +486,14 @@ void __ieee80211_key_free(struct ieee80211_key *key) | |||
501 | __ieee80211_key_replace(key->sdata, key->sta, | 486 | __ieee80211_key_replace(key->sdata, key->sta, |
502 | key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE, | 487 | key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE, |
503 | key, NULL); | 488 | key, NULL); |
504 | __ieee80211_key_destroy(key); | 489 | __ieee80211_key_destroy(key, delay_tailroom); |
505 | } | 490 | } |
506 | 491 | ||
507 | void ieee80211_key_free(struct ieee80211_local *local, | 492 | void ieee80211_key_free(struct ieee80211_local *local, |
508 | struct ieee80211_key *key) | 493 | struct ieee80211_key *key) |
509 | { | 494 | { |
510 | mutex_lock(&local->key_mtx); | 495 | mutex_lock(&local->key_mtx); |
511 | __ieee80211_key_free(key); | 496 | __ieee80211_key_free(key, true); |
512 | mutex_unlock(&local->key_mtx); | 497 | mutex_unlock(&local->key_mtx); |
513 | } | 498 | } |
514 | 499 | ||
@@ -566,36 +551,60 @@ void ieee80211_iter_keys(struct ieee80211_hw *hw, | |||
566 | } | 551 | } |
567 | EXPORT_SYMBOL(ieee80211_iter_keys); | 552 | EXPORT_SYMBOL(ieee80211_iter_keys); |
568 | 553 | ||
569 | void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata) | ||
570 | { | ||
571 | struct ieee80211_key *key; | ||
572 | |||
573 | ASSERT_RTNL(); | ||
574 | |||
575 | mutex_lock(&sdata->local->key_mtx); | ||
576 | |||
577 | list_for_each_entry(key, &sdata->key_list, list) | ||
578 | ieee80211_key_disable_hw_accel(key); | ||
579 | |||
580 | mutex_unlock(&sdata->local->key_mtx); | ||
581 | } | ||
582 | |||
583 | void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata) | 554 | void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata) |
584 | { | 555 | { |
585 | struct ieee80211_key *key, *tmp; | 556 | struct ieee80211_key *key, *tmp; |
586 | 557 | ||
558 | cancel_delayed_work_sync(&sdata->dec_tailroom_needed_wk); | ||
559 | |||
587 | mutex_lock(&sdata->local->key_mtx); | 560 | mutex_lock(&sdata->local->key_mtx); |
588 | 561 | ||
562 | sdata->crypto_tx_tailroom_needed_cnt -= | ||
563 | sdata->crypto_tx_tailroom_pending_dec; | ||
564 | sdata->crypto_tx_tailroom_pending_dec = 0; | ||
565 | |||
589 | ieee80211_debugfs_key_remove_mgmt_default(sdata); | 566 | ieee80211_debugfs_key_remove_mgmt_default(sdata); |
590 | 567 | ||
591 | list_for_each_entry_safe(key, tmp, &sdata->key_list, list) | 568 | list_for_each_entry_safe(key, tmp, &sdata->key_list, list) |
592 | __ieee80211_key_free(key); | 569 | __ieee80211_key_free(key, false); |
593 | 570 | ||
594 | ieee80211_debugfs_key_update_default(sdata); | 571 | ieee80211_debugfs_key_update_default(sdata); |
595 | 572 | ||
573 | WARN_ON_ONCE(sdata->crypto_tx_tailroom_needed_cnt || | ||
574 | sdata->crypto_tx_tailroom_pending_dec); | ||
575 | |||
596 | mutex_unlock(&sdata->local->key_mtx); | 576 | mutex_unlock(&sdata->local->key_mtx); |
597 | } | 577 | } |
598 | 578 | ||
579 | void ieee80211_delayed_tailroom_dec(struct work_struct *wk) | ||
580 | { | ||
581 | struct ieee80211_sub_if_data *sdata; | ||
582 | |||
583 | sdata = container_of(wk, struct ieee80211_sub_if_data, | ||
584 | dec_tailroom_needed_wk.work); | ||
585 | |||
586 | /* | ||
587 | * The reason for the delayed tailroom needed decrementing is to | ||
588 | * make roaming faster: during roaming, all keys are first deleted | ||
589 | * and then new keys are installed. The first new key causes the | ||
590 | * crypto_tx_tailroom_needed_cnt to go from 0 to 1, which invokes | ||
591 | * the cost of synchronize_net() (which can be slow). Avoid this | ||
592 | * by deferring the crypto_tx_tailroom_needed_cnt decrementing on | ||
593 | * key removal for a while, so if we roam the value is larger than | ||
594 | * zero and no 0->1 transition happens. | ||
595 | * | ||
596 | * The cost is that if the AP switching was from an AP with keys | ||
597 | * to one without, we still allocate tailroom while it would no | ||
598 | * longer be needed. However, in the typical (fast) roaming case | ||
599 | * within an ESS this usually won't happen. | ||
600 | */ | ||
601 | |||
602 | mutex_lock(&sdata->local->key_mtx); | ||
603 | sdata->crypto_tx_tailroom_needed_cnt -= | ||
604 | sdata->crypto_tx_tailroom_pending_dec; | ||
605 | sdata->crypto_tx_tailroom_pending_dec = 0; | ||
606 | mutex_unlock(&sdata->local->key_mtx); | ||
607 | } | ||
599 | 608 | ||
600 | void ieee80211_gtk_rekey_notify(struct ieee80211_vif *vif, const u8 *bssid, | 609 | void ieee80211_gtk_rekey_notify(struct ieee80211_vif *vif, const u8 *bssid, |
601 | const u8 *replay_ctr, gfp_t gfp) | 610 | const u8 *replay_ctr, gfp_t gfp) |
diff --git a/net/mac80211/key.h b/net/mac80211/key.h index 382dc44ed330..2a682d81cee9 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h | |||
@@ -134,7 +134,7 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, | |||
134 | int __must_check ieee80211_key_link(struct ieee80211_key *key, | 134 | int __must_check ieee80211_key_link(struct ieee80211_key *key, |
135 | struct ieee80211_sub_if_data *sdata, | 135 | struct ieee80211_sub_if_data *sdata, |
136 | struct sta_info *sta); | 136 | struct sta_info *sta); |
137 | void __ieee80211_key_free(struct ieee80211_key *key); | 137 | void __ieee80211_key_free(struct ieee80211_key *key, bool delay_tailroom); |
138 | void ieee80211_key_free(struct ieee80211_local *local, | 138 | void ieee80211_key_free(struct ieee80211_local *local, |
139 | struct ieee80211_key *key); | 139 | struct ieee80211_key *key); |
140 | void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx, | 140 | void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx, |
@@ -143,9 +143,10 @@ void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, | |||
143 | int idx); | 143 | int idx); |
144 | void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata); | 144 | void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata); |
145 | void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata); | 145 | void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata); |
146 | void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata); | ||
147 | 146 | ||
148 | #define key_mtx_dereference(local, ref) \ | 147 | #define key_mtx_dereference(local, ref) \ |
149 | rcu_dereference_protected(ref, lockdep_is_held(&((local)->key_mtx))) | 148 | rcu_dereference_protected(ref, lockdep_is_held(&((local)->key_mtx))) |
150 | 149 | ||
150 | void ieee80211_delayed_tailroom_dec(struct work_struct *wk); | ||
151 | |||
151 | #endif /* IEEE80211_KEY_H */ | 152 | #endif /* IEEE80211_KEY_H */ |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 1a8591b77a13..5a53aa5ede80 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -399,30 +399,6 @@ static int ieee80211_ifa6_changed(struct notifier_block *nb, | |||
399 | } | 399 | } |
400 | #endif | 400 | #endif |
401 | 401 | ||
402 | static int ieee80211_napi_poll(struct napi_struct *napi, int budget) | ||
403 | { | ||
404 | struct ieee80211_local *local = | ||
405 | container_of(napi, struct ieee80211_local, napi); | ||
406 | |||
407 | return local->ops->napi_poll(&local->hw, budget); | ||
408 | } | ||
409 | |||
410 | void ieee80211_napi_schedule(struct ieee80211_hw *hw) | ||
411 | { | ||
412 | struct ieee80211_local *local = hw_to_local(hw); | ||
413 | |||
414 | napi_schedule(&local->napi); | ||
415 | } | ||
416 | EXPORT_SYMBOL(ieee80211_napi_schedule); | ||
417 | |||
418 | void ieee80211_napi_complete(struct ieee80211_hw *hw) | ||
419 | { | ||
420 | struct ieee80211_local *local = hw_to_local(hw); | ||
421 | |||
422 | napi_complete(&local->napi); | ||
423 | } | ||
424 | EXPORT_SYMBOL(ieee80211_napi_complete); | ||
425 | |||
426 | /* There isn't a lot of sense in it, but you can transmit anything you like */ | 402 | /* There isn't a lot of sense in it, but you can transmit anything you like */ |
427 | static const struct ieee80211_txrx_stypes | 403 | static const struct ieee80211_txrx_stypes |
428 | ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { | 404 | ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { |
@@ -501,6 +477,27 @@ static const struct ieee80211_ht_cap mac80211_ht_capa_mod_mask = { | |||
501 | }, | 477 | }, |
502 | }; | 478 | }; |
503 | 479 | ||
480 | static const struct ieee80211_vht_cap mac80211_vht_capa_mod_mask = { | ||
481 | .vht_cap_info = | ||
482 | cpu_to_le32(IEEE80211_VHT_CAP_RXLDPC | | ||
483 | IEEE80211_VHT_CAP_SHORT_GI_80 | | ||
484 | IEEE80211_VHT_CAP_SHORT_GI_160 | | ||
485 | IEEE80211_VHT_CAP_RXSTBC_1 | | ||
486 | IEEE80211_VHT_CAP_RXSTBC_2 | | ||
487 | IEEE80211_VHT_CAP_RXSTBC_3 | | ||
488 | IEEE80211_VHT_CAP_RXSTBC_4 | | ||
489 | IEEE80211_VHT_CAP_TXSTBC | | ||
490 | IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE | | ||
491 | IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | | ||
492 | IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN | | ||
493 | IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN | | ||
494 | IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK), | ||
495 | .supp_mcs = { | ||
496 | .rx_mcs_map = cpu_to_le16(~0), | ||
497 | .tx_mcs_map = cpu_to_le16(~0), | ||
498 | }, | ||
499 | }; | ||
500 | |||
504 | static const u8 extended_capabilities[] = { | 501 | static const u8 extended_capabilities[] = { |
505 | 0, 0, 0, 0, 0, 0, 0, | 502 | 0, 0, 0, 0, 0, 0, 0, |
506 | WLAN_EXT_CAPA8_OPMODE_NOTIF, | 503 | WLAN_EXT_CAPA8_OPMODE_NOTIF, |
@@ -572,7 +569,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
572 | wiphy->features |= NL80211_FEATURE_SK_TX_STATUS | | 569 | wiphy->features |= NL80211_FEATURE_SK_TX_STATUS | |
573 | NL80211_FEATURE_SAE | | 570 | NL80211_FEATURE_SAE | |
574 | NL80211_FEATURE_HT_IBSS | | 571 | NL80211_FEATURE_HT_IBSS | |
575 | NL80211_FEATURE_VIF_TXPOWER; | 572 | NL80211_FEATURE_VIF_TXPOWER | |
573 | NL80211_FEATURE_USERSPACE_MPM; | ||
576 | 574 | ||
577 | if (!ops->hw_scan) | 575 | if (!ops->hw_scan) |
578 | wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN | | 576 | wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN | |
@@ -609,6 +607,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
609 | IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH; | 607 | IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH; |
610 | local->user_power_level = IEEE80211_UNSET_POWER_LEVEL; | 608 | local->user_power_level = IEEE80211_UNSET_POWER_LEVEL; |
611 | wiphy->ht_capa_mod_mask = &mac80211_ht_capa_mod_mask; | 609 | wiphy->ht_capa_mod_mask = &mac80211_ht_capa_mod_mask; |
610 | wiphy->vht_capa_mod_mask = &mac80211_vht_capa_mod_mask; | ||
612 | 611 | ||
613 | INIT_LIST_HEAD(&local->interfaces); | 612 | INIT_LIST_HEAD(&local->interfaces); |
614 | 613 | ||
@@ -664,9 +663,6 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
664 | skb_queue_head_init(&local->skb_queue); | 663 | skb_queue_head_init(&local->skb_queue); |
665 | skb_queue_head_init(&local->skb_queue_unreliable); | 664 | skb_queue_head_init(&local->skb_queue_unreliable); |
666 | 665 | ||
667 | /* init dummy netdev for use w/ NAPI */ | ||
668 | init_dummy_netdev(&local->napi_dev); | ||
669 | |||
670 | ieee80211_led_names(local); | 666 | ieee80211_led_names(local); |
671 | 667 | ||
672 | ieee80211_roc_setup(local); | 668 | ieee80211_roc_setup(local); |
@@ -1021,9 +1017,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1021 | goto fail_ifa6; | 1017 | goto fail_ifa6; |
1022 | #endif | 1018 | #endif |
1023 | 1019 | ||
1024 | netif_napi_add(&local->napi_dev, &local->napi, ieee80211_napi_poll, | ||
1025 | local->hw.napi_weight); | ||
1026 | |||
1027 | return 0; | 1020 | return 0; |
1028 | 1021 | ||
1029 | #if IS_ENABLED(CONFIG_IPV6) | 1022 | #if IS_ENABLED(CONFIG_IPV6) |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 29ce2aa87e7b..5ac017f3fcd2 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -13,10 +13,6 @@ | |||
13 | #include "ieee80211_i.h" | 13 | #include "ieee80211_i.h" |
14 | #include "mesh.h" | 14 | #include "mesh.h" |
15 | 15 | ||
16 | #define TMR_RUNNING_HK 0 | ||
17 | #define TMR_RUNNING_MP 1 | ||
18 | #define TMR_RUNNING_MPR 2 | ||
19 | |||
20 | static int mesh_allocated; | 16 | static int mesh_allocated; |
21 | static struct kmem_cache *rm_cache; | 17 | static struct kmem_cache *rm_cache; |
22 | 18 | ||
@@ -50,11 +46,6 @@ static void ieee80211_mesh_housekeeping_timer(unsigned long data) | |||
50 | 46 | ||
51 | set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags); | 47 | set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags); |
52 | 48 | ||
53 | if (local->quiescing) { | ||
54 | set_bit(TMR_RUNNING_HK, &ifmsh->timers_running); | ||
55 | return; | ||
56 | } | ||
57 | |||
58 | ieee80211_queue_work(&local->hw, &sdata->work); | 49 | ieee80211_queue_work(&local->hw, &sdata->work); |
59 | } | 50 | } |
60 | 51 | ||
@@ -165,7 +156,7 @@ void mesh_sta_cleanup(struct sta_info *sta) | |||
165 | * an update. | 156 | * an update. |
166 | */ | 157 | */ |
167 | changed = mesh_accept_plinks_update(sdata); | 158 | changed = mesh_accept_plinks_update(sdata); |
168 | if (sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) { | 159 | if (!sdata->u.mesh.user_mpm) { |
169 | changed |= mesh_plink_deactivate(sta); | 160 | changed |= mesh_plink_deactivate(sta); |
170 | del_timer_sync(&sta->plink_timer); | 161 | del_timer_sync(&sta->plink_timer); |
171 | } | 162 | } |
@@ -479,15 +470,8 @@ static void ieee80211_mesh_path_timer(unsigned long data) | |||
479 | { | 470 | { |
480 | struct ieee80211_sub_if_data *sdata = | 471 | struct ieee80211_sub_if_data *sdata = |
481 | (struct ieee80211_sub_if_data *) data; | 472 | (struct ieee80211_sub_if_data *) data; |
482 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
483 | struct ieee80211_local *local = sdata->local; | ||
484 | |||
485 | if (local->quiescing) { | ||
486 | set_bit(TMR_RUNNING_MP, &ifmsh->timers_running); | ||
487 | return; | ||
488 | } | ||
489 | 473 | ||
490 | ieee80211_queue_work(&local->hw, &sdata->work); | 474 | ieee80211_queue_work(&sdata->local->hw, &sdata->work); |
491 | } | 475 | } |
492 | 476 | ||
493 | static void ieee80211_mesh_path_root_timer(unsigned long data) | 477 | static void ieee80211_mesh_path_root_timer(unsigned long data) |
@@ -495,16 +479,10 @@ static void ieee80211_mesh_path_root_timer(unsigned long data) | |||
495 | struct ieee80211_sub_if_data *sdata = | 479 | struct ieee80211_sub_if_data *sdata = |
496 | (struct ieee80211_sub_if_data *) data; | 480 | (struct ieee80211_sub_if_data *) data; |
497 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 481 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
498 | struct ieee80211_local *local = sdata->local; | ||
499 | 482 | ||
500 | set_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags); | 483 | set_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags); |
501 | 484 | ||
502 | if (local->quiescing) { | 485 | ieee80211_queue_work(&sdata->local->hw, &sdata->work); |
503 | set_bit(TMR_RUNNING_MPR, &ifmsh->timers_running); | ||
504 | return; | ||
505 | } | ||
506 | |||
507 | ieee80211_queue_work(&local->hw, &sdata->work); | ||
508 | } | 486 | } |
509 | 487 | ||
510 | void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh) | 488 | void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh) |
@@ -622,35 +600,6 @@ static void ieee80211_mesh_rootpath(struct ieee80211_sub_if_data *sdata) | |||
622 | round_jiffies(TU_TO_EXP_TIME(interval))); | 600 | round_jiffies(TU_TO_EXP_TIME(interval))); |
623 | } | 601 | } |
624 | 602 | ||
625 | #ifdef CONFIG_PM | ||
626 | void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata) | ||
627 | { | ||
628 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
629 | |||
630 | /* use atomic bitops in case all timers fire at the same time */ | ||
631 | |||
632 | if (del_timer_sync(&ifmsh->housekeeping_timer)) | ||
633 | set_bit(TMR_RUNNING_HK, &ifmsh->timers_running); | ||
634 | if (del_timer_sync(&ifmsh->mesh_path_timer)) | ||
635 | set_bit(TMR_RUNNING_MP, &ifmsh->timers_running); | ||
636 | if (del_timer_sync(&ifmsh->mesh_path_root_timer)) | ||
637 | set_bit(TMR_RUNNING_MPR, &ifmsh->timers_running); | ||
638 | } | ||
639 | |||
640 | void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata) | ||
641 | { | ||
642 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
643 | |||
644 | if (test_and_clear_bit(TMR_RUNNING_HK, &ifmsh->timers_running)) | ||
645 | add_timer(&ifmsh->housekeeping_timer); | ||
646 | if (test_and_clear_bit(TMR_RUNNING_MP, &ifmsh->timers_running)) | ||
647 | add_timer(&ifmsh->mesh_path_timer); | ||
648 | if (test_and_clear_bit(TMR_RUNNING_MPR, &ifmsh->timers_running)) | ||
649 | add_timer(&ifmsh->mesh_path_root_timer); | ||
650 | ieee80211_mesh_root_setup(ifmsh); | ||
651 | } | ||
652 | #endif | ||
653 | |||
654 | static int | 603 | static int |
655 | ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh) | 604 | ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh) |
656 | { | 605 | { |
@@ -871,8 +820,6 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) | |||
871 | local->fif_other_bss--; | 820 | local->fif_other_bss--; |
872 | atomic_dec(&local->iff_allmultis); | 821 | atomic_dec(&local->iff_allmultis); |
873 | ieee80211_configure_filter(local); | 822 | ieee80211_configure_filter(local); |
874 | |||
875 | sdata->u.mesh.timers_running = 0; | ||
876 | } | 823 | } |
877 | 824 | ||
878 | static void | 825 | static void |
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 336c88a16687..6ffabbe99c46 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
@@ -313,8 +313,6 @@ void mesh_path_timer(unsigned long data); | |||
313 | void mesh_path_flush_by_nexthop(struct sta_info *sta); | 313 | void mesh_path_flush_by_nexthop(struct sta_info *sta); |
314 | void mesh_path_discard_frame(struct ieee80211_sub_if_data *sdata, | 314 | void mesh_path_discard_frame(struct ieee80211_sub_if_data *sdata, |
315 | struct sk_buff *skb); | 315 | struct sk_buff *skb); |
316 | void mesh_path_quiesce(struct ieee80211_sub_if_data *sdata); | ||
317 | void mesh_path_restart(struct ieee80211_sub_if_data *sdata); | ||
318 | void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata); | 316 | void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata); |
319 | 317 | ||
320 | bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt); | 318 | bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt); |
@@ -359,22 +357,12 @@ static inline bool mesh_path_sel_is_hwmp(struct ieee80211_sub_if_data *sdata) | |||
359 | 357 | ||
360 | void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local); | 358 | void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local); |
361 | 359 | ||
362 | void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata); | ||
363 | void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata); | ||
364 | void mesh_plink_quiesce(struct sta_info *sta); | ||
365 | void mesh_plink_restart(struct sta_info *sta); | ||
366 | void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata); | 360 | void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata); |
367 | void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata); | 361 | void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata); |
368 | void ieee80211s_stop(void); | 362 | void ieee80211s_stop(void); |
369 | #else | 363 | #else |
370 | static inline void | 364 | static inline void |
371 | ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) {} | 365 | ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) {} |
372 | static inline void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata) | ||
373 | {} | ||
374 | static inline void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata) | ||
375 | {} | ||
376 | static inline void mesh_plink_quiesce(struct sta_info *sta) {} | ||
377 | static inline void mesh_plink_restart(struct sta_info *sta) {} | ||
378 | static inline bool mesh_path_sel_is_hwmp(struct ieee80211_sub_if_data *sdata) | 366 | static inline bool mesh_path_sel_is_hwmp(struct ieee80211_sub_if_data *sdata) |
379 | { return false; } | 367 | { return false; } |
380 | static inline void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata) | 368 | static inline void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata) |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 07d396d57079..937e06fe8f2a 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -420,7 +420,6 @@ __mesh_sta_info_alloc(struct ieee80211_sub_if_data *sdata, u8 *hw_addr) | |||
420 | return NULL; | 420 | return NULL; |
421 | 421 | ||
422 | sta->plink_state = NL80211_PLINK_LISTEN; | 422 | sta->plink_state = NL80211_PLINK_LISTEN; |
423 | init_timer(&sta->plink_timer); | ||
424 | 423 | ||
425 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); | 424 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); |
426 | sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); | 425 | sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); |
@@ -437,8 +436,9 @@ mesh_sta_info_alloc(struct ieee80211_sub_if_data *sdata, u8 *addr, | |||
437 | { | 436 | { |
438 | struct sta_info *sta = NULL; | 437 | struct sta_info *sta = NULL; |
439 | 438 | ||
440 | /* Userspace handles peer allocation when security is enabled */ | 439 | /* Userspace handles station allocation */ |
441 | if (sdata->u.mesh.security & IEEE80211_MESH_SEC_AUTHED) | 440 | if (sdata->u.mesh.user_mpm || |
441 | sdata->u.mesh.security & IEEE80211_MESH_SEC_AUTHED) | ||
442 | cfg80211_notify_new_peer_candidate(sdata->dev, addr, | 442 | cfg80211_notify_new_peer_candidate(sdata->dev, addr, |
443 | elems->ie_start, | 443 | elems->ie_start, |
444 | elems->total_len, | 444 | elems->total_len, |
@@ -534,10 +534,8 @@ static void mesh_plink_timer(unsigned long data) | |||
534 | */ | 534 | */ |
535 | sta = (struct sta_info *) data; | 535 | sta = (struct sta_info *) data; |
536 | 536 | ||
537 | if (sta->sdata->local->quiescing) { | 537 | if (sta->sdata->local->quiescing) |
538 | sta->plink_timer_was_running = true; | ||
539 | return; | 538 | return; |
540 | } | ||
541 | 539 | ||
542 | spin_lock_bh(&sta->lock); | 540 | spin_lock_bh(&sta->lock); |
543 | if (sta->ignore_plink_timer) { | 541 | if (sta->ignore_plink_timer) { |
@@ -598,29 +596,6 @@ static void mesh_plink_timer(unsigned long data) | |||
598 | } | 596 | } |
599 | } | 597 | } |
600 | 598 | ||
601 | #ifdef CONFIG_PM | ||
602 | void mesh_plink_quiesce(struct sta_info *sta) | ||
603 | { | ||
604 | if (!ieee80211_vif_is_mesh(&sta->sdata->vif)) | ||
605 | return; | ||
606 | |||
607 | /* no kernel mesh sta timers have been initialized */ | ||
608 | if (sta->sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE) | ||
609 | return; | ||
610 | |||
611 | if (del_timer_sync(&sta->plink_timer)) | ||
612 | sta->plink_timer_was_running = true; | ||
613 | } | ||
614 | |||
615 | void mesh_plink_restart(struct sta_info *sta) | ||
616 | { | ||
617 | if (sta->plink_timer_was_running) { | ||
618 | add_timer(&sta->plink_timer); | ||
619 | sta->plink_timer_was_running = false; | ||
620 | } | ||
621 | } | ||
622 | #endif | ||
623 | |||
624 | static inline void mesh_plink_timer_set(struct sta_info *sta, int timeout) | 599 | static inline void mesh_plink_timer_set(struct sta_info *sta, int timeout) |
625 | { | 600 | { |
626 | sta->plink_timer.expires = jiffies + (HZ * timeout / 1000); | 601 | sta->plink_timer.expires = jiffies + (HZ * timeout / 1000); |
@@ -695,6 +670,10 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, | |||
695 | if (len < IEEE80211_MIN_ACTION_SIZE + 3) | 670 | if (len < IEEE80211_MIN_ACTION_SIZE + 3) |
696 | return; | 671 | return; |
697 | 672 | ||
673 | if (sdata->u.mesh.user_mpm) | ||
674 | /* userspace must register for these */ | ||
675 | return; | ||
676 | |||
698 | if (is_multicast_ether_addr(mgmt->da)) { | 677 | if (is_multicast_ether_addr(mgmt->da)) { |
699 | mpl_dbg(sdata, | 678 | mpl_dbg(sdata, |
700 | "Mesh plink: ignore frame from multicast address\n"); | 679 | "Mesh plink: ignore frame from multicast address\n"); |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 141577412d84..fdc06e381c10 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -87,9 +87,6 @@ MODULE_PARM_DESC(probe_wait_ms, | |||
87 | */ | 87 | */ |
88 | #define IEEE80211_SIGNAL_AVE_MIN_COUNT 4 | 88 | #define IEEE80211_SIGNAL_AVE_MIN_COUNT 4 |
89 | 89 | ||
90 | #define TMR_RUNNING_TIMER 0 | ||
91 | #define TMR_RUNNING_CHANSW 1 | ||
92 | |||
93 | /* | 90 | /* |
94 | * All cfg80211 functions have to be called outside a locked | 91 | * All cfg80211 functions have to be called outside a locked |
95 | * section so that they can acquire a lock themselves... This | 92 | * section so that they can acquire a lock themselves... This |
@@ -609,6 +606,7 @@ static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata, | |||
609 | BUILD_BUG_ON(sizeof(vht_cap) != sizeof(sband->vht_cap)); | 606 | BUILD_BUG_ON(sizeof(vht_cap) != sizeof(sband->vht_cap)); |
610 | 607 | ||
611 | memcpy(&vht_cap, &sband->vht_cap, sizeof(vht_cap)); | 608 | memcpy(&vht_cap, &sband->vht_cap, sizeof(vht_cap)); |
609 | ieee80211_apply_vhtcap_overrides(sdata, &vht_cap); | ||
612 | 610 | ||
613 | /* determine capability flags */ | 611 | /* determine capability flags */ |
614 | cap = vht_cap.cap; | 612 | cap = vht_cap.cap; |
@@ -1038,14 +1036,8 @@ static void ieee80211_chswitch_timer(unsigned long data) | |||
1038 | { | 1036 | { |
1039 | struct ieee80211_sub_if_data *sdata = | 1037 | struct ieee80211_sub_if_data *sdata = |
1040 | (struct ieee80211_sub_if_data *) data; | 1038 | (struct ieee80211_sub_if_data *) data; |
1041 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
1042 | 1039 | ||
1043 | if (sdata->local->quiescing) { | 1040 | ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.chswitch_work); |
1044 | set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running); | ||
1045 | return; | ||
1046 | } | ||
1047 | |||
1048 | ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work); | ||
1049 | } | 1041 | } |
1050 | 1042 | ||
1051 | void | 1043 | void |
@@ -1802,9 +1794,11 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1802 | sdata->vif.bss_conf.p2p_ctwindow = 0; | 1794 | sdata->vif.bss_conf.p2p_ctwindow = 0; |
1803 | sdata->vif.bss_conf.p2p_oppps = false; | 1795 | sdata->vif.bss_conf.p2p_oppps = false; |
1804 | 1796 | ||
1805 | /* on the next assoc, re-program HT parameters */ | 1797 | /* on the next assoc, re-program HT/VHT parameters */ |
1806 | memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa)); | 1798 | memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa)); |
1807 | memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask)); | 1799 | memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask)); |
1800 | memset(&ifmgd->vht_capa, 0, sizeof(ifmgd->vht_capa)); | ||
1801 | memset(&ifmgd->vht_capa_mask, 0, sizeof(ifmgd->vht_capa_mask)); | ||
1808 | 1802 | ||
1809 | sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL; | 1803 | sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL; |
1810 | 1804 | ||
@@ -1830,8 +1824,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1830 | del_timer_sync(&sdata->u.mgd.timer); | 1824 | del_timer_sync(&sdata->u.mgd.timer); |
1831 | del_timer_sync(&sdata->u.mgd.chswitch_timer); | 1825 | del_timer_sync(&sdata->u.mgd.chswitch_timer); |
1832 | 1826 | ||
1833 | sdata->u.mgd.timers_running = 0; | ||
1834 | |||
1835 | sdata->vif.bss_conf.dtim_period = 0; | 1827 | sdata->vif.bss_conf.dtim_period = 0; |
1836 | 1828 | ||
1837 | ifmgd->flags = 0; | 1829 | ifmgd->flags = 0; |
@@ -3140,15 +3132,8 @@ static void ieee80211_sta_timer(unsigned long data) | |||
3140 | { | 3132 | { |
3141 | struct ieee80211_sub_if_data *sdata = | 3133 | struct ieee80211_sub_if_data *sdata = |
3142 | (struct ieee80211_sub_if_data *) data; | 3134 | (struct ieee80211_sub_if_data *) data; |
3143 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
3144 | struct ieee80211_local *local = sdata->local; | ||
3145 | |||
3146 | if (local->quiescing) { | ||
3147 | set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running); | ||
3148 | return; | ||
3149 | } | ||
3150 | 3135 | ||
3151 | ieee80211_queue_work(&local->hw, &sdata->work); | 3136 | ieee80211_queue_work(&sdata->local->hw, &sdata->work); |
3152 | } | 3137 | } |
3153 | 3138 | ||
3154 | static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata, | 3139 | static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata, |
@@ -3500,72 +3485,6 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) | |||
3500 | } | 3485 | } |
3501 | } | 3486 | } |
3502 | 3487 | ||
3503 | #ifdef CONFIG_PM | ||
3504 | void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata) | ||
3505 | { | ||
3506 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
3507 | |||
3508 | /* | ||
3509 | * Stop timers before deleting work items, as timers | ||
3510 | * could race and re-add the work-items. They will be | ||
3511 | * re-established on connection. | ||
3512 | */ | ||
3513 | del_timer_sync(&ifmgd->conn_mon_timer); | ||
3514 | del_timer_sync(&ifmgd->bcn_mon_timer); | ||
3515 | |||
3516 | /* | ||
3517 | * we need to use atomic bitops for the running bits | ||
3518 | * only because both timers might fire at the same | ||
3519 | * time -- the code here is properly synchronised. | ||
3520 | */ | ||
3521 | |||
3522 | cancel_work_sync(&ifmgd->request_smps_work); | ||
3523 | |||
3524 | cancel_work_sync(&ifmgd->monitor_work); | ||
3525 | cancel_work_sync(&ifmgd->beacon_connection_loss_work); | ||
3526 | cancel_work_sync(&ifmgd->csa_connection_drop_work); | ||
3527 | if (del_timer_sync(&ifmgd->timer)) | ||
3528 | set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running); | ||
3529 | |||
3530 | if (del_timer_sync(&ifmgd->chswitch_timer)) | ||
3531 | set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running); | ||
3532 | cancel_work_sync(&ifmgd->chswitch_work); | ||
3533 | } | ||
3534 | |||
3535 | void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata) | ||
3536 | { | ||
3537 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
3538 | |||
3539 | mutex_lock(&ifmgd->mtx); | ||
3540 | if (!ifmgd->associated) { | ||
3541 | mutex_unlock(&ifmgd->mtx); | ||
3542 | return; | ||
3543 | } | ||
3544 | |||
3545 | if (sdata->flags & IEEE80211_SDATA_DISCONNECT_RESUME) { | ||
3546 | sdata->flags &= ~IEEE80211_SDATA_DISCONNECT_RESUME; | ||
3547 | mlme_dbg(sdata, "driver requested disconnect after resume\n"); | ||
3548 | ieee80211_sta_connection_lost(sdata, | ||
3549 | ifmgd->associated->bssid, | ||
3550 | WLAN_REASON_UNSPECIFIED, | ||
3551 | true); | ||
3552 | mutex_unlock(&ifmgd->mtx); | ||
3553 | return; | ||
3554 | } | ||
3555 | mutex_unlock(&ifmgd->mtx); | ||
3556 | |||
3557 | if (test_and_clear_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running)) | ||
3558 | add_timer(&ifmgd->timer); | ||
3559 | if (test_and_clear_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running)) | ||
3560 | add_timer(&ifmgd->chswitch_timer); | ||
3561 | ieee80211_sta_reset_beacon_monitor(sdata); | ||
3562 | |||
3563 | mutex_lock(&sdata->local->mtx); | ||
3564 | ieee80211_restart_sta_timer(sdata); | ||
3565 | mutex_unlock(&sdata->local->mtx); | ||
3566 | } | ||
3567 | #endif | ||
3568 | |||
3569 | /* interface setup */ | 3488 | /* interface setup */ |
3570 | void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) | 3489 | void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) |
3571 | { | 3490 | { |
@@ -4071,6 +3990,9 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
4071 | ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; | 3990 | ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; |
4072 | } | 3991 | } |
4073 | 3992 | ||
3993 | if (req->flags & ASSOC_REQ_DISABLE_VHT) | ||
3994 | ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; | ||
3995 | |||
4074 | /* Also disable HT if we don't support it or the AP doesn't use WMM */ | 3996 | /* Also disable HT if we don't support it or the AP doesn't use WMM */ |
4075 | sband = local->hw.wiphy->bands[req->bss->channel->band]; | 3997 | sband = local->hw.wiphy->bands[req->bss->channel->band]; |
4076 | if (!sband->ht_cap.ht_supported || | 3998 | if (!sband->ht_cap.ht_supported || |
@@ -4094,6 +4016,10 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
4094 | memcpy(&ifmgd->ht_capa_mask, &req->ht_capa_mask, | 4016 | memcpy(&ifmgd->ht_capa_mask, &req->ht_capa_mask, |
4095 | sizeof(ifmgd->ht_capa_mask)); | 4017 | sizeof(ifmgd->ht_capa_mask)); |
4096 | 4018 | ||
4019 | memcpy(&ifmgd->vht_capa, &req->vht_capa, sizeof(ifmgd->vht_capa)); | ||
4020 | memcpy(&ifmgd->vht_capa_mask, &req->vht_capa_mask, | ||
4021 | sizeof(ifmgd->vht_capa_mask)); | ||
4022 | |||
4097 | if (req->ie && req->ie_len) { | 4023 | if (req->ie && req->ie_len) { |
4098 | memcpy(assoc_data->ie, req->ie, req->ie_len); | 4024 | memcpy(assoc_data->ie, req->ie, req->ie_len); |
4099 | assoc_data->ie_len = req->ie_len; | 4025 | assoc_data->ie_len = req->ie_len; |
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index cc79b4a2e821..db547fceaeb9 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c | |||
@@ -277,7 +277,7 @@ void ieee80211_start_next_roc(struct ieee80211_local *local) | |||
277 | duration = 10; | 277 | duration = 10; |
278 | 278 | ||
279 | ret = drv_remain_on_channel(local, roc->sdata, roc->chan, | 279 | ret = drv_remain_on_channel(local, roc->sdata, roc->chan, |
280 | duration); | 280 | duration, roc->type); |
281 | 281 | ||
282 | roc->started = true; | 282 | roc->started = true; |
283 | 283 | ||
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index d0275f34bf70..b471a67f224d 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
@@ -6,32 +6,11 @@ | |||
6 | #include "driver-ops.h" | 6 | #include "driver-ops.h" |
7 | #include "led.h" | 7 | #include "led.h" |
8 | 8 | ||
9 | /* return value indicates whether the driver should be further notified */ | ||
10 | static void ieee80211_quiesce(struct ieee80211_sub_if_data *sdata) | ||
11 | { | ||
12 | switch (sdata->vif.type) { | ||
13 | case NL80211_IFTYPE_STATION: | ||
14 | ieee80211_sta_quiesce(sdata); | ||
15 | break; | ||
16 | case NL80211_IFTYPE_ADHOC: | ||
17 | ieee80211_ibss_quiesce(sdata); | ||
18 | break; | ||
19 | case NL80211_IFTYPE_MESH_POINT: | ||
20 | ieee80211_mesh_quiesce(sdata); | ||
21 | break; | ||
22 | default: | ||
23 | break; | ||
24 | } | ||
25 | |||
26 | cancel_work_sync(&sdata->work); | ||
27 | } | ||
28 | |||
29 | int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | 9 | int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) |
30 | { | 10 | { |
31 | struct ieee80211_local *local = hw_to_local(hw); | 11 | struct ieee80211_local *local = hw_to_local(hw); |
32 | struct ieee80211_sub_if_data *sdata; | 12 | struct ieee80211_sub_if_data *sdata; |
33 | struct sta_info *sta; | 13 | struct sta_info *sta; |
34 | struct ieee80211_chanctx *ctx; | ||
35 | 14 | ||
36 | if (!local->open_count) | 15 | if (!local->open_count) |
37 | goto suspend; | 16 | goto suspend; |
@@ -93,19 +72,12 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
93 | return err; | 72 | return err; |
94 | } else if (err > 0) { | 73 | } else if (err > 0) { |
95 | WARN_ON(err != 1); | 74 | WARN_ON(err != 1); |
96 | local->wowlan = false; | 75 | return err; |
97 | } else { | 76 | } else { |
98 | list_for_each_entry(sdata, &local->interfaces, list) | ||
99 | if (ieee80211_sdata_running(sdata)) | ||
100 | ieee80211_quiesce(sdata); | ||
101 | goto suspend; | 77 | goto suspend; |
102 | } | 78 | } |
103 | } | 79 | } |
104 | 80 | ||
105 | /* disable keys */ | ||
106 | list_for_each_entry(sdata, &local->interfaces, list) | ||
107 | ieee80211_disable_keys(sdata); | ||
108 | |||
109 | /* tear down aggregation sessions and remove STAs */ | 81 | /* tear down aggregation sessions and remove STAs */ |
110 | mutex_lock(&local->sta_mtx); | 82 | mutex_lock(&local->sta_mtx); |
111 | list_for_each_entry(sta, &local->sta_list, list) { | 83 | list_for_each_entry(sta, &local->sta_list, list) { |
@@ -117,100 +89,25 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
117 | WARN_ON(drv_sta_state(local, sta->sdata, sta, | 89 | WARN_ON(drv_sta_state(local, sta->sdata, sta, |
118 | state, state - 1)); | 90 | state, state - 1)); |
119 | } | 91 | } |
120 | |||
121 | mesh_plink_quiesce(sta); | ||
122 | } | 92 | } |
123 | mutex_unlock(&local->sta_mtx); | 93 | mutex_unlock(&local->sta_mtx); |
124 | 94 | ||
125 | /* remove all interfaces */ | 95 | /* remove all interfaces */ |
126 | list_for_each_entry(sdata, &local->interfaces, list) { | 96 | list_for_each_entry(sdata, &local->interfaces, list) { |
127 | static u8 zero_addr[ETH_ALEN] = {}; | ||
128 | u32 changed = 0; | ||
129 | |||
130 | if (!ieee80211_sdata_running(sdata)) | 97 | if (!ieee80211_sdata_running(sdata)) |
131 | continue; | 98 | continue; |
132 | |||
133 | switch (sdata->vif.type) { | ||
134 | case NL80211_IFTYPE_AP_VLAN: | ||
135 | case NL80211_IFTYPE_MONITOR: | ||
136 | /* skip these */ | ||
137 | continue; | ||
138 | case NL80211_IFTYPE_STATION: | ||
139 | if (sdata->vif.bss_conf.assoc) | ||
140 | changed = BSS_CHANGED_ASSOC | | ||
141 | BSS_CHANGED_BSSID | | ||
142 | BSS_CHANGED_IDLE; | ||
143 | break; | ||
144 | case NL80211_IFTYPE_AP: | ||
145 | case NL80211_IFTYPE_ADHOC: | ||
146 | case NL80211_IFTYPE_MESH_POINT: | ||
147 | if (sdata->vif.bss_conf.enable_beacon) | ||
148 | changed = BSS_CHANGED_BEACON_ENABLED; | ||
149 | break; | ||
150 | default: | ||
151 | break; | ||
152 | } | ||
153 | |||
154 | ieee80211_quiesce(sdata); | ||
155 | |||
156 | sdata->suspend_bss_conf = sdata->vif.bss_conf; | ||
157 | memset(&sdata->vif.bss_conf, 0, sizeof(sdata->vif.bss_conf)); | ||
158 | sdata->vif.bss_conf.idle = true; | ||
159 | if (sdata->suspend_bss_conf.bssid) | ||
160 | sdata->vif.bss_conf.bssid = zero_addr; | ||
161 | |||
162 | /* disable beaconing or remove association */ | ||
163 | ieee80211_bss_info_change_notify(sdata, changed); | ||
164 | |||
165 | if (sdata->vif.type == NL80211_IFTYPE_AP && | ||
166 | rcu_access_pointer(sdata->u.ap.beacon)) | ||
167 | drv_stop_ap(local, sdata); | ||
168 | |||
169 | if (local->use_chanctx) { | ||
170 | struct ieee80211_chanctx_conf *conf; | ||
171 | |||
172 | mutex_lock(&local->chanctx_mtx); | ||
173 | conf = rcu_dereference_protected( | ||
174 | sdata->vif.chanctx_conf, | ||
175 | lockdep_is_held(&local->chanctx_mtx)); | ||
176 | if (conf) { | ||
177 | ctx = container_of(conf, | ||
178 | struct ieee80211_chanctx, | ||
179 | conf); | ||
180 | drv_unassign_vif_chanctx(local, sdata, ctx); | ||
181 | } | ||
182 | |||
183 | mutex_unlock(&local->chanctx_mtx); | ||
184 | } | ||
185 | drv_remove_interface(local, sdata); | 99 | drv_remove_interface(local, sdata); |
186 | } | 100 | } |
187 | 101 | ||
188 | sdata = rtnl_dereference(local->monitor_sdata); | 102 | sdata = rtnl_dereference(local->monitor_sdata); |
189 | if (sdata) { | 103 | if (sdata) |
190 | if (local->use_chanctx) { | ||
191 | struct ieee80211_chanctx_conf *conf; | ||
192 | |||
193 | mutex_lock(&local->chanctx_mtx); | ||
194 | conf = rcu_dereference_protected( | ||
195 | sdata->vif.chanctx_conf, | ||
196 | lockdep_is_held(&local->chanctx_mtx)); | ||
197 | if (conf) { | ||
198 | ctx = container_of(conf, | ||
199 | struct ieee80211_chanctx, | ||
200 | conf); | ||
201 | drv_unassign_vif_chanctx(local, sdata, ctx); | ||
202 | } | ||
203 | |||
204 | mutex_unlock(&local->chanctx_mtx); | ||
205 | } | ||
206 | |||
207 | drv_remove_interface(local, sdata); | 104 | drv_remove_interface(local, sdata); |
208 | } | ||
209 | 105 | ||
210 | mutex_lock(&local->chanctx_mtx); | 106 | /* |
211 | list_for_each_entry(ctx, &local->chanctx_list, list) | 107 | * We disconnected on all interfaces before suspend, all channel |
212 | drv_remove_chanctx(local, ctx); | 108 | * contexts should be released. |
213 | mutex_unlock(&local->chanctx_mtx); | 109 | */ |
110 | WARN_ON(!list_empty(&local->chanctx_list)); | ||
214 | 111 | ||
215 | /* stop hardware - this must stop RX */ | 112 | /* stop hardware - this must stop RX */ |
216 | if (local->open_count) | 113 | if (local->open_count) |
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index eea45a2c7c35..1c36c9b4fa4a 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c | |||
@@ -55,7 +55,6 @@ | |||
55 | #include "rate.h" | 55 | #include "rate.h" |
56 | #include "rc80211_minstrel.h" | 56 | #include "rc80211_minstrel.h" |
57 | 57 | ||
58 | #define SAMPLE_COLUMNS 10 | ||
59 | #define SAMPLE_TBL(_mi, _idx, _col) \ | 58 | #define SAMPLE_TBL(_mi, _idx, _col) \ |
60 | _mi->sample_table[(_idx * SAMPLE_COLUMNS) + _col] | 59 | _mi->sample_table[(_idx * SAMPLE_COLUMNS) + _col] |
61 | 60 | ||
@@ -70,16 +69,31 @@ rix_to_ndx(struct minstrel_sta_info *mi, int rix) | |||
70 | return i; | 69 | return i; |
71 | } | 70 | } |
72 | 71 | ||
72 | /* find & sort topmost throughput rates */ | ||
73 | static inline void | ||
74 | minstrel_sort_best_tp_rates(struct minstrel_sta_info *mi, int i, u8 *tp_list) | ||
75 | { | ||
76 | int j = MAX_THR_RATES; | ||
77 | |||
78 | while (j > 0 && mi->r[i].cur_tp > mi->r[tp_list[j - 1]].cur_tp) | ||
79 | j--; | ||
80 | if (j < MAX_THR_RATES - 1) | ||
81 | memmove(&tp_list[j + 1], &tp_list[j], MAX_THR_RATES - (j + 1)); | ||
82 | if (j < MAX_THR_RATES) | ||
83 | tp_list[j] = i; | ||
84 | } | ||
85 | |||
73 | static void | 86 | static void |
74 | minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) | 87 | minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) |
75 | { | 88 | { |
76 | u32 max_tp = 0, index_max_tp = 0, index_max_tp2 = 0; | 89 | u8 tmp_tp_rate[MAX_THR_RATES]; |
77 | u32 max_prob = 0, index_max_prob = 0; | 90 | u8 tmp_prob_rate = 0; |
78 | u32 usecs; | 91 | u32 usecs; |
79 | u32 p; | ||
80 | int i; | 92 | int i; |
81 | 93 | ||
82 | mi->stats_update = jiffies; | 94 | for (i=0; i < MAX_THR_RATES; i++) |
95 | tmp_tp_rate[i] = 0; | ||
96 | |||
83 | for (i = 0; i < mi->n_rates; i++) { | 97 | for (i = 0; i < mi->n_rates; i++) { |
84 | struct minstrel_rate *mr = &mi->r[i]; | 98 | struct minstrel_rate *mr = &mi->r[i]; |
85 | 99 | ||
@@ -87,27 +101,32 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) | |||
87 | if (!usecs) | 101 | if (!usecs) |
88 | usecs = 1000000; | 102 | usecs = 1000000; |
89 | 103 | ||
90 | /* To avoid rounding issues, probabilities scale from 0 (0%) | 104 | if (unlikely(mr->attempts > 0)) { |
91 | * to 18000 (100%) */ | 105 | mr->sample_skipped = 0; |
92 | if (mr->attempts) { | 106 | mr->cur_prob = MINSTREL_FRAC(mr->success, mr->attempts); |
93 | p = (mr->success * 18000) / mr->attempts; | ||
94 | mr->succ_hist += mr->success; | 107 | mr->succ_hist += mr->success; |
95 | mr->att_hist += mr->attempts; | 108 | mr->att_hist += mr->attempts; |
96 | mr->cur_prob = p; | 109 | mr->probability = minstrel_ewma(mr->probability, |
97 | p = ((p * (100 - mp->ewma_level)) + (mr->probability * | 110 | mr->cur_prob, |
98 | mp->ewma_level)) / 100; | 111 | EWMA_LEVEL); |
99 | mr->probability = p; | 112 | } else |
100 | mr->cur_tp = p * (1000000 / usecs); | 113 | mr->sample_skipped++; |
101 | } | ||
102 | 114 | ||
103 | mr->last_success = mr->success; | 115 | mr->last_success = mr->success; |
104 | mr->last_attempts = mr->attempts; | 116 | mr->last_attempts = mr->attempts; |
105 | mr->success = 0; | 117 | mr->success = 0; |
106 | mr->attempts = 0; | 118 | mr->attempts = 0; |
107 | 119 | ||
120 | /* Update throughput per rate, reset thr. below 10% success */ | ||
121 | if (mr->probability < MINSTREL_FRAC(10, 100)) | ||
122 | mr->cur_tp = 0; | ||
123 | else | ||
124 | mr->cur_tp = mr->probability * (1000000 / usecs); | ||
125 | |||
108 | /* Sample less often below the 10% chance of success. | 126 | /* Sample less often below the 10% chance of success. |
109 | * Sample less often above the 95% chance of success. */ | 127 | * Sample less often above the 95% chance of success. */ |
110 | if ((mr->probability > 17100) || (mr->probability < 1800)) { | 128 | if (mr->probability > MINSTREL_FRAC(95, 100) || |
129 | mr->probability < MINSTREL_FRAC(10, 100)) { | ||
111 | mr->adjusted_retry_count = mr->retry_count >> 1; | 130 | mr->adjusted_retry_count = mr->retry_count >> 1; |
112 | if (mr->adjusted_retry_count > 2) | 131 | if (mr->adjusted_retry_count > 2) |
113 | mr->adjusted_retry_count = 2; | 132 | mr->adjusted_retry_count = 2; |
@@ -118,35 +137,30 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) | |||
118 | } | 137 | } |
119 | if (!mr->adjusted_retry_count) | 138 | if (!mr->adjusted_retry_count) |
120 | mr->adjusted_retry_count = 2; | 139 | mr->adjusted_retry_count = 2; |
121 | } | ||
122 | 140 | ||
123 | for (i = 0; i < mi->n_rates; i++) { | 141 | minstrel_sort_best_tp_rates(mi, i, tmp_tp_rate); |
124 | struct minstrel_rate *mr = &mi->r[i]; | 142 | |
125 | if (max_tp < mr->cur_tp) { | 143 | /* To determine the most robust rate (max_prob_rate) used at |
126 | index_max_tp = i; | 144 | * 3rd mmr stage we distinct between two cases: |
127 | max_tp = mr->cur_tp; | 145 | * (1) if any success probabilitiy >= 95%, out of those rates |
128 | } | 146 | * choose the maximum throughput rate as max_prob_rate |
129 | if (max_prob < mr->probability) { | 147 | * (2) if all success probabilities < 95%, the rate with |
130 | index_max_prob = i; | 148 | * highest success probability is choosen as max_prob_rate */ |
131 | max_prob = mr->probability; | 149 | if (mr->probability >= MINSTREL_FRAC(95,100)) { |
150 | if (mr->cur_tp >= mi->r[tmp_prob_rate].cur_tp) | ||
151 | tmp_prob_rate = i; | ||
152 | } else { | ||
153 | if (mr->probability >= mi->r[tmp_prob_rate].probability) | ||
154 | tmp_prob_rate = i; | ||
132 | } | 155 | } |
133 | } | 156 | } |
134 | 157 | ||
135 | max_tp = 0; | 158 | /* Assign the new rate set */ |
136 | for (i = 0; i < mi->n_rates; i++) { | 159 | memcpy(mi->max_tp_rate, tmp_tp_rate, sizeof(mi->max_tp_rate)); |
137 | struct minstrel_rate *mr = &mi->r[i]; | 160 | mi->max_prob_rate = tmp_prob_rate; |
138 | |||
139 | if (i == index_max_tp) | ||
140 | continue; | ||
141 | 161 | ||
142 | if (max_tp < mr->cur_tp) { | 162 | /* Reset update timer */ |
143 | index_max_tp2 = i; | 163 | mi->stats_update = jiffies; |
144 | max_tp = mr->cur_tp; | ||
145 | } | ||
146 | } | ||
147 | mi->max_tp_rate = index_max_tp; | ||
148 | mi->max_tp_rate2 = index_max_tp2; | ||
149 | mi->max_prob_rate = index_max_prob; | ||
150 | } | 164 | } |
151 | 165 | ||
152 | static void | 166 | static void |
@@ -207,10 +221,10 @@ static int | |||
207 | minstrel_get_next_sample(struct minstrel_sta_info *mi) | 221 | minstrel_get_next_sample(struct minstrel_sta_info *mi) |
208 | { | 222 | { |
209 | unsigned int sample_ndx; | 223 | unsigned int sample_ndx; |
210 | sample_ndx = SAMPLE_TBL(mi, mi->sample_idx, mi->sample_column); | 224 | sample_ndx = SAMPLE_TBL(mi, mi->sample_row, mi->sample_column); |
211 | mi->sample_idx++; | 225 | mi->sample_row++; |
212 | if ((int) mi->sample_idx > (mi->n_rates - 2)) { | 226 | if ((int) mi->sample_row >= mi->n_rates) { |
213 | mi->sample_idx = 0; | 227 | mi->sample_row = 0; |
214 | mi->sample_column++; | 228 | mi->sample_column++; |
215 | if (mi->sample_column >= SAMPLE_COLUMNS) | 229 | if (mi->sample_column >= SAMPLE_COLUMNS) |
216 | mi->sample_column = 0; | 230 | mi->sample_column = 0; |
@@ -228,31 +242,37 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta, | |||
228 | struct minstrel_priv *mp = priv; | 242 | struct minstrel_priv *mp = priv; |
229 | struct ieee80211_tx_rate *ar = info->control.rates; | 243 | struct ieee80211_tx_rate *ar = info->control.rates; |
230 | unsigned int ndx, sample_ndx = 0; | 244 | unsigned int ndx, sample_ndx = 0; |
231 | bool mrr; | 245 | bool mrr_capable; |
232 | bool sample_slower = false; | 246 | bool indirect_rate_sampling = false; |
233 | bool sample = false; | 247 | bool rate_sampling = false; |
234 | int i, delta; | 248 | int i, delta; |
235 | int mrr_ndx[3]; | 249 | int mrr_ndx[3]; |
236 | int sample_rate; | 250 | int sampling_ratio; |
237 | 251 | ||
252 | /* management/no-ack frames do not use rate control */ | ||
238 | if (rate_control_send_low(sta, priv_sta, txrc)) | 253 | if (rate_control_send_low(sta, priv_sta, txrc)) |
239 | return; | 254 | return; |
240 | 255 | ||
241 | mrr = mp->has_mrr && !txrc->rts && !txrc->bss_conf->use_cts_prot; | 256 | /* check multi-rate-retry capabilities & adjust lookaround_rate */ |
242 | 257 | mrr_capable = mp->has_mrr && | |
243 | ndx = mi->max_tp_rate; | 258 | !txrc->rts && |
244 | 259 | !txrc->bss_conf->use_cts_prot; | |
245 | if (mrr) | 260 | if (mrr_capable) |
246 | sample_rate = mp->lookaround_rate_mrr; | 261 | sampling_ratio = mp->lookaround_rate_mrr; |
247 | else | 262 | else |
248 | sample_rate = mp->lookaround_rate; | 263 | sampling_ratio = mp->lookaround_rate; |
264 | |||
265 | /* init rateindex [ndx] with max throughput rate */ | ||
266 | ndx = mi->max_tp_rate[0]; | ||
249 | 267 | ||
268 | /* increase sum packet counter */ | ||
250 | mi->packet_count++; | 269 | mi->packet_count++; |
251 | delta = (mi->packet_count * sample_rate / 100) - | 270 | |
271 | delta = (mi->packet_count * sampling_ratio / 100) - | ||
252 | (mi->sample_count + mi->sample_deferred / 2); | 272 | (mi->sample_count + mi->sample_deferred / 2); |
253 | 273 | ||
254 | /* delta > 0: sampling required */ | 274 | /* delta > 0: sampling required */ |
255 | if ((delta > 0) && (mrr || !mi->prev_sample)) { | 275 | if ((delta > 0) && (mrr_capable || !mi->prev_sample)) { |
256 | struct minstrel_rate *msr; | 276 | struct minstrel_rate *msr; |
257 | if (mi->packet_count >= 10000) { | 277 | if (mi->packet_count >= 10000) { |
258 | mi->sample_deferred = 0; | 278 | mi->sample_deferred = 0; |
@@ -271,21 +291,28 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta, | |||
271 | mi->sample_count += (delta - mi->n_rates * 2); | 291 | mi->sample_count += (delta - mi->n_rates * 2); |
272 | } | 292 | } |
273 | 293 | ||
294 | /* get next random rate sample */ | ||
274 | sample_ndx = minstrel_get_next_sample(mi); | 295 | sample_ndx = minstrel_get_next_sample(mi); |
275 | msr = &mi->r[sample_ndx]; | 296 | msr = &mi->r[sample_ndx]; |
276 | sample = true; | 297 | rate_sampling = true; |
277 | sample_slower = mrr && (msr->perfect_tx_time > | 298 | |
278 | mi->r[ndx].perfect_tx_time); | 299 | /* Decide if direct ( 1st mrr stage) or indirect (2nd mrr stage) |
279 | 300 | * rate sampling method should be used. | |
280 | if (!sample_slower) { | 301 | * Respect such rates that are not sampled for 20 interations. |
302 | */ | ||
303 | if (mrr_capable && | ||
304 | msr->perfect_tx_time > mi->r[ndx].perfect_tx_time && | ||
305 | msr->sample_skipped < 20) | ||
306 | indirect_rate_sampling = true; | ||
307 | |||
308 | if (!indirect_rate_sampling) { | ||
281 | if (msr->sample_limit != 0) { | 309 | if (msr->sample_limit != 0) { |
282 | ndx = sample_ndx; | 310 | ndx = sample_ndx; |
283 | mi->sample_count++; | 311 | mi->sample_count++; |
284 | if (msr->sample_limit > 0) | 312 | if (msr->sample_limit > 0) |
285 | msr->sample_limit--; | 313 | msr->sample_limit--; |
286 | } else { | 314 | } else |
287 | sample = false; | 315 | rate_sampling = false; |
288 | } | ||
289 | } else { | 316 | } else { |
290 | /* Only use IEEE80211_TX_CTL_RATE_CTRL_PROBE to mark | 317 | /* Only use IEEE80211_TX_CTL_RATE_CTRL_PROBE to mark |
291 | * packets that have the sampling rate deferred to the | 318 | * packets that have the sampling rate deferred to the |
@@ -297,34 +324,39 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta, | |||
297 | mi->sample_deferred++; | 324 | mi->sample_deferred++; |
298 | } | 325 | } |
299 | } | 326 | } |
300 | mi->prev_sample = sample; | 327 | mi->prev_sample = rate_sampling; |
301 | 328 | ||
302 | /* If we're not using MRR and the sampling rate already | 329 | /* If we're not using MRR and the sampling rate already |
303 | * has a probability of >95%, we shouldn't be attempting | 330 | * has a probability of >95%, we shouldn't be attempting |
304 | * to use it, as this only wastes precious airtime */ | 331 | * to use it, as this only wastes precious airtime */ |
305 | if (!mrr && sample && (mi->r[ndx].probability > 17100)) | 332 | if (!mrr_capable && rate_sampling && |
306 | ndx = mi->max_tp_rate; | 333 | (mi->r[ndx].probability > MINSTREL_FRAC(95, 100))) |
334 | ndx = mi->max_tp_rate[0]; | ||
307 | 335 | ||
336 | /* mrr setup for 1st stage */ | ||
308 | ar[0].idx = mi->r[ndx].rix; | 337 | ar[0].idx = mi->r[ndx].rix; |
309 | ar[0].count = minstrel_get_retry_count(&mi->r[ndx], info); | 338 | ar[0].count = minstrel_get_retry_count(&mi->r[ndx], info); |
310 | 339 | ||
311 | if (!mrr) { | 340 | /* non mrr setup for 2nd stage */ |
312 | if (!sample) | 341 | if (!mrr_capable) { |
342 | if (!rate_sampling) | ||
313 | ar[0].count = mp->max_retry; | 343 | ar[0].count = mp->max_retry; |
314 | ar[1].idx = mi->lowest_rix; | 344 | ar[1].idx = mi->lowest_rix; |
315 | ar[1].count = mp->max_retry; | 345 | ar[1].count = mp->max_retry; |
316 | return; | 346 | return; |
317 | } | 347 | } |
318 | 348 | ||
319 | /* MRR setup */ | 349 | /* mrr setup for 2nd stage */ |
320 | if (sample) { | 350 | if (rate_sampling) { |
321 | if (sample_slower) | 351 | if (indirect_rate_sampling) |
322 | mrr_ndx[0] = sample_ndx; | 352 | mrr_ndx[0] = sample_ndx; |
323 | else | 353 | else |
324 | mrr_ndx[0] = mi->max_tp_rate; | 354 | mrr_ndx[0] = mi->max_tp_rate[0]; |
325 | } else { | 355 | } else { |
326 | mrr_ndx[0] = mi->max_tp_rate2; | 356 | mrr_ndx[0] = mi->max_tp_rate[1]; |
327 | } | 357 | } |
358 | |||
359 | /* mrr setup for 3rd & 4th stage */ | ||
328 | mrr_ndx[1] = mi->max_prob_rate; | 360 | mrr_ndx[1] = mi->max_prob_rate; |
329 | mrr_ndx[2] = 0; | 361 | mrr_ndx[2] = 0; |
330 | for (i = 1; i < 4; i++) { | 362 | for (i = 1; i < 4; i++) { |
@@ -351,26 +383,21 @@ static void | |||
351 | init_sample_table(struct minstrel_sta_info *mi) | 383 | init_sample_table(struct minstrel_sta_info *mi) |
352 | { | 384 | { |
353 | unsigned int i, col, new_idx; | 385 | unsigned int i, col, new_idx; |
354 | unsigned int n_srates = mi->n_rates - 1; | ||
355 | u8 rnd[8]; | 386 | u8 rnd[8]; |
356 | 387 | ||
357 | mi->sample_column = 0; | 388 | mi->sample_column = 0; |
358 | mi->sample_idx = 0; | 389 | mi->sample_row = 0; |
359 | memset(mi->sample_table, 0, SAMPLE_COLUMNS * mi->n_rates); | 390 | memset(mi->sample_table, 0xff, SAMPLE_COLUMNS * mi->n_rates); |
360 | 391 | ||
361 | for (col = 0; col < SAMPLE_COLUMNS; col++) { | 392 | for (col = 0; col < SAMPLE_COLUMNS; col++) { |
362 | for (i = 0; i < n_srates; i++) { | 393 | for (i = 0; i < mi->n_rates; i++) { |
363 | get_random_bytes(rnd, sizeof(rnd)); | 394 | get_random_bytes(rnd, sizeof(rnd)); |
364 | new_idx = (i + rnd[i & 7]) % n_srates; | 395 | new_idx = (i + rnd[i & 7]) % mi->n_rates; |
365 | 396 | ||
366 | while (SAMPLE_TBL(mi, new_idx, col) != 0) | 397 | while (SAMPLE_TBL(mi, new_idx, col) != 0xff) |
367 | new_idx = (new_idx + 1) % n_srates; | 398 | new_idx = (new_idx + 1) % mi->n_rates; |
368 | 399 | ||
369 | /* Don't sample the slowest rate (i.e. slowest base | 400 | SAMPLE_TBL(mi, new_idx, col) = i; |
370 | * rate). We must presume that the slowest rate works | ||
371 | * fine, or else other management frames will also be | ||
372 | * failing and the link will break */ | ||
373 | SAMPLE_TBL(mi, new_idx, col) = i + 1; | ||
374 | } | 401 | } |
375 | } | 402 | } |
376 | } | 403 | } |
@@ -542,9 +569,6 @@ minstrel_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) | |||
542 | mp->lookaround_rate = 5; | 569 | mp->lookaround_rate = 5; |
543 | mp->lookaround_rate_mrr = 10; | 570 | mp->lookaround_rate_mrr = 10; |
544 | 571 | ||
545 | /* moving average weight for EWMA */ | ||
546 | mp->ewma_level = 75; | ||
547 | |||
548 | /* maximum time that the hw is allowed to stay in one MRR segment */ | 572 | /* maximum time that the hw is allowed to stay in one MRR segment */ |
549 | mp->segment_size = 6000; | 573 | mp->segment_size = 6000; |
550 | 574 | ||
diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h index 5ecf757817f2..85ebf42cb46d 100644 --- a/net/mac80211/rc80211_minstrel.h +++ b/net/mac80211/rc80211_minstrel.h | |||
@@ -9,6 +9,28 @@ | |||
9 | #ifndef __RC_MINSTREL_H | 9 | #ifndef __RC_MINSTREL_H |
10 | #define __RC_MINSTREL_H | 10 | #define __RC_MINSTREL_H |
11 | 11 | ||
12 | #define EWMA_LEVEL 75 /* ewma weighting factor [%] */ | ||
13 | #define SAMPLE_COLUMNS 10 /* number of columns in sample table */ | ||
14 | |||
15 | |||
16 | /* scaled fraction values */ | ||
17 | #define MINSTREL_SCALE 16 | ||
18 | #define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / div) | ||
19 | #define MINSTREL_TRUNC(val) ((val) >> MINSTREL_SCALE) | ||
20 | |||
21 | /* number of highest throughput rates to consider*/ | ||
22 | #define MAX_THR_RATES 4 | ||
23 | |||
24 | /* | ||
25 | * Perform EWMA (Exponentially Weighted Moving Average) calculation | ||
26 | */ | ||
27 | static inline int | ||
28 | minstrel_ewma(int old, int new, int weight) | ||
29 | { | ||
30 | return (new * (100 - weight) + old * weight) / 100; | ||
31 | } | ||
32 | |||
33 | |||
12 | struct minstrel_rate { | 34 | struct minstrel_rate { |
13 | int bitrate; | 35 | int bitrate; |
14 | int rix; | 36 | int rix; |
@@ -26,6 +48,7 @@ struct minstrel_rate { | |||
26 | u32 attempts; | 48 | u32 attempts; |
27 | u32 last_attempts; | 49 | u32 last_attempts; |
28 | u32 last_success; | 50 | u32 last_success; |
51 | u8 sample_skipped; | ||
29 | 52 | ||
30 | /* parts per thousand */ | 53 | /* parts per thousand */ |
31 | u32 cur_prob; | 54 | u32 cur_prob; |
@@ -45,14 +68,13 @@ struct minstrel_sta_info { | |||
45 | 68 | ||
46 | unsigned int lowest_rix; | 69 | unsigned int lowest_rix; |
47 | 70 | ||
48 | unsigned int max_tp_rate; | 71 | u8 max_tp_rate[MAX_THR_RATES]; |
49 | unsigned int max_tp_rate2; | 72 | u8 max_prob_rate; |
50 | unsigned int max_prob_rate; | ||
51 | unsigned int packet_count; | 73 | unsigned int packet_count; |
52 | unsigned int sample_count; | 74 | unsigned int sample_count; |
53 | int sample_deferred; | 75 | int sample_deferred; |
54 | 76 | ||
55 | unsigned int sample_idx; | 77 | unsigned int sample_row; |
56 | unsigned int sample_column; | 78 | unsigned int sample_column; |
57 | 79 | ||
58 | int n_rates; | 80 | int n_rates; |
@@ -73,7 +95,6 @@ struct minstrel_priv { | |||
73 | unsigned int cw_min; | 95 | unsigned int cw_min; |
74 | unsigned int cw_max; | 96 | unsigned int cw_max; |
75 | unsigned int max_retry; | 97 | unsigned int max_retry; |
76 | unsigned int ewma_level; | ||
77 | unsigned int segment_size; | 98 | unsigned int segment_size; |
78 | unsigned int update_interval; | 99 | unsigned int update_interval; |
79 | unsigned int lookaround_rate; | 100 | unsigned int lookaround_rate; |
diff --git a/net/mac80211/rc80211_minstrel_debugfs.c b/net/mac80211/rc80211_minstrel_debugfs.c index d5a56226e675..d1048348d399 100644 --- a/net/mac80211/rc80211_minstrel_debugfs.c +++ b/net/mac80211/rc80211_minstrel_debugfs.c | |||
@@ -73,15 +73,17 @@ minstrel_stats_open(struct inode *inode, struct file *file) | |||
73 | for (i = 0; i < mi->n_rates; i++) { | 73 | for (i = 0; i < mi->n_rates; i++) { |
74 | struct minstrel_rate *mr = &mi->r[i]; | 74 | struct minstrel_rate *mr = &mi->r[i]; |
75 | 75 | ||
76 | *(p++) = (i == mi->max_tp_rate) ? 'T' : ' '; | 76 | *(p++) = (i == mi->max_tp_rate[0]) ? 'A' : ' '; |
77 | *(p++) = (i == mi->max_tp_rate2) ? 't' : ' '; | 77 | *(p++) = (i == mi->max_tp_rate[1]) ? 'B' : ' '; |
78 | *(p++) = (i == mi->max_tp_rate[2]) ? 'C' : ' '; | ||
79 | *(p++) = (i == mi->max_tp_rate[3]) ? 'D' : ' '; | ||
78 | *(p++) = (i == mi->max_prob_rate) ? 'P' : ' '; | 80 | *(p++) = (i == mi->max_prob_rate) ? 'P' : ' '; |
79 | p += sprintf(p, "%3u%s", mr->bitrate / 2, | 81 | p += sprintf(p, "%3u%s", mr->bitrate / 2, |
80 | (mr->bitrate & 1 ? ".5" : " ")); | 82 | (mr->bitrate & 1 ? ".5" : " ")); |
81 | 83 | ||
82 | tp = mr->cur_tp / ((18000 << 10) / 96); | 84 | tp = MINSTREL_TRUNC(mr->cur_tp / 10); |
83 | prob = mr->cur_prob / 18; | 85 | prob = MINSTREL_TRUNC(mr->cur_prob * 1000); |
84 | eprob = mr->probability / 18; | 86 | eprob = MINSTREL_TRUNC(mr->probability * 1000); |
85 | 87 | ||
86 | p += sprintf(p, " %6u.%1u %6u.%1u %6u.%1u " | 88 | p += sprintf(p, " %6u.%1u %6u.%1u %6u.%1u " |
87 | "%3u(%3u) %8llu %8llu\n", | 89 | "%3u(%3u) %8llu %8llu\n", |
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index 3af141c69712..749552bdcfe1 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c | |||
@@ -17,8 +17,6 @@ | |||
17 | #include "rc80211_minstrel_ht.h" | 17 | #include "rc80211_minstrel_ht.h" |
18 | 18 | ||
19 | #define AVG_PKT_SIZE 1200 | 19 | #define AVG_PKT_SIZE 1200 |
20 | #define SAMPLE_COLUMNS 10 | ||
21 | #define EWMA_LEVEL 75 | ||
22 | 20 | ||
23 | /* Number of bits for an average sized packet */ | 21 | /* Number of bits for an average sized packet */ |
24 | #define MCS_NBITS (AVG_PKT_SIZE << 3) | 22 | #define MCS_NBITS (AVG_PKT_SIZE << 3) |
@@ -26,11 +24,11 @@ | |||
26 | /* Number of symbols for a packet with (bps) bits per symbol */ | 24 | /* Number of symbols for a packet with (bps) bits per symbol */ |
27 | #define MCS_NSYMS(bps) ((MCS_NBITS + (bps) - 1) / (bps)) | 25 | #define MCS_NSYMS(bps) ((MCS_NBITS + (bps) - 1) / (bps)) |
28 | 26 | ||
29 | /* Transmission time for a packet containing (syms) symbols */ | 27 | /* Transmission time (nanoseconds) for a packet containing (syms) symbols */ |
30 | #define MCS_SYMBOL_TIME(sgi, syms) \ | 28 | #define MCS_SYMBOL_TIME(sgi, syms) \ |
31 | (sgi ? \ | 29 | (sgi ? \ |
32 | ((syms) * 18 + 4) / 5 : /* syms * 3.6 us */ \ | 30 | ((syms) * 18000 + 4000) / 5 : /* syms * 3.6 us */ \ |
33 | (syms) << 2 /* syms * 4 us */ \ | 31 | ((syms) * 1000) << 2 /* syms * 4 us */ \ |
34 | ) | 32 | ) |
35 | 33 | ||
36 | /* Transmit duration for the raw data part of an average sized packet */ | 34 | /* Transmit duration for the raw data part of an average sized packet */ |
@@ -64,9 +62,9 @@ | |||
64 | } | 62 | } |
65 | 63 | ||
66 | #define CCK_DURATION(_bitrate, _short, _len) \ | 64 | #define CCK_DURATION(_bitrate, _short, _len) \ |
67 | (10 /* SIFS */ + \ | 65 | (1000 * (10 /* SIFS */ + \ |
68 | (_short ? 72 + 24 : 144 + 48 ) + \ | 66 | (_short ? 72 + 24 : 144 + 48 ) + \ |
69 | (8 * (_len + 4) * 10) / (_bitrate)) | 67 | (8 * (_len + 4) * 10) / (_bitrate))) |
70 | 68 | ||
71 | #define CCK_ACK_DURATION(_bitrate, _short) \ | 69 | #define CCK_ACK_DURATION(_bitrate, _short) \ |
72 | (CCK_DURATION((_bitrate > 10 ? 20 : 10), false, 60) + \ | 70 | (CCK_DURATION((_bitrate > 10 ? 20 : 10), false, 60) + \ |
@@ -129,15 +127,6 @@ const struct mcs_group minstrel_mcs_groups[] = { | |||
129 | static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES]; | 127 | static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES]; |
130 | 128 | ||
131 | /* | 129 | /* |
132 | * Perform EWMA (Exponentially Weighted Moving Average) calculation | ||
133 | */ | ||
134 | static int | ||
135 | minstrel_ewma(int old, int new, int weight) | ||
136 | { | ||
137 | return (new * (100 - weight) + old * weight) / 100; | ||
138 | } | ||
139 | |||
140 | /* | ||
141 | * Look up an MCS group index based on mac80211 rate information | 130 | * Look up an MCS group index based on mac80211 rate information |
142 | */ | 131 | */ |
143 | static int | 132 | static int |
@@ -211,7 +200,8 @@ static void | |||
211 | minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int group, int rate) | 200 | minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int group, int rate) |
212 | { | 201 | { |
213 | struct minstrel_rate_stats *mr; | 202 | struct minstrel_rate_stats *mr; |
214 | unsigned int usecs = 0; | 203 | unsigned int nsecs = 0; |
204 | unsigned int tp; | ||
215 | 205 | ||
216 | mr = &mi->groups[group].rates[rate]; | 206 | mr = &mi->groups[group].rates[rate]; |
217 | 207 | ||
@@ -221,10 +211,12 @@ minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int group, int rate) | |||
221 | } | 211 | } |
222 | 212 | ||
223 | if (group != MINSTREL_CCK_GROUP) | 213 | if (group != MINSTREL_CCK_GROUP) |
224 | usecs = mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len); | 214 | nsecs = 1000 * mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len); |
225 | 215 | ||
226 | usecs += minstrel_mcs_groups[group].duration[rate]; | 216 | nsecs += minstrel_mcs_groups[group].duration[rate]; |
227 | mr->cur_tp = MINSTREL_TRUNC((1000000 / usecs) * mr->probability); | 217 | tp = 1000000 * ((mr->probability * 1000) / nsecs); |
218 | |||
219 | mr->cur_tp = MINSTREL_TRUNC(tp); | ||
228 | } | 220 | } |
229 | 221 | ||
230 | /* | 222 | /* |
@@ -308,8 +300,8 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) | |||
308 | } | 300 | } |
309 | } | 301 | } |
310 | 302 | ||
311 | /* try to sample up to half of the available rates during each interval */ | 303 | /* try to sample all available rates during each interval */ |
312 | mi->sample_count *= 4; | 304 | mi->sample_count *= 8; |
313 | 305 | ||
314 | cur_prob = 0; | 306 | cur_prob = 0; |
315 | cur_prob_tp = 0; | 307 | cur_prob_tp = 0; |
@@ -320,20 +312,13 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) | |||
320 | if (!mg->supported) | 312 | if (!mg->supported) |
321 | continue; | 313 | continue; |
322 | 314 | ||
323 | mr = minstrel_get_ratestats(mi, mg->max_prob_rate); | ||
324 | if (cur_prob_tp < mr->cur_tp && | ||
325 | minstrel_mcs_groups[group].streams == 1) { | ||
326 | mi->max_prob_rate = mg->max_prob_rate; | ||
327 | cur_prob = mr->cur_prob; | ||
328 | cur_prob_tp = mr->cur_tp; | ||
329 | } | ||
330 | |||
331 | mr = minstrel_get_ratestats(mi, mg->max_tp_rate); | 315 | mr = minstrel_get_ratestats(mi, mg->max_tp_rate); |
332 | if (cur_tp < mr->cur_tp) { | 316 | if (cur_tp < mr->cur_tp) { |
333 | mi->max_tp_rate2 = mi->max_tp_rate; | 317 | mi->max_tp_rate2 = mi->max_tp_rate; |
334 | cur_tp2 = cur_tp; | 318 | cur_tp2 = cur_tp; |
335 | mi->max_tp_rate = mg->max_tp_rate; | 319 | mi->max_tp_rate = mg->max_tp_rate; |
336 | cur_tp = mr->cur_tp; | 320 | cur_tp = mr->cur_tp; |
321 | mi->max_prob_streams = minstrel_mcs_groups[group].streams - 1; | ||
337 | } | 322 | } |
338 | 323 | ||
339 | mr = minstrel_get_ratestats(mi, mg->max_tp_rate2); | 324 | mr = minstrel_get_ratestats(mi, mg->max_tp_rate2); |
@@ -343,6 +328,23 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) | |||
343 | } | 328 | } |
344 | } | 329 | } |
345 | 330 | ||
331 | if (mi->max_prob_streams < 1) | ||
332 | mi->max_prob_streams = 1; | ||
333 | |||
334 | for (group = 0; group < ARRAY_SIZE(minstrel_mcs_groups); group++) { | ||
335 | mg = &mi->groups[group]; | ||
336 | if (!mg->supported) | ||
337 | continue; | ||
338 | mr = minstrel_get_ratestats(mi, mg->max_prob_rate); | ||
339 | if (cur_prob_tp < mr->cur_tp && | ||
340 | minstrel_mcs_groups[group].streams <= mi->max_prob_streams) { | ||
341 | mi->max_prob_rate = mg->max_prob_rate; | ||
342 | cur_prob = mr->cur_prob; | ||
343 | cur_prob_tp = mr->cur_tp; | ||
344 | } | ||
345 | } | ||
346 | |||
347 | |||
346 | mi->stats_update = jiffies; | 348 | mi->stats_update = jiffies; |
347 | } | 349 | } |
348 | 350 | ||
@@ -467,7 +469,7 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband, | |||
467 | 469 | ||
468 | if (!mi->sample_wait && !mi->sample_tries && mi->sample_count > 0) { | 470 | if (!mi->sample_wait && !mi->sample_tries && mi->sample_count > 0) { |
469 | mi->sample_wait = 16 + 2 * MINSTREL_TRUNC(mi->avg_ampdu_len); | 471 | mi->sample_wait = 16 + 2 * MINSTREL_TRUNC(mi->avg_ampdu_len); |
470 | mi->sample_tries = 2; | 472 | mi->sample_tries = 1; |
471 | mi->sample_count--; | 473 | mi->sample_count--; |
472 | } | 474 | } |
473 | 475 | ||
@@ -536,7 +538,7 @@ minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, | |||
536 | mr->retry_updated = true; | 538 | mr->retry_updated = true; |
537 | 539 | ||
538 | group = &minstrel_mcs_groups[index / MCS_GROUP_RATES]; | 540 | group = &minstrel_mcs_groups[index / MCS_GROUP_RATES]; |
539 | tx_time_data = group->duration[index % MCS_GROUP_RATES] * ampdu_len; | 541 | tx_time_data = group->duration[index % MCS_GROUP_RATES] * ampdu_len / 1000; |
540 | 542 | ||
541 | /* Contention time for first 2 tries */ | 543 | /* Contention time for first 2 tries */ |
542 | ctime = (t_slot * cw) >> 1; | 544 | ctime = (t_slot * cw) >> 1; |
@@ -616,6 +618,7 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) | |||
616 | { | 618 | { |
617 | struct minstrel_rate_stats *mr; | 619 | struct minstrel_rate_stats *mr; |
618 | struct minstrel_mcs_group_data *mg; | 620 | struct minstrel_mcs_group_data *mg; |
621 | unsigned int sample_dur, sample_group; | ||
619 | int sample_idx = 0; | 622 | int sample_idx = 0; |
620 | 623 | ||
621 | if (mi->sample_wait > 0) { | 624 | if (mi->sample_wait > 0) { |
@@ -626,11 +629,11 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) | |||
626 | if (!mi->sample_tries) | 629 | if (!mi->sample_tries) |
627 | return -1; | 630 | return -1; |
628 | 631 | ||
629 | mi->sample_tries--; | ||
630 | mg = &mi->groups[mi->sample_group]; | 632 | mg = &mi->groups[mi->sample_group]; |
631 | sample_idx = sample_table[mg->column][mg->index]; | 633 | sample_idx = sample_table[mg->column][mg->index]; |
632 | mr = &mg->rates[sample_idx]; | 634 | mr = &mg->rates[sample_idx]; |
633 | sample_idx += mi->sample_group * MCS_GROUP_RATES; | 635 | sample_group = mi->sample_group; |
636 | sample_idx += sample_group * MCS_GROUP_RATES; | ||
634 | minstrel_next_sample_idx(mi); | 637 | minstrel_next_sample_idx(mi); |
635 | 638 | ||
636 | /* | 639 | /* |
@@ -651,14 +654,18 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) | |||
651 | * Make sure that lower rates get sampled only occasionally, | 654 | * Make sure that lower rates get sampled only occasionally, |
652 | * if the link is working perfectly. | 655 | * if the link is working perfectly. |
653 | */ | 656 | */ |
654 | if (minstrel_get_duration(sample_idx) > | 657 | sample_dur = minstrel_get_duration(sample_idx); |
655 | minstrel_get_duration(mi->max_tp_rate)) { | 658 | if (sample_dur >= minstrel_get_duration(mi->max_tp_rate2) && |
659 | (mi->max_prob_streams < | ||
660 | minstrel_mcs_groups[sample_group].streams || | ||
661 | sample_dur >= minstrel_get_duration(mi->max_prob_rate))) { | ||
656 | if (mr->sample_skipped < 20) | 662 | if (mr->sample_skipped < 20) |
657 | return -1; | 663 | return -1; |
658 | 664 | ||
659 | if (mi->sample_slow++ > 2) | 665 | if (mi->sample_slow++ > 2) |
660 | return -1; | 666 | return -1; |
661 | } | 667 | } |
668 | mi->sample_tries--; | ||
662 | 669 | ||
663 | return sample_idx; | 670 | return sample_idx; |
664 | } | 671 | } |
diff --git a/net/mac80211/rc80211_minstrel_ht.h b/net/mac80211/rc80211_minstrel_ht.h index 302dbd52180d..9b16e9de9923 100644 --- a/net/mac80211/rc80211_minstrel_ht.h +++ b/net/mac80211/rc80211_minstrel_ht.h | |||
@@ -16,11 +16,6 @@ | |||
16 | #define MINSTREL_MAX_STREAMS 3 | 16 | #define MINSTREL_MAX_STREAMS 3 |
17 | #define MINSTREL_STREAM_GROUPS 4 | 17 | #define MINSTREL_STREAM_GROUPS 4 |
18 | 18 | ||
19 | /* scaled fraction values */ | ||
20 | #define MINSTREL_SCALE 16 | ||
21 | #define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / div) | ||
22 | #define MINSTREL_TRUNC(val) ((val) >> MINSTREL_SCALE) | ||
23 | |||
24 | #define MCS_GROUP_RATES 8 | 19 | #define MCS_GROUP_RATES 8 |
25 | 20 | ||
26 | struct mcs_group { | 21 | struct mcs_group { |
@@ -85,6 +80,7 @@ struct minstrel_ht_sta { | |||
85 | 80 | ||
86 | /* best probability rate */ | 81 | /* best probability rate */ |
87 | unsigned int max_prob_rate; | 82 | unsigned int max_prob_rate; |
83 | unsigned int max_prob_streams; | ||
88 | 84 | ||
89 | /* time of last status update */ | 85 | /* time of last status update */ |
90 | unsigned long stats_update; | 86 | unsigned long stats_update; |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index bb73ed2d20b9..5b4492af4e85 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -648,24 +648,6 @@ static ieee80211_rx_result ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) | |||
648 | return RX_CONTINUE; | 648 | return RX_CONTINUE; |
649 | } | 649 | } |
650 | 650 | ||
651 | #define SEQ_MODULO 0x1000 | ||
652 | #define SEQ_MASK 0xfff | ||
653 | |||
654 | static inline int seq_less(u16 sq1, u16 sq2) | ||
655 | { | ||
656 | return ((sq1 - sq2) & SEQ_MASK) > (SEQ_MODULO >> 1); | ||
657 | } | ||
658 | |||
659 | static inline u16 seq_inc(u16 sq) | ||
660 | { | ||
661 | return (sq + 1) & SEQ_MASK; | ||
662 | } | ||
663 | |||
664 | static inline u16 seq_sub(u16 sq1, u16 sq2) | ||
665 | { | ||
666 | return (sq1 - sq2) & SEQ_MASK; | ||
667 | } | ||
668 | |||
669 | static void ieee80211_release_reorder_frame(struct ieee80211_sub_if_data *sdata, | 651 | static void ieee80211_release_reorder_frame(struct ieee80211_sub_if_data *sdata, |
670 | struct tid_ampdu_rx *tid_agg_rx, | 652 | struct tid_ampdu_rx *tid_agg_rx, |
671 | int index, | 653 | int index, |
@@ -687,7 +669,7 @@ static void ieee80211_release_reorder_frame(struct ieee80211_sub_if_data *sdata, | |||
687 | __skb_queue_tail(frames, skb); | 669 | __skb_queue_tail(frames, skb); |
688 | 670 | ||
689 | no_frame: | 671 | no_frame: |
690 | tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); | 672 | tid_agg_rx->head_seq_num = ieee80211_sn_inc(tid_agg_rx->head_seq_num); |
691 | } | 673 | } |
692 | 674 | ||
693 | static void ieee80211_release_reorder_frames(struct ieee80211_sub_if_data *sdata, | 675 | static void ieee80211_release_reorder_frames(struct ieee80211_sub_if_data *sdata, |
@@ -699,8 +681,9 @@ static void ieee80211_release_reorder_frames(struct ieee80211_sub_if_data *sdata | |||
699 | 681 | ||
700 | lockdep_assert_held(&tid_agg_rx->reorder_lock); | 682 | lockdep_assert_held(&tid_agg_rx->reorder_lock); |
701 | 683 | ||
702 | while (seq_less(tid_agg_rx->head_seq_num, head_seq_num)) { | 684 | while (ieee80211_sn_less(tid_agg_rx->head_seq_num, head_seq_num)) { |
703 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % | 685 | index = ieee80211_sn_sub(tid_agg_rx->head_seq_num, |
686 | tid_agg_rx->ssn) % | ||
704 | tid_agg_rx->buf_size; | 687 | tid_agg_rx->buf_size; |
705 | ieee80211_release_reorder_frame(sdata, tid_agg_rx, index, | 688 | ieee80211_release_reorder_frame(sdata, tid_agg_rx, index, |
706 | frames); | 689 | frames); |
@@ -727,8 +710,8 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata, | |||
727 | lockdep_assert_held(&tid_agg_rx->reorder_lock); | 710 | lockdep_assert_held(&tid_agg_rx->reorder_lock); |
728 | 711 | ||
729 | /* release the buffer until next missing frame */ | 712 | /* release the buffer until next missing frame */ |
730 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % | 713 | index = ieee80211_sn_sub(tid_agg_rx->head_seq_num, |
731 | tid_agg_rx->buf_size; | 714 | tid_agg_rx->ssn) % tid_agg_rx->buf_size; |
732 | if (!tid_agg_rx->reorder_buf[index] && | 715 | if (!tid_agg_rx->reorder_buf[index] && |
733 | tid_agg_rx->stored_mpdu_num) { | 716 | tid_agg_rx->stored_mpdu_num) { |
734 | /* | 717 | /* |
@@ -756,19 +739,22 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata, | |||
756 | * Increment the head seq# also for the skipped slots. | 739 | * Increment the head seq# also for the skipped slots. |
757 | */ | 740 | */ |
758 | tid_agg_rx->head_seq_num = | 741 | tid_agg_rx->head_seq_num = |
759 | (tid_agg_rx->head_seq_num + skipped) & SEQ_MASK; | 742 | (tid_agg_rx->head_seq_num + |
743 | skipped) & IEEE80211_SN_MASK; | ||
760 | skipped = 0; | 744 | skipped = 0; |
761 | } | 745 | } |
762 | } else while (tid_agg_rx->reorder_buf[index]) { | 746 | } else while (tid_agg_rx->reorder_buf[index]) { |
763 | ieee80211_release_reorder_frame(sdata, tid_agg_rx, index, | 747 | ieee80211_release_reorder_frame(sdata, tid_agg_rx, index, |
764 | frames); | 748 | frames); |
765 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % | 749 | index = ieee80211_sn_sub(tid_agg_rx->head_seq_num, |
750 | tid_agg_rx->ssn) % | ||
766 | tid_agg_rx->buf_size; | 751 | tid_agg_rx->buf_size; |
767 | } | 752 | } |
768 | 753 | ||
769 | if (tid_agg_rx->stored_mpdu_num) { | 754 | if (tid_agg_rx->stored_mpdu_num) { |
770 | j = index = seq_sub(tid_agg_rx->head_seq_num, | 755 | j = index = ieee80211_sn_sub(tid_agg_rx->head_seq_num, |
771 | tid_agg_rx->ssn) % tid_agg_rx->buf_size; | 756 | tid_agg_rx->ssn) % |
757 | tid_agg_rx->buf_size; | ||
772 | 758 | ||
773 | for (; j != (index - 1) % tid_agg_rx->buf_size; | 759 | for (; j != (index - 1) % tid_agg_rx->buf_size; |
774 | j = (j + 1) % tid_agg_rx->buf_size) { | 760 | j = (j + 1) % tid_agg_rx->buf_size) { |
@@ -809,7 +795,7 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata | |||
809 | head_seq_num = tid_agg_rx->head_seq_num; | 795 | head_seq_num = tid_agg_rx->head_seq_num; |
810 | 796 | ||
811 | /* frame with out of date sequence number */ | 797 | /* frame with out of date sequence number */ |
812 | if (seq_less(mpdu_seq_num, head_seq_num)) { | 798 | if (ieee80211_sn_less(mpdu_seq_num, head_seq_num)) { |
813 | dev_kfree_skb(skb); | 799 | dev_kfree_skb(skb); |
814 | goto out; | 800 | goto out; |
815 | } | 801 | } |
@@ -818,8 +804,9 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata | |||
818 | * If frame the sequence number exceeds our buffering window | 804 | * If frame the sequence number exceeds our buffering window |
819 | * size release some previous frames to make room for this one. | 805 | * size release some previous frames to make room for this one. |
820 | */ | 806 | */ |
821 | if (!seq_less(mpdu_seq_num, head_seq_num + buf_size)) { | 807 | if (!ieee80211_sn_less(mpdu_seq_num, head_seq_num + buf_size)) { |
822 | head_seq_num = seq_inc(seq_sub(mpdu_seq_num, buf_size)); | 808 | head_seq_num = ieee80211_sn_inc( |
809 | ieee80211_sn_sub(mpdu_seq_num, buf_size)); | ||
823 | /* release stored frames up to new head to stack */ | 810 | /* release stored frames up to new head to stack */ |
824 | ieee80211_release_reorder_frames(sdata, tid_agg_rx, | 811 | ieee80211_release_reorder_frames(sdata, tid_agg_rx, |
825 | head_seq_num, frames); | 812 | head_seq_num, frames); |
@@ -827,7 +814,8 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata | |||
827 | 814 | ||
828 | /* Now the new frame is always in the range of the reordering buffer */ | 815 | /* Now the new frame is always in the range of the reordering buffer */ |
829 | 816 | ||
830 | index = seq_sub(mpdu_seq_num, tid_agg_rx->ssn) % tid_agg_rx->buf_size; | 817 | index = ieee80211_sn_sub(mpdu_seq_num, |
818 | tid_agg_rx->ssn) % tid_agg_rx->buf_size; | ||
831 | 819 | ||
832 | /* check if we already stored this frame */ | 820 | /* check if we already stored this frame */ |
833 | if (tid_agg_rx->reorder_buf[index]) { | 821 | if (tid_agg_rx->reorder_buf[index]) { |
@@ -843,7 +831,8 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata | |||
843 | */ | 831 | */ |
844 | if (mpdu_seq_num == tid_agg_rx->head_seq_num && | 832 | if (mpdu_seq_num == tid_agg_rx->head_seq_num && |
845 | tid_agg_rx->stored_mpdu_num == 0) { | 833 | tid_agg_rx->stored_mpdu_num == 0) { |
846 | tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); | 834 | tid_agg_rx->head_seq_num = |
835 | ieee80211_sn_inc(tid_agg_rx->head_seq_num); | ||
847 | ret = false; | 836 | ret = false; |
848 | goto out; | 837 | goto out; |
849 | } | 838 | } |
@@ -1894,8 +1883,10 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) | |||
1894 | * 'align' will only take the values 0 or 2 here | 1883 | * 'align' will only take the values 0 or 2 here |
1895 | * since all frames are required to be aligned | 1884 | * since all frames are required to be aligned |
1896 | * to 2-byte boundaries when being passed to | 1885 | * to 2-byte boundaries when being passed to |
1897 | * mac80211. That also explains the __skb_push() | 1886 | * mac80211; the code here works just as well if |
1898 | * below. | 1887 | * that isn't true, but mac80211 assumes it can |
1888 | * access fields as 2-byte aligned (e.g. for | ||
1889 | * compare_ether_addr) | ||
1899 | */ | 1890 | */ |
1900 | align = ((unsigned long)(skb->data + sizeof(struct ethhdr))) & 3; | 1891 | align = ((unsigned long)(skb->data + sizeof(struct ethhdr))) & 3; |
1901 | if (align) { | 1892 | if (align) { |
@@ -2552,7 +2543,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2552 | case WLAN_SP_MESH_PEERING_CONFIRM: | 2543 | case WLAN_SP_MESH_PEERING_CONFIRM: |
2553 | if (!ieee80211_vif_is_mesh(&sdata->vif)) | 2544 | if (!ieee80211_vif_is_mesh(&sdata->vif)) |
2554 | goto invalid; | 2545 | goto invalid; |
2555 | if (sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE) | 2546 | if (sdata->u.mesh.user_mpm) |
2556 | /* userspace handles this frame */ | 2547 | /* userspace handles this frame */ |
2557 | break; | 2548 | break; |
2558 | goto queue; | 2549 | goto queue; |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index a79ce820cb50..3644ad79688a 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -342,6 +342,11 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
342 | INIT_WORK(&sta->drv_unblock_wk, sta_unblock); | 342 | INIT_WORK(&sta->drv_unblock_wk, sta_unblock); |
343 | INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work); | 343 | INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work); |
344 | mutex_init(&sta->ampdu_mlme.mtx); | 344 | mutex_init(&sta->ampdu_mlme.mtx); |
345 | #ifdef CONFIG_MAC80211_MESH | ||
346 | if (ieee80211_vif_is_mesh(&sdata->vif) && | ||
347 | !sdata->u.mesh.user_mpm) | ||
348 | init_timer(&sta->plink_timer); | ||
349 | #endif | ||
345 | 350 | ||
346 | memcpy(sta->sta.addr, addr, ETH_ALEN); | 351 | memcpy(sta->sta.addr, addr, ETH_ALEN); |
347 | sta->local = local; | 352 | sta->local = local; |
@@ -794,9 +799,11 @@ int __must_check __sta_info_destroy(struct sta_info *sta) | |||
794 | 799 | ||
795 | mutex_lock(&local->key_mtx); | 800 | mutex_lock(&local->key_mtx); |
796 | for (i = 0; i < NUM_DEFAULT_KEYS; i++) | 801 | for (i = 0; i < NUM_DEFAULT_KEYS; i++) |
797 | __ieee80211_key_free(key_mtx_dereference(local, sta->gtk[i])); | 802 | __ieee80211_key_free(key_mtx_dereference(local, sta->gtk[i]), |
803 | true); | ||
798 | if (sta->ptk) | 804 | if (sta->ptk) |
799 | __ieee80211_key_free(key_mtx_dereference(local, sta->ptk)); | 805 | __ieee80211_key_free(key_mtx_dereference(local, sta->ptk), |
806 | true); | ||
800 | mutex_unlock(&local->key_mtx); | 807 | mutex_unlock(&local->key_mtx); |
801 | 808 | ||
802 | sta->dead = true; | 809 | sta->dead = true; |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 4947341a2a82..e5868c32d1a3 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -281,7 +281,6 @@ struct sta_ampdu_mlme { | |||
281 | * @plink_state: peer link state | 281 | * @plink_state: peer link state |
282 | * @plink_timeout: timeout of peer link | 282 | * @plink_timeout: timeout of peer link |
283 | * @plink_timer: peer link watch timer | 283 | * @plink_timer: peer link watch timer |
284 | * @plink_timer_was_running: used by suspend/resume to restore timers | ||
285 | * @t_offset: timing offset relative to this host | 284 | * @t_offset: timing offset relative to this host |
286 | * @t_offset_setpoint: reference timing offset of this sta to be used when | 285 | * @t_offset_setpoint: reference timing offset of this sta to be used when |
287 | * calculating clockdrift | 286 | * calculating clockdrift |
@@ -379,7 +378,6 @@ struct sta_info { | |||
379 | __le16 reason; | 378 | __le16 reason; |
380 | u8 plink_retries; | 379 | u8 plink_retries; |
381 | bool ignore_plink_timer; | 380 | bool ignore_plink_timer; |
382 | bool plink_timer_was_running; | ||
383 | enum nl80211_plink_state plink_state; | 381 | enum nl80211_plink_state plink_state; |
384 | u32 plink_timeout; | 382 | u32 plink_timeout; |
385 | struct timer_list plink_timer; | 383 | struct timer_list plink_timer; |
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index 3d7cd2a0582f..e7db2b804e0c 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h | |||
@@ -1042,15 +1042,17 @@ TRACE_EVENT(drv_remain_on_channel, | |||
1042 | TP_PROTO(struct ieee80211_local *local, | 1042 | TP_PROTO(struct ieee80211_local *local, |
1043 | struct ieee80211_sub_if_data *sdata, | 1043 | struct ieee80211_sub_if_data *sdata, |
1044 | struct ieee80211_channel *chan, | 1044 | struct ieee80211_channel *chan, |
1045 | unsigned int duration), | 1045 | unsigned int duration, |
1046 | enum ieee80211_roc_type type), | ||
1046 | 1047 | ||
1047 | TP_ARGS(local, sdata, chan, duration), | 1048 | TP_ARGS(local, sdata, chan, duration, type), |
1048 | 1049 | ||
1049 | TP_STRUCT__entry( | 1050 | TP_STRUCT__entry( |
1050 | LOCAL_ENTRY | 1051 | LOCAL_ENTRY |
1051 | VIF_ENTRY | 1052 | VIF_ENTRY |
1052 | __field(int, center_freq) | 1053 | __field(int, center_freq) |
1053 | __field(unsigned int, duration) | 1054 | __field(unsigned int, duration) |
1055 | __field(u32, type) | ||
1054 | ), | 1056 | ), |
1055 | 1057 | ||
1056 | TP_fast_assign( | 1058 | TP_fast_assign( |
@@ -1058,12 +1060,13 @@ TRACE_EVENT(drv_remain_on_channel, | |||
1058 | VIF_ASSIGN; | 1060 | VIF_ASSIGN; |
1059 | __entry->center_freq = chan->center_freq; | 1061 | __entry->center_freq = chan->center_freq; |
1060 | __entry->duration = duration; | 1062 | __entry->duration = duration; |
1063 | __entry->type = type; | ||
1061 | ), | 1064 | ), |
1062 | 1065 | ||
1063 | TP_printk( | 1066 | TP_printk( |
1064 | LOCAL_PR_FMT VIF_PR_FMT " freq:%dMHz duration:%dms", | 1067 | LOCAL_PR_FMT VIF_PR_FMT " freq:%dMHz duration:%dms type=%d", |
1065 | LOCAL_PR_ARG, VIF_PR_ARG, | 1068 | LOCAL_PR_ARG, VIF_PR_ARG, |
1066 | __entry->center_freq, __entry->duration | 1069 | __entry->center_freq, __entry->duration, __entry->type |
1067 | ) | 1070 | ) |
1068 | ); | 1071 | ); |
1069 | 1072 | ||
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 0f38f43ac62e..b7a856e3281b 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -1357,6 +1357,25 @@ void ieee80211_stop_device(struct ieee80211_local *local) | |||
1357 | drv_stop(local); | 1357 | drv_stop(local); |
1358 | } | 1358 | } |
1359 | 1359 | ||
1360 | static void ieee80211_assign_chanctx(struct ieee80211_local *local, | ||
1361 | struct ieee80211_sub_if_data *sdata) | ||
1362 | { | ||
1363 | struct ieee80211_chanctx_conf *conf; | ||
1364 | struct ieee80211_chanctx *ctx; | ||
1365 | |||
1366 | if (!local->use_chanctx) | ||
1367 | return; | ||
1368 | |||
1369 | mutex_lock(&local->chanctx_mtx); | ||
1370 | conf = rcu_dereference_protected(sdata->vif.chanctx_conf, | ||
1371 | lockdep_is_held(&local->chanctx_mtx)); | ||
1372 | if (conf) { | ||
1373 | ctx = container_of(conf, struct ieee80211_chanctx, conf); | ||
1374 | drv_assign_vif_chanctx(local, sdata, ctx); | ||
1375 | } | ||
1376 | mutex_unlock(&local->chanctx_mtx); | ||
1377 | } | ||
1378 | |||
1360 | int ieee80211_reconfig(struct ieee80211_local *local) | 1379 | int ieee80211_reconfig(struct ieee80211_local *local) |
1361 | { | 1380 | { |
1362 | struct ieee80211_hw *hw = &local->hw; | 1381 | struct ieee80211_hw *hw = &local->hw; |
@@ -1445,36 +1464,14 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1445 | } | 1464 | } |
1446 | 1465 | ||
1447 | list_for_each_entry(sdata, &local->interfaces, list) { | 1466 | list_for_each_entry(sdata, &local->interfaces, list) { |
1448 | struct ieee80211_chanctx_conf *ctx_conf; | ||
1449 | |||
1450 | if (!ieee80211_sdata_running(sdata)) | 1467 | if (!ieee80211_sdata_running(sdata)) |
1451 | continue; | 1468 | continue; |
1452 | 1469 | ieee80211_assign_chanctx(local, sdata); | |
1453 | mutex_lock(&local->chanctx_mtx); | ||
1454 | ctx_conf = rcu_dereference_protected(sdata->vif.chanctx_conf, | ||
1455 | lockdep_is_held(&local->chanctx_mtx)); | ||
1456 | if (ctx_conf) { | ||
1457 | ctx = container_of(ctx_conf, struct ieee80211_chanctx, | ||
1458 | conf); | ||
1459 | drv_assign_vif_chanctx(local, sdata, ctx); | ||
1460 | } | ||
1461 | mutex_unlock(&local->chanctx_mtx); | ||
1462 | } | 1470 | } |
1463 | 1471 | ||
1464 | sdata = rtnl_dereference(local->monitor_sdata); | 1472 | sdata = rtnl_dereference(local->monitor_sdata); |
1465 | if (sdata && local->use_chanctx && ieee80211_sdata_running(sdata)) { | 1473 | if (sdata && ieee80211_sdata_running(sdata)) |
1466 | struct ieee80211_chanctx_conf *ctx_conf; | 1474 | ieee80211_assign_chanctx(local, sdata); |
1467 | |||
1468 | mutex_lock(&local->chanctx_mtx); | ||
1469 | ctx_conf = rcu_dereference_protected(sdata->vif.chanctx_conf, | ||
1470 | lockdep_is_held(&local->chanctx_mtx)); | ||
1471 | if (ctx_conf) { | ||
1472 | ctx = container_of(ctx_conf, struct ieee80211_chanctx, | ||
1473 | conf); | ||
1474 | drv_assign_vif_chanctx(local, sdata, ctx); | ||
1475 | } | ||
1476 | mutex_unlock(&local->chanctx_mtx); | ||
1477 | } | ||
1478 | 1475 | ||
1479 | /* add STAs back */ | 1476 | /* add STAs back */ |
1480 | mutex_lock(&local->sta_mtx); | 1477 | mutex_lock(&local->sta_mtx); |
@@ -1534,11 +1531,6 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1534 | BSS_CHANGED_IDLE | | 1531 | BSS_CHANGED_IDLE | |
1535 | BSS_CHANGED_TXPOWER; | 1532 | BSS_CHANGED_TXPOWER; |
1536 | 1533 | ||
1537 | #ifdef CONFIG_PM | ||
1538 | if (local->resuming && !reconfig_due_to_wowlan) | ||
1539 | sdata->vif.bss_conf = sdata->suspend_bss_conf; | ||
1540 | #endif | ||
1541 | |||
1542 | switch (sdata->vif.type) { | 1534 | switch (sdata->vif.type) { |
1543 | case NL80211_IFTYPE_STATION: | 1535 | case NL80211_IFTYPE_STATION: |
1544 | changed |= BSS_CHANGED_ASSOC | | 1536 | changed |= BSS_CHANGED_ASSOC | |
@@ -1678,28 +1670,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1678 | mb(); | 1670 | mb(); |
1679 | local->resuming = false; | 1671 | local->resuming = false; |
1680 | 1672 | ||
1681 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
1682 | switch(sdata->vif.type) { | ||
1683 | case NL80211_IFTYPE_STATION: | ||
1684 | ieee80211_sta_restart(sdata); | ||
1685 | break; | ||
1686 | case NL80211_IFTYPE_ADHOC: | ||
1687 | ieee80211_ibss_restart(sdata); | ||
1688 | break; | ||
1689 | case NL80211_IFTYPE_MESH_POINT: | ||
1690 | ieee80211_mesh_restart(sdata); | ||
1691 | break; | ||
1692 | default: | ||
1693 | break; | ||
1694 | } | ||
1695 | } | ||
1696 | |||
1697 | mod_timer(&local->sta_cleanup, jiffies + 1); | 1673 | mod_timer(&local->sta_cleanup, jiffies + 1); |
1698 | |||
1699 | mutex_lock(&local->sta_mtx); | ||
1700 | list_for_each_entry(sta, &local->sta_list, list) | ||
1701 | mesh_plink_restart(sta); | ||
1702 | mutex_unlock(&local->sta_mtx); | ||
1703 | #else | 1674 | #else |
1704 | WARN_ON(1); | 1675 | WARN_ON(1); |
1705 | #endif | 1676 | #endif |
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c index a2c2258bc84e..171344d4eb7c 100644 --- a/net/mac80211/vht.c +++ b/net/mac80211/vht.c | |||
@@ -13,6 +13,104 @@ | |||
13 | #include "rate.h" | 13 | #include "rate.h" |
14 | 14 | ||
15 | 15 | ||
16 | static void __check_vhtcap_disable(struct ieee80211_sub_if_data *sdata, | ||
17 | struct ieee80211_sta_vht_cap *vht_cap, | ||
18 | u32 flag) | ||
19 | { | ||
20 | __le32 le_flag = cpu_to_le32(flag); | ||
21 | |||
22 | if (sdata->u.mgd.vht_capa_mask.vht_cap_info & le_flag && | ||
23 | !(sdata->u.mgd.vht_capa.vht_cap_info & le_flag)) | ||
24 | vht_cap->cap &= ~flag; | ||
25 | } | ||
26 | |||
27 | void ieee80211_apply_vhtcap_overrides(struct ieee80211_sub_if_data *sdata, | ||
28 | struct ieee80211_sta_vht_cap *vht_cap) | ||
29 | { | ||
30 | int i; | ||
31 | u16 rxmcs_mask, rxmcs_cap, rxmcs_n, txmcs_mask, txmcs_cap, txmcs_n; | ||
32 | |||
33 | if (!vht_cap->vht_supported) | ||
34 | return; | ||
35 | |||
36 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | ||
37 | return; | ||
38 | |||
39 | __check_vhtcap_disable(sdata, vht_cap, | ||
40 | IEEE80211_VHT_CAP_RXLDPC); | ||
41 | __check_vhtcap_disable(sdata, vht_cap, | ||
42 | IEEE80211_VHT_CAP_SHORT_GI_80); | ||
43 | __check_vhtcap_disable(sdata, vht_cap, | ||
44 | IEEE80211_VHT_CAP_SHORT_GI_160); | ||
45 | __check_vhtcap_disable(sdata, vht_cap, | ||
46 | IEEE80211_VHT_CAP_TXSTBC); | ||
47 | __check_vhtcap_disable(sdata, vht_cap, | ||
48 | IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE); | ||
49 | __check_vhtcap_disable(sdata, vht_cap, | ||
50 | IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE); | ||
51 | __check_vhtcap_disable(sdata, vht_cap, | ||
52 | IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN); | ||
53 | __check_vhtcap_disable(sdata, vht_cap, | ||
54 | IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN); | ||
55 | |||
56 | /* Allow user to decrease AMPDU length exponent */ | ||
57 | if (sdata->u.mgd.vht_capa_mask.vht_cap_info & | ||
58 | cpu_to_le32(IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK)) { | ||
59 | u32 cap, n; | ||
60 | |||
61 | n = le32_to_cpu(sdata->u.mgd.vht_capa.vht_cap_info) & | ||
62 | IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; | ||
63 | n >>= IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT; | ||
64 | cap = vht_cap->cap & IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; | ||
65 | cap >>= IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT; | ||
66 | |||
67 | if (n < cap) { | ||
68 | vht_cap->cap &= | ||
69 | ~IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; | ||
70 | vht_cap->cap |= | ||
71 | n << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT; | ||
72 | } | ||
73 | } | ||
74 | |||
75 | /* Allow the user to decrease MCSes */ | ||
76 | rxmcs_mask = | ||
77 | le16_to_cpu(sdata->u.mgd.vht_capa_mask.supp_mcs.rx_mcs_map); | ||
78 | rxmcs_n = le16_to_cpu(sdata->u.mgd.vht_capa.supp_mcs.rx_mcs_map); | ||
79 | rxmcs_n &= rxmcs_mask; | ||
80 | rxmcs_cap = le16_to_cpu(vht_cap->vht_mcs.rx_mcs_map); | ||
81 | |||
82 | txmcs_mask = | ||
83 | le16_to_cpu(sdata->u.mgd.vht_capa_mask.supp_mcs.tx_mcs_map); | ||
84 | txmcs_n = le16_to_cpu(sdata->u.mgd.vht_capa.supp_mcs.tx_mcs_map); | ||
85 | txmcs_n &= txmcs_mask; | ||
86 | txmcs_cap = le16_to_cpu(vht_cap->vht_mcs.tx_mcs_map); | ||
87 | for (i = 0; i < 8; i++) { | ||
88 | u8 m, n, c; | ||
89 | |||
90 | m = (rxmcs_mask >> 2*i) & IEEE80211_VHT_MCS_NOT_SUPPORTED; | ||
91 | n = (rxmcs_n >> 2*i) & IEEE80211_VHT_MCS_NOT_SUPPORTED; | ||
92 | c = (rxmcs_cap >> 2*i) & IEEE80211_VHT_MCS_NOT_SUPPORTED; | ||
93 | |||
94 | if (m && ((c != IEEE80211_VHT_MCS_NOT_SUPPORTED && n < c) || | ||
95 | n == IEEE80211_VHT_MCS_NOT_SUPPORTED)) { | ||
96 | rxmcs_cap &= ~(3 << 2*i); | ||
97 | rxmcs_cap |= (rxmcs_n & (3 << 2*i)); | ||
98 | } | ||
99 | |||
100 | m = (txmcs_mask >> 2*i) & IEEE80211_VHT_MCS_NOT_SUPPORTED; | ||
101 | n = (txmcs_n >> 2*i) & IEEE80211_VHT_MCS_NOT_SUPPORTED; | ||
102 | c = (txmcs_cap >> 2*i) & IEEE80211_VHT_MCS_NOT_SUPPORTED; | ||
103 | |||
104 | if (m && ((c != IEEE80211_VHT_MCS_NOT_SUPPORTED && n < c) || | ||
105 | n == IEEE80211_VHT_MCS_NOT_SUPPORTED)) { | ||
106 | txmcs_cap &= ~(3 << 2*i); | ||
107 | txmcs_cap |= (txmcs_n & (3 << 2*i)); | ||
108 | } | ||
109 | } | ||
110 | vht_cap->vht_mcs.rx_mcs_map = cpu_to_le16(rxmcs_cap); | ||
111 | vht_cap->vht_mcs.tx_mcs_map = cpu_to_le16(txmcs_cap); | ||
112 | } | ||
113 | |||
16 | void | 114 | void |
17 | ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, | 115 | ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, |
18 | struct ieee80211_supported_band *sband, | 116 | struct ieee80211_supported_band *sband, |
@@ -20,6 +118,8 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, | |||
20 | struct sta_info *sta) | 118 | struct sta_info *sta) |
21 | { | 119 | { |
22 | struct ieee80211_sta_vht_cap *vht_cap = &sta->sta.vht_cap; | 120 | struct ieee80211_sta_vht_cap *vht_cap = &sta->sta.vht_cap; |
121 | struct ieee80211_sta_vht_cap own_cap; | ||
122 | u32 cap_info, i; | ||
23 | 123 | ||
24 | memset(vht_cap, 0, sizeof(*vht_cap)); | 124 | memset(vht_cap, 0, sizeof(*vht_cap)); |
25 | 125 | ||
@@ -35,12 +135,122 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, | |||
35 | 135 | ||
36 | vht_cap->vht_supported = true; | 136 | vht_cap->vht_supported = true; |
37 | 137 | ||
38 | vht_cap->cap = le32_to_cpu(vht_cap_ie->vht_cap_info); | 138 | own_cap = sband->vht_cap; |
139 | /* | ||
140 | * If user has specified capability overrides, take care | ||
141 | * of that if the station we're setting up is the AP that | ||
142 | * we advertised a restricted capability set to. Override | ||
143 | * our own capabilities and then use those below. | ||
144 | */ | ||
145 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | ||
146 | !test_sta_flag(sta, WLAN_STA_TDLS_PEER)) | ||
147 | ieee80211_apply_vhtcap_overrides(sdata, &own_cap); | ||
148 | |||
149 | /* take some capabilities as-is */ | ||
150 | cap_info = le32_to_cpu(vht_cap_ie->vht_cap_info); | ||
151 | vht_cap->cap = cap_info; | ||
152 | vht_cap->cap &= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 | | ||
153 | IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 | | ||
154 | IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | | ||
155 | IEEE80211_VHT_CAP_RXLDPC | | ||
156 | IEEE80211_VHT_CAP_VHT_TXOP_PS | | ||
157 | IEEE80211_VHT_CAP_HTC_VHT | | ||
158 | IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK | | ||
159 | IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB | | ||
160 | IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB | | ||
161 | IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN | | ||
162 | IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN; | ||
163 | |||
164 | /* and some based on our own capabilities */ | ||
165 | switch (own_cap.cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) { | ||
166 | case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ: | ||
167 | vht_cap->cap |= cap_info & | ||
168 | IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ; | ||
169 | break; | ||
170 | case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ: | ||
171 | vht_cap->cap |= cap_info & | ||
172 | IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK; | ||
173 | break; | ||
174 | default: | ||
175 | /* nothing */ | ||
176 | break; | ||
177 | } | ||
178 | |||
179 | /* symmetric capabilities */ | ||
180 | vht_cap->cap |= cap_info & own_cap.cap & | ||
181 | (IEEE80211_VHT_CAP_SHORT_GI_80 | | ||
182 | IEEE80211_VHT_CAP_SHORT_GI_160); | ||
183 | |||
184 | /* remaining ones */ | ||
185 | if (own_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE) { | ||
186 | vht_cap->cap |= cap_info & | ||
187 | (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE | | ||
188 | IEEE80211_VHT_CAP_BEAMFORMER_ANTENNAS_MAX | | ||
189 | IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MAX); | ||
190 | } | ||
191 | |||
192 | if (own_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE) | ||
193 | vht_cap->cap |= cap_info & | ||
194 | IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE; | ||
195 | |||
196 | if (own_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) | ||
197 | vht_cap->cap |= cap_info & | ||
198 | IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE; | ||
199 | |||
200 | if (own_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE) | ||
201 | vht_cap->cap |= cap_info & | ||
202 | IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE; | ||
203 | |||
204 | if (own_cap.cap & IEEE80211_VHT_CAP_TXSTBC) | ||
205 | vht_cap->cap |= cap_info & IEEE80211_VHT_CAP_RXSTBC_MASK; | ||
206 | |||
207 | if (own_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK) | ||
208 | vht_cap->cap |= cap_info & IEEE80211_VHT_CAP_TXSTBC; | ||
39 | 209 | ||
40 | /* Copy peer MCS info, the driver might need them. */ | 210 | /* Copy peer MCS info, the driver might need them. */ |
41 | memcpy(&vht_cap->vht_mcs, &vht_cap_ie->supp_mcs, | 211 | memcpy(&vht_cap->vht_mcs, &vht_cap_ie->supp_mcs, |
42 | sizeof(struct ieee80211_vht_mcs_info)); | 212 | sizeof(struct ieee80211_vht_mcs_info)); |
43 | 213 | ||
214 | /* but also restrict MCSes */ | ||
215 | for (i = 0; i < 8; i++) { | ||
216 | u16 own_rx, own_tx, peer_rx, peer_tx; | ||
217 | |||
218 | own_rx = le16_to_cpu(own_cap.vht_mcs.rx_mcs_map); | ||
219 | own_rx = (own_rx >> i * 2) & IEEE80211_VHT_MCS_NOT_SUPPORTED; | ||
220 | |||
221 | own_tx = le16_to_cpu(own_cap.vht_mcs.tx_mcs_map); | ||
222 | own_tx = (own_tx >> i * 2) & IEEE80211_VHT_MCS_NOT_SUPPORTED; | ||
223 | |||
224 | peer_rx = le16_to_cpu(vht_cap->vht_mcs.rx_mcs_map); | ||
225 | peer_rx = (peer_rx >> i * 2) & IEEE80211_VHT_MCS_NOT_SUPPORTED; | ||
226 | |||
227 | peer_tx = le16_to_cpu(vht_cap->vht_mcs.tx_mcs_map); | ||
228 | peer_tx = (peer_tx >> i * 2) & IEEE80211_VHT_MCS_NOT_SUPPORTED; | ||
229 | |||
230 | if (peer_tx != IEEE80211_VHT_MCS_NOT_SUPPORTED) { | ||
231 | if (own_rx == IEEE80211_VHT_MCS_NOT_SUPPORTED) | ||
232 | peer_tx = IEEE80211_VHT_MCS_NOT_SUPPORTED; | ||
233 | else if (own_rx < peer_tx) | ||
234 | peer_tx = own_rx; | ||
235 | } | ||
236 | |||
237 | if (peer_rx != IEEE80211_VHT_MCS_NOT_SUPPORTED) { | ||
238 | if (own_tx == IEEE80211_VHT_MCS_NOT_SUPPORTED) | ||
239 | peer_rx = IEEE80211_VHT_MCS_NOT_SUPPORTED; | ||
240 | else if (own_tx < peer_rx) | ||
241 | peer_rx = own_tx; | ||
242 | } | ||
243 | |||
244 | vht_cap->vht_mcs.rx_mcs_map &= | ||
245 | ~cpu_to_le16(IEEE80211_VHT_MCS_NOT_SUPPORTED << i * 2); | ||
246 | vht_cap->vht_mcs.rx_mcs_map |= cpu_to_le16(peer_rx << i * 2); | ||
247 | |||
248 | vht_cap->vht_mcs.tx_mcs_map &= | ||
249 | ~cpu_to_le16(IEEE80211_VHT_MCS_NOT_SUPPORTED << i * 2); | ||
250 | vht_cap->vht_mcs.tx_mcs_map |= cpu_to_le16(peer_tx << i * 2); | ||
251 | } | ||
252 | |||
253 | /* finally set up the bandwidth */ | ||
44 | switch (vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) { | 254 | switch (vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) { |
45 | case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ: | 255 | case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ: |
46 | case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ: | 256 | case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ: |
diff --git a/net/nfc/llcp/commands.c b/net/nfc/llcp/commands.c index c6bc3bd95052..b75a9b3f9e89 100644 --- a/net/nfc/llcp/commands.c +++ b/net/nfc/llcp/commands.c | |||
@@ -117,6 +117,88 @@ u8 *nfc_llcp_build_tlv(u8 type, u8 *value, u8 value_length, u8 *tlv_length) | |||
117 | return tlv; | 117 | return tlv; |
118 | } | 118 | } |
119 | 119 | ||
120 | struct nfc_llcp_sdp_tlv *nfc_llcp_build_sdres_tlv(u8 tid, u8 sap) | ||
121 | { | ||
122 | struct nfc_llcp_sdp_tlv *sdres; | ||
123 | u8 value[2]; | ||
124 | |||
125 | sdres = kzalloc(sizeof(struct nfc_llcp_sdp_tlv), GFP_KERNEL); | ||
126 | if (sdres == NULL) | ||
127 | return NULL; | ||
128 | |||
129 | value[0] = tid; | ||
130 | value[1] = sap; | ||
131 | |||
132 | sdres->tlv = nfc_llcp_build_tlv(LLCP_TLV_SDRES, value, 2, | ||
133 | &sdres->tlv_len); | ||
134 | if (sdres->tlv == NULL) { | ||
135 | kfree(sdres); | ||
136 | return NULL; | ||
137 | } | ||
138 | |||
139 | sdres->tid = tid; | ||
140 | sdres->sap = sap; | ||
141 | |||
142 | INIT_HLIST_NODE(&sdres->node); | ||
143 | |||
144 | return sdres; | ||
145 | } | ||
146 | |||
147 | struct nfc_llcp_sdp_tlv *nfc_llcp_build_sdreq_tlv(u8 tid, char *uri, | ||
148 | size_t uri_len) | ||
149 | { | ||
150 | struct nfc_llcp_sdp_tlv *sdreq; | ||
151 | |||
152 | pr_debug("uri: %s, len: %zu\n", uri, uri_len); | ||
153 | |||
154 | sdreq = kzalloc(sizeof(struct nfc_llcp_sdp_tlv), GFP_KERNEL); | ||
155 | if (sdreq == NULL) | ||
156 | return NULL; | ||
157 | |||
158 | sdreq->tlv_len = uri_len + 3; | ||
159 | |||
160 | if (uri[uri_len - 1] == 0) | ||
161 | sdreq->tlv_len--; | ||
162 | |||
163 | sdreq->tlv = kzalloc(sdreq->tlv_len + 1, GFP_KERNEL); | ||
164 | if (sdreq->tlv == NULL) { | ||
165 | kfree(sdreq); | ||
166 | return NULL; | ||
167 | } | ||
168 | |||
169 | sdreq->tlv[0] = LLCP_TLV_SDREQ; | ||
170 | sdreq->tlv[1] = sdreq->tlv_len - 2; | ||
171 | sdreq->tlv[2] = tid; | ||
172 | |||
173 | sdreq->tid = tid; | ||
174 | sdreq->uri = sdreq->tlv + 3; | ||
175 | memcpy(sdreq->uri, uri, uri_len); | ||
176 | |||
177 | sdreq->time = jiffies; | ||
178 | |||
179 | INIT_HLIST_NODE(&sdreq->node); | ||
180 | |||
181 | return sdreq; | ||
182 | } | ||
183 | |||
184 | void nfc_llcp_free_sdp_tlv(struct nfc_llcp_sdp_tlv *sdp) | ||
185 | { | ||
186 | kfree(sdp->tlv); | ||
187 | kfree(sdp); | ||
188 | } | ||
189 | |||
190 | void nfc_llcp_free_sdp_tlv_list(struct hlist_head *head) | ||
191 | { | ||
192 | struct nfc_llcp_sdp_tlv *sdp; | ||
193 | struct hlist_node *n; | ||
194 | |||
195 | hlist_for_each_entry_safe(sdp, n, head, node) { | ||
196 | hlist_del(&sdp->node); | ||
197 | |||
198 | nfc_llcp_free_sdp_tlv(sdp); | ||
199 | } | ||
200 | } | ||
201 | |||
120 | int nfc_llcp_parse_gb_tlv(struct nfc_llcp_local *local, | 202 | int nfc_llcp_parse_gb_tlv(struct nfc_llcp_local *local, |
121 | u8 *tlv_array, u16 tlv_array_len) | 203 | u8 *tlv_array, u16 tlv_array_len) |
122 | { | 204 | { |
@@ -184,10 +266,10 @@ int nfc_llcp_parse_connection_tlv(struct nfc_llcp_sock *sock, | |||
184 | 266 | ||
185 | switch (type) { | 267 | switch (type) { |
186 | case LLCP_TLV_MIUX: | 268 | case LLCP_TLV_MIUX: |
187 | sock->miu = llcp_tlv_miux(tlv) + 128; | 269 | sock->remote_miu = llcp_tlv_miux(tlv) + 128; |
188 | break; | 270 | break; |
189 | case LLCP_TLV_RW: | 271 | case LLCP_TLV_RW: |
190 | sock->rw = llcp_tlv_rw(tlv); | 272 | sock->remote_rw = llcp_tlv_rw(tlv); |
191 | break; | 273 | break; |
192 | case LLCP_TLV_SN: | 274 | case LLCP_TLV_SN: |
193 | break; | 275 | break; |
@@ -200,7 +282,8 @@ int nfc_llcp_parse_connection_tlv(struct nfc_llcp_sock *sock, | |||
200 | tlv += length + 2; | 282 | tlv += length + 2; |
201 | } | 283 | } |
202 | 284 | ||
203 | pr_debug("sock %p rw %d miu %d\n", sock, sock->rw, sock->miu); | 285 | pr_debug("sock %p rw %d miu %d\n", sock, |
286 | sock->remote_rw, sock->remote_miu); | ||
204 | 287 | ||
205 | return 0; | 288 | return 0; |
206 | } | 289 | } |
@@ -318,9 +401,9 @@ int nfc_llcp_send_connect(struct nfc_llcp_sock *sock) | |||
318 | struct sk_buff *skb; | 401 | struct sk_buff *skb; |
319 | u8 *service_name_tlv = NULL, service_name_tlv_length; | 402 | u8 *service_name_tlv = NULL, service_name_tlv_length; |
320 | u8 *miux_tlv = NULL, miux_tlv_length; | 403 | u8 *miux_tlv = NULL, miux_tlv_length; |
321 | u8 *rw_tlv = NULL, rw_tlv_length; | 404 | u8 *rw_tlv = NULL, rw_tlv_length, rw; |
322 | int err; | 405 | int err; |
323 | u16 size = 0; | 406 | u16 size = 0, miux; |
324 | 407 | ||
325 | pr_debug("Sending CONNECT\n"); | 408 | pr_debug("Sending CONNECT\n"); |
326 | 409 | ||
@@ -336,11 +419,15 @@ int nfc_llcp_send_connect(struct nfc_llcp_sock *sock) | |||
336 | size += service_name_tlv_length; | 419 | size += service_name_tlv_length; |
337 | } | 420 | } |
338 | 421 | ||
339 | miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&local->miux, 0, | 422 | /* If the socket parameters are not set, use the local ones */ |
423 | miux = sock->miux > LLCP_MAX_MIUX ? local->miux : sock->miux; | ||
424 | rw = sock->rw > LLCP_MAX_RW ? local->rw : sock->rw; | ||
425 | |||
426 | miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&miux, 0, | ||
340 | &miux_tlv_length); | 427 | &miux_tlv_length); |
341 | size += miux_tlv_length; | 428 | size += miux_tlv_length; |
342 | 429 | ||
343 | rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &local->rw, 0, &rw_tlv_length); | 430 | rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &rw, 0, &rw_tlv_length); |
344 | size += rw_tlv_length; | 431 | size += rw_tlv_length; |
345 | 432 | ||
346 | pr_debug("SKB size %d SN length %zu\n", size, sock->service_name_len); | 433 | pr_debug("SKB size %d SN length %zu\n", size, sock->service_name_len); |
@@ -377,9 +464,9 @@ int nfc_llcp_send_cc(struct nfc_llcp_sock *sock) | |||
377 | struct nfc_llcp_local *local; | 464 | struct nfc_llcp_local *local; |
378 | struct sk_buff *skb; | 465 | struct sk_buff *skb; |
379 | u8 *miux_tlv = NULL, miux_tlv_length; | 466 | u8 *miux_tlv = NULL, miux_tlv_length; |
380 | u8 *rw_tlv = NULL, rw_tlv_length; | 467 | u8 *rw_tlv = NULL, rw_tlv_length, rw; |
381 | int err; | 468 | int err; |
382 | u16 size = 0; | 469 | u16 size = 0, miux; |
383 | 470 | ||
384 | pr_debug("Sending CC\n"); | 471 | pr_debug("Sending CC\n"); |
385 | 472 | ||
@@ -387,11 +474,15 @@ int nfc_llcp_send_cc(struct nfc_llcp_sock *sock) | |||
387 | if (local == NULL) | 474 | if (local == NULL) |
388 | return -ENODEV; | 475 | return -ENODEV; |
389 | 476 | ||
390 | miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&local->miux, 0, | 477 | /* If the socket parameters are not set, use the local ones */ |
478 | miux = sock->miux > LLCP_MAX_MIUX ? local->miux : sock->miux; | ||
479 | rw = sock->rw > LLCP_MAX_RW ? local->rw : sock->rw; | ||
480 | |||
481 | miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&miux, 0, | ||
391 | &miux_tlv_length); | 482 | &miux_tlv_length); |
392 | size += miux_tlv_length; | 483 | size += miux_tlv_length; |
393 | 484 | ||
394 | rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &local->rw, 0, &rw_tlv_length); | 485 | rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &rw, 0, &rw_tlv_length); |
395 | size += rw_tlv_length; | 486 | size += rw_tlv_length; |
396 | 487 | ||
397 | skb = llcp_allocate_pdu(sock, LLCP_PDU_CC, size); | 488 | skb = llcp_allocate_pdu(sock, LLCP_PDU_CC, size); |
@@ -416,48 +507,90 @@ error_tlv: | |||
416 | return err; | 507 | return err; |
417 | } | 508 | } |
418 | 509 | ||
419 | int nfc_llcp_send_snl(struct nfc_llcp_local *local, u8 tid, u8 sap) | 510 | static struct sk_buff *nfc_llcp_allocate_snl(struct nfc_llcp_local *local, |
511 | size_t tlv_length) | ||
420 | { | 512 | { |
421 | struct sk_buff *skb; | 513 | struct sk_buff *skb; |
422 | struct nfc_dev *dev; | 514 | struct nfc_dev *dev; |
423 | u8 *sdres_tlv = NULL, sdres_tlv_length, sdres[2]; | ||
424 | u16 size = 0; | 515 | u16 size = 0; |
425 | 516 | ||
426 | pr_debug("Sending SNL tid 0x%x sap 0x%x\n", tid, sap); | ||
427 | |||
428 | if (local == NULL) | 517 | if (local == NULL) |
429 | return -ENODEV; | 518 | return ERR_PTR(-ENODEV); |
430 | 519 | ||
431 | dev = local->dev; | 520 | dev = local->dev; |
432 | if (dev == NULL) | 521 | if (dev == NULL) |
433 | return -ENODEV; | 522 | return ERR_PTR(-ENODEV); |
434 | |||
435 | sdres[0] = tid; | ||
436 | sdres[1] = sap; | ||
437 | sdres_tlv = nfc_llcp_build_tlv(LLCP_TLV_SDRES, sdres, 0, | ||
438 | &sdres_tlv_length); | ||
439 | if (sdres_tlv == NULL) | ||
440 | return -ENOMEM; | ||
441 | 523 | ||
442 | size += LLCP_HEADER_SIZE; | 524 | size += LLCP_HEADER_SIZE; |
443 | size += dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE; | 525 | size += dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE; |
444 | size += sdres_tlv_length; | 526 | size += tlv_length; |
445 | 527 | ||
446 | skb = alloc_skb(size, GFP_KERNEL); | 528 | skb = alloc_skb(size, GFP_KERNEL); |
447 | if (skb == NULL) { | 529 | if (skb == NULL) |
448 | kfree(sdres_tlv); | 530 | return ERR_PTR(-ENOMEM); |
449 | return -ENOMEM; | ||
450 | } | ||
451 | 531 | ||
452 | skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE); | 532 | skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE); |
453 | 533 | ||
454 | skb = llcp_add_header(skb, LLCP_SAP_SDP, LLCP_SAP_SDP, LLCP_PDU_SNL); | 534 | skb = llcp_add_header(skb, LLCP_SAP_SDP, LLCP_SAP_SDP, LLCP_PDU_SNL); |
455 | 535 | ||
456 | memcpy(skb_put(skb, sdres_tlv_length), sdres_tlv, sdres_tlv_length); | 536 | return skb; |
537 | } | ||
538 | |||
539 | int nfc_llcp_send_snl_sdres(struct nfc_llcp_local *local, | ||
540 | struct hlist_head *tlv_list, size_t tlvs_len) | ||
541 | { | ||
542 | struct nfc_llcp_sdp_tlv *sdp; | ||
543 | struct hlist_node *n; | ||
544 | struct sk_buff *skb; | ||
545 | |||
546 | skb = nfc_llcp_allocate_snl(local, tlvs_len); | ||
547 | if (IS_ERR(skb)) | ||
548 | return PTR_ERR(skb); | ||
549 | |||
550 | hlist_for_each_entry_safe(sdp, n, tlv_list, node) { | ||
551 | memcpy(skb_put(skb, sdp->tlv_len), sdp->tlv, sdp->tlv_len); | ||
552 | |||
553 | hlist_del(&sdp->node); | ||
554 | |||
555 | nfc_llcp_free_sdp_tlv(sdp); | ||
556 | } | ||
457 | 557 | ||
458 | skb_queue_tail(&local->tx_queue, skb); | 558 | skb_queue_tail(&local->tx_queue, skb); |
459 | 559 | ||
460 | kfree(sdres_tlv); | 560 | return 0; |
561 | } | ||
562 | |||
563 | int nfc_llcp_send_snl_sdreq(struct nfc_llcp_local *local, | ||
564 | struct hlist_head *tlv_list, size_t tlvs_len) | ||
565 | { | ||
566 | struct nfc_llcp_sdp_tlv *sdreq; | ||
567 | struct hlist_node *n; | ||
568 | struct sk_buff *skb; | ||
569 | |||
570 | skb = nfc_llcp_allocate_snl(local, tlvs_len); | ||
571 | if (IS_ERR(skb)) | ||
572 | return PTR_ERR(skb); | ||
573 | |||
574 | mutex_lock(&local->sdreq_lock); | ||
575 | |||
576 | if (hlist_empty(&local->pending_sdreqs)) | ||
577 | mod_timer(&local->sdreq_timer, | ||
578 | jiffies + msecs_to_jiffies(3 * local->remote_lto)); | ||
579 | |||
580 | hlist_for_each_entry_safe(sdreq, n, tlv_list, node) { | ||
581 | pr_debug("tid %d for %s\n", sdreq->tid, sdreq->uri); | ||
582 | |||
583 | memcpy(skb_put(skb, sdreq->tlv_len), sdreq->tlv, | ||
584 | sdreq->tlv_len); | ||
585 | |||
586 | hlist_del(&sdreq->node); | ||
587 | |||
588 | hlist_add_head(&sdreq->node, &local->pending_sdreqs); | ||
589 | } | ||
590 | |||
591 | mutex_unlock(&local->sdreq_lock); | ||
592 | |||
593 | skb_queue_tail(&local->tx_queue, skb); | ||
461 | 594 | ||
462 | return 0; | 595 | return 0; |
463 | } | 596 | } |
@@ -532,8 +665,8 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock, | |||
532 | 665 | ||
533 | /* Remote is ready but has not acknowledged our frames */ | 666 | /* Remote is ready but has not acknowledged our frames */ |
534 | if((sock->remote_ready && | 667 | if((sock->remote_ready && |
535 | skb_queue_len(&sock->tx_pending_queue) >= sock->rw && | 668 | skb_queue_len(&sock->tx_pending_queue) >= sock->remote_rw && |
536 | skb_queue_len(&sock->tx_queue) >= 2 * sock->rw)) { | 669 | skb_queue_len(&sock->tx_queue) >= 2 * sock->remote_rw)) { |
537 | pr_err("Pending queue is full %d frames\n", | 670 | pr_err("Pending queue is full %d frames\n", |
538 | skb_queue_len(&sock->tx_pending_queue)); | 671 | skb_queue_len(&sock->tx_pending_queue)); |
539 | return -ENOBUFS; | 672 | return -ENOBUFS; |
@@ -541,7 +674,7 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock, | |||
541 | 674 | ||
542 | /* Remote is not ready and we've been queueing enough frames */ | 675 | /* Remote is not ready and we've been queueing enough frames */ |
543 | if ((!sock->remote_ready && | 676 | if ((!sock->remote_ready && |
544 | skb_queue_len(&sock->tx_queue) >= 2 * sock->rw)) { | 677 | skb_queue_len(&sock->tx_queue) >= 2 * sock->remote_rw)) { |
545 | pr_err("Tx queue is full %d frames\n", | 678 | pr_err("Tx queue is full %d frames\n", |
546 | skb_queue_len(&sock->tx_queue)); | 679 | skb_queue_len(&sock->tx_queue)); |
547 | return -ENOBUFS; | 680 | return -ENOBUFS; |
@@ -561,7 +694,7 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock, | |||
561 | 694 | ||
562 | while (remaining_len > 0) { | 695 | while (remaining_len > 0) { |
563 | 696 | ||
564 | frag_len = min_t(size_t, sock->miu, remaining_len); | 697 | frag_len = min_t(size_t, sock->remote_miu, remaining_len); |
565 | 698 | ||
566 | pr_debug("Fragment %zd bytes remaining %zd", | 699 | pr_debug("Fragment %zd bytes remaining %zd", |
567 | frag_len, remaining_len); | 700 | frag_len, remaining_len); |
@@ -621,7 +754,7 @@ int nfc_llcp_send_ui_frame(struct nfc_llcp_sock *sock, u8 ssap, u8 dsap, | |||
621 | 754 | ||
622 | while (remaining_len > 0) { | 755 | while (remaining_len > 0) { |
623 | 756 | ||
624 | frag_len = min_t(size_t, sock->miu, remaining_len); | 757 | frag_len = min_t(size_t, sock->remote_miu, remaining_len); |
625 | 758 | ||
626 | pr_debug("Fragment %zd bytes remaining %zd", | 759 | pr_debug("Fragment %zd bytes remaining %zd", |
627 | frag_len, remaining_len); | 760 | frag_len, remaining_len); |
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c index b530afadd76c..bb67b98b9797 100644 --- a/net/nfc/llcp/llcp.c +++ b/net/nfc/llcp/llcp.c | |||
@@ -188,6 +188,9 @@ static void local_cleanup(struct nfc_llcp_local *local, bool listen) | |||
188 | cancel_work_sync(&local->rx_work); | 188 | cancel_work_sync(&local->rx_work); |
189 | cancel_work_sync(&local->timeout_work); | 189 | cancel_work_sync(&local->timeout_work); |
190 | kfree_skb(local->rx_pending); | 190 | kfree_skb(local->rx_pending); |
191 | del_timer_sync(&local->sdreq_timer); | ||
192 | cancel_work_sync(&local->sdreq_timeout_work); | ||
193 | nfc_llcp_free_sdp_tlv_list(&local->pending_sdreqs); | ||
191 | } | 194 | } |
192 | 195 | ||
193 | static void local_release(struct kref *ref) | 196 | static void local_release(struct kref *ref) |
@@ -265,6 +268,47 @@ static void nfc_llcp_symm_timer(unsigned long data) | |||
265 | schedule_work(&local->timeout_work); | 268 | schedule_work(&local->timeout_work); |
266 | } | 269 | } |
267 | 270 | ||
271 | static void nfc_llcp_sdreq_timeout_work(struct work_struct *work) | ||
272 | { | ||
273 | unsigned long time; | ||
274 | HLIST_HEAD(nl_sdres_list); | ||
275 | struct hlist_node *n; | ||
276 | struct nfc_llcp_sdp_tlv *sdp; | ||
277 | struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local, | ||
278 | sdreq_timeout_work); | ||
279 | |||
280 | mutex_lock(&local->sdreq_lock); | ||
281 | |||
282 | time = jiffies - msecs_to_jiffies(3 * local->remote_lto); | ||
283 | |||
284 | hlist_for_each_entry_safe(sdp, n, &local->pending_sdreqs, node) { | ||
285 | if (time_after(sdp->time, time)) | ||
286 | continue; | ||
287 | |||
288 | sdp->sap = LLCP_SDP_UNBOUND; | ||
289 | |||
290 | hlist_del(&sdp->node); | ||
291 | |||
292 | hlist_add_head(&sdp->node, &nl_sdres_list); | ||
293 | } | ||
294 | |||
295 | if (!hlist_empty(&local->pending_sdreqs)) | ||
296 | mod_timer(&local->sdreq_timer, | ||
297 | jiffies + msecs_to_jiffies(3 * local->remote_lto)); | ||
298 | |||
299 | mutex_unlock(&local->sdreq_lock); | ||
300 | |||
301 | if (!hlist_empty(&nl_sdres_list)) | ||
302 | nfc_genl_llc_send_sdres(local->dev, &nl_sdres_list); | ||
303 | } | ||
304 | |||
305 | static void nfc_llcp_sdreq_timer(unsigned long data) | ||
306 | { | ||
307 | struct nfc_llcp_local *local = (struct nfc_llcp_local *) data; | ||
308 | |||
309 | schedule_work(&local->sdreq_timeout_work); | ||
310 | } | ||
311 | |||
268 | struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev) | 312 | struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev) |
269 | { | 313 | { |
270 | struct nfc_llcp_local *local, *n; | 314 | struct nfc_llcp_local *local, *n; |
@@ -808,8 +852,6 @@ static void nfc_llcp_recv_ui(struct nfc_llcp_local *local, | |||
808 | ui_cb->dsap = dsap; | 852 | ui_cb->dsap = dsap; |
809 | ui_cb->ssap = ssap; | 853 | ui_cb->ssap = ssap; |
810 | 854 | ||
811 | printk("%s %d %d\n", __func__, dsap, ssap); | ||
812 | |||
813 | pr_debug("%d %d\n", dsap, ssap); | 855 | pr_debug("%d %d\n", dsap, ssap); |
814 | 856 | ||
815 | /* We're looking for a bound socket, not a client one */ | 857 | /* We're looking for a bound socket, not a client one */ |
@@ -907,7 +949,9 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local, | |||
907 | new_sock = nfc_llcp_sock(new_sk); | 949 | new_sock = nfc_llcp_sock(new_sk); |
908 | new_sock->dev = local->dev; | 950 | new_sock->dev = local->dev; |
909 | new_sock->local = nfc_llcp_local_get(local); | 951 | new_sock->local = nfc_llcp_local_get(local); |
910 | new_sock->miu = local->remote_miu; | 952 | new_sock->rw = sock->rw; |
953 | new_sock->miux = sock->miux; | ||
954 | new_sock->remote_miu = local->remote_miu; | ||
911 | new_sock->nfc_protocol = sock->nfc_protocol; | 955 | new_sock->nfc_protocol = sock->nfc_protocol; |
912 | new_sock->dsap = ssap; | 956 | new_sock->dsap = ssap; |
913 | new_sock->target_idx = local->target_idx; | 957 | new_sock->target_idx = local->target_idx; |
@@ -961,11 +1005,11 @@ int nfc_llcp_queue_i_frames(struct nfc_llcp_sock *sock) | |||
961 | 1005 | ||
962 | pr_debug("Remote ready %d tx queue len %d remote rw %d", | 1006 | pr_debug("Remote ready %d tx queue len %d remote rw %d", |
963 | sock->remote_ready, skb_queue_len(&sock->tx_pending_queue), | 1007 | sock->remote_ready, skb_queue_len(&sock->tx_pending_queue), |
964 | sock->rw); | 1008 | sock->remote_rw); |
965 | 1009 | ||
966 | /* Try to queue some I frames for transmission */ | 1010 | /* Try to queue some I frames for transmission */ |
967 | while (sock->remote_ready && | 1011 | while (sock->remote_ready && |
968 | skb_queue_len(&sock->tx_pending_queue) < sock->rw) { | 1012 | skb_queue_len(&sock->tx_pending_queue) < sock->remote_rw) { |
969 | struct sk_buff *pdu; | 1013 | struct sk_buff *pdu; |
970 | 1014 | ||
971 | pdu = skb_dequeue(&sock->tx_queue); | 1015 | pdu = skb_dequeue(&sock->tx_queue); |
@@ -1186,6 +1230,10 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local, | |||
1186 | u16 tlv_len, offset; | 1230 | u16 tlv_len, offset; |
1187 | char *service_name; | 1231 | char *service_name; |
1188 | size_t service_name_len; | 1232 | size_t service_name_len; |
1233 | struct nfc_llcp_sdp_tlv *sdp; | ||
1234 | HLIST_HEAD(llc_sdres_list); | ||
1235 | size_t sdres_tlvs_len; | ||
1236 | HLIST_HEAD(nl_sdres_list); | ||
1189 | 1237 | ||
1190 | dsap = nfc_llcp_dsap(skb); | 1238 | dsap = nfc_llcp_dsap(skb); |
1191 | ssap = nfc_llcp_ssap(skb); | 1239 | ssap = nfc_llcp_ssap(skb); |
@@ -1200,6 +1248,7 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local, | |||
1200 | tlv = &skb->data[LLCP_HEADER_SIZE]; | 1248 | tlv = &skb->data[LLCP_HEADER_SIZE]; |
1201 | tlv_len = skb->len - LLCP_HEADER_SIZE; | 1249 | tlv_len = skb->len - LLCP_HEADER_SIZE; |
1202 | offset = 0; | 1250 | offset = 0; |
1251 | sdres_tlvs_len = 0; | ||
1203 | 1252 | ||
1204 | while (offset < tlv_len) { | 1253 | while (offset < tlv_len) { |
1205 | type = tlv[0]; | 1254 | type = tlv[0]; |
@@ -1217,14 +1266,14 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local, | |||
1217 | !strncmp(service_name, "urn:nfc:sn:sdp", | 1266 | !strncmp(service_name, "urn:nfc:sn:sdp", |
1218 | service_name_len)) { | 1267 | service_name_len)) { |
1219 | sap = 1; | 1268 | sap = 1; |
1220 | goto send_snl; | 1269 | goto add_snl; |
1221 | } | 1270 | } |
1222 | 1271 | ||
1223 | llcp_sock = nfc_llcp_sock_from_sn(local, service_name, | 1272 | llcp_sock = nfc_llcp_sock_from_sn(local, service_name, |
1224 | service_name_len); | 1273 | service_name_len); |
1225 | if (!llcp_sock) { | 1274 | if (!llcp_sock) { |
1226 | sap = 0; | 1275 | sap = 0; |
1227 | goto send_snl; | 1276 | goto add_snl; |
1228 | } | 1277 | } |
1229 | 1278 | ||
1230 | /* | 1279 | /* |
@@ -1241,7 +1290,7 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local, | |||
1241 | 1290 | ||
1242 | if (sap == LLCP_SAP_MAX) { | 1291 | if (sap == LLCP_SAP_MAX) { |
1243 | sap = 0; | 1292 | sap = 0; |
1244 | goto send_snl; | 1293 | goto add_snl; |
1245 | } | 1294 | } |
1246 | 1295 | ||
1247 | client_count = | 1296 | client_count = |
@@ -1258,8 +1307,37 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local, | |||
1258 | 1307 | ||
1259 | pr_debug("%p %d\n", llcp_sock, sap); | 1308 | pr_debug("%p %d\n", llcp_sock, sap); |
1260 | 1309 | ||
1261 | send_snl: | 1310 | add_snl: |
1262 | nfc_llcp_send_snl(local, tid, sap); | 1311 | sdp = nfc_llcp_build_sdres_tlv(tid, sap); |
1312 | if (sdp == NULL) | ||
1313 | goto exit; | ||
1314 | |||
1315 | sdres_tlvs_len += sdp->tlv_len; | ||
1316 | hlist_add_head(&sdp->node, &llc_sdres_list); | ||
1317 | break; | ||
1318 | |||
1319 | case LLCP_TLV_SDRES: | ||
1320 | mutex_lock(&local->sdreq_lock); | ||
1321 | |||
1322 | pr_debug("LLCP_TLV_SDRES: searching tid %d\n", tlv[2]); | ||
1323 | |||
1324 | hlist_for_each_entry(sdp, &local->pending_sdreqs, node) { | ||
1325 | if (sdp->tid != tlv[2]) | ||
1326 | continue; | ||
1327 | |||
1328 | sdp->sap = tlv[3]; | ||
1329 | |||
1330 | pr_debug("Found: uri=%s, sap=%d\n", | ||
1331 | sdp->uri, sdp->sap); | ||
1332 | |||
1333 | hlist_del(&sdp->node); | ||
1334 | |||
1335 | hlist_add_head(&sdp->node, &nl_sdres_list); | ||
1336 | |||
1337 | break; | ||
1338 | } | ||
1339 | |||
1340 | mutex_unlock(&local->sdreq_lock); | ||
1263 | break; | 1341 | break; |
1264 | 1342 | ||
1265 | default: | 1343 | default: |
@@ -1270,6 +1348,13 @@ send_snl: | |||
1270 | offset += length + 2; | 1348 | offset += length + 2; |
1271 | tlv += length + 2; | 1349 | tlv += length + 2; |
1272 | } | 1350 | } |
1351 | |||
1352 | exit: | ||
1353 | if (!hlist_empty(&nl_sdres_list)) | ||
1354 | nfc_genl_llc_send_sdres(local->dev, &nl_sdres_list); | ||
1355 | |||
1356 | if (!hlist_empty(&llc_sdres_list)) | ||
1357 | nfc_llcp_send_snl_sdres(local, &llc_sdres_list, sdres_tlvs_len); | ||
1273 | } | 1358 | } |
1274 | 1359 | ||
1275 | static void nfc_llcp_rx_work(struct work_struct *work) | 1360 | static void nfc_llcp_rx_work(struct work_struct *work) |
@@ -1455,6 +1540,13 @@ int nfc_llcp_register_device(struct nfc_dev *ndev) | |||
1455 | local->remote_miu = LLCP_DEFAULT_MIU; | 1540 | local->remote_miu = LLCP_DEFAULT_MIU; |
1456 | local->remote_lto = LLCP_DEFAULT_LTO; | 1541 | local->remote_lto = LLCP_DEFAULT_LTO; |
1457 | 1542 | ||
1543 | mutex_init(&local->sdreq_lock); | ||
1544 | INIT_HLIST_HEAD(&local->pending_sdreqs); | ||
1545 | init_timer(&local->sdreq_timer); | ||
1546 | local->sdreq_timer.data = (unsigned long) local; | ||
1547 | local->sdreq_timer.function = nfc_llcp_sdreq_timer; | ||
1548 | INIT_WORK(&local->sdreq_timeout_work, nfc_llcp_sdreq_timeout_work); | ||
1549 | |||
1458 | list_add(&local->list, &llcp_devices); | 1550 | list_add(&local->list, &llcp_devices); |
1459 | 1551 | ||
1460 | return 0; | 1552 | return 0; |
diff --git a/net/nfc/llcp/llcp.h b/net/nfc/llcp/llcp.h index 0eae5c509504..7e87a66b02ec 100644 --- a/net/nfc/llcp/llcp.h +++ b/net/nfc/llcp/llcp.h | |||
@@ -46,6 +46,19 @@ struct llcp_sock_list { | |||
46 | rwlock_t lock; | 46 | rwlock_t lock; |
47 | }; | 47 | }; |
48 | 48 | ||
49 | struct nfc_llcp_sdp_tlv { | ||
50 | u8 *tlv; | ||
51 | u8 tlv_len; | ||
52 | |||
53 | char *uri; | ||
54 | u8 tid; | ||
55 | u8 sap; | ||
56 | |||
57 | unsigned long time; | ||
58 | |||
59 | struct hlist_node node; | ||
60 | }; | ||
61 | |||
49 | struct nfc_llcp_local { | 62 | struct nfc_llcp_local { |
50 | struct list_head list; | 63 | struct list_head list; |
51 | struct nfc_dev *dev; | 64 | struct nfc_dev *dev; |
@@ -86,6 +99,12 @@ struct nfc_llcp_local { | |||
86 | u8 remote_opt; | 99 | u8 remote_opt; |
87 | u16 remote_wks; | 100 | u16 remote_wks; |
88 | 101 | ||
102 | struct mutex sdreq_lock; | ||
103 | struct hlist_head pending_sdreqs; | ||
104 | struct timer_list sdreq_timer; | ||
105 | struct work_struct sdreq_timeout_work; | ||
106 | u8 sdreq_next_tid; | ||
107 | |||
89 | /* sockets array */ | 108 | /* sockets array */ |
90 | struct llcp_sock_list sockets; | 109 | struct llcp_sock_list sockets; |
91 | struct llcp_sock_list connecting_sockets; | 110 | struct llcp_sock_list connecting_sockets; |
@@ -105,7 +124,12 @@ struct nfc_llcp_sock { | |||
105 | char *service_name; | 124 | char *service_name; |
106 | size_t service_name_len; | 125 | size_t service_name_len; |
107 | u8 rw; | 126 | u8 rw; |
108 | u16 miu; | 127 | u16 miux; |
128 | |||
129 | |||
130 | /* Remote link parameters */ | ||
131 | u8 remote_rw; | ||
132 | u16 remote_miu; | ||
109 | 133 | ||
110 | /* Link variables */ | 134 | /* Link variables */ |
111 | u8 send_n; | 135 | u8 send_n; |
@@ -213,12 +237,20 @@ int nfc_llcp_parse_connection_tlv(struct nfc_llcp_sock *sock, | |||
213 | /* Commands API */ | 237 | /* Commands API */ |
214 | void nfc_llcp_recv(void *data, struct sk_buff *skb, int err); | 238 | void nfc_llcp_recv(void *data, struct sk_buff *skb, int err); |
215 | u8 *nfc_llcp_build_tlv(u8 type, u8 *value, u8 value_length, u8 *tlv_length); | 239 | u8 *nfc_llcp_build_tlv(u8 type, u8 *value, u8 value_length, u8 *tlv_length); |
240 | struct nfc_llcp_sdp_tlv *nfc_llcp_build_sdres_tlv(u8 tid, u8 sap); | ||
241 | struct nfc_llcp_sdp_tlv *nfc_llcp_build_sdreq_tlv(u8 tid, char *uri, | ||
242 | size_t uri_len); | ||
243 | void nfc_llcp_free_sdp_tlv(struct nfc_llcp_sdp_tlv *sdp); | ||
244 | void nfc_llcp_free_sdp_tlv_list(struct hlist_head *sdp_head); | ||
216 | void nfc_llcp_recv(void *data, struct sk_buff *skb, int err); | 245 | void nfc_llcp_recv(void *data, struct sk_buff *skb, int err); |
217 | int nfc_llcp_disconnect(struct nfc_llcp_sock *sock); | 246 | int nfc_llcp_disconnect(struct nfc_llcp_sock *sock); |
218 | int nfc_llcp_send_symm(struct nfc_dev *dev); | 247 | int nfc_llcp_send_symm(struct nfc_dev *dev); |
219 | int nfc_llcp_send_connect(struct nfc_llcp_sock *sock); | 248 | int nfc_llcp_send_connect(struct nfc_llcp_sock *sock); |
220 | int nfc_llcp_send_cc(struct nfc_llcp_sock *sock); | 249 | int nfc_llcp_send_cc(struct nfc_llcp_sock *sock); |
221 | int nfc_llcp_send_snl(struct nfc_llcp_local *local, u8 tid, u8 sap); | 250 | int nfc_llcp_send_snl_sdres(struct nfc_llcp_local *local, |
251 | struct hlist_head *tlv_list, size_t tlvs_len); | ||
252 | int nfc_llcp_send_snl_sdreq(struct nfc_llcp_local *local, | ||
253 | struct hlist_head *tlv_list, size_t tlvs_len); | ||
222 | int nfc_llcp_send_dm(struct nfc_llcp_local *local, u8 ssap, u8 dsap, u8 reason); | 254 | int nfc_llcp_send_dm(struct nfc_llcp_local *local, u8 ssap, u8 dsap, u8 reason); |
223 | int nfc_llcp_send_disconnect(struct nfc_llcp_sock *sock); | 255 | int nfc_llcp_send_disconnect(struct nfc_llcp_sock *sock); |
224 | int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock, | 256 | int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock, |
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c index 5c7cdf3f2a83..f1b377e247fe 100644 --- a/net/nfc/llcp/sock.c +++ b/net/nfc/llcp/sock.c | |||
@@ -223,6 +223,124 @@ error: | |||
223 | return ret; | 223 | return ret; |
224 | } | 224 | } |
225 | 225 | ||
226 | static int nfc_llcp_setsockopt(struct socket *sock, int level, int optname, | ||
227 | char __user *optval, unsigned int optlen) | ||
228 | { | ||
229 | struct sock *sk = sock->sk; | ||
230 | struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); | ||
231 | u32 opt; | ||
232 | int err = 0; | ||
233 | |||
234 | pr_debug("%p optname %d\n", sk, optname); | ||
235 | |||
236 | if (level != SOL_NFC) | ||
237 | return -ENOPROTOOPT; | ||
238 | |||
239 | lock_sock(sk); | ||
240 | |||
241 | switch (optname) { | ||
242 | case NFC_LLCP_RW: | ||
243 | if (sk->sk_state == LLCP_CONNECTED || | ||
244 | sk->sk_state == LLCP_BOUND || | ||
245 | sk->sk_state == LLCP_LISTEN) { | ||
246 | err = -EINVAL; | ||
247 | break; | ||
248 | } | ||
249 | |||
250 | if (get_user(opt, (u32 __user *) optval)) { | ||
251 | err = -EFAULT; | ||
252 | break; | ||
253 | } | ||
254 | |||
255 | if (opt > LLCP_MAX_RW) { | ||
256 | err = -EINVAL; | ||
257 | break; | ||
258 | } | ||
259 | |||
260 | llcp_sock->rw = (u8) opt; | ||
261 | |||
262 | break; | ||
263 | |||
264 | case NFC_LLCP_MIUX: | ||
265 | if (sk->sk_state == LLCP_CONNECTED || | ||
266 | sk->sk_state == LLCP_BOUND || | ||
267 | sk->sk_state == LLCP_LISTEN) { | ||
268 | err = -EINVAL; | ||
269 | break; | ||
270 | } | ||
271 | |||
272 | if (get_user(opt, (u32 __user *) optval)) { | ||
273 | err = -EFAULT; | ||
274 | break; | ||
275 | } | ||
276 | |||
277 | if (opt > LLCP_MAX_MIUX) { | ||
278 | err = -EINVAL; | ||
279 | break; | ||
280 | } | ||
281 | |||
282 | llcp_sock->miux = (u16) opt; | ||
283 | |||
284 | break; | ||
285 | |||
286 | default: | ||
287 | err = -ENOPROTOOPT; | ||
288 | break; | ||
289 | } | ||
290 | |||
291 | release_sock(sk); | ||
292 | |||
293 | pr_debug("%p rw %d miux %d\n", llcp_sock, | ||
294 | llcp_sock->rw, llcp_sock->miux); | ||
295 | |||
296 | return err; | ||
297 | } | ||
298 | |||
299 | static int nfc_llcp_getsockopt(struct socket *sock, int level, int optname, | ||
300 | char __user *optval, int __user *optlen) | ||
301 | { | ||
302 | struct sock *sk = sock->sk; | ||
303 | struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); | ||
304 | int len, err = 0; | ||
305 | |||
306 | pr_debug("%p optname %d\n", sk, optname); | ||
307 | |||
308 | if (level != SOL_NFC) | ||
309 | return -ENOPROTOOPT; | ||
310 | |||
311 | if (get_user(len, optlen)) | ||
312 | return -EFAULT; | ||
313 | |||
314 | len = min_t(u32, len, sizeof(u32)); | ||
315 | |||
316 | lock_sock(sk); | ||
317 | |||
318 | switch (optname) { | ||
319 | case NFC_LLCP_RW: | ||
320 | if (put_user(llcp_sock->rw, (u32 __user *) optval)) | ||
321 | err = -EFAULT; | ||
322 | |||
323 | break; | ||
324 | |||
325 | case NFC_LLCP_MIUX: | ||
326 | if (put_user(llcp_sock->miux, (u32 __user *) optval)) | ||
327 | err = -EFAULT; | ||
328 | |||
329 | break; | ||
330 | |||
331 | default: | ||
332 | err = -ENOPROTOOPT; | ||
333 | break; | ||
334 | } | ||
335 | |||
336 | release_sock(sk); | ||
337 | |||
338 | if (put_user(len, optlen)) | ||
339 | return -EFAULT; | ||
340 | |||
341 | return err; | ||
342 | } | ||
343 | |||
226 | void nfc_llcp_accept_unlink(struct sock *sk) | 344 | void nfc_llcp_accept_unlink(struct sock *sk) |
227 | { | 345 | { |
228 | struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); | 346 | struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); |
@@ -543,7 +661,7 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, | |||
543 | 661 | ||
544 | llcp_sock->dev = dev; | 662 | llcp_sock->dev = dev; |
545 | llcp_sock->local = nfc_llcp_local_get(local); | 663 | llcp_sock->local = nfc_llcp_local_get(local); |
546 | llcp_sock->miu = llcp_sock->local->remote_miu; | 664 | llcp_sock->remote_miu = llcp_sock->local->remote_miu; |
547 | llcp_sock->ssap = nfc_llcp_get_local_ssap(local); | 665 | llcp_sock->ssap = nfc_llcp_get_local_ssap(local); |
548 | if (llcp_sock->ssap == LLCP_SAP_MAX) { | 666 | if (llcp_sock->ssap == LLCP_SAP_MAX) { |
549 | ret = -ENOMEM; | 667 | ret = -ENOMEM; |
@@ -737,8 +855,8 @@ static const struct proto_ops llcp_sock_ops = { | |||
737 | .ioctl = sock_no_ioctl, | 855 | .ioctl = sock_no_ioctl, |
738 | .listen = llcp_sock_listen, | 856 | .listen = llcp_sock_listen, |
739 | .shutdown = sock_no_shutdown, | 857 | .shutdown = sock_no_shutdown, |
740 | .setsockopt = sock_no_setsockopt, | 858 | .setsockopt = nfc_llcp_setsockopt, |
741 | .getsockopt = sock_no_getsockopt, | 859 | .getsockopt = nfc_llcp_getsockopt, |
742 | .sendmsg = llcp_sock_sendmsg, | 860 | .sendmsg = llcp_sock_sendmsg, |
743 | .recvmsg = llcp_sock_recvmsg, | 861 | .recvmsg = llcp_sock_recvmsg, |
744 | .mmap = sock_no_mmap, | 862 | .mmap = sock_no_mmap, |
@@ -802,8 +920,10 @@ struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp) | |||
802 | 920 | ||
803 | llcp_sock->ssap = 0; | 921 | llcp_sock->ssap = 0; |
804 | llcp_sock->dsap = LLCP_SAP_SDP; | 922 | llcp_sock->dsap = LLCP_SAP_SDP; |
805 | llcp_sock->rw = LLCP_DEFAULT_RW; | 923 | llcp_sock->rw = LLCP_MAX_RW + 1; |
806 | llcp_sock->miu = LLCP_DEFAULT_MIU; | 924 | llcp_sock->miux = LLCP_MAX_MIUX + 1; |
925 | llcp_sock->remote_rw = LLCP_DEFAULT_RW; | ||
926 | llcp_sock->remote_miu = LLCP_DEFAULT_MIU; | ||
807 | llcp_sock->send_n = llcp_sock->send_ack_n = 0; | 927 | llcp_sock->send_n = llcp_sock->send_ack_n = 0; |
808 | llcp_sock->recv_n = llcp_sock->recv_ack_n = 0; | 928 | llcp_sock->recv_n = llcp_sock->recv_ack_n = 0; |
809 | llcp_sock->remote_ready = 1; | 929 | llcp_sock->remote_ready = 1; |
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index 504b883439f1..73fd51098f4d 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c | |||
@@ -53,6 +53,15 @@ static const struct nla_policy nfc_genl_policy[NFC_ATTR_MAX + 1] = { | |||
53 | [NFC_ATTR_DEVICE_POWERED] = { .type = NLA_U8 }, | 53 | [NFC_ATTR_DEVICE_POWERED] = { .type = NLA_U8 }, |
54 | [NFC_ATTR_IM_PROTOCOLS] = { .type = NLA_U32 }, | 54 | [NFC_ATTR_IM_PROTOCOLS] = { .type = NLA_U32 }, |
55 | [NFC_ATTR_TM_PROTOCOLS] = { .type = NLA_U32 }, | 55 | [NFC_ATTR_TM_PROTOCOLS] = { .type = NLA_U32 }, |
56 | [NFC_ATTR_LLC_PARAM_LTO] = { .type = NLA_U8 }, | ||
57 | [NFC_ATTR_LLC_PARAM_RW] = { .type = NLA_U8 }, | ||
58 | [NFC_ATTR_LLC_PARAM_MIUX] = { .type = NLA_U16 }, | ||
59 | [NFC_ATTR_LLC_SDP] = { .type = NLA_NESTED }, | ||
60 | }; | ||
61 | |||
62 | static const struct nla_policy nfc_sdp_genl_policy[NFC_SDP_ATTR_MAX + 1] = { | ||
63 | [NFC_SDP_ATTR_URI] = { .type = NLA_STRING }, | ||
64 | [NFC_SDP_ATTR_SAP] = { .type = NLA_U8 }, | ||
56 | }; | 65 | }; |
57 | 66 | ||
58 | static int nfc_genl_send_target(struct sk_buff *msg, struct nfc_target *target, | 67 | static int nfc_genl_send_target(struct sk_buff *msg, struct nfc_target *target, |
@@ -348,6 +357,74 @@ free_msg: | |||
348 | return -EMSGSIZE; | 357 | return -EMSGSIZE; |
349 | } | 358 | } |
350 | 359 | ||
360 | int nfc_genl_llc_send_sdres(struct nfc_dev *dev, struct hlist_head *sdres_list) | ||
361 | { | ||
362 | struct sk_buff *msg; | ||
363 | struct nlattr *sdp_attr, *uri_attr; | ||
364 | struct nfc_llcp_sdp_tlv *sdres; | ||
365 | struct hlist_node *n; | ||
366 | void *hdr; | ||
367 | int rc = -EMSGSIZE; | ||
368 | int i; | ||
369 | |||
370 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
371 | if (!msg) | ||
372 | return -ENOMEM; | ||
373 | |||
374 | hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, | ||
375 | NFC_EVENT_LLC_SDRES); | ||
376 | if (!hdr) | ||
377 | goto free_msg; | ||
378 | |||
379 | if (nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx)) | ||
380 | goto nla_put_failure; | ||
381 | |||
382 | sdp_attr = nla_nest_start(msg, NFC_ATTR_LLC_SDP); | ||
383 | if (sdp_attr == NULL) { | ||
384 | rc = -ENOMEM; | ||
385 | goto nla_put_failure; | ||
386 | } | ||
387 | |||
388 | i = 1; | ||
389 | hlist_for_each_entry_safe(sdres, n, sdres_list, node) { | ||
390 | pr_debug("uri: %s, sap: %d\n", sdres->uri, sdres->sap); | ||
391 | |||
392 | uri_attr = nla_nest_start(msg, i++); | ||
393 | if (uri_attr == NULL) { | ||
394 | rc = -ENOMEM; | ||
395 | goto nla_put_failure; | ||
396 | } | ||
397 | |||
398 | if (nla_put_u8(msg, NFC_SDP_ATTR_SAP, sdres->sap)) | ||
399 | goto nla_put_failure; | ||
400 | |||
401 | if (nla_put_string(msg, NFC_SDP_ATTR_URI, sdres->uri)) | ||
402 | goto nla_put_failure; | ||
403 | |||
404 | nla_nest_end(msg, uri_attr); | ||
405 | |||
406 | hlist_del(&sdres->node); | ||
407 | |||
408 | nfc_llcp_free_sdp_tlv(sdres); | ||
409 | } | ||
410 | |||
411 | nla_nest_end(msg, sdp_attr); | ||
412 | |||
413 | genlmsg_end(msg, hdr); | ||
414 | |||
415 | return genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_ATOMIC); | ||
416 | |||
417 | nla_put_failure: | ||
418 | genlmsg_cancel(msg, hdr); | ||
419 | |||
420 | free_msg: | ||
421 | nlmsg_free(msg); | ||
422 | |||
423 | nfc_llcp_free_sdp_tlv_list(sdres_list); | ||
424 | |||
425 | return rc; | ||
426 | } | ||
427 | |||
351 | static int nfc_genl_send_device(struct sk_buff *msg, struct nfc_dev *dev, | 428 | static int nfc_genl_send_device(struct sk_buff *msg, struct nfc_dev *dev, |
352 | u32 portid, u32 seq, | 429 | u32 portid, u32 seq, |
353 | struct netlink_callback *cb, | 430 | struct netlink_callback *cb, |
@@ -859,6 +936,96 @@ exit: | |||
859 | return rc; | 936 | return rc; |
860 | } | 937 | } |
861 | 938 | ||
939 | static int nfc_genl_llc_sdreq(struct sk_buff *skb, struct genl_info *info) | ||
940 | { | ||
941 | struct nfc_dev *dev; | ||
942 | struct nfc_llcp_local *local; | ||
943 | struct nlattr *attr, *sdp_attrs[NFC_SDP_ATTR_MAX+1]; | ||
944 | u32 idx; | ||
945 | u8 tid; | ||
946 | char *uri; | ||
947 | int rc = 0, rem; | ||
948 | size_t uri_len, tlvs_len; | ||
949 | struct hlist_head sdreq_list; | ||
950 | struct nfc_llcp_sdp_tlv *sdreq; | ||
951 | |||
952 | if (!info->attrs[NFC_ATTR_DEVICE_INDEX] || | ||
953 | !info->attrs[NFC_ATTR_LLC_SDP]) | ||
954 | return -EINVAL; | ||
955 | |||
956 | idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]); | ||
957 | |||
958 | dev = nfc_get_device(idx); | ||
959 | if (!dev) { | ||
960 | rc = -ENODEV; | ||
961 | goto exit; | ||
962 | } | ||
963 | |||
964 | device_lock(&dev->dev); | ||
965 | |||
966 | if (dev->dep_link_up == false) { | ||
967 | rc = -ENOLINK; | ||
968 | goto exit; | ||
969 | } | ||
970 | |||
971 | local = nfc_llcp_find_local(dev); | ||
972 | if (!local) { | ||
973 | nfc_put_device(dev); | ||
974 | rc = -ENODEV; | ||
975 | goto exit; | ||
976 | } | ||
977 | |||
978 | INIT_HLIST_HEAD(&sdreq_list); | ||
979 | |||
980 | tlvs_len = 0; | ||
981 | |||
982 | nla_for_each_nested(attr, info->attrs[NFC_ATTR_LLC_SDP], rem) { | ||
983 | rc = nla_parse_nested(sdp_attrs, NFC_SDP_ATTR_MAX, attr, | ||
984 | nfc_sdp_genl_policy); | ||
985 | |||
986 | if (rc != 0) { | ||
987 | rc = -EINVAL; | ||
988 | goto exit; | ||
989 | } | ||
990 | |||
991 | if (!sdp_attrs[NFC_SDP_ATTR_URI]) | ||
992 | continue; | ||
993 | |||
994 | uri_len = nla_len(sdp_attrs[NFC_SDP_ATTR_URI]); | ||
995 | if (uri_len == 0) | ||
996 | continue; | ||
997 | |||
998 | uri = nla_data(sdp_attrs[NFC_SDP_ATTR_URI]); | ||
999 | if (uri == NULL || *uri == 0) | ||
1000 | continue; | ||
1001 | |||
1002 | tid = local->sdreq_next_tid++; | ||
1003 | |||
1004 | sdreq = nfc_llcp_build_sdreq_tlv(tid, uri, uri_len); | ||
1005 | if (sdreq == NULL) { | ||
1006 | rc = -ENOMEM; | ||
1007 | goto exit; | ||
1008 | } | ||
1009 | |||
1010 | tlvs_len += sdreq->tlv_len; | ||
1011 | |||
1012 | hlist_add_head(&sdreq->node, &sdreq_list); | ||
1013 | } | ||
1014 | |||
1015 | if (hlist_empty(&sdreq_list)) { | ||
1016 | rc = -EINVAL; | ||
1017 | goto exit; | ||
1018 | } | ||
1019 | |||
1020 | rc = nfc_llcp_send_snl_sdreq(local, &sdreq_list, tlvs_len); | ||
1021 | exit: | ||
1022 | device_unlock(&dev->dev); | ||
1023 | |||
1024 | nfc_put_device(dev); | ||
1025 | |||
1026 | return rc; | ||
1027 | } | ||
1028 | |||
862 | static struct genl_ops nfc_genl_ops[] = { | 1029 | static struct genl_ops nfc_genl_ops[] = { |
863 | { | 1030 | { |
864 | .cmd = NFC_CMD_GET_DEVICE, | 1031 | .cmd = NFC_CMD_GET_DEVICE, |
@@ -913,6 +1080,11 @@ static struct genl_ops nfc_genl_ops[] = { | |||
913 | .doit = nfc_genl_llc_set_params, | 1080 | .doit = nfc_genl_llc_set_params, |
914 | .policy = nfc_genl_policy, | 1081 | .policy = nfc_genl_policy, |
915 | }, | 1082 | }, |
1083 | { | ||
1084 | .cmd = NFC_CMD_LLC_SDREQ, | ||
1085 | .doit = nfc_genl_llc_sdreq, | ||
1086 | .policy = nfc_genl_policy, | ||
1087 | }, | ||
916 | }; | 1088 | }; |
917 | 1089 | ||
918 | 1090 | ||
diff --git a/net/nfc/nfc.h b/net/nfc/nfc.h index 87d914d2876a..94bfe19ba678 100644 --- a/net/nfc/nfc.h +++ b/net/nfc/nfc.h | |||
@@ -46,6 +46,8 @@ struct nfc_rawsock { | |||
46 | #define to_rawsock_sk(_tx_work) \ | 46 | #define to_rawsock_sk(_tx_work) \ |
47 | ((struct sock *) container_of(_tx_work, struct nfc_rawsock, tx_work)) | 47 | ((struct sock *) container_of(_tx_work, struct nfc_rawsock, tx_work)) |
48 | 48 | ||
49 | struct nfc_llcp_sdp_tlv; | ||
50 | |||
49 | #ifdef CONFIG_NFC_LLCP | 51 | #ifdef CONFIG_NFC_LLCP |
50 | 52 | ||
51 | void nfc_llcp_mac_is_down(struct nfc_dev *dev); | 53 | void nfc_llcp_mac_is_down(struct nfc_dev *dev); |
@@ -59,6 +61,8 @@ int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb); | |||
59 | struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev); | 61 | struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev); |
60 | int __init nfc_llcp_init(void); | 62 | int __init nfc_llcp_init(void); |
61 | void nfc_llcp_exit(void); | 63 | void nfc_llcp_exit(void); |
64 | void nfc_llcp_free_sdp_tlv(struct nfc_llcp_sdp_tlv *sdp); | ||
65 | void nfc_llcp_free_sdp_tlv_list(struct hlist_head *head); | ||
62 | 66 | ||
63 | #else | 67 | #else |
64 | 68 | ||
@@ -112,6 +116,14 @@ static inline void nfc_llcp_exit(void) | |||
112 | { | 116 | { |
113 | } | 117 | } |
114 | 118 | ||
119 | static inline void nfc_llcp_free_sdp_tlv(struct nfc_llcp_sdp_tlv *sdp) | ||
120 | { | ||
121 | } | ||
122 | |||
123 | static inline void nfc_llcp_free_sdp_tlv_list(struct hlist_head *sdp_head) | ||
124 | { | ||
125 | } | ||
126 | |||
115 | #endif | 127 | #endif |
116 | 128 | ||
117 | int __init rawsock_init(void); | 129 | int __init rawsock_init(void); |
@@ -144,6 +156,8 @@ int nfc_genl_dep_link_down_event(struct nfc_dev *dev); | |||
144 | int nfc_genl_tm_activated(struct nfc_dev *dev, u32 protocol); | 156 | int nfc_genl_tm_activated(struct nfc_dev *dev, u32 protocol); |
145 | int nfc_genl_tm_deactivated(struct nfc_dev *dev); | 157 | int nfc_genl_tm_deactivated(struct nfc_dev *dev); |
146 | 158 | ||
159 | int nfc_genl_llc_send_sdres(struct nfc_dev *dev, struct hlist_head *sdres_list); | ||
160 | |||
147 | struct nfc_dev *nfc_get_device(unsigned int idx); | 161 | struct nfc_dev *nfc_get_device(unsigned int idx); |
148 | 162 | ||
149 | static inline void nfc_put_device(struct nfc_dev *dev) | 163 | static inline void nfc_put_device(struct nfc_dev *dev) |
diff --git a/net/rfkill/rfkill-regulator.c b/net/rfkill/rfkill-regulator.c index 4b5ab21ecb24..d11ac79246e4 100644 --- a/net/rfkill/rfkill-regulator.c +++ b/net/rfkill/rfkill-regulator.c | |||
@@ -51,7 +51,7 @@ static int rfkill_regulator_set_block(void *data, bool blocked) | |||
51 | return 0; | 51 | return 0; |
52 | } | 52 | } |
53 | 53 | ||
54 | struct rfkill_ops rfkill_regulator_ops = { | 54 | static struct rfkill_ops rfkill_regulator_ops = { |
55 | .set_block = rfkill_regulator_set_block, | 55 | .set_block = rfkill_regulator_set_block, |
56 | }; | 56 | }; |
57 | 57 | ||
diff --git a/net/wireless/ap.c b/net/wireless/ap.c index a4a14e8f55cc..324e8d851dc4 100644 --- a/net/wireless/ap.c +++ b/net/wireless/ap.c | |||
@@ -46,65 +46,3 @@ int cfg80211_stop_ap(struct cfg80211_registered_device *rdev, | |||
46 | 46 | ||
47 | return err; | 47 | return err; |
48 | } | 48 | } |
49 | |||
50 | void cfg80211_ch_switch_notify(struct net_device *dev, | ||
51 | struct cfg80211_chan_def *chandef) | ||
52 | { | ||
53 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
54 | struct wiphy *wiphy = wdev->wiphy; | ||
55 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
56 | |||
57 | trace_cfg80211_ch_switch_notify(dev, chandef); | ||
58 | |||
59 | wdev_lock(wdev); | ||
60 | |||
61 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && | ||
62 | wdev->iftype != NL80211_IFTYPE_P2P_GO)) | ||
63 | goto out; | ||
64 | |||
65 | wdev->channel = chandef->chan; | ||
66 | nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL); | ||
67 | out: | ||
68 | wdev_unlock(wdev); | ||
69 | return; | ||
70 | } | ||
71 | EXPORT_SYMBOL(cfg80211_ch_switch_notify); | ||
72 | |||
73 | bool cfg80211_rx_spurious_frame(struct net_device *dev, | ||
74 | const u8 *addr, gfp_t gfp) | ||
75 | { | ||
76 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
77 | bool ret; | ||
78 | |||
79 | trace_cfg80211_rx_spurious_frame(dev, addr); | ||
80 | |||
81 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && | ||
82 | wdev->iftype != NL80211_IFTYPE_P2P_GO)) { | ||
83 | trace_cfg80211_return_bool(false); | ||
84 | return false; | ||
85 | } | ||
86 | ret = nl80211_unexpected_frame(dev, addr, gfp); | ||
87 | trace_cfg80211_return_bool(ret); | ||
88 | return ret; | ||
89 | } | ||
90 | EXPORT_SYMBOL(cfg80211_rx_spurious_frame); | ||
91 | |||
92 | bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev, | ||
93 | const u8 *addr, gfp_t gfp) | ||
94 | { | ||
95 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
96 | bool ret; | ||
97 | |||
98 | trace_cfg80211_rx_unexpected_4addr_frame(dev, addr); | ||
99 | |||
100 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && | ||
101 | wdev->iftype != NL80211_IFTYPE_P2P_GO && | ||
102 | wdev->iftype != NL80211_IFTYPE_AP_VLAN)) { | ||
103 | trace_cfg80211_return_bool(false); | ||
104 | return false; | ||
105 | } | ||
106 | ret = nl80211_unexpected_4addr_frame(dev, addr, gfp); | ||
107 | trace_cfg80211_return_bool(ret); | ||
108 | return ret; | ||
109 | } | ||
110 | EXPORT_SYMBOL(cfg80211_rx_unexpected_4addr_frame); | ||
diff --git a/net/wireless/core.c b/net/wireless/core.c index ea4155fe9733..f382cae983ba 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -814,6 +814,46 @@ void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, | |||
814 | rdev->num_running_monitor_ifaces += num; | 814 | rdev->num_running_monitor_ifaces += num; |
815 | } | 815 | } |
816 | 816 | ||
817 | void cfg80211_leave(struct cfg80211_registered_device *rdev, | ||
818 | struct wireless_dev *wdev) | ||
819 | { | ||
820 | struct net_device *dev = wdev->netdev; | ||
821 | |||
822 | switch (wdev->iftype) { | ||
823 | case NL80211_IFTYPE_ADHOC: | ||
824 | cfg80211_leave_ibss(rdev, dev, true); | ||
825 | break; | ||
826 | case NL80211_IFTYPE_P2P_CLIENT: | ||
827 | case NL80211_IFTYPE_STATION: | ||
828 | mutex_lock(&rdev->sched_scan_mtx); | ||
829 | __cfg80211_stop_sched_scan(rdev, false); | ||
830 | mutex_unlock(&rdev->sched_scan_mtx); | ||
831 | |||
832 | wdev_lock(wdev); | ||
833 | #ifdef CONFIG_CFG80211_WEXT | ||
834 | kfree(wdev->wext.ie); | ||
835 | wdev->wext.ie = NULL; | ||
836 | wdev->wext.ie_len = 0; | ||
837 | wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; | ||
838 | #endif | ||
839 | __cfg80211_disconnect(rdev, dev, | ||
840 | WLAN_REASON_DEAUTH_LEAVING, true); | ||
841 | cfg80211_mlme_down(rdev, dev); | ||
842 | wdev_unlock(wdev); | ||
843 | break; | ||
844 | case NL80211_IFTYPE_MESH_POINT: | ||
845 | cfg80211_leave_mesh(rdev, dev); | ||
846 | break; | ||
847 | case NL80211_IFTYPE_AP: | ||
848 | cfg80211_stop_ap(rdev, dev); | ||
849 | break; | ||
850 | default: | ||
851 | break; | ||
852 | } | ||
853 | |||
854 | wdev->beacon_interval = 0; | ||
855 | } | ||
856 | |||
817 | static int cfg80211_netdev_notifier_call(struct notifier_block *nb, | 857 | static int cfg80211_netdev_notifier_call(struct notifier_block *nb, |
818 | unsigned long state, | 858 | unsigned long state, |
819 | void *ndev) | 859 | void *ndev) |
@@ -882,38 +922,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, | |||
882 | dev->priv_flags |= IFF_DONT_BRIDGE; | 922 | dev->priv_flags |= IFF_DONT_BRIDGE; |
883 | break; | 923 | break; |
884 | case NETDEV_GOING_DOWN: | 924 | case NETDEV_GOING_DOWN: |
885 | switch (wdev->iftype) { | 925 | cfg80211_leave(rdev, wdev); |
886 | case NL80211_IFTYPE_ADHOC: | ||
887 | cfg80211_leave_ibss(rdev, dev, true); | ||
888 | break; | ||
889 | case NL80211_IFTYPE_P2P_CLIENT: | ||
890 | case NL80211_IFTYPE_STATION: | ||
891 | mutex_lock(&rdev->sched_scan_mtx); | ||
892 | __cfg80211_stop_sched_scan(rdev, false); | ||
893 | mutex_unlock(&rdev->sched_scan_mtx); | ||
894 | |||
895 | wdev_lock(wdev); | ||
896 | #ifdef CONFIG_CFG80211_WEXT | ||
897 | kfree(wdev->wext.ie); | ||
898 | wdev->wext.ie = NULL; | ||
899 | wdev->wext.ie_len = 0; | ||
900 | wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; | ||
901 | #endif | ||
902 | __cfg80211_disconnect(rdev, dev, | ||
903 | WLAN_REASON_DEAUTH_LEAVING, true); | ||
904 | cfg80211_mlme_down(rdev, dev); | ||
905 | wdev_unlock(wdev); | ||
906 | break; | ||
907 | case NL80211_IFTYPE_MESH_POINT: | ||
908 | cfg80211_leave_mesh(rdev, dev); | ||
909 | break; | ||
910 | case NL80211_IFTYPE_AP: | ||
911 | cfg80211_stop_ap(rdev, dev); | ||
912 | break; | ||
913 | default: | ||
914 | break; | ||
915 | } | ||
916 | wdev->beacon_interval = 0; | ||
917 | break; | 926 | break; |
918 | case NETDEV_DOWN: | 927 | case NETDEV_DOWN: |
919 | cfg80211_update_iface_num(rdev, wdev->iftype, -1); | 928 | cfg80211_update_iface_num(rdev, wdev->iftype, -1); |
diff --git a/net/wireless/core.h b/net/wireless/core.h index 3aec0e429d8a..d5d06fdea961 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -330,20 +330,15 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
330 | int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | 330 | int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, |
331 | struct net_device *dev, | 331 | struct net_device *dev, |
332 | struct ieee80211_channel *chan, | 332 | struct ieee80211_channel *chan, |
333 | const u8 *bssid, const u8 *prev_bssid, | 333 | const u8 *bssid, |
334 | const u8 *ssid, int ssid_len, | 334 | const u8 *ssid, int ssid_len, |
335 | const u8 *ie, int ie_len, bool use_mfp, | 335 | struct cfg80211_assoc_request *req); |
336 | struct cfg80211_crypto_settings *crypt, | ||
337 | u32 assoc_flags, struct ieee80211_ht_cap *ht_capa, | ||
338 | struct ieee80211_ht_cap *ht_capa_mask); | ||
339 | int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | 336 | int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, |
340 | struct net_device *dev, struct ieee80211_channel *chan, | 337 | struct net_device *dev, |
341 | const u8 *bssid, const u8 *prev_bssid, | 338 | struct ieee80211_channel *chan, |
339 | const u8 *bssid, | ||
342 | const u8 *ssid, int ssid_len, | 340 | const u8 *ssid, int ssid_len, |
343 | const u8 *ie, int ie_len, bool use_mfp, | 341 | struct cfg80211_assoc_request *req); |
344 | struct cfg80211_crypto_settings *crypt, | ||
345 | u32 assoc_flags, struct ieee80211_ht_cap *ht_capa, | ||
346 | struct ieee80211_ht_cap *ht_capa_mask); | ||
347 | int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, | 342 | int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, |
348 | struct net_device *dev, const u8 *bssid, | 343 | struct net_device *dev, const u8 *bssid, |
349 | const u8 *ie, int ie_len, u16 reason, | 344 | const u8 *ie, int ie_len, u16 reason, |
@@ -375,6 +370,8 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, | |||
375 | bool no_cck, bool dont_wait_for_ack, u64 *cookie); | 370 | bool no_cck, bool dont_wait_for_ack, u64 *cookie); |
376 | void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa, | 371 | void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa, |
377 | const struct ieee80211_ht_cap *ht_capa_mask); | 372 | const struct ieee80211_ht_cap *ht_capa_mask); |
373 | void cfg80211_oper_and_vht_capa(struct ieee80211_vht_cap *vht_capa, | ||
374 | const struct ieee80211_vht_cap *vht_capa_mask); | ||
378 | 375 | ||
379 | /* SME */ | 376 | /* SME */ |
380 | int __cfg80211_connect(struct cfg80211_registered_device *rdev, | 377 | int __cfg80211_connect(struct cfg80211_registered_device *rdev, |
@@ -503,6 +500,9 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, | |||
503 | void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, | 500 | void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, |
504 | enum nl80211_iftype iftype, int num); | 501 | enum nl80211_iftype iftype, int num); |
505 | 502 | ||
503 | void cfg80211_leave(struct cfg80211_registered_device *rdev, | ||
504 | struct wireless_dev *wdev); | ||
505 | |||
506 | #define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10 | 506 | #define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10 |
507 | 507 | ||
508 | #ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS | 508 | #ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS |
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c index 55957a284f6c..0bb93f3061a4 100644 --- a/net/wireless/mesh.c +++ b/net/wireless/mesh.c | |||
@@ -85,6 +85,7 @@ const struct mesh_setup default_mesh_setup = { | |||
85 | .ie = NULL, | 85 | .ie = NULL, |
86 | .ie_len = 0, | 86 | .ie_len = 0, |
87 | .is_secure = false, | 87 | .is_secure = false, |
88 | .user_mpm = false, | ||
88 | .beacon_interval = MESH_DEFAULT_BEACON_INTERVAL, | 89 | .beacon_interval = MESH_DEFAULT_BEACON_INTERVAL, |
89 | .dtim_period = MESH_DEFAULT_DTIM_PERIOD, | 90 | .dtim_period = MESH_DEFAULT_DTIM_PERIOD, |
90 | }; | 91 | }; |
@@ -233,20 +234,6 @@ int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev, | |||
233 | return 0; | 234 | return 0; |
234 | } | 235 | } |
235 | 236 | ||
236 | void cfg80211_notify_new_peer_candidate(struct net_device *dev, | ||
237 | const u8 *macaddr, const u8* ie, u8 ie_len, gfp_t gfp) | ||
238 | { | ||
239 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
240 | |||
241 | trace_cfg80211_notify_new_peer_candidate(dev, macaddr); | ||
242 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_MESH_POINT)) | ||
243 | return; | ||
244 | |||
245 | nl80211_send_new_peer_candidate(wiphy_to_dev(wdev->wiphy), dev, | ||
246 | macaddr, ie, ie_len, gfp); | ||
247 | } | ||
248 | EXPORT_SYMBOL(cfg80211_notify_new_peer_candidate); | ||
249 | |||
250 | static int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, | 237 | static int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, |
251 | struct net_device *dev) | 238 | struct net_device *dev) |
252 | { | 239 | { |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index caddca35d686..390198bf4b36 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -187,30 +187,6 @@ void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len) | |||
187 | } | 187 | } |
188 | EXPORT_SYMBOL(cfg80211_send_disassoc); | 188 | EXPORT_SYMBOL(cfg80211_send_disassoc); |
189 | 189 | ||
190 | void cfg80211_send_unprot_deauth(struct net_device *dev, const u8 *buf, | ||
191 | size_t len) | ||
192 | { | ||
193 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
194 | struct wiphy *wiphy = wdev->wiphy; | ||
195 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
196 | |||
197 | trace_cfg80211_send_unprot_deauth(dev); | ||
198 | nl80211_send_unprot_deauth(rdev, dev, buf, len, GFP_ATOMIC); | ||
199 | } | ||
200 | EXPORT_SYMBOL(cfg80211_send_unprot_deauth); | ||
201 | |||
202 | void cfg80211_send_unprot_disassoc(struct net_device *dev, const u8 *buf, | ||
203 | size_t len) | ||
204 | { | ||
205 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
206 | struct wiphy *wiphy = wdev->wiphy; | ||
207 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
208 | |||
209 | trace_cfg80211_send_unprot_disassoc(dev); | ||
210 | nl80211_send_unprot_disassoc(rdev, dev, buf, len, GFP_ATOMIC); | ||
211 | } | ||
212 | EXPORT_SYMBOL(cfg80211_send_unprot_disassoc); | ||
213 | |||
214 | void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr) | 190 | void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr) |
215 | { | 191 | { |
216 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 192 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
@@ -367,27 +343,38 @@ void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa, | |||
367 | p1[i] &= p2[i]; | 343 | p1[i] &= p2[i]; |
368 | } | 344 | } |
369 | 345 | ||
346 | /* Do a logical ht_capa &= ht_capa_mask. */ | ||
347 | void cfg80211_oper_and_vht_capa(struct ieee80211_vht_cap *vht_capa, | ||
348 | const struct ieee80211_vht_cap *vht_capa_mask) | ||
349 | { | ||
350 | int i; | ||
351 | u8 *p1, *p2; | ||
352 | if (!vht_capa_mask) { | ||
353 | memset(vht_capa, 0, sizeof(*vht_capa)); | ||
354 | return; | ||
355 | } | ||
356 | |||
357 | p1 = (u8*)(vht_capa); | ||
358 | p2 = (u8*)(vht_capa_mask); | ||
359 | for (i = 0; i < sizeof(*vht_capa); i++) | ||
360 | p1[i] &= p2[i]; | ||
361 | } | ||
362 | |||
370 | int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | 363 | int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, |
371 | struct net_device *dev, | 364 | struct net_device *dev, |
372 | struct ieee80211_channel *chan, | 365 | struct ieee80211_channel *chan, |
373 | const u8 *bssid, const u8 *prev_bssid, | 366 | const u8 *bssid, |
374 | const u8 *ssid, int ssid_len, | 367 | const u8 *ssid, int ssid_len, |
375 | const u8 *ie, int ie_len, bool use_mfp, | 368 | struct cfg80211_assoc_request *req) |
376 | struct cfg80211_crypto_settings *crypt, | ||
377 | u32 assoc_flags, struct ieee80211_ht_cap *ht_capa, | ||
378 | struct ieee80211_ht_cap *ht_capa_mask) | ||
379 | { | 369 | { |
380 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 370 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
381 | struct cfg80211_assoc_request req; | ||
382 | int err; | 371 | int err; |
383 | bool was_connected = false; | 372 | bool was_connected = false; |
384 | 373 | ||
385 | ASSERT_WDEV_LOCK(wdev); | 374 | ASSERT_WDEV_LOCK(wdev); |
386 | 375 | ||
387 | memset(&req, 0, sizeof(req)); | 376 | if (wdev->current_bss && req->prev_bssid && |
388 | 377 | ether_addr_equal(wdev->current_bss->pub.bssid, req->prev_bssid)) { | |
389 | if (wdev->current_bss && prev_bssid && | ||
390 | ether_addr_equal(wdev->current_bss->pub.bssid, prev_bssid)) { | ||
391 | /* | 378 | /* |
392 | * Trying to reassociate: Allow this to proceed and let the old | 379 | * Trying to reassociate: Allow this to proceed and let the old |
393 | * association to be dropped when the new one is completed. | 380 | * association to be dropped when the new one is completed. |
@@ -399,40 +386,30 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | |||
399 | } else if (wdev->current_bss) | 386 | } else if (wdev->current_bss) |
400 | return -EALREADY; | 387 | return -EALREADY; |
401 | 388 | ||
402 | req.ie = ie; | 389 | cfg80211_oper_and_ht_capa(&req->ht_capa_mask, |
403 | req.ie_len = ie_len; | ||
404 | memcpy(&req.crypto, crypt, sizeof(req.crypto)); | ||
405 | req.use_mfp = use_mfp; | ||
406 | req.prev_bssid = prev_bssid; | ||
407 | req.flags = assoc_flags; | ||
408 | if (ht_capa) | ||
409 | memcpy(&req.ht_capa, ht_capa, sizeof(req.ht_capa)); | ||
410 | if (ht_capa_mask) | ||
411 | memcpy(&req.ht_capa_mask, ht_capa_mask, | ||
412 | sizeof(req.ht_capa_mask)); | ||
413 | cfg80211_oper_and_ht_capa(&req.ht_capa_mask, | ||
414 | rdev->wiphy.ht_capa_mod_mask); | 390 | rdev->wiphy.ht_capa_mod_mask); |
391 | cfg80211_oper_and_vht_capa(&req->vht_capa_mask, | ||
392 | rdev->wiphy.vht_capa_mod_mask); | ||
415 | 393 | ||
416 | req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len, | 394 | req->bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len, |
417 | WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); | 395 | WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); |
418 | if (!req.bss) { | 396 | if (!req->bss) { |
419 | if (was_connected) | 397 | if (was_connected) |
420 | wdev->sme_state = CFG80211_SME_CONNECTED; | 398 | wdev->sme_state = CFG80211_SME_CONNECTED; |
421 | return -ENOENT; | 399 | return -ENOENT; |
422 | } | 400 | } |
423 | 401 | ||
424 | err = cfg80211_can_use_chan(rdev, wdev, req.bss->channel, | 402 | err = cfg80211_can_use_chan(rdev, wdev, chan, CHAN_MODE_SHARED); |
425 | CHAN_MODE_SHARED); | ||
426 | if (err) | 403 | if (err) |
427 | goto out; | 404 | goto out; |
428 | 405 | ||
429 | err = rdev_assoc(rdev, dev, &req); | 406 | err = rdev_assoc(rdev, dev, req); |
430 | 407 | ||
431 | out: | 408 | out: |
432 | if (err) { | 409 | if (err) { |
433 | if (was_connected) | 410 | if (was_connected) |
434 | wdev->sme_state = CFG80211_SME_CONNECTED; | 411 | wdev->sme_state = CFG80211_SME_CONNECTED; |
435 | cfg80211_put_bss(&rdev->wiphy, req.bss); | 412 | cfg80211_put_bss(&rdev->wiphy, req->bss); |
436 | } | 413 | } |
437 | 414 | ||
438 | return err; | 415 | return err; |
@@ -441,21 +418,17 @@ out: | |||
441 | int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | 418 | int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, |
442 | struct net_device *dev, | 419 | struct net_device *dev, |
443 | struct ieee80211_channel *chan, | 420 | struct ieee80211_channel *chan, |
444 | const u8 *bssid, const u8 *prev_bssid, | 421 | const u8 *bssid, |
445 | const u8 *ssid, int ssid_len, | 422 | const u8 *ssid, int ssid_len, |
446 | const u8 *ie, int ie_len, bool use_mfp, | 423 | struct cfg80211_assoc_request *req) |
447 | struct cfg80211_crypto_settings *crypt, | ||
448 | u32 assoc_flags, struct ieee80211_ht_cap *ht_capa, | ||
449 | struct ieee80211_ht_cap *ht_capa_mask) | ||
450 | { | 424 | { |
451 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 425 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
452 | int err; | 426 | int err; |
453 | 427 | ||
454 | mutex_lock(&rdev->devlist_mtx); | 428 | mutex_lock(&rdev->devlist_mtx); |
455 | wdev_lock(wdev); | 429 | wdev_lock(wdev); |
456 | err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid, | 430 | err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid, |
457 | ssid, ssid_len, ie, ie_len, use_mfp, crypt, | 431 | ssid, ssid_len, req); |
458 | assoc_flags, ht_capa, ht_capa_mask); | ||
459 | wdev_unlock(wdev); | 432 | wdev_unlock(wdev); |
460 | mutex_unlock(&rdev->devlist_mtx); | 433 | mutex_unlock(&rdev->devlist_mtx); |
461 | 434 | ||
@@ -577,62 +550,6 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, | |||
577 | } | 550 | } |
578 | } | 551 | } |
579 | 552 | ||
580 | void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie, | ||
581 | struct ieee80211_channel *chan, | ||
582 | unsigned int duration, gfp_t gfp) | ||
583 | { | ||
584 | struct wiphy *wiphy = wdev->wiphy; | ||
585 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
586 | |||
587 | trace_cfg80211_ready_on_channel(wdev, cookie, chan, duration); | ||
588 | nl80211_send_remain_on_channel(rdev, wdev, cookie, chan, duration, gfp); | ||
589 | } | ||
590 | EXPORT_SYMBOL(cfg80211_ready_on_channel); | ||
591 | |||
592 | void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie, | ||
593 | struct ieee80211_channel *chan, | ||
594 | gfp_t gfp) | ||
595 | { | ||
596 | struct wiphy *wiphy = wdev->wiphy; | ||
597 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
598 | |||
599 | trace_cfg80211_ready_on_channel_expired(wdev, cookie, chan); | ||
600 | nl80211_send_remain_on_channel_cancel(rdev, wdev, cookie, chan, gfp); | ||
601 | } | ||
602 | EXPORT_SYMBOL(cfg80211_remain_on_channel_expired); | ||
603 | |||
604 | void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr, | ||
605 | struct station_info *sinfo, gfp_t gfp) | ||
606 | { | ||
607 | struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; | ||
608 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
609 | |||
610 | trace_cfg80211_new_sta(dev, mac_addr, sinfo); | ||
611 | nl80211_send_sta_event(rdev, dev, mac_addr, sinfo, gfp); | ||
612 | } | ||
613 | EXPORT_SYMBOL(cfg80211_new_sta); | ||
614 | |||
615 | void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp) | ||
616 | { | ||
617 | struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; | ||
618 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
619 | |||
620 | trace_cfg80211_del_sta(dev, mac_addr); | ||
621 | nl80211_send_sta_del_event(rdev, dev, mac_addr, gfp); | ||
622 | } | ||
623 | EXPORT_SYMBOL(cfg80211_del_sta); | ||
624 | |||
625 | void cfg80211_conn_failed(struct net_device *dev, const u8 *mac_addr, | ||
626 | enum nl80211_connect_failed_reason reason, | ||
627 | gfp_t gfp) | ||
628 | { | ||
629 | struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; | ||
630 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
631 | |||
632 | nl80211_send_conn_failed_event(rdev, dev, mac_addr, reason, gfp); | ||
633 | } | ||
634 | EXPORT_SYMBOL(cfg80211_conn_failed); | ||
635 | |||
636 | struct cfg80211_mgmt_registration { | 553 | struct cfg80211_mgmt_registration { |
637 | struct list_head list; | 554 | struct list_head list; |
638 | 555 | ||
@@ -909,85 +826,6 @@ bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_mbm, | |||
909 | } | 826 | } |
910 | EXPORT_SYMBOL(cfg80211_rx_mgmt); | 827 | EXPORT_SYMBOL(cfg80211_rx_mgmt); |
911 | 828 | ||
912 | void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie, | ||
913 | const u8 *buf, size_t len, bool ack, gfp_t gfp) | ||
914 | { | ||
915 | struct wiphy *wiphy = wdev->wiphy; | ||
916 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
917 | |||
918 | trace_cfg80211_mgmt_tx_status(wdev, cookie, ack); | ||
919 | |||
920 | /* Indicate TX status of the Action frame to user space */ | ||
921 | nl80211_send_mgmt_tx_status(rdev, wdev, cookie, buf, len, ack, gfp); | ||
922 | } | ||
923 | EXPORT_SYMBOL(cfg80211_mgmt_tx_status); | ||
924 | |||
925 | void cfg80211_cqm_rssi_notify(struct net_device *dev, | ||
926 | enum nl80211_cqm_rssi_threshold_event rssi_event, | ||
927 | gfp_t gfp) | ||
928 | { | ||
929 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
930 | struct wiphy *wiphy = wdev->wiphy; | ||
931 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
932 | |||
933 | trace_cfg80211_cqm_rssi_notify(dev, rssi_event); | ||
934 | |||
935 | /* Indicate roaming trigger event to user space */ | ||
936 | nl80211_send_cqm_rssi_notify(rdev, dev, rssi_event, gfp); | ||
937 | } | ||
938 | EXPORT_SYMBOL(cfg80211_cqm_rssi_notify); | ||
939 | |||
940 | void cfg80211_cqm_pktloss_notify(struct net_device *dev, | ||
941 | const u8 *peer, u32 num_packets, gfp_t gfp) | ||
942 | { | ||
943 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
944 | struct wiphy *wiphy = wdev->wiphy; | ||
945 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
946 | |||
947 | trace_cfg80211_cqm_pktloss_notify(dev, peer, num_packets); | ||
948 | |||
949 | /* Indicate roaming trigger event to user space */ | ||
950 | nl80211_send_cqm_pktloss_notify(rdev, dev, peer, num_packets, gfp); | ||
951 | } | ||
952 | EXPORT_SYMBOL(cfg80211_cqm_pktloss_notify); | ||
953 | |||
954 | void cfg80211_cqm_txe_notify(struct net_device *dev, | ||
955 | const u8 *peer, u32 num_packets, | ||
956 | u32 rate, u32 intvl, gfp_t gfp) | ||
957 | { | ||
958 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
959 | struct wiphy *wiphy = wdev->wiphy; | ||
960 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
961 | |||
962 | nl80211_send_cqm_txe_notify(rdev, dev, peer, num_packets, | ||
963 | rate, intvl, gfp); | ||
964 | } | ||
965 | EXPORT_SYMBOL(cfg80211_cqm_txe_notify); | ||
966 | |||
967 | void cfg80211_gtk_rekey_notify(struct net_device *dev, const u8 *bssid, | ||
968 | const u8 *replay_ctr, gfp_t gfp) | ||
969 | { | ||
970 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
971 | struct wiphy *wiphy = wdev->wiphy; | ||
972 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
973 | |||
974 | trace_cfg80211_gtk_rekey_notify(dev, bssid); | ||
975 | nl80211_gtk_rekey_notify(rdev, dev, bssid, replay_ctr, gfp); | ||
976 | } | ||
977 | EXPORT_SYMBOL(cfg80211_gtk_rekey_notify); | ||
978 | |||
979 | void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index, | ||
980 | const u8 *bssid, bool preauth, gfp_t gfp) | ||
981 | { | ||
982 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
983 | struct wiphy *wiphy = wdev->wiphy; | ||
984 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
985 | |||
986 | trace_cfg80211_pmksa_candidate_notify(dev, index, bssid, preauth); | ||
987 | nl80211_pmksa_candidate_notify(rdev, dev, index, bssid, preauth, gfp); | ||
988 | } | ||
989 | EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify); | ||
990 | |||
991 | void cfg80211_dfs_channels_update_work(struct work_struct *work) | 829 | void cfg80211_dfs_channels_update_work(struct work_struct *work) |
992 | { | 830 | { |
993 | struct delayed_work *delayed_work; | 831 | struct delayed_work *delayed_work; |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index d44ab216c0ec..f924d45af1b8 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -370,6 +370,14 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
370 | [NL80211_ATTR_MAC_ADDRS] = { .type = NLA_NESTED }, | 370 | [NL80211_ATTR_MAC_ADDRS] = { .type = NLA_NESTED }, |
371 | [NL80211_ATTR_STA_CAPABILITY] = { .type = NLA_U16 }, | 371 | [NL80211_ATTR_STA_CAPABILITY] = { .type = NLA_U16 }, |
372 | [NL80211_ATTR_STA_EXT_CAPABILITY] = { .type = NLA_BINARY, }, | 372 | [NL80211_ATTR_STA_EXT_CAPABILITY] = { .type = NLA_BINARY, }, |
373 | [NL80211_ATTR_SPLIT_WIPHY_DUMP] = { .type = NLA_FLAG, }, | ||
374 | [NL80211_ATTR_DISABLE_VHT] = { .type = NLA_FLAG }, | ||
375 | [NL80211_ATTR_VHT_CAPABILITY_MASK] = { | ||
376 | .len = NL80211_VHT_CAPABILITY_LEN, | ||
377 | }, | ||
378 | [NL80211_ATTR_MDID] = { .type = NLA_U16 }, | ||
379 | [NL80211_ATTR_IE_RIC] = { .type = NLA_BINARY, | ||
380 | .len = IEEE80211_MAX_DATA_LEN }, | ||
373 | }; | 381 | }; |
374 | 382 | ||
375 | /* policy for the key attributes */ | 383 | /* policy for the key attributes */ |
@@ -539,7 +547,8 @@ static inline void *nl80211hdr_put(struct sk_buff *skb, u32 portid, u32 seq, | |||
539 | } | 547 | } |
540 | 548 | ||
541 | static int nl80211_msg_put_channel(struct sk_buff *msg, | 549 | static int nl80211_msg_put_channel(struct sk_buff *msg, |
542 | struct ieee80211_channel *chan) | 550 | struct ieee80211_channel *chan, |
551 | bool large) | ||
543 | { | 552 | { |
544 | if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_FREQ, | 553 | if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_FREQ, |
545 | chan->center_freq)) | 554 | chan->center_freq)) |
@@ -554,9 +563,37 @@ static int nl80211_msg_put_channel(struct sk_buff *msg, | |||
554 | if ((chan->flags & IEEE80211_CHAN_NO_IBSS) && | 563 | if ((chan->flags & IEEE80211_CHAN_NO_IBSS) && |
555 | nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IBSS)) | 564 | nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IBSS)) |
556 | goto nla_put_failure; | 565 | goto nla_put_failure; |
557 | if ((chan->flags & IEEE80211_CHAN_RADAR) && | 566 | if (chan->flags & IEEE80211_CHAN_RADAR) { |
558 | nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR)) | 567 | if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR)) |
559 | goto nla_put_failure; | 568 | goto nla_put_failure; |
569 | if (large) { | ||
570 | u32 time; | ||
571 | |||
572 | time = elapsed_jiffies_msecs(chan->dfs_state_entered); | ||
573 | |||
574 | if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_STATE, | ||
575 | chan->dfs_state)) | ||
576 | goto nla_put_failure; | ||
577 | if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_TIME, | ||
578 | time)) | ||
579 | goto nla_put_failure; | ||
580 | } | ||
581 | } | ||
582 | |||
583 | if (large) { | ||
584 | if ((chan->flags & IEEE80211_CHAN_NO_HT40MINUS) && | ||
585 | nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_MINUS)) | ||
586 | goto nla_put_failure; | ||
587 | if ((chan->flags & IEEE80211_CHAN_NO_HT40PLUS) && | ||
588 | nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_PLUS)) | ||
589 | goto nla_put_failure; | ||
590 | if ((chan->flags & IEEE80211_CHAN_NO_80MHZ) && | ||
591 | nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_80MHZ)) | ||
592 | goto nla_put_failure; | ||
593 | if ((chan->flags & IEEE80211_CHAN_NO_160MHZ) && | ||
594 | nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_160MHZ)) | ||
595 | goto nla_put_failure; | ||
596 | } | ||
560 | 597 | ||
561 | if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER, | 598 | if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER, |
562 | DBM_TO_MBM(chan->max_power))) | 599 | DBM_TO_MBM(chan->max_power))) |
@@ -832,7 +869,8 @@ nla_put_failure: | |||
832 | } | 869 | } |
833 | 870 | ||
834 | static int nl80211_put_iface_combinations(struct wiphy *wiphy, | 871 | static int nl80211_put_iface_combinations(struct wiphy *wiphy, |
835 | struct sk_buff *msg) | 872 | struct sk_buff *msg, |
873 | bool large) | ||
836 | { | 874 | { |
837 | struct nlattr *nl_combis; | 875 | struct nlattr *nl_combis; |
838 | int i, j; | 876 | int i, j; |
@@ -881,6 +919,10 @@ static int nl80211_put_iface_combinations(struct wiphy *wiphy, | |||
881 | nla_put_u32(msg, NL80211_IFACE_COMB_MAXNUM, | 919 | nla_put_u32(msg, NL80211_IFACE_COMB_MAXNUM, |
882 | c->max_interfaces)) | 920 | c->max_interfaces)) |
883 | goto nla_put_failure; | 921 | goto nla_put_failure; |
922 | if (large && | ||
923 | nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS, | ||
924 | c->radar_detect_widths)) | ||
925 | goto nla_put_failure; | ||
884 | 926 | ||
885 | nla_nest_end(msg, nl_combi); | 927 | nla_nest_end(msg, nl_combi); |
886 | } | 928 | } |
@@ -892,412 +934,611 @@ nla_put_failure: | |||
892 | return -ENOBUFS; | 934 | return -ENOBUFS; |
893 | } | 935 | } |
894 | 936 | ||
895 | static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flags, | 937 | #ifdef CONFIG_PM |
896 | struct cfg80211_registered_device *dev) | 938 | static int nl80211_send_wowlan_tcp_caps(struct cfg80211_registered_device *rdev, |
939 | struct sk_buff *msg) | ||
897 | { | 940 | { |
898 | void *hdr; | 941 | const struct wiphy_wowlan_tcp_support *tcp = rdev->wiphy.wowlan.tcp; |
899 | struct nlattr *nl_bands, *nl_band; | 942 | struct nlattr *nl_tcp; |
900 | struct nlattr *nl_freqs, *nl_freq; | ||
901 | struct nlattr *nl_rates, *nl_rate; | ||
902 | struct nlattr *nl_cmds; | ||
903 | enum ieee80211_band band; | ||
904 | struct ieee80211_channel *chan; | ||
905 | struct ieee80211_rate *rate; | ||
906 | int i; | ||
907 | const struct ieee80211_txrx_stypes *mgmt_stypes = | ||
908 | dev->wiphy.mgmt_stypes; | ||
909 | 943 | ||
910 | hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_WIPHY); | 944 | if (!tcp) |
911 | if (!hdr) | 945 | return 0; |
912 | return -1; | ||
913 | 946 | ||
914 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, dev->wiphy_idx) || | 947 | nl_tcp = nla_nest_start(msg, NL80211_WOWLAN_TRIG_TCP_CONNECTION); |
915 | nla_put_string(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy)) || | 948 | if (!nl_tcp) |
916 | nla_put_u32(msg, NL80211_ATTR_GENERATION, | 949 | return -ENOBUFS; |
917 | cfg80211_rdev_list_generation) || | ||
918 | nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT, | ||
919 | dev->wiphy.retry_short) || | ||
920 | nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_LONG, | ||
921 | dev->wiphy.retry_long) || | ||
922 | nla_put_u32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD, | ||
923 | dev->wiphy.frag_threshold) || | ||
924 | nla_put_u32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD, | ||
925 | dev->wiphy.rts_threshold) || | ||
926 | nla_put_u8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS, | ||
927 | dev->wiphy.coverage_class) || | ||
928 | nla_put_u8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS, | ||
929 | dev->wiphy.max_scan_ssids) || | ||
930 | nla_put_u8(msg, NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS, | ||
931 | dev->wiphy.max_sched_scan_ssids) || | ||
932 | nla_put_u16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN, | ||
933 | dev->wiphy.max_scan_ie_len) || | ||
934 | nla_put_u16(msg, NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN, | ||
935 | dev->wiphy.max_sched_scan_ie_len) || | ||
936 | nla_put_u8(msg, NL80211_ATTR_MAX_MATCH_SETS, | ||
937 | dev->wiphy.max_match_sets)) | ||
938 | goto nla_put_failure; | ||
939 | 950 | ||
940 | if ((dev->wiphy.flags & WIPHY_FLAG_IBSS_RSN) && | 951 | if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD, |
941 | nla_put_flag(msg, NL80211_ATTR_SUPPORT_IBSS_RSN)) | 952 | tcp->data_payload_max)) |
942 | goto nla_put_failure; | 953 | return -ENOBUFS; |
943 | if ((dev->wiphy.flags & WIPHY_FLAG_MESH_AUTH) && | ||
944 | nla_put_flag(msg, NL80211_ATTR_SUPPORT_MESH_AUTH)) | ||
945 | goto nla_put_failure; | ||
946 | if ((dev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) && | ||
947 | nla_put_flag(msg, NL80211_ATTR_SUPPORT_AP_UAPSD)) | ||
948 | goto nla_put_failure; | ||
949 | if ((dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_FW_ROAM) && | ||
950 | nla_put_flag(msg, NL80211_ATTR_ROAM_SUPPORT)) | ||
951 | goto nla_put_failure; | ||
952 | if ((dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) && | ||
953 | nla_put_flag(msg, NL80211_ATTR_TDLS_SUPPORT)) | ||
954 | goto nla_put_failure; | ||
955 | if ((dev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) && | ||
956 | nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP)) | ||
957 | goto nla_put_failure; | ||
958 | 954 | ||
959 | if (nla_put(msg, NL80211_ATTR_CIPHER_SUITES, | 955 | if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD, |
960 | sizeof(u32) * dev->wiphy.n_cipher_suites, | 956 | tcp->data_payload_max)) |
961 | dev->wiphy.cipher_suites)) | 957 | return -ENOBUFS; |
962 | goto nla_put_failure; | ||
963 | 958 | ||
964 | if (nla_put_u8(msg, NL80211_ATTR_MAX_NUM_PMKIDS, | 959 | if (tcp->seq && nla_put_flag(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ)) |
965 | dev->wiphy.max_num_pmkids)) | 960 | return -ENOBUFS; |
966 | goto nla_put_failure; | ||
967 | 961 | ||
968 | if ((dev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) && | 962 | if (tcp->tok && nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN, |
969 | nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE)) | 963 | sizeof(*tcp->tok), tcp->tok)) |
970 | goto nla_put_failure; | 964 | return -ENOBUFS; |
971 | 965 | ||
972 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX, | 966 | if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_INTERVAL, |
973 | dev->wiphy.available_antennas_tx) || | 967 | tcp->data_interval_max)) |
974 | nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX, | 968 | return -ENOBUFS; |
975 | dev->wiphy.available_antennas_rx)) | ||
976 | goto nla_put_failure; | ||
977 | 969 | ||
978 | if ((dev->wiphy.flags & WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD) && | 970 | if (nla_put_u32(msg, NL80211_WOWLAN_TCP_WAKE_PAYLOAD, |
979 | nla_put_u32(msg, NL80211_ATTR_PROBE_RESP_OFFLOAD, | 971 | tcp->wake_payload_max)) |
980 | dev->wiphy.probe_resp_offload)) | 972 | return -ENOBUFS; |
981 | goto nla_put_failure; | ||
982 | 973 | ||
983 | if ((dev->wiphy.available_antennas_tx || | 974 | nla_nest_end(msg, nl_tcp); |
984 | dev->wiphy.available_antennas_rx) && dev->ops->get_antenna) { | 975 | return 0; |
985 | u32 tx_ant = 0, rx_ant = 0; | 976 | } |
986 | int res; | 977 | |
987 | res = rdev_get_antenna(dev, &tx_ant, &rx_ant); | 978 | static int nl80211_send_wowlan(struct sk_buff *msg, |
988 | if (!res) { | 979 | struct cfg80211_registered_device *dev, |
989 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_TX, | 980 | bool large) |
990 | tx_ant) || | 981 | { |
991 | nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_RX, | 982 | struct nlattr *nl_wowlan; |
992 | rx_ant)) | 983 | |
993 | goto nla_put_failure; | 984 | if (!dev->wiphy.wowlan.flags && !dev->wiphy.wowlan.n_patterns) |
994 | } | 985 | return 0; |
986 | |||
987 | nl_wowlan = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED); | ||
988 | if (!nl_wowlan) | ||
989 | return -ENOBUFS; | ||
990 | |||
991 | if (((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_ANY) && | ||
992 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) || | ||
993 | ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_DISCONNECT) && | ||
994 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) || | ||
995 | ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_MAGIC_PKT) && | ||
996 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) || | ||
997 | ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY) && | ||
998 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED)) || | ||
999 | ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) && | ||
1000 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) || | ||
1001 | ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ) && | ||
1002 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) || | ||
1003 | ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_4WAY_HANDSHAKE) && | ||
1004 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) || | ||
1005 | ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_RFKILL_RELEASE) && | ||
1006 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE))) | ||
1007 | return -ENOBUFS; | ||
1008 | |||
1009 | if (dev->wiphy.wowlan.n_patterns) { | ||
1010 | struct nl80211_wowlan_pattern_support pat = { | ||
1011 | .max_patterns = dev->wiphy.wowlan.n_patterns, | ||
1012 | .min_pattern_len = dev->wiphy.wowlan.pattern_min_len, | ||
1013 | .max_pattern_len = dev->wiphy.wowlan.pattern_max_len, | ||
1014 | .max_pkt_offset = dev->wiphy.wowlan.max_pkt_offset, | ||
1015 | }; | ||
1016 | |||
1017 | if (nla_put(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN, | ||
1018 | sizeof(pat), &pat)) | ||
1019 | return -ENOBUFS; | ||
995 | } | 1020 | } |
996 | 1021 | ||
997 | if (nl80211_put_iftypes(msg, NL80211_ATTR_SUPPORTED_IFTYPES, | 1022 | if (large && nl80211_send_wowlan_tcp_caps(dev, msg)) |
998 | dev->wiphy.interface_modes)) | 1023 | return -ENOBUFS; |
999 | goto nla_put_failure; | ||
1000 | 1024 | ||
1001 | nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS); | 1025 | nla_nest_end(msg, nl_wowlan); |
1002 | if (!nl_bands) | ||
1003 | goto nla_put_failure; | ||
1004 | 1026 | ||
1005 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | 1027 | return 0; |
1006 | if (!dev->wiphy.bands[band]) | 1028 | } |
1007 | continue; | 1029 | #endif |
1008 | 1030 | ||
1009 | nl_band = nla_nest_start(msg, band); | 1031 | static int nl80211_send_band_rateinfo(struct sk_buff *msg, |
1010 | if (!nl_band) | 1032 | struct ieee80211_supported_band *sband) |
1011 | goto nla_put_failure; | 1033 | { |
1034 | struct nlattr *nl_rates, *nl_rate; | ||
1035 | struct ieee80211_rate *rate; | ||
1036 | int i; | ||
1012 | 1037 | ||
1013 | /* add HT info */ | 1038 | /* add HT info */ |
1014 | if (dev->wiphy.bands[band]->ht_cap.ht_supported && | 1039 | if (sband->ht_cap.ht_supported && |
1015 | (nla_put(msg, NL80211_BAND_ATTR_HT_MCS_SET, | 1040 | (nla_put(msg, NL80211_BAND_ATTR_HT_MCS_SET, |
1016 | sizeof(dev->wiphy.bands[band]->ht_cap.mcs), | 1041 | sizeof(sband->ht_cap.mcs), |
1017 | &dev->wiphy.bands[band]->ht_cap.mcs) || | 1042 | &sband->ht_cap.mcs) || |
1018 | nla_put_u16(msg, NL80211_BAND_ATTR_HT_CAPA, | 1043 | nla_put_u16(msg, NL80211_BAND_ATTR_HT_CAPA, |
1019 | dev->wiphy.bands[band]->ht_cap.cap) || | 1044 | sband->ht_cap.cap) || |
1020 | nla_put_u8(msg, NL80211_BAND_ATTR_HT_AMPDU_FACTOR, | 1045 | nla_put_u8(msg, NL80211_BAND_ATTR_HT_AMPDU_FACTOR, |
1021 | dev->wiphy.bands[band]->ht_cap.ampdu_factor) || | 1046 | sband->ht_cap.ampdu_factor) || |
1022 | nla_put_u8(msg, NL80211_BAND_ATTR_HT_AMPDU_DENSITY, | 1047 | nla_put_u8(msg, NL80211_BAND_ATTR_HT_AMPDU_DENSITY, |
1023 | dev->wiphy.bands[band]->ht_cap.ampdu_density))) | 1048 | sband->ht_cap.ampdu_density))) |
1024 | goto nla_put_failure; | 1049 | return -ENOBUFS; |
1025 | 1050 | ||
1026 | /* add VHT info */ | 1051 | /* add VHT info */ |
1027 | if (dev->wiphy.bands[band]->vht_cap.vht_supported && | 1052 | if (sband->vht_cap.vht_supported && |
1028 | (nla_put(msg, NL80211_BAND_ATTR_VHT_MCS_SET, | 1053 | (nla_put(msg, NL80211_BAND_ATTR_VHT_MCS_SET, |
1029 | sizeof(dev->wiphy.bands[band]->vht_cap.vht_mcs), | 1054 | sizeof(sband->vht_cap.vht_mcs), |
1030 | &dev->wiphy.bands[band]->vht_cap.vht_mcs) || | 1055 | &sband->vht_cap.vht_mcs) || |
1031 | nla_put_u32(msg, NL80211_BAND_ATTR_VHT_CAPA, | 1056 | nla_put_u32(msg, NL80211_BAND_ATTR_VHT_CAPA, |
1032 | dev->wiphy.bands[band]->vht_cap.cap))) | 1057 | sband->vht_cap.cap))) |
1033 | goto nla_put_failure; | 1058 | return -ENOBUFS; |
1034 | 1059 | ||
1035 | /* add frequencies */ | 1060 | /* add bitrates */ |
1036 | nl_freqs = nla_nest_start(msg, NL80211_BAND_ATTR_FREQS); | 1061 | nl_rates = nla_nest_start(msg, NL80211_BAND_ATTR_RATES); |
1037 | if (!nl_freqs) | 1062 | if (!nl_rates) |
1038 | goto nla_put_failure; | 1063 | return -ENOBUFS; |
1039 | 1064 | ||
1040 | for (i = 0; i < dev->wiphy.bands[band]->n_channels; i++) { | 1065 | for (i = 0; i < sband->n_bitrates; i++) { |
1041 | nl_freq = nla_nest_start(msg, i); | 1066 | nl_rate = nla_nest_start(msg, i); |
1042 | if (!nl_freq) | 1067 | if (!nl_rate) |
1043 | goto nla_put_failure; | 1068 | return -ENOBUFS; |
1044 | 1069 | ||
1045 | chan = &dev->wiphy.bands[band]->channels[i]; | 1070 | rate = &sband->bitrates[i]; |
1071 | if (nla_put_u32(msg, NL80211_BITRATE_ATTR_RATE, | ||
1072 | rate->bitrate)) | ||
1073 | return -ENOBUFS; | ||
1074 | if ((rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) && | ||
1075 | nla_put_flag(msg, | ||
1076 | NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE)) | ||
1077 | return -ENOBUFS; | ||
1046 | 1078 | ||
1047 | if (nl80211_msg_put_channel(msg, chan)) | 1079 | nla_nest_end(msg, nl_rate); |
1048 | goto nla_put_failure; | 1080 | } |
1049 | 1081 | ||
1050 | nla_nest_end(msg, nl_freq); | 1082 | nla_nest_end(msg, nl_rates); |
1051 | } | ||
1052 | 1083 | ||
1053 | nla_nest_end(msg, nl_freqs); | 1084 | return 0; |
1085 | } | ||
1054 | 1086 | ||
1055 | /* add bitrates */ | 1087 | static int |
1056 | nl_rates = nla_nest_start(msg, NL80211_BAND_ATTR_RATES); | 1088 | nl80211_send_mgmt_stypes(struct sk_buff *msg, |
1057 | if (!nl_rates) | 1089 | const struct ieee80211_txrx_stypes *mgmt_stypes) |
1058 | goto nla_put_failure; | 1090 | { |
1091 | u16 stypes; | ||
1092 | struct nlattr *nl_ftypes, *nl_ifs; | ||
1093 | enum nl80211_iftype ift; | ||
1094 | int i; | ||
1059 | 1095 | ||
1060 | for (i = 0; i < dev->wiphy.bands[band]->n_bitrates; i++) { | 1096 | if (!mgmt_stypes) |
1061 | nl_rate = nla_nest_start(msg, i); | 1097 | return 0; |
1062 | if (!nl_rate) | ||
1063 | goto nla_put_failure; | ||
1064 | 1098 | ||
1065 | rate = &dev->wiphy.bands[band]->bitrates[i]; | 1099 | nl_ifs = nla_nest_start(msg, NL80211_ATTR_TX_FRAME_TYPES); |
1066 | if (nla_put_u32(msg, NL80211_BITRATE_ATTR_RATE, | 1100 | if (!nl_ifs) |
1067 | rate->bitrate)) | 1101 | return -ENOBUFS; |
1068 | goto nla_put_failure; | ||
1069 | if ((rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) && | ||
1070 | nla_put_flag(msg, | ||
1071 | NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE)) | ||
1072 | goto nla_put_failure; | ||
1073 | 1102 | ||
1074 | nla_nest_end(msg, nl_rate); | 1103 | for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) { |
1104 | nl_ftypes = nla_nest_start(msg, ift); | ||
1105 | if (!nl_ftypes) | ||
1106 | return -ENOBUFS; | ||
1107 | i = 0; | ||
1108 | stypes = mgmt_stypes[ift].tx; | ||
1109 | while (stypes) { | ||
1110 | if ((stypes & 1) && | ||
1111 | nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE, | ||
1112 | (i << 4) | IEEE80211_FTYPE_MGMT)) | ||
1113 | return -ENOBUFS; | ||
1114 | stypes >>= 1; | ||
1115 | i++; | ||
1075 | } | 1116 | } |
1117 | nla_nest_end(msg, nl_ftypes); | ||
1118 | } | ||
1076 | 1119 | ||
1077 | nla_nest_end(msg, nl_rates); | 1120 | nla_nest_end(msg, nl_ifs); |
1078 | 1121 | ||
1079 | nla_nest_end(msg, nl_band); | 1122 | nl_ifs = nla_nest_start(msg, NL80211_ATTR_RX_FRAME_TYPES); |
1123 | if (!nl_ifs) | ||
1124 | return -ENOBUFS; | ||
1125 | |||
1126 | for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) { | ||
1127 | nl_ftypes = nla_nest_start(msg, ift); | ||
1128 | if (!nl_ftypes) | ||
1129 | return -ENOBUFS; | ||
1130 | i = 0; | ||
1131 | stypes = mgmt_stypes[ift].rx; | ||
1132 | while (stypes) { | ||
1133 | if ((stypes & 1) && | ||
1134 | nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE, | ||
1135 | (i << 4) | IEEE80211_FTYPE_MGMT)) | ||
1136 | return -ENOBUFS; | ||
1137 | stypes >>= 1; | ||
1138 | i++; | ||
1139 | } | ||
1140 | nla_nest_end(msg, nl_ftypes); | ||
1080 | } | 1141 | } |
1081 | nla_nest_end(msg, nl_bands); | 1142 | nla_nest_end(msg, nl_ifs); |
1082 | 1143 | ||
1083 | nl_cmds = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_COMMANDS); | 1144 | return 0; |
1084 | if (!nl_cmds) | 1145 | } |
1085 | goto nla_put_failure; | ||
1086 | 1146 | ||
1087 | i = 0; | 1147 | static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, |
1088 | #define CMD(op, n) \ | 1148 | struct sk_buff *msg, u32 portid, u32 seq, |
1089 | do { \ | 1149 | int flags, bool split, long *split_start, |
1090 | if (dev->ops->op) { \ | 1150 | long *band_start, long *chan_start) |
1091 | i++; \ | 1151 | { |
1092 | if (nla_put_u32(msg, i, NL80211_CMD_ ## n)) \ | 1152 | void *hdr; |
1093 | goto nla_put_failure; \ | 1153 | struct nlattr *nl_bands, *nl_band; |
1094 | } \ | 1154 | struct nlattr *nl_freqs, *nl_freq; |
1095 | } while (0) | 1155 | struct nlattr *nl_cmds; |
1096 | 1156 | enum ieee80211_band band; | |
1097 | CMD(add_virtual_intf, NEW_INTERFACE); | 1157 | struct ieee80211_channel *chan; |
1098 | CMD(change_virtual_intf, SET_INTERFACE); | 1158 | int i; |
1099 | CMD(add_key, NEW_KEY); | 1159 | const struct ieee80211_txrx_stypes *mgmt_stypes = |
1100 | CMD(start_ap, START_AP); | 1160 | dev->wiphy.mgmt_stypes; |
1101 | CMD(add_station, NEW_STATION); | 1161 | long start = 0, start_chan = 0, start_band = 0; |
1102 | CMD(add_mpath, NEW_MPATH); | 1162 | u32 features; |
1103 | CMD(update_mesh_config, SET_MESH_CONFIG); | 1163 | |
1104 | CMD(change_bss, SET_BSS); | 1164 | hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_WIPHY); |
1105 | CMD(auth, AUTHENTICATE); | 1165 | if (!hdr) |
1106 | CMD(assoc, ASSOCIATE); | 1166 | return -ENOBUFS; |
1107 | CMD(deauth, DEAUTHENTICATE); | 1167 | |
1108 | CMD(disassoc, DISASSOCIATE); | 1168 | /* allow always using the variables */ |
1109 | CMD(join_ibss, JOIN_IBSS); | 1169 | if (!split) { |
1110 | CMD(join_mesh, JOIN_MESH); | 1170 | split_start = &start; |
1111 | CMD(set_pmksa, SET_PMKSA); | 1171 | band_start = &start_band; |
1112 | CMD(del_pmksa, DEL_PMKSA); | 1172 | chan_start = &start_chan; |
1113 | CMD(flush_pmksa, FLUSH_PMKSA); | ||
1114 | if (dev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL) | ||
1115 | CMD(remain_on_channel, REMAIN_ON_CHANNEL); | ||
1116 | CMD(set_bitrate_mask, SET_TX_BITRATE_MASK); | ||
1117 | CMD(mgmt_tx, FRAME); | ||
1118 | CMD(mgmt_tx_cancel_wait, FRAME_WAIT_CANCEL); | ||
1119 | if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) { | ||
1120 | i++; | ||
1121 | if (nla_put_u32(msg, i, NL80211_CMD_SET_WIPHY_NETNS)) | ||
1122 | goto nla_put_failure; | ||
1123 | } | 1173 | } |
1124 | if (dev->ops->set_monitor_channel || dev->ops->start_ap || | 1174 | |
1125 | dev->ops->join_mesh) { | 1175 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, dev->wiphy_idx) || |
1126 | i++; | 1176 | nla_put_string(msg, NL80211_ATTR_WIPHY_NAME, |
1127 | if (nla_put_u32(msg, i, NL80211_CMD_SET_CHANNEL)) | 1177 | wiphy_name(&dev->wiphy)) || |
1178 | nla_put_u32(msg, NL80211_ATTR_GENERATION, | ||
1179 | cfg80211_rdev_list_generation)) | ||
1180 | goto nla_put_failure; | ||
1181 | |||
1182 | switch (*split_start) { | ||
1183 | case 0: | ||
1184 | if (nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT, | ||
1185 | dev->wiphy.retry_short) || | ||
1186 | nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_LONG, | ||
1187 | dev->wiphy.retry_long) || | ||
1188 | nla_put_u32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD, | ||
1189 | dev->wiphy.frag_threshold) || | ||
1190 | nla_put_u32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD, | ||
1191 | dev->wiphy.rts_threshold) || | ||
1192 | nla_put_u8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS, | ||
1193 | dev->wiphy.coverage_class) || | ||
1194 | nla_put_u8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS, | ||
1195 | dev->wiphy.max_scan_ssids) || | ||
1196 | nla_put_u8(msg, NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS, | ||
1197 | dev->wiphy.max_sched_scan_ssids) || | ||
1198 | nla_put_u16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN, | ||
1199 | dev->wiphy.max_scan_ie_len) || | ||
1200 | nla_put_u16(msg, NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN, | ||
1201 | dev->wiphy.max_sched_scan_ie_len) || | ||
1202 | nla_put_u8(msg, NL80211_ATTR_MAX_MATCH_SETS, | ||
1203 | dev->wiphy.max_match_sets)) | ||
1128 | goto nla_put_failure; | 1204 | goto nla_put_failure; |
1129 | } | 1205 | |
1130 | CMD(set_wds_peer, SET_WDS_PEER); | 1206 | if ((dev->wiphy.flags & WIPHY_FLAG_IBSS_RSN) && |
1131 | if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) { | 1207 | nla_put_flag(msg, NL80211_ATTR_SUPPORT_IBSS_RSN)) |
1132 | CMD(tdls_mgmt, TDLS_MGMT); | 1208 | goto nla_put_failure; |
1133 | CMD(tdls_oper, TDLS_OPER); | 1209 | if ((dev->wiphy.flags & WIPHY_FLAG_MESH_AUTH) && |
1134 | } | 1210 | nla_put_flag(msg, NL80211_ATTR_SUPPORT_MESH_AUTH)) |
1135 | if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) | 1211 | goto nla_put_failure; |
1136 | CMD(sched_scan_start, START_SCHED_SCAN); | 1212 | if ((dev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) && |
1137 | CMD(probe_client, PROBE_CLIENT); | 1213 | nla_put_flag(msg, NL80211_ATTR_SUPPORT_AP_UAPSD)) |
1138 | CMD(set_noack_map, SET_NOACK_MAP); | 1214 | goto nla_put_failure; |
1139 | if (dev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS) { | 1215 | if ((dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_FW_ROAM) && |
1140 | i++; | 1216 | nla_put_flag(msg, NL80211_ATTR_ROAM_SUPPORT)) |
1141 | if (nla_put_u32(msg, i, NL80211_CMD_REGISTER_BEACONS)) | 1217 | goto nla_put_failure; |
1218 | if ((dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) && | ||
1219 | nla_put_flag(msg, NL80211_ATTR_TDLS_SUPPORT)) | ||
1220 | goto nla_put_failure; | ||
1221 | if ((dev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) && | ||
1222 | nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP)) | ||
1142 | goto nla_put_failure; | 1223 | goto nla_put_failure; |
1143 | } | ||
1144 | CMD(start_p2p_device, START_P2P_DEVICE); | ||
1145 | CMD(set_mcast_rate, SET_MCAST_RATE); | ||
1146 | 1224 | ||
1147 | #ifdef CONFIG_NL80211_TESTMODE | 1225 | (*split_start)++; |
1148 | CMD(testmode_cmd, TESTMODE); | 1226 | if (split) |
1149 | #endif | 1227 | break; |
1228 | case 1: | ||
1229 | if (nla_put(msg, NL80211_ATTR_CIPHER_SUITES, | ||
1230 | sizeof(u32) * dev->wiphy.n_cipher_suites, | ||
1231 | dev->wiphy.cipher_suites)) | ||
1232 | goto nla_put_failure; | ||
1150 | 1233 | ||
1151 | #undef CMD | 1234 | if (nla_put_u8(msg, NL80211_ATTR_MAX_NUM_PMKIDS, |
1235 | dev->wiphy.max_num_pmkids)) | ||
1236 | goto nla_put_failure; | ||
1152 | 1237 | ||
1153 | if (dev->ops->connect || dev->ops->auth) { | 1238 | if ((dev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) && |
1154 | i++; | 1239 | nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE)) |
1155 | if (nla_put_u32(msg, i, NL80211_CMD_CONNECT)) | ||
1156 | goto nla_put_failure; | 1240 | goto nla_put_failure; |
1157 | } | ||
1158 | 1241 | ||
1159 | if (dev->ops->disconnect || dev->ops->deauth) { | 1242 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX, |
1160 | i++; | 1243 | dev->wiphy.available_antennas_tx) || |
1161 | if (nla_put_u32(msg, i, NL80211_CMD_DISCONNECT)) | 1244 | nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX, |
1245 | dev->wiphy.available_antennas_rx)) | ||
1162 | goto nla_put_failure; | 1246 | goto nla_put_failure; |
1163 | } | ||
1164 | 1247 | ||
1165 | nla_nest_end(msg, nl_cmds); | 1248 | if ((dev->wiphy.flags & WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD) && |
1249 | nla_put_u32(msg, NL80211_ATTR_PROBE_RESP_OFFLOAD, | ||
1250 | dev->wiphy.probe_resp_offload)) | ||
1251 | goto nla_put_failure; | ||
1166 | 1252 | ||
1167 | if (dev->ops->remain_on_channel && | 1253 | if ((dev->wiphy.available_antennas_tx || |
1168 | (dev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL) && | 1254 | dev->wiphy.available_antennas_rx) && |
1169 | nla_put_u32(msg, NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION, | 1255 | dev->ops->get_antenna) { |
1170 | dev->wiphy.max_remain_on_channel_duration)) | 1256 | u32 tx_ant = 0, rx_ant = 0; |
1171 | goto nla_put_failure; | 1257 | int res; |
1258 | res = rdev_get_antenna(dev, &tx_ant, &rx_ant); | ||
1259 | if (!res) { | ||
1260 | if (nla_put_u32(msg, | ||
1261 | NL80211_ATTR_WIPHY_ANTENNA_TX, | ||
1262 | tx_ant) || | ||
1263 | nla_put_u32(msg, | ||
1264 | NL80211_ATTR_WIPHY_ANTENNA_RX, | ||
1265 | rx_ant)) | ||
1266 | goto nla_put_failure; | ||
1267 | } | ||
1268 | } | ||
1172 | 1269 | ||
1173 | if ((dev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX) && | 1270 | (*split_start)++; |
1174 | nla_put_flag(msg, NL80211_ATTR_OFFCHANNEL_TX_OK)) | 1271 | if (split) |
1175 | goto nla_put_failure; | 1272 | break; |
1273 | case 2: | ||
1274 | if (nl80211_put_iftypes(msg, NL80211_ATTR_SUPPORTED_IFTYPES, | ||
1275 | dev->wiphy.interface_modes)) | ||
1276 | goto nla_put_failure; | ||
1277 | (*split_start)++; | ||
1278 | if (split) | ||
1279 | break; | ||
1280 | case 3: | ||
1281 | nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS); | ||
1282 | if (!nl_bands) | ||
1283 | goto nla_put_failure; | ||
1176 | 1284 | ||
1177 | if (mgmt_stypes) { | 1285 | for (band = *band_start; band < IEEE80211_NUM_BANDS; band++) { |
1178 | u16 stypes; | 1286 | struct ieee80211_supported_band *sband; |
1179 | struct nlattr *nl_ftypes, *nl_ifs; | ||
1180 | enum nl80211_iftype ift; | ||
1181 | 1287 | ||
1182 | nl_ifs = nla_nest_start(msg, NL80211_ATTR_TX_FRAME_TYPES); | 1288 | sband = dev->wiphy.bands[band]; |
1183 | if (!nl_ifs) | ||
1184 | goto nla_put_failure; | ||
1185 | 1289 | ||
1186 | for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) { | 1290 | if (!sband) |
1187 | nl_ftypes = nla_nest_start(msg, ift); | 1291 | continue; |
1188 | if (!nl_ftypes) | 1292 | |
1293 | nl_band = nla_nest_start(msg, band); | ||
1294 | if (!nl_band) | ||
1189 | goto nla_put_failure; | 1295 | goto nla_put_failure; |
1190 | i = 0; | 1296 | |
1191 | stypes = mgmt_stypes[ift].tx; | 1297 | switch (*chan_start) { |
1192 | while (stypes) { | 1298 | case 0: |
1193 | if ((stypes & 1) && | 1299 | if (nl80211_send_band_rateinfo(msg, sband)) |
1194 | nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE, | ||
1195 | (i << 4) | IEEE80211_FTYPE_MGMT)) | ||
1196 | goto nla_put_failure; | 1300 | goto nla_put_failure; |
1197 | stypes >>= 1; | 1301 | (*chan_start)++; |
1198 | i++; | 1302 | if (split) |
1303 | break; | ||
1304 | default: | ||
1305 | /* add frequencies */ | ||
1306 | nl_freqs = nla_nest_start( | ||
1307 | msg, NL80211_BAND_ATTR_FREQS); | ||
1308 | if (!nl_freqs) | ||
1309 | goto nla_put_failure; | ||
1310 | |||
1311 | for (i = *chan_start - 1; | ||
1312 | i < sband->n_channels; | ||
1313 | i++) { | ||
1314 | nl_freq = nla_nest_start(msg, i); | ||
1315 | if (!nl_freq) | ||
1316 | goto nla_put_failure; | ||
1317 | |||
1318 | chan = &sband->channels[i]; | ||
1319 | |||
1320 | if (nl80211_msg_put_channel(msg, chan, | ||
1321 | split)) | ||
1322 | goto nla_put_failure; | ||
1323 | |||
1324 | nla_nest_end(msg, nl_freq); | ||
1325 | if (split) | ||
1326 | break; | ||
1327 | } | ||
1328 | if (i < sband->n_channels) | ||
1329 | *chan_start = i + 2; | ||
1330 | else | ||
1331 | *chan_start = 0; | ||
1332 | nla_nest_end(msg, nl_freqs); | ||
1333 | } | ||
1334 | |||
1335 | nla_nest_end(msg, nl_band); | ||
1336 | |||
1337 | if (split) { | ||
1338 | /* start again here */ | ||
1339 | if (*chan_start) | ||
1340 | band--; | ||
1341 | break; | ||
1199 | } | 1342 | } |
1200 | nla_nest_end(msg, nl_ftypes); | ||
1201 | } | 1343 | } |
1344 | nla_nest_end(msg, nl_bands); | ||
1202 | 1345 | ||
1203 | nla_nest_end(msg, nl_ifs); | 1346 | if (band < IEEE80211_NUM_BANDS) |
1347 | *band_start = band + 1; | ||
1348 | else | ||
1349 | *band_start = 0; | ||
1204 | 1350 | ||
1205 | nl_ifs = nla_nest_start(msg, NL80211_ATTR_RX_FRAME_TYPES); | 1351 | /* if bands & channels are done, continue outside */ |
1206 | if (!nl_ifs) | 1352 | if (*band_start == 0 && *chan_start == 0) |
1353 | (*split_start)++; | ||
1354 | if (split) | ||
1355 | break; | ||
1356 | case 4: | ||
1357 | nl_cmds = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_COMMANDS); | ||
1358 | if (!nl_cmds) | ||
1207 | goto nla_put_failure; | 1359 | goto nla_put_failure; |
1208 | 1360 | ||
1209 | for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) { | 1361 | i = 0; |
1210 | nl_ftypes = nla_nest_start(msg, ift); | 1362 | #define CMD(op, n) \ |
1211 | if (!nl_ftypes) | 1363 | do { \ |
1364 | if (dev->ops->op) { \ | ||
1365 | i++; \ | ||
1366 | if (nla_put_u32(msg, i, NL80211_CMD_ ## n)) \ | ||
1367 | goto nla_put_failure; \ | ||
1368 | } \ | ||
1369 | } while (0) | ||
1370 | |||
1371 | CMD(add_virtual_intf, NEW_INTERFACE); | ||
1372 | CMD(change_virtual_intf, SET_INTERFACE); | ||
1373 | CMD(add_key, NEW_KEY); | ||
1374 | CMD(start_ap, START_AP); | ||
1375 | CMD(add_station, NEW_STATION); | ||
1376 | CMD(add_mpath, NEW_MPATH); | ||
1377 | CMD(update_mesh_config, SET_MESH_CONFIG); | ||
1378 | CMD(change_bss, SET_BSS); | ||
1379 | CMD(auth, AUTHENTICATE); | ||
1380 | CMD(assoc, ASSOCIATE); | ||
1381 | CMD(deauth, DEAUTHENTICATE); | ||
1382 | CMD(disassoc, DISASSOCIATE); | ||
1383 | CMD(join_ibss, JOIN_IBSS); | ||
1384 | CMD(join_mesh, JOIN_MESH); | ||
1385 | CMD(set_pmksa, SET_PMKSA); | ||
1386 | CMD(del_pmksa, DEL_PMKSA); | ||
1387 | CMD(flush_pmksa, FLUSH_PMKSA); | ||
1388 | if (dev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL) | ||
1389 | CMD(remain_on_channel, REMAIN_ON_CHANNEL); | ||
1390 | CMD(set_bitrate_mask, SET_TX_BITRATE_MASK); | ||
1391 | CMD(mgmt_tx, FRAME); | ||
1392 | CMD(mgmt_tx_cancel_wait, FRAME_WAIT_CANCEL); | ||
1393 | if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) { | ||
1394 | i++; | ||
1395 | if (nla_put_u32(msg, i, NL80211_CMD_SET_WIPHY_NETNS)) | ||
1212 | goto nla_put_failure; | 1396 | goto nla_put_failure; |
1213 | i = 0; | ||
1214 | stypes = mgmt_stypes[ift].rx; | ||
1215 | while (stypes) { | ||
1216 | if ((stypes & 1) && | ||
1217 | nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE, | ||
1218 | (i << 4) | IEEE80211_FTYPE_MGMT)) | ||
1219 | goto nla_put_failure; | ||
1220 | stypes >>= 1; | ||
1221 | i++; | ||
1222 | } | ||
1223 | nla_nest_end(msg, nl_ftypes); | ||
1224 | } | 1397 | } |
1225 | nla_nest_end(msg, nl_ifs); | 1398 | if (dev->ops->set_monitor_channel || dev->ops->start_ap || |
1226 | } | 1399 | dev->ops->join_mesh) { |
1400 | i++; | ||
1401 | if (nla_put_u32(msg, i, NL80211_CMD_SET_CHANNEL)) | ||
1402 | goto nla_put_failure; | ||
1403 | } | ||
1404 | CMD(set_wds_peer, SET_WDS_PEER); | ||
1405 | if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) { | ||
1406 | CMD(tdls_mgmt, TDLS_MGMT); | ||
1407 | CMD(tdls_oper, TDLS_OPER); | ||
1408 | } | ||
1409 | if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) | ||
1410 | CMD(sched_scan_start, START_SCHED_SCAN); | ||
1411 | CMD(probe_client, PROBE_CLIENT); | ||
1412 | CMD(set_noack_map, SET_NOACK_MAP); | ||
1413 | if (dev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS) { | ||
1414 | i++; | ||
1415 | if (nla_put_u32(msg, i, NL80211_CMD_REGISTER_BEACONS)) | ||
1416 | goto nla_put_failure; | ||
1417 | } | ||
1418 | CMD(start_p2p_device, START_P2P_DEVICE); | ||
1419 | CMD(set_mcast_rate, SET_MCAST_RATE); | ||
1227 | 1420 | ||
1228 | #ifdef CONFIG_PM | 1421 | #ifdef CONFIG_NL80211_TESTMODE |
1229 | if (dev->wiphy.wowlan.flags || dev->wiphy.wowlan.n_patterns) { | 1422 | CMD(testmode_cmd, TESTMODE); |
1230 | struct nlattr *nl_wowlan; | 1423 | #endif |
1231 | 1424 | ||
1232 | nl_wowlan = nla_nest_start(msg, | 1425 | #undef CMD |
1233 | NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED); | ||
1234 | if (!nl_wowlan) | ||
1235 | goto nla_put_failure; | ||
1236 | 1426 | ||
1237 | if (((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_ANY) && | 1427 | if (dev->ops->connect || dev->ops->auth) { |
1238 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) || | 1428 | i++; |
1239 | ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_DISCONNECT) && | 1429 | if (nla_put_u32(msg, i, NL80211_CMD_CONNECT)) |
1240 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) || | ||
1241 | ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_MAGIC_PKT) && | ||
1242 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) || | ||
1243 | ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY) && | ||
1244 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED)) || | ||
1245 | ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) && | ||
1246 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) || | ||
1247 | ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ) && | ||
1248 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) || | ||
1249 | ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_4WAY_HANDSHAKE) && | ||
1250 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) || | ||
1251 | ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_RFKILL_RELEASE) && | ||
1252 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE))) | ||
1253 | goto nla_put_failure; | ||
1254 | if (dev->wiphy.wowlan.n_patterns) { | ||
1255 | struct nl80211_wowlan_pattern_support pat = { | ||
1256 | .max_patterns = dev->wiphy.wowlan.n_patterns, | ||
1257 | .min_pattern_len = | ||
1258 | dev->wiphy.wowlan.pattern_min_len, | ||
1259 | .max_pattern_len = | ||
1260 | dev->wiphy.wowlan.pattern_max_len, | ||
1261 | .max_pkt_offset = | ||
1262 | dev->wiphy.wowlan.max_pkt_offset, | ||
1263 | }; | ||
1264 | if (nla_put(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN, | ||
1265 | sizeof(pat), &pat)) | ||
1266 | goto nla_put_failure; | 1430 | goto nla_put_failure; |
1267 | } | 1431 | } |
1268 | 1432 | ||
1269 | nla_nest_end(msg, nl_wowlan); | 1433 | if (dev->ops->disconnect || dev->ops->deauth) { |
1270 | } | 1434 | i++; |
1435 | if (nla_put_u32(msg, i, NL80211_CMD_DISCONNECT)) | ||
1436 | goto nla_put_failure; | ||
1437 | } | ||
1438 | |||
1439 | nla_nest_end(msg, nl_cmds); | ||
1440 | (*split_start)++; | ||
1441 | if (split) | ||
1442 | break; | ||
1443 | case 5: | ||
1444 | if (dev->ops->remain_on_channel && | ||
1445 | (dev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL) && | ||
1446 | nla_put_u32(msg, | ||
1447 | NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION, | ||
1448 | dev->wiphy.max_remain_on_channel_duration)) | ||
1449 | goto nla_put_failure; | ||
1450 | |||
1451 | if ((dev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX) && | ||
1452 | nla_put_flag(msg, NL80211_ATTR_OFFCHANNEL_TX_OK)) | ||
1453 | goto nla_put_failure; | ||
1454 | |||
1455 | if (nl80211_send_mgmt_stypes(msg, mgmt_stypes)) | ||
1456 | goto nla_put_failure; | ||
1457 | (*split_start)++; | ||
1458 | if (split) | ||
1459 | break; | ||
1460 | case 6: | ||
1461 | #ifdef CONFIG_PM | ||
1462 | if (nl80211_send_wowlan(msg, dev, split)) | ||
1463 | goto nla_put_failure; | ||
1464 | (*split_start)++; | ||
1465 | if (split) | ||
1466 | break; | ||
1467 | #else | ||
1468 | (*split_start)++; | ||
1271 | #endif | 1469 | #endif |
1470 | case 7: | ||
1471 | if (nl80211_put_iftypes(msg, NL80211_ATTR_SOFTWARE_IFTYPES, | ||
1472 | dev->wiphy.software_iftypes)) | ||
1473 | goto nla_put_failure; | ||
1272 | 1474 | ||
1273 | if (nl80211_put_iftypes(msg, NL80211_ATTR_SOFTWARE_IFTYPES, | 1475 | if (nl80211_put_iface_combinations(&dev->wiphy, msg, split)) |
1274 | dev->wiphy.software_iftypes)) | 1476 | goto nla_put_failure; |
1275 | goto nla_put_failure; | ||
1276 | 1477 | ||
1277 | if (nl80211_put_iface_combinations(&dev->wiphy, msg)) | 1478 | (*split_start)++; |
1278 | goto nla_put_failure; | 1479 | if (split) |
1480 | break; | ||
1481 | case 8: | ||
1482 | if ((dev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME) && | ||
1483 | nla_put_u32(msg, NL80211_ATTR_DEVICE_AP_SME, | ||
1484 | dev->wiphy.ap_sme_capa)) | ||
1485 | goto nla_put_failure; | ||
1279 | 1486 | ||
1280 | if ((dev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME) && | 1487 | features = dev->wiphy.features; |
1281 | nla_put_u32(msg, NL80211_ATTR_DEVICE_AP_SME, | 1488 | /* |
1282 | dev->wiphy.ap_sme_capa)) | 1489 | * We can only add the per-channel limit information if the |
1283 | goto nla_put_failure; | 1490 | * dump is split, otherwise it makes it too big. Therefore |
1491 | * only advertise it in that case. | ||
1492 | */ | ||
1493 | if (split) | ||
1494 | features |= NL80211_FEATURE_ADVERTISE_CHAN_LIMITS; | ||
1495 | if (nla_put_u32(msg, NL80211_ATTR_FEATURE_FLAGS, features)) | ||
1496 | goto nla_put_failure; | ||
1284 | 1497 | ||
1285 | if (nla_put_u32(msg, NL80211_ATTR_FEATURE_FLAGS, | 1498 | if (dev->wiphy.ht_capa_mod_mask && |
1286 | dev->wiphy.features)) | 1499 | nla_put(msg, NL80211_ATTR_HT_CAPABILITY_MASK, |
1287 | goto nla_put_failure; | 1500 | sizeof(*dev->wiphy.ht_capa_mod_mask), |
1501 | dev->wiphy.ht_capa_mod_mask)) | ||
1502 | goto nla_put_failure; | ||
1288 | 1503 | ||
1289 | if (dev->wiphy.ht_capa_mod_mask && | 1504 | if (dev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME && |
1290 | nla_put(msg, NL80211_ATTR_HT_CAPABILITY_MASK, | 1505 | dev->wiphy.max_acl_mac_addrs && |
1291 | sizeof(*dev->wiphy.ht_capa_mod_mask), | 1506 | nla_put_u32(msg, NL80211_ATTR_MAC_ACL_MAX, |
1292 | dev->wiphy.ht_capa_mod_mask)) | 1507 | dev->wiphy.max_acl_mac_addrs)) |
1293 | goto nla_put_failure; | 1508 | goto nla_put_failure; |
1294 | 1509 | ||
1295 | if (dev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME && | 1510 | /* |
1296 | dev->wiphy.max_acl_mac_addrs && | 1511 | * Any information below this point is only available to |
1297 | nla_put_u32(msg, NL80211_ATTR_MAC_ACL_MAX, | 1512 | * applications that can deal with it being split. This |
1298 | dev->wiphy.max_acl_mac_addrs)) | 1513 | * helps ensure that newly added capabilities don't break |
1299 | goto nla_put_failure; | 1514 | * older tools by overrunning their buffers. |
1515 | * | ||
1516 | * We still increment split_start so that in the split | ||
1517 | * case we'll continue with more data in the next round, | ||
1518 | * but break unconditionally so unsplit data stops here. | ||
1519 | */ | ||
1520 | (*split_start)++; | ||
1521 | break; | ||
1522 | case 9: | ||
1523 | if (dev->wiphy.extended_capabilities && | ||
1524 | (nla_put(msg, NL80211_ATTR_EXT_CAPA, | ||
1525 | dev->wiphy.extended_capabilities_len, | ||
1526 | dev->wiphy.extended_capabilities) || | ||
1527 | nla_put(msg, NL80211_ATTR_EXT_CAPA_MASK, | ||
1528 | dev->wiphy.extended_capabilities_len, | ||
1529 | dev->wiphy.extended_capabilities_mask))) | ||
1530 | goto nla_put_failure; | ||
1300 | 1531 | ||
1532 | if (dev->wiphy.vht_capa_mod_mask && | ||
1533 | nla_put(msg, NL80211_ATTR_VHT_CAPABILITY_MASK, | ||
1534 | sizeof(*dev->wiphy.vht_capa_mod_mask), | ||
1535 | dev->wiphy.vht_capa_mod_mask)) | ||
1536 | goto nla_put_failure; | ||
1537 | |||
1538 | /* done */ | ||
1539 | *split_start = 0; | ||
1540 | break; | ||
1541 | } | ||
1301 | return genlmsg_end(msg, hdr); | 1542 | return genlmsg_end(msg, hdr); |
1302 | 1543 | ||
1303 | nla_put_failure: | 1544 | nla_put_failure: |
@@ -1310,39 +1551,80 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) | |||
1310 | int idx = 0, ret; | 1551 | int idx = 0, ret; |
1311 | int start = cb->args[0]; | 1552 | int start = cb->args[0]; |
1312 | struct cfg80211_registered_device *dev; | 1553 | struct cfg80211_registered_device *dev; |
1554 | s64 filter_wiphy = -1; | ||
1555 | bool split = false; | ||
1556 | struct nlattr **tb = nl80211_fam.attrbuf; | ||
1557 | int res; | ||
1313 | 1558 | ||
1314 | mutex_lock(&cfg80211_mutex); | 1559 | mutex_lock(&cfg80211_mutex); |
1560 | res = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, | ||
1561 | tb, nl80211_fam.maxattr, nl80211_policy); | ||
1562 | if (res == 0) { | ||
1563 | split = tb[NL80211_ATTR_SPLIT_WIPHY_DUMP]; | ||
1564 | if (tb[NL80211_ATTR_WIPHY]) | ||
1565 | filter_wiphy = nla_get_u32(tb[NL80211_ATTR_WIPHY]); | ||
1566 | if (tb[NL80211_ATTR_WDEV]) | ||
1567 | filter_wiphy = nla_get_u64(tb[NL80211_ATTR_WDEV]) >> 32; | ||
1568 | if (tb[NL80211_ATTR_IFINDEX]) { | ||
1569 | struct net_device *netdev; | ||
1570 | int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]); | ||
1571 | |||
1572 | netdev = dev_get_by_index(sock_net(skb->sk), ifidx); | ||
1573 | if (!netdev) { | ||
1574 | mutex_unlock(&cfg80211_mutex); | ||
1575 | return -ENODEV; | ||
1576 | } | ||
1577 | if (netdev->ieee80211_ptr) { | ||
1578 | dev = wiphy_to_dev( | ||
1579 | netdev->ieee80211_ptr->wiphy); | ||
1580 | filter_wiphy = dev->wiphy_idx; | ||
1581 | } | ||
1582 | dev_put(netdev); | ||
1583 | } | ||
1584 | } | ||
1585 | |||
1315 | list_for_each_entry(dev, &cfg80211_rdev_list, list) { | 1586 | list_for_each_entry(dev, &cfg80211_rdev_list, list) { |
1316 | if (!net_eq(wiphy_net(&dev->wiphy), sock_net(skb->sk))) | 1587 | if (!net_eq(wiphy_net(&dev->wiphy), sock_net(skb->sk))) |
1317 | continue; | 1588 | continue; |
1318 | if (++idx <= start) | 1589 | if (++idx <= start) |
1319 | continue; | 1590 | continue; |
1320 | ret = nl80211_send_wiphy(skb, NETLINK_CB(cb->skb).portid, | 1591 | if (filter_wiphy != -1 && dev->wiphy_idx != filter_wiphy) |
1321 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | 1592 | continue; |
1322 | dev); | 1593 | /* attempt to fit multiple wiphy data chunks into the skb */ |
1323 | if (ret < 0) { | 1594 | do { |
1324 | /* | 1595 | ret = nl80211_send_wiphy(dev, skb, |
1325 | * If sending the wiphy data didn't fit (ENOBUFS or | 1596 | NETLINK_CB(cb->skb).portid, |
1326 | * EMSGSIZE returned), this SKB is still empty (so | 1597 | cb->nlh->nlmsg_seq, |
1327 | * it's not too big because another wiphy dataset is | 1598 | NLM_F_MULTI, |
1328 | * already in the skb) and we've not tried to adjust | 1599 | split, &cb->args[1], |
1329 | * the dump allocation yet ... then adjust the alloc | 1600 | &cb->args[2], |
1330 | * size to be bigger, and return 1 but with the empty | 1601 | &cb->args[3]); |
1331 | * skb. This results in an empty message being RX'ed | 1602 | if (ret < 0) { |
1332 | * in userspace, but that is ignored. | 1603 | /* |
1333 | * | 1604 | * If sending the wiphy data didn't fit (ENOBUFS |
1334 | * We can then retry with the larger buffer. | 1605 | * or EMSGSIZE returned), this SKB is still |
1335 | */ | 1606 | * empty (so it's not too big because another |
1336 | if ((ret == -ENOBUFS || ret == -EMSGSIZE) && | 1607 | * wiphy dataset is already in the skb) and |
1337 | !skb->len && | 1608 | * we've not tried to adjust the dump allocation |
1338 | cb->min_dump_alloc < 4096) { | 1609 | * yet ... then adjust the alloc size to be |
1339 | cb->min_dump_alloc = 4096; | 1610 | * bigger, and return 1 but with the empty skb. |
1340 | mutex_unlock(&cfg80211_mutex); | 1611 | * This results in an empty message being RX'ed |
1341 | return 1; | 1612 | * in userspace, but that is ignored. |
1613 | * | ||
1614 | * We can then retry with the larger buffer. | ||
1615 | */ | ||
1616 | if ((ret == -ENOBUFS || ret == -EMSGSIZE) && | ||
1617 | !skb->len && | ||
1618 | cb->min_dump_alloc < 4096) { | ||
1619 | cb->min_dump_alloc = 4096; | ||
1620 | mutex_unlock(&cfg80211_mutex); | ||
1621 | return 1; | ||
1622 | } | ||
1623 | idx--; | ||
1624 | break; | ||
1342 | } | 1625 | } |
1343 | idx--; | 1626 | } while (cb->args[1] > 0); |
1344 | break; | 1627 | break; |
1345 | } | ||
1346 | } | 1628 | } |
1347 | mutex_unlock(&cfg80211_mutex); | 1629 | mutex_unlock(&cfg80211_mutex); |
1348 | 1630 | ||
@@ -1360,7 +1642,8 @@ static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
1360 | if (!msg) | 1642 | if (!msg) |
1361 | return -ENOMEM; | 1643 | return -ENOMEM; |
1362 | 1644 | ||
1363 | if (nl80211_send_wiphy(msg, info->snd_portid, info->snd_seq, 0, dev) < 0) { | 1645 | if (nl80211_send_wiphy(dev, msg, info->snd_portid, info->snd_seq, 0, |
1646 | false, NULL, NULL, NULL) < 0) { | ||
1364 | nlmsg_free(msg); | 1647 | nlmsg_free(msg); |
1365 | return -ENOBUFS; | 1648 | return -ENOBUFS; |
1366 | } | 1649 | } |
@@ -2967,6 +3250,7 @@ static int parse_station_flags(struct genl_info *info, | |||
2967 | sta_flags = nla_data(nla); | 3250 | sta_flags = nla_data(nla); |
2968 | params->sta_flags_mask = sta_flags->mask; | 3251 | params->sta_flags_mask = sta_flags->mask; |
2969 | params->sta_flags_set = sta_flags->set; | 3252 | params->sta_flags_set = sta_flags->set; |
3253 | params->sta_flags_set &= params->sta_flags_mask; | ||
2970 | if ((params->sta_flags_mask | | 3254 | if ((params->sta_flags_mask | |
2971 | params->sta_flags_set) & BIT(__NL80211_STA_FLAG_INVALID)) | 3255 | params->sta_flags_set) & BIT(__NL80211_STA_FLAG_INVALID)) |
2972 | return -EINVAL; | 3256 | return -EINVAL; |
@@ -3320,6 +3604,136 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info) | |||
3320 | return genlmsg_reply(msg, info); | 3604 | return genlmsg_reply(msg, info); |
3321 | } | 3605 | } |
3322 | 3606 | ||
3607 | int cfg80211_check_station_change(struct wiphy *wiphy, | ||
3608 | struct station_parameters *params, | ||
3609 | enum cfg80211_station_type statype) | ||
3610 | { | ||
3611 | if (params->listen_interval != -1) | ||
3612 | return -EINVAL; | ||
3613 | if (params->aid) | ||
3614 | return -EINVAL; | ||
3615 | |||
3616 | /* When you run into this, adjust the code below for the new flag */ | ||
3617 | BUILD_BUG_ON(NL80211_STA_FLAG_MAX != 7); | ||
3618 | |||
3619 | switch (statype) { | ||
3620 | case CFG80211_STA_MESH_PEER_KERNEL: | ||
3621 | case CFG80211_STA_MESH_PEER_USER: | ||
3622 | /* | ||
3623 | * No ignoring the TDLS flag here -- the userspace mesh | ||
3624 | * code doesn't have the bug of including TDLS in the | ||
3625 | * mask everywhere. | ||
3626 | */ | ||
3627 | if (params->sta_flags_mask & | ||
3628 | ~(BIT(NL80211_STA_FLAG_AUTHENTICATED) | | ||
3629 | BIT(NL80211_STA_FLAG_MFP) | | ||
3630 | BIT(NL80211_STA_FLAG_AUTHORIZED))) | ||
3631 | return -EINVAL; | ||
3632 | break; | ||
3633 | case CFG80211_STA_TDLS_PEER_SETUP: | ||
3634 | case CFG80211_STA_TDLS_PEER_ACTIVE: | ||
3635 | if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) | ||
3636 | return -EINVAL; | ||
3637 | /* ignore since it can't change */ | ||
3638 | params->sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER); | ||
3639 | break; | ||
3640 | default: | ||
3641 | /* disallow mesh-specific things */ | ||
3642 | if (params->plink_action != NL80211_PLINK_ACTION_NO_ACTION) | ||
3643 | return -EINVAL; | ||
3644 | if (params->local_pm) | ||
3645 | return -EINVAL; | ||
3646 | if (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE) | ||
3647 | return -EINVAL; | ||
3648 | } | ||
3649 | |||
3650 | if (statype != CFG80211_STA_TDLS_PEER_SETUP && | ||
3651 | statype != CFG80211_STA_TDLS_PEER_ACTIVE) { | ||
3652 | /* TDLS can't be set, ... */ | ||
3653 | if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) | ||
3654 | return -EINVAL; | ||
3655 | /* | ||
3656 | * ... but don't bother the driver with it. This works around | ||
3657 | * a hostapd/wpa_supplicant issue -- it always includes the | ||
3658 | * TLDS_PEER flag in the mask even for AP mode. | ||
3659 | */ | ||
3660 | params->sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER); | ||
3661 | } | ||
3662 | |||
3663 | if (statype != CFG80211_STA_TDLS_PEER_SETUP) { | ||
3664 | /* reject other things that can't change */ | ||
3665 | if (params->sta_modify_mask & STATION_PARAM_APPLY_UAPSD) | ||
3666 | return -EINVAL; | ||
3667 | if (params->sta_modify_mask & STATION_PARAM_APPLY_CAPABILITY) | ||
3668 | return -EINVAL; | ||
3669 | if (params->supported_rates) | ||
3670 | return -EINVAL; | ||
3671 | if (params->ext_capab || params->ht_capa || params->vht_capa) | ||
3672 | return -EINVAL; | ||
3673 | } | ||
3674 | |||
3675 | if (statype != CFG80211_STA_AP_CLIENT) { | ||
3676 | if (params->vlan) | ||
3677 | return -EINVAL; | ||
3678 | } | ||
3679 | |||
3680 | switch (statype) { | ||
3681 | case CFG80211_STA_AP_MLME_CLIENT: | ||
3682 | /* Use this only for authorizing/unauthorizing a station */ | ||
3683 | if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED))) | ||
3684 | return -EOPNOTSUPP; | ||
3685 | break; | ||
3686 | case CFG80211_STA_AP_CLIENT: | ||
3687 | /* accept only the listed bits */ | ||
3688 | if (params->sta_flags_mask & | ||
3689 | ~(BIT(NL80211_STA_FLAG_AUTHORIZED) | | ||
3690 | BIT(NL80211_STA_FLAG_AUTHENTICATED) | | ||
3691 | BIT(NL80211_STA_FLAG_ASSOCIATED) | | ||
3692 | BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) | | ||
3693 | BIT(NL80211_STA_FLAG_WME) | | ||
3694 | BIT(NL80211_STA_FLAG_MFP))) | ||
3695 | return -EINVAL; | ||
3696 | |||
3697 | /* but authenticated/associated only if driver handles it */ | ||
3698 | if (!(wiphy->features & NL80211_FEATURE_FULL_AP_CLIENT_STATE) && | ||
3699 | params->sta_flags_mask & | ||
3700 | (BIT(NL80211_STA_FLAG_AUTHENTICATED) | | ||
3701 | BIT(NL80211_STA_FLAG_ASSOCIATED))) | ||
3702 | return -EINVAL; | ||
3703 | break; | ||
3704 | case CFG80211_STA_IBSS: | ||
3705 | case CFG80211_STA_AP_STA: | ||
3706 | /* reject any changes other than AUTHORIZED */ | ||
3707 | if (params->sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED)) | ||
3708 | return -EINVAL; | ||
3709 | break; | ||
3710 | case CFG80211_STA_TDLS_PEER_SETUP: | ||
3711 | /* reject any changes other than AUTHORIZED or WME */ | ||
3712 | if (params->sta_flags_mask & ~(BIT(NL80211_STA_FLAG_AUTHORIZED) | | ||
3713 | BIT(NL80211_STA_FLAG_WME))) | ||
3714 | return -EINVAL; | ||
3715 | /* force (at least) rates when authorizing */ | ||
3716 | if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED) && | ||
3717 | !params->supported_rates) | ||
3718 | return -EINVAL; | ||
3719 | break; | ||
3720 | case CFG80211_STA_TDLS_PEER_ACTIVE: | ||
3721 | /* reject any changes */ | ||
3722 | return -EINVAL; | ||
3723 | case CFG80211_STA_MESH_PEER_KERNEL: | ||
3724 | if (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE) | ||
3725 | return -EINVAL; | ||
3726 | break; | ||
3727 | case CFG80211_STA_MESH_PEER_USER: | ||
3728 | if (params->plink_action != NL80211_PLINK_ACTION_NO_ACTION) | ||
3729 | return -EINVAL; | ||
3730 | break; | ||
3731 | } | ||
3732 | |||
3733 | return 0; | ||
3734 | } | ||
3735 | EXPORT_SYMBOL(cfg80211_check_station_change); | ||
3736 | |||
3323 | /* | 3737 | /* |
3324 | * Get vlan interface making sure it is running and on the right wiphy. | 3738 | * Get vlan interface making sure it is running and on the right wiphy. |
3325 | */ | 3739 | */ |
@@ -3342,6 +3756,13 @@ static struct net_device *get_vlan(struct genl_info *info, | |||
3342 | goto error; | 3756 | goto error; |
3343 | } | 3757 | } |
3344 | 3758 | ||
3759 | if (v->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && | ||
3760 | v->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && | ||
3761 | v->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) { | ||
3762 | ret = -EINVAL; | ||
3763 | goto error; | ||
3764 | } | ||
3765 | |||
3345 | if (!netif_running(v)) { | 3766 | if (!netif_running(v)) { |
3346 | ret = -ENETDOWN; | 3767 | ret = -ENETDOWN; |
3347 | goto error; | 3768 | goto error; |
@@ -3359,21 +3780,13 @@ nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] __read_mostly = { | |||
3359 | [NL80211_STA_WME_MAX_SP] = { .type = NLA_U8 }, | 3780 | [NL80211_STA_WME_MAX_SP] = { .type = NLA_U8 }, |
3360 | }; | 3781 | }; |
3361 | 3782 | ||
3362 | static int nl80211_set_station_tdls(struct genl_info *info, | 3783 | static int nl80211_parse_sta_wme(struct genl_info *info, |
3363 | struct station_parameters *params) | 3784 | struct station_parameters *params) |
3364 | { | 3785 | { |
3365 | struct nlattr *tb[NL80211_STA_WME_MAX + 1]; | 3786 | struct nlattr *tb[NL80211_STA_WME_MAX + 1]; |
3366 | struct nlattr *nla; | 3787 | struct nlattr *nla; |
3367 | int err; | 3788 | int err; |
3368 | 3789 | ||
3369 | /* Dummy STA entry gets updated once the peer capabilities are known */ | ||
3370 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) | ||
3371 | params->ht_capa = | ||
3372 | nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); | ||
3373 | if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) | ||
3374 | params->vht_capa = | ||
3375 | nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]); | ||
3376 | |||
3377 | /* parse WME attributes if present */ | 3790 | /* parse WME attributes if present */ |
3378 | if (!info->attrs[NL80211_ATTR_STA_WME]) | 3791 | if (!info->attrs[NL80211_ATTR_STA_WME]) |
3379 | return 0; | 3792 | return 0; |
@@ -3401,18 +3814,34 @@ static int nl80211_set_station_tdls(struct genl_info *info, | |||
3401 | return 0; | 3814 | return 0; |
3402 | } | 3815 | } |
3403 | 3816 | ||
3817 | static int nl80211_set_station_tdls(struct genl_info *info, | ||
3818 | struct station_parameters *params) | ||
3819 | { | ||
3820 | /* Dummy STA entry gets updated once the peer capabilities are known */ | ||
3821 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) | ||
3822 | params->ht_capa = | ||
3823 | nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); | ||
3824 | if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) | ||
3825 | params->vht_capa = | ||
3826 | nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]); | ||
3827 | |||
3828 | return nl80211_parse_sta_wme(info, params); | ||
3829 | } | ||
3830 | |||
3404 | static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) | 3831 | static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) |
3405 | { | 3832 | { |
3406 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 3833 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
3407 | int err; | ||
3408 | struct net_device *dev = info->user_ptr[1]; | 3834 | struct net_device *dev = info->user_ptr[1]; |
3409 | struct station_parameters params; | 3835 | struct station_parameters params; |
3410 | u8 *mac_addr = NULL; | 3836 | u8 *mac_addr; |
3837 | int err; | ||
3411 | 3838 | ||
3412 | memset(¶ms, 0, sizeof(params)); | 3839 | memset(¶ms, 0, sizeof(params)); |
3413 | 3840 | ||
3414 | params.listen_interval = -1; | 3841 | params.listen_interval = -1; |
3415 | params.plink_state = -1; | 3842 | |
3843 | if (!rdev->ops->change_station) | ||
3844 | return -EOPNOTSUPP; | ||
3416 | 3845 | ||
3417 | if (info->attrs[NL80211_ATTR_STA_AID]) | 3846 | if (info->attrs[NL80211_ATTR_STA_AID]) |
3418 | return -EINVAL; | 3847 | return -EINVAL; |
@@ -3445,19 +3874,23 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) | |||
3445 | if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]) | 3874 | if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]) |
3446 | return -EINVAL; | 3875 | return -EINVAL; |
3447 | 3876 | ||
3448 | if (!rdev->ops->change_station) | ||
3449 | return -EOPNOTSUPP; | ||
3450 | |||
3451 | if (parse_station_flags(info, dev->ieee80211_ptr->iftype, ¶ms)) | 3877 | if (parse_station_flags(info, dev->ieee80211_ptr->iftype, ¶ms)) |
3452 | return -EINVAL; | 3878 | return -EINVAL; |
3453 | 3879 | ||
3454 | if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) | 3880 | if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) { |
3455 | params.plink_action = | 3881 | params.plink_action = |
3456 | nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]); | 3882 | nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]); |
3883 | if (params.plink_action >= NUM_NL80211_PLINK_ACTIONS) | ||
3884 | return -EINVAL; | ||
3885 | } | ||
3457 | 3886 | ||
3458 | if (info->attrs[NL80211_ATTR_STA_PLINK_STATE]) | 3887 | if (info->attrs[NL80211_ATTR_STA_PLINK_STATE]) { |
3459 | params.plink_state = | 3888 | params.plink_state = |
3460 | nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]); | 3889 | nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]); |
3890 | if (params.plink_state >= NUM_NL80211_PLINK_STATES) | ||
3891 | return -EINVAL; | ||
3892 | params.sta_modify_mask |= STATION_PARAM_APPLY_PLINK_STATE; | ||
3893 | } | ||
3461 | 3894 | ||
3462 | if (info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE]) { | 3895 | if (info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE]) { |
3463 | enum nl80211_mesh_power_mode pm = nla_get_u32( | 3896 | enum nl80211_mesh_power_mode pm = nla_get_u32( |
@@ -3470,127 +3903,33 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) | |||
3470 | params.local_pm = pm; | 3903 | params.local_pm = pm; |
3471 | } | 3904 | } |
3472 | 3905 | ||
3906 | /* Include parameters for TDLS peer (will check later) */ | ||
3907 | err = nl80211_set_station_tdls(info, ¶ms); | ||
3908 | if (err) | ||
3909 | return err; | ||
3910 | |||
3911 | params.vlan = get_vlan(info, rdev); | ||
3912 | if (IS_ERR(params.vlan)) | ||
3913 | return PTR_ERR(params.vlan); | ||
3914 | |||
3473 | switch (dev->ieee80211_ptr->iftype) { | 3915 | switch (dev->ieee80211_ptr->iftype) { |
3474 | case NL80211_IFTYPE_AP: | 3916 | case NL80211_IFTYPE_AP: |
3475 | case NL80211_IFTYPE_AP_VLAN: | 3917 | case NL80211_IFTYPE_AP_VLAN: |
3476 | case NL80211_IFTYPE_P2P_GO: | 3918 | case NL80211_IFTYPE_P2P_GO: |
3477 | /* disallow mesh-specific things */ | ||
3478 | if (params.plink_action) | ||
3479 | return -EINVAL; | ||
3480 | if (params.local_pm) | ||
3481 | return -EINVAL; | ||
3482 | |||
3483 | /* TDLS can't be set, ... */ | ||
3484 | if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) | ||
3485 | return -EINVAL; | ||
3486 | /* | ||
3487 | * ... but don't bother the driver with it. This works around | ||
3488 | * a hostapd/wpa_supplicant issue -- it always includes the | ||
3489 | * TLDS_PEER flag in the mask even for AP mode. | ||
3490 | */ | ||
3491 | params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER); | ||
3492 | |||
3493 | /* accept only the listed bits */ | ||
3494 | if (params.sta_flags_mask & | ||
3495 | ~(BIT(NL80211_STA_FLAG_AUTHORIZED) | | ||
3496 | BIT(NL80211_STA_FLAG_AUTHENTICATED) | | ||
3497 | BIT(NL80211_STA_FLAG_ASSOCIATED) | | ||
3498 | BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) | | ||
3499 | BIT(NL80211_STA_FLAG_WME) | | ||
3500 | BIT(NL80211_STA_FLAG_MFP))) | ||
3501 | return -EINVAL; | ||
3502 | |||
3503 | /* but authenticated/associated only if driver handles it */ | ||
3504 | if (!(rdev->wiphy.features & | ||
3505 | NL80211_FEATURE_FULL_AP_CLIENT_STATE) && | ||
3506 | params.sta_flags_mask & | ||
3507 | (BIT(NL80211_STA_FLAG_AUTHENTICATED) | | ||
3508 | BIT(NL80211_STA_FLAG_ASSOCIATED))) | ||
3509 | return -EINVAL; | ||
3510 | |||
3511 | /* reject other things that can't change */ | ||
3512 | if (params.supported_rates) | ||
3513 | return -EINVAL; | ||
3514 | if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) | ||
3515 | return -EINVAL; | ||
3516 | if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]) | ||
3517 | return -EINVAL; | ||
3518 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY] || | ||
3519 | info->attrs[NL80211_ATTR_VHT_CAPABILITY]) | ||
3520 | return -EINVAL; | ||
3521 | |||
3522 | /* must be last in here for error handling */ | ||
3523 | params.vlan = get_vlan(info, rdev); | ||
3524 | if (IS_ERR(params.vlan)) | ||
3525 | return PTR_ERR(params.vlan); | ||
3526 | break; | ||
3527 | case NL80211_IFTYPE_P2P_CLIENT: | 3919 | case NL80211_IFTYPE_P2P_CLIENT: |
3528 | case NL80211_IFTYPE_STATION: | 3920 | case NL80211_IFTYPE_STATION: |
3529 | /* | ||
3530 | * Don't allow userspace to change the TDLS_PEER flag, | ||
3531 | * but silently ignore attempts to change it since we | ||
3532 | * don't have state here to verify that it doesn't try | ||
3533 | * to change the flag. | ||
3534 | */ | ||
3535 | params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER); | ||
3536 | /* Include parameters for TDLS peer (driver will check) */ | ||
3537 | err = nl80211_set_station_tdls(info, ¶ms); | ||
3538 | if (err) | ||
3539 | return err; | ||
3540 | /* disallow things sta doesn't support */ | ||
3541 | if (params.plink_action) | ||
3542 | return -EINVAL; | ||
3543 | if (params.local_pm) | ||
3544 | return -EINVAL; | ||
3545 | /* reject any changes other than AUTHORIZED or WME (for TDLS) */ | ||
3546 | if (params.sta_flags_mask & ~(BIT(NL80211_STA_FLAG_AUTHORIZED) | | ||
3547 | BIT(NL80211_STA_FLAG_WME))) | ||
3548 | return -EINVAL; | ||
3549 | break; | ||
3550 | case NL80211_IFTYPE_ADHOC: | 3921 | case NL80211_IFTYPE_ADHOC: |
3551 | /* disallow things sta doesn't support */ | ||
3552 | if (params.plink_action) | ||
3553 | return -EINVAL; | ||
3554 | if (params.local_pm) | ||
3555 | return -EINVAL; | ||
3556 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY] || | ||
3557 | info->attrs[NL80211_ATTR_VHT_CAPABILITY]) | ||
3558 | return -EINVAL; | ||
3559 | /* reject any changes other than AUTHORIZED */ | ||
3560 | if (params.sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED)) | ||
3561 | return -EINVAL; | ||
3562 | break; | ||
3563 | case NL80211_IFTYPE_MESH_POINT: | 3922 | case NL80211_IFTYPE_MESH_POINT: |
3564 | /* disallow things mesh doesn't support */ | ||
3565 | if (params.vlan) | ||
3566 | return -EINVAL; | ||
3567 | if (params.supported_rates) | ||
3568 | return -EINVAL; | ||
3569 | if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) | ||
3570 | return -EINVAL; | ||
3571 | if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]) | ||
3572 | return -EINVAL; | ||
3573 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY] || | ||
3574 | info->attrs[NL80211_ATTR_VHT_CAPABILITY]) | ||
3575 | return -EINVAL; | ||
3576 | /* | ||
3577 | * No special handling for TDLS here -- the userspace | ||
3578 | * mesh code doesn't have this bug. | ||
3579 | */ | ||
3580 | if (params.sta_flags_mask & | ||
3581 | ~(BIT(NL80211_STA_FLAG_AUTHENTICATED) | | ||
3582 | BIT(NL80211_STA_FLAG_MFP) | | ||
3583 | BIT(NL80211_STA_FLAG_AUTHORIZED))) | ||
3584 | return -EINVAL; | ||
3585 | break; | 3923 | break; |
3586 | default: | 3924 | default: |
3587 | return -EOPNOTSUPP; | 3925 | err = -EOPNOTSUPP; |
3926 | goto out_put_vlan; | ||
3588 | } | 3927 | } |
3589 | 3928 | ||
3590 | /* be aware of params.vlan when changing code here */ | 3929 | /* driver will call cfg80211_check_station_change() */ |
3591 | |||
3592 | err = rdev_change_station(rdev, dev, mac_addr, ¶ms); | 3930 | err = rdev_change_station(rdev, dev, mac_addr, ¶ms); |
3593 | 3931 | ||
3932 | out_put_vlan: | ||
3594 | if (params.vlan) | 3933 | if (params.vlan) |
3595 | dev_put(params.vlan); | 3934 | dev_put(params.vlan); |
3596 | 3935 | ||
@@ -3607,6 +3946,9 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
3607 | 3946 | ||
3608 | memset(¶ms, 0, sizeof(params)); | 3947 | memset(¶ms, 0, sizeof(params)); |
3609 | 3948 | ||
3949 | if (!rdev->ops->add_station) | ||
3950 | return -EOPNOTSUPP; | ||
3951 | |||
3610 | if (!info->attrs[NL80211_ATTR_MAC]) | 3952 | if (!info->attrs[NL80211_ATTR_MAC]) |
3611 | return -EINVAL; | 3953 | return -EINVAL; |
3612 | 3954 | ||
@@ -3652,50 +3994,32 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
3652 | params.vht_capa = | 3994 | params.vht_capa = |
3653 | nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]); | 3995 | nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]); |
3654 | 3996 | ||
3655 | if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) | 3997 | if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) { |
3656 | params.plink_action = | 3998 | params.plink_action = |
3657 | nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]); | 3999 | nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]); |
4000 | if (params.plink_action >= NUM_NL80211_PLINK_ACTIONS) | ||
4001 | return -EINVAL; | ||
4002 | } | ||
3658 | 4003 | ||
3659 | if (!rdev->ops->add_station) | 4004 | err = nl80211_parse_sta_wme(info, ¶ms); |
3660 | return -EOPNOTSUPP; | 4005 | if (err) |
4006 | return err; | ||
3661 | 4007 | ||
3662 | if (parse_station_flags(info, dev->ieee80211_ptr->iftype, ¶ms)) | 4008 | if (parse_station_flags(info, dev->ieee80211_ptr->iftype, ¶ms)) |
3663 | return -EINVAL; | 4009 | return -EINVAL; |
3664 | 4010 | ||
4011 | /* When you run into this, adjust the code below for the new flag */ | ||
4012 | BUILD_BUG_ON(NL80211_STA_FLAG_MAX != 7); | ||
4013 | |||
3665 | switch (dev->ieee80211_ptr->iftype) { | 4014 | switch (dev->ieee80211_ptr->iftype) { |
3666 | case NL80211_IFTYPE_AP: | 4015 | case NL80211_IFTYPE_AP: |
3667 | case NL80211_IFTYPE_AP_VLAN: | 4016 | case NL80211_IFTYPE_AP_VLAN: |
3668 | case NL80211_IFTYPE_P2P_GO: | 4017 | case NL80211_IFTYPE_P2P_GO: |
3669 | /* parse WME attributes if sta is WME capable */ | 4018 | /* ignore WME attributes if iface/sta is not capable */ |
3670 | if ((rdev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) && | 4019 | if (!(rdev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) || |
3671 | (params.sta_flags_set & BIT(NL80211_STA_FLAG_WME)) && | 4020 | !(params.sta_flags_set & BIT(NL80211_STA_FLAG_WME))) |
3672 | info->attrs[NL80211_ATTR_STA_WME]) { | 4021 | params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD; |
3673 | struct nlattr *tb[NL80211_STA_WME_MAX + 1]; | ||
3674 | struct nlattr *nla; | ||
3675 | |||
3676 | nla = info->attrs[NL80211_ATTR_STA_WME]; | ||
3677 | err = nla_parse_nested(tb, NL80211_STA_WME_MAX, nla, | ||
3678 | nl80211_sta_wme_policy); | ||
3679 | if (err) | ||
3680 | return err; | ||
3681 | 4022 | ||
3682 | if (tb[NL80211_STA_WME_UAPSD_QUEUES]) | ||
3683 | params.uapsd_queues = | ||
3684 | nla_get_u8(tb[NL80211_STA_WME_UAPSD_QUEUES]); | ||
3685 | if (params.uapsd_queues & | ||
3686 | ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK) | ||
3687 | return -EINVAL; | ||
3688 | |||
3689 | if (tb[NL80211_STA_WME_MAX_SP]) | ||
3690 | params.max_sp = | ||
3691 | nla_get_u8(tb[NL80211_STA_WME_MAX_SP]); | ||
3692 | |||
3693 | if (params.max_sp & | ||
3694 | ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK) | ||
3695 | return -EINVAL; | ||
3696 | |||
3697 | params.sta_modify_mask |= STATION_PARAM_APPLY_UAPSD; | ||
3698 | } | ||
3699 | /* TDLS peers cannot be added */ | 4023 | /* TDLS peers cannot be added */ |
3700 | if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) | 4024 | if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) |
3701 | return -EINVAL; | 4025 | return -EINVAL; |
@@ -3716,6 +4040,9 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
3716 | return PTR_ERR(params.vlan); | 4040 | return PTR_ERR(params.vlan); |
3717 | break; | 4041 | break; |
3718 | case NL80211_IFTYPE_MESH_POINT: | 4042 | case NL80211_IFTYPE_MESH_POINT: |
4043 | /* ignore uAPSD data */ | ||
4044 | params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD; | ||
4045 | |||
3719 | /* associated is disallowed */ | 4046 | /* associated is disallowed */ |
3720 | if (params.sta_flags_mask & BIT(NL80211_STA_FLAG_ASSOCIATED)) | 4047 | if (params.sta_flags_mask & BIT(NL80211_STA_FLAG_ASSOCIATED)) |
3721 | return -EINVAL; | 4048 | return -EINVAL; |
@@ -3724,8 +4051,14 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
3724 | return -EINVAL; | 4051 | return -EINVAL; |
3725 | break; | 4052 | break; |
3726 | case NL80211_IFTYPE_STATION: | 4053 | case NL80211_IFTYPE_STATION: |
3727 | /* associated is disallowed */ | 4054 | case NL80211_IFTYPE_P2P_CLIENT: |
3728 | if (params.sta_flags_mask & BIT(NL80211_STA_FLAG_ASSOCIATED)) | 4055 | /* ignore uAPSD data */ |
4056 | params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD; | ||
4057 | |||
4058 | /* these are disallowed */ | ||
4059 | if (params.sta_flags_mask & | ||
4060 | (BIT(NL80211_STA_FLAG_ASSOCIATED) | | ||
4061 | BIT(NL80211_STA_FLAG_AUTHENTICATED))) | ||
3729 | return -EINVAL; | 4062 | return -EINVAL; |
3730 | /* Only TDLS peers can be added */ | 4063 | /* Only TDLS peers can be added */ |
3731 | if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) | 4064 | if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) |
@@ -3736,6 +4069,11 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
3736 | /* ... with external setup is supported */ | 4069 | /* ... with external setup is supported */ |
3737 | if (!(rdev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP)) | 4070 | if (!(rdev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP)) |
3738 | return -EOPNOTSUPP; | 4071 | return -EOPNOTSUPP; |
4072 | /* | ||
4073 | * Older wpa_supplicant versions always mark the TDLS peer | ||
4074 | * as authorized, but it shouldn't yet be. | ||
4075 | */ | ||
4076 | params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_AUTHORIZED); | ||
3739 | break; | 4077 | break; |
3740 | default: | 4078 | default: |
3741 | return -EOPNOTSUPP; | 4079 | return -EOPNOTSUPP; |
@@ -4280,6 +4618,7 @@ static const struct nla_policy | |||
4280 | [NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL] = { .type = NLA_U8 }, | 4618 | [NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL] = { .type = NLA_U8 }, |
4281 | [NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC] = { .type = NLA_U8 }, | 4619 | [NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC] = { .type = NLA_U8 }, |
4282 | [NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG }, | 4620 | [NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG }, |
4621 | [NL80211_MESH_SETUP_USERSPACE_MPM] = { .type = NLA_FLAG }, | ||
4283 | [NL80211_MESH_SETUP_IE] = { .type = NLA_BINARY, | 4622 | [NL80211_MESH_SETUP_IE] = { .type = NLA_BINARY, |
4284 | .len = IEEE80211_MAX_DATA_LEN }, | 4623 | .len = IEEE80211_MAX_DATA_LEN }, |
4285 | [NL80211_MESH_SETUP_USERSPACE_AMPE] = { .type = NLA_FLAG }, | 4624 | [NL80211_MESH_SETUP_USERSPACE_AMPE] = { .type = NLA_FLAG }, |
@@ -4418,6 +4757,7 @@ do { \ | |||
4418 | static int nl80211_parse_mesh_setup(struct genl_info *info, | 4757 | static int nl80211_parse_mesh_setup(struct genl_info *info, |
4419 | struct mesh_setup *setup) | 4758 | struct mesh_setup *setup) |
4420 | { | 4759 | { |
4760 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | ||
4421 | struct nlattr *tb[NL80211_MESH_SETUP_ATTR_MAX + 1]; | 4761 | struct nlattr *tb[NL80211_MESH_SETUP_ATTR_MAX + 1]; |
4422 | 4762 | ||
4423 | if (!info->attrs[NL80211_ATTR_MESH_SETUP]) | 4763 | if (!info->attrs[NL80211_ATTR_MESH_SETUP]) |
@@ -4454,8 +4794,14 @@ static int nl80211_parse_mesh_setup(struct genl_info *info, | |||
4454 | setup->ie = nla_data(ieattr); | 4794 | setup->ie = nla_data(ieattr); |
4455 | setup->ie_len = nla_len(ieattr); | 4795 | setup->ie_len = nla_len(ieattr); |
4456 | } | 4796 | } |
4797 | if (tb[NL80211_MESH_SETUP_USERSPACE_MPM] && | ||
4798 | !(rdev->wiphy.features & NL80211_FEATURE_USERSPACE_MPM)) | ||
4799 | return -EINVAL; | ||
4800 | setup->user_mpm = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_MPM]); | ||
4457 | setup->is_authenticated = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AUTH]); | 4801 | setup->is_authenticated = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AUTH]); |
4458 | setup->is_secure = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AMPE]); | 4802 | setup->is_secure = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AMPE]); |
4803 | if (setup->is_secure) | ||
4804 | setup->user_mpm = true; | ||
4459 | 4805 | ||
4460 | return 0; | 4806 | return 0; |
4461 | } | 4807 | } |
@@ -5650,14 +5996,10 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) | |||
5650 | { | 5996 | { |
5651 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 5997 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
5652 | struct net_device *dev = info->user_ptr[1]; | 5998 | struct net_device *dev = info->user_ptr[1]; |
5653 | struct cfg80211_crypto_settings crypto; | ||
5654 | struct ieee80211_channel *chan; | 5999 | struct ieee80211_channel *chan; |
5655 | const u8 *bssid, *ssid, *ie = NULL, *prev_bssid = NULL; | 6000 | struct cfg80211_assoc_request req = {}; |
5656 | int err, ssid_len, ie_len = 0; | 6001 | const u8 *bssid, *ssid; |
5657 | bool use_mfp = false; | 6002 | int err, ssid_len = 0; |
5658 | u32 flags = 0; | ||
5659 | struct ieee80211_ht_cap *ht_capa = NULL; | ||
5660 | struct ieee80211_ht_cap *ht_capa_mask = NULL; | ||
5661 | 6003 | ||
5662 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) | 6004 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) |
5663 | return -EINVAL; | 6005 | return -EINVAL; |
@@ -5685,41 +6027,58 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) | |||
5685 | ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]); | 6027 | ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]); |
5686 | 6028 | ||
5687 | if (info->attrs[NL80211_ATTR_IE]) { | 6029 | if (info->attrs[NL80211_ATTR_IE]) { |
5688 | ie = nla_data(info->attrs[NL80211_ATTR_IE]); | 6030 | req.ie = nla_data(info->attrs[NL80211_ATTR_IE]); |
5689 | ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); | 6031 | req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); |
5690 | } | 6032 | } |
5691 | 6033 | ||
5692 | if (info->attrs[NL80211_ATTR_USE_MFP]) { | 6034 | if (info->attrs[NL80211_ATTR_USE_MFP]) { |
5693 | enum nl80211_mfp mfp = | 6035 | enum nl80211_mfp mfp = |
5694 | nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]); | 6036 | nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]); |
5695 | if (mfp == NL80211_MFP_REQUIRED) | 6037 | if (mfp == NL80211_MFP_REQUIRED) |
5696 | use_mfp = true; | 6038 | req.use_mfp = true; |
5697 | else if (mfp != NL80211_MFP_NO) | 6039 | else if (mfp != NL80211_MFP_NO) |
5698 | return -EINVAL; | 6040 | return -EINVAL; |
5699 | } | 6041 | } |
5700 | 6042 | ||
5701 | if (info->attrs[NL80211_ATTR_PREV_BSSID]) | 6043 | if (info->attrs[NL80211_ATTR_PREV_BSSID]) |
5702 | prev_bssid = nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]); | 6044 | req.prev_bssid = nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]); |
5703 | 6045 | ||
5704 | if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT])) | 6046 | if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT])) |
5705 | flags |= ASSOC_REQ_DISABLE_HT; | 6047 | req.flags |= ASSOC_REQ_DISABLE_HT; |
5706 | 6048 | ||
5707 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]) | 6049 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]) |
5708 | ht_capa_mask = | 6050 | memcpy(&req.ht_capa_mask, |
5709 | nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]); | 6051 | nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]), |
6052 | sizeof(req.ht_capa_mask)); | ||
5710 | 6053 | ||
5711 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) { | 6054 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) { |
5712 | if (!ht_capa_mask) | 6055 | if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]) |
5713 | return -EINVAL; | 6056 | return -EINVAL; |
5714 | ht_capa = nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); | 6057 | memcpy(&req.ht_capa, |
6058 | nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]), | ||
6059 | sizeof(req.ht_capa)); | ||
5715 | } | 6060 | } |
5716 | 6061 | ||
5717 | err = nl80211_crypto_settings(rdev, info, &crypto, 1); | 6062 | if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_VHT])) |
6063 | req.flags |= ASSOC_REQ_DISABLE_VHT; | ||
6064 | |||
6065 | if (info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]) | ||
6066 | memcpy(&req.vht_capa_mask, | ||
6067 | nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]), | ||
6068 | sizeof(req.vht_capa_mask)); | ||
6069 | |||
6070 | if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) { | ||
6071 | if (!info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]) | ||
6072 | return -EINVAL; | ||
6073 | memcpy(&req.vht_capa, | ||
6074 | nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]), | ||
6075 | sizeof(req.vht_capa)); | ||
6076 | } | ||
6077 | |||
6078 | err = nl80211_crypto_settings(rdev, info, &req.crypto, 1); | ||
5718 | if (!err) | 6079 | if (!err) |
5719 | err = cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid, | 6080 | err = cfg80211_mlme_assoc(rdev, dev, chan, bssid, |
5720 | ssid, ssid_len, ie, ie_len, use_mfp, | 6081 | ssid, ssid_len, &req); |
5721 | &crypto, flags, ht_capa, | ||
5722 | ht_capa_mask); | ||
5723 | 6082 | ||
5724 | return err; | 6083 | return err; |
5725 | } | 6084 | } |
@@ -6299,6 +6658,24 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) | |||
6299 | sizeof(connect.ht_capa)); | 6658 | sizeof(connect.ht_capa)); |
6300 | } | 6659 | } |
6301 | 6660 | ||
6661 | if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_VHT])) | ||
6662 | connect.flags |= ASSOC_REQ_DISABLE_VHT; | ||
6663 | |||
6664 | if (info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]) | ||
6665 | memcpy(&connect.vht_capa_mask, | ||
6666 | nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]), | ||
6667 | sizeof(connect.vht_capa_mask)); | ||
6668 | |||
6669 | if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) { | ||
6670 | if (!info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]) { | ||
6671 | kfree(connkeys); | ||
6672 | return -EINVAL; | ||
6673 | } | ||
6674 | memcpy(&connect.vht_capa, | ||
6675 | nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]), | ||
6676 | sizeof(connect.vht_capa)); | ||
6677 | } | ||
6678 | |||
6302 | err = cfg80211_connect(rdev, dev, &connect, connkeys); | 6679 | err = cfg80211_connect(rdev, dev, &connect, connkeys); |
6303 | if (err) | 6680 | if (err) |
6304 | kfree(connkeys); | 6681 | kfree(connkeys); |
@@ -7072,6 +7449,9 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info) | |||
7072 | return err; | 7449 | return err; |
7073 | } | 7450 | } |
7074 | 7451 | ||
7452 | if (setup.user_mpm) | ||
7453 | cfg.auto_open_plinks = false; | ||
7454 | |||
7075 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { | 7455 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { |
7076 | err = nl80211_parse_chandef(rdev, info, &setup.chandef); | 7456 | err = nl80211_parse_chandef(rdev, info, &setup.chandef); |
7077 | if (err) | 7457 | if (err) |
@@ -7271,7 +7651,8 @@ static int nl80211_parse_wowlan_tcp(struct cfg80211_registered_device *rdev, | |||
7271 | return -EINVAL; | 7651 | return -EINVAL; |
7272 | 7652 | ||
7273 | if (nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]) > | 7653 | if (nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]) > |
7274 | rdev->wiphy.wowlan.tcp->data_interval_max) | 7654 | rdev->wiphy.wowlan.tcp->data_interval_max || |
7655 | nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]) == 0) | ||
7275 | return -EINVAL; | 7656 | return -EINVAL; |
7276 | 7657 | ||
7277 | wake_size = nla_len(tb[NL80211_WOWLAN_TCP_WAKE_PAYLOAD]); | 7658 | wake_size = nla_len(tb[NL80211_WOWLAN_TCP_WAKE_PAYLOAD]); |
@@ -7767,6 +8148,54 @@ static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info) | |||
7767 | return 0; | 8148 | return 0; |
7768 | } | 8149 | } |
7769 | 8150 | ||
8151 | static int nl80211_get_protocol_features(struct sk_buff *skb, | ||
8152 | struct genl_info *info) | ||
8153 | { | ||
8154 | void *hdr; | ||
8155 | struct sk_buff *msg; | ||
8156 | |||
8157 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
8158 | if (!msg) | ||
8159 | return -ENOMEM; | ||
8160 | |||
8161 | hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0, | ||
8162 | NL80211_CMD_GET_PROTOCOL_FEATURES); | ||
8163 | if (!hdr) | ||
8164 | goto nla_put_failure; | ||
8165 | |||
8166 | if (nla_put_u32(msg, NL80211_ATTR_PROTOCOL_FEATURES, | ||
8167 | NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP)) | ||
8168 | goto nla_put_failure; | ||
8169 | |||
8170 | genlmsg_end(msg, hdr); | ||
8171 | return genlmsg_reply(msg, info); | ||
8172 | |||
8173 | nla_put_failure: | ||
8174 | kfree_skb(msg); | ||
8175 | return -ENOBUFS; | ||
8176 | } | ||
8177 | |||
8178 | static int nl80211_update_ft_ies(struct sk_buff *skb, struct genl_info *info) | ||
8179 | { | ||
8180 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | ||
8181 | struct cfg80211_update_ft_ies_params ft_params; | ||
8182 | struct net_device *dev = info->user_ptr[1]; | ||
8183 | |||
8184 | if (!rdev->ops->update_ft_ies) | ||
8185 | return -EOPNOTSUPP; | ||
8186 | |||
8187 | if (!info->attrs[NL80211_ATTR_MDID] || | ||
8188 | !is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) | ||
8189 | return -EINVAL; | ||
8190 | |||
8191 | memset(&ft_params, 0, sizeof(ft_params)); | ||
8192 | ft_params.md = nla_get_u16(info->attrs[NL80211_ATTR_MDID]); | ||
8193 | ft_params.ie = nla_data(info->attrs[NL80211_ATTR_IE]); | ||
8194 | ft_params.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); | ||
8195 | |||
8196 | return rdev_update_ft_ies(rdev, dev, &ft_params); | ||
8197 | } | ||
8198 | |||
7770 | #define NL80211_FLAG_NEED_WIPHY 0x01 | 8199 | #define NL80211_FLAG_NEED_WIPHY 0x01 |
7771 | #define NL80211_FLAG_NEED_NETDEV 0x02 | 8200 | #define NL80211_FLAG_NEED_NETDEV 0x02 |
7772 | #define NL80211_FLAG_NEED_RTNL 0x04 | 8201 | #define NL80211_FLAG_NEED_RTNL 0x04 |
@@ -8443,6 +8872,19 @@ static struct genl_ops nl80211_ops[] = { | |||
8443 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | 8872 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | |
8444 | NL80211_FLAG_NEED_RTNL, | 8873 | NL80211_FLAG_NEED_RTNL, |
8445 | }, | 8874 | }, |
8875 | { | ||
8876 | .cmd = NL80211_CMD_GET_PROTOCOL_FEATURES, | ||
8877 | .doit = nl80211_get_protocol_features, | ||
8878 | .policy = nl80211_policy, | ||
8879 | }, | ||
8880 | { | ||
8881 | .cmd = NL80211_CMD_UPDATE_FT_IES, | ||
8882 | .doit = nl80211_update_ft_ies, | ||
8883 | .policy = nl80211_policy, | ||
8884 | .flags = GENL_ADMIN_PERM, | ||
8885 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | ||
8886 | NL80211_FLAG_NEED_RTNL, | ||
8887 | }, | ||
8446 | }; | 8888 | }; |
8447 | 8889 | ||
8448 | static struct genl_multicast_group nl80211_mlme_mcgrp = { | 8890 | static struct genl_multicast_group nl80211_mlme_mcgrp = { |
@@ -8470,7 +8912,8 @@ void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev) | |||
8470 | if (!msg) | 8912 | if (!msg) |
8471 | return; | 8913 | return; |
8472 | 8914 | ||
8473 | if (nl80211_send_wiphy(msg, 0, 0, 0, rdev) < 0) { | 8915 | if (nl80211_send_wiphy(rdev, msg, 0, 0, 0, |
8916 | false, NULL, NULL, NULL) < 0) { | ||
8474 | nlmsg_free(msg); | 8917 | nlmsg_free(msg); |
8475 | return; | 8918 | return; |
8476 | } | 8919 | } |
@@ -8794,21 +9237,31 @@ void nl80211_send_disassoc(struct cfg80211_registered_device *rdev, | |||
8794 | NL80211_CMD_DISASSOCIATE, gfp); | 9237 | NL80211_CMD_DISASSOCIATE, gfp); |
8795 | } | 9238 | } |
8796 | 9239 | ||
8797 | void nl80211_send_unprot_deauth(struct cfg80211_registered_device *rdev, | 9240 | void cfg80211_send_unprot_deauth(struct net_device *dev, const u8 *buf, |
8798 | struct net_device *netdev, const u8 *buf, | 9241 | size_t len) |
8799 | size_t len, gfp_t gfp) | ||
8800 | { | 9242 | { |
8801 | nl80211_send_mlme_event(rdev, netdev, buf, len, | 9243 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
8802 | NL80211_CMD_UNPROT_DEAUTHENTICATE, gfp); | 9244 | struct wiphy *wiphy = wdev->wiphy; |
9245 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
9246 | |||
9247 | trace_cfg80211_send_unprot_deauth(dev); | ||
9248 | nl80211_send_mlme_event(rdev, dev, buf, len, | ||
9249 | NL80211_CMD_UNPROT_DEAUTHENTICATE, GFP_ATOMIC); | ||
8803 | } | 9250 | } |
9251 | EXPORT_SYMBOL(cfg80211_send_unprot_deauth); | ||
8804 | 9252 | ||
8805 | void nl80211_send_unprot_disassoc(struct cfg80211_registered_device *rdev, | 9253 | void cfg80211_send_unprot_disassoc(struct net_device *dev, const u8 *buf, |
8806 | struct net_device *netdev, const u8 *buf, | 9254 | size_t len) |
8807 | size_t len, gfp_t gfp) | ||
8808 | { | 9255 | { |
8809 | nl80211_send_mlme_event(rdev, netdev, buf, len, | 9256 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
8810 | NL80211_CMD_UNPROT_DISASSOCIATE, gfp); | 9257 | struct wiphy *wiphy = wdev->wiphy; |
9258 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
9259 | |||
9260 | trace_cfg80211_send_unprot_disassoc(dev); | ||
9261 | nl80211_send_mlme_event(rdev, dev, buf, len, | ||
9262 | NL80211_CMD_UNPROT_DISASSOCIATE, GFP_ATOMIC); | ||
8811 | } | 9263 | } |
9264 | EXPORT_SYMBOL(cfg80211_send_unprot_disassoc); | ||
8812 | 9265 | ||
8813 | static void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev, | 9266 | static void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev, |
8814 | struct net_device *netdev, int cmd, | 9267 | struct net_device *netdev, int cmd, |
@@ -9011,14 +9464,19 @@ void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev, | |||
9011 | nlmsg_free(msg); | 9464 | nlmsg_free(msg); |
9012 | } | 9465 | } |
9013 | 9466 | ||
9014 | void nl80211_send_new_peer_candidate(struct cfg80211_registered_device *rdev, | 9467 | void cfg80211_notify_new_peer_candidate(struct net_device *dev, const u8 *addr, |
9015 | struct net_device *netdev, | 9468 | const u8* ie, u8 ie_len, gfp_t gfp) |
9016 | const u8 *macaddr, const u8* ie, u8 ie_len, | ||
9017 | gfp_t gfp) | ||
9018 | { | 9469 | { |
9470 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
9471 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | ||
9019 | struct sk_buff *msg; | 9472 | struct sk_buff *msg; |
9020 | void *hdr; | 9473 | void *hdr; |
9021 | 9474 | ||
9475 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_MESH_POINT)) | ||
9476 | return; | ||
9477 | |||
9478 | trace_cfg80211_notify_new_peer_candidate(dev, addr); | ||
9479 | |||
9022 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); | 9480 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); |
9023 | if (!msg) | 9481 | if (!msg) |
9024 | return; | 9482 | return; |
@@ -9030,8 +9488,8 @@ void nl80211_send_new_peer_candidate(struct cfg80211_registered_device *rdev, | |||
9030 | } | 9488 | } |
9031 | 9489 | ||
9032 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | 9490 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || |
9033 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || | 9491 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || |
9034 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, macaddr) || | 9492 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) || |
9035 | (ie_len && ie && | 9493 | (ie_len && ie && |
9036 | nla_put(msg, NL80211_ATTR_IE, ie_len , ie))) | 9494 | nla_put(msg, NL80211_ATTR_IE, ie_len , ie))) |
9037 | goto nla_put_failure; | 9495 | goto nla_put_failure; |
@@ -9046,6 +9504,7 @@ void nl80211_send_new_peer_candidate(struct cfg80211_registered_device *rdev, | |||
9046 | genlmsg_cancel(msg, hdr); | 9504 | genlmsg_cancel(msg, hdr); |
9047 | nlmsg_free(msg); | 9505 | nlmsg_free(msg); |
9048 | } | 9506 | } |
9507 | EXPORT_SYMBOL(cfg80211_notify_new_peer_candidate); | ||
9049 | 9508 | ||
9050 | void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev, | 9509 | void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev, |
9051 | struct net_device *netdev, const u8 *addr, | 9510 | struct net_device *netdev, const u8 *addr, |
@@ -9114,7 +9573,7 @@ void nl80211_send_beacon_hint_event(struct wiphy *wiphy, | |||
9114 | nl_freq = nla_nest_start(msg, NL80211_ATTR_FREQ_BEFORE); | 9573 | nl_freq = nla_nest_start(msg, NL80211_ATTR_FREQ_BEFORE); |
9115 | if (!nl_freq) | 9574 | if (!nl_freq) |
9116 | goto nla_put_failure; | 9575 | goto nla_put_failure; |
9117 | if (nl80211_msg_put_channel(msg, channel_before)) | 9576 | if (nl80211_msg_put_channel(msg, channel_before, false)) |
9118 | goto nla_put_failure; | 9577 | goto nla_put_failure; |
9119 | nla_nest_end(msg, nl_freq); | 9578 | nla_nest_end(msg, nl_freq); |
9120 | 9579 | ||
@@ -9122,7 +9581,7 @@ void nl80211_send_beacon_hint_event(struct wiphy *wiphy, | |||
9122 | nl_freq = nla_nest_start(msg, NL80211_ATTR_FREQ_AFTER); | 9581 | nl_freq = nla_nest_start(msg, NL80211_ATTR_FREQ_AFTER); |
9123 | if (!nl_freq) | 9582 | if (!nl_freq) |
9124 | goto nla_put_failure; | 9583 | goto nla_put_failure; |
9125 | if (nl80211_msg_put_channel(msg, channel_after)) | 9584 | if (nl80211_msg_put_channel(msg, channel_after, false)) |
9126 | goto nla_put_failure; | 9585 | goto nla_put_failure; |
9127 | nla_nest_end(msg, nl_freq); | 9586 | nla_nest_end(msg, nl_freq); |
9128 | 9587 | ||
@@ -9184,31 +9643,42 @@ static void nl80211_send_remain_on_chan_event( | |||
9184 | nlmsg_free(msg); | 9643 | nlmsg_free(msg); |
9185 | } | 9644 | } |
9186 | 9645 | ||
9187 | void nl80211_send_remain_on_channel(struct cfg80211_registered_device *rdev, | 9646 | void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie, |
9188 | struct wireless_dev *wdev, u64 cookie, | 9647 | struct ieee80211_channel *chan, |
9189 | struct ieee80211_channel *chan, | 9648 | unsigned int duration, gfp_t gfp) |
9190 | unsigned int duration, gfp_t gfp) | ||
9191 | { | 9649 | { |
9650 | struct wiphy *wiphy = wdev->wiphy; | ||
9651 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
9652 | |||
9653 | trace_cfg80211_ready_on_channel(wdev, cookie, chan, duration); | ||
9192 | nl80211_send_remain_on_chan_event(NL80211_CMD_REMAIN_ON_CHANNEL, | 9654 | nl80211_send_remain_on_chan_event(NL80211_CMD_REMAIN_ON_CHANNEL, |
9193 | rdev, wdev, cookie, chan, | 9655 | rdev, wdev, cookie, chan, |
9194 | duration, gfp); | 9656 | duration, gfp); |
9195 | } | 9657 | } |
9658 | EXPORT_SYMBOL(cfg80211_ready_on_channel); | ||
9196 | 9659 | ||
9197 | void nl80211_send_remain_on_channel_cancel( | 9660 | void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie, |
9198 | struct cfg80211_registered_device *rdev, | 9661 | struct ieee80211_channel *chan, |
9199 | struct wireless_dev *wdev, | 9662 | gfp_t gfp) |
9200 | u64 cookie, struct ieee80211_channel *chan, gfp_t gfp) | ||
9201 | { | 9663 | { |
9664 | struct wiphy *wiphy = wdev->wiphy; | ||
9665 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
9666 | |||
9667 | trace_cfg80211_ready_on_channel_expired(wdev, cookie, chan); | ||
9202 | nl80211_send_remain_on_chan_event(NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL, | 9668 | nl80211_send_remain_on_chan_event(NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL, |
9203 | rdev, wdev, cookie, chan, 0, gfp); | 9669 | rdev, wdev, cookie, chan, 0, gfp); |
9204 | } | 9670 | } |
9671 | EXPORT_SYMBOL(cfg80211_remain_on_channel_expired); | ||
9205 | 9672 | ||
9206 | void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, | 9673 | void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr, |
9207 | struct net_device *dev, const u8 *mac_addr, | 9674 | struct station_info *sinfo, gfp_t gfp) |
9208 | struct station_info *sinfo, gfp_t gfp) | ||
9209 | { | 9675 | { |
9676 | struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; | ||
9677 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
9210 | struct sk_buff *msg; | 9678 | struct sk_buff *msg; |
9211 | 9679 | ||
9680 | trace_cfg80211_new_sta(dev, mac_addr, sinfo); | ||
9681 | |||
9212 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); | 9682 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); |
9213 | if (!msg) | 9683 | if (!msg) |
9214 | return; | 9684 | return; |
@@ -9222,14 +9692,17 @@ void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, | |||
9222 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, | 9692 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, |
9223 | nl80211_mlme_mcgrp.id, gfp); | 9693 | nl80211_mlme_mcgrp.id, gfp); |
9224 | } | 9694 | } |
9695 | EXPORT_SYMBOL(cfg80211_new_sta); | ||
9225 | 9696 | ||
9226 | void nl80211_send_sta_del_event(struct cfg80211_registered_device *rdev, | 9697 | void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp) |
9227 | struct net_device *dev, const u8 *mac_addr, | ||
9228 | gfp_t gfp) | ||
9229 | { | 9698 | { |
9699 | struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; | ||
9700 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
9230 | struct sk_buff *msg; | 9701 | struct sk_buff *msg; |
9231 | void *hdr; | 9702 | void *hdr; |
9232 | 9703 | ||
9704 | trace_cfg80211_del_sta(dev, mac_addr); | ||
9705 | |||
9233 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); | 9706 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); |
9234 | if (!msg) | 9707 | if (!msg) |
9235 | return; | 9708 | return; |
@@ -9254,12 +9727,14 @@ void nl80211_send_sta_del_event(struct cfg80211_registered_device *rdev, | |||
9254 | genlmsg_cancel(msg, hdr); | 9727 | genlmsg_cancel(msg, hdr); |
9255 | nlmsg_free(msg); | 9728 | nlmsg_free(msg); |
9256 | } | 9729 | } |
9730 | EXPORT_SYMBOL(cfg80211_del_sta); | ||
9257 | 9731 | ||
9258 | void nl80211_send_conn_failed_event(struct cfg80211_registered_device *rdev, | 9732 | void cfg80211_conn_failed(struct net_device *dev, const u8 *mac_addr, |
9259 | struct net_device *dev, const u8 *mac_addr, | 9733 | enum nl80211_connect_failed_reason reason, |
9260 | enum nl80211_connect_failed_reason reason, | 9734 | gfp_t gfp) |
9261 | gfp_t gfp) | ||
9262 | { | 9735 | { |
9736 | struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; | ||
9737 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
9263 | struct sk_buff *msg; | 9738 | struct sk_buff *msg; |
9264 | void *hdr; | 9739 | void *hdr; |
9265 | 9740 | ||
@@ -9288,6 +9763,7 @@ void nl80211_send_conn_failed_event(struct cfg80211_registered_device *rdev, | |||
9288 | genlmsg_cancel(msg, hdr); | 9763 | genlmsg_cancel(msg, hdr); |
9289 | nlmsg_free(msg); | 9764 | nlmsg_free(msg); |
9290 | } | 9765 | } |
9766 | EXPORT_SYMBOL(cfg80211_conn_failed); | ||
9291 | 9767 | ||
9292 | static bool __nl80211_unexpected_frame(struct net_device *dev, u8 cmd, | 9768 | static bool __nl80211_unexpected_frame(struct net_device *dev, u8 cmd, |
9293 | const u8 *addr, gfp_t gfp) | 9769 | const u8 *addr, gfp_t gfp) |
@@ -9332,19 +9808,47 @@ static bool __nl80211_unexpected_frame(struct net_device *dev, u8 cmd, | |||
9332 | return true; | 9808 | return true; |
9333 | } | 9809 | } |
9334 | 9810 | ||
9335 | bool nl80211_unexpected_frame(struct net_device *dev, const u8 *addr, gfp_t gfp) | 9811 | bool cfg80211_rx_spurious_frame(struct net_device *dev, |
9812 | const u8 *addr, gfp_t gfp) | ||
9336 | { | 9813 | { |
9337 | return __nl80211_unexpected_frame(dev, NL80211_CMD_UNEXPECTED_FRAME, | 9814 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
9338 | addr, gfp); | 9815 | bool ret; |
9816 | |||
9817 | trace_cfg80211_rx_spurious_frame(dev, addr); | ||
9818 | |||
9819 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && | ||
9820 | wdev->iftype != NL80211_IFTYPE_P2P_GO)) { | ||
9821 | trace_cfg80211_return_bool(false); | ||
9822 | return false; | ||
9823 | } | ||
9824 | ret = __nl80211_unexpected_frame(dev, NL80211_CMD_UNEXPECTED_FRAME, | ||
9825 | addr, gfp); | ||
9826 | trace_cfg80211_return_bool(ret); | ||
9827 | return ret; | ||
9339 | } | 9828 | } |
9829 | EXPORT_SYMBOL(cfg80211_rx_spurious_frame); | ||
9340 | 9830 | ||
9341 | bool nl80211_unexpected_4addr_frame(struct net_device *dev, | 9831 | bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev, |
9342 | const u8 *addr, gfp_t gfp) | 9832 | const u8 *addr, gfp_t gfp) |
9343 | { | 9833 | { |
9344 | return __nl80211_unexpected_frame(dev, | 9834 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
9345 | NL80211_CMD_UNEXPECTED_4ADDR_FRAME, | 9835 | bool ret; |
9346 | addr, gfp); | 9836 | |
9837 | trace_cfg80211_rx_unexpected_4addr_frame(dev, addr); | ||
9838 | |||
9839 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && | ||
9840 | wdev->iftype != NL80211_IFTYPE_P2P_GO && | ||
9841 | wdev->iftype != NL80211_IFTYPE_AP_VLAN)) { | ||
9842 | trace_cfg80211_return_bool(false); | ||
9843 | return false; | ||
9844 | } | ||
9845 | ret = __nl80211_unexpected_frame(dev, | ||
9846 | NL80211_CMD_UNEXPECTED_4ADDR_FRAME, | ||
9847 | addr, gfp); | ||
9848 | trace_cfg80211_return_bool(ret); | ||
9849 | return ret; | ||
9347 | } | 9850 | } |
9851 | EXPORT_SYMBOL(cfg80211_rx_unexpected_4addr_frame); | ||
9348 | 9852 | ||
9349 | int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, | 9853 | int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, |
9350 | struct wireless_dev *wdev, u32 nlportid, | 9854 | struct wireless_dev *wdev, u32 nlportid, |
@@ -9384,15 +9888,17 @@ int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, | |||
9384 | return -ENOBUFS; | 9888 | return -ENOBUFS; |
9385 | } | 9889 | } |
9386 | 9890 | ||
9387 | void nl80211_send_mgmt_tx_status(struct cfg80211_registered_device *rdev, | 9891 | void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie, |
9388 | struct wireless_dev *wdev, u64 cookie, | 9892 | const u8 *buf, size_t len, bool ack, gfp_t gfp) |
9389 | const u8 *buf, size_t len, bool ack, | ||
9390 | gfp_t gfp) | ||
9391 | { | 9893 | { |
9894 | struct wiphy *wiphy = wdev->wiphy; | ||
9895 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
9392 | struct net_device *netdev = wdev->netdev; | 9896 | struct net_device *netdev = wdev->netdev; |
9393 | struct sk_buff *msg; | 9897 | struct sk_buff *msg; |
9394 | void *hdr; | 9898 | void *hdr; |
9395 | 9899 | ||
9900 | trace_cfg80211_mgmt_tx_status(wdev, cookie, ack); | ||
9901 | |||
9396 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); | 9902 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); |
9397 | if (!msg) | 9903 | if (!msg) |
9398 | return; | 9904 | return; |
@@ -9420,17 +9926,21 @@ void nl80211_send_mgmt_tx_status(struct cfg80211_registered_device *rdev, | |||
9420 | genlmsg_cancel(msg, hdr); | 9926 | genlmsg_cancel(msg, hdr); |
9421 | nlmsg_free(msg); | 9927 | nlmsg_free(msg); |
9422 | } | 9928 | } |
9929 | EXPORT_SYMBOL(cfg80211_mgmt_tx_status); | ||
9423 | 9930 | ||
9424 | void | 9931 | void cfg80211_cqm_rssi_notify(struct net_device *dev, |
9425 | nl80211_send_cqm_rssi_notify(struct cfg80211_registered_device *rdev, | 9932 | enum nl80211_cqm_rssi_threshold_event rssi_event, |
9426 | struct net_device *netdev, | 9933 | gfp_t gfp) |
9427 | enum nl80211_cqm_rssi_threshold_event rssi_event, | ||
9428 | gfp_t gfp) | ||
9429 | { | 9934 | { |
9935 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
9936 | struct wiphy *wiphy = wdev->wiphy; | ||
9937 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
9430 | struct sk_buff *msg; | 9938 | struct sk_buff *msg; |
9431 | struct nlattr *pinfoattr; | 9939 | struct nlattr *pinfoattr; |
9432 | void *hdr; | 9940 | void *hdr; |
9433 | 9941 | ||
9942 | trace_cfg80211_cqm_rssi_notify(dev, rssi_event); | ||
9943 | |||
9434 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); | 9944 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); |
9435 | if (!msg) | 9945 | if (!msg) |
9436 | return; | 9946 | return; |
@@ -9442,7 +9952,7 @@ nl80211_send_cqm_rssi_notify(struct cfg80211_registered_device *rdev, | |||
9442 | } | 9952 | } |
9443 | 9953 | ||
9444 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | 9954 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || |
9445 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex)) | 9955 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex)) |
9446 | goto nla_put_failure; | 9956 | goto nla_put_failure; |
9447 | 9957 | ||
9448 | pinfoattr = nla_nest_start(msg, NL80211_ATTR_CQM); | 9958 | pinfoattr = nla_nest_start(msg, NL80211_ATTR_CQM); |
@@ -9465,10 +9975,11 @@ nl80211_send_cqm_rssi_notify(struct cfg80211_registered_device *rdev, | |||
9465 | genlmsg_cancel(msg, hdr); | 9975 | genlmsg_cancel(msg, hdr); |
9466 | nlmsg_free(msg); | 9976 | nlmsg_free(msg); |
9467 | } | 9977 | } |
9978 | EXPORT_SYMBOL(cfg80211_cqm_rssi_notify); | ||
9468 | 9979 | ||
9469 | void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev, | 9980 | static void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev, |
9470 | struct net_device *netdev, const u8 *bssid, | 9981 | struct net_device *netdev, const u8 *bssid, |
9471 | const u8 *replay_ctr, gfp_t gfp) | 9982 | const u8 *replay_ctr, gfp_t gfp) |
9472 | { | 9983 | { |
9473 | struct sk_buff *msg; | 9984 | struct sk_buff *msg; |
9474 | struct nlattr *rekey_attr; | 9985 | struct nlattr *rekey_attr; |
@@ -9510,9 +10021,22 @@ void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev, | |||
9510 | nlmsg_free(msg); | 10021 | nlmsg_free(msg); |
9511 | } | 10022 | } |
9512 | 10023 | ||
9513 | void nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev, | 10024 | void cfg80211_gtk_rekey_notify(struct net_device *dev, const u8 *bssid, |
9514 | struct net_device *netdev, int index, | 10025 | const u8 *replay_ctr, gfp_t gfp) |
9515 | const u8 *bssid, bool preauth, gfp_t gfp) | 10026 | { |
10027 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
10028 | struct wiphy *wiphy = wdev->wiphy; | ||
10029 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
10030 | |||
10031 | trace_cfg80211_gtk_rekey_notify(dev, bssid); | ||
10032 | nl80211_gtk_rekey_notify(rdev, dev, bssid, replay_ctr, gfp); | ||
10033 | } | ||
10034 | EXPORT_SYMBOL(cfg80211_gtk_rekey_notify); | ||
10035 | |||
10036 | static void | ||
10037 | nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev, | ||
10038 | struct net_device *netdev, int index, | ||
10039 | const u8 *bssid, bool preauth, gfp_t gfp) | ||
9516 | { | 10040 | { |
9517 | struct sk_buff *msg; | 10041 | struct sk_buff *msg; |
9518 | struct nlattr *attr; | 10042 | struct nlattr *attr; |
@@ -9555,9 +10079,22 @@ void nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev, | |||
9555 | nlmsg_free(msg); | 10079 | nlmsg_free(msg); |
9556 | } | 10080 | } |
9557 | 10081 | ||
9558 | void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev, | 10082 | void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index, |
9559 | struct net_device *netdev, | 10083 | const u8 *bssid, bool preauth, gfp_t gfp) |
9560 | struct cfg80211_chan_def *chandef, gfp_t gfp) | 10084 | { |
10085 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
10086 | struct wiphy *wiphy = wdev->wiphy; | ||
10087 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
10088 | |||
10089 | trace_cfg80211_pmksa_candidate_notify(dev, index, bssid, preauth); | ||
10090 | nl80211_pmksa_candidate_notify(rdev, dev, index, bssid, preauth, gfp); | ||
10091 | } | ||
10092 | EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify); | ||
10093 | |||
10094 | static void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev, | ||
10095 | struct net_device *netdev, | ||
10096 | struct cfg80211_chan_def *chandef, | ||
10097 | gfp_t gfp) | ||
9561 | { | 10098 | { |
9562 | struct sk_buff *msg; | 10099 | struct sk_buff *msg; |
9563 | void *hdr; | 10100 | void *hdr; |
@@ -9589,11 +10126,36 @@ void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev, | |||
9589 | nlmsg_free(msg); | 10126 | nlmsg_free(msg); |
9590 | } | 10127 | } |
9591 | 10128 | ||
9592 | void | 10129 | void cfg80211_ch_switch_notify(struct net_device *dev, |
9593 | nl80211_send_cqm_txe_notify(struct cfg80211_registered_device *rdev, | 10130 | struct cfg80211_chan_def *chandef) |
9594 | struct net_device *netdev, const u8 *peer, | ||
9595 | u32 num_packets, u32 rate, u32 intvl, gfp_t gfp) | ||
9596 | { | 10131 | { |
10132 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
10133 | struct wiphy *wiphy = wdev->wiphy; | ||
10134 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
10135 | |||
10136 | trace_cfg80211_ch_switch_notify(dev, chandef); | ||
10137 | |||
10138 | wdev_lock(wdev); | ||
10139 | |||
10140 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && | ||
10141 | wdev->iftype != NL80211_IFTYPE_P2P_GO)) | ||
10142 | goto out; | ||
10143 | |||
10144 | wdev->channel = chandef->chan; | ||
10145 | nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL); | ||
10146 | out: | ||
10147 | wdev_unlock(wdev); | ||
10148 | return; | ||
10149 | } | ||
10150 | EXPORT_SYMBOL(cfg80211_ch_switch_notify); | ||
10151 | |||
10152 | void cfg80211_cqm_txe_notify(struct net_device *dev, | ||
10153 | const u8 *peer, u32 num_packets, | ||
10154 | u32 rate, u32 intvl, gfp_t gfp) | ||
10155 | { | ||
10156 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
10157 | struct wiphy *wiphy = wdev->wiphy; | ||
10158 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
9597 | struct sk_buff *msg; | 10159 | struct sk_buff *msg; |
9598 | struct nlattr *pinfoattr; | 10160 | struct nlattr *pinfoattr; |
9599 | void *hdr; | 10161 | void *hdr; |
@@ -9609,7 +10171,7 @@ nl80211_send_cqm_txe_notify(struct cfg80211_registered_device *rdev, | |||
9609 | } | 10171 | } |
9610 | 10172 | ||
9611 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | 10173 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || |
9612 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || | 10174 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || |
9613 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer)) | 10175 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer)) |
9614 | goto nla_put_failure; | 10176 | goto nla_put_failure; |
9615 | 10177 | ||
@@ -9638,6 +10200,7 @@ nl80211_send_cqm_txe_notify(struct cfg80211_registered_device *rdev, | |||
9638 | genlmsg_cancel(msg, hdr); | 10200 | genlmsg_cancel(msg, hdr); |
9639 | nlmsg_free(msg); | 10201 | nlmsg_free(msg); |
9640 | } | 10202 | } |
10203 | EXPORT_SYMBOL(cfg80211_cqm_txe_notify); | ||
9641 | 10204 | ||
9642 | void | 10205 | void |
9643 | nl80211_radar_notify(struct cfg80211_registered_device *rdev, | 10206 | nl80211_radar_notify(struct cfg80211_registered_device *rdev, |
@@ -9690,15 +10253,18 @@ nl80211_radar_notify(struct cfg80211_registered_device *rdev, | |||
9690 | nlmsg_free(msg); | 10253 | nlmsg_free(msg); |
9691 | } | 10254 | } |
9692 | 10255 | ||
9693 | void | 10256 | void cfg80211_cqm_pktloss_notify(struct net_device *dev, |
9694 | nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev, | 10257 | const u8 *peer, u32 num_packets, gfp_t gfp) |
9695 | struct net_device *netdev, const u8 *peer, | ||
9696 | u32 num_packets, gfp_t gfp) | ||
9697 | { | 10258 | { |
10259 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
10260 | struct wiphy *wiphy = wdev->wiphy; | ||
10261 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
9698 | struct sk_buff *msg; | 10262 | struct sk_buff *msg; |
9699 | struct nlattr *pinfoattr; | 10263 | struct nlattr *pinfoattr; |
9700 | void *hdr; | 10264 | void *hdr; |
9701 | 10265 | ||
10266 | trace_cfg80211_cqm_pktloss_notify(dev, peer, num_packets); | ||
10267 | |||
9702 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); | 10268 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); |
9703 | if (!msg) | 10269 | if (!msg) |
9704 | return; | 10270 | return; |
@@ -9710,7 +10276,7 @@ nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev, | |||
9710 | } | 10276 | } |
9711 | 10277 | ||
9712 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | 10278 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || |
9713 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || | 10279 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || |
9714 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer)) | 10280 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer)) |
9715 | goto nla_put_failure; | 10281 | goto nla_put_failure; |
9716 | 10282 | ||
@@ -9733,6 +10299,7 @@ nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev, | |||
9733 | genlmsg_cancel(msg, hdr); | 10299 | genlmsg_cancel(msg, hdr); |
9734 | nlmsg_free(msg); | 10300 | nlmsg_free(msg); |
9735 | } | 10301 | } |
10302 | EXPORT_SYMBOL(cfg80211_cqm_pktloss_notify); | ||
9736 | 10303 | ||
9737 | void cfg80211_probe_status(struct net_device *dev, const u8 *addr, | 10304 | void cfg80211_probe_status(struct net_device *dev, const u8 *addr, |
9738 | u64 cookie, bool acked, gfp_t gfp) | 10305 | u64 cookie, bool acked, gfp_t gfp) |
@@ -10019,6 +10586,50 @@ static struct notifier_block nl80211_netlink_notifier = { | |||
10019 | .notifier_call = nl80211_netlink_notify, | 10586 | .notifier_call = nl80211_netlink_notify, |
10020 | }; | 10587 | }; |
10021 | 10588 | ||
10589 | void cfg80211_ft_event(struct net_device *netdev, | ||
10590 | struct cfg80211_ft_event_params *ft_event) | ||
10591 | { | ||
10592 | struct wiphy *wiphy = netdev->ieee80211_ptr->wiphy; | ||
10593 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
10594 | struct sk_buff *msg; | ||
10595 | void *hdr; | ||
10596 | int err; | ||
10597 | |||
10598 | trace_cfg80211_ft_event(wiphy, netdev, ft_event); | ||
10599 | |||
10600 | if (!ft_event->target_ap) | ||
10601 | return; | ||
10602 | |||
10603 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
10604 | if (!msg) | ||
10605 | return; | ||
10606 | |||
10607 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FT_EVENT); | ||
10608 | if (!hdr) { | ||
10609 | nlmsg_free(msg); | ||
10610 | return; | ||
10611 | } | ||
10612 | |||
10613 | nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); | ||
10614 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); | ||
10615 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, ft_event->target_ap); | ||
10616 | if (ft_event->ies) | ||
10617 | nla_put(msg, NL80211_ATTR_IE, ft_event->ies_len, ft_event->ies); | ||
10618 | if (ft_event->ric_ies) | ||
10619 | nla_put(msg, NL80211_ATTR_IE_RIC, ft_event->ric_ies_len, | ||
10620 | ft_event->ric_ies); | ||
10621 | |||
10622 | err = genlmsg_end(msg, hdr); | ||
10623 | if (err < 0) { | ||
10624 | nlmsg_free(msg); | ||
10625 | return; | ||
10626 | } | ||
10627 | |||
10628 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, | ||
10629 | nl80211_mlme_mcgrp.id, GFP_KERNEL); | ||
10630 | } | ||
10631 | EXPORT_SYMBOL(cfg80211_ft_event); | ||
10632 | |||
10022 | /* initialisation/exit functions */ | 10633 | /* initialisation/exit functions */ |
10023 | 10634 | ||
10024 | int nl80211_init(void) | 10635 | int nl80211_init(void) |
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index b061da4919e1..a4073e808c13 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h | |||
@@ -29,12 +29,6 @@ void nl80211_send_deauth(struct cfg80211_registered_device *rdev, | |||
29 | void nl80211_send_disassoc(struct cfg80211_registered_device *rdev, | 29 | void nl80211_send_disassoc(struct cfg80211_registered_device *rdev, |
30 | struct net_device *netdev, | 30 | struct net_device *netdev, |
31 | const u8 *buf, size_t len, gfp_t gfp); | 31 | const u8 *buf, size_t len, gfp_t gfp); |
32 | void nl80211_send_unprot_deauth(struct cfg80211_registered_device *rdev, | ||
33 | struct net_device *netdev, | ||
34 | const u8 *buf, size_t len, gfp_t gfp); | ||
35 | void nl80211_send_unprot_disassoc(struct cfg80211_registered_device *rdev, | ||
36 | struct net_device *netdev, | ||
37 | const u8 *buf, size_t len, gfp_t gfp); | ||
38 | void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev, | 32 | void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev, |
39 | struct net_device *netdev, | 33 | struct net_device *netdev, |
40 | const u8 *addr, gfp_t gfp); | 34 | const u8 *addr, gfp_t gfp); |
@@ -54,10 +48,6 @@ void nl80211_send_disconnected(struct cfg80211_registered_device *rdev, | |||
54 | struct net_device *netdev, u16 reason, | 48 | struct net_device *netdev, u16 reason, |
55 | const u8 *ie, size_t ie_len, bool from_ap); | 49 | const u8 *ie, size_t ie_len, bool from_ap); |
56 | 50 | ||
57 | void nl80211_send_new_peer_candidate(struct cfg80211_registered_device *rdev, | ||
58 | struct net_device *netdev, | ||
59 | const u8 *macaddr, const u8* ie, u8 ie_len, | ||
60 | gfp_t gfp); | ||
61 | void | 51 | void |
62 | nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev, | 52 | nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev, |
63 | struct net_device *netdev, const u8 *addr, | 53 | struct net_device *netdev, const u8 *addr, |
@@ -73,41 +63,10 @@ void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev, | |||
73 | struct net_device *netdev, const u8 *bssid, | 63 | struct net_device *netdev, const u8 *bssid, |
74 | gfp_t gfp); | 64 | gfp_t gfp); |
75 | 65 | ||
76 | void nl80211_send_remain_on_channel(struct cfg80211_registered_device *rdev, | ||
77 | struct wireless_dev *wdev, u64 cookie, | ||
78 | struct ieee80211_channel *chan, | ||
79 | unsigned int duration, gfp_t gfp); | ||
80 | void nl80211_send_remain_on_channel_cancel( | ||
81 | struct cfg80211_registered_device *rdev, | ||
82 | struct wireless_dev *wdev, | ||
83 | u64 cookie, struct ieee80211_channel *chan, gfp_t gfp); | ||
84 | |||
85 | void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, | ||
86 | struct net_device *dev, const u8 *mac_addr, | ||
87 | struct station_info *sinfo, gfp_t gfp); | ||
88 | void nl80211_send_sta_del_event(struct cfg80211_registered_device *rdev, | ||
89 | struct net_device *dev, const u8 *mac_addr, | ||
90 | gfp_t gfp); | ||
91 | |||
92 | void nl80211_send_conn_failed_event(struct cfg80211_registered_device *rdev, | ||
93 | struct net_device *dev, const u8 *mac_addr, | ||
94 | enum nl80211_connect_failed_reason reason, | ||
95 | gfp_t gfp); | ||
96 | |||
97 | int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, | 66 | int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, |
98 | struct wireless_dev *wdev, u32 nlpid, | 67 | struct wireless_dev *wdev, u32 nlpid, |
99 | int freq, int sig_dbm, | 68 | int freq, int sig_dbm, |
100 | const u8 *buf, size_t len, gfp_t gfp); | 69 | const u8 *buf, size_t len, gfp_t gfp); |
101 | void nl80211_send_mgmt_tx_status(struct cfg80211_registered_device *rdev, | ||
102 | struct wireless_dev *wdev, u64 cookie, | ||
103 | const u8 *buf, size_t len, bool ack, | ||
104 | gfp_t gfp); | ||
105 | |||
106 | void | ||
107 | nl80211_send_cqm_rssi_notify(struct cfg80211_registered_device *rdev, | ||
108 | struct net_device *netdev, | ||
109 | enum nl80211_cqm_rssi_threshold_event rssi_event, | ||
110 | gfp_t gfp); | ||
111 | 70 | ||
112 | void | 71 | void |
113 | nl80211_radar_notify(struct cfg80211_registered_device *rdev, | 72 | nl80211_radar_notify(struct cfg80211_registered_device *rdev, |
@@ -115,31 +74,4 @@ nl80211_radar_notify(struct cfg80211_registered_device *rdev, | |||
115 | enum nl80211_radar_event event, | 74 | enum nl80211_radar_event event, |
116 | struct net_device *netdev, gfp_t gfp); | 75 | struct net_device *netdev, gfp_t gfp); |
117 | 76 | ||
118 | void | ||
119 | nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev, | ||
120 | struct net_device *netdev, const u8 *peer, | ||
121 | u32 num_packets, gfp_t gfp); | ||
122 | |||
123 | void | ||
124 | nl80211_send_cqm_txe_notify(struct cfg80211_registered_device *rdev, | ||
125 | struct net_device *netdev, const u8 *peer, | ||
126 | u32 num_packets, u32 rate, u32 intvl, gfp_t gfp); | ||
127 | |||
128 | void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev, | ||
129 | struct net_device *netdev, const u8 *bssid, | ||
130 | const u8 *replay_ctr, gfp_t gfp); | ||
131 | |||
132 | void nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev, | ||
133 | struct net_device *netdev, int index, | ||
134 | const u8 *bssid, bool preauth, gfp_t gfp); | ||
135 | |||
136 | void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev, | ||
137 | struct net_device *dev, | ||
138 | struct cfg80211_chan_def *chandef, gfp_t gfp); | ||
139 | |||
140 | bool nl80211_unexpected_frame(struct net_device *dev, | ||
141 | const u8 *addr, gfp_t gfp); | ||
142 | bool nl80211_unexpected_4addr_frame(struct net_device *dev, | ||
143 | const u8 *addr, gfp_t gfp); | ||
144 | |||
145 | #endif /* __NET_WIRELESS_NL80211_H */ | 77 | #endif /* __NET_WIRELESS_NL80211_H */ |
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h index 422d38291d66..d77e1c1d3a0e 100644 --- a/net/wireless/rdev-ops.h +++ b/net/wireless/rdev-ops.h | |||
@@ -6,11 +6,12 @@ | |||
6 | #include "core.h" | 6 | #include "core.h" |
7 | #include "trace.h" | 7 | #include "trace.h" |
8 | 8 | ||
9 | static inline int rdev_suspend(struct cfg80211_registered_device *rdev) | 9 | static inline int rdev_suspend(struct cfg80211_registered_device *rdev, |
10 | struct cfg80211_wowlan *wowlan) | ||
10 | { | 11 | { |
11 | int ret; | 12 | int ret; |
12 | trace_rdev_suspend(&rdev->wiphy, rdev->wowlan); | 13 | trace_rdev_suspend(&rdev->wiphy, wowlan); |
13 | ret = rdev->ops->suspend(&rdev->wiphy, rdev->wowlan); | 14 | ret = rdev->ops->suspend(&rdev->wiphy, wowlan); |
14 | trace_rdev_return_int(&rdev->wiphy, ret); | 15 | trace_rdev_return_int(&rdev->wiphy, ret); |
15 | return ret; | 16 | return ret; |
16 | } | 17 | } |
@@ -887,4 +888,17 @@ static inline int rdev_set_mac_acl(struct cfg80211_registered_device *rdev, | |||
887 | trace_rdev_return_int(&rdev->wiphy, ret); | 888 | trace_rdev_return_int(&rdev->wiphy, ret); |
888 | return ret; | 889 | return ret; |
889 | } | 890 | } |
891 | |||
892 | static inline int rdev_update_ft_ies(struct cfg80211_registered_device *rdev, | ||
893 | struct net_device *dev, | ||
894 | struct cfg80211_update_ft_ies_params *ftie) | ||
895 | { | ||
896 | int ret; | ||
897 | |||
898 | trace_rdev_update_ft_ies(&rdev->wiphy, dev, ftie); | ||
899 | ret = rdev->ops->update_ft_ies(&rdev->wiphy, dev, ftie); | ||
900 | trace_rdev_return_int(&rdev->wiphy, ret); | ||
901 | return ret; | ||
902 | } | ||
903 | |||
890 | #endif /* __CFG80211_RDEV_OPS */ | 904 | #endif /* __CFG80211_RDEV_OPS */ |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 98532c00242d..e6df52dc8c69 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -184,14 +184,14 @@ static const struct ieee80211_regdomain world_regdom = { | |||
184 | NL80211_RRF_NO_IBSS | | 184 | NL80211_RRF_NO_IBSS | |
185 | NL80211_RRF_NO_OFDM), | 185 | NL80211_RRF_NO_OFDM), |
186 | /* IEEE 802.11a, channel 36..48 */ | 186 | /* IEEE 802.11a, channel 36..48 */ |
187 | REG_RULE(5180-10, 5240+10, 40, 6, 20, | 187 | REG_RULE(5180-10, 5240+10, 80, 6, 20, |
188 | NL80211_RRF_PASSIVE_SCAN | | 188 | NL80211_RRF_PASSIVE_SCAN | |
189 | NL80211_RRF_NO_IBSS), | 189 | NL80211_RRF_NO_IBSS), |
190 | 190 | ||
191 | /* NB: 5260 MHz - 5700 MHz requies DFS */ | 191 | /* NB: 5260 MHz - 5700 MHz requires DFS */ |
192 | 192 | ||
193 | /* IEEE 802.11a, channel 149..165 */ | 193 | /* IEEE 802.11a, channel 149..165 */ |
194 | REG_RULE(5745-10, 5825+10, 40, 6, 20, | 194 | REG_RULE(5745-10, 5825+10, 80, 6, 20, |
195 | NL80211_RRF_PASSIVE_SCAN | | 195 | NL80211_RRF_PASSIVE_SCAN | |
196 | NL80211_RRF_NO_IBSS), | 196 | NL80211_RRF_NO_IBSS), |
197 | 197 | ||
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index f432bd3755b1..bad4c4b5e4eb 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
@@ -159,7 +159,7 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev) | |||
159 | { | 159 | { |
160 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | 160 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); |
161 | struct cfg80211_connect_params *params; | 161 | struct cfg80211_connect_params *params; |
162 | const u8 *prev_bssid = NULL; | 162 | struct cfg80211_assoc_request req = {}; |
163 | int err; | 163 | int err; |
164 | 164 | ||
165 | ASSERT_WDEV_LOCK(wdev); | 165 | ASSERT_WDEV_LOCK(wdev); |
@@ -186,16 +186,20 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev) | |||
186 | BUG_ON(!rdev->ops->assoc); | 186 | BUG_ON(!rdev->ops->assoc); |
187 | wdev->conn->state = CFG80211_CONN_ASSOCIATING; | 187 | wdev->conn->state = CFG80211_CONN_ASSOCIATING; |
188 | if (wdev->conn->prev_bssid_valid) | 188 | if (wdev->conn->prev_bssid_valid) |
189 | prev_bssid = wdev->conn->prev_bssid; | 189 | req.prev_bssid = wdev->conn->prev_bssid; |
190 | err = __cfg80211_mlme_assoc(rdev, wdev->netdev, | 190 | req.ie = params->ie; |
191 | params->channel, params->bssid, | 191 | req.ie_len = params->ie_len; |
192 | prev_bssid, | 192 | req.use_mfp = params->mfp != NL80211_MFP_NO; |
193 | params->ssid, params->ssid_len, | 193 | req.crypto = params->crypto; |
194 | params->ie, params->ie_len, | 194 | req.flags = params->flags; |
195 | params->mfp != NL80211_MFP_NO, | 195 | req.ht_capa = params->ht_capa; |
196 | ¶ms->crypto, | 196 | req.ht_capa_mask = params->ht_capa_mask; |
197 | params->flags, ¶ms->ht_capa, | 197 | req.vht_capa = params->vht_capa; |
198 | ¶ms->ht_capa_mask); | 198 | req.vht_capa_mask = params->vht_capa_mask; |
199 | |||
200 | err = __cfg80211_mlme_assoc(rdev, wdev->netdev, params->channel, | ||
201 | params->bssid, params->ssid, | ||
202 | params->ssid_len, &req); | ||
199 | if (err) | 203 | if (err) |
200 | __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, | 204 | __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, |
201 | NULL, 0, | 205 | NULL, 0, |
diff --git a/net/wireless/sysfs.c b/net/wireless/sysfs.c index 238ee49b3868..8f28b9f798d8 100644 --- a/net/wireless/sysfs.c +++ b/net/wireless/sysfs.c | |||
@@ -83,6 +83,14 @@ static int wiphy_uevent(struct device *dev, struct kobj_uevent_env *env) | |||
83 | return 0; | 83 | return 0; |
84 | } | 84 | } |
85 | 85 | ||
86 | static void cfg80211_leave_all(struct cfg80211_registered_device *rdev) | ||
87 | { | ||
88 | struct wireless_dev *wdev; | ||
89 | |||
90 | list_for_each_entry(wdev, &rdev->wdev_list, list) | ||
91 | cfg80211_leave(rdev, wdev); | ||
92 | } | ||
93 | |||
86 | static int wiphy_suspend(struct device *dev, pm_message_t state) | 94 | static int wiphy_suspend(struct device *dev, pm_message_t state) |
87 | { | 95 | { |
88 | struct cfg80211_registered_device *rdev = dev_to_rdev(dev); | 96 | struct cfg80211_registered_device *rdev = dev_to_rdev(dev); |
@@ -90,12 +98,19 @@ static int wiphy_suspend(struct device *dev, pm_message_t state) | |||
90 | 98 | ||
91 | rdev->suspend_at = get_seconds(); | 99 | rdev->suspend_at = get_seconds(); |
92 | 100 | ||
93 | if (rdev->ops->suspend) { | 101 | rtnl_lock(); |
94 | rtnl_lock(); | 102 | if (rdev->wiphy.registered) { |
95 | if (rdev->wiphy.registered) | 103 | if (!rdev->wowlan) |
96 | ret = rdev_suspend(rdev); | 104 | cfg80211_leave_all(rdev); |
97 | rtnl_unlock(); | 105 | if (rdev->ops->suspend) |
106 | ret = rdev_suspend(rdev, rdev->wowlan); | ||
107 | if (ret == 1) { | ||
108 | /* Driver refuse to configure wowlan */ | ||
109 | cfg80211_leave_all(rdev); | ||
110 | ret = rdev_suspend(rdev, NULL); | ||
111 | } | ||
98 | } | 112 | } |
113 | rtnl_unlock(); | ||
99 | 114 | ||
100 | return ret; | 115 | return ret; |
101 | } | 116 | } |
diff --git a/net/wireless/trace.h b/net/wireless/trace.h index b7a531380e19..ccadef2106ac 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h | |||
@@ -1785,6 +1785,26 @@ TRACE_EVENT(rdev_set_mac_acl, | |||
1785 | WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->acl_policy) | 1785 | WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->acl_policy) |
1786 | ); | 1786 | ); |
1787 | 1787 | ||
1788 | TRACE_EVENT(rdev_update_ft_ies, | ||
1789 | TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, | ||
1790 | struct cfg80211_update_ft_ies_params *ftie), | ||
1791 | TP_ARGS(wiphy, netdev, ftie), | ||
1792 | TP_STRUCT__entry( | ||
1793 | WIPHY_ENTRY | ||
1794 | NETDEV_ENTRY | ||
1795 | __field(u16, md) | ||
1796 | __dynamic_array(u8, ie, ftie->ie_len) | ||
1797 | ), | ||
1798 | TP_fast_assign( | ||
1799 | WIPHY_ASSIGN; | ||
1800 | NETDEV_ASSIGN; | ||
1801 | __entry->md = ftie->md; | ||
1802 | memcpy(__get_dynamic_array(ie), ftie->ie, ftie->ie_len); | ||
1803 | ), | ||
1804 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", md: 0x%x", | ||
1805 | WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->md) | ||
1806 | ); | ||
1807 | |||
1788 | /************************************************************* | 1808 | /************************************************************* |
1789 | * cfg80211 exported functions traces * | 1809 | * cfg80211 exported functions traces * |
1790 | *************************************************************/ | 1810 | *************************************************************/ |
@@ -2413,6 +2433,32 @@ TRACE_EVENT(cfg80211_report_wowlan_wakeup, | |||
2413 | TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT, WIPHY_PR_ARG, WDEV_PR_ARG) | 2433 | TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT, WIPHY_PR_ARG, WDEV_PR_ARG) |
2414 | ); | 2434 | ); |
2415 | 2435 | ||
2436 | TRACE_EVENT(cfg80211_ft_event, | ||
2437 | TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, | ||
2438 | struct cfg80211_ft_event_params *ft_event), | ||
2439 | TP_ARGS(wiphy, netdev, ft_event), | ||
2440 | TP_STRUCT__entry( | ||
2441 | WIPHY_ENTRY | ||
2442 | NETDEV_ENTRY | ||
2443 | __dynamic_array(u8, ies, ft_event->ies_len) | ||
2444 | MAC_ENTRY(target_ap) | ||
2445 | __dynamic_array(u8, ric_ies, ft_event->ric_ies_len) | ||
2446 | ), | ||
2447 | TP_fast_assign( | ||
2448 | WIPHY_ASSIGN; | ||
2449 | NETDEV_ASSIGN; | ||
2450 | if (ft_event->ies) | ||
2451 | memcpy(__get_dynamic_array(ies), ft_event->ies, | ||
2452 | ft_event->ies_len); | ||
2453 | MAC_ASSIGN(target_ap, ft_event->target_ap); | ||
2454 | if (ft_event->ric_ies) | ||
2455 | memcpy(__get_dynamic_array(ric_ies), ft_event->ric_ies, | ||
2456 | ft_event->ric_ies_len); | ||
2457 | ), | ||
2458 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", target_ap: " MAC_PR_FMT, | ||
2459 | WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(target_ap)) | ||
2460 | ); | ||
2461 | |||
2416 | #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */ | 2462 | #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */ |
2417 | 2463 | ||
2418 | #undef TRACE_INCLUDE_PATH | 2464 | #undef TRACE_INCLUDE_PATH |