diff options
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/mvm/mvm.h')
| -rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 1173 |
1 files changed, 918 insertions, 255 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 1dcbb0eb63c3..301d590fe0bd 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2012-2014, 2018-2020 Intel Corporation + * Copyright (C) 2012-2014, 2018-2025 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -9,6 +9,7 @@ #include <linux/list.h> #include <linux/spinlock.h> +#include <linux/cleanup.h> #include <linux/leds.h> #include <linux/in6.h> @@ -16,12 +17,14 @@ #include <linux/thermal.h> #endif +#include <linux/ptp_clock_kernel.h> + #include <linux/ktime.h> #include "iwl-op-mode.h" #include "iwl-trans.h" #include "fw/notif-wait.h" -#include "iwl-eeprom-parse.h" +#include "iwl-nvm-utils.h" #include "fw/file.h" #include "iwl-config.h" #include "sta.h" @@ -38,8 +41,9 @@ #define IWL_MVM_MAX_ADDRESSES 5 /* RSSI offset for WkP */ #define IWL_RSSI_OFFSET 50 +#define IWL_MVM_MISSED_BEACONS_SINCE_RX_THOLD 4 #define IWL_MVM_MISSED_BEACONS_THRESHOLD 8 -#define IWL_MVM_MISSED_BEACONS_THRESHOLD_LONG 16 +#define IWL_MVM_MISSED_BEACONS_THRESHOLD_LONG 19 /* A TimeUnit is 1024 microsecond */ #define MSEC_TO_TU(_msec) (_msec*1000/1024) @@ -71,18 +75,17 @@ /* offchannel queue towards mac80211 */ #define IWL_MVM_OFFCHANNEL_QUEUE 0 +/* invalid value for FW link id */ +#define IWL_MVM_FW_LINK_ID_INVALID 0xff + extern const struct ieee80211_ops iwl_mvm_hw_ops; +extern const struct ieee80211_ops iwl_mvm_mld_hw_ops; /** * struct iwl_mvm_mod_params - module parameters for iwlmvm - * @init_dbg: if true, then the NIC won't be stopped if the INIT fw asserted. - * We will register to mac80211 to have testmode working. The NIC must not - * be up'ed after the INIT fw asserted. This is useful to be able to use - * proprietary tools over testmode to debug the INIT fw. * @power_scheme: one of enum iwl_power_scheme */ struct iwl_mvm_mod_params { - bool init_dbg; int power_scheme; }; extern struct iwl_mvm_mod_params iwlmvm_mod_params; @@ -98,6 +101,9 @@ struct iwl_mvm_phy_ctxt { /* track for RLC config command */ u32 center_freq1; + bool rlc_disabled; + u32 channel_load_by_us; + u32 channel_load_not_by_us; }; struct iwl_mvm_time_event_data { @@ -114,15 +120,16 @@ struct iwl_mvm_time_event_data { * if the te is in the time event list or not (when id == TE_MAX) */ u32 id; + s8 link_id; }; /* Power management */ /** - * enum iwl_power_scheme - * @IWL_POWER_LEVEL_CAM - Continuously Active Mode - * @IWL_POWER_LEVEL_BPS - Balanced Power Save (default) - * @IWL_POWER_LEVEL_LP - Low Power + * enum iwl_power_scheme - iwl power schemes + * @IWL_POWER_SCHEME_CAM: Continuously Active Mode + * @IWL_POWER_SCHEME_BPS: Balanced Power Save (default) + * @IWL_POWER_SCHEME_LP: Low Power */ enum iwl_power_scheme { IWL_POWER_SCHEME_CAM = 1, @@ -130,7 +137,6 @@ enum iwl_power_scheme { IWL_POWER_SCHEME_LP }; -#define IWL_CONN_MAX_LISTEN_INTERVAL 10 #define IWL_UAPSD_MAX_SP IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL #ifdef CONFIG_IWLWIFI_DEBUGFS @@ -211,7 +217,7 @@ enum iwl_bt_force_ant_mode { }; /** - * struct iwl_mvm_low_latency_force - low latency force mode set by debugfs + * enum iwl_mvm_low_latency_force - low latency force mode set by debugfs * @LOW_LATENCY_FORCE_UNSET: unset force mode * @LOW_LATENCY_FORCE_ON: for low latency on * @LOW_LATENCY_FORCE_OFF: for low latency off @@ -225,7 +231,7 @@ enum iwl_mvm_low_latency_force { }; /** -* struct iwl_mvm_low_latency_cause - low latency set causes +* enum iwl_mvm_low_latency_cause - low latency set causes * @LOW_LATENCY_TRAFFIC: indicates low latency traffic was detected * @LOW_LATENCY_DEBUGFS: low latency mode set from debugfs * @LOW_LATENCY_VCMD: low latency mode set from vendor command @@ -246,18 +252,14 @@ enum iwl_mvm_low_latency_cause { }; /** -* struct iwl_mvm_vif_bf_data - beacon filtering related data -* @bf_enabled: indicates if beacon filtering is enabled -* @ba_enabled: indicated if beacon abort is enabled +* struct iwl_mvm_link_bf_data - beacon filtering related data * @ave_beacon_signal: average beacon signal * @last_cqm_event: rssi of the last cqm event * @bt_coex_min_thold: minimum threshold for BT coex * @bt_coex_max_thold: maximum threshold for BT coex * @last_bt_coex_event: rssi of the last BT coex event */ -struct iwl_mvm_vif_bf_data { - bool bf_enabled; - bool ba_enabled; +struct iwl_mvm_link_bf_data { int ave_beacon_signal; int last_cqm_event; int bt_coex_min_thold; @@ -278,11 +280,78 @@ struct iwl_probe_resp_data { }; /** + * struct iwl_mvm_vif_link_info - per link data in Virtual Interface + * @ap_sta_id: the sta_id of the AP - valid only if VIF type is STA + * @fw_link_id: the id of the link according to the FW API + * @bssid: BSSID for this (client) interface + * @bcast_sta: station used for broadcast packets. Used by the following + * vifs: P2P_DEVICE, GO and AP. + * @beacon_stats: beacon statistics, containing the # of received beacons, + * # of received beacons accumulated over FW restart, and the current + * average signal of beacons retrieved from the firmware + * @smps_requests: the SMPS requests of different parts of the driver, + * combined on update to yield the overall request to mac80211. + * @probe_resp_data: data from FW notification to store NOA and CSA related + * data to be inserted into probe response. + * @he_ru_2mhz_block: 26-tone RU OFDMA transmissions should be blocked + * @queue_params: QoS params for this MAC + * @mgmt_queue: queue number for unbufferable management frames + * @igtk: the current IGTK programmed into the firmware + * @active: indicates the link is active in FW (for sanity checking) + * @cab_queue: content-after-beacon (multicast) queue + * @listen_lmac: indicates this link is allocated to the listen LMAC + * @csa_block_tx: we got CSA with mode=1 + * @mcast_sta: multicast station + * @phy_ctxt: phy context allocated to this link, if any + * @bf_data: beacon filtering data + * @average_beacon_energy: average beacon energy for beacons received during + * client connections + */ +struct iwl_mvm_vif_link_info { + u8 bssid[ETH_ALEN]; + u8 ap_sta_id; + u8 fw_link_id; + + struct iwl_mvm_int_sta bcast_sta; + struct iwl_mvm_int_sta mcast_sta; + + struct { + u32 num_beacons, accu_num_beacons; + u8 avg_signal; + } beacon_stats; + + enum ieee80211_smps_mode smps_requests[NUM_IWL_MVM_SMPS_REQ]; + struct iwl_probe_resp_data __rcu *probe_resp_data; + + struct ieee80211_key_conf *igtk; + + bool he_ru_2mhz_block; + bool active; + bool listen_lmac; + bool csa_block_tx; + + u16 cab_queue; + /* Assigned while mac80211 has the link in a channel context, + * or, for P2P Device, while it exists. + */ + struct iwl_mvm_phy_ctxt *phy_ctxt; + /* QoS data from mac80211, need to store this here + * as mac80211 has a separate callback but we need + * to have the data for the MAC context + */ + struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS]; + + u16 mgmt_queue; + + struct iwl_mvm_link_bf_data bf_data; + u32 average_beacon_energy; +}; + +/** * struct iwl_mvm_vif - data per Virtual Interface, it is a MAC context + * @mvm: pointer back to the mvm struct * @id: between 0 and 3 * @color: to solve races upon MAC addition and removal - * @ap_sta_id: the sta_id of the AP - valid only if VIF type is STA - * @bssid: BSSID for this (client) interface * @associated: indicates that we're currently associated, used only for * managing the firmware state in iwl_mvm_bss_info_changed_station() * @ap_assoc_sta_count: count of stations associated to us - valid only @@ -290,7 +359,7 @@ struct iwl_probe_resp_data { * @uploaded: indicates the MAC context has been added to the device * @ap_ibss_active: indicates that AP/IBSS is configured and that the interface * should get quota etc. - * @pm_enabled - Indicate if MAC power management is allowed + * @pm_enabled - indicate if MAC power management is allowed * @monitor_active: indicates that monitor context is configured, and that the * interface should get quota etc. * @low_latency: bit flags for low latency @@ -299,70 +368,86 @@ struct iwl_probe_resp_data { * as a result from low_latency bit flags and takes force into account. * @authorized: indicates the AP station was set to authorized * @ps_disabled: indicates that this interface requires PS to be disabled - * @queue_params: QoS params for this MAC - * @bcast_sta: station used for broadcast packets. Used by the following - * vifs: P2P_DEVICE, GO and AP. - * @beacon_skb: the skb used to hold the AP/GO beacon template - * @smps_requests: the SMPS requests of different parts of the driver, - * combined on update to yield the overall request to mac80211. - * @beacon_stats: beacon statistics, containing the # of received beacons, - * # of received beacons accumulated over FW restart, and the current - * average signal of beacons retrieved from the firmware + * @csa_countdown: indicates that CSA countdown may be started * @csa_failed: CSA failed to schedule time event, report an error later + * @csa_bcn_pending: indicates that we are waiting for a beacon on a new channel + * @csa_blocks_tx: CSA is blocking TX * @features: hw features active for this vif - * @probe_resp_data: data from FW notification to store NOA and CSA related - * data to be inserted into probe response. + * @max_tx_op: max TXOP in usecs for all ACs, zero for no limit. + * @ap_beacon_time: AP beacon time for synchronisation (on older FW) + * @bf_enabled: indicates if beacon filtering is enabled + * @ba_enabled: indicated if beacon abort is enabled + * @bcn_prot: beacon protection data (keys; FIXME: needs to be per link) + * @deflink: default link data for use in non-MLO + * @link: link data for each link in MLO + * @esr_active: indicates eSR mode is active + * @pm_enabled: indicates powersave is enabled + * @link_selection_res: bitmap of active links as it was decided in the last + * link selection. Valid only for a MLO vif after assoc. 0 if there wasn't + * any link selection yet. + * @link_selection_primary: primary link selected by link selection + * @primary_link: primary link in eSR. Valid only for an associated MLD vif, + * and in eSR mode. Valid only for a STA. + * @roc_activity: currently running ROC activity for this vif (or + * ROC_NUM_ACTIVITIES if no activity is running). + * @session_prot_connection_loss: the connection was lost due to session + * protection ending without receiving a beacon, so we need to now + * protect the deauth separately + * @ap_early_keys: The firmware cannot install keys before stations etc., + * but higher layers work differently, so we store the keys here for + * later installation. + * @ap_sta: pointer to the AP STA data structure + * @csa_count: CSA counter (old CSA implementation w/o firmware) + * @csa_misbehave: CSA AP misbehaviour flag (old implementation) + * @csa_target_freq: CSA target channel frequency (old implementation) + * @csa_work: CSA work (old implementation) + * @dbgfs_bf: beamforming debugfs data + * @dbgfs_dir: debugfs directory for this vif + * @dbgfs_pm: power management debugfs data + * @dbgfs_quota_min: debugfs value for minimal quota + * @dbgfs_slink: debugfs symlink for this interface + * @ftm_unprotected: unprotected FTM debugfs override + * @hs_time_event_data: hotspot/AUX ROC time event data + * @mac_pwr_cmd: debugfs override for MAC power command + * @target_ipv6_addrs: IPv6 addresses on this interface for offload + * @num_target_ipv6_addrs: number of @target_ipv6_addrs + * @tentative_addrs: bitmap of tentative IPv6 addresses in @target_ipv6_addrs + * @rekey_data: rekeying data for WoWLAN GTK rekey offload + * @seqno: storage for seqno for older firmware D0/D3 transition + * @seqno_valid: indicates @seqno is valid + * @time_event_data: session protection time event data + * @tsf_id: the TSF resource ID assigned in firmware (for firmware needing that) + * @tx_key_idx: WEP transmit key index for D3 + * @uapsd_misbehaving_ap_addr: MLD address/BSSID of U-APSD misbehaving AP, to + * not use U-APSD on reconnection + * @uapsd_nonagg_detected_wk: worker for handling detection of no aggregation + * in U-APSD */ struct iwl_mvm_vif { struct iwl_mvm *mvm; u16 id; u16 color; - u8 ap_sta_id; - u8 bssid[ETH_ALEN]; bool associated; u8 ap_assoc_sta_count; - - u16 cab_queue; - bool uploaded; bool ap_ibss_active; bool pm_enabled; bool monitor_active; + bool esr_active; + bool session_prot_connection_loss; + u8 low_latency: 6; u8 low_latency_actual: 1; + u8 authorized:1; bool ps_disabled; - struct iwl_mvm_vif_bf_data bf_data; - - struct { - u32 num_beacons, accu_num_beacons; - u8 avg_signal; - } beacon_stats; u32 ap_beacon_time; + bool bf_enabled; + bool ba_enabled; - enum iwl_tsf_id tsf_id; - - /* - * QoS data from mac80211, need to store this here - * as mac80211 has a separate callback but we need - * to have the data for the MAC context - */ - struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS]; - struct iwl_mvm_time_event_data time_event_data; - struct iwl_mvm_time_event_data hs_time_event_data; - - struct iwl_mvm_int_sta bcast_sta; - struct iwl_mvm_int_sta mcast_sta; - - /* - * Assigned while mac80211 has the interface in a channel context, - * or, for P2P Device, while it exists. - */ - struct iwl_mvm_phy_ctxt *phy_ctxt; - -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP /* WoWLAN GTK rekey data */ struct { u8 kck[NL80211_KCK_EXT_LEN]; @@ -394,42 +479,56 @@ struct iwl_mvm_vif { struct iwl_dbgfs_bf dbgfs_bf; struct iwl_mac_power_cmd mac_pwr_cmd; int dbgfs_quota_min; + bool ftm_unprotected; #endif - enum ieee80211_smps_mode smps_requests[NUM_IWL_MVM_SMPS_REQ]; - /* FW identified misbehaving AP */ - u8 uapsd_misbehaving_bssid[ETH_ALEN]; - + u8 uapsd_misbehaving_ap_addr[ETH_ALEN] __aligned(2); struct delayed_work uapsd_nonagg_detected_wk; - /* Indicates that CSA countdown may be started */ bool csa_countdown; bool csa_failed; + bool csa_bcn_pending; + bool csa_blocks_tx; u16 csa_target_freq; u16 csa_count; u16 csa_misbehave; struct delayed_work csa_work; - /* Indicates that we are waiting for a beacon on a new channel */ - bool csa_bcn_pending; + enum iwl_tsf_id tsf_id; + + struct iwl_mvm_time_event_data time_event_data; + struct iwl_mvm_time_event_data hs_time_event_data; + enum iwl_roc_activity roc_activity; /* TCP Checksum Offload */ netdev_features_t features; - struct iwl_probe_resp_data __rcu *probe_resp_data; + struct ieee80211_sta *ap_sta; /* we can only have 2 GTK + 2 IGTK active at a time */ struct ieee80211_key_conf *ap_early_keys[4]; - /* 26-tone RU OFDMA transmissions should be blocked */ - bool he_ru_2mhz_block; - struct { struct ieee80211_key_conf __rcu *keys[2]; } bcn_prot; + + u16 max_tx_op; + + u16 link_selection_res; + u8 link_selection_primary; + u8 primary_link; + + struct iwl_mvm_vif_link_info deflink; + struct iwl_mvm_vif_link_info *link[IEEE80211_MLD_MAX_NUM_LINKS]; }; +#define for_each_mvm_vif_valid_link(mvm_vif, link_id) \ + for (link_id = 0; \ + link_id < ARRAY_SIZE((mvm_vif)->link); \ + link_id++) \ + if ((mvm_vif)->link[link_id]) + static inline struct iwl_mvm_vif * iwl_mvm_vif_from_mac80211(struct ieee80211_vif *vif) { @@ -448,6 +547,7 @@ enum iwl_scan_status { IWL_MVM_SCAN_STOPPING_REGULAR = BIT(8), IWL_MVM_SCAN_STOPPING_SCHED = BIT(9), IWL_MVM_SCAN_STOPPING_NETDETECT = BIT(10), + IWL_MVM_SCAN_STOPPING_INT_MLO = BIT(11), IWL_MVM_SCAN_REGULAR_MASK = IWL_MVM_SCAN_REGULAR | IWL_MVM_SCAN_STOPPING_REGULAR, @@ -476,13 +576,15 @@ enum iwl_mvm_sched_scan_pass_all_states { }; /** - * struct iwl_mvm_tt_mgnt - Thermal Throttling Management structure + * struct iwl_mvm_tt_mgmt - Thermal Throttling Management structure * @ct_kill_exit: worker to exit thermal kill * @dynamic_smps: Is thermal throttling enabled dynamic_smps? * @tx_backoff: The current thremal throttling tx backoff in uSec. * @min_backoff: The minimal tx backoff due to power restrictions * @params: Parameters to configure the thermal throttling algorithm. * @throttle: Is thermal throttling is active? + * @power_budget_mw: maximum cTDP power budget as defined for this system and + * device */ struct iwl_mvm_tt_mgmt { struct delayed_work ct_kill_exit; @@ -491,18 +593,18 @@ struct iwl_mvm_tt_mgmt { u32 min_backoff; struct iwl_tt_params params; bool throttle; + + u32 power_budget_mw; }; #ifdef CONFIG_THERMAL /** - *struct iwl_mvm_thermal_device - thermal zone related data - * @temp_trips: temperature thresholds for report - * @fw_trips_index: keep indexes to original array - temp_trips + * struct iwl_mvm_thermal_device - thermal zone related data + * @trips: temperature thresholds for report * @tzone: thermal zone device data */ struct iwl_mvm_thermal_device { - s16 temp_trips[IWL_MAX_DTS_TRIPS]; - u8 fw_trips_index[IWL_MAX_DTS_TRIPS]; + struct thermal_trip trips[IWL_MAX_DTS_TRIPS]; struct thermal_zone_device *tzone; }; @@ -601,87 +703,62 @@ struct iwl_mvm_tcm { * struct iwl_mvm_reorder_buffer - per ra/tid/queue reorder buffer * @head_sn: reorder window head sn * @num_stored: number of mpdus stored in the buffer - * @buf_size: the reorder buffer size as set by the last addba request * @queue: queue of this reorder buffer - * @last_amsdu: track last ASMDU SN for duplication detection - * @last_sub_index: track ASMDU sub frame index for duplication detection - * @reorder_timer: timer for frames are in the reorder buffer. For AMSDU - * it is the time of last received sub-frame - * @removed: prevent timer re-arming * @valid: reordering is valid for this queue * @lock: protect reorder buffer internal state - * @mvm: mvm pointer, needed for frame timer context - * @consec_oldsn_drops: consecutive drops due to old SN - * @consec_oldsn_ampdu_gp2: A-MPDU GP2 timestamp to track - * when to apply old SN consecutive drop workaround - * @consec_oldsn_prev_drop: track whether or not an MPDU - * that was single/part of the previous A-MPDU was - * dropped due to old SN */ struct iwl_mvm_reorder_buffer { u16 head_sn; u16 num_stored; - u16 buf_size; int queue; - u16 last_amsdu; - u8 last_sub_index; - struct timer_list reorder_timer; - bool removed; bool valid; spinlock_t lock; - struct iwl_mvm *mvm; - unsigned int consec_oldsn_drops; - u32 consec_oldsn_ampdu_gp2; - unsigned int consec_oldsn_prev_drop:1; } ____cacheline_aligned_in_smp; /** - * struct _iwl_mvm_reorder_buf_entry - reorder buffer entry per-queue/per-seqno + * struct iwl_mvm_reorder_buf_entry - reorder buffer entry per-queue/per-seqno * @frames: list of skbs stored - * @reorder_time: time the packet was stored in the reorder buffer */ -struct _iwl_mvm_reorder_buf_entry { - struct sk_buff_head frames; - unsigned long reorder_time; -}; - -/* make this indirection to get the aligned thing */ struct iwl_mvm_reorder_buf_entry { - struct _iwl_mvm_reorder_buf_entry e; + struct sk_buff_head frames; } #ifndef __CHECKER__ /* sparse doesn't like this construct: "bad integer constant expression" */ -__aligned(roundup_pow_of_two(sizeof(struct _iwl_mvm_reorder_buf_entry))) +__aligned(roundup_pow_of_two(sizeof(struct sk_buff_head))) #endif ; /** * struct iwl_mvm_baid_data - BA session data - * @sta_id: station id + * @sta_mask: current station mask for the BAID * @tid: tid of the session - * @baid baid of the session + * @baid: baid of the session * @timeout: the timeout set in the addba request + * @buf_size: the reorder buffer size as set by the last addba request * @entries_per_queue: # of buffers per queue, this actually gets * aligned up to avoid cache line sharing between queues * @last_rx: last rx jiffies, updated only if timeout passed from last update * @session_timer: timer to check if BA session expired, runs at 2 * timeout + * @rcu_ptr: BA data RCU protected access + * @rcu_head: RCU head for freeing this data * @mvm: mvm pointer, needed for timer context * @reorder_buf: reorder buffer, allocated per queue - * @reorder_buf_data: data + * @entries: data */ struct iwl_mvm_baid_data { struct rcu_head rcu_head; - u8 sta_id; + u32 sta_mask; u8 tid; u8 baid; u16 timeout; + u16 buf_size; u16 entries_per_queue; unsigned long last_rx; struct timer_list session_timer; struct iwl_mvm_baid_data __rcu **rcu_ptr; struct iwl_mvm *mvm; struct iwl_mvm_reorder_buffer reorder_buf[IWL_MAX_RX_HW_QUEUES]; - struct iwl_mvm_reorder_buf_entry entries[]; + struct iwl_mvm_reorder_buf_entry entries[] ____cacheline_aligned_in_smp; }; static inline struct iwl_mvm_baid_data * @@ -729,7 +806,11 @@ struct iwl_mvm_txq { struct list_head list; u16 txq_id; atomic_t tx_request; - bool stopped; +#define IWL_MVM_TXQ_STATE_READY 0 +#define IWL_MVM_TXQ_STATE_STOP_FULL 1 +#define IWL_MVM_TXQ_STATE_STOP_REDIRECT 2 +#define IWL_MVM_TXQ_STATE_STOP_AP_CSA 3 + unsigned long state; }; static inline struct iwl_mvm_txq * @@ -769,13 +850,79 @@ struct iwl_mvm_dqa_txq_info { enum iwl_mvm_queue_status status; }; +struct ptp_data { + struct ptp_clock *ptp_clock; + struct ptp_clock_info ptp_clock_info; + + struct delayed_work dwork; + + /* The last GP2 reading from the hw */ + u32 last_gp2; + + /* number of wraparounds since scale_update_adj_time_ns */ + u32 wrap_counter; + + /* GP2 time when the scale was last updated */ + u32 scale_update_gp2; + + /* Adjusted time when the scale was last updated in nanoseconds */ + u64 scale_update_adj_time_ns; + + /* clock frequency offset, scaled to 65536000000 */ + u64 scaled_freq; + + /* Delta between hardware clock and ptp clock in nanoseconds */ + s64 delta; +}; + +struct iwl_time_sync_data { + struct sk_buff_head frame_list; + u8 peer_addr[ETH_ALEN]; + bool active; +}; + +struct iwl_mei_scan_filter { + bool is_mei_limited_scan; + struct sk_buff_head scan_res; + struct work_struct scan_work; +}; + +/** + * struct iwl_mvm_acs_survey_channel - per-channel survey information + * + * Stripped down version of &struct survey_info. + * + * @time: time in ms the radio was on the channel + * @time_busy: time in ms the channel was sensed busy + * @time_tx: time in ms spent transmitting data + * @time_rx: time in ms spent receiving data + * @noise: channel noise in dBm + */ +struct iwl_mvm_acs_survey_channel { + u32 time; + u32 time_busy; + u32 time_tx; + u32 time_rx; + s8 noise; +}; + +struct iwl_mvm_acs_survey { + struct iwl_mvm_acs_survey_channel *bands[NUM_NL80211_BANDS]; + + /* Overall number of channels */ + int n_channels; + + /* Storage space for per-channel information follows */ + struct iwl_mvm_acs_survey_channel channels[] __counted_by(n_channels); +}; + struct iwl_mvm { /* for logger access */ struct device *dev; struct iwl_trans *trans; const struct iwl_fw *fw; - const struct iwl_cfg *cfg; + const struct iwl_rf_cfg *cfg; struct iwl_phy_db *phy_db; struct ieee80211_hw *hw; @@ -785,6 +932,9 @@ struct iwl_mvm { spinlock_t async_handlers_lock; struct work_struct async_handlers_wk; + /* For async rx handlers that require the wiphy lock */ + struct wiphy_work async_handlers_wiphy_wk; + struct work_struct roc_done_wk; unsigned long init_status; @@ -804,6 +954,8 @@ struct iwl_mvm { u8 cca_40mhz_workaround; + u8 fw_rates_ver; + u32 ampdu_ref; bool ampdu_toggle; @@ -827,6 +979,7 @@ struct iwl_mvm { struct iwl_mvm_tvqm_txq_info tvqm_info[IWL_MAX_TVQM_QUEUES]; }; struct work_struct add_stream_wk; /* To add streams to queues */ + spinlock_t add_stream_lock; const char *nvm_file_name; struct iwl_nvm_data *nvm_data; @@ -852,7 +1005,9 @@ struct iwl_mvm { /* data related to data path */ struct iwl_rx_phy_info last_phy_info; - struct ieee80211_sta __rcu *fw_id_to_mac_id[IWL_MVM_STATION_COUNT_MAX]; + struct ieee80211_sta __rcu *fw_id_to_mac_id[IWL_STATION_COUNT_MAX]; + /* note: fw_id_to_link_sta must be protected by wiphy and mvm mutexes */ + struct ieee80211_link_sta __rcu *fw_id_to_link_sta[IWL_STATION_COUNT_MAX]; u8 rx_ba_sessions; /* configured by mac80211 */ @@ -860,6 +1015,7 @@ struct iwl_mvm { /* Scan status, cmd (pre-allocated) and auxiliary station */ unsigned int scan_status; + size_t scan_cmd_size; void *scan_cmd; struct iwl_mcast_filter_cmd *mcast_filter_cmd; /* For CDB this is low band scan type, for non-CDB - type. */ @@ -873,28 +1029,18 @@ struct iwl_mvm { unsigned int max_scans; /* UMAC scan tracking */ - u32 scan_uid_status[IWL_MVM_MAX_UMAC_SCANS]; + u32 scan_uid_status[IWL_MAX_UMAC_SCANS]; /* start time of last scan in TSF of the mac that requested the scan */ u64 scan_start; /* the vif that requested the current scan */ struct iwl_mvm_vif *scan_vif; + u8 scan_link_id; /* rx chain antennas set through debugfs for the scan command */ u8 scan_rx_ant; -#ifdef CONFIG_IWLWIFI_BCAST_FILTERING - /* broadcast filters to configure for each associated station */ - const struct iwl_fw_bcast_filter *bcast_filters; -#ifdef CONFIG_IWLWIFI_DEBUGFS - struct { - bool override; - struct iwl_bcast_filter_cmd cmd; - } dbgfs_bcast_filtering; -#endif -#endif - /* Internal station */ struct iwl_mvm_int_sta aux_sta; struct iwl_mvm_int_sta snif_sta; @@ -904,6 +1050,9 @@ struct iwl_mvm { u8 scan_last_antenna_idx; /* to toggle TX between antennas */ u8 mgmt_last_antenna_idx; + u8 set_tx_ant; + u8 set_rx_ant; + /* last smart fifo state that was successfully sent to firmware */ enum iwl_sf_state sf_state; @@ -945,11 +1094,8 @@ struct iwl_mvm { unsigned long fw_key_table[BITS_TO_LONGS(STA_KEY_MAX_NUM)]; u8 fw_key_deleted[STA_KEY_MAX_NUM]; - u8 vif_count; struct ieee80211_vif __rcu *vif_id_to_mac[NUM_MAC_INDEX_DRIVER]; - /* -1 for always, 0 for never, >0 for that many times */ - s8 fw_restart; u8 *error_recovery_buf; #ifdef CONFIG_IWLWIFI_LEDS @@ -958,7 +1104,7 @@ struct iwl_mvm { struct ieee80211_vif *p2p_device_vif; -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP struct wiphy_wowlan_support wowlan; int gtk_ivlen, gtk_icvlen, ptk_ivlen, ptk_icvlen; @@ -969,20 +1115,17 @@ struct iwl_mvm { struct ieee80211_channel **nd_channels; int n_nd_channels; bool net_detect; + bool fast_resume; u8 offload_tid; #ifdef CONFIG_IWLWIFI_DEBUGFS bool d3_wake_sysassert; - bool d3_test_active; - u32 d3_test_pme_ptr; - struct ieee80211_vif *keep_vif; u32 last_netdetect_scans; /* no. of scans in the last net-detect wake */ #endif #endif wait_queue_head_t rx_sync_waitq; - /* BT-Coex */ - struct iwl_bt_coex_profile_notif last_bt_notif; + struct iwl_bt_coex_prof_old_notif last_bt_notif; struct iwl_bt_coex_ci_cmd last_bt_ci_cmd; u8 bt_tx_prio; @@ -1017,11 +1160,6 @@ struct iwl_mvm { struct iwl_time_quota_cmd last_quota_cmd; -#ifdef CONFIG_NL80211_TESTMODE - u32 noa_duration; - struct ieee80211_vif *noa_vif; -#endif - /* Tx queues */ u16 aux_queue; u16 snif_queue; @@ -1075,14 +1213,13 @@ struct iwl_mvm { u32 ciphers[IWL_MVM_NUM_CIPHERS]; - struct ieee80211_cipher_scheme cs[IWL_UCODE_MAX_CS]; struct cfg80211_ftm_responder_stats ftm_resp_stats; struct { struct cfg80211_pmsr_request *req; struct wireless_dev *req_wdev; struct list_head loc_list; - int responses[IWL_MVM_TOF_MAX_APS]; + int responses[IWL_TOF_MAX_APS]; struct { struct list_head resp; } smooth; @@ -1091,13 +1228,12 @@ struct iwl_mvm { struct list_head resp_pasn_list; + struct ptp_data ptp_data; + struct { - u8 d0i3_resp; u8 range_resp; } cmd_ver; - struct ieee80211_vif *nan_vif; -#define IWL_MAX_BAID 32 struct iwl_mvm_baid_data __rcu *baid_map[IWL_MAX_BAID]; /* @@ -1110,13 +1246,39 @@ struct iwl_mvm { /* does a monitor vif exist (only one can exist hence bool) */ bool monitor_on; + /* + * primary channel position relative to he whole bandwidth, + * in steps of 80 MHz + */ + u8 monitor_p80; /* sniffer data to include in radiotap */ __le16 cur_aid; u8 cur_bssid[ETH_ALEN]; + /* report rx timestamp in ptp clock time */ + bool rx_ts_ptp; + unsigned long last_6ghz_passive_scan_jiffies; unsigned long last_reset_or_resume_time_jiffies; + + bool sta_remove_requires_queue_remove; + bool mld_api_is_used; + + /* + * Indicates that firmware will do a product reset (and then + * therefore fail to load) when we start it (due to OTP burn), + * if so don't dump errors etc. since this is expected. + */ + bool fw_product_reset; + + struct iwl_time_sync_data time_sync; + + struct iwl_mei_scan_filter mei_scan_filter; + + struct iwl_mvm_acs_survey *acs_survey; + + bool statistics_clear; }; /* Extract MVM priv from op_mode and _hw */ @@ -1126,34 +1288,32 @@ struct iwl_mvm { #define IWL_MAC80211_GET_MVM(_hw) \ IWL_OP_MODE_GET_MVM((struct iwl_op_mode *)((_hw)->priv)) +DEFINE_GUARD(mvm, struct iwl_mvm *, mutex_lock(&_T->mutex), mutex_unlock(&_T->mutex)) + /** * enum iwl_mvm_status - MVM status bits * @IWL_MVM_STATUS_HW_RFKILL: HW RF-kill is asserted * @IWL_MVM_STATUS_HW_CTKILL: CT-kill is active - * @IWL_MVM_STATUS_ROC_RUNNING: remain-on-channel is running + * @IWL_MVM_STATUS_ROC_P2P_RUNNING: remain-on-channel on P2P is running (when + * P2P is not over AUX) * @IWL_MVM_STATUS_HW_RESTART_REQUESTED: HW restart was requested * @IWL_MVM_STATUS_IN_HW_RESTART: HW restart is active * @IWL_MVM_STATUS_ROC_AUX_RUNNING: AUX remain-on-channel is running * @IWL_MVM_STATUS_FIRMWARE_RUNNING: firmware is running - * @IWL_MVM_STATUS_NEED_FLUSH_P2P: need to flush P2P bcast STA * @IWL_MVM_STATUS_IN_D3: in D3 (or at least about to go into it) * @IWL_MVM_STATUS_SUPPRESS_ERROR_LOG_ONCE: suppress one error log * if this is set, when intentionally triggered - * @IWL_MVM_STATUS_STARTING: starting mac, - * used to disable restart flow while in STARTING state */ enum iwl_mvm_status { IWL_MVM_STATUS_HW_RFKILL, IWL_MVM_STATUS_HW_CTKILL, - IWL_MVM_STATUS_ROC_RUNNING, + IWL_MVM_STATUS_ROC_P2P_RUNNING, IWL_MVM_STATUS_HW_RESTART_REQUESTED, IWL_MVM_STATUS_IN_HW_RESTART, IWL_MVM_STATUS_ROC_AUX_RUNNING, IWL_MVM_STATUS_FIRMWARE_RUNNING, - IWL_MVM_STATUS_NEED_FLUSH_P2P, IWL_MVM_STATUS_IN_D3, IWL_MVM_STATUS_SUPPRESS_ERROR_LOG_ONCE, - IWL_MVM_STATUS_STARTING, }; struct iwl_mvm_csme_conn_info { @@ -1291,7 +1451,7 @@ static inline bool iwl_mvm_is_lar_supported(struct iwl_mvm *mvm) * Enable LAR only if it is supported by the FW (TLV) && * enabled in the NVM */ - if (mvm->cfg->nvm_type == IWL_NVM_EXT) + if (mvm->trans->cfg->nvm_type == IWL_NVM_EXT) return nvm_lar && tlv_lar; else return tlv_lar; @@ -1315,8 +1475,7 @@ static inline bool iwl_mvm_bt_is_rrc_supported(struct iwl_mvm *mvm) static inline bool iwl_mvm_is_csum_supported(struct iwl_mvm *mvm) { return fw_has_capa(&mvm->fw->ucode_capa, - IWL_UCODE_TLV_CAPA_CSUM_SUPPORT) && - !IWL_MVM_HW_CSUM_DISABLE; + IWL_UCODE_TLV_CAPA_CSUM_SUPPORT); } static inline bool iwl_mvm_is_mplut_supported(struct iwl_mvm *mvm) @@ -1341,16 +1500,28 @@ static inline bool iwl_mvm_has_new_rx_api(struct iwl_mvm *mvm) IWL_UCODE_TLV_CAPA_MULTI_QUEUE_RX_SUPPORT); } +static inline bool iwl_mvm_has_mld_api(const struct iwl_fw *fw) +{ + return fw_has_capa(&fw->ucode_capa, + IWL_UCODE_TLV_CAPA_MLD_API_SUPPORT); +} + +static inline bool iwl_mvm_has_new_station_api(const struct iwl_fw *fw) +{ + return iwl_mvm_has_mld_api(fw) || + iwl_fw_lookup_cmd_ver(fw, ADD_STA, 0) >= 12; +} + static inline bool iwl_mvm_has_new_tx_api(struct iwl_mvm *mvm) { /* TODO - replace with TLV once defined */ - return mvm->trans->trans_cfg->use_tfh; + return mvm->trans->mac_cfg->gen2; } static inline bool iwl_mvm_has_unified_ucode(struct iwl_mvm *mvm) { /* TODO - better define this */ - return mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000; + return mvm->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_22000; } static inline bool iwl_mvm_is_cdb_supported(struct iwl_mvm *mvm) @@ -1375,7 +1546,7 @@ static inline bool iwl_mvm_cdb_scan_api(struct iwl_mvm *mvm) * but then there's a little bit of code in scan that won't make * any sense... */ - return mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000; + return mvm->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_22000; } static inline bool iwl_mvm_is_scan_ext_chan_supported(struct iwl_mvm *mvm) @@ -1409,6 +1580,12 @@ static inline bool iwl_mvm_has_quota_low_latency(struct iwl_mvm *mvm) IWL_UCODE_TLV_API_QUOTA_LOW_LATENCY); } +static inline bool iwl_mvm_has_no_host_disable_tx(struct iwl_mvm *mvm) +{ + return fw_has_api(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_API_NO_HOST_DISABLE_TX); +} + static inline bool iwl_mvm_has_tlc_offload(const struct iwl_mvm *mvm) { return fw_has_capa(&mvm->fw->ucode_capa, @@ -1419,9 +1596,9 @@ static inline struct agg_tx_status * iwl_mvm_get_agg_status(struct iwl_mvm *mvm, void *tx_resp) { if (iwl_mvm_has_new_tx_api(mvm)) - return &((struct iwl_mvm_tx_resp *)tx_resp)->status; + return &((struct iwl_tx_resp *)tx_resp)->status; else - return ((struct iwl_mvm_tx_resp_v3 *)tx_resp)->status; + return ((struct iwl_tx_resp_v3 *)tx_resp)->status; } static inline bool iwl_mvm_is_tt_in_fw(struct iwl_mvm *mvm) @@ -1442,14 +1619,59 @@ static inline bool iwl_mvm_is_ctdp_supported(struct iwl_mvm *mvm) IWL_UCODE_TLV_CAPA_CTDP_SUPPORT); } +static inline bool iwl_mvm_is_esr_supported(struct iwl_trans *trans) +{ + if (CSR_HW_RFID_IS_CDB(trans->info.hw_rf_id)) + return false; + + switch (CSR_HW_RFID_TYPE(trans->info.hw_rf_id)) { + case IWL_CFG_RF_TYPE_FM: + /* Step A doesn't support eSR */ + return CSR_HW_RFID_STEP(trans->info.hw_rf_id); + case IWL_CFG_RF_TYPE_WH: + case IWL_CFG_RF_TYPE_PE: + return true; + default: + return false; + } +} + +static inline int iwl_mvm_max_active_links(struct iwl_mvm *mvm, + struct ieee80211_vif *vif) +{ + struct iwl_trans *trans = mvm->fwrt.trans; + + if (vif->type == NL80211_IFTYPE_AP) + return mvm->fw->ucode_capa.num_beacons; + + /* Check if HW supports eSR or STR */ + if (iwl_mvm_is_esr_supported(trans) || + (CSR_HW_RFID_TYPE(trans->info.hw_rf_id) == IWL_CFG_RF_TYPE_FM && + CSR_HW_RFID_IS_CDB(trans->info.hw_rf_id))) + return IWL_FW_MAX_ACTIVE_LINKS_NUM; + + return 1; +} + extern const u8 iwl_mvm_ac_to_tx_fifo[]; extern const u8 iwl_mvm_ac_to_gen2_tx_fifo[]; +extern const u8 iwl_mvm_ac_to_bz_tx_fifo[]; static inline u8 iwl_mvm_mac_ac_to_tx_fifo(struct iwl_mvm *mvm, enum ieee80211_ac_numbers ac) { - return iwl_mvm_has_new_tx_api(mvm) ? - iwl_mvm_ac_to_gen2_tx_fifo[ac] : iwl_mvm_ac_to_tx_fifo[ac]; + if (mvm->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) + return iwl_mvm_ac_to_bz_tx_fifo[ac]; + if (iwl_mvm_has_new_tx_api(mvm)) + return iwl_mvm_ac_to_gen2_tx_fifo[ac]; + return iwl_mvm_ac_to_tx_fifo[ac]; +} + +static inline bool iwl_mvm_has_rlc_offload(struct iwl_mvm *mvm) +{ + return iwl_fw_lookup_cmd_ver(mvm->fw, + WIDE_ID(DATA_PATH_GROUP, RLC_CONFIG_CMD), + 0) >= 3; } struct iwl_rate_info { @@ -1460,7 +1682,7 @@ struct iwl_rate_info { u8 ieee; /* MAC header: IWL_RATE_6M_IEEE, etc. */ }; -void __iwl_mvm_mac_stop(struct iwl_mvm *mvm); +void __iwl_mvm_mac_stop(struct iwl_mvm *mvm, bool suspend); int __iwl_mvm_mac_start(struct iwl_mvm *mvm); /****************** @@ -1477,11 +1699,9 @@ int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags, void iwl_mvm_hwrate_to_tx_rate(u32 rate_n_flags, enum nl80211_band band, struct ieee80211_tx_rate *r); -void iwl_mvm_hwrate_to_tx_rate_v1(u32 rate_n_flags, - enum nl80211_band band, - struct ieee80211_tx_rate *r); u8 iwl_mvm_mac80211_idx_to_hwrate(const struct iwl_fw *fw, int rate_idx); u8 iwl_mvm_mac80211_ac_to_ucode_ac(enum ieee80211_ac_numbers ac); +bool iwl_mvm_is_nic_ack_enabled(struct iwl_mvm *mvm, struct ieee80211_vif *vif); static inline void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm) { @@ -1509,16 +1729,16 @@ int iwl_mvm_tx_skb_sta(struct iwl_mvm *mvm, struct sk_buff *skb, struct ieee80211_sta *sta); int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb); void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb, - struct iwl_tx_cmd *tx_cmd, + struct iwl_tx_cmd_v6_params *tx_cmd_params, struct ieee80211_tx_info *info, u8 sta_id); -void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, struct iwl_tx_cmd *tx_cmd, - struct ieee80211_tx_info *info, - struct ieee80211_sta *sta, __le16 fc); +void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, + struct iwl_tx_cmd_v6_params *tx_cmd_params, + struct ieee80211_tx_info *info, + struct ieee80211_sta *sta, __le16 fc); void iwl_mvm_mac_itxq_xmit(struct ieee80211_hw *hw, struct ieee80211_txq *txq); unsigned int iwl_mvm_max_amsdu_size(struct iwl_mvm *mvm, struct ieee80211_sta *sta, unsigned int tid); -u32 iwl_mvm_tx_csum_bz(struct iwl_mvm *mvm, struct sk_buff *skb, bool amsdu); #ifdef CONFIG_IWLWIFI_DEBUG const char *iwl_mvm_get_tx_fail_reason(u32 status); @@ -1526,18 +1746,29 @@ const char *iwl_mvm_get_tx_fail_reason(u32 status); static inline const char *iwl_mvm_get_tx_fail_reason(u32 status) { return ""; } #endif int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk); -int iwl_mvm_flush_sta(struct iwl_mvm *mvm, void *sta, bool internal); +int iwl_mvm_flush_sta(struct iwl_mvm *mvm, u32 sta_id, u32 tfd_queue_mask); int iwl_mvm_flush_sta_tids(struct iwl_mvm *mvm, u32 sta_id, u16 tids); +/* Utils to extract sta related data */ +__le32 iwl_mvm_get_sta_htc_flags(struct ieee80211_sta *sta, + struct ieee80211_link_sta *link_sta); +u8 iwl_mvm_get_sta_uapsd_acs(struct ieee80211_sta *sta); +u32 iwl_mvm_get_sta_ampdu_dens(struct ieee80211_link_sta *link_sta, + struct ieee80211_bss_conf *link_conf, + u32 *_agg_size); +int iwl_mvm_set_sta_pkt_ext(struct iwl_mvm *mvm, + struct ieee80211_link_sta *link_sta, + struct iwl_he_pkt_ext_v2 *pkt_ext); + void iwl_mvm_async_handlers_purge(struct iwl_mvm *mvm); static inline void iwl_mvm_set_tx_cmd_ccmp(struct ieee80211_tx_info *info, - struct iwl_tx_cmd *tx_cmd) + struct iwl_tx_cmd_v6_params *tx_cmd_params) { struct ieee80211_key_conf *keyconf = info->control.hw_key; - tx_cmd->sec_ctl = TX_CMD_SEC_CCM; - memcpy(tx_cmd->key, keyconf->key, keyconf->keylen); + tx_cmd_params->sec_ctl = TX_CMD_SEC_CCM; + memcpy(tx_cmd_params->key, keyconf->key, keyconf->keylen); } static inline void iwl_mvm_wait_for_async_handlers(struct iwl_mvm *mvm) @@ -1546,11 +1777,23 @@ static inline void iwl_mvm_wait_for_async_handlers(struct iwl_mvm *mvm) } /* Statistics */ +void iwl_mvm_handle_rx_system_oper_stats(struct iwl_mvm *mvm, + struct iwl_rx_cmd_buffer *rxb); +void iwl_mvm_handle_rx_system_oper_part1_stats(struct iwl_mvm *mvm, + struct iwl_rx_cmd_buffer *rxb); +static inline void +iwl_mvm_handle_rx_system_end_stats_notif(struct iwl_mvm *mvm, + struct iwl_rx_cmd_buffer *rxb) +{ +} + void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm, struct iwl_rx_packet *pkt); void iwl_mvm_rx_statistics(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); int iwl_mvm_request_statistics(struct iwl_mvm *mvm, bool clear); +int iwl_mvm_request_periodic_system_statistics(struct iwl_mvm *mvm, + bool enable); void iwl_mvm_accu_radio_stats(struct iwl_mvm *mvm); /* NVM */ @@ -1559,16 +1802,29 @@ int iwl_mvm_load_nvm_to_nic(struct iwl_mvm *mvm); static inline u8 iwl_mvm_get_valid_tx_ant(struct iwl_mvm *mvm) { - return mvm->nvm_data && mvm->nvm_data->valid_tx_ant ? - mvm->fw->valid_tx_ant & mvm->nvm_data->valid_tx_ant : - mvm->fw->valid_tx_ant; + u8 tx_ant = mvm->fw->valid_tx_ant; + + if (mvm->nvm_data && mvm->nvm_data->valid_tx_ant) + tx_ant &= mvm->nvm_data->valid_tx_ant; + + if (mvm->set_tx_ant) + tx_ant &= mvm->set_tx_ant; + + return tx_ant; } static inline u8 iwl_mvm_get_valid_rx_ant(struct iwl_mvm *mvm) { - return mvm->nvm_data && mvm->nvm_data->valid_rx_ant ? - mvm->fw->valid_rx_ant & mvm->nvm_data->valid_rx_ant : - mvm->fw->valid_rx_ant; + u8 rx_ant = mvm->fw->valid_rx_ant; + + if (mvm->nvm_data && mvm->nvm_data->valid_rx_ant) + rx_ant &= mvm->nvm_data->valid_rx_ant; + + if (mvm->set_rx_ant) + rx_ant &= mvm->set_rx_ant; + + return rx_ant; + } static inline void iwl_mvm_toggle_tx_ant(struct iwl_mvm *mvm, u8 *ant) @@ -1593,8 +1849,8 @@ int iwl_mvm_up(struct iwl_mvm *mvm); int iwl_mvm_load_d3_fw(struct iwl_mvm *mvm); int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm); -bool iwl_mvm_bcast_filter_build_cmd(struct iwl_mvm *mvm, - struct iwl_bcast_filter_cmd *cmd); + +void iwl_mvm_mac_init_mvmvif(struct iwl_mvm *mvm, struct iwl_mvm_vif *mvmvif); /* * FW notifications / CMD responses handlers @@ -1630,35 +1886,79 @@ void iwl_mvm_rx_shared_mem_cfg_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); /* MVM PHY */ +struct iwl_mvm_phy_ctxt *iwl_mvm_get_free_phy_ctxt(struct iwl_mvm *mvm); int iwl_mvm_phy_ctxt_add(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt, - struct cfg80211_chan_def *chandef, + const struct cfg80211_chan_def *chandef, + const struct cfg80211_chan_def *ap, u8 chains_static, u8 chains_dynamic); int iwl_mvm_phy_ctxt_changed(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt, - struct cfg80211_chan_def *chandef, + const struct cfg80211_chan_def *chandef, + const struct cfg80211_chan_def *ap, u8 chains_static, u8 chains_dynamic); void iwl_mvm_phy_ctxt_ref(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt); void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt); int iwl_mvm_phy_ctx_count(struct iwl_mvm *mvm); -u8 iwl_mvm_get_channel_width(struct cfg80211_chan_def *chandef); -u8 iwl_mvm_get_ctrl_pos(struct cfg80211_chan_def *chandef); +u8 iwl_mvm_get_channel_width(const struct cfg80211_chan_def *chandef); +u8 iwl_mvm_get_ctrl_pos(const struct cfg80211_chan_def *chandef); +int iwl_mvm_phy_send_rlc(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt, + u8 chains_static, u8 chains_dynamic); /* MAC (virtual interface) programming */ + +void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm, + struct ieee80211_vif *vif); +void iwl_mvm_set_fw_basic_rates(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + struct iwl_mvm_vif_link_info *link_info, + __le32 *cck_rates, __le32 *ofdm_rates); +void iwl_mvm_set_fw_protection_flags(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf, + __le32 *protection_flags, u32 ht_flag, + u32 tgg_flag); +void iwl_mvm_set_fw_qos_params(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf, + struct iwl_ac_qos *ac, __le32 *qos_flags); +bool iwl_mvm_set_fw_mu_edca_params(struct iwl_mvm *mvm, + const struct iwl_mvm_vif_link_info *link_info, + struct iwl_he_backoff_conf *trig_based_txf); +void iwl_mvm_set_fw_dtim_tbtt(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf, + __le64 *dtim_tsf, __le32 *dtim_time, + __le32 *assoc_beacon_arrive_time); +__le32 iwl_mac_ctxt_p2p_dev_has_extended_disc(struct iwl_mvm *mvm, + struct ieee80211_vif *vif); +void iwl_mvm_mac_ctxt_cmd_ap_set_filter_flags(struct iwl_mvm *mvm, + struct iwl_mvm_vif *mvmvif, + __le32 *filter_flags, + int accept_probe_req_flag, + int accept_beacon_flag); +int iwl_mvm_get_mac_type(struct ieee80211_vif *vif); +__le32 iwl_mvm_mac_ctxt_cmd_p2p_sta_get_oppps_ctwin(struct iwl_mvm *mvm, + struct ieee80211_vif *vif); +u32 iwl_mvm_mac_ctxt_cmd_sta_get_twt_policy(struct iwl_mvm *mvm, + struct ieee80211_vif *vif); +int iwl_mvm_mld_mac_ctxt_add(struct iwl_mvm *mvm, struct ieee80211_vif *vif); +int iwl_mvm_mld_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + bool force_assoc_off); +int iwl_mvm_mld_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif); int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif); int iwl_mvm_mac_ctxt_add(struct iwl_mvm *mvm, struct ieee80211_vif *vif); int iwl_mvm_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif, bool force_assoc_off, const u8 *bssid_override); int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif); int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm, - struct ieee80211_vif *vif); -int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm, - struct ieee80211_vif *vif, - struct sk_buff *beacon); + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf); int iwl_mvm_mac_ctxt_send_beacon_cmd(struct iwl_mvm *mvm, struct sk_buff *beacon, void *data, int len); -u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct ieee80211_tx_info *info, +u8 iwl_mvm_mac_ctxt_get_beacon_rate(struct iwl_mvm *mvm, + struct ieee80211_tx_info *info, + struct ieee80211_vif *vif); +u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct iwl_mvm *mvm, + struct ieee80211_tx_info *info, struct ieee80211_vif *vif); u16 iwl_mvm_mac_ctxt_get_beacon_flags(const struct iwl_fw *fw, u8 rate_idx); @@ -1669,6 +1969,8 @@ void iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); +void iwl_mvm_rx_missed_beacons_notif_legacy(struct iwl_mvm *mvm, + struct iwl_rx_cmd_buffer *rxb); void iwl_mvm_rx_stored_beacon_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); void iwl_mvm_mu_mimo_grp_notif(struct iwl_mvm *mvm, @@ -1680,13 +1982,89 @@ void iwl_mvm_mac_ctxt_recalc_tsf_id(struct iwl_mvm *mvm, struct ieee80211_vif *vif); void iwl_mvm_probe_resp_data_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); -void iwl_mvm_rx_missed_vap_notif(struct iwl_mvm *mvm, - struct iwl_rx_cmd_buffer *rxb); void iwl_mvm_channel_switch_start_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); +void iwl_mvm_channel_switch_error_notif(struct iwl_mvm *mvm, + struct iwl_rx_cmd_buffer *rxb); +void iwl_mvm_rx_beacon_filter_notif(struct iwl_mvm *mvm, + struct iwl_rx_cmd_buffer *rxb); + /* Bindings */ int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif); int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif); +u32 iwl_mvm_get_lmac_id(struct iwl_mvm *mvm, enum nl80211_band band); + +/* Links */ +void iwl_mvm_init_link(struct iwl_mvm_vif_link_info *link); +void iwl_mvm_set_link_fw_id(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf); +int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf); +int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf, + u32 changes, bool active); +int iwl_mvm_remove_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf); +int iwl_mvm_disable_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf); + +u8 iwl_mvm_get_primary_link(struct ieee80211_vif *vif); + +struct iwl_mvm_link_sel_data { + u8 link_id; + const struct cfg80211_chan_def *chandef; + s32 signal; + u16 grade; +}; + +#if IS_ENABLED(CONFIG_IWLWIFI_KUNIT_TESTS) +extern const struct iwl_hcmd_arr iwl_mvm_groups[]; +extern const unsigned int iwl_mvm_groups_size; +#endif + +/* AP and IBSS */ +bool iwl_mvm_start_ap_ibss_common(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, int *ret); +void iwl_mvm_stop_ap_ibss_common(struct iwl_mvm *mvm, + struct ieee80211_vif *vif); + +/* BSS Info */ +void iwl_mvm_bss_info_changed_station_common(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf, + u64 changes); +void iwl_mvm_bss_info_changed_station_assoc(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + u64 changes); + +/* ROC */ +/** + * struct iwl_mvm_roc_ops - callbacks for the remain_on_channel() + * + * Since the only difference between both MLD and + * non-MLD versions of remain_on_channel() is these function calls, + * each version will send its specific function calls to + * %iwl_mvm_roc_common(). + * + * @add_aux_sta_for_hs20: pointer to the function that adds an aux sta + * for Hot Spot 2.0 + * @link: For a P2P Device interface, pointer to a function that links the + * MAC/Link to the PHY context + */ +struct iwl_mvm_roc_ops { + int (*add_aux_sta_for_hs20)(struct iwl_mvm *mvm, u32 lmac_id); + int (*link)(struct iwl_mvm *mvm, struct ieee80211_vif *vif); +}; + +int iwl_mvm_roc_common(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_channel *channel, int duration, + enum ieee80211_roc_type type, + const struct iwl_mvm_roc_ops *ops); +int iwl_mvm_cancel_roc(struct ieee80211_hw *hw, + struct ieee80211_vif *vif); +/*Session Protection */ +void iwl_mvm_protect_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + u32 duration_override, unsigned int link_id); /* Quota management */ static inline size_t iwl_mvm_quota_cmd_size(struct iwl_mvm *mvm) @@ -1717,11 +2095,14 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, bool force_upload, int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct cfg80211_scan_request *req, struct ieee80211_scan_ies *ies); -int iwl_mvm_scan_size(struct iwl_mvm *mvm); +size_t iwl_mvm_scan_size(struct iwl_mvm *mvm); int iwl_mvm_scan_stop(struct iwl_mvm *mvm, int type, bool notify); + int iwl_mvm_max_scan_ie_len(struct iwl_mvm *mvm); void iwl_mvm_report_scan_aborted(struct iwl_mvm *mvm); void iwl_mvm_scan_timeout_wk(struct work_struct *work); +void iwl_mvm_rx_channel_survey_notif(struct iwl_mvm *mvm, + struct iwl_rx_cmd_buffer *rxb); /* Scheduled scan */ void iwl_mvm_rx_lmac_scan_complete_notif(struct iwl_mvm *mvm, @@ -1746,18 +2127,19 @@ void iwl_mvm_rx_umac_scan_iter_complete_notif(struct iwl_mvm *mvm, /* MVM debugfs */ #ifdef CONFIG_IWLWIFI_DEBUGFS void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm); -void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif); -void iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif); +void iwl_mvm_vif_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif); +void iwl_mvm_vif_dbgfs_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif); +void iwl_mvm_vif_dbgfs_rm_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif); #else static inline void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm) { } static inline void -iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif) +iwl_mvm_vif_dbgfs_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif) { } static inline void -iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif) +iwl_mvm_vif_dbgfs_rm_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif) { } #endif /* CONFIG_IWLWIFI_DEBUGFS */ @@ -1811,27 +2193,39 @@ void iwl_mvm_ipv6_addr_change(struct ieee80211_hw *hw, void iwl_mvm_set_default_unicast_key(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int idx); extern const struct file_operations iwl_dbgfs_d3_test_ops; -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP void iwl_mvm_set_last_nonqos_seq(struct iwl_mvm *mvm, struct ieee80211_vif *vif); +void iwl_mvm_fast_suspend(struct iwl_mvm *mvm); +int iwl_mvm_fast_resume(struct iwl_mvm *mvm); #else static inline void iwl_mvm_set_last_nonqos_seq(struct iwl_mvm *mvm, struct ieee80211_vif *vif) { } + +static inline void iwl_mvm_fast_suspend(struct iwl_mvm *mvm) +{ +} + +static inline int iwl_mvm_fast_resume(struct iwl_mvm *mvm) +{ + return 0; +} #endif void iwl_mvm_set_wowlan_qos_seq(struct iwl_mvm_sta *mvm_ap_sta, - struct iwl_wowlan_config_cmd *cmd); + struct iwl_wowlan_config_cmd_v6 *cmd); int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm, struct ieee80211_vif *vif, bool disable_offloading, bool offload_ns, - u32 cmd_flags); + u32 cmd_flags, + u8 sta_id); /* BT Coex */ int iwl_mvm_send_bt_init_conf(struct iwl_mvm *mvm); -void iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm, - struct iwl_rx_cmd_buffer *rxb); +void iwl_mvm_rx_bt_coex_old_notif(struct iwl_mvm *mvm, + struct iwl_rx_cmd_buffer *rxb); void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif, enum ieee80211_rssi_event_data); void iwl_mvm_bt_coex_vif_change(struct iwl_mvm *mvm); @@ -1859,18 +2253,23 @@ iwl_mvm_beacon_filter_debugfs_parameters(struct ieee80211_vif *vif, {} #endif int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm, - struct ieee80211_vif *vif, - u32 flags); + struct ieee80211_vif *vif); int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm, - struct ieee80211_vif *vif, - u32 flags); + struct ieee80211_vif *vif); /* SMPS */ void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif, enum iwl_mvm_smps_type_request req_type, - enum ieee80211_smps_mode smps_request); + enum ieee80211_smps_mode smps_request, + unsigned int link_id); +void +iwl_mvm_update_smps_on_active_links(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + enum iwl_mvm_smps_type_request req_type, + enum ieee80211_smps_mode smps_request); bool iwl_mvm_rx_diversity_allowed(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt); -void iwl_mvm_apply_fw_smps_request(struct ieee80211_vif *vif); +void iwl_mvm_update_link_smps(struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf); /* Low latency */ int iwl_mvm_update_low_latency(struct iwl_mvm *mvm, struct ieee80211_vif *vif, @@ -1939,16 +2338,12 @@ void iwl_mvm_vif_set_low_latency(struct iwl_mvm_vif *mvmvif, bool set, */ static inline u32 iwl_mvm_flushable_queues(struct iwl_mvm *mvm) { - return ((BIT(mvm->trans->trans_cfg->base_params->num_of_queues) - 1) & + return ((BIT(mvm->trans->mac_cfg->base->num_of_queues) - 1) & ~BIT(IWL_MVM_DQA_CMD_QUEUE)); } void iwl_mvm_stop_device(struct iwl_mvm *mvm); -/* Re-configure the SCD for a queue that has already been configured */ -int iwl_mvm_reconfig_scd(struct iwl_mvm *mvm, int queue, int fifo, int sta_id, - int tid, int frame_limit, u16 ssn); - /* Thermal management and CT-kill */ void iwl_mvm_tt_tx_backoff(struct iwl_mvm *mvm, u32 backoff); void iwl_mvm_temp_notif(struct iwl_mvm *mvm, @@ -1975,7 +2370,7 @@ static inline void iwl_mvm_vendor_cmds_register(struct iwl_mvm *mvm) {} #endif /* Location Aware Regulatory */ -struct iwl_mcc_update_resp * +struct iwl_mcc_update_resp_v8 * iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2, enum iwl_mcc_source src_id); int iwl_mvm_init_mcc(struct iwl_mvm *mvm); @@ -1987,7 +2382,7 @@ struct ieee80211_regdomain *iwl_mvm_get_regdomain(struct wiphy *wiphy, bool *changed); struct ieee80211_regdomain *iwl_mvm_get_current_regdomain(struct iwl_mvm *mvm, bool *changed); -int iwl_mvm_init_fw_regd(struct iwl_mvm *mvm); +int iwl_mvm_init_fw_regd(struct iwl_mvm *mvm, bool force_regd_sync); void iwl_mvm_update_changed_regdom(struct iwl_mvm *mvm); /* smart fifo */ @@ -1995,17 +2390,13 @@ int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *vif, bool added_vif); /* FTM responder */ -int iwl_mvm_ftm_start_responder(struct iwl_mvm *mvm, struct ieee80211_vif *vif); +int iwl_mvm_ftm_start_responder(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf); void iwl_mvm_ftm_restart_responder(struct iwl_mvm *mvm, - struct ieee80211_vif *vif); + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf); void iwl_mvm_ftm_responder_stats(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); -int iwl_mvm_ftm_resp_remove_pasn_sta(struct iwl_mvm *mvm, - struct ieee80211_vif *vif, u8 *addr); -int iwl_mvm_ftm_respoder_add_pasn_sta(struct iwl_mvm *mvm, - struct ieee80211_vif *vif, - u8 *addr, u32 cipher, u8 *tk, u32 tk_len, - u8 *hltk, u32 hltk_len); void iwl_mvm_ftm_responder_clear(struct iwl_mvm *mvm, struct ieee80211_vif *vif); @@ -2020,10 +2411,6 @@ int iwl_mvm_ftm_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, void iwl_mvm_ftm_abort(struct iwl_mvm *mvm, struct cfg80211_pmsr_request *req); void iwl_mvm_ftm_initiator_smooth_config(struct iwl_mvm *mvm); void iwl_mvm_ftm_initiator_smooth_stop(struct iwl_mvm *mvm); -int iwl_mvm_ftm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif, - u8 *addr, u32 cipher, u8 *tk, u32 tk_len, - u8 *hltk, u32 hltk_len); -void iwl_mvm_ftm_remove_pasn_sta(struct iwl_mvm *mvm, u8 *addr); /* TDLS */ @@ -2038,7 +2425,8 @@ void iwl_mvm_teardown_tdls_peers(struct iwl_mvm *mvm); void iwl_mvm_recalc_tdls_state(struct iwl_mvm *mvm, struct ieee80211_vif *vif, bool sta_added); void iwl_mvm_mac_mgd_protect_tdls_discover(struct ieee80211_hw *hw, - struct ieee80211_vif *vif); + struct ieee80211_vif *vif, + unsigned int link_id); int iwl_mvm_tdls_channel_switch(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u8 oper_class, @@ -2057,7 +2445,6 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm, enum iwl_mvm_rxq_notif_type type, bool sync, const void *data, u32 size); -void iwl_mvm_reorder_timer_expired(struct timer_list *t); struct ieee80211_vif *iwl_mvm_get_bss_vif(struct iwl_mvm *mvm); struct ieee80211_vif *iwl_mvm_get_vif_by_macid(struct iwl_mvm *mvm, u32 macid); bool iwl_mvm_is_vif_assoc(struct iwl_mvm *mvm); @@ -2073,31 +2460,69 @@ void iwl_mvm_tcm_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif); void iwl_mvm_tcm_rm_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif); u8 iwl_mvm_tcm_load_percentage(u32 airtime, u32 elapsed); -void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error); unsigned int iwl_mvm_get_wd_timeout(struct iwl_mvm *mvm, - struct ieee80211_vif *vif, - bool tdls, bool cmd_q); + struct ieee80211_vif *vif); void iwl_mvm_connection_loss(struct iwl_mvm *mvm, struct ieee80211_vif *vif, const char *errmsg); void iwl_mvm_event_frame_timeout_callback(struct iwl_mvm *mvm, struct ieee80211_vif *vif, const struct ieee80211_sta *sta, u16 tid); +void iwl_mvm_mei_scan_filter_init(struct iwl_mei_scan_filter *mei_scan_filter); +void iwl_mvm_ptp_init(struct iwl_mvm *mvm); +void iwl_mvm_ptp_remove(struct iwl_mvm *mvm); +u64 iwl_mvm_ptp_get_adj_time(struct iwl_mvm *mvm, u64 base_time); int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b); int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm); int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm); -void iwl_mvm_get_acpi_tables(struct iwl_mvm *mvm); +void iwl_mvm_get_bios_tables(struct iwl_mvm *mvm); #ifdef CONFIG_IWLWIFI_DEBUGFS -void iwl_mvm_sta_add_debugfs(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct dentry *dir); +void iwl_mvm_link_sta_add_debugfs(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_link_sta *link_sta, + struct dentry *dir); +void iwl_mvm_link_add_debugfs(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf, + struct dentry *dir); #endif +/* new MLD related APIs */ +int iwl_mvm_sec_key_add(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *keyconf); +int iwl_mvm_sec_key_del(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *keyconf); +int iwl_mvm_sec_key_del_pasn(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + u32 sta_mask, + struct ieee80211_key_conf *keyconf); +void iwl_mvm_sec_key_remove_ap(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct iwl_mvm_vif_link_info *link, + unsigned int link_id); +int iwl_mvm_mld_update_sta_keys(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + u32 old_sta_mask, + u32 new_sta_mask); +int iwl_mvm_mld_send_key(struct iwl_mvm *mvm, u32 sta_mask, u32 key_flags, + struct ieee80211_key_conf *keyconf); +u32 iwl_mvm_get_sec_flags(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *keyconf); + +bool iwl_rfi_supported(struct iwl_mvm *mvm); int iwl_rfi_send_config_cmd(struct iwl_mvm *mvm, struct iwl_rfi_lut_entry *rfi_table); struct iwl_rfi_freq_table_resp_cmd *iwl_rfi_get_freq_table(struct iwl_mvm *mvm); +void iwl_rfi_deactivate_notif_handler(struct iwl_mvm *mvm, + struct iwl_rx_cmd_buffer *rxb); static inline u8 iwl_mvm_phy_band_from_nl80211(enum nl80211_band band) { @@ -2114,6 +2539,61 @@ static inline u8 iwl_mvm_phy_band_from_nl80211(enum nl80211_band band) } } +static inline u8 iwl_mvm_nl80211_band_from_phy(u8 phy_band) +{ + switch (phy_band) { + case PHY_BAND_24: + return NL80211_BAND_2GHZ; + case PHY_BAND_5: + return NL80211_BAND_5GHZ; + case PHY_BAND_6: + return NL80211_BAND_6GHZ; + default: + WARN_ONCE(1, "Unsupported phy band (%u)\n", phy_band); + return NL80211_BAND_5GHZ; + } +} + +/* Channel Switch */ +void iwl_mvm_channel_switch_disconnect_wk(struct work_struct *wk); +int iwl_mvm_post_channel_switch(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link); + +/* Channel Context */ +/** + * struct iwl_mvm_switch_vif_chanctx_ops - callbacks for switch_vif_chanctx() + * + * Since the only difference between both MLD and + * non-MLD versions of switch_vif_chanctx() is these function calls, + * each version will send its specific function calls to + * %iwl_mvm_switch_vif_chanctx_common(). + * + * @__assign_vif_chanctx: pointer to the function that assigns a chanctx to + * a given vif + * @__unassign_vif_chanctx: pointer to the function that unassigns a chanctx to + * a given vif + */ +struct iwl_mvm_switch_vif_chanctx_ops { + int (*__assign_vif_chanctx)(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf, + struct ieee80211_chanctx_conf *ctx, + bool switching_chanctx); + void (*__unassign_vif_chanctx)(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf, + struct ieee80211_chanctx_conf *ctx, + bool switching_chanctx); +}; + +int +iwl_mvm_switch_vif_chanctx_common(struct ieee80211_hw *hw, + struct ieee80211_vif_chanctx_switch *vifs, + int n_vifs, + enum ieee80211_chanctx_switch_mode mode, + const struct iwl_mvm_switch_vif_chanctx_ops *ops); + /* Channel info utils */ static inline bool iwl_mvm_has_ultra_hb_channel(struct iwl_mvm *mvm) { @@ -2160,7 +2640,7 @@ static inline void iwl_mvm_set_chan_info(struct iwl_mvm *mvm, static inline void iwl_mvm_set_chan_info_chandef(struct iwl_mvm *mvm, struct iwl_fw_channel_info *ci, - struct cfg80211_chan_def *chandef) + const struct cfg80211_chan_def *chandef) { enum nl80211_band band = chandef->chan->band; @@ -2172,8 +2652,7 @@ iwl_mvm_set_chan_info_chandef(struct iwl_mvm *mvm, static inline int iwl_umac_scan_get_max_profiles(const struct iwl_fw *fw) { - u8 ver = iwl_fw_lookup_cmd_ver(fw, IWL_ALWAYS_LONG_GROUP, - SCAN_OFFLOAD_UPDATE_PROFILES_CMD, + u8 ver = iwl_fw_lookup_cmd_ver(fw, SCAN_OFFLOAD_UPDATE_PROFILES_CMD, IWL_FW_CMD_VER_UNKNOWN); return (ver == IWL_FW_CMD_VER_UNKNOWN || ver < 3) ? IWL_SCAN_MAX_PROFILES : IWL_SCAN_MAX_PROFILES_V2; @@ -2216,24 +2695,208 @@ static inline void iwl_mvm_mei_host_disassociated(struct iwl_mvm *mvm) iwl_mei_host_disassociated(); } -static inline void iwl_mvm_mei_device_down(struct iwl_mvm *mvm) +static inline void iwl_mvm_mei_device_state(struct iwl_mvm *mvm, bool up) { if (mvm->mei_registered) - iwl_mei_device_down(); + iwl_mei_device_state(up); } static inline void iwl_mvm_mei_set_sw_rfkill_state(struct iwl_mvm *mvm) { bool sw_rfkill = - mvm->hw_registered ? rfkill_blocked(mvm->hw->wiphy->rfkill) : false; + mvm->hw_registered ? rfkill_soft_blocked(mvm->hw->wiphy->rfkill) : false; if (mvm->mei_registered) iwl_mei_set_rfkill_state(iwl_mvm_is_radio_killed(mvm), sw_rfkill); } +static inline bool iwl_mvm_has_p2p_over_aux(struct iwl_mvm *mvm) +{ + u32 cmd_id = WIDE_ID(MAC_CONF_GROUP, ROC_CMD); + + return iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, 0) >= 4; +} + +static inline bool iwl_mvm_mei_filter_scan(struct iwl_mvm *mvm, + struct sk_buff *skb) +{ + struct ieee80211_mgmt *mgmt = (void *)skb->data; + + if (mvm->mei_scan_filter.is_mei_limited_scan && + (ieee80211_is_probe_resp(mgmt->frame_control) || + ieee80211_is_beacon(mgmt->frame_control))) { + skb_queue_tail(&mvm->mei_scan_filter.scan_res, skb); + schedule_work(&mvm->mei_scan_filter.scan_work); + return true; + } + + return false; +} + void iwl_mvm_send_roaming_forbidden_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif, bool forbidden); +/* Callbacks for ieee80211_ops */ +void iwl_mvm_mac_tx(struct ieee80211_hw *hw, + struct ieee80211_tx_control *control, struct sk_buff *skb); +void iwl_mvm_mac_wake_tx_queue(struct ieee80211_hw *hw, + struct ieee80211_txq *txq); + +int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_ampdu_params *params); +int iwl_mvm_op_get_antenna(struct ieee80211_hw *hw, int radio_idx, u32 *tx_ant, + u32 *rx_ant); +int iwl_mvm_op_set_antenna(struct ieee80211_hw *hw, int radio_idx, u32 tx_ant, + u32 rx_ant); +int iwl_mvm_mac_start(struct ieee80211_hw *hw); +void iwl_mvm_mac_reconfig_complete(struct ieee80211_hw *hw, + enum ieee80211_reconfig_type reconfig_type); +void iwl_mvm_mac_stop(struct ieee80211_hw *hw, bool suspend); +static inline int iwl_mvm_mac_config(struct ieee80211_hw *hw, int radio_idx, + u32 changed) +{ + return 0; +} + +u64 iwl_mvm_prepare_multicast(struct ieee80211_hw *hw, + struct netdev_hw_addr_list *mc_list); + +void iwl_mvm_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *total_flags, u64 multicast); +int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_scan_request *hw_req); +void iwl_mvm_mac_cancel_hw_scan(struct ieee80211_hw *hw, + struct ieee80211_vif *vif); +void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta); +void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + enum sta_notify_cmd cmd, + struct ieee80211_sta *sta); +void +iwl_mvm_mac_allow_buffered_frames(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u16 tids, + int num_frames, + enum ieee80211_frame_release_type reason, + bool more_data); +void +iwl_mvm_mac_release_buffered_frames(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u16 tids, + int num_frames, + enum ieee80211_frame_release_type reason, + bool more_data); +int iwl_mvm_mac_set_rts_threshold(struct ieee80211_hw *hw, int radio_idx, + u32 value); +void iwl_mvm_sta_rc_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_link_sta *link_sta, u32 changed); +void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_prep_tx_info *info); +void iwl_mvm_mac_mgd_complete_tx(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_prep_tx_info *info); +void iwl_mvm_mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + u32 queues, bool drop); +void iwl_mvm_mac_flush_sta(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); +int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct cfg80211_sched_scan_request *req, + struct ieee80211_scan_ies *ies); +int iwl_mvm_mac_sched_scan_stop(struct ieee80211_hw *hw, + struct ieee80211_vif *vif); +int iwl_mvm_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key); +void iwl_mvm_mac_update_tkip_key(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_key_conf *keyconf, + struct ieee80211_sta *sta, + u32 iv32, u16 *phase1key); +int iwl_mvm_add_chanctx(struct ieee80211_hw *hw, + struct ieee80211_chanctx_conf *ctx); +void iwl_mvm_remove_chanctx(struct ieee80211_hw *hw, + struct ieee80211_chanctx_conf *ctx); +void iwl_mvm_change_chanctx(struct ieee80211_hw *hw, + struct ieee80211_chanctx_conf *ctx, u32 changed); +int iwl_mvm_tx_last_beacon(struct ieee80211_hw *hw); +void iwl_mvm_channel_switch(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_channel_switch *chsw); +int iwl_mvm_mac_pre_channel_switch(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_channel_switch *chsw); + +void iwl_mvm_abort_channel_switch(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf); +void iwl_mvm_channel_switch_rx_beacon(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_channel_switch *chsw); +void iwl_mvm_mac_event_callback(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + const struct ieee80211_event *event); +void iwl_mvm_sync_rx_queues(struct ieee80211_hw *hw); +int iwl_mvm_mac_testmode_cmd(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + void *data, int len); +int iwl_mvm_mac_get_survey(struct ieee80211_hw *hw, int idx, + struct survey_info *survey); +void iwl_mvm_mac_sta_statistics(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct station_info *sinfo); +int +iwl_mvm_mac_get_ftm_responder_stats(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct cfg80211_ftm_responder_stats *stats); +int iwl_mvm_start_pmsr(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct cfg80211_pmsr_request *request); +void iwl_mvm_abort_pmsr(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct cfg80211_pmsr_request *request); + +bool iwl_mvm_have_links_same_channel(struct iwl_mvm_vif *vif1, + struct iwl_mvm_vif *vif2); +bool iwl_mvm_vif_is_active(struct iwl_mvm_vif *mvmvif); +int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, + struct ieee80211_bss_conf *bss_conf, + s16 tx_power); +int iwl_mvm_set_hw_timestamp(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct cfg80211_set_hw_timestamp *hwts); +int iwl_mvm_update_mu_groups(struct iwl_mvm *mvm, struct ieee80211_vif *vif); +bool iwl_mvm_enable_fils(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct ieee80211_chanctx_conf *ctx); + +struct cfg80211_chan_def * +iwl_mvm_chanctx_def(struct iwl_mvm *mvm, struct ieee80211_chanctx_conf *ctx); + +void iwl_mvm_roc_duration_and_delay(struct ieee80211_vif *vif, + u32 duration_ms, + u32 *duration_tu, + u32 *delay); +int iwl_mvm_roc_add_cmd(struct iwl_mvm *mvm, + struct ieee80211_channel *channel, + struct ieee80211_vif *vif, + int duration, enum iwl_roc_activity activity); + +/* EMLSR */ +bool iwl_mvm_vif_has_esr_cap(struct iwl_mvm *mvm, struct ieee80211_vif *vif); +void +iwl_mvm_send_ap_tx_power_constraint_cmd(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf, + bool is_ap); + +void iwl_mvm_smps_workaround(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + bool update); + +/* rate_n_flags conversion */ +u32 iwl_mvm_v3_rate_from_fw(__le32 rate, u8 rate_ver); +__le32 iwl_mvm_v3_rate_to_fw(u32 rate, u8 rate_ver); + #endif /* __IWL_MVM_H__ */ |
