diff options
Diffstat (limited to 'net')
31 files changed, 868 insertions, 304 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 296620d6ca0c..d15ba0d0de94 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -776,12 +776,10 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
776 | 776 | ||
777 | if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED) && | 777 | if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED) && |
778 | !test_sta_flag(sta, WLAN_STA_AUTH)) { | 778 | !test_sta_flag(sta, WLAN_STA_AUTH)) { |
779 | ret = sta_info_move_state_checked(sta, | 779 | ret = sta_info_move_state(sta, IEEE80211_STA_AUTH); |
780 | IEEE80211_STA_AUTH); | ||
781 | if (ret) | 780 | if (ret) |
782 | return ret; | 781 | return ret; |
783 | ret = sta_info_move_state_checked(sta, | 782 | ret = sta_info_move_state(sta, IEEE80211_STA_ASSOC); |
784 | IEEE80211_STA_ASSOC); | ||
785 | if (ret) | 783 | if (ret) |
786 | return ret; | 784 | return ret; |
787 | } | 785 | } |
@@ -789,11 +787,9 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
789 | 787 | ||
790 | if (mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) { | 788 | if (mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) { |
791 | if (set & BIT(NL80211_STA_FLAG_AUTHORIZED)) | 789 | if (set & BIT(NL80211_STA_FLAG_AUTHORIZED)) |
792 | ret = sta_info_move_state_checked(sta, | 790 | ret = sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED); |
793 | IEEE80211_STA_AUTHORIZED); | ||
794 | else if (test_sta_flag(sta, WLAN_STA_AUTHORIZED)) | 791 | else if (test_sta_flag(sta, WLAN_STA_AUTHORIZED)) |
795 | ret = sta_info_move_state_checked(sta, | 792 | ret = sta_info_move_state(sta, IEEE80211_STA_ASSOC); |
796 | IEEE80211_STA_ASSOC); | ||
797 | if (ret) | 793 | if (ret) |
798 | return ret; | 794 | return ret; |
799 | } | 795 | } |
@@ -805,12 +801,10 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
805 | 801 | ||
806 | if (!(set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) && | 802 | if (!(set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) && |
807 | test_sta_flag(sta, WLAN_STA_AUTH)) { | 803 | test_sta_flag(sta, WLAN_STA_AUTH)) { |
808 | ret = sta_info_move_state_checked(sta, | 804 | ret = sta_info_move_state(sta, IEEE80211_STA_AUTH); |
809 | IEEE80211_STA_AUTH); | ||
810 | if (ret) | 805 | if (ret) |
811 | return ret; | 806 | return ret; |
812 | ret = sta_info_move_state_checked(sta, | 807 | ret = sta_info_move_state(sta, IEEE80211_STA_NONE); |
813 | IEEE80211_STA_NONE); | ||
814 | if (ret) | 808 | if (ret) |
815 | return ret; | 809 | return ret; |
816 | } | 810 | } |
@@ -944,8 +938,8 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
944 | if (!sta) | 938 | if (!sta) |
945 | return -ENOMEM; | 939 | return -ENOMEM; |
946 | 940 | ||
947 | sta_info_move_state(sta, IEEE80211_STA_AUTH); | 941 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); |
948 | sta_info_move_state(sta, IEEE80211_STA_ASSOC); | 942 | sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); |
949 | 943 | ||
950 | err = sta_apply_parameters(local, sta, params); | 944 | err = sta_apply_parameters(local, sta, params); |
951 | if (err) { | 945 | if (err) { |
@@ -1001,6 +995,7 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
1001 | struct ieee80211_local *local = wiphy_priv(wiphy); | 995 | struct ieee80211_local *local = wiphy_priv(wiphy); |
1002 | struct sta_info *sta; | 996 | struct sta_info *sta; |
1003 | struct ieee80211_sub_if_data *vlansdata; | 997 | struct ieee80211_sub_if_data *vlansdata; |
998 | int err; | ||
1004 | 999 | ||
1005 | mutex_lock(&local->sta_mtx); | 1000 | mutex_lock(&local->sta_mtx); |
1006 | 1001 | ||
@@ -1040,7 +1035,11 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
1040 | ieee80211_send_layer2_update(sta); | 1035 | ieee80211_send_layer2_update(sta); |
1041 | } | 1036 | } |
1042 | 1037 | ||
1043 | sta_apply_parameters(local, sta, params); | 1038 | err = sta_apply_parameters(local, sta, params); |
1039 | if (err) { | ||
1040 | mutex_unlock(&local->sta_mtx); | ||
1041 | return err; | ||
1042 | } | ||
1044 | 1043 | ||
1045 | if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) && params->supported_rates) | 1044 | if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) && params->supported_rates) |
1046 | rate_control_rate_init(sta); | 1045 | rate_control_rate_init(sta); |
@@ -1341,6 +1340,8 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy, | |||
1341 | conf->dot11MeshHWMPRannInterval = | 1340 | conf->dot11MeshHWMPRannInterval = |
1342 | nconf->dot11MeshHWMPRannInterval; | 1341 | nconf->dot11MeshHWMPRannInterval; |
1343 | } | 1342 | } |
1343 | if (_chg_mesh_attr(NL80211_MESHCONF_FORWARDING, mask)) | ||
1344 | conf->dot11MeshForwarding = nconf->dot11MeshForwarding; | ||
1344 | return 0; | 1345 | return 0; |
1345 | } | 1346 | } |
1346 | 1347 | ||
@@ -1868,7 +1869,6 @@ static int ieee80211_set_cqm_rssi_config(struct wiphy *wiphy, | |||
1868 | s32 rssi_thold, u32 rssi_hyst) | 1869 | s32 rssi_thold, u32 rssi_hyst) |
1869 | { | 1870 | { |
1870 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1871 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1871 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
1872 | struct ieee80211_vif *vif = &sdata->vif; | 1872 | struct ieee80211_vif *vif = &sdata->vif; |
1873 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; | 1873 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; |
1874 | 1874 | ||
@@ -1879,14 +1879,9 @@ static int ieee80211_set_cqm_rssi_config(struct wiphy *wiphy, | |||
1879 | bss_conf->cqm_rssi_thold = rssi_thold; | 1879 | bss_conf->cqm_rssi_thold = rssi_thold; |
1880 | bss_conf->cqm_rssi_hyst = rssi_hyst; | 1880 | bss_conf->cqm_rssi_hyst = rssi_hyst; |
1881 | 1881 | ||
1882 | if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI)) { | ||
1883 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | ||
1884 | return -EOPNOTSUPP; | ||
1885 | return 0; | ||
1886 | } | ||
1887 | |||
1888 | /* tell the driver upon association, unless already associated */ | 1882 | /* tell the driver upon association, unless already associated */ |
1889 | if (sdata->u.mgd.associated) | 1883 | if (sdata->u.mgd.associated && |
1884 | sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI) | ||
1890 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_CQM); | 1885 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_CQM); |
1891 | 1886 | ||
1892 | return 0; | 1887 | return 0; |
@@ -1907,8 +1902,11 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, | |||
1907 | return ret; | 1902 | return ret; |
1908 | } | 1903 | } |
1909 | 1904 | ||
1910 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) | 1905 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { |
1911 | sdata->rc_rateidx_mask[i] = mask->control[i].legacy; | 1906 | sdata->rc_rateidx_mask[i] = mask->control[i].legacy; |
1907 | memcpy(sdata->rc_rateidx_mcs_mask[i], mask->control[i].mcs, | ||
1908 | sizeof(mask->control[i].mcs)); | ||
1909 | } | ||
1912 | 1910 | ||
1913 | return 0; | 1911 | return 0; |
1914 | } | 1912 | } |
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index 889c3e93e0f4..d1f7abddb182 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c | |||
@@ -20,23 +20,29 @@ __ieee80211_get_channel_mode(struct ieee80211_local *local, | |||
20 | if (!ieee80211_sdata_running(sdata)) | 20 | if (!ieee80211_sdata_running(sdata)) |
21 | continue; | 21 | continue; |
22 | 22 | ||
23 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR) | 23 | switch (sdata->vif.type) { |
24 | case NL80211_IFTYPE_MONITOR: | ||
24 | continue; | 25 | continue; |
25 | 26 | case NL80211_IFTYPE_STATION: | |
26 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | 27 | if (!sdata->u.mgd.associated) |
27 | !sdata->u.mgd.associated) | 28 | continue; |
28 | continue; | 29 | break; |
29 | 30 | case NL80211_IFTYPE_ADHOC: | |
30 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { | ||
31 | if (!sdata->u.ibss.ssid_len) | 31 | if (!sdata->u.ibss.ssid_len) |
32 | continue; | 32 | continue; |
33 | if (!sdata->u.ibss.fixed_channel) | 33 | if (!sdata->u.ibss.fixed_channel) |
34 | return CHAN_MODE_HOPPING; | 34 | return CHAN_MODE_HOPPING; |
35 | } | 35 | break; |
36 | 36 | case NL80211_IFTYPE_AP_VLAN: | |
37 | if (sdata->vif.type == NL80211_IFTYPE_AP && | 37 | /* will also have _AP interface */ |
38 | !sdata->u.ap.beacon) | ||
39 | continue; | 38 | continue; |
39 | case NL80211_IFTYPE_AP: | ||
40 | if (!sdata->u.ap.beacon) | ||
41 | continue; | ||
42 | break; | ||
43 | default: | ||
44 | break; | ||
45 | } | ||
40 | 46 | ||
41 | return CHAN_MODE_FIXED; | 47 | return CHAN_MODE_FIXED; |
42 | } | 48 | } |
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 90baea53e7c5..affe64be9092 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c | |||
@@ -247,8 +247,6 @@ static ssize_t hwflags_read(struct file *file, char __user *user_buf, | |||
247 | sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_DYNAMIC_PS\n"); | 247 | sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_DYNAMIC_PS\n"); |
248 | if (local->hw.flags & IEEE80211_HW_MFP_CAPABLE) | 248 | if (local->hw.flags & IEEE80211_HW_MFP_CAPABLE) |
249 | sf += snprintf(buf + sf, mxln - sf, "MFP_CAPABLE\n"); | 249 | sf += snprintf(buf + sf, mxln - sf, "MFP_CAPABLE\n"); |
250 | if (local->hw.flags & IEEE80211_HW_BEACON_FILTER) | ||
251 | sf += snprintf(buf + sf, mxln - sf, "BEACON_FILTER\n"); | ||
252 | if (local->hw.flags & IEEE80211_HW_SUPPORTS_STATIC_SMPS) | 250 | if (local->hw.flags & IEEE80211_HW_SUPPORTS_STATIC_SMPS) |
253 | sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_STATIC_SMPS\n"); | 251 | sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_STATIC_SMPS\n"); |
254 | if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS) | 252 | if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS) |
@@ -259,8 +257,6 @@ static ssize_t hwflags_read(struct file *file, char __user *user_buf, | |||
259 | sf += snprintf(buf + sf, mxln - sf, "REPORTS_TX_ACK_STATUS\n"); | 257 | sf += snprintf(buf + sf, mxln - sf, "REPORTS_TX_ACK_STATUS\n"); |
260 | if (local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) | 258 | if (local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) |
261 | sf += snprintf(buf + sf, mxln - sf, "CONNECTION_MONITOR\n"); | 259 | sf += snprintf(buf + sf, mxln - sf, "CONNECTION_MONITOR\n"); |
262 | if (local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI) | ||
263 | sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_CQM_RSSI\n"); | ||
264 | if (local->hw.flags & IEEE80211_HW_SUPPORTS_PER_STA_GTK) | 260 | if (local->hw.flags & IEEE80211_HW_SUPPORTS_PER_STA_GTK) |
265 | sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_PER_STA_GTK\n"); | 261 | sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_PER_STA_GTK\n"); |
266 | if (local->hw.flags & IEEE80211_HW_AP_LINK_PS) | 262 | if (local->hw.flags & IEEE80211_HW_AP_LINK_PS) |
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 176c08ffb13c..510ed1dab3c7 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -87,6 +87,21 @@ static ssize_t ieee80211_if_fmt_##name( \ | |||
87 | #define IEEE80211_IF_FMT_SIZE(name, field) \ | 87 | #define IEEE80211_IF_FMT_SIZE(name, field) \ |
88 | IEEE80211_IF_FMT(name, field, "%zd\n") | 88 | IEEE80211_IF_FMT(name, field, "%zd\n") |
89 | 89 | ||
90 | #define IEEE80211_IF_FMT_HEXARRAY(name, field) \ | ||
91 | static ssize_t ieee80211_if_fmt_##name( \ | ||
92 | const struct ieee80211_sub_if_data *sdata, \ | ||
93 | char *buf, int buflen) \ | ||
94 | { \ | ||
95 | char *p = buf; \ | ||
96 | int i; \ | ||
97 | for (i = 0; i < sizeof(sdata->field); i++) { \ | ||
98 | p += scnprintf(p, buflen + buf - p, "%.2x ", \ | ||
99 | sdata->field[i]); \ | ||
100 | } \ | ||
101 | p += scnprintf(p, buflen + buf - p, "\n"); \ | ||
102 | return p - buf; \ | ||
103 | } | ||
104 | |||
90 | #define IEEE80211_IF_FMT_ATOMIC(name, field) \ | 105 | #define IEEE80211_IF_FMT_ATOMIC(name, field) \ |
91 | static ssize_t ieee80211_if_fmt_##name( \ | 106 | static ssize_t ieee80211_if_fmt_##name( \ |
92 | const struct ieee80211_sub_if_data *sdata, \ | 107 | const struct ieee80211_sub_if_data *sdata, \ |
@@ -148,6 +163,11 @@ IEEE80211_IF_FILE(rc_rateidx_mask_2ghz, rc_rateidx_mask[IEEE80211_BAND_2GHZ], | |||
148 | HEX); | 163 | HEX); |
149 | IEEE80211_IF_FILE(rc_rateidx_mask_5ghz, rc_rateidx_mask[IEEE80211_BAND_5GHZ], | 164 | IEEE80211_IF_FILE(rc_rateidx_mask_5ghz, rc_rateidx_mask[IEEE80211_BAND_5GHZ], |
150 | HEX); | 165 | HEX); |
166 | IEEE80211_IF_FILE(rc_rateidx_mcs_mask_2ghz, | ||
167 | rc_rateidx_mcs_mask[IEEE80211_BAND_2GHZ], HEXARRAY); | ||
168 | IEEE80211_IF_FILE(rc_rateidx_mcs_mask_5ghz, | ||
169 | rc_rateidx_mcs_mask[IEEE80211_BAND_5GHZ], HEXARRAY); | ||
170 | |||
151 | IEEE80211_IF_FILE(flags, flags, HEX); | 171 | IEEE80211_IF_FILE(flags, flags, HEX); |
152 | IEEE80211_IF_FILE(state, state, LHEX); | 172 | IEEE80211_IF_FILE(state, state, LHEX); |
153 | IEEE80211_IF_FILE(channel_type, vif.bss_conf.channel_type, DEC); | 173 | IEEE80211_IF_FILE(channel_type, vif.bss_conf.channel_type, DEC); |
@@ -422,6 +442,7 @@ IEEE80211_IF_FILE(dot11MeshGateAnnouncementProtocol, | |||
422 | u.mesh.mshcfg.dot11MeshGateAnnouncementProtocol, DEC); | 442 | u.mesh.mshcfg.dot11MeshGateAnnouncementProtocol, DEC); |
423 | IEEE80211_IF_FILE(dot11MeshHWMPRannInterval, | 443 | IEEE80211_IF_FILE(dot11MeshHWMPRannInterval, |
424 | u.mesh.mshcfg.dot11MeshHWMPRannInterval, DEC); | 444 | u.mesh.mshcfg.dot11MeshHWMPRannInterval, DEC); |
445 | IEEE80211_IF_FILE(dot11MeshForwarding, u.mesh.mshcfg.dot11MeshForwarding, DEC); | ||
425 | #endif | 446 | #endif |
426 | 447 | ||
427 | 448 | ||
@@ -441,6 +462,8 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata) | |||
441 | DEBUGFS_ADD(channel_type); | 462 | DEBUGFS_ADD(channel_type); |
442 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); | 463 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); |
443 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); | 464 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); |
465 | DEBUGFS_ADD(rc_rateidx_mcs_mask_2ghz); | ||
466 | DEBUGFS_ADD(rc_rateidx_mcs_mask_5ghz); | ||
444 | 467 | ||
445 | DEBUGFS_ADD(bssid); | 468 | DEBUGFS_ADD(bssid); |
446 | DEBUGFS_ADD(aid); | 469 | DEBUGFS_ADD(aid); |
@@ -458,6 +481,8 @@ static void add_ap_files(struct ieee80211_sub_if_data *sdata) | |||
458 | DEBUGFS_ADD(channel_type); | 481 | DEBUGFS_ADD(channel_type); |
459 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); | 482 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); |
460 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); | 483 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); |
484 | DEBUGFS_ADD(rc_rateidx_mcs_mask_2ghz); | ||
485 | DEBUGFS_ADD(rc_rateidx_mcs_mask_5ghz); | ||
461 | 486 | ||
462 | DEBUGFS_ADD(num_sta_authorized); | 487 | DEBUGFS_ADD(num_sta_authorized); |
463 | DEBUGFS_ADD(num_sta_ps); | 488 | DEBUGFS_ADD(num_sta_ps); |
@@ -468,6 +493,12 @@ static void add_ap_files(struct ieee80211_sub_if_data *sdata) | |||
468 | 493 | ||
469 | static void add_ibss_files(struct ieee80211_sub_if_data *sdata) | 494 | static void add_ibss_files(struct ieee80211_sub_if_data *sdata) |
470 | { | 495 | { |
496 | DEBUGFS_ADD(channel_type); | ||
497 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); | ||
498 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); | ||
499 | DEBUGFS_ADD(rc_rateidx_mcs_mask_2ghz); | ||
500 | DEBUGFS_ADD(rc_rateidx_mcs_mask_5ghz); | ||
501 | |||
471 | DEBUGFS_ADD_MODE(tsf, 0600); | 502 | DEBUGFS_ADD_MODE(tsf, 0600); |
472 | } | 503 | } |
473 | 504 | ||
@@ -479,6 +510,8 @@ static void add_wds_files(struct ieee80211_sub_if_data *sdata) | |||
479 | DEBUGFS_ADD(channel_type); | 510 | DEBUGFS_ADD(channel_type); |
480 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); | 511 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); |
481 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); | 512 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); |
513 | DEBUGFS_ADD(rc_rateidx_mcs_mask_2ghz); | ||
514 | DEBUGFS_ADD(rc_rateidx_mcs_mask_5ghz); | ||
482 | 515 | ||
483 | DEBUGFS_ADD(peer); | 516 | DEBUGFS_ADD(peer); |
484 | } | 517 | } |
@@ -491,6 +524,8 @@ static void add_vlan_files(struct ieee80211_sub_if_data *sdata) | |||
491 | DEBUGFS_ADD(channel_type); | 524 | DEBUGFS_ADD(channel_type); |
492 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); | 525 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); |
493 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); | 526 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); |
527 | DEBUGFS_ADD(rc_rateidx_mcs_mask_2ghz); | ||
528 | DEBUGFS_ADD(rc_rateidx_mcs_mask_5ghz); | ||
494 | } | 529 | } |
495 | 530 | ||
496 | static void add_monitor_files(struct ieee80211_sub_if_data *sdata) | 531 | static void add_monitor_files(struct ieee80211_sub_if_data *sdata) |
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 2406b3e7393f..c8383712fdec 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
@@ -63,14 +63,15 @@ static ssize_t sta_flags_read(struct file *file, char __user *userbuf, | |||
63 | test_sta_flag(sta, WLAN_STA_##flg) ? #flg "\n" : "" | 63 | test_sta_flag(sta, WLAN_STA_##flg) ? #flg "\n" : "" |
64 | 64 | ||
65 | int res = scnprintf(buf, sizeof(buf), | 65 | int res = scnprintf(buf, sizeof(buf), |
66 | "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", | 66 | "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", |
67 | TEST(AUTH), TEST(ASSOC), TEST(PS_STA), | 67 | TEST(AUTH), TEST(ASSOC), TEST(PS_STA), |
68 | TEST(PS_DRIVER), TEST(AUTHORIZED), | 68 | TEST(PS_DRIVER), TEST(AUTHORIZED), |
69 | TEST(SHORT_PREAMBLE), | 69 | TEST(SHORT_PREAMBLE), |
70 | TEST(WME), TEST(WDS), TEST(CLEAR_PS_FILT), | 70 | TEST(WME), TEST(WDS), TEST(CLEAR_PS_FILT), |
71 | TEST(MFP), TEST(BLOCK_BA), TEST(PSPOLL), | 71 | TEST(MFP), TEST(BLOCK_BA), TEST(PSPOLL), |
72 | TEST(UAPSD), TEST(SP), TEST(TDLS_PEER), | 72 | TEST(UAPSD), TEST(SP), TEST(TDLS_PEER), |
73 | TEST(TDLS_PEER_AUTH)); | 73 | TEST(TDLS_PEER_AUTH), TEST(4ADDR_EVENT), |
74 | TEST(INSERTED)); | ||
74 | #undef TEST | 75 | #undef TEST |
75 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); | 76 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); |
76 | } | 77 | } |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index a4643969a13b..7b3a0b0aa246 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -36,31 +36,6 @@ | |||
36 | #define IEEE80211_IBSS_MAX_STA_ENTRIES 128 | 36 | #define IEEE80211_IBSS_MAX_STA_ENTRIES 128 |
37 | 37 | ||
38 | 38 | ||
39 | static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata, | ||
40 | struct ieee80211_mgmt *mgmt, | ||
41 | size_t len) | ||
42 | { | ||
43 | u16 auth_alg, auth_transaction; | ||
44 | |||
45 | lockdep_assert_held(&sdata->u.ibss.mtx); | ||
46 | |||
47 | if (len < 24 + 6) | ||
48 | return; | ||
49 | |||
50 | auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg); | ||
51 | auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction); | ||
52 | |||
53 | /* | ||
54 | * IEEE 802.11 standard does not require authentication in IBSS | ||
55 | * networks and most implementations do not seem to use it. | ||
56 | * However, try to reply to authentication attempts if someone | ||
57 | * has actually implemented this. | ||
58 | */ | ||
59 | if (auth_alg == WLAN_AUTH_OPEN && auth_transaction == 1) | ||
60 | ieee80211_send_auth(sdata, 2, WLAN_AUTH_OPEN, NULL, 0, | ||
61 | sdata->u.ibss.bssid, NULL, 0, 0); | ||
62 | } | ||
63 | |||
64 | static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | 39 | static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, |
65 | const u8 *bssid, const int beacon_int, | 40 | const u8 *bssid, const int beacon_int, |
66 | struct ieee80211_channel *chan, | 41 | struct ieee80211_channel *chan, |
@@ -276,7 +251,8 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
276 | cbss->tsf); | 251 | cbss->tsf); |
277 | } | 252 | } |
278 | 253 | ||
279 | static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta) | 254 | static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta, |
255 | bool auth) | ||
280 | __acquires(RCU) | 256 | __acquires(RCU) |
281 | { | 257 | { |
282 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 258 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
@@ -290,22 +266,31 @@ static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta) | |||
290 | addr, sdata->name); | 266 | addr, sdata->name); |
291 | #endif | 267 | #endif |
292 | 268 | ||
293 | sta_info_move_state(sta, IEEE80211_STA_AUTH); | 269 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); |
294 | sta_info_move_state(sta, IEEE80211_STA_ASSOC); | 270 | sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); |
295 | sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED); | 271 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTHORIZED); |
296 | 272 | ||
297 | rate_control_rate_init(sta); | 273 | rate_control_rate_init(sta); |
298 | 274 | ||
299 | /* If it fails, maybe we raced another insertion? */ | 275 | /* If it fails, maybe we raced another insertion? */ |
300 | if (sta_info_insert_rcu(sta)) | 276 | if (sta_info_insert_rcu(sta)) |
301 | return sta_info_get(sdata, addr); | 277 | return sta_info_get(sdata, addr); |
278 | if (auth) { | ||
279 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | ||
280 | printk(KERN_DEBUG "TX Auth SA=%pM DA=%pM BSSID=%pM" | ||
281 | "(auth_transaction=1)\n", sdata->vif.addr, | ||
282 | sdata->u.ibss.bssid, addr); | ||
283 | #endif | ||
284 | ieee80211_send_auth(sdata, 1, WLAN_AUTH_OPEN, NULL, 0, | ||
285 | addr, sdata->u.ibss.bssid, NULL, 0, 0); | ||
286 | } | ||
302 | return sta; | 287 | return sta; |
303 | } | 288 | } |
304 | 289 | ||
305 | static struct sta_info * | 290 | static struct sta_info * |
306 | ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | 291 | ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, |
307 | const u8 *bssid, const u8 *addr, | 292 | const u8 *bssid, const u8 *addr, |
308 | u32 supp_rates) | 293 | u32 supp_rates, bool auth) |
309 | __acquires(RCU) | 294 | __acquires(RCU) |
310 | { | 295 | { |
311 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 296 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
@@ -347,7 +332,42 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | |||
347 | sta->sta.supp_rates[band] = supp_rates | | 332 | sta->sta.supp_rates[band] = supp_rates | |
348 | ieee80211_mandatory_rates(local, band); | 333 | ieee80211_mandatory_rates(local, band); |
349 | 334 | ||
350 | return ieee80211_ibss_finish_sta(sta); | 335 | return ieee80211_ibss_finish_sta(sta, auth); |
336 | } | ||
337 | |||
338 | static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata, | ||
339 | struct ieee80211_mgmt *mgmt, | ||
340 | size_t len) | ||
341 | { | ||
342 | u16 auth_alg, auth_transaction; | ||
343 | |||
344 | lockdep_assert_held(&sdata->u.ibss.mtx); | ||
345 | |||
346 | if (len < 24 + 6) | ||
347 | return; | ||
348 | |||
349 | auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg); | ||
350 | auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction); | ||
351 | |||
352 | if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) | ||
353 | return; | ||
354 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | ||
355 | printk(KERN_DEBUG "%s: RX Auth SA=%pM DA=%pM BSSID=%pM." | ||
356 | "(auth_transaction=%d)\n", | ||
357 | sdata->name, mgmt->sa, mgmt->da, mgmt->bssid, auth_transaction); | ||
358 | #endif | ||
359 | sta_info_destroy_addr(sdata, mgmt->sa); | ||
360 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, 0, false); | ||
361 | rcu_read_unlock(); | ||
362 | |||
363 | /* | ||
364 | * IEEE 802.11 standard does not require authentication in IBSS | ||
365 | * networks and most implementations do not seem to use it. | ||
366 | * However, try to reply to authentication attempts if someone | ||
367 | * has actually implemented this. | ||
368 | */ | ||
369 | ieee80211_send_auth(sdata, 2, WLAN_AUTH_OPEN, NULL, 0, | ||
370 | mgmt->sa, sdata->u.ibss.bssid, NULL, 0, 0); | ||
351 | } | 371 | } |
352 | 372 | ||
353 | static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | 373 | static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, |
@@ -412,7 +432,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
412 | } else { | 432 | } else { |
413 | rcu_read_unlock(); | 433 | rcu_read_unlock(); |
414 | sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid, | 434 | sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid, |
415 | mgmt->sa, supp_rates); | 435 | mgmt->sa, supp_rates, true); |
416 | } | 436 | } |
417 | } | 437 | } |
418 | 438 | ||
@@ -540,7 +560,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
540 | ieee80211_sta_join_ibss(sdata, bss); | 560 | ieee80211_sta_join_ibss(sdata, bss); |
541 | supp_rates = ieee80211_sta_get_rates(local, elems, band); | 561 | supp_rates = ieee80211_sta_get_rates(local, elems, band); |
542 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, | 562 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, |
543 | supp_rates); | 563 | supp_rates, true); |
544 | rcu_read_unlock(); | 564 | rcu_read_unlock(); |
545 | } | 565 | } |
546 | 566 | ||
@@ -643,8 +663,7 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) | |||
643 | "IBSS networks with same SSID (merge)\n", sdata->name); | 663 | "IBSS networks with same SSID (merge)\n", sdata->name); |
644 | 664 | ||
645 | ieee80211_request_internal_scan(sdata, | 665 | ieee80211_request_internal_scan(sdata, |
646 | ifibss->ssid, ifibss->ssid_len, | 666 | ifibss->ssid, ifibss->ssid_len, NULL); |
647 | ifibss->fixed_channel ? ifibss->channel : NULL); | ||
648 | } | 667 | } |
649 | 668 | ||
650 | static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) | 669 | static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) |
@@ -855,9 +874,6 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, | |||
855 | size_t baselen; | 874 | size_t baselen; |
856 | struct ieee802_11_elems elems; | 875 | struct ieee802_11_elems elems; |
857 | 876 | ||
858 | if (memcmp(mgmt->da, sdata->vif.addr, ETH_ALEN)) | ||
859 | return; /* ignore ProbeResp to foreign address */ | ||
860 | |||
861 | baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; | 877 | baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; |
862 | if (baselen > len) | 878 | if (baselen > len) |
863 | return; | 879 | return; |
@@ -945,7 +961,7 @@ void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata) | |||
945 | list_del(&sta->list); | 961 | list_del(&sta->list); |
946 | spin_unlock_bh(&ifibss->incomplete_lock); | 962 | spin_unlock_bh(&ifibss->incomplete_lock); |
947 | 963 | ||
948 | ieee80211_ibss_finish_sta(sta); | 964 | ieee80211_ibss_finish_sta(sta, true); |
949 | rcu_read_unlock(); | 965 | rcu_read_unlock(); |
950 | spin_lock_bh(&ifibss->incomplete_lock); | 966 | spin_lock_bh(&ifibss->incomplete_lock); |
951 | } | 967 | } |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 2f0642d9e154..d47e8c110b16 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -646,6 +646,7 @@ struct ieee80211_sub_if_data { | |||
646 | 646 | ||
647 | /* bitmap of allowed (non-MCS) rate indexes for rate control */ | 647 | /* bitmap of allowed (non-MCS) rate indexes for rate control */ |
648 | u32 rc_rateidx_mask[IEEE80211_NUM_BANDS]; | 648 | u32 rc_rateidx_mask[IEEE80211_NUM_BANDS]; |
649 | u8 rc_rateidx_mcs_mask[IEEE80211_NUM_BANDS][IEEE80211_HT_MCS_MASK_LEN]; | ||
649 | 650 | ||
650 | union { | 651 | union { |
651 | struct ieee80211_if_ap ap; | 652 | struct ieee80211_if_ap ap; |
@@ -1396,7 +1397,7 @@ void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, | |||
1396 | void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | 1397 | void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, |
1397 | u16 transaction, u16 auth_alg, | 1398 | u16 transaction, u16 auth_alg, |
1398 | u8 *extra, size_t extra_len, const u8 *bssid, | 1399 | u8 *extra, size_t extra_len, const u8 *bssid, |
1399 | const u8 *key, u8 key_len, u8 key_idx); | 1400 | const u8 *da, const u8 *key, u8 key_len, u8 key_idx); |
1400 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | 1401 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, |
1401 | const u8 *ie, size_t ie_len, | 1402 | const u8 *ie, size_t ie_len, |
1402 | enum ieee80211_band band, u32 rate_mask, | 1403 | enum ieee80211_band band, u32 rate_mask, |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 01a21c2f6ab3..2efd595b2f7a 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -318,9 +318,9 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
318 | goto err_del_interface; | 318 | goto err_del_interface; |
319 | } | 319 | } |
320 | 320 | ||
321 | sta_info_move_state(sta, IEEE80211_STA_AUTH); | 321 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); |
322 | sta_info_move_state(sta, IEEE80211_STA_ASSOC); | 322 | sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); |
323 | sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED); | 323 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTHORIZED); |
324 | 324 | ||
325 | res = sta_info_insert(sta); | 325 | res = sta_info_insert(sta); |
326 | if (res) { | 326 | if (res) { |
@@ -1181,6 +1181,13 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1181 | sband = local->hw.wiphy->bands[i]; | 1181 | sband = local->hw.wiphy->bands[i]; |
1182 | sdata->rc_rateidx_mask[i] = | 1182 | sdata->rc_rateidx_mask[i] = |
1183 | sband ? (1 << sband->n_bitrates) - 1 : 0; | 1183 | sband ? (1 << sband->n_bitrates) - 1 : 0; |
1184 | if (sband) | ||
1185 | memcpy(sdata->rc_rateidx_mcs_mask[i], | ||
1186 | sband->ht_cap.mcs.rx_mask, | ||
1187 | sizeof(sdata->rc_rateidx_mcs_mask[i])); | ||
1188 | else | ||
1189 | memset(sdata->rc_rateidx_mcs_mask[i], 0, | ||
1190 | sizeof(sdata->rc_rateidx_mcs_mask[i])); | ||
1184 | } | 1191 | } |
1185 | 1192 | ||
1186 | /* setup type-dependent data */ | 1193 | /* setup type-dependent data */ |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 0a0d94ad9b08..6192caadfab9 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -155,7 +155,8 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | |||
155 | power = chan->max_power; | 155 | power = chan->max_power; |
156 | else | 156 | else |
157 | power = local->power_constr_level ? | 157 | power = local->power_constr_level ? |
158 | (chan->max_power - local->power_constr_level) : | 158 | min(chan->max_power, |
159 | (chan->max_reg_power - local->power_constr_level)) : | ||
159 | chan->max_power; | 160 | chan->max_power; |
160 | 161 | ||
161 | if (local->user_power_level >= 0) | 162 | if (local->user_power_level >= 0) |
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 54df1b2bafd2..c27dec904963 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
@@ -575,7 +575,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, | |||
575 | ifmsh->mshstats.dropped_frames_ttl++; | 575 | ifmsh->mshstats.dropped_frames_ttl++; |
576 | } | 576 | } |
577 | 577 | ||
578 | if (forward) { | 578 | if (forward && ifmsh->mshcfg.dot11MeshForwarding) { |
579 | u32 preq_id; | 579 | u32 preq_id; |
580 | u8 hopcount, flags; | 580 | u8 hopcount, flags; |
581 | 581 | ||
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index a17251730b9e..8806e5ef8ffe 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -96,9 +96,9 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata, | |||
96 | if (!sta) | 96 | if (!sta) |
97 | return NULL; | 97 | return NULL; |
98 | 98 | ||
99 | sta_info_move_state(sta, IEEE80211_STA_AUTH); | 99 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); |
100 | sta_info_move_state(sta, IEEE80211_STA_ASSOC); | 100 | sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); |
101 | sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED); | 101 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTHORIZED); |
102 | 102 | ||
103 | set_sta_flag(sta, WLAN_STA_WME); | 103 | set_sta_flag(sta, WLAN_STA_WME); |
104 | 104 | ||
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 295be92f7c77..49fd1acd5d15 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -127,7 +127,7 @@ static void run_again(struct ieee80211_if_managed *ifmgd, | |||
127 | 127 | ||
128 | void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata) | 128 | void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata) |
129 | { | 129 | { |
130 | if (sdata->local->hw.flags & IEEE80211_HW_BEACON_FILTER) | 130 | if (sdata->vif.driver_flags & IEEE80211_VIF_BEACON_FILTER) |
131 | return; | 131 | return; |
132 | 132 | ||
133 | mod_timer(&sdata->u.mgd.bcn_mon_timer, | 133 | mod_timer(&sdata->u.mgd.bcn_mon_timer, |
@@ -547,7 +547,7 @@ static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, | |||
547 | if (pwr_constr_elem_len != 1) | 547 | if (pwr_constr_elem_len != 1) |
548 | return; | 548 | return; |
549 | 549 | ||
550 | if ((*pwr_constr_elem <= conf->channel->max_power) && | 550 | if ((*pwr_constr_elem <= conf->channel->max_reg_power) && |
551 | (*pwr_constr_elem != sdata->local->power_constr_level)) { | 551 | (*pwr_constr_elem != sdata->local->power_constr_level)) { |
552 | sdata->local->power_constr_level = *pwr_constr_elem; | 552 | sdata->local->power_constr_level = *pwr_constr_elem; |
553 | ieee80211_hw_config(sdata->local, 0); | 553 | ieee80211_hw_config(sdata->local, 0); |
@@ -1043,7 +1043,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
1043 | bss_info_changed |= BSS_CHANGED_BSSID; | 1043 | bss_info_changed |= BSS_CHANGED_BSSID; |
1044 | 1044 | ||
1045 | /* Tell the driver to monitor connection quality (if supported) */ | 1045 | /* Tell the driver to monitor connection quality (if supported) */ |
1046 | if ((local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI) && | 1046 | if (sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI && |
1047 | bss_conf->cqm_rssi_thold) | 1047 | bss_conf->cqm_rssi_thold) |
1048 | bss_info_changed |= BSS_CHANGED_CQM; | 1048 | bss_info_changed |= BSS_CHANGED_CQM; |
1049 | 1049 | ||
@@ -1587,10 +1587,19 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, | |||
1587 | return false; | 1587 | return false; |
1588 | } | 1588 | } |
1589 | 1589 | ||
1590 | sta_info_move_state(sta, IEEE80211_STA_AUTH); | 1590 | err = sta_info_move_state(sta, IEEE80211_STA_AUTH); |
1591 | sta_info_move_state(sta, IEEE80211_STA_ASSOC); | 1591 | if (!err) |
1592 | if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) | 1592 | err = sta_info_move_state(sta, IEEE80211_STA_ASSOC); |
1593 | sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED); | 1593 | if (!err && !(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) |
1594 | err = sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED); | ||
1595 | if (err) { | ||
1596 | printk(KERN_DEBUG | ||
1597 | "%s: failed to move station %pM to desired state\n", | ||
1598 | sdata->name, sta->sta.addr); | ||
1599 | WARN_ON(__sta_info_destroy(sta)); | ||
1600 | mutex_unlock(&sdata->local->sta_mtx); | ||
1601 | return false; | ||
1602 | } | ||
1594 | 1603 | ||
1595 | rates = 0; | 1604 | rates = 0; |
1596 | basic_rates = 0; | 1605 | basic_rates = 0; |
@@ -1882,7 +1891,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1882 | 1891 | ||
1883 | if (bss_conf->cqm_rssi_thold && | 1892 | if (bss_conf->cqm_rssi_thold && |
1884 | ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT && | 1893 | ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT && |
1885 | !(local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI)) { | 1894 | !(sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI)) { |
1886 | int sig = ifmgd->ave_beacon_signal / 16; | 1895 | int sig = ifmgd->ave_beacon_signal / 16; |
1887 | int last_event = ifmgd->last_cqm_event_signal; | 1896 | int last_event = ifmgd->last_cqm_event_signal; |
1888 | int thold = bss_conf->cqm_rssi_thold; | 1897 | int thold = bss_conf->cqm_rssi_thold; |
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 5a5a7767d541..3fef26d8898a 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
@@ -159,7 +159,6 @@ static struct rate_control_ref *rate_control_alloc(const char *name, | |||
159 | ref = kmalloc(sizeof(struct rate_control_ref), GFP_KERNEL); | 159 | ref = kmalloc(sizeof(struct rate_control_ref), GFP_KERNEL); |
160 | if (!ref) | 160 | if (!ref) |
161 | goto fail_ref; | 161 | goto fail_ref; |
162 | kref_init(&ref->kref); | ||
163 | ref->local = local; | 162 | ref->local = local; |
164 | ref->ops = ieee80211_rate_control_ops_get(name); | 163 | ref->ops = ieee80211_rate_control_ops_get(name); |
165 | if (!ref->ops) | 164 | if (!ref->ops) |
@@ -184,11 +183,8 @@ fail_ref: | |||
184 | return NULL; | 183 | return NULL; |
185 | } | 184 | } |
186 | 185 | ||
187 | static void rate_control_release(struct kref *kref) | 186 | static void rate_control_free(struct rate_control_ref *ctrl_ref) |
188 | { | 187 | { |
189 | struct rate_control_ref *ctrl_ref; | ||
190 | |||
191 | ctrl_ref = container_of(kref, struct rate_control_ref, kref); | ||
192 | ctrl_ref->ops->free(ctrl_ref->priv); | 188 | ctrl_ref->ops->free(ctrl_ref->priv); |
193 | 189 | ||
194 | #ifdef CONFIG_MAC80211_DEBUGFS | 190 | #ifdef CONFIG_MAC80211_DEBUGFS |
@@ -293,8 +289,8 @@ bool rate_control_send_low(struct ieee80211_sta *sta, | |||
293 | } | 289 | } |
294 | EXPORT_SYMBOL(rate_control_send_low); | 290 | EXPORT_SYMBOL(rate_control_send_low); |
295 | 291 | ||
296 | static void rate_idx_match_mask(struct ieee80211_tx_rate *rate, | 292 | static bool rate_idx_match_legacy_mask(struct ieee80211_tx_rate *rate, |
297 | int n_bitrates, u32 mask) | 293 | int n_bitrates, u32 mask) |
298 | { | 294 | { |
299 | int j; | 295 | int j; |
300 | 296 | ||
@@ -303,7 +299,7 @@ static void rate_idx_match_mask(struct ieee80211_tx_rate *rate, | |||
303 | if (mask & (1 << j)) { | 299 | if (mask & (1 << j)) { |
304 | /* Okay, found a suitable rate. Use it. */ | 300 | /* Okay, found a suitable rate. Use it. */ |
305 | rate->idx = j; | 301 | rate->idx = j; |
306 | return; | 302 | return true; |
307 | } | 303 | } |
308 | } | 304 | } |
309 | 305 | ||
@@ -312,6 +308,112 @@ static void rate_idx_match_mask(struct ieee80211_tx_rate *rate, | |||
312 | if (mask & (1 << j)) { | 308 | if (mask & (1 << j)) { |
313 | /* Okay, found a suitable rate. Use it. */ | 309 | /* Okay, found a suitable rate. Use it. */ |
314 | rate->idx = j; | 310 | rate->idx = j; |
311 | return true; | ||
312 | } | ||
313 | } | ||
314 | return false; | ||
315 | } | ||
316 | |||
317 | static bool rate_idx_match_mcs_mask(struct ieee80211_tx_rate *rate, | ||
318 | u8 mcs_mask[IEEE80211_HT_MCS_MASK_LEN]) | ||
319 | { | ||
320 | int i, j; | ||
321 | int ridx, rbit; | ||
322 | |||
323 | ridx = rate->idx / 8; | ||
324 | rbit = rate->idx % 8; | ||
325 | |||
326 | /* sanity check */ | ||
327 | if (ridx < 0 || ridx > IEEE80211_HT_MCS_MASK_LEN) | ||
328 | return false; | ||
329 | |||
330 | /* See whether the selected rate or anything below it is allowed. */ | ||
331 | for (i = ridx; i >= 0; i--) { | ||
332 | for (j = rbit; j >= 0; j--) | ||
333 | if (mcs_mask[i] & BIT(j)) { | ||
334 | rate->idx = i * 8 + j; | ||
335 | return true; | ||
336 | } | ||
337 | rbit = 7; | ||
338 | } | ||
339 | |||
340 | /* Try to find a higher rate that would be allowed */ | ||
341 | ridx = (rate->idx + 1) / 8; | ||
342 | rbit = (rate->idx + 1) % 8; | ||
343 | |||
344 | for (i = ridx; i < IEEE80211_HT_MCS_MASK_LEN; i++) { | ||
345 | for (j = rbit; j < 8; j++) | ||
346 | if (mcs_mask[i] & BIT(j)) { | ||
347 | rate->idx = i * 8 + j; | ||
348 | return true; | ||
349 | } | ||
350 | rbit = 0; | ||
351 | } | ||
352 | return false; | ||
353 | } | ||
354 | |||
355 | |||
356 | |||
357 | static void rate_idx_match_mask(struct ieee80211_tx_rate *rate, | ||
358 | struct ieee80211_tx_rate_control *txrc, | ||
359 | u32 mask, | ||
360 | u8 mcs_mask[IEEE80211_HT_MCS_MASK_LEN]) | ||
361 | { | ||
362 | struct ieee80211_tx_rate alt_rate; | ||
363 | |||
364 | /* handle HT rates */ | ||
365 | if (rate->flags & IEEE80211_TX_RC_MCS) { | ||
366 | if (rate_idx_match_mcs_mask(rate, mcs_mask)) | ||
367 | return; | ||
368 | |||
369 | /* also try the legacy rates. */ | ||
370 | alt_rate.idx = 0; | ||
371 | /* keep protection flags */ | ||
372 | alt_rate.flags = rate->flags & | ||
373 | (IEEE80211_TX_RC_USE_RTS_CTS | | ||
374 | IEEE80211_TX_RC_USE_CTS_PROTECT | | ||
375 | IEEE80211_TX_RC_USE_SHORT_PREAMBLE); | ||
376 | alt_rate.count = rate->count; | ||
377 | if (rate_idx_match_legacy_mask(&alt_rate, | ||
378 | txrc->sband->n_bitrates, | ||
379 | mask)) { | ||
380 | *rate = alt_rate; | ||
381 | return; | ||
382 | } | ||
383 | } else { | ||
384 | struct sk_buff *skb = txrc->skb; | ||
385 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
386 | __le16 fc; | ||
387 | |||
388 | /* handle legacy rates */ | ||
389 | if (rate_idx_match_legacy_mask(rate, txrc->sband->n_bitrates, | ||
390 | mask)) | ||
391 | return; | ||
392 | |||
393 | /* if HT BSS, and we handle a data frame, also try HT rates */ | ||
394 | if (txrc->bss_conf->channel_type == NL80211_CHAN_NO_HT) | ||
395 | return; | ||
396 | |||
397 | fc = hdr->frame_control; | ||
398 | if (!ieee80211_is_data(fc)) | ||
399 | return; | ||
400 | |||
401 | alt_rate.idx = 0; | ||
402 | /* keep protection flags */ | ||
403 | alt_rate.flags = rate->flags & | ||
404 | (IEEE80211_TX_RC_USE_RTS_CTS | | ||
405 | IEEE80211_TX_RC_USE_CTS_PROTECT | | ||
406 | IEEE80211_TX_RC_USE_SHORT_PREAMBLE); | ||
407 | alt_rate.count = rate->count; | ||
408 | |||
409 | alt_rate.flags |= IEEE80211_TX_RC_MCS; | ||
410 | |||
411 | if ((txrc->bss_conf->channel_type == NL80211_CHAN_HT40MINUS) || | ||
412 | (txrc->bss_conf->channel_type == NL80211_CHAN_HT40PLUS)) | ||
413 | alt_rate.flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; | ||
414 | |||
415 | if (rate_idx_match_mcs_mask(&alt_rate, mcs_mask)) { | ||
416 | *rate = alt_rate; | ||
315 | return; | 417 | return; |
316 | } | 418 | } |
317 | } | 419 | } |
@@ -335,6 +437,7 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, | |||
335 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb); | 437 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb); |
336 | int i; | 438 | int i; |
337 | u32 mask; | 439 | u32 mask; |
440 | u8 mcs_mask[IEEE80211_HT_MCS_MASK_LEN]; | ||
338 | 441 | ||
339 | if (sta) { | 442 | if (sta) { |
340 | ista = &sta->sta; | 443 | ista = &sta->sta; |
@@ -358,10 +461,14 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, | |||
358 | * the common case. | 461 | * the common case. |
359 | */ | 462 | */ |
360 | mask = sdata->rc_rateidx_mask[info->band]; | 463 | mask = sdata->rc_rateidx_mask[info->band]; |
464 | memcpy(mcs_mask, sdata->rc_rateidx_mcs_mask[info->band], | ||
465 | sizeof(mcs_mask)); | ||
361 | if (mask != (1 << txrc->sband->n_bitrates) - 1) { | 466 | if (mask != (1 << txrc->sband->n_bitrates) - 1) { |
362 | if (sta) { | 467 | if (sta) { |
363 | /* Filter out rates that the STA does not support */ | 468 | /* Filter out rates that the STA does not support */ |
364 | mask &= sta->sta.supp_rates[info->band]; | 469 | mask &= sta->sta.supp_rates[info->band]; |
470 | for (i = 0; i < sizeof(mcs_mask); i++) | ||
471 | mcs_mask[i] &= sta->sta.ht_cap.mcs.rx_mask[i]; | ||
365 | } | 472 | } |
366 | /* | 473 | /* |
367 | * Make sure the rate index selected for each TX rate is | 474 | * Make sure the rate index selected for each TX rate is |
@@ -372,32 +479,18 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, | |||
372 | /* Skip invalid rates */ | 479 | /* Skip invalid rates */ |
373 | if (info->control.rates[i].idx < 0) | 480 | if (info->control.rates[i].idx < 0) |
374 | break; | 481 | break; |
375 | /* Rate masking supports only legacy rates for now */ | 482 | rate_idx_match_mask(&info->control.rates[i], txrc, |
376 | if (info->control.rates[i].flags & IEEE80211_TX_RC_MCS) | 483 | mask, mcs_mask); |
377 | continue; | ||
378 | rate_idx_match_mask(&info->control.rates[i], | ||
379 | txrc->sband->n_bitrates, mask); | ||
380 | } | 484 | } |
381 | } | 485 | } |
382 | 486 | ||
383 | BUG_ON(info->control.rates[0].idx < 0); | 487 | BUG_ON(info->control.rates[0].idx < 0); |
384 | } | 488 | } |
385 | 489 | ||
386 | struct rate_control_ref *rate_control_get(struct rate_control_ref *ref) | ||
387 | { | ||
388 | kref_get(&ref->kref); | ||
389 | return ref; | ||
390 | } | ||
391 | |||
392 | void rate_control_put(struct rate_control_ref *ref) | ||
393 | { | ||
394 | kref_put(&ref->kref, rate_control_release); | ||
395 | } | ||
396 | |||
397 | int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, | 490 | int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, |
398 | const char *name) | 491 | const char *name) |
399 | { | 492 | { |
400 | struct rate_control_ref *ref, *old; | 493 | struct rate_control_ref *ref; |
401 | 494 | ||
402 | ASSERT_RTNL(); | 495 | ASSERT_RTNL(); |
403 | 496 | ||
@@ -417,12 +510,8 @@ int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, | |||
417 | return -ENOENT; | 510 | return -ENOENT; |
418 | } | 511 | } |
419 | 512 | ||
420 | old = local->rate_ctrl; | 513 | WARN_ON(local->rate_ctrl); |
421 | local->rate_ctrl = ref; | 514 | local->rate_ctrl = ref; |
422 | if (old) { | ||
423 | rate_control_put(old); | ||
424 | sta_info_flush(local, NULL); | ||
425 | } | ||
426 | 515 | ||
427 | wiphy_debug(local->hw.wiphy, "Selected rate control algorithm '%s'\n", | 516 | wiphy_debug(local->hw.wiphy, "Selected rate control algorithm '%s'\n", |
428 | ref->ops->name); | 517 | ref->ops->name); |
@@ -440,6 +529,6 @@ void rate_control_deinitialize(struct ieee80211_local *local) | |||
440 | return; | 529 | return; |
441 | 530 | ||
442 | local->rate_ctrl = NULL; | 531 | local->rate_ctrl = NULL; |
443 | rate_control_put(ref); | 532 | rate_control_free(ref); |
444 | } | 533 | } |
445 | 534 | ||
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index 168427b0ffdc..8268457bd143 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h | |||
@@ -14,7 +14,6 @@ | |||
14 | #include <linux/netdevice.h> | 14 | #include <linux/netdevice.h> |
15 | #include <linux/skbuff.h> | 15 | #include <linux/skbuff.h> |
16 | #include <linux/types.h> | 16 | #include <linux/types.h> |
17 | #include <linux/kref.h> | ||
18 | #include <net/mac80211.h> | 17 | #include <net/mac80211.h> |
19 | #include "ieee80211_i.h" | 18 | #include "ieee80211_i.h" |
20 | #include "sta_info.h" | 19 | #include "sta_info.h" |
@@ -23,14 +22,11 @@ struct rate_control_ref { | |||
23 | struct ieee80211_local *local; | 22 | struct ieee80211_local *local; |
24 | struct rate_control_ops *ops; | 23 | struct rate_control_ops *ops; |
25 | void *priv; | 24 | void *priv; |
26 | struct kref kref; | ||
27 | }; | 25 | }; |
28 | 26 | ||
29 | void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, | 27 | void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, |
30 | struct sta_info *sta, | 28 | struct sta_info *sta, |
31 | struct ieee80211_tx_rate_control *txrc); | 29 | struct ieee80211_tx_rate_control *txrc); |
32 | struct rate_control_ref *rate_control_get(struct rate_control_ref *ref); | ||
33 | void rate_control_put(struct rate_control_ref *ref); | ||
34 | 30 | ||
35 | static inline void rate_control_tx_status(struct ieee80211_local *local, | 31 | static inline void rate_control_tx_status(struct ieee80211_local *local, |
36 | struct ieee80211_supported_band *sband, | 32 | struct ieee80211_supported_band *sband, |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 5a5e504a8ffb..b5ee0847a7e1 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -1145,19 +1145,15 @@ static void ap_sta_ps_start(struct sta_info *sta) | |||
1145 | 1145 | ||
1146 | static void ap_sta_ps_end(struct sta_info *sta) | 1146 | static void ap_sta_ps_end(struct sta_info *sta) |
1147 | { | 1147 | { |
1148 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
1149 | |||
1150 | atomic_dec(&sdata->bss->num_sta_ps); | ||
1151 | |||
1152 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 1148 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
1153 | printk(KERN_DEBUG "%s: STA %pM aid %d exits power save mode\n", | 1149 | printk(KERN_DEBUG "%s: STA %pM aid %d exits power save mode\n", |
1154 | sdata->name, sta->sta.addr, sta->sta.aid); | 1150 | sta->sdata->name, sta->sta.addr, sta->sta.aid); |
1155 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 1151 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
1156 | 1152 | ||
1157 | if (test_sta_flag(sta, WLAN_STA_PS_DRIVER)) { | 1153 | if (test_sta_flag(sta, WLAN_STA_PS_DRIVER)) { |
1158 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 1154 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
1159 | printk(KERN_DEBUG "%s: STA %pM aid %d driver-ps-blocked\n", | 1155 | printk(KERN_DEBUG "%s: STA %pM aid %d driver-ps-blocked\n", |
1160 | sdata->name, sta->sta.addr, sta->sta.aid); | 1156 | sta->sdata->name, sta->sta.addr, sta->sta.aid); |
1161 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 1157 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
1162 | return; | 1158 | return; |
1163 | } | 1159 | } |
@@ -2180,9 +2176,6 @@ ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx) | |||
2180 | if (rx->sdata->vif.type == NL80211_IFTYPE_AP && | 2176 | if (rx->sdata->vif.type == NL80211_IFTYPE_AP && |
2181 | ieee80211_is_beacon(mgmt->frame_control) && | 2177 | ieee80211_is_beacon(mgmt->frame_control) && |
2182 | !(rx->flags & IEEE80211_RX_BEACON_REPORTED)) { | 2178 | !(rx->flags & IEEE80211_RX_BEACON_REPORTED)) { |
2183 | struct ieee80211_rx_status *status; | ||
2184 | |||
2185 | status = IEEE80211_SKB_RXCB(rx->skb); | ||
2186 | cfg80211_report_obss_beacon(rx->local->hw.wiphy, | 2179 | cfg80211_report_obss_beacon(rx->local->hw.wiphy, |
2187 | rx->skb->data, rx->skb->len, | 2180 | rx->skb->data, rx->skb->len, |
2188 | status->freq, GFP_ATOMIC); | 2181 | status->freq, GFP_ATOMIC); |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index ff11f6bf8266..fa0823892b2d 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -208,10 +208,8 @@ struct sta_info *sta_info_get_by_idx(struct ieee80211_sub_if_data *sdata, | |||
208 | */ | 208 | */ |
209 | void sta_info_free(struct ieee80211_local *local, struct sta_info *sta) | 209 | void sta_info_free(struct ieee80211_local *local, struct sta_info *sta) |
210 | { | 210 | { |
211 | if (sta->rate_ctrl) { | 211 | if (sta->rate_ctrl) |
212 | rate_control_free_sta(sta); | 212 | rate_control_free_sta(sta); |
213 | rate_control_put(sta->rate_ctrl); | ||
214 | } | ||
215 | 213 | ||
216 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 214 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
217 | wiphy_debug(local->hw.wiphy, "Destroyed STA %pM\n", sta->sta.addr); | 215 | wiphy_debug(local->hw.wiphy, "Destroyed STA %pM\n", sta->sta.addr); |
@@ -264,13 +262,11 @@ static int sta_prepare_rate_control(struct ieee80211_local *local, | |||
264 | if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) | 262 | if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) |
265 | return 0; | 263 | return 0; |
266 | 264 | ||
267 | sta->rate_ctrl = rate_control_get(local->rate_ctrl); | 265 | sta->rate_ctrl = local->rate_ctrl; |
268 | sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl, | 266 | sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl, |
269 | &sta->sta, gfp); | 267 | &sta->sta, gfp); |
270 | if (!sta->rate_ctrl_priv) { | 268 | if (!sta->rate_ctrl_priv) |
271 | rate_control_put(sta->rate_ctrl); | ||
272 | return -ENOMEM; | 269 | return -ENOMEM; |
273 | } | ||
274 | 270 | ||
275 | return 0; | 271 | return 0; |
276 | } | 272 | } |
@@ -407,6 +403,8 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU) | |||
407 | sta_info_hash_add(local, sta); | 403 | sta_info_hash_add(local, sta); |
408 | 404 | ||
409 | list_add(&sta->list, &local->sta_list); | 405 | list_add(&sta->list, &local->sta_list); |
406 | |||
407 | set_sta_flag(sta, WLAN_STA_INSERTED); | ||
410 | } else { | 408 | } else { |
411 | sta->dummy = false; | 409 | sta->dummy = false; |
412 | } | 410 | } |
@@ -711,7 +709,7 @@ static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local, | |||
711 | return have_buffered; | 709 | return have_buffered; |
712 | } | 710 | } |
713 | 711 | ||
714 | static int __must_check __sta_info_destroy(struct sta_info *sta) | 712 | int __must_check __sta_info_destroy(struct sta_info *sta) |
715 | { | 713 | { |
716 | struct ieee80211_local *local; | 714 | struct ieee80211_local *local; |
717 | struct ieee80211_sub_if_data *sdata; | 715 | struct ieee80211_sub_if_data *sdata; |
@@ -726,6 +724,8 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
726 | local = sta->local; | 724 | local = sta->local; |
727 | sdata = sta->sdata; | 725 | sdata = sta->sdata; |
728 | 726 | ||
727 | lockdep_assert_held(&local->sta_mtx); | ||
728 | |||
729 | /* | 729 | /* |
730 | * Before removing the station from the driver and | 730 | * Before removing the station from the driver and |
731 | * rate control, it might still start new aggregation | 731 | * rate control, it might still start new aggregation |
@@ -750,25 +750,19 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
750 | 750 | ||
751 | sta->dead = true; | 751 | sta->dead = true; |
752 | 752 | ||
753 | if (test_sta_flag(sta, WLAN_STA_PS_STA) || | ||
754 | test_sta_flag(sta, WLAN_STA_PS_DRIVER)) { | ||
755 | BUG_ON(!sdata->bss); | ||
756 | |||
757 | clear_sta_flag(sta, WLAN_STA_PS_STA); | ||
758 | clear_sta_flag(sta, WLAN_STA_PS_DRIVER); | ||
759 | |||
760 | atomic_dec(&sdata->bss->num_sta_ps); | ||
761 | sta_info_recalc_tim(sta); | ||
762 | } | ||
763 | |||
764 | local->num_sta--; | 753 | local->num_sta--; |
765 | local->sta_generation++; | 754 | local->sta_generation++; |
766 | 755 | ||
767 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 756 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
768 | RCU_INIT_POINTER(sdata->u.vlan.sta, NULL); | 757 | RCU_INIT_POINTER(sdata->u.vlan.sta, NULL); |
769 | 758 | ||
770 | while (sta->sta_state > IEEE80211_STA_NONE) | 759 | while (sta->sta_state > IEEE80211_STA_NONE) { |
771 | sta_info_move_state(sta, sta->sta_state - 1); | 760 | int err = sta_info_move_state(sta, sta->sta_state - 1); |
761 | if (err) { | ||
762 | WARN_ON_ONCE(1); | ||
763 | break; | ||
764 | } | ||
765 | } | ||
772 | 766 | ||
773 | if (sta->uploaded) { | 767 | if (sta->uploaded) { |
774 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 768 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
@@ -787,6 +781,15 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
787 | */ | 781 | */ |
788 | synchronize_rcu(); | 782 | synchronize_rcu(); |
789 | 783 | ||
784 | if (test_sta_flag(sta, WLAN_STA_PS_STA)) { | ||
785 | BUG_ON(!sdata->bss); | ||
786 | |||
787 | clear_sta_flag(sta, WLAN_STA_PS_STA); | ||
788 | |||
789 | atomic_dec(&sdata->bss->num_sta_ps); | ||
790 | sta_info_recalc_tim(sta); | ||
791 | } | ||
792 | |||
790 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { | 793 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { |
791 | local->total_ps_buffered -= skb_queue_len(&sta->ps_tx_buf[ac]); | 794 | local->total_ps_buffered -= skb_queue_len(&sta->ps_tx_buf[ac]); |
792 | __skb_queue_purge(&sta->ps_tx_buf[ac]); | 795 | __skb_queue_purge(&sta->ps_tx_buf[ac]); |
@@ -815,35 +818,20 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
815 | } | 818 | } |
816 | #endif | 819 | #endif |
817 | 820 | ||
818 | /* There could be some memory leaks because of ampdu tx pending queue | 821 | /* |
819 | * not being freed before destroying the station info. | 822 | * Destroy aggregation state here. It would be nice to wait for the |
820 | * | 823 | * driver to finish aggregation stop and then clean up, but for now |
821 | * Make sure that such queues are purged before freeing the station | 824 | * drivers have to handle aggregation stop being requested, followed |
822 | * info. | 825 | * directly by station destruction. |
823 | * TODO: We have to somehow postpone the full destruction | ||
824 | * until the aggregation stop completes. Refer | ||
825 | * http://thread.gmane.org/gmane.linux.kernel.wireless.general/81936 | ||
826 | */ | 826 | */ |
827 | |||
828 | mutex_lock(&sta->ampdu_mlme.mtx); | ||
829 | |||
830 | for (i = 0; i < STA_TID_NUM; i++) { | 827 | for (i = 0; i < STA_TID_NUM; i++) { |
831 | tid_tx = rcu_dereference_protected_tid_tx(sta, i); | 828 | tid_tx = rcu_dereference_raw(sta->ampdu_mlme.tid_tx[i]); |
832 | if (!tid_tx) | 829 | if (!tid_tx) |
833 | continue; | 830 | continue; |
834 | if (skb_queue_len(&tid_tx->pending)) { | 831 | __skb_queue_purge(&tid_tx->pending); |
835 | #ifdef CONFIG_MAC80211_HT_DEBUG | 832 | kfree(tid_tx); |
836 | wiphy_debug(local->hw.wiphy, "TX A-MPDU purging %d " | ||
837 | "packets for tid=%d\n", | ||
838 | skb_queue_len(&tid_tx->pending), i); | ||
839 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
840 | __skb_queue_purge(&tid_tx->pending); | ||
841 | } | ||
842 | kfree_rcu(tid_tx, rcu_head); | ||
843 | } | 833 | } |
844 | 834 | ||
845 | mutex_unlock(&sta->ampdu_mlme.mtx); | ||
846 | |||
847 | sta_info_free(local, sta); | 835 | sta_info_free(local, sta); |
848 | 836 | ||
849 | return 0; | 837 | return 0; |
@@ -1009,9 +997,11 @@ EXPORT_SYMBOL(ieee80211_find_sta); | |||
1009 | static void clear_sta_ps_flags(void *_sta) | 997 | static void clear_sta_ps_flags(void *_sta) |
1010 | { | 998 | { |
1011 | struct sta_info *sta = _sta; | 999 | struct sta_info *sta = _sta; |
1000 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
1012 | 1001 | ||
1013 | clear_sta_flag(sta, WLAN_STA_PS_DRIVER); | 1002 | clear_sta_flag(sta, WLAN_STA_PS_DRIVER); |
1014 | clear_sta_flag(sta, WLAN_STA_PS_STA); | 1003 | if (test_and_clear_sta_flag(sta, WLAN_STA_PS_STA)) |
1004 | atomic_dec(&sdata->bss->num_sta_ps); | ||
1015 | } | 1005 | } |
1016 | 1006 | ||
1017 | /* powersave support code */ | 1007 | /* powersave support code */ |
@@ -1410,8 +1400,8 @@ void ieee80211_sta_set_buffered(struct ieee80211_sta *pubsta, | |||
1410 | } | 1400 | } |
1411 | EXPORT_SYMBOL(ieee80211_sta_set_buffered); | 1401 | EXPORT_SYMBOL(ieee80211_sta_set_buffered); |
1412 | 1402 | ||
1413 | int sta_info_move_state_checked(struct sta_info *sta, | 1403 | int sta_info_move_state(struct sta_info *sta, |
1414 | enum ieee80211_sta_state new_state) | 1404 | enum ieee80211_sta_state new_state) |
1415 | { | 1405 | { |
1416 | might_sleep(); | 1406 | might_sleep(); |
1417 | 1407 | ||
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 6f77f12dc3fc..381de37d2478 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -52,6 +52,7 @@ | |||
52 | * @WLAN_STA_SP: Station is in a service period, so don't try to | 52 | * @WLAN_STA_SP: Station is in a service period, so don't try to |
53 | * reply to other uAPSD trigger frames or PS-Poll. | 53 | * reply to other uAPSD trigger frames or PS-Poll. |
54 | * @WLAN_STA_4ADDR_EVENT: 4-addr event was already sent for this frame. | 54 | * @WLAN_STA_4ADDR_EVENT: 4-addr event was already sent for this frame. |
55 | * @WLAN_STA_INSERTED: This station is inserted into the hash table. | ||
55 | */ | 56 | */ |
56 | enum ieee80211_sta_info_flags { | 57 | enum ieee80211_sta_info_flags { |
57 | WLAN_STA_AUTH, | 58 | WLAN_STA_AUTH, |
@@ -71,6 +72,7 @@ enum ieee80211_sta_info_flags { | |||
71 | WLAN_STA_UAPSD, | 72 | WLAN_STA_UAPSD, |
72 | WLAN_STA_SP, | 73 | WLAN_STA_SP, |
73 | WLAN_STA_4ADDR_EVENT, | 74 | WLAN_STA_4ADDR_EVENT, |
75 | WLAN_STA_INSERTED, | ||
74 | }; | 76 | }; |
75 | 77 | ||
76 | enum ieee80211_sta_state { | 78 | enum ieee80211_sta_state { |
@@ -427,13 +429,17 @@ static inline int test_and_set_sta_flag(struct sta_info *sta, | |||
427 | return test_and_set_bit(flag, &sta->_flags); | 429 | return test_and_set_bit(flag, &sta->_flags); |
428 | } | 430 | } |
429 | 431 | ||
430 | int sta_info_move_state_checked(struct sta_info *sta, | 432 | int sta_info_move_state(struct sta_info *sta, |
431 | enum ieee80211_sta_state new_state); | 433 | enum ieee80211_sta_state new_state); |
432 | 434 | ||
433 | static inline void sta_info_move_state(struct sta_info *sta, | 435 | static inline void sta_info_pre_move_state(struct sta_info *sta, |
434 | enum ieee80211_sta_state new_state) | 436 | enum ieee80211_sta_state new_state) |
435 | { | 437 | { |
436 | int ret = sta_info_move_state_checked(sta, new_state); | 438 | int ret; |
439 | |||
440 | WARN_ON_ONCE(test_sta_flag(sta, WLAN_STA_INSERTED)); | ||
441 | |||
442 | ret = sta_info_move_state(sta, new_state); | ||
437 | WARN_ON_ONCE(ret); | 443 | WARN_ON_ONCE(ret); |
438 | } | 444 | } |
439 | 445 | ||
@@ -544,6 +550,7 @@ int sta_info_insert(struct sta_info *sta); | |||
544 | int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU); | 550 | int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU); |
545 | int sta_info_reinsert(struct sta_info *sta); | 551 | int sta_info_reinsert(struct sta_info *sta); |
546 | 552 | ||
553 | int __must_check __sta_info_destroy(struct sta_info *sta); | ||
547 | int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, | 554 | int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, |
548 | const u8 *addr); | 555 | const u8 *addr); |
549 | int sta_info_destroy_addr_bss(struct ieee80211_sub_if_data *sdata, | 556 | int sta_info_destroy_addr_bss(struct ieee80211_sub_if_data *sdata, |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 30c265c98f73..d67f0b967f8a 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -350,7 +350,6 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
350 | bool send_to_cooked; | 350 | bool send_to_cooked; |
351 | bool acked; | 351 | bool acked; |
352 | struct ieee80211_bar *bar; | 352 | struct ieee80211_bar *bar; |
353 | u16 tid; | ||
354 | int rtap_len; | 353 | int rtap_len; |
355 | 354 | ||
356 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { | 355 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { |
@@ -412,7 +411,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
412 | } | 411 | } |
413 | 412 | ||
414 | if (!acked && ieee80211_is_back_req(fc)) { | 413 | if (!acked && ieee80211_is_back_req(fc)) { |
415 | u16 control; | 414 | u16 tid, control; |
416 | 415 | ||
417 | /* | 416 | /* |
418 | * BAR failed, store the last SSN and retry sending | 417 | * BAR failed, store the last SSN and retry sending |
@@ -516,7 +515,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
516 | 515 | ||
517 | if (ieee80211_is_nullfunc(hdr->frame_control) || | 516 | if (ieee80211_is_nullfunc(hdr->frame_control) || |
518 | ieee80211_is_qos_nullfunc(hdr->frame_control)) { | 517 | ieee80211_is_qos_nullfunc(hdr->frame_control)) { |
519 | bool acked = info->flags & IEEE80211_TX_STAT_ACK; | 518 | acked = info->flags & IEEE80211_TX_STAT_ACK; |
519 | |||
520 | cfg80211_probe_status(skb->dev, hdr->addr1, | 520 | cfg80211_probe_status(skb->dev, hdr->addr1, |
521 | cookie, acked, GFP_ATOMIC); | 521 | cookie, acked, GFP_ATOMIC); |
522 | } else { | 522 | } else { |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index e05667cd5e76..1be0ca2b5936 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -635,6 +635,9 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | |||
635 | txrc.max_rate_idx = -1; | 635 | txrc.max_rate_idx = -1; |
636 | else | 636 | else |
637 | txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1; | 637 | txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1; |
638 | memcpy(txrc.rate_idx_mcs_mask, | ||
639 | tx->sdata->rc_rateidx_mcs_mask[tx->channel->band], | ||
640 | sizeof(txrc.rate_idx_mcs_mask)); | ||
638 | txrc.bss = (tx->sdata->vif.type == NL80211_IFTYPE_AP || | 641 | txrc.bss = (tx->sdata->vif.type == NL80211_IFTYPE_AP || |
639 | tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT || | 642 | tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT || |
640 | tx->sdata->vif.type == NL80211_IFTYPE_ADHOC); | 643 | tx->sdata->vif.type == NL80211_IFTYPE_ADHOC); |
@@ -2431,6 +2434,8 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2431 | txrc.max_rate_idx = -1; | 2434 | txrc.max_rate_idx = -1; |
2432 | else | 2435 | else |
2433 | txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1; | 2436 | txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1; |
2437 | memcpy(txrc.rate_idx_mcs_mask, sdata->rc_rateidx_mcs_mask[band], | ||
2438 | sizeof(txrc.rate_idx_mcs_mask)); | ||
2434 | txrc.bss = true; | 2439 | txrc.bss = true; |
2435 | rate_control_get_rate(sdata, NULL, &txrc); | 2440 | rate_control_get_rate(sdata, NULL, &txrc); |
2436 | 2441 | ||
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 9919892575f4..d82d886d0867 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -862,8 +862,8 @@ u32 ieee80211_mandatory_rates(struct ieee80211_local *local, | |||
862 | 862 | ||
863 | void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | 863 | void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, |
864 | u16 transaction, u16 auth_alg, | 864 | u16 transaction, u16 auth_alg, |
865 | u8 *extra, size_t extra_len, const u8 *bssid, | 865 | u8 *extra, size_t extra_len, const u8 *da, |
866 | const u8 *key, u8 key_len, u8 key_idx) | 866 | const u8 *bssid, const u8 *key, u8 key_len, u8 key_idx) |
867 | { | 867 | { |
868 | struct ieee80211_local *local = sdata->local; | 868 | struct ieee80211_local *local = sdata->local; |
869 | struct sk_buff *skb; | 869 | struct sk_buff *skb; |
@@ -881,7 +881,7 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | |||
881 | memset(mgmt, 0, 24 + 6); | 881 | memset(mgmt, 0, 24 + 6); |
882 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 882 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
883 | IEEE80211_STYPE_AUTH); | 883 | IEEE80211_STYPE_AUTH); |
884 | memcpy(mgmt->da, bssid, ETH_ALEN); | 884 | memcpy(mgmt->da, da, ETH_ALEN); |
885 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); | 885 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
886 | memcpy(mgmt->bssid, bssid, ETH_ALEN); | 886 | memcpy(mgmt->bssid, bssid, ETH_ALEN); |
887 | mgmt->u.auth.auth_alg = cpu_to_le16(auth_alg); | 887 | mgmt->u.auth.auth_alg = cpu_to_le16(auth_alg); |
@@ -1272,6 +1272,21 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1272 | ieee80211_recalc_ps(local, -1); | 1272 | ieee80211_recalc_ps(local, -1); |
1273 | 1273 | ||
1274 | /* | 1274 | /* |
1275 | * The sta might be in psm against the ap (e.g. because | ||
1276 | * this was the state before a hw restart), so we | ||
1277 | * explicitly send a null packet in order to make sure | ||
1278 | * it'll sync against the ap (and get out of psm). | ||
1279 | */ | ||
1280 | if (!(local->hw.conf.flags & IEEE80211_CONF_PS)) { | ||
1281 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
1282 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | ||
1283 | continue; | ||
1284 | |||
1285 | ieee80211_send_nullfunc(local, sdata, 0); | ||
1286 | } | ||
1287 | } | ||
1288 | |||
1289 | /* | ||
1275 | * Clear the WLAN_STA_BLOCK_BA flag so new aggregation | 1290 | * Clear the WLAN_STA_BLOCK_BA flag so new aggregation |
1276 | * sessions can be established after a resume. | 1291 | * sessions can be established after a resume. |
1277 | * | 1292 | * |
diff --git a/net/mac80211/work.c b/net/mac80211/work.c index c6dd01a05291..0a1a176fbe91 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c | |||
@@ -480,7 +480,8 @@ ieee80211_authenticate(struct ieee80211_work *wk) | |||
480 | sdata->name, wk->filter_ta, wk->probe_auth.tries); | 480 | sdata->name, wk->filter_ta, wk->probe_auth.tries); |
481 | 481 | ||
482 | ieee80211_send_auth(sdata, 1, wk->probe_auth.algorithm, wk->ie, | 482 | ieee80211_send_auth(sdata, 1, wk->probe_auth.algorithm, wk->ie, |
483 | wk->ie_len, wk->filter_ta, NULL, 0, 0); | 483 | wk->ie_len, wk->filter_ta, wk->filter_ta, NULL, 0, |
484 | 0); | ||
484 | wk->probe_auth.transaction = 2; | 485 | wk->probe_auth.transaction = 2; |
485 | 486 | ||
486 | wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; | 487 | wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; |
@@ -598,7 +599,7 @@ static void ieee80211_auth_challenge(struct ieee80211_work *wk, | |||
598 | return; | 599 | return; |
599 | ieee80211_send_auth(sdata, 3, wk->probe_auth.algorithm, | 600 | ieee80211_send_auth(sdata, 3, wk->probe_auth.algorithm, |
600 | elems.challenge - 2, elems.challenge_len + 2, | 601 | elems.challenge - 2, elems.challenge_len + 2, |
601 | wk->filter_ta, wk->probe_auth.key, | 602 | wk->filter_ta, wk->filter_ta, wk->probe_auth.key, |
602 | wk->probe_auth.key_len, wk->probe_auth.key_idx); | 603 | wk->probe_auth.key_len, wk->probe_auth.key_idx); |
603 | wk->probe_auth.transaction = 4; | 604 | wk->probe_auth.transaction = 4; |
604 | } | 605 | } |
diff --git a/net/nfc/core.c b/net/nfc/core.c index 3ddf6e698df0..6089aca67b14 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c | |||
@@ -431,15 +431,10 @@ EXPORT_SYMBOL(nfc_alloc_recv_skb); | |||
431 | int nfc_targets_found(struct nfc_dev *dev, struct nfc_target *targets, | 431 | int nfc_targets_found(struct nfc_dev *dev, struct nfc_target *targets, |
432 | int n_targets) | 432 | int n_targets) |
433 | { | 433 | { |
434 | int i; | ||
435 | |||
436 | pr_debug("dev_name=%s n_targets=%d\n", dev_name(&dev->dev), n_targets); | 434 | pr_debug("dev_name=%s n_targets=%d\n", dev_name(&dev->dev), n_targets); |
437 | 435 | ||
438 | dev->polling = false; | 436 | dev->polling = false; |
439 | 437 | ||
440 | for (i = 0; i < n_targets; i++) | ||
441 | targets[i].idx = dev->target_idx++; | ||
442 | |||
443 | spin_lock_bh(&dev->targets_lock); | 438 | spin_lock_bh(&dev->targets_lock); |
444 | 439 | ||
445 | dev->targets_generation++; | 440 | dev->targets_generation++; |
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c index 7650139a1a05..a47e90c7d9d1 100644 --- a/net/nfc/nci/core.c +++ b/net/nfc/nci/core.c | |||
@@ -216,6 +216,39 @@ static void nci_rf_discover_req(struct nci_dev *ndev, unsigned long opt) | |||
216 | &cmd); | 216 | &cmd); |
217 | } | 217 | } |
218 | 218 | ||
219 | struct nci_rf_discover_select_param { | ||
220 | __u8 rf_discovery_id; | ||
221 | __u8 rf_protocol; | ||
222 | }; | ||
223 | |||
224 | static void nci_rf_discover_select_req(struct nci_dev *ndev, unsigned long opt) | ||
225 | { | ||
226 | struct nci_rf_discover_select_param *param = | ||
227 | (struct nci_rf_discover_select_param *)opt; | ||
228 | struct nci_rf_discover_select_cmd cmd; | ||
229 | |||
230 | cmd.rf_discovery_id = param->rf_discovery_id; | ||
231 | cmd.rf_protocol = param->rf_protocol; | ||
232 | |||
233 | switch (cmd.rf_protocol) { | ||
234 | case NCI_RF_PROTOCOL_ISO_DEP: | ||
235 | cmd.rf_interface = NCI_RF_INTERFACE_ISO_DEP; | ||
236 | break; | ||
237 | |||
238 | case NCI_RF_PROTOCOL_NFC_DEP: | ||
239 | cmd.rf_interface = NCI_RF_INTERFACE_NFC_DEP; | ||
240 | break; | ||
241 | |||
242 | default: | ||
243 | cmd.rf_interface = NCI_RF_INTERFACE_FRAME; | ||
244 | break; | ||
245 | } | ||
246 | |||
247 | nci_send_cmd(ndev, NCI_OP_RF_DISCOVER_SELECT_CMD, | ||
248 | sizeof(struct nci_rf_discover_select_cmd), | ||
249 | &cmd); | ||
250 | } | ||
251 | |||
219 | static void nci_rf_deactivate_req(struct nci_dev *ndev, unsigned long opt) | 252 | static void nci_rf_deactivate_req(struct nci_dev *ndev, unsigned long opt) |
220 | { | 253 | { |
221 | struct nci_rf_deactivate_cmd cmd; | 254 | struct nci_rf_deactivate_cmd cmd; |
@@ -264,6 +297,8 @@ static int nci_open_device(struct nci_dev *ndev) | |||
264 | 297 | ||
265 | if (!rc) { | 298 | if (!rc) { |
266 | set_bit(NCI_UP, &ndev->flags); | 299 | set_bit(NCI_UP, &ndev->flags); |
300 | nci_clear_target_list(ndev); | ||
301 | atomic_set(&ndev->state, NCI_IDLE); | ||
267 | } else { | 302 | } else { |
268 | /* Init failed, cleanup */ | 303 | /* Init failed, cleanup */ |
269 | skb_queue_purge(&ndev->cmd_q); | 304 | skb_queue_purge(&ndev->cmd_q); |
@@ -286,6 +321,7 @@ static int nci_close_device(struct nci_dev *ndev) | |||
286 | 321 | ||
287 | if (!test_and_clear_bit(NCI_UP, &ndev->flags)) { | 322 | if (!test_and_clear_bit(NCI_UP, &ndev->flags)) { |
288 | del_timer_sync(&ndev->cmd_timer); | 323 | del_timer_sync(&ndev->cmd_timer); |
324 | del_timer_sync(&ndev->data_timer); | ||
289 | mutex_unlock(&ndev->req_lock); | 325 | mutex_unlock(&ndev->req_lock); |
290 | return 0; | 326 | return 0; |
291 | } | 327 | } |
@@ -331,6 +367,15 @@ static void nci_cmd_timer(unsigned long arg) | |||
331 | queue_work(ndev->cmd_wq, &ndev->cmd_work); | 367 | queue_work(ndev->cmd_wq, &ndev->cmd_work); |
332 | } | 368 | } |
333 | 369 | ||
370 | /* NCI data exchange timer function */ | ||
371 | static void nci_data_timer(unsigned long arg) | ||
372 | { | ||
373 | struct nci_dev *ndev = (void *) arg; | ||
374 | |||
375 | set_bit(NCI_DATA_EXCHANGE_TO, &ndev->flags); | ||
376 | queue_work(ndev->rx_wq, &ndev->rx_work); | ||
377 | } | ||
378 | |||
334 | static int nci_dev_up(struct nfc_dev *nfc_dev) | 379 | static int nci_dev_up(struct nfc_dev *nfc_dev) |
335 | { | 380 | { |
336 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); | 381 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); |
@@ -350,7 +395,8 @@ static int nci_start_poll(struct nfc_dev *nfc_dev, __u32 protocols) | |||
350 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); | 395 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); |
351 | int rc; | 396 | int rc; |
352 | 397 | ||
353 | if (test_bit(NCI_DISCOVERY, &ndev->flags)) { | 398 | if ((atomic_read(&ndev->state) == NCI_DISCOVERY) || |
399 | (atomic_read(&ndev->state) == NCI_W4_ALL_DISCOVERIES)) { | ||
354 | pr_err("unable to start poll, since poll is already active\n"); | 400 | pr_err("unable to start poll, since poll is already active\n"); |
355 | return -EBUSY; | 401 | return -EBUSY; |
356 | } | 402 | } |
@@ -360,8 +406,9 @@ static int nci_start_poll(struct nfc_dev *nfc_dev, __u32 protocols) | |||
360 | return -EBUSY; | 406 | return -EBUSY; |
361 | } | 407 | } |
362 | 408 | ||
363 | if (test_bit(NCI_POLL_ACTIVE, &ndev->flags)) { | 409 | if ((atomic_read(&ndev->state) == NCI_W4_HOST_SELECT) || |
364 | pr_debug("target is active, implicitly deactivate...\n"); | 410 | (atomic_read(&ndev->state) == NCI_POLL_ACTIVE)) { |
411 | pr_debug("target active or w4 select, implicitly deactivate\n"); | ||
365 | 412 | ||
366 | rc = nci_request(ndev, nci_rf_deactivate_req, 0, | 413 | rc = nci_request(ndev, nci_rf_deactivate_req, 0, |
367 | msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT)); | 414 | msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT)); |
@@ -382,7 +429,8 @@ static void nci_stop_poll(struct nfc_dev *nfc_dev) | |||
382 | { | 429 | { |
383 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); | 430 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); |
384 | 431 | ||
385 | if (!test_bit(NCI_DISCOVERY, &ndev->flags)) { | 432 | if ((atomic_read(&ndev->state) != NCI_DISCOVERY) && |
433 | (atomic_read(&ndev->state) != NCI_W4_ALL_DISCOVERIES)) { | ||
386 | pr_err("unable to stop poll, since poll is not active\n"); | 434 | pr_err("unable to stop poll, since poll is not active\n"); |
387 | return; | 435 | return; |
388 | } | 436 | } |
@@ -395,10 +443,15 @@ static int nci_activate_target(struct nfc_dev *nfc_dev, __u32 target_idx, | |||
395 | __u32 protocol) | 443 | __u32 protocol) |
396 | { | 444 | { |
397 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); | 445 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); |
446 | struct nci_rf_discover_select_param param; | ||
447 | struct nfc_target *target = NULL; | ||
448 | int i; | ||
449 | int rc = 0; | ||
398 | 450 | ||
399 | pr_debug("target_idx %d, protocol 0x%x\n", target_idx, protocol); | 451 | pr_debug("target_idx %d, protocol 0x%x\n", target_idx, protocol); |
400 | 452 | ||
401 | if (!test_bit(NCI_POLL_ACTIVE, &ndev->flags)) { | 453 | if ((atomic_read(&ndev->state) != NCI_W4_HOST_SELECT) && |
454 | (atomic_read(&ndev->state) != NCI_POLL_ACTIVE)) { | ||
402 | pr_err("there is no available target to activate\n"); | 455 | pr_err("there is no available target to activate\n"); |
403 | return -EINVAL; | 456 | return -EINVAL; |
404 | } | 457 | } |
@@ -408,16 +461,47 @@ static int nci_activate_target(struct nfc_dev *nfc_dev, __u32 target_idx, | |||
408 | return -EBUSY; | 461 | return -EBUSY; |
409 | } | 462 | } |
410 | 463 | ||
411 | if (!(ndev->target_available_prots & (1 << protocol))) { | 464 | for (i = 0; i < ndev->n_targets; i++) { |
465 | if (ndev->targets[i].idx == target_idx) { | ||
466 | target = &ndev->targets[i]; | ||
467 | break; | ||
468 | } | ||
469 | } | ||
470 | |||
471 | if (!target) { | ||
472 | pr_err("unable to find the selected target\n"); | ||
473 | return -EINVAL; | ||
474 | } | ||
475 | |||
476 | if (!(target->supported_protocols & (1 << protocol))) { | ||
412 | pr_err("target does not support the requested protocol 0x%x\n", | 477 | pr_err("target does not support the requested protocol 0x%x\n", |
413 | protocol); | 478 | protocol); |
414 | return -EINVAL; | 479 | return -EINVAL; |
415 | } | 480 | } |
416 | 481 | ||
417 | ndev->target_active_prot = protocol; | 482 | if (atomic_read(&ndev->state) == NCI_W4_HOST_SELECT) { |
418 | ndev->target_available_prots = 0; | 483 | param.rf_discovery_id = target->idx; |
419 | 484 | ||
420 | return 0; | 485 | if (protocol == NFC_PROTO_JEWEL) |
486 | param.rf_protocol = NCI_RF_PROTOCOL_T1T; | ||
487 | else if (protocol == NFC_PROTO_MIFARE) | ||
488 | param.rf_protocol = NCI_RF_PROTOCOL_T2T; | ||
489 | else if (protocol == NFC_PROTO_FELICA) | ||
490 | param.rf_protocol = NCI_RF_PROTOCOL_T3T; | ||
491 | else if (protocol == NFC_PROTO_ISO14443) | ||
492 | param.rf_protocol = NCI_RF_PROTOCOL_ISO_DEP; | ||
493 | else | ||
494 | param.rf_protocol = NCI_RF_PROTOCOL_NFC_DEP; | ||
495 | |||
496 | rc = nci_request(ndev, nci_rf_discover_select_req, | ||
497 | (unsigned long)¶m, | ||
498 | msecs_to_jiffies(NCI_RF_DISC_SELECT_TIMEOUT)); | ||
499 | } | ||
500 | |||
501 | if (!rc) | ||
502 | ndev->target_active_prot = protocol; | ||
503 | |||
504 | return rc; | ||
421 | } | 505 | } |
422 | 506 | ||
423 | static void nci_deactivate_target(struct nfc_dev *nfc_dev, __u32 target_idx) | 507 | static void nci_deactivate_target(struct nfc_dev *nfc_dev, __u32 target_idx) |
@@ -433,7 +517,7 @@ static void nci_deactivate_target(struct nfc_dev *nfc_dev, __u32 target_idx) | |||
433 | 517 | ||
434 | ndev->target_active_prot = 0; | 518 | ndev->target_active_prot = 0; |
435 | 519 | ||
436 | if (test_bit(NCI_POLL_ACTIVE, &ndev->flags)) { | 520 | if (atomic_read(&ndev->state) == NCI_POLL_ACTIVE) { |
437 | nci_request(ndev, nci_rf_deactivate_req, 0, | 521 | nci_request(ndev, nci_rf_deactivate_req, 0, |
438 | msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT)); | 522 | msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT)); |
439 | } | 523 | } |
@@ -585,6 +669,8 @@ int nci_register_device(struct nci_dev *ndev) | |||
585 | 669 | ||
586 | setup_timer(&ndev->cmd_timer, nci_cmd_timer, | 670 | setup_timer(&ndev->cmd_timer, nci_cmd_timer, |
587 | (unsigned long) ndev); | 671 | (unsigned long) ndev); |
672 | setup_timer(&ndev->data_timer, nci_data_timer, | ||
673 | (unsigned long) ndev); | ||
588 | 674 | ||
589 | mutex_init(&ndev->req_lock); | 675 | mutex_init(&ndev->req_lock); |
590 | 676 | ||
@@ -722,6 +808,9 @@ static void nci_tx_work(struct work_struct *work) | |||
722 | nci_plen(skb->data)); | 808 | nci_plen(skb->data)); |
723 | 809 | ||
724 | nci_send_frame(skb); | 810 | nci_send_frame(skb); |
811 | |||
812 | mod_timer(&ndev->data_timer, | ||
813 | jiffies + msecs_to_jiffies(NCI_DATA_TIMEOUT)); | ||
725 | } | 814 | } |
726 | } | 815 | } |
727 | 816 | ||
@@ -753,6 +842,15 @@ static void nci_rx_work(struct work_struct *work) | |||
753 | break; | 842 | break; |
754 | } | 843 | } |
755 | } | 844 | } |
845 | |||
846 | /* check if a data exchange timout has occurred */ | ||
847 | if (test_bit(NCI_DATA_EXCHANGE_TO, &ndev->flags)) { | ||
848 | /* complete the data exchange transaction, if exists */ | ||
849 | if (test_bit(NCI_DATA_EXCHANGE, &ndev->flags)) | ||
850 | nci_data_exchange_complete(ndev, NULL, -ETIMEDOUT); | ||
851 | |||
852 | clear_bit(NCI_DATA_EXCHANGE_TO, &ndev->flags); | ||
853 | } | ||
756 | } | 854 | } |
757 | 855 | ||
758 | /* ----- NCI TX CMD worker thread ----- */ | 856 | /* ----- NCI TX CMD worker thread ----- */ |
diff --git a/net/nfc/nci/data.c b/net/nfc/nci/data.c index e5756b30e602..7880ae924d5e 100644 --- a/net/nfc/nci/data.c +++ b/net/nfc/nci/data.c | |||
@@ -44,6 +44,10 @@ void nci_data_exchange_complete(struct nci_dev *ndev, | |||
44 | 44 | ||
45 | pr_debug("len %d, err %d\n", skb ? skb->len : 0, err); | 45 | pr_debug("len %d, err %d\n", skb ? skb->len : 0, err); |
46 | 46 | ||
47 | /* data exchange is complete, stop the data timer */ | ||
48 | del_timer_sync(&ndev->data_timer); | ||
49 | clear_bit(NCI_DATA_EXCHANGE_TO, &ndev->flags); | ||
50 | |||
47 | if (cb) { | 51 | if (cb) { |
48 | ndev->data_exchange_cb = NULL; | 52 | ndev->data_exchange_cb = NULL; |
49 | ndev->data_exchange_cb_context = 0; | 53 | ndev->data_exchange_cb_context = 0; |
diff --git a/net/nfc/nci/ntf.c b/net/nfc/nci/ntf.c index b16a8dc2afbe..03e7b4626a3e 100644 --- a/net/nfc/nci/ntf.c +++ b/net/nfc/nci/ntf.c | |||
@@ -71,6 +71,20 @@ static void nci_core_conn_credits_ntf_packet(struct nci_dev *ndev, | |||
71 | queue_work(ndev->tx_wq, &ndev->tx_work); | 71 | queue_work(ndev->tx_wq, &ndev->tx_work); |
72 | } | 72 | } |
73 | 73 | ||
74 | static void nci_core_generic_error_ntf_packet(struct nci_dev *ndev, | ||
75 | struct sk_buff *skb) | ||
76 | { | ||
77 | __u8 status = skb->data[0]; | ||
78 | |||
79 | pr_debug("status 0x%x\n", status); | ||
80 | |||
81 | if (atomic_read(&ndev->state) == NCI_W4_HOST_SELECT) { | ||
82 | /* Activation failed, so complete the request | ||
83 | (the state remains the same) */ | ||
84 | nci_req_complete(ndev, status); | ||
85 | } | ||
86 | } | ||
87 | |||
74 | static void nci_core_conn_intf_error_ntf_packet(struct nci_dev *ndev, | 88 | static void nci_core_conn_intf_error_ntf_packet(struct nci_dev *ndev, |
75 | struct sk_buff *skb) | 89 | struct sk_buff *skb) |
76 | { | 90 | { |
@@ -86,12 +100,9 @@ static void nci_core_conn_intf_error_ntf_packet(struct nci_dev *ndev, | |||
86 | } | 100 | } |
87 | 101 | ||
88 | static __u8 *nci_extract_rf_params_nfca_passive_poll(struct nci_dev *ndev, | 102 | static __u8 *nci_extract_rf_params_nfca_passive_poll(struct nci_dev *ndev, |
89 | struct nci_rf_intf_activated_ntf *ntf, __u8 *data) | 103 | struct rf_tech_specific_params_nfca_poll *nfca_poll, |
104 | __u8 *data) | ||
90 | { | 105 | { |
91 | struct rf_tech_specific_params_nfca_poll *nfca_poll; | ||
92 | |||
93 | nfca_poll = &ntf->rf_tech_specific_params.nfca_poll; | ||
94 | |||
95 | nfca_poll->sens_res = __le16_to_cpu(*((__u16 *)data)); | 106 | nfca_poll->sens_res = __le16_to_cpu(*((__u16 *)data)); |
96 | data += 2; | 107 | data += 2; |
97 | 108 | ||
@@ -115,15 +126,213 @@ static __u8 *nci_extract_rf_params_nfca_passive_poll(struct nci_dev *ndev, | |||
115 | return data; | 126 | return data; |
116 | } | 127 | } |
117 | 128 | ||
129 | static __u8 *nci_extract_rf_params_nfcb_passive_poll(struct nci_dev *ndev, | ||
130 | struct rf_tech_specific_params_nfcb_poll *nfcb_poll, | ||
131 | __u8 *data) | ||
132 | { | ||
133 | nfcb_poll->sensb_res_len = *data++; | ||
134 | |||
135 | pr_debug("sensb_res_len %d\n", nfcb_poll->sensb_res_len); | ||
136 | |||
137 | memcpy(nfcb_poll->sensb_res, data, nfcb_poll->sensb_res_len); | ||
138 | data += nfcb_poll->sensb_res_len; | ||
139 | |||
140 | return data; | ||
141 | } | ||
142 | |||
143 | static __u8 *nci_extract_rf_params_nfcf_passive_poll(struct nci_dev *ndev, | ||
144 | struct rf_tech_specific_params_nfcf_poll *nfcf_poll, | ||
145 | __u8 *data) | ||
146 | { | ||
147 | nfcf_poll->bit_rate = *data++; | ||
148 | nfcf_poll->sensf_res_len = *data++; | ||
149 | |||
150 | pr_debug("bit_rate %d, sensf_res_len %d\n", | ||
151 | nfcf_poll->bit_rate, nfcf_poll->sensf_res_len); | ||
152 | |||
153 | memcpy(nfcf_poll->sensf_res, data, nfcf_poll->sensf_res_len); | ||
154 | data += nfcf_poll->sensf_res_len; | ||
155 | |||
156 | return data; | ||
157 | } | ||
158 | |||
159 | static int nci_add_new_protocol(struct nci_dev *ndev, | ||
160 | struct nfc_target *target, | ||
161 | __u8 rf_protocol, | ||
162 | __u8 rf_tech_and_mode, | ||
163 | void *params) | ||
164 | { | ||
165 | struct rf_tech_specific_params_nfca_poll *nfca_poll; | ||
166 | struct rf_tech_specific_params_nfcb_poll *nfcb_poll; | ||
167 | struct rf_tech_specific_params_nfcf_poll *nfcf_poll; | ||
168 | __u32 protocol; | ||
169 | |||
170 | if (rf_protocol == NCI_RF_PROTOCOL_T2T) | ||
171 | protocol = NFC_PROTO_MIFARE_MASK; | ||
172 | else if (rf_protocol == NCI_RF_PROTOCOL_ISO_DEP) | ||
173 | protocol = NFC_PROTO_ISO14443_MASK; | ||
174 | else if (rf_protocol == NCI_RF_PROTOCOL_T3T) | ||
175 | protocol = NFC_PROTO_FELICA_MASK; | ||
176 | else | ||
177 | protocol = 0; | ||
178 | |||
179 | if (!(protocol & ndev->poll_prots)) { | ||
180 | pr_err("the target found does not have the desired protocol\n"); | ||
181 | return -EPROTO; | ||
182 | } | ||
183 | |||
184 | if (rf_tech_and_mode == NCI_NFC_A_PASSIVE_POLL_MODE) { | ||
185 | nfca_poll = (struct rf_tech_specific_params_nfca_poll *)params; | ||
186 | |||
187 | target->sens_res = nfca_poll->sens_res; | ||
188 | target->sel_res = nfca_poll->sel_res; | ||
189 | target->nfcid1_len = nfca_poll->nfcid1_len; | ||
190 | if (target->nfcid1_len > 0) { | ||
191 | memcpy(target->nfcid1, nfca_poll->nfcid1, | ||
192 | target->nfcid1_len); | ||
193 | } | ||
194 | } else if (rf_tech_and_mode == NCI_NFC_B_PASSIVE_POLL_MODE) { | ||
195 | nfcb_poll = (struct rf_tech_specific_params_nfcb_poll *)params; | ||
196 | |||
197 | target->sensb_res_len = nfcb_poll->sensb_res_len; | ||
198 | if (target->sensb_res_len > 0) { | ||
199 | memcpy(target->sensb_res, nfcb_poll->sensb_res, | ||
200 | target->sensb_res_len); | ||
201 | } | ||
202 | } else if (rf_tech_and_mode == NCI_NFC_F_PASSIVE_POLL_MODE) { | ||
203 | nfcf_poll = (struct rf_tech_specific_params_nfcf_poll *)params; | ||
204 | |||
205 | target->sensf_res_len = nfcf_poll->sensf_res_len; | ||
206 | if (target->sensf_res_len > 0) { | ||
207 | memcpy(target->sensf_res, nfcf_poll->sensf_res, | ||
208 | target->sensf_res_len); | ||
209 | } | ||
210 | } else { | ||
211 | pr_err("unsupported rf_tech_and_mode 0x%x\n", rf_tech_and_mode); | ||
212 | return -EPROTO; | ||
213 | } | ||
214 | |||
215 | target->supported_protocols |= protocol; | ||
216 | |||
217 | pr_debug("protocol 0x%x\n", protocol); | ||
218 | |||
219 | return 0; | ||
220 | } | ||
221 | |||
222 | static void nci_add_new_target(struct nci_dev *ndev, | ||
223 | struct nci_rf_discover_ntf *ntf) | ||
224 | { | ||
225 | struct nfc_target *target; | ||
226 | int i, rc; | ||
227 | |||
228 | for (i = 0; i < ndev->n_targets; i++) { | ||
229 | target = &ndev->targets[i]; | ||
230 | if (target->idx == ntf->rf_discovery_id) { | ||
231 | /* This target already exists, add the new protocol */ | ||
232 | nci_add_new_protocol(ndev, target, ntf->rf_protocol, | ||
233 | ntf->rf_tech_and_mode, | ||
234 | &ntf->rf_tech_specific_params); | ||
235 | return; | ||
236 | } | ||
237 | } | ||
238 | |||
239 | /* This is a new target, check if we've enough room */ | ||
240 | if (ndev->n_targets == NCI_MAX_DISCOVERED_TARGETS) { | ||
241 | pr_debug("not enough room, ignoring new target...\n"); | ||
242 | return; | ||
243 | } | ||
244 | |||
245 | target = &ndev->targets[ndev->n_targets]; | ||
246 | |||
247 | rc = nci_add_new_protocol(ndev, target, ntf->rf_protocol, | ||
248 | ntf->rf_tech_and_mode, | ||
249 | &ntf->rf_tech_specific_params); | ||
250 | if (!rc) { | ||
251 | target->idx = ntf->rf_discovery_id; | ||
252 | ndev->n_targets++; | ||
253 | |||
254 | pr_debug("target_idx %d, n_targets %d\n", target->idx, | ||
255 | ndev->n_targets); | ||
256 | } | ||
257 | } | ||
258 | |||
259 | void nci_clear_target_list(struct nci_dev *ndev) | ||
260 | { | ||
261 | memset(ndev->targets, 0, | ||
262 | (sizeof(struct nfc_target)*NCI_MAX_DISCOVERED_TARGETS)); | ||
263 | |||
264 | ndev->n_targets = 0; | ||
265 | } | ||
266 | |||
267 | static void nci_rf_discover_ntf_packet(struct nci_dev *ndev, | ||
268 | struct sk_buff *skb) | ||
269 | { | ||
270 | struct nci_rf_discover_ntf ntf; | ||
271 | __u8 *data = skb->data; | ||
272 | bool add_target = true; | ||
273 | |||
274 | ntf.rf_discovery_id = *data++; | ||
275 | ntf.rf_protocol = *data++; | ||
276 | ntf.rf_tech_and_mode = *data++; | ||
277 | ntf.rf_tech_specific_params_len = *data++; | ||
278 | |||
279 | pr_debug("rf_discovery_id %d\n", ntf.rf_discovery_id); | ||
280 | pr_debug("rf_protocol 0x%x\n", ntf.rf_protocol); | ||
281 | pr_debug("rf_tech_and_mode 0x%x\n", ntf.rf_tech_and_mode); | ||
282 | pr_debug("rf_tech_specific_params_len %d\n", | ||
283 | ntf.rf_tech_specific_params_len); | ||
284 | |||
285 | if (ntf.rf_tech_specific_params_len > 0) { | ||
286 | switch (ntf.rf_tech_and_mode) { | ||
287 | case NCI_NFC_A_PASSIVE_POLL_MODE: | ||
288 | data = nci_extract_rf_params_nfca_passive_poll(ndev, | ||
289 | &(ntf.rf_tech_specific_params.nfca_poll), data); | ||
290 | break; | ||
291 | |||
292 | case NCI_NFC_B_PASSIVE_POLL_MODE: | ||
293 | data = nci_extract_rf_params_nfcb_passive_poll(ndev, | ||
294 | &(ntf.rf_tech_specific_params.nfcb_poll), data); | ||
295 | break; | ||
296 | |||
297 | case NCI_NFC_F_PASSIVE_POLL_MODE: | ||
298 | data = nci_extract_rf_params_nfcf_passive_poll(ndev, | ||
299 | &(ntf.rf_tech_specific_params.nfcf_poll), data); | ||
300 | break; | ||
301 | |||
302 | default: | ||
303 | pr_err("unsupported rf_tech_and_mode 0x%x\n", | ||
304 | ntf.rf_tech_and_mode); | ||
305 | data += ntf.rf_tech_specific_params_len; | ||
306 | add_target = false; | ||
307 | } | ||
308 | } | ||
309 | |||
310 | ntf.ntf_type = *data++; | ||
311 | pr_debug("ntf_type %d\n", ntf.ntf_type); | ||
312 | |||
313 | if (add_target == true) | ||
314 | nci_add_new_target(ndev, &ntf); | ||
315 | |||
316 | if (ntf.ntf_type == NCI_DISCOVER_NTF_TYPE_MORE) { | ||
317 | atomic_set(&ndev->state, NCI_W4_ALL_DISCOVERIES); | ||
318 | } else { | ||
319 | atomic_set(&ndev->state, NCI_W4_HOST_SELECT); | ||
320 | nfc_targets_found(ndev->nfc_dev, ndev->targets, | ||
321 | ndev->n_targets); | ||
322 | } | ||
323 | } | ||
324 | |||
118 | static int nci_extract_activation_params_iso_dep(struct nci_dev *ndev, | 325 | static int nci_extract_activation_params_iso_dep(struct nci_dev *ndev, |
119 | struct nci_rf_intf_activated_ntf *ntf, __u8 *data) | 326 | struct nci_rf_intf_activated_ntf *ntf, __u8 *data) |
120 | { | 327 | { |
121 | struct activation_params_nfca_poll_iso_dep *nfca_poll; | 328 | struct activation_params_nfca_poll_iso_dep *nfca_poll; |
329 | struct activation_params_nfcb_poll_iso_dep *nfcb_poll; | ||
122 | 330 | ||
123 | switch (ntf->activation_rf_tech_and_mode) { | 331 | switch (ntf->activation_rf_tech_and_mode) { |
124 | case NCI_NFC_A_PASSIVE_POLL_MODE: | 332 | case NCI_NFC_A_PASSIVE_POLL_MODE: |
125 | nfca_poll = &ntf->activation_params.nfca_poll_iso_dep; | 333 | nfca_poll = &ntf->activation_params.nfca_poll_iso_dep; |
126 | nfca_poll->rats_res_len = *data++; | 334 | nfca_poll->rats_res_len = *data++; |
335 | pr_debug("rats_res_len %d\n", nfca_poll->rats_res_len); | ||
127 | if (nfca_poll->rats_res_len > 0) { | 336 | if (nfca_poll->rats_res_len > 0) { |
128 | memcpy(nfca_poll->rats_res, | 337 | memcpy(nfca_poll->rats_res, |
129 | data, | 338 | data, |
@@ -131,52 +340,47 @@ static int nci_extract_activation_params_iso_dep(struct nci_dev *ndev, | |||
131 | } | 340 | } |
132 | break; | 341 | break; |
133 | 342 | ||
343 | case NCI_NFC_B_PASSIVE_POLL_MODE: | ||
344 | nfcb_poll = &ntf->activation_params.nfcb_poll_iso_dep; | ||
345 | nfcb_poll->attrib_res_len = *data++; | ||
346 | pr_debug("attrib_res_len %d\n", | ||
347 | nfcb_poll->attrib_res_len); | ||
348 | if (nfcb_poll->attrib_res_len > 0) { | ||
349 | memcpy(nfcb_poll->attrib_res, | ||
350 | data, | ||
351 | nfcb_poll->attrib_res_len); | ||
352 | } | ||
353 | break; | ||
354 | |||
134 | default: | 355 | default: |
135 | pr_err("unsupported activation_rf_tech_and_mode 0x%x\n", | 356 | pr_err("unsupported activation_rf_tech_and_mode 0x%x\n", |
136 | ntf->activation_rf_tech_and_mode); | 357 | ntf->activation_rf_tech_and_mode); |
137 | return -EPROTO; | 358 | return NCI_STATUS_RF_PROTOCOL_ERROR; |
138 | } | 359 | } |
139 | 360 | ||
140 | return 0; | 361 | return NCI_STATUS_OK; |
141 | } | 362 | } |
142 | 363 | ||
143 | static void nci_target_found(struct nci_dev *ndev, | 364 | static void nci_target_auto_activated(struct nci_dev *ndev, |
144 | struct nci_rf_intf_activated_ntf *ntf) | 365 | struct nci_rf_intf_activated_ntf *ntf) |
145 | { | 366 | { |
146 | struct nfc_target nfc_tgt; | 367 | struct nfc_target *target; |
368 | int rc; | ||
147 | 369 | ||
148 | if (ntf->rf_protocol == NCI_RF_PROTOCOL_T2T) /* T2T MifareUL */ | 370 | target = &ndev->targets[ndev->n_targets]; |
149 | nfc_tgt.supported_protocols = NFC_PROTO_MIFARE_MASK; | ||
150 | else if (ntf->rf_protocol == NCI_RF_PROTOCOL_ISO_DEP) /* 4A */ | ||
151 | nfc_tgt.supported_protocols = NFC_PROTO_ISO14443_MASK; | ||
152 | else | ||
153 | nfc_tgt.supported_protocols = 0; | ||
154 | |||
155 | nfc_tgt.sens_res = ntf->rf_tech_specific_params.nfca_poll.sens_res; | ||
156 | nfc_tgt.sel_res = ntf->rf_tech_specific_params.nfca_poll.sel_res; | ||
157 | nfc_tgt.nfcid1_len = ntf->rf_tech_specific_params.nfca_poll.nfcid1_len; | ||
158 | if (nfc_tgt.nfcid1_len > 0) { | ||
159 | memcpy(nfc_tgt.nfcid1, | ||
160 | ntf->rf_tech_specific_params.nfca_poll.nfcid1, | ||
161 | nfc_tgt.nfcid1_len); | ||
162 | } | ||
163 | 371 | ||
164 | if (!(nfc_tgt.supported_protocols & ndev->poll_prots)) { | 372 | rc = nci_add_new_protocol(ndev, target, ntf->rf_protocol, |
165 | pr_debug("the target found does not have the desired protocol\n"); | 373 | ntf->activation_rf_tech_and_mode, |
374 | &ntf->rf_tech_specific_params); | ||
375 | if (rc) | ||
166 | return; | 376 | return; |
167 | } | ||
168 | 377 | ||
169 | pr_debug("new target found, supported_protocols 0x%x\n", | 378 | target->idx = ntf->rf_discovery_id; |
170 | nfc_tgt.supported_protocols); | 379 | ndev->n_targets++; |
171 | 380 | ||
172 | ndev->target_available_prots = nfc_tgt.supported_protocols; | 381 | pr_debug("target_idx %d, n_targets %d\n", target->idx, ndev->n_targets); |
173 | ndev->max_data_pkt_payload_size = ntf->max_data_pkt_payload_size; | ||
174 | ndev->initial_num_credits = ntf->initial_num_credits; | ||
175 | 382 | ||
176 | /* set the available credits to initial value */ | 383 | nfc_targets_found(ndev->nfc_dev, ndev->targets, ndev->n_targets); |
177 | atomic_set(&ndev->credits_cnt, ndev->initial_num_credits); | ||
178 | |||
179 | nfc_targets_found(ndev->nfc_dev, &nfc_tgt, 1); | ||
180 | } | 384 | } |
181 | 385 | ||
182 | static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev, | 386 | static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev, |
@@ -184,10 +388,7 @@ static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev, | |||
184 | { | 388 | { |
185 | struct nci_rf_intf_activated_ntf ntf; | 389 | struct nci_rf_intf_activated_ntf ntf; |
186 | __u8 *data = skb->data; | 390 | __u8 *data = skb->data; |
187 | int err = 0; | 391 | int err = NCI_STATUS_OK; |
188 | |||
189 | clear_bit(NCI_DISCOVERY, &ndev->flags); | ||
190 | set_bit(NCI_POLL_ACTIVE, &ndev->flags); | ||
191 | 392 | ||
192 | ntf.rf_discovery_id = *data++; | 393 | ntf.rf_discovery_id = *data++; |
193 | ntf.rf_interface = *data++; | 394 | ntf.rf_interface = *data++; |
@@ -212,13 +413,24 @@ static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev, | |||
212 | switch (ntf.activation_rf_tech_and_mode) { | 413 | switch (ntf.activation_rf_tech_and_mode) { |
213 | case NCI_NFC_A_PASSIVE_POLL_MODE: | 414 | case NCI_NFC_A_PASSIVE_POLL_MODE: |
214 | data = nci_extract_rf_params_nfca_passive_poll(ndev, | 415 | data = nci_extract_rf_params_nfca_passive_poll(ndev, |
215 | &ntf, data); | 416 | &(ntf.rf_tech_specific_params.nfca_poll), data); |
417 | break; | ||
418 | |||
419 | case NCI_NFC_B_PASSIVE_POLL_MODE: | ||
420 | data = nci_extract_rf_params_nfcb_passive_poll(ndev, | ||
421 | &(ntf.rf_tech_specific_params.nfcb_poll), data); | ||
422 | break; | ||
423 | |||
424 | case NCI_NFC_F_PASSIVE_POLL_MODE: | ||
425 | data = nci_extract_rf_params_nfcf_passive_poll(ndev, | ||
426 | &(ntf.rf_tech_specific_params.nfcf_poll), data); | ||
216 | break; | 427 | break; |
217 | 428 | ||
218 | default: | 429 | default: |
219 | pr_err("unsupported activation_rf_tech_and_mode 0x%x\n", | 430 | pr_err("unsupported activation_rf_tech_and_mode 0x%x\n", |
220 | ntf.activation_rf_tech_and_mode); | 431 | ntf.activation_rf_tech_and_mode); |
221 | return; | 432 | err = NCI_STATUS_RF_PROTOCOL_ERROR; |
433 | goto exit; | ||
222 | } | 434 | } |
223 | } | 435 | } |
224 | 436 | ||
@@ -250,12 +462,30 @@ static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev, | |||
250 | default: | 462 | default: |
251 | pr_err("unsupported rf_interface 0x%x\n", | 463 | pr_err("unsupported rf_interface 0x%x\n", |
252 | ntf.rf_interface); | 464 | ntf.rf_interface); |
253 | return; | 465 | err = NCI_STATUS_RF_PROTOCOL_ERROR; |
466 | break; | ||
254 | } | 467 | } |
255 | } | 468 | } |
256 | 469 | ||
257 | if (!err) | 470 | exit: |
258 | nci_target_found(ndev, &ntf); | 471 | if (err == NCI_STATUS_OK) { |
472 | ndev->max_data_pkt_payload_size = ntf.max_data_pkt_payload_size; | ||
473 | ndev->initial_num_credits = ntf.initial_num_credits; | ||
474 | |||
475 | /* set the available credits to initial value */ | ||
476 | atomic_set(&ndev->credits_cnt, ndev->initial_num_credits); | ||
477 | } | ||
478 | |||
479 | if (atomic_read(&ndev->state) == NCI_DISCOVERY) { | ||
480 | /* A single target was found and activated automatically */ | ||
481 | atomic_set(&ndev->state, NCI_POLL_ACTIVE); | ||
482 | if (err == NCI_STATUS_OK) | ||
483 | nci_target_auto_activated(ndev, &ntf); | ||
484 | } else { /* ndev->state == NCI_W4_HOST_SELECT */ | ||
485 | /* A selected target was activated, so complete the request */ | ||
486 | atomic_set(&ndev->state, NCI_POLL_ACTIVE); | ||
487 | nci_req_complete(ndev, err); | ||
488 | } | ||
259 | } | 489 | } |
260 | 490 | ||
261 | static void nci_rf_deactivate_ntf_packet(struct nci_dev *ndev, | 491 | static void nci_rf_deactivate_ntf_packet(struct nci_dev *ndev, |
@@ -265,9 +495,6 @@ static void nci_rf_deactivate_ntf_packet(struct nci_dev *ndev, | |||
265 | 495 | ||
266 | pr_debug("entry, type 0x%x, reason 0x%x\n", ntf->type, ntf->reason); | 496 | pr_debug("entry, type 0x%x, reason 0x%x\n", ntf->type, ntf->reason); |
267 | 497 | ||
268 | clear_bit(NCI_POLL_ACTIVE, &ndev->flags); | ||
269 | ndev->target_active_prot = 0; | ||
270 | |||
271 | /* drop tx data queue */ | 498 | /* drop tx data queue */ |
272 | skb_queue_purge(&ndev->tx_q); | 499 | skb_queue_purge(&ndev->tx_q); |
273 | 500 | ||
@@ -280,6 +507,10 @@ static void nci_rf_deactivate_ntf_packet(struct nci_dev *ndev, | |||
280 | /* complete the data exchange transaction, if exists */ | 507 | /* complete the data exchange transaction, if exists */ |
281 | if (test_bit(NCI_DATA_EXCHANGE, &ndev->flags)) | 508 | if (test_bit(NCI_DATA_EXCHANGE, &ndev->flags)) |
282 | nci_data_exchange_complete(ndev, NULL, -EIO); | 509 | nci_data_exchange_complete(ndev, NULL, -EIO); |
510 | |||
511 | nci_clear_target_list(ndev); | ||
512 | atomic_set(&ndev->state, NCI_IDLE); | ||
513 | nci_req_complete(ndev, NCI_STATUS_OK); | ||
283 | } | 514 | } |
284 | 515 | ||
285 | void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb) | 516 | void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb) |
@@ -300,10 +531,18 @@ void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb) | |||
300 | nci_core_conn_credits_ntf_packet(ndev, skb); | 531 | nci_core_conn_credits_ntf_packet(ndev, skb); |
301 | break; | 532 | break; |
302 | 533 | ||
534 | case NCI_OP_CORE_GENERIC_ERROR_NTF: | ||
535 | nci_core_generic_error_ntf_packet(ndev, skb); | ||
536 | break; | ||
537 | |||
303 | case NCI_OP_CORE_INTF_ERROR_NTF: | 538 | case NCI_OP_CORE_INTF_ERROR_NTF: |
304 | nci_core_conn_intf_error_ntf_packet(ndev, skb); | 539 | nci_core_conn_intf_error_ntf_packet(ndev, skb); |
305 | break; | 540 | break; |
306 | 541 | ||
542 | case NCI_OP_RF_DISCOVER_NTF: | ||
543 | nci_rf_discover_ntf_packet(ndev, skb); | ||
544 | break; | ||
545 | |||
307 | case NCI_OP_RF_INTF_ACTIVATED_NTF: | 546 | case NCI_OP_RF_INTF_ACTIVATED_NTF: |
308 | nci_rf_intf_activated_ntf_packet(ndev, skb); | 547 | nci_rf_intf_activated_ntf_packet(ndev, skb); |
309 | break; | 548 | break; |
diff --git a/net/nfc/nci/rsp.c b/net/nfc/nci/rsp.c index 2840ae2f3615..aa63b1e99188 100644 --- a/net/nfc/nci/rsp.c +++ b/net/nfc/nci/rsp.c | |||
@@ -137,11 +137,23 @@ static void nci_rf_disc_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb) | |||
137 | pr_debug("status 0x%x\n", status); | 137 | pr_debug("status 0x%x\n", status); |
138 | 138 | ||
139 | if (status == NCI_STATUS_OK) | 139 | if (status == NCI_STATUS_OK) |
140 | set_bit(NCI_DISCOVERY, &ndev->flags); | 140 | atomic_set(&ndev->state, NCI_DISCOVERY); |
141 | 141 | ||
142 | nci_req_complete(ndev, status); | 142 | nci_req_complete(ndev, status); |
143 | } | 143 | } |
144 | 144 | ||
145 | static void nci_rf_disc_select_rsp_packet(struct nci_dev *ndev, | ||
146 | struct sk_buff *skb) | ||
147 | { | ||
148 | __u8 status = skb->data[0]; | ||
149 | |||
150 | pr_debug("status 0x%x\n", status); | ||
151 | |||
152 | /* Complete the request on intf_activated_ntf or generic_error_ntf */ | ||
153 | if (status != NCI_STATUS_OK) | ||
154 | nci_req_complete(ndev, status); | ||
155 | } | ||
156 | |||
145 | static void nci_rf_deactivate_rsp_packet(struct nci_dev *ndev, | 157 | static void nci_rf_deactivate_rsp_packet(struct nci_dev *ndev, |
146 | struct sk_buff *skb) | 158 | struct sk_buff *skb) |
147 | { | 159 | { |
@@ -149,9 +161,13 @@ static void nci_rf_deactivate_rsp_packet(struct nci_dev *ndev, | |||
149 | 161 | ||
150 | pr_debug("status 0x%x\n", status); | 162 | pr_debug("status 0x%x\n", status); |
151 | 163 | ||
152 | clear_bit(NCI_DISCOVERY, &ndev->flags); | 164 | /* If target was active, complete the request only in deactivate_ntf */ |
153 | 165 | if ((status != NCI_STATUS_OK) || | |
154 | nci_req_complete(ndev, status); | 166 | (atomic_read(&ndev->state) != NCI_POLL_ACTIVE)) { |
167 | nci_clear_target_list(ndev); | ||
168 | atomic_set(&ndev->state, NCI_IDLE); | ||
169 | nci_req_complete(ndev, status); | ||
170 | } | ||
155 | } | 171 | } |
156 | 172 | ||
157 | void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb) | 173 | void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb) |
@@ -187,6 +203,10 @@ void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb) | |||
187 | nci_rf_disc_rsp_packet(ndev, skb); | 203 | nci_rf_disc_rsp_packet(ndev, skb); |
188 | break; | 204 | break; |
189 | 205 | ||
206 | case NCI_OP_RF_DISCOVER_SELECT_RSP: | ||
207 | nci_rf_disc_select_rsp_packet(ndev, skb); | ||
208 | break; | ||
209 | |||
190 | case NCI_OP_RF_DEACTIVATE_RSP: | 210 | case NCI_OP_RF_DEACTIVATE_RSP: |
191 | nci_rf_deactivate_rsp_packet(ndev, skb); | 211 | nci_rf_deactivate_rsp_packet(ndev, skb); |
192 | break; | 212 | break; |
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index 6989dfa28ee2..07f0348aabf5 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c | |||
@@ -70,6 +70,12 @@ static int nfc_genl_send_target(struct sk_buff *msg, struct nfc_target *target, | |||
70 | if (target->nfcid1_len > 0) | 70 | if (target->nfcid1_len > 0) |
71 | NLA_PUT(msg, NFC_ATTR_TARGET_NFCID1, target->nfcid1_len, | 71 | NLA_PUT(msg, NFC_ATTR_TARGET_NFCID1, target->nfcid1_len, |
72 | target->nfcid1); | 72 | target->nfcid1); |
73 | if (target->sensb_res_len > 0) | ||
74 | NLA_PUT(msg, NFC_ATTR_TARGET_SENSB_RES, target->sensb_res_len, | ||
75 | target->sensb_res); | ||
76 | if (target->sensf_res_len > 0) | ||
77 | NLA_PUT(msg, NFC_ATTR_TARGET_SENSF_RES, target->sensf_res_len, | ||
78 | target->sensf_res); | ||
73 | 79 | ||
74 | return genlmsg_end(msg, hdr); | 80 | return genlmsg_end(msg, hdr); |
75 | 81 | ||
diff --git a/net/nfc/rawsock.c b/net/nfc/rawsock.c index 2e2f8c6a61fe..5325439b0c60 100644 --- a/net/nfc/rawsock.c +++ b/net/nfc/rawsock.c | |||
@@ -92,18 +92,6 @@ static int rawsock_connect(struct socket *sock, struct sockaddr *_addr, | |||
92 | goto error; | 92 | goto error; |
93 | } | 93 | } |
94 | 94 | ||
95 | if (addr->target_idx > dev->target_idx - 1 || | ||
96 | addr->target_idx < dev->target_idx - dev->n_targets) { | ||
97 | rc = -EINVAL; | ||
98 | goto error; | ||
99 | } | ||
100 | |||
101 | if (addr->target_idx > dev->target_idx - 1 || | ||
102 | addr->target_idx < dev->target_idx - dev->n_targets) { | ||
103 | rc = -EINVAL; | ||
104 | goto error; | ||
105 | } | ||
106 | |||
107 | rc = nfc_activate_target(dev, addr->target_idx, addr->nfc_protocol); | 95 | rc = nfc_activate_target(dev, addr->target_idx, addr->nfc_protocol); |
108 | if (rc) | 96 | if (rc) |
109 | goto put_dev; | 97 | goto put_dev; |
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c index 8c550df13037..9d3e3b6bfcf4 100644 --- a/net/wireless/mesh.c +++ b/net/wireless/mesh.c | |||
@@ -55,6 +55,7 @@ const struct mesh_config default_mesh_config = { | |||
55 | .min_discovery_timeout = MESH_MIN_DISCOVERY_TIMEOUT, | 55 | .min_discovery_timeout = MESH_MIN_DISCOVERY_TIMEOUT, |
56 | .dot11MeshHWMPRannInterval = MESH_RANN_INTERVAL, | 56 | .dot11MeshHWMPRannInterval = MESH_RANN_INTERVAL, |
57 | .dot11MeshGateAnnouncementProtocol = false, | 57 | .dot11MeshGateAnnouncementProtocol = false, |
58 | .dot11MeshForwarding = true, | ||
58 | }; | 59 | }; |
59 | 60 | ||
60 | const struct mesh_setup default_mesh_setup = { | 61 | const struct mesh_setup default_mesh_setup = { |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index afeea32e04ad..c910b0750dc2 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -427,10 +427,9 @@ static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k) | |||
427 | 427 | ||
428 | if (tb[NL80211_KEY_DEFAULT_TYPES]) { | 428 | if (tb[NL80211_KEY_DEFAULT_TYPES]) { |
429 | struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES]; | 429 | struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES]; |
430 | int err = nla_parse_nested(kdt, | 430 | err = nla_parse_nested(kdt, NUM_NL80211_KEY_DEFAULT_TYPES - 1, |
431 | NUM_NL80211_KEY_DEFAULT_TYPES - 1, | 431 | tb[NL80211_KEY_DEFAULT_TYPES], |
432 | tb[NL80211_KEY_DEFAULT_TYPES], | 432 | nl80211_key_default_policy); |
433 | nl80211_key_default_policy); | ||
434 | if (err) | 433 | if (err) |
435 | return err; | 434 | return err; |
436 | 435 | ||
@@ -3259,6 +3258,8 @@ static int nl80211_get_mesh_config(struct sk_buff *skb, | |||
3259 | cur_params.dot11MeshHWMPRannInterval); | 3258 | cur_params.dot11MeshHWMPRannInterval); |
3260 | NLA_PUT_U8(msg, NL80211_MESHCONF_GATE_ANNOUNCEMENTS, | 3259 | NLA_PUT_U8(msg, NL80211_MESHCONF_GATE_ANNOUNCEMENTS, |
3261 | cur_params.dot11MeshGateAnnouncementProtocol); | 3260 | cur_params.dot11MeshGateAnnouncementProtocol); |
3261 | NLA_PUT_U8(msg, NL80211_MESHCONF_FORWARDING, | ||
3262 | cur_params.dot11MeshForwarding); | ||
3262 | nla_nest_end(msg, pinfoattr); | 3263 | nla_nest_end(msg, pinfoattr); |
3263 | genlmsg_end(msg, hdr); | 3264 | genlmsg_end(msg, hdr); |
3264 | return genlmsg_reply(msg, info); | 3265 | return genlmsg_reply(msg, info); |
@@ -3290,6 +3291,7 @@ static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_A | |||
3290 | [NL80211_MESHCONF_HWMP_ROOTMODE] = { .type = NLA_U8 }, | 3291 | [NL80211_MESHCONF_HWMP_ROOTMODE] = { .type = NLA_U8 }, |
3291 | [NL80211_MESHCONF_HWMP_RANN_INTERVAL] = { .type = NLA_U16 }, | 3292 | [NL80211_MESHCONF_HWMP_RANN_INTERVAL] = { .type = NLA_U16 }, |
3292 | [NL80211_MESHCONF_GATE_ANNOUNCEMENTS] = { .type = NLA_U8 }, | 3293 | [NL80211_MESHCONF_GATE_ANNOUNCEMENTS] = { .type = NLA_U8 }, |
3294 | [NL80211_MESHCONF_FORWARDING] = { .type = NLA_U8 }, | ||
3293 | }; | 3295 | }; |
3294 | 3296 | ||
3295 | static const struct nla_policy | 3297 | static const struct nla_policy |
@@ -3379,6 +3381,8 @@ do {\ | |||
3379 | dot11MeshGateAnnouncementProtocol, mask, | 3381 | dot11MeshGateAnnouncementProtocol, mask, |
3380 | NL80211_MESHCONF_GATE_ANNOUNCEMENTS, | 3382 | NL80211_MESHCONF_GATE_ANNOUNCEMENTS, |
3381 | nla_get_u8); | 3383 | nla_get_u8); |
3384 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshForwarding, | ||
3385 | mask, NL80211_MESHCONF_FORWARDING, nla_get_u8); | ||
3382 | if (mask_out) | 3386 | if (mask_out) |
3383 | *mask_out = mask; | 3387 | *mask_out = mask; |
3384 | 3388 | ||
@@ -4781,7 +4785,6 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) | |||
4781 | nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); | 4785 | nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); |
4782 | struct ieee80211_supported_band *sband = | 4786 | struct ieee80211_supported_band *sband = |
4783 | wiphy->bands[ibss.channel->band]; | 4787 | wiphy->bands[ibss.channel->band]; |
4784 | int err; | ||
4785 | 4788 | ||
4786 | err = ieee80211_get_ratemask(sband, rates, n_rates, | 4789 | err = ieee80211_get_ratemask(sband, rates, n_rates, |
4787 | &ibss.basic_rates); | 4790 | &ibss.basic_rates); |
@@ -5390,9 +5393,39 @@ static u32 rateset_to_mask(struct ieee80211_supported_band *sband, | |||
5390 | return mask; | 5393 | return mask; |
5391 | } | 5394 | } |
5392 | 5395 | ||
5396 | static bool ht_rateset_to_mask(struct ieee80211_supported_band *sband, | ||
5397 | u8 *rates, u8 rates_len, | ||
5398 | u8 mcs[IEEE80211_HT_MCS_MASK_LEN]) | ||
5399 | { | ||
5400 | u8 i; | ||
5401 | |||
5402 | memset(mcs, 0, IEEE80211_HT_MCS_MASK_LEN); | ||
5403 | |||
5404 | for (i = 0; i < rates_len; i++) { | ||
5405 | int ridx, rbit; | ||
5406 | |||
5407 | ridx = rates[i] / 8; | ||
5408 | rbit = BIT(rates[i] % 8); | ||
5409 | |||
5410 | /* check validity */ | ||
5411 | if ((ridx < 0) || (ridx > IEEE80211_HT_MCS_MASK_LEN)) | ||
5412 | return false; | ||
5413 | |||
5414 | /* check availability */ | ||
5415 | if (sband->ht_cap.mcs.rx_mask[ridx] & rbit) | ||
5416 | mcs[ridx] |= rbit; | ||
5417 | else | ||
5418 | return false; | ||
5419 | } | ||
5420 | |||
5421 | return true; | ||
5422 | } | ||
5423 | |||
5393 | static const struct nla_policy nl80211_txattr_policy[NL80211_TXRATE_MAX + 1] = { | 5424 | static const struct nla_policy nl80211_txattr_policy[NL80211_TXRATE_MAX + 1] = { |
5394 | [NL80211_TXRATE_LEGACY] = { .type = NLA_BINARY, | 5425 | [NL80211_TXRATE_LEGACY] = { .type = NLA_BINARY, |
5395 | .len = NL80211_MAX_SUPP_RATES }, | 5426 | .len = NL80211_MAX_SUPP_RATES }, |
5427 | [NL80211_TXRATE_MCS] = { .type = NLA_BINARY, | ||
5428 | .len = NL80211_MAX_SUPP_HT_RATES }, | ||
5396 | }; | 5429 | }; |
5397 | 5430 | ||
5398 | static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, | 5431 | static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, |
@@ -5418,12 +5451,20 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, | |||
5418 | sband = rdev->wiphy.bands[i]; | 5451 | sband = rdev->wiphy.bands[i]; |
5419 | mask.control[i].legacy = | 5452 | mask.control[i].legacy = |
5420 | sband ? (1 << sband->n_bitrates) - 1 : 0; | 5453 | sband ? (1 << sband->n_bitrates) - 1 : 0; |
5454 | if (sband) | ||
5455 | memcpy(mask.control[i].mcs, | ||
5456 | sband->ht_cap.mcs.rx_mask, | ||
5457 | sizeof(mask.control[i].mcs)); | ||
5458 | else | ||
5459 | memset(mask.control[i].mcs, 0, | ||
5460 | sizeof(mask.control[i].mcs)); | ||
5421 | } | 5461 | } |
5422 | 5462 | ||
5423 | /* | 5463 | /* |
5424 | * The nested attribute uses enum nl80211_band as the index. This maps | 5464 | * The nested attribute uses enum nl80211_band as the index. This maps |
5425 | * directly to the enum ieee80211_band values used in cfg80211. | 5465 | * directly to the enum ieee80211_band values used in cfg80211. |
5426 | */ | 5466 | */ |
5467 | BUILD_BUG_ON(NL80211_MAX_SUPP_HT_RATES > IEEE80211_HT_MCS_MASK_LEN * 8); | ||
5427 | nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem) | 5468 | nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem) |
5428 | { | 5469 | { |
5429 | enum ieee80211_band band = nla_type(tx_rates); | 5470 | enum ieee80211_band band = nla_type(tx_rates); |
@@ -5439,7 +5480,28 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, | |||
5439 | sband, | 5480 | sband, |
5440 | nla_data(tb[NL80211_TXRATE_LEGACY]), | 5481 | nla_data(tb[NL80211_TXRATE_LEGACY]), |
5441 | nla_len(tb[NL80211_TXRATE_LEGACY])); | 5482 | nla_len(tb[NL80211_TXRATE_LEGACY])); |
5442 | if (mask.control[band].legacy == 0) | 5483 | } |
5484 | if (tb[NL80211_TXRATE_MCS]) { | ||
5485 | if (!ht_rateset_to_mask( | ||
5486 | sband, | ||
5487 | nla_data(tb[NL80211_TXRATE_MCS]), | ||
5488 | nla_len(tb[NL80211_TXRATE_MCS]), | ||
5489 | mask.control[band].mcs)) | ||
5490 | return -EINVAL; | ||
5491 | } | ||
5492 | |||
5493 | if (mask.control[band].legacy == 0) { | ||
5494 | /* don't allow empty legacy rates if HT | ||
5495 | * is not even supported. */ | ||
5496 | if (!rdev->wiphy.bands[band]->ht_cap.ht_supported) | ||
5497 | return -EINVAL; | ||
5498 | |||
5499 | for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) | ||
5500 | if (mask.control[band].mcs[i]) | ||
5501 | break; | ||
5502 | |||
5503 | /* legacy and mcs rates may not be both empty */ | ||
5504 | if (i == IEEE80211_HT_MCS_MASK_LEN) | ||
5443 | return -EINVAL; | 5505 | return -EINVAL; |
5444 | } | 5506 | } |
5445 | } | 5507 | } |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index f65feaad155f..e9a0ac83b84c 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -882,23 +882,8 @@ static void handle_channel(struct wiphy *wiphy, | |||
882 | chan->flags = flags | bw_flags | map_regdom_flags(reg_rule->flags); | 882 | chan->flags = flags | bw_flags | map_regdom_flags(reg_rule->flags); |
883 | chan->max_antenna_gain = min(chan->orig_mag, | 883 | chan->max_antenna_gain = min(chan->orig_mag, |
884 | (int) MBI_TO_DBI(power_rule->max_antenna_gain)); | 884 | (int) MBI_TO_DBI(power_rule->max_antenna_gain)); |
885 | if (chan->orig_mpwr) { | 885 | chan->max_reg_power = (int) MBM_TO_DBM(power_rule->max_eirp); |
886 | /* | 886 | chan->max_power = min(chan->max_power, chan->max_reg_power); |
887 | * Devices that have their own custom regulatory domain | ||
888 | * but also use WIPHY_FLAG_STRICT_REGULATORY will follow the | ||
889 | * passed country IE power settings. | ||
890 | */ | ||
891 | if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE && | ||
892 | wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY && | ||
893 | wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) { | ||
894 | chan->max_power = | ||
895 | MBM_TO_DBM(power_rule->max_eirp); | ||
896 | } else { | ||
897 | chan->max_power = min(chan->orig_mpwr, | ||
898 | (int) MBM_TO_DBM(power_rule->max_eirp)); | ||
899 | } | ||
900 | } else | ||
901 | chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp); | ||
902 | } | 887 | } |
903 | 888 | ||
904 | static void handle_band(struct wiphy *wiphy, | 889 | static void handle_band(struct wiphy *wiphy, |