1 /* 2 * Copyright (c) 2011-2012,2016-2020 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #ifndef _WLAN_HDD_WMM_H 21 #define _WLAN_HDD_WMM_H 22 23 /** 24 * DOC: HDD WMM 25 * 26 * This module (wlan_hdd_wmm.h interface + wlan_hdd_wmm.c implementation) 27 * houses all the logic for WMM in HDD. 28 * 29 * On the control path, it has the logic to setup QoS, modify QoS and delete 30 * QoS (QoS here refers to a TSPEC). The setup QoS comes in two flavors: an 31 * explicit application invoked and an internal HDD invoked. The implicit QoS 32 * is for applications that do NOT call the custom QCT WLAN OIDs for QoS but 33 * which DO mark their traffic for priortization. It also has logic to start, 34 * update and stop the U-APSD trigger frame generation. It also has logic to 35 * read WMM related config parameters from the registry. 36 * 37 * On the data path, it has the logic to figure out the WMM AC of an egress 38 * packet and when to signal TL to serve a particular AC queue. It also has the 39 * logic to retrieve a packet based on WMM priority in response to a fetch from 40 * TL. 41 * 42 * The remaining functions are utility functions for information hiding. 43 */ 44 45 /* Include files */ 46 #include <linux/workqueue.h> 47 #include <linux/list.h> 48 #include <wlan_hdd_main.h> 49 #include <wlan_hdd_wext.h> 50 #include <sme_qos_api.h> 51 #include <qca_vendor.h> 52 53 /*Maximum number of ACs */ 54 #define WLAN_MAX_AC 4 55 56 57 /* Preprocessor Definitions and Constants */ 58 59 /* #define HDD_WMM_DEBUG 1 */ 60 61 #define HDD_WMM_CTX_MAGIC 0x574d4d58 /* "WMMX" */ 62 63 #define HDD_WMM_HANDLE_IMPLICIT 0xFFFFFFFF 64 65 #define HDD_WLAN_INVALID_STA_ID 0xFF 66 67 /* Type Declarations */ 68 69 /** 70 * enum hdd_wmm_user_mode - WMM modes of operation 71 * 72 * @HDD_WMM_USER_MODE_AUTO: STA can associate with any AP, & HDD looks at 73 * the SME notification after association to find out if associated 74 * with QAP and acts accordingly 75 * @HDD_WMM_USER_MODE_QBSS_ONLY: SME will add the extra logic to make sure 76 * STA associates with a QAP only 77 * @HDD_WMM_USER_MODE_NO_QOS: Join any AP, but uapsd is disabled 78 */ 79 enum hdd_wmm_user_mode { 80 HDD_WMM_USER_MODE_AUTO = 0, 81 HDD_WMM_USER_MODE_QBSS_ONLY = 1, 82 HDD_WMM_USER_MODE_NO_QOS = 2, 83 }; 84 85 /* UAPSD Mask bits */ 86 /* (Bit0:VO; Bit1:VI; Bit2:BK; Bit3:BE all other bits are ignored) */ 87 #define HDD_AC_VO 0x1 88 #define HDD_AC_VI 0x2 89 #define HDD_AC_BK 0x4 90 #define HDD_AC_BE 0x8 91 92 /** 93 * enum hdd_wmm_linuxac: AC/Queue Index values for Linux Qdisc to 94 * operate on different traffic. 95 * @HDD_LINUX_AC_VO: voice priority 96 * @HDD_LINUX_AC_VI: video priority 97 * @HDD_LINUX_AC_BE: best effort priority 98 * @HDD_LINUX_AC_BK: background priority 99 * @HDD_LINUX_AC_HI_PRIO: unclassified high priority 100 */ 101 enum hdd_wmm_linuxac { 102 HDD_LINUX_AC_VO = 0, 103 HDD_LINUX_AC_VI = 1, 104 HDD_LINUX_AC_BE = 2, 105 HDD_LINUX_AC_BK = 3, 106 HDD_LINUX_AC_HI_PRIO = 4, 107 }; 108 109 /** 110 * struct hdd_wmm_qos_context - HDD WMM QoS Context 111 * 112 * This structure holds the context for a single flow which has either 113 * been configured explicitly from userspace or implicitly via the 114 * Implicit QoS feature. 115 * 116 * @node: list node which can be used to put the context into a list 117 * of contexts 118 * @handle: identifier which uniquely identifies this context to userspace 119 * @flow_id: identifier which uniquely identifies this flow to SME 120 * @adapter: adapter upon which this flow was configured 121 * @ac_type: access category for this flow 122 * @status: the status of the last operation performed on this flow by SME 123 * @implicit_qos_work: work structure used for deferring implicit QoS work 124 * from softirq context to thread context 125 * @magic: magic number used to verify that this is a valid context when 126 * referenced anonymously 127 * @is_inactivity_timer_running: true if inactivity timer is running 128 * @ts_id: identifier which gets used at time of DEL request 129 */ 130 struct hdd_wmm_qos_context { 131 struct list_head node; 132 uint32_t handle; 133 uint32_t flow_id; 134 struct hdd_adapter *adapter; 135 sme_ac_enum_type ac_type; 136 hdd_wlan_wmm_status_e status; 137 struct work_struct implicit_qos_work; 138 uint32_t magic; 139 bool is_inactivity_timer_running; 140 uint8_t ts_id; 141 }; 142 143 /** 144 * struct hdd_wmm_ac_status - WMM related per-AC state & status info 145 * @is_access_required: does the AP require access to this AC? 146 * @is_access_needed: does the worker thread need to acquire access to 147 * this AC? 148 * @is_access_pending: is implicit QoS negotiation currently taking place? 149 * @has_access_failed: has implicit QoS negotiation already failed? 150 * @was_access_granted: has implicit QoS negotiation already succeeded? 151 * @is_access_allowed: is access to this AC allowed, either because we 152 * are not doing WMM, we are not doing implicit QoS, implicit QoS has 153 * completed, or explicit QoS has completed? 154 * @is_tspec_valid: is the tspec valid? 155 * @is_uapsd_info_valid: are the UAPSD-related fields valid? 156 * @tspec: current (possibly aggregate) Tspec for this AC 157 * @is_uapsd_enabled: is UAPSD enabled on this AC? 158 * @uapsd_service_interval: service interval for this AC 159 * @uapsd_suspension_interval: suspension interval for this AC 160 * @uapsd_direction: direction for this AC 161 * @inactivity_time: inactivity time for this AC 162 * @last_traffic_count: TX counter used for inactivity detection 163 * @inactivity_timer: timer used for inactivity detection 164 */ 165 struct hdd_wmm_ac_status { 166 bool is_access_required; 167 bool is_access_needed; 168 bool is_access_pending; 169 bool has_access_failed; 170 bool was_access_granted; 171 bool is_access_allowed; 172 bool is_tspec_valid; 173 bool is_uapsd_info_valid; 174 struct sme_qos_wmmtspecinfo tspec; 175 bool is_uapsd_enabled; 176 uint32_t uapsd_service_interval; 177 uint32_t uapsd_suspension_interval; 178 enum sme_qos_wmm_dir_type uapsd_direction; 179 180 #ifdef FEATURE_WLAN_ESE 181 uint32_t inactivity_time; 182 uint32_t last_traffic_count; 183 qdf_mc_timer_t inactivity_timer; 184 #endif 185 }; 186 187 /** 188 * struct hdd_wmm_status - WMM status maintained per-adapter 189 * @context_list: list of WMM contexts active on the adapter 190 * @mutex: mutex used for exclusive access to this adapter's WMM status 191 * @ac_status: per-AC WMM status 192 * @qap: is this connected to a QoS-enabled AP? 193 * @qos_connection: is this a QoS connection? 194 */ 195 struct hdd_wmm_status { 196 struct list_head context_list; 197 struct mutex mutex; 198 struct hdd_wmm_ac_status ac_status[WLAN_MAX_AC]; 199 bool qap; 200 bool qos_connection; 201 }; 202 203 extern const uint8_t hdd_qdisc_ac_to_tl_ac[]; 204 extern const uint8_t hdd_wmm_up_to_ac_map[]; 205 extern const uint8_t hdd_linux_up_to_ac_map[]; 206 207 /** 208 * hdd_wmmps_helper() - Function to set uapsd psb dynamically 209 * 210 * @adapter: [in] pointer to adapter structure 211 * @ptr: [in] pointer to command buffer 212 * 213 * Return: Zero on success, appropriate error on failure. 214 */ 215 int hdd_wmmps_helper(struct hdd_adapter *adapter, uint8_t *ptr); 216 217 /** 218 * hdd_send_dscp_up_map_to_fw() - send dscp to up map to FW 219 * @adapter : [in] pointer to Adapter context 220 * 221 * This function will send the WMM DSCP configuration of an 222 * adapter to FW. 223 * 224 * Return: QDF_STATUS enumeration 225 */ 226 QDF_STATUS hdd_send_dscp_up_map_to_fw(struct hdd_adapter *adapter); 227 228 /** 229 * hdd_wmm_dscp_initial_state() - initialize the WMM DSCP configuration 230 * @adapter : [in] pointer to Adapter context 231 * 232 * This function will initialize the WMM DSCP configuration of an 233 * adapter to an initial state. The configuration can later be 234 * overwritten via application APIs or via QoS Map sent OTA. 235 * 236 * Return: QDF_STATUS enumeration 237 */ 238 QDF_STATUS hdd_wmm_dscp_initial_state(struct hdd_adapter *adapter); 239 240 /** 241 * hdd_wmm_adapter_init() - initialize the WMM configuration of an adapter 242 * @adapter: [in] pointer to Adapter context 243 * 244 * This function will initialize the WMM configuration and status of an 245 * adapter to an initial state. The configuration can later be 246 * overwritten via application APIs 247 * 248 * Return: QDF_STATUS enumeration 249 */ 250 QDF_STATUS hdd_wmm_adapter_init(struct hdd_adapter *adapter); 251 252 /** 253 * hdd_wmm_adapter_close() - WMM close function 254 * @adapter: [in] pointer to adapter context 255 * 256 * Function which will perform any necessary work to to clean up the 257 * WMM functionality prior to the kernel module unload. 258 * 259 * Return: QDF_STATUS enumeration 260 */ 261 QDF_STATUS hdd_wmm_adapter_close(struct hdd_adapter *adapter); 262 263 /** 264 * hdd_select_queue() - Return queue to be used. 265 * @dev: Pointer to the WLAN device. 266 * @skb: Pointer to OS packet (sk_buff). 267 * @sb_dev: Pointer to subordinate device (unused) 268 * 269 * This function is registered with the Linux OS for network 270 * core to decide which queue to use for the skb. 271 * 272 * Return: Qdisc queue index. 273 */ 274 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)) 275 uint16_t hdd_select_queue(struct net_device *dev, struct sk_buff *skb, 276 struct net_device *sb_dev); 277 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)) 278 uint16_t hdd_select_queue(struct net_device *dev, struct sk_buff *skb, 279 struct net_device *sb_dev, 280 select_queue_fallback_t fallback); 281 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) 282 uint16_t hdd_select_queue(struct net_device *dev, struct sk_buff *skb, 283 void *accel_priv, select_queue_fallback_t fallback); 284 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)) 285 uint16_t hdd_select_queue(struct net_device *dev, struct sk_buff *skb, 286 void *accel_priv); 287 #else 288 uint16_t hdd_select_queue(struct net_device *dev, struct sk_buff *skb); 289 #endif 290 291 /** 292 * hdd_wmm_select_queue() - Function which will classify the packet 293 * according to linux qdisc expectation. 294 * 295 * @dev: [in] pointer to net_device structure 296 * @skb: [in] pointer to os packet 297 * 298 * Return: Qdisc queue index 299 */ 300 uint16_t hdd_wmm_select_queue(struct net_device *dev, 301 struct sk_buff *skb); 302 303 /** 304 * hdd_wmm_acquire_access_required() - Function which will determine 305 * acquire admittance for a WMM AC is required or not based on psb configuration 306 * done in framework 307 * 308 * @adapter: [in] pointer to adapter structure 309 * @ac_type: [in] WMM AC type of OS packet 310 * 311 * Return: void 312 */ 313 void hdd_wmm_acquire_access_required(struct hdd_adapter *adapter, 314 sme_ac_enum_type ac_type); 315 316 /** 317 * hdd_wmm_acquire_access() - Function which will attempt to acquire 318 * admittance for a WMM AC 319 * 320 * @adapter: [in] pointer to adapter context 321 * @ac_type: [in] WMM AC type of OS packet 322 * @granted: [out] pointer to bool flag when indicates if access 323 * has been granted or not 324 * 325 * Return: QDF_STATUS enumeration 326 */ 327 QDF_STATUS hdd_wmm_acquire_access(struct hdd_adapter *adapter, 328 sme_ac_enum_type ac_type, bool *granted); 329 330 /** 331 * hdd_wmm_assoc() - Function which will handle the housekeeping 332 * required by WMM when association takes place 333 * 334 * @adapter: pointer to adapter context 335 * @is_reassoc: is this reassoc scenario 336 * @uapsd_mask : Negotiated uapsd msk 337 * 338 * Return: QDF_STATUS enumeration 339 */ 340 QDF_STATUS hdd_wmm_assoc(struct hdd_adapter *adapter, 341 bool is_reassoc, uint8_t uapsd_mask); 342 343 /** 344 * hdd_wmm_connect() - Function which will handle the housekeeping 345 * required by WMM when a connection is established 346 * 347 * @adapter : [in] pointer to adapter context 348 * @roam_info: [in] pointer to roam information 349 * @bss_type : [in] type of BSS 350 * 351 * Return: QDF_STATUS enumeration 352 */ 353 QDF_STATUS hdd_wmm_connect(struct hdd_adapter *adapter, 354 struct csr_roam_info *roam_info, 355 eCsrRoamBssType bss_type); 356 357 /** 358 * hdd_wmm_is_active() - Function which will determine if WMM is 359 * active on the current connection 360 * 361 * @adapter: [in] pointer to adapter context 362 * 363 * Return: true if WMM is enabled, false if WMM is not enabled 364 */ 365 bool hdd_wmm_is_active(struct hdd_adapter *adapter); 366 367 /** 368 * hdd_wmm_is_acm_allowed() - Function which will determine if WMM is 369 * active on the current connection 370 * 371 * @vdev_id: vdev id 372 * 373 * Return: true if WMM is enabled, false if WMM is not enabled 374 */ 375 bool hdd_wmm_is_acm_allowed(uint8_t vdev_id); 376 377 378 /** 379 * hdd_wmm_addts() - Function which will add a traffic spec at the 380 * request of an application 381 * 382 * @adapter : [in] pointer to adapter context 383 * @handle : [in] handle to uniquely identify a TS 384 * @tspec : [in] pointer to the traffic spec 385 * 386 * Return: HDD_WLAN_WMM_STATUS_* 387 */ 388 hdd_wlan_wmm_status_e hdd_wmm_addts(struct hdd_adapter *adapter, 389 uint32_t handle, 390 struct sme_qos_wmmtspecinfo *tspec); 391 392 /** 393 * hdd_wmm_delts() - Function which will delete a traffic spec at the 394 * request of an application 395 * 396 * @adapter: [in] pointer to adapter context 397 * @handle: [in] handle to uniquely identify a TS 398 * 399 * Return: HDD_WLAN_WMM_STATUS_* 400 */ 401 hdd_wlan_wmm_status_e hdd_wmm_delts(struct hdd_adapter *adapter, 402 uint32_t handle); 403 404 /** 405 * hdd_wmm_checkts() - Function which will return the status of a traffic 406 * spec at the request of an application 407 * 408 * @adapter: [in] pointer to adapter context 409 * @handle: [in] handle to uniquely identify a TS 410 * 411 * Return: HDD_WLAN_WMM_STATUS_* 412 */ 413 hdd_wlan_wmm_status_e hdd_wmm_checkts(struct hdd_adapter *adapter, 414 uint32_t handle); 415 /** 416 * hdd_wmm_adapter_clear() - Function which will clear the WMM status 417 * for all the ACs 418 * 419 * @adapter: [in] pointer to Adapter context 420 * 421 * Return: QDF_STATUS enumeration 422 */ 423 QDF_STATUS hdd_wmm_adapter_clear(struct hdd_adapter *adapter); 424 425 void wlan_hdd_process_peer_unauthorised_pause(struct hdd_adapter *adapter); 426 427 extern const struct nla_policy 428 config_tspec_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_MAX + 1]; 429 430 /** 431 * wlan_hdd_cfg80211_config_tspec() - config tpsec 432 * @wiphy: pointer to wireless wiphy structure. 433 * @wdev: pointer to wireless_dev structure. 434 * @data: pointer to config tspec command parameters. 435 * @data_len: the length in byte of config tspec command parameters. 436 * 437 * Return: An error code or 0 on success. 438 */ 439 int wlan_hdd_cfg80211_config_tspec(struct wiphy *wiphy, 440 struct wireless_dev *wdev, 441 const void *data, int data_len); 442 #ifdef QCA_SUPPORT_TX_MIN_RATES_FOR_SPECIAL_FRAMES 443 /** 444 * hdd_wmm_classify_pkt_cb() - Call back to identify critical packets 445 * @adapter: adapter for which callback is called 446 * @nbuf: skb for which callback is called 447 * 448 * Callback used by intrabss forwarding path to identify critical packets. 449 * QDF_NBUF_CB_TX_EXTRA_IS_CRITICAL is marked 1 for such packets. 450 * The function also populates sb->priority for these packets. 451 * skb->priority is used as TID for these frames during TX. 452 * 453 * Return: None 454 */ 455 void hdd_wmm_classify_pkt_cb(void *adapter, 456 qdf_nbuf_t nbuf); 457 #else 458 static inline hdd_wmm_classify_pkt_cb(void * adapter,qdf_nbuf_t nbuf)459 void hdd_wmm_classify_pkt_cb(void *adapter, 460 qdf_nbuf_t nbuf) 461 { 462 } 463 #endif 464 465 #define FEATURE_WMM_COMMANDS \ 466 { \ 467 .info.vendor_id = QCA_NL80211_VENDOR_ID, \ 468 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_CONFIG_TSPEC, \ 469 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | \ 470 WIPHY_VENDOR_CMD_NEED_NETDEV | \ 471 WIPHY_VENDOR_CMD_NEED_RUNNING, \ 472 .doit = wlan_hdd_cfg80211_config_tspec, \ 473 vendor_command_policy(config_tspec_policy, \ 474 QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_MAX) \ 475 }, 476 477 #endif /* #ifndef _WLAN_HDD_WMM_H */ 478