Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'mac80211-next-for-net-next-2021-08-26' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next

Johannes Berg says:

====================
A few more things:
* Use correct DFS domain for self-managed devices
* some preparations for transmit power element handling
and other 6 GHz regulatory handling
* TWT support in AP mode in mac80211
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+558 -4
+105 -1
include/linux/ieee80211.h
··· 1088 1088 } u; 1089 1089 } __packed __aligned(2); 1090 1090 1091 + #define IEEE80211_TWT_CONTROL_NDP BIT(0) 1092 + #define IEEE80211_TWT_CONTROL_RESP_MODE BIT(1) 1093 + #define IEEE80211_TWT_CONTROL_NEG_TYPE_BROADCAST BIT(3) 1094 + #define IEEE80211_TWT_CONTROL_RX_DISABLED BIT(4) 1095 + #define IEEE80211_TWT_CONTROL_WAKE_DUR_UNIT BIT(5) 1096 + 1097 + #define IEEE80211_TWT_REQTYPE_REQUEST BIT(0) 1098 + #define IEEE80211_TWT_REQTYPE_SETUP_CMD GENMASK(3, 1) 1099 + #define IEEE80211_TWT_REQTYPE_TRIGGER BIT(4) 1100 + #define IEEE80211_TWT_REQTYPE_IMPLICIT BIT(5) 1101 + #define IEEE80211_TWT_REQTYPE_FLOWTYPE BIT(6) 1102 + #define IEEE80211_TWT_REQTYPE_FLOWID GENMASK(9, 7) 1103 + #define IEEE80211_TWT_REQTYPE_WAKE_INT_EXP GENMASK(14, 10) 1104 + #define IEEE80211_TWT_REQTYPE_PROTECTION BIT(15) 1105 + 1106 + enum ieee80211_twt_setup_cmd { 1107 + TWT_SETUP_CMD_REQUEST, 1108 + TWT_SETUP_CMD_SUGGEST, 1109 + TWT_SETUP_CMD_DEMAND, 1110 + TWT_SETUP_CMD_GROUPING, 1111 + TWT_SETUP_CMD_ACCEPT, 1112 + TWT_SETUP_CMD_ALTERNATE, 1113 + TWT_SETUP_CMD_DICTATE, 1114 + TWT_SETUP_CMD_REJECT, 1115 + }; 1116 + 1117 + struct ieee80211_twt_params { 1118 + __le16 req_type; 1119 + __le64 twt; 1120 + u8 min_twt_dur; 1121 + __le16 mantissa; 1122 + u8 channel; 1123 + } __packed; 1124 + 1125 + struct ieee80211_twt_setup { 1126 + u8 dialog_token; 1127 + u8 element_id; 1128 + u8 length; 1129 + u8 control; 1130 + u8 params[]; 1131 + } __packed; 1132 + 1091 1133 struct ieee80211_mgmt { 1092 1134 __le16 frame_control; 1093 1135 __le16 duration; ··· 1294 1252 __le16 toa_error; 1295 1253 u8 variable[0]; 1296 1254 } __packed ftm; 1255 + struct { 1256 + u8 action_code; 1257 + u8 variable[]; 1258 + } __packed s1g; 1297 1259 } u; 1298 1260 } __packed action; 1299 1261 } u; ··· 2312 2266 #define IEEE80211_HE_OPERATION_PARTIAL_BSS_COLOR 0x40000000 2313 2267 #define IEEE80211_HE_OPERATION_BSS_COLOR_DISABLED 0x80000000 2314 2268 2269 + #define IEEE80211_6GHZ_CTRL_REG_LPI_AP 0 2270 + #define IEEE80211_6GHZ_CTRL_REG_SP_AP 1 2271 + 2315 2272 /** 2316 2273 * ieee80211_he_6ghz_oper - HE 6 GHz operation Information field 2317 2274 * @primary: primary channel ··· 2331 2282 #define IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_80MHZ 2 2332 2283 #define IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_160MHZ 3 2333 2284 #define IEEE80211_HE_6GHZ_OPER_CTRL_DUP_BEACON 0x4 2285 + #define IEEE80211_HE_6GHZ_OPER_CTRL_REG_INFO 0x38 2334 2286 u8 control; 2335 2287 u8 ccfs0; 2336 2288 u8 ccfs1; 2337 2289 u8 minrate; 2338 2290 } __packed; 2291 + 2292 + /* 2293 + * In "9.4.2.161 Transmit Power Envelope element" of "IEEE Std 802.11ax-2021", 2294 + * it show four types in "Table 9-275a-Maximum Transmit Power Interpretation 2295 + * subfield encoding", and two category for each type in "Table E-12-Regulatory 2296 + * Info subfield encoding in the United States". 2297 + * So it it totally max 8 Transmit Power Envelope element. 2298 + */ 2299 + #define IEEE80211_TPE_MAX_IE_COUNT 8 2300 + /* 2301 + * In "Table 9-277—Meaning of Maximum Transmit Power Count subfield" 2302 + * of "IEEE Std 802.11ax™‐2021", the max power level is 8. 2303 + */ 2304 + #define IEEE80211_MAX_NUM_PWR_LEVEL 8 2305 + 2306 + #define IEEE80211_TPE_MAX_POWER_COUNT 8 2307 + 2308 + /* transmit power interpretation type of transmit power envelope element */ 2309 + enum ieee80211_tx_power_intrpt_type { 2310 + IEEE80211_TPE_LOCAL_EIRP, 2311 + IEEE80211_TPE_LOCAL_EIRP_PSD, 2312 + IEEE80211_TPE_REG_CLIENT_EIRP, 2313 + IEEE80211_TPE_REG_CLIENT_EIRP_PSD, 2314 + }; 2315 + 2316 + /** 2317 + * struct ieee80211_tx_pwr_env 2318 + * 2319 + * This structure represents the "Transmit Power Envelope element" 2320 + */ 2321 + struct ieee80211_tx_pwr_env { 2322 + u8 tx_power_info; 2323 + s8 tx_power[IEEE80211_TPE_MAX_POWER_COUNT]; 2324 + } __packed; 2325 + 2326 + #define IEEE80211_TX_PWR_ENV_INFO_COUNT 0x7 2327 + #define IEEE80211_TX_PWR_ENV_INFO_INTERPRET 0x38 2328 + #define IEEE80211_TX_PWR_ENV_INFO_CATEGORY 0xC0 2339 2329 2340 2330 /* 2341 2331 * ieee80211_he_oper_size - calculate 802.11ax HE Operations IE size ··· 2957 2869 WLAN_EID_VHT_OPERATION = 192, 2958 2870 WLAN_EID_EXTENDED_BSS_LOAD = 193, 2959 2871 WLAN_EID_WIDE_BW_CHANNEL_SWITCH = 194, 2960 - WLAN_EID_VHT_TX_POWER_ENVELOPE = 195, 2872 + WLAN_EID_TX_POWER_ENVELOPE = 195, 2961 2873 WLAN_EID_CHANNEL_SWITCH_WRAPPER = 196, 2962 2874 WLAN_EID_AID = 197, 2963 2875 WLAN_EID_QUIET_CHANNEL = 198, ··· 2969 2881 WLAN_EID_AID_RESPONSE = 211, 2970 2882 WLAN_EID_S1G_BCN_COMPAT = 213, 2971 2883 WLAN_EID_S1G_SHORT_BCN_INTERVAL = 214, 2884 + WLAN_EID_S1G_TWT = 216, 2972 2885 WLAN_EID_S1G_CAPABILITIES = 217, 2973 2886 WLAN_EID_VENDOR_SPECIFIC = 221, 2974 2887 WLAN_EID_QOS_PARAMETER = 222, ··· 3039 2950 WLAN_CATEGORY_FST = 18, 3040 2951 WLAN_CATEGORY_UNPROT_DMG = 20, 3041 2952 WLAN_CATEGORY_VHT = 21, 2953 + WLAN_CATEGORY_S1G = 22, 3042 2954 WLAN_CATEGORY_VENDOR_SPECIFIC_PROTECTED = 126, 3043 2955 WLAN_CATEGORY_VENDOR_SPECIFIC = 127, 3044 2956 }; ··· 3111 3021 WLAN_KEY_LEN_BIP_CMAC_256 = 32, 3112 3022 WLAN_KEY_LEN_BIP_GMAC_128 = 16, 3113 3023 WLAN_KEY_LEN_BIP_GMAC_256 = 32, 3024 + }; 3025 + 3026 + enum ieee80211_s1g_actioncode { 3027 + WLAN_S1G_AID_SWITCH_REQUEST, 3028 + WLAN_S1G_AID_SWITCH_RESPONSE, 3029 + WLAN_S1G_SYNC_CONTROL, 3030 + WLAN_S1G_STA_INFO_ANNOUNCE, 3031 + WLAN_S1G_EDCA_PARAM_SET, 3032 + WLAN_S1G_EL_OPERATION, 3033 + WLAN_S1G_TWT_SETUP, 3034 + WLAN_S1G_TWT_TEARDOWN, 3035 + WLAN_S1G_SECT_GROUP_ID_LIST, 3036 + WLAN_S1G_SECT_ID_FEEDBACK, 3037 + WLAN_S1G_TWT_INFORMATION = 11, 3114 3038 }; 3115 3039 3116 3040 #define IEEE80211_WEP_IV_LEN 4
+12
include/net/mac80211.h
··· 3926 3926 * @set_sar_specs: Update the SAR (TX power) settings. 3927 3927 * @sta_set_decap_offload: Called to notify the driver when a station is allowed 3928 3928 * to use rx decapsulation offload 3929 + * @add_twt_setup: Update hw with TWT agreement parameters received from the peer. 3930 + * This callback allows the hw to check if requested parameters 3931 + * are supported and if there is enough room for a new agreement. 3932 + * The hw is expected to set agreement result in the req_type field of 3933 + * twt structure. 3934 + * @twt_teardown_request: Update the hw with TWT teardown request received 3935 + * from the peer. 3929 3936 */ 3930 3937 struct ieee80211_ops { 3931 3938 void (*tx)(struct ieee80211_hw *hw, ··· 4256 4249 void (*sta_set_decap_offload)(struct ieee80211_hw *hw, 4257 4250 struct ieee80211_vif *vif, 4258 4251 struct ieee80211_sta *sta, bool enabled); 4252 + void (*add_twt_setup)(struct ieee80211_hw *hw, 4253 + struct ieee80211_sta *sta, 4254 + struct ieee80211_twt_setup *twt); 4255 + void (*twt_teardown_request)(struct ieee80211_hw *hw, 4256 + struct ieee80211_sta *sta, u8 flowid); 4259 4257 }; 4260 4258 4261 4259 /**
+36
net/mac80211/driver-ops.h
··· 1447 1447 trace_drv_return_void(local); 1448 1448 } 1449 1449 1450 + static inline void drv_add_twt_setup(struct ieee80211_local *local, 1451 + struct ieee80211_sub_if_data *sdata, 1452 + struct ieee80211_sta *sta, 1453 + struct ieee80211_twt_setup *twt) 1454 + { 1455 + struct ieee80211_twt_params *twt_agrt; 1456 + 1457 + might_sleep(); 1458 + 1459 + if (!check_sdata_in_driver(sdata)) 1460 + return; 1461 + 1462 + twt_agrt = (void *)twt->params; 1463 + 1464 + trace_drv_add_twt_setup(local, sta, twt, twt_agrt); 1465 + local->ops->add_twt_setup(&local->hw, sta, twt); 1466 + trace_drv_return_void(local); 1467 + } 1468 + 1469 + static inline void drv_twt_teardown_request(struct ieee80211_local *local, 1470 + struct ieee80211_sub_if_data *sdata, 1471 + struct ieee80211_sta *sta, 1472 + u8 flowid) 1473 + { 1474 + might_sleep(); 1475 + if (!check_sdata_in_driver(sdata)) 1476 + return; 1477 + 1478 + if (!local->ops->twt_teardown_request) 1479 + return; 1480 + 1481 + trace_drv_twt_teardown_request(local, sta, flowid); 1482 + local->ops->twt_teardown_request(&local->hw, sta, flowid); 1483 + trace_drv_return_void(local); 1484 + } 1485 + 1450 1486 #endif /* __MAC80211_DRIVER_OPS */
+9
net/mac80211/ieee80211_i.h
··· 946 946 947 947 struct work_struct work; 948 948 struct sk_buff_head skb_queue; 949 + struct sk_buff_head status_queue; 949 950 950 951 u8 needed_rx_chains; 951 952 enum ieee80211_smps_mode smps_mode; ··· 1534 1533 const struct ieee80211_he_spr *he_spr; 1535 1534 const struct ieee80211_mu_edca_param_set *mu_edca_param_set; 1536 1535 const struct ieee80211_he_6ghz_capa *he_6ghz_capa; 1536 + const struct ieee80211_tx_pwr_env *tx_pwr_env[IEEE80211_TPE_MAX_IE_COUNT]; 1537 1537 const u8 *uora_element; 1538 1538 const u8 *mesh_id; 1539 1539 const u8 *peering; ··· 1585 1583 u8 perr_len; 1586 1584 u8 country_elem_len; 1587 1585 u8 bssid_index_len; 1586 + u8 tx_pwr_env_len[IEEE80211_TPE_MAX_IE_COUNT]; 1587 + u8 tx_pwr_env_num; 1588 1588 1589 1589 /* whether a parse error occurred while retrieving these elements */ 1590 1590 bool parse_error; ··· 2084 2080 2085 2081 /* S1G */ 2086 2082 void ieee80211_s1g_sta_rate_init(struct sta_info *sta); 2083 + bool ieee80211_s1g_is_twt_setup(struct sk_buff *skb); 2084 + void ieee80211_s1g_rx_twt_action(struct ieee80211_sub_if_data *sdata, 2085 + struct sk_buff *skb); 2086 + void ieee80211_s1g_status_twt_action(struct ieee80211_sub_if_data *sdata, 2087 + struct sk_buff *skb); 2087 2088 2088 2089 /* Spectrum management */ 2089 2090 void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata,
+41
net/mac80211/iface.c
··· 552 552 */ 553 553 ieee80211_free_keys(sdata, true); 554 554 skb_queue_purge(&sdata->skb_queue); 555 + skb_queue_purge(&sdata->status_queue); 555 556 } 556 557 557 558 spin_lock_irqsave(&local->queue_stop_reason_lock, flags); ··· 985 984 } 986 985 987 986 skb_queue_head_init(&sdata->skb_queue); 987 + skb_queue_head_init(&sdata->status_queue); 988 988 INIT_WORK(&sdata->work, ieee80211_iface_work); 989 989 990 990 return 0; ··· 1384 1382 WARN_ON(1); 1385 1383 break; 1386 1384 } 1385 + } else if (ieee80211_is_action(mgmt->frame_control) && 1386 + mgmt->u.action.category == WLAN_CATEGORY_S1G) { 1387 + switch (mgmt->u.action.u.s1g.action_code) { 1388 + case WLAN_S1G_TWT_TEARDOWN: 1389 + case WLAN_S1G_TWT_SETUP: 1390 + ieee80211_s1g_rx_twt_action(sdata, skb); 1391 + break; 1392 + default: 1393 + break; 1394 + } 1387 1395 } else if (ieee80211_is_ext(mgmt->frame_control)) { 1388 1396 if (sdata->vif.type == NL80211_IFTYPE_STATION) 1389 1397 ieee80211_sta_rx_queued_ext(sdata, skb); ··· 1449 1437 } 1450 1438 } 1451 1439 1440 + static void ieee80211_iface_process_status(struct ieee80211_sub_if_data *sdata, 1441 + struct sk_buff *skb) 1442 + { 1443 + struct ieee80211_mgmt *mgmt = (void *)skb->data; 1444 + 1445 + if (ieee80211_is_action(mgmt->frame_control) && 1446 + mgmt->u.action.category == WLAN_CATEGORY_S1G) { 1447 + switch (mgmt->u.action.u.s1g.action_code) { 1448 + case WLAN_S1G_TWT_TEARDOWN: 1449 + case WLAN_S1G_TWT_SETUP: 1450 + ieee80211_s1g_status_twt_action(sdata, skb); 1451 + break; 1452 + default: 1453 + break; 1454 + } 1455 + } 1456 + } 1457 + 1452 1458 static void ieee80211_iface_work(struct work_struct *work) 1453 1459 { 1454 1460 struct ieee80211_sub_if_data *sdata = ··· 1493 1463 ieee80211_iface_process_skb(local, sdata, skb); 1494 1464 1495 1465 kfree_skb(skb); 1466 + kcov_remote_stop(); 1467 + } 1468 + 1469 + /* process status queue */ 1470 + while ((skb = skb_dequeue(&sdata->status_queue))) { 1471 + kcov_remote_start_common(skb_get_kcov_handle(skb)); 1472 + 1473 + ieee80211_iface_process_status(sdata, skb); 1474 + kfree_skb(skb); 1475 + 1496 1476 kcov_remote_stop(); 1497 1477 } 1498 1478 ··· 1569 1529 } 1570 1530 1571 1531 skb_queue_head_init(&sdata->skb_queue); 1532 + skb_queue_head_init(&sdata->status_queue); 1572 1533 INIT_WORK(&sdata->work, ieee80211_iface_work); 1573 1534 INIT_WORK(&sdata->recalc_smps, ieee80211_recalc_smps_work); 1574 1535 INIT_WORK(&sdata->csa_finalize_work, ieee80211_csa_finalize_work);
+73
net/mac80211/rx.c
··· 3212 3212 return RX_CONTINUE; 3213 3213 } 3214 3214 3215 + static bool 3216 + ieee80211_process_rx_twt_action(struct ieee80211_rx_data *rx) 3217 + { 3218 + struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)rx->skb->data; 3219 + struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); 3220 + struct ieee80211_sub_if_data *sdata = rx->sdata; 3221 + const struct ieee80211_sta_he_cap *hecap; 3222 + struct ieee80211_supported_band *sband; 3223 + 3224 + /* TWT actions are only supported in AP for the moment */ 3225 + if (sdata->vif.type != NL80211_IFTYPE_AP) 3226 + return false; 3227 + 3228 + if (!rx->local->ops->add_twt_setup) 3229 + return false; 3230 + 3231 + sband = rx->local->hw.wiphy->bands[status->band]; 3232 + hecap = ieee80211_get_he_iftype_cap(sband, 3233 + ieee80211_vif_type_p2p(&sdata->vif)); 3234 + if (!hecap) 3235 + return false; 3236 + 3237 + if (!(hecap->he_cap_elem.mac_cap_info[0] & 3238 + IEEE80211_HE_MAC_CAP0_TWT_RES)) 3239 + return false; 3240 + 3241 + if (!rx->sta) 3242 + return false; 3243 + 3244 + switch (mgmt->u.action.u.s1g.action_code) { 3245 + case WLAN_S1G_TWT_SETUP: { 3246 + struct ieee80211_twt_setup *twt; 3247 + 3248 + if (rx->skb->len < IEEE80211_MIN_ACTION_SIZE + 3249 + 1 + /* action code */ 3250 + sizeof(struct ieee80211_twt_setup) + 3251 + 2 /* TWT req_type agrt */) 3252 + break; 3253 + 3254 + twt = (void *)mgmt->u.action.u.s1g.variable; 3255 + if (twt->element_id != WLAN_EID_S1G_TWT) 3256 + break; 3257 + 3258 + if (rx->skb->len < IEEE80211_MIN_ACTION_SIZE + 3259 + 4 + /* action code + token + tlv */ 3260 + twt->length) 3261 + break; 3262 + 3263 + return true; /* queue the frame */ 3264 + } 3265 + case WLAN_S1G_TWT_TEARDOWN: 3266 + if (rx->skb->len < IEEE80211_MIN_ACTION_SIZE + 2) 3267 + break; 3268 + 3269 + return true; /* queue the frame */ 3270 + default: 3271 + break; 3272 + } 3273 + 3274 + return false; 3275 + } 3276 + 3215 3277 static ieee80211_rx_result debug_noinline 3216 3278 ieee80211_rx_h_action(struct ieee80211_rx_data *rx) 3217 3279 { ··· 3553 3491 !mesh_path_sel_is_hwmp(sdata)) 3554 3492 break; 3555 3493 goto queue; 3494 + case WLAN_CATEGORY_S1G: 3495 + switch (mgmt->u.action.u.s1g.action_code) { 3496 + case WLAN_S1G_TWT_SETUP: 3497 + case WLAN_S1G_TWT_TEARDOWN: 3498 + if (ieee80211_process_rx_twt_action(rx)) 3499 + goto queue; 3500 + break; 3501 + default: 3502 + break; 3503 + } 3504 + break; 3556 3505 } 3557 3506 3558 3507 return RX_CONTINUE;
+180
net/mac80211/s1g.c
··· 6 6 #include <linux/ieee80211.h> 7 7 #include <net/mac80211.h> 8 8 #include "ieee80211_i.h" 9 + #include "driver-ops.h" 9 10 10 11 void ieee80211_s1g_sta_rate_init(struct sta_info *sta) 11 12 { ··· 14 13 sta->tx_stats.last_rate.flags |= IEEE80211_TX_RC_S1G_MCS; 15 14 sta->rx_stats.last_rate = 16 15 STA_STATS_FIELD(TYPE, STA_STATS_RATE_TYPE_S1G); 16 + } 17 + 18 + bool ieee80211_s1g_is_twt_setup(struct sk_buff *skb) 19 + { 20 + struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; 21 + 22 + if (likely(!ieee80211_is_action(mgmt->frame_control))) 23 + return false; 24 + 25 + if (likely(mgmt->u.action.category != WLAN_CATEGORY_S1G)) 26 + return false; 27 + 28 + return mgmt->u.action.u.s1g.action_code == WLAN_S1G_TWT_SETUP; 29 + } 30 + 31 + static void 32 + ieee80211_s1g_send_twt_setup(struct ieee80211_sub_if_data *sdata, const u8 *da, 33 + const u8 *bssid, struct ieee80211_twt_setup *twt) 34 + { 35 + int len = IEEE80211_MIN_ACTION_SIZE + 4 + twt->length; 36 + struct ieee80211_local *local = sdata->local; 37 + struct ieee80211_mgmt *mgmt; 38 + struct sk_buff *skb; 39 + 40 + skb = dev_alloc_skb(local->hw.extra_tx_headroom + len); 41 + if (!skb) 42 + return; 43 + 44 + skb_reserve(skb, local->hw.extra_tx_headroom); 45 + mgmt = skb_put_zero(skb, len); 46 + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | 47 + IEEE80211_STYPE_ACTION); 48 + memcpy(mgmt->da, da, ETH_ALEN); 49 + memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); 50 + memcpy(mgmt->bssid, bssid, ETH_ALEN); 51 + 52 + mgmt->u.action.category = WLAN_CATEGORY_S1G; 53 + mgmt->u.action.u.s1g.action_code = WLAN_S1G_TWT_SETUP; 54 + memcpy(mgmt->u.action.u.s1g.variable, twt, 3 + twt->length); 55 + 56 + IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT | 57 + IEEE80211_TX_INTFL_MLME_CONN_TX | 58 + IEEE80211_TX_CTL_REQ_TX_STATUS; 59 + ieee80211_tx_skb(sdata, skb); 60 + } 61 + 62 + static void 63 + ieee80211_s1g_send_twt_teardown(struct ieee80211_sub_if_data *sdata, 64 + const u8 *da, const u8 *bssid, u8 flowid) 65 + { 66 + struct ieee80211_local *local = sdata->local; 67 + struct ieee80211_mgmt *mgmt; 68 + struct sk_buff *skb; 69 + u8 *id; 70 + 71 + skb = dev_alloc_skb(local->hw.extra_tx_headroom + 72 + IEEE80211_MIN_ACTION_SIZE + 2); 73 + if (!skb) 74 + return; 75 + 76 + skb_reserve(skb, local->hw.extra_tx_headroom); 77 + mgmt = skb_put_zero(skb, IEEE80211_MIN_ACTION_SIZE + 2); 78 + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | 79 + IEEE80211_STYPE_ACTION); 80 + memcpy(mgmt->da, da, ETH_ALEN); 81 + memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); 82 + memcpy(mgmt->bssid, bssid, ETH_ALEN); 83 + 84 + mgmt->u.action.category = WLAN_CATEGORY_S1G; 85 + mgmt->u.action.u.s1g.action_code = WLAN_S1G_TWT_TEARDOWN; 86 + id = (u8 *)mgmt->u.action.u.s1g.variable; 87 + *id = flowid; 88 + 89 + IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT | 90 + IEEE80211_TX_CTL_REQ_TX_STATUS; 91 + ieee80211_tx_skb(sdata, skb); 92 + } 93 + 94 + static void 95 + ieee80211_s1g_rx_twt_setup(struct ieee80211_sub_if_data *sdata, 96 + struct sta_info *sta, struct sk_buff *skb) 97 + { 98 + struct ieee80211_mgmt *mgmt = (void *)skb->data; 99 + struct ieee80211_twt_setup *twt = (void *)mgmt->u.action.u.s1g.variable; 100 + struct ieee80211_twt_params *twt_agrt = (void *)twt->params; 101 + 102 + twt_agrt->req_type &= cpu_to_le16(~IEEE80211_TWT_REQTYPE_REQUEST); 103 + 104 + /* broadcast TWT not supported yet */ 105 + if (twt->control & IEEE80211_TWT_CONTROL_NEG_TYPE_BROADCAST) { 106 + le16p_replace_bits(&twt_agrt->req_type, 107 + TWT_SETUP_CMD_REJECT, 108 + IEEE80211_TWT_REQTYPE_SETUP_CMD); 109 + goto out; 110 + } 111 + 112 + drv_add_twt_setup(sdata->local, sdata, &sta->sta, twt); 113 + out: 114 + ieee80211_s1g_send_twt_setup(sdata, mgmt->sa, sdata->vif.addr, twt); 115 + } 116 + 117 + static void 118 + ieee80211_s1g_rx_twt_teardown(struct ieee80211_sub_if_data *sdata, 119 + struct sta_info *sta, struct sk_buff *skb) 120 + { 121 + struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; 122 + 123 + drv_twt_teardown_request(sdata->local, sdata, &sta->sta, 124 + mgmt->u.action.u.s1g.variable[0]); 125 + } 126 + 127 + static void 128 + ieee80211_s1g_tx_twt_setup_fail(struct ieee80211_sub_if_data *sdata, 129 + struct sta_info *sta, struct sk_buff *skb) 130 + { 131 + struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; 132 + struct ieee80211_twt_setup *twt = (void *)mgmt->u.action.u.s1g.variable; 133 + struct ieee80211_twt_params *twt_agrt = (void *)twt->params; 134 + u8 flowid = le16_get_bits(twt_agrt->req_type, 135 + IEEE80211_TWT_REQTYPE_FLOWID); 136 + 137 + drv_twt_teardown_request(sdata->local, sdata, &sta->sta, flowid); 138 + 139 + ieee80211_s1g_send_twt_teardown(sdata, mgmt->sa, sdata->vif.addr, 140 + flowid); 141 + } 142 + 143 + void ieee80211_s1g_rx_twt_action(struct ieee80211_sub_if_data *sdata, 144 + struct sk_buff *skb) 145 + { 146 + struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; 147 + struct ieee80211_local *local = sdata->local; 148 + struct sta_info *sta; 149 + 150 + mutex_lock(&local->sta_mtx); 151 + 152 + sta = sta_info_get_bss(sdata, mgmt->sa); 153 + if (!sta) 154 + goto out; 155 + 156 + switch (mgmt->u.action.u.s1g.action_code) { 157 + case WLAN_S1G_TWT_SETUP: 158 + ieee80211_s1g_rx_twt_setup(sdata, sta, skb); 159 + break; 160 + case WLAN_S1G_TWT_TEARDOWN: 161 + ieee80211_s1g_rx_twt_teardown(sdata, sta, skb); 162 + break; 163 + default: 164 + break; 165 + } 166 + 167 + out: 168 + mutex_unlock(&local->sta_mtx); 169 + } 170 + 171 + void ieee80211_s1g_status_twt_action(struct ieee80211_sub_if_data *sdata, 172 + struct sk_buff *skb) 173 + { 174 + struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; 175 + struct ieee80211_local *local = sdata->local; 176 + struct sta_info *sta; 177 + 178 + mutex_lock(&local->sta_mtx); 179 + 180 + sta = sta_info_get_bss(sdata, mgmt->da); 181 + if (!sta) 182 + goto out; 183 + 184 + switch (mgmt->u.action.u.s1g.action_code) { 185 + case WLAN_S1G_TWT_SETUP: 186 + /* process failed twt setup frames */ 187 + ieee80211_s1g_tx_twt_setup_fail(sdata, sta, skb); 188 + break; 189 + default: 190 + break; 191 + } 192 + 193 + out: 194 + mutex_unlock(&local->sta_mtx); 17 195 }
+15 -2
net/mac80211/status.c
··· 705 705 /* Check to see if packet is a TDLS teardown packet */ 706 706 if (ieee80211_is_data(hdr->frame_control) && 707 707 (ieee80211_get_tdls_action(skb, hdr_size) == 708 - WLAN_TDLS_TEARDOWN)) 708 + WLAN_TDLS_TEARDOWN)) { 709 709 ieee80211_tdls_td_tx_handle(local, sdata, skb, 710 710 info->flags); 711 - else 711 + } else if (ieee80211_s1g_is_twt_setup(skb)) { 712 + if (!acked) { 713 + struct sk_buff *qskb; 714 + 715 + qskb = skb_clone(skb, GFP_ATOMIC); 716 + if (qskb) { 717 + skb_queue_tail(&sdata->status_queue, 718 + qskb); 719 + ieee80211_queue_work(&local->hw, 720 + &sdata->work); 721 + } 722 + } 723 + } else { 712 724 ieee80211_mgd_conn_tx_status(sdata, 713 725 hdr->frame_control, 714 726 acked); 727 + } 715 728 } 716 729 717 730 rcu_read_unlock();
+67
net/mac80211/trace.h
··· 2825 2825 TP_ARGS(local, sdata, sta, enabled) 2826 2826 ); 2827 2827 2828 + TRACE_EVENT(drv_add_twt_setup, 2829 + TP_PROTO(struct ieee80211_local *local, 2830 + struct ieee80211_sta *sta, 2831 + struct ieee80211_twt_setup *twt, 2832 + struct ieee80211_twt_params *twt_agrt), 2833 + 2834 + TP_ARGS(local, sta, twt, twt_agrt), 2835 + 2836 + TP_STRUCT__entry( 2837 + LOCAL_ENTRY 2838 + STA_ENTRY 2839 + __field(u8, dialog_token) 2840 + __field(u8, control) 2841 + __field(__le16, req_type) 2842 + __field(__le64, twt) 2843 + __field(u8, duration) 2844 + __field(__le16, mantissa) 2845 + __field(u8, channel) 2846 + ), 2847 + 2848 + TP_fast_assign( 2849 + LOCAL_ASSIGN; 2850 + STA_ASSIGN; 2851 + __entry->dialog_token = twt->dialog_token; 2852 + __entry->control = twt->control; 2853 + __entry->req_type = twt_agrt->req_type; 2854 + __entry->twt = twt_agrt->twt; 2855 + __entry->duration = twt_agrt->min_twt_dur; 2856 + __entry->mantissa = twt_agrt->mantissa; 2857 + __entry->channel = twt_agrt->channel; 2858 + ), 2859 + 2860 + TP_printk( 2861 + LOCAL_PR_FMT STA_PR_FMT 2862 + " token:%d control:0x%02x req_type:0x%04x" 2863 + " twt:%llu duration:%d mantissa:%d channel:%d", 2864 + LOCAL_PR_ARG, STA_PR_ARG, __entry->dialog_token, 2865 + __entry->control, le16_to_cpu(__entry->req_type), 2866 + le64_to_cpu(__entry->twt), __entry->duration, 2867 + le16_to_cpu(__entry->mantissa), __entry->channel 2868 + ) 2869 + ); 2870 + 2871 + TRACE_EVENT(drv_twt_teardown_request, 2872 + TP_PROTO(struct ieee80211_local *local, 2873 + struct ieee80211_sta *sta, u8 flowid), 2874 + 2875 + TP_ARGS(local, sta, flowid), 2876 + 2877 + TP_STRUCT__entry( 2878 + LOCAL_ENTRY 2879 + STA_ENTRY 2880 + __field(u8, flowid) 2881 + ), 2882 + 2883 + TP_fast_assign( 2884 + LOCAL_ASSIGN; 2885 + STA_ASSIGN; 2886 + __entry->flowid = flowid; 2887 + ), 2888 + 2889 + TP_printk( 2890 + LOCAL_PR_FMT STA_PR_FMT " flowid:%d", 2891 + LOCAL_PR_ARG, STA_PR_ARG, __entry->flowid 2892 + ) 2893 + ); 2894 + 2828 2895 #endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */ 2829 2896 2830 2897 #undef TRACE_INCLUDE_PATH
+12
net/mac80211/util.c
··· 1336 1336 elems->rsnx = pos; 1337 1337 elems->rsnx_len = elen; 1338 1338 break; 1339 + case WLAN_EID_TX_POWER_ENVELOPE: 1340 + if (elen < 1 || 1341 + elen > sizeof(struct ieee80211_tx_pwr_env)) 1342 + break; 1343 + 1344 + if (elems->tx_pwr_env_num >= ARRAY_SIZE(elems->tx_pwr_env)) 1345 + break; 1346 + 1347 + elems->tx_pwr_env[elems->tx_pwr_env_num] = (void *)pos; 1348 + elems->tx_pwr_env_len[elems->tx_pwr_env_num] = elen; 1349 + elems->tx_pwr_env_num++; 1350 + break; 1339 1351 case WLAN_EID_EXTENSION: 1340 1352 ieee80211_parse_extension_element(calc_crc ? 1341 1353 &crc : NULL,
+8 -1
net/wireless/reg.c
··· 171 171 { 172 172 const struct ieee80211_regdomain *regd = NULL; 173 173 const struct ieee80211_regdomain *wiphy_regd = NULL; 174 + enum nl80211_dfs_regions dfs_region; 174 175 175 176 rcu_read_lock(); 176 177 regd = get_cfg80211_regdom(); 178 + dfs_region = regd->dfs_region; 177 179 178 180 if (!wiphy) 179 181 goto out; ··· 183 181 wiphy_regd = get_wiphy_regdom(wiphy); 184 182 if (!wiphy_regd) 185 183 goto out; 184 + 185 + if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED) { 186 + dfs_region = wiphy_regd->dfs_region; 187 + goto out; 188 + } 186 189 187 190 if (wiphy_regd->dfs_region == regd->dfs_region) 188 191 goto out; ··· 200 193 out: 201 194 rcu_read_unlock(); 202 195 203 - return regd->dfs_region; 196 + return dfs_region; 204 197 } 205 198 206 199 static void rcu_free_regdom(const struct ieee80211_regdomain *r)