1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * AP handling 4 * 5 * Partially 6 * Copyright (C) 2026 Intel Corporation 7 */ 8 9 #include "driver-ops.h" 10 #include "ieee80211_i.h" 11 12 static void 13 ieee80211_send_eml_op_mode_notif(struct ieee80211_sub_if_data *sdata, 14 struct ieee80211_mgmt *req, int opt_len) 15 { 16 int len = IEEE80211_MIN_ACTION_SIZE(eml_omn); 17 struct ieee80211_local *local = sdata->local; 18 struct ieee80211_mgmt *mgmt; 19 struct sk_buff *skb; 20 21 len += opt_len; /* optional len */ 22 skb = dev_alloc_skb(local->tx_headroom + len); 23 if (!skb) 24 return; 25 26 skb_reserve(skb, local->tx_headroom); 27 mgmt = skb_put_zero(skb, len); 28 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | 29 IEEE80211_STYPE_ACTION); 30 memcpy(mgmt->da, req->sa, ETH_ALEN); 31 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); 32 memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); 33 34 mgmt->u.action.category = WLAN_CATEGORY_PROTECTED_EHT; 35 mgmt->u.action.action_code = 36 WLAN_PROTECTED_EHT_ACTION_EML_OP_MODE_NOTIF; 37 mgmt->u.action.eml_omn.dialog_token = 38 req->u.action.eml_omn.dialog_token; 39 mgmt->u.action.eml_omn.control = req->u.action.eml_omn.control & 40 ~(IEEE80211_EML_CTRL_EMLSR_PARAM_UPDATE | 41 IEEE80211_EML_CTRL_INDEV_COEX_ACT); 42 /* Copy optional fields from the received notification frame */ 43 memcpy(mgmt->u.action.eml_omn.variable, 44 req->u.action.eml_omn.variable, opt_len); 45 46 ieee80211_tx_skb(sdata, skb); 47 } 48 49 static void 50 ieee80211_rx_eml_op_mode_notif(struct ieee80211_sub_if_data *sdata, 51 struct sk_buff *skb) 52 { 53 int len = IEEE80211_MIN_ACTION_SIZE(eml_omn); 54 enum nl80211_iftype type = ieee80211_vif_type_p2p(&sdata->vif); 55 struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); 56 const struct wiphy_iftype_ext_capab *ift_ext_capa; 57 struct ieee80211_mgmt *mgmt = (void *)skb->data; 58 struct ieee80211_local *local = sdata->local; 59 u8 control = mgmt->u.action.eml_omn.control; 60 u8 *ptr = mgmt->u.action.eml_omn.variable; 61 struct ieee80211_eml_params eml_params = { 62 .link_id = status->link_id, 63 .control = control, 64 }; 65 struct sta_info *sta; 66 int opt_len = 0; 67 68 if (!ieee80211_vif_is_mld(&sdata->vif)) 69 return; 70 71 /* eMLSR and eMLMR can't be enabled at the same time */ 72 if ((control & IEEE80211_EML_CTRL_EMLSR_MODE) && 73 (control & IEEE80211_EML_CTRL_EMLMR_MODE)) 74 return; 75 76 if ((control & IEEE80211_EML_CTRL_EMLMR_MODE) && 77 (control & IEEE80211_EML_CTRL_EMLSR_PARAM_UPDATE)) 78 return; 79 80 ift_ext_capa = cfg80211_get_iftype_ext_capa(local->hw.wiphy, type); 81 if (!ift_ext_capa) 82 return; 83 84 if (!status->link_valid) 85 return; 86 87 sta = sta_info_get_bss(sdata, mgmt->sa); 88 if (!sta) 89 return; 90 91 if (control & IEEE80211_EML_CTRL_EMLSR_MODE) { 92 u8 emlsr_param_update_len; 93 94 if (!(ift_ext_capa->eml_capabilities & 95 IEEE80211_EML_CAP_EMLSR_SUPP)) 96 return; 97 98 opt_len += sizeof(__le16); /* eMLSR link_bitmap */ 99 /* 100 * eMLSR param update field is not part of Notification frame 101 * sent by the AP to client so account it separately. 102 */ 103 emlsr_param_update_len = 104 !!(control & IEEE80211_EML_CTRL_EMLSR_PARAM_UPDATE); 105 106 if (skb->len < len + opt_len + emlsr_param_update_len) 107 return; 108 109 if (control & IEEE80211_EML_CTRL_EMLSR_PARAM_UPDATE) { 110 u8 pad_delay, trans_delay; 111 112 pad_delay = u8_get_bits(ptr[2], 113 IEEE80211_EML_EMLSR_PAD_DELAY); 114 if (pad_delay > 115 IEEE80211_EML_CAP_EML_PADDING_DELAY_256US) 116 return; 117 118 trans_delay = u8_get_bits(ptr[2], 119 IEEE80211_EML_EMLSR_TRANS_DELAY); 120 if (trans_delay > 121 IEEE80211_EML_CAP_EMLSR_TRANSITION_DELAY_256US) 122 return; 123 124 /* Update sta padding and transition delay */ 125 sta->sta.eml_cap = 126 u8_replace_bits(sta->sta.eml_cap, 127 pad_delay, 128 IEEE80211_EML_CAP_EML_PADDING_DELAY); 129 sta->sta.eml_cap = 130 u8_replace_bits(sta->sta.eml_cap, 131 trans_delay, 132 IEEE80211_EML_CAP_EML_TRANSITION_DELAY); 133 } 134 } 135 136 if (control & IEEE80211_EML_CTRL_EMLMR_MODE) { 137 u8 mcs_map_size; 138 int i; 139 140 if (!(ift_ext_capa->eml_capabilities & 141 IEEE80211_EML_CAP_EMLMR_SUPPORT)) 142 return; 143 144 opt_len += sizeof(__le16); /* eMLMR link_bitmap */ 145 opt_len++; /* eMLMR mcs_map_count */ 146 if (skb->len < len + opt_len) 147 return; 148 149 eml_params.emlmr_mcs_map_count = ptr[2]; 150 if (eml_params.emlmr_mcs_map_count > 2) 151 return; 152 153 mcs_map_size = 3 * (1 + eml_params.emlmr_mcs_map_count); 154 opt_len += mcs_map_size; 155 if (skb->len < len + opt_len) 156 return; 157 158 for (i = 0; i < mcs_map_size; i++) { 159 u8 rx_mcs, tx_mcs; 160 161 rx_mcs = u8_get_bits(ptr[3 + i], 162 IEEE80211_EML_EMLMR_RX_MCS_MAP); 163 if (rx_mcs > 8) 164 return; 165 166 tx_mcs = u8_get_bits(ptr[3 + i], 167 IEEE80211_EML_EMLMR_TX_MCS_MAP); 168 if (tx_mcs > 8) 169 return; 170 } 171 172 memcpy(eml_params.emlmr_mcs_map_bw, &ptr[3], mcs_map_size); 173 } 174 175 if ((control & IEEE80211_EML_CTRL_EMLSR_MODE) || 176 (control & IEEE80211_EML_CTRL_EMLMR_MODE)) { 177 eml_params.link_bitmap = get_unaligned_le16(ptr); 178 if ((eml_params.link_bitmap & sdata->vif.active_links) != 179 eml_params.link_bitmap) 180 return; 181 } 182 183 if (drv_set_eml_op_mode(sdata, &sta->sta, &eml_params)) 184 return; 185 186 ieee80211_send_eml_op_mode_notif(sdata, mgmt, opt_len); 187 } 188 189 void ieee80211_ap_rx_queued_frame(struct ieee80211_sub_if_data *sdata, 190 struct sk_buff *skb) 191 { 192 struct ieee80211_mgmt *mgmt = (void *)skb->data; 193 194 /* rx.c cannot queue any non-action frames to AP interfaces */ 195 if (WARN_ON(!ieee80211_is_action(mgmt->frame_control))) 196 return; 197 198 switch (mgmt->u.action.category) { 199 case WLAN_CATEGORY_PROTECTED_EHT: 200 switch (mgmt->u.action.action_code) { 201 case WLAN_PROTECTED_EHT_ACTION_EML_OP_MODE_NOTIF: 202 ieee80211_rx_eml_op_mode_notif(sdata, skb); 203 break; 204 } 205 break; 206 } 207 } 208