wireless-drivers-next patches for v5.10

Fourth and last set of patches for v5.10. Most of these are iwlwifi
 patches, but few small fixes to other drivers as well.
 
 Major changes:
 
 iwlwifi
 
 * PNVM support (platform-specific phy config data)
 
 * bump the FW API support to 59
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQEcBAABAgAGBQJfgIilAAoJEG4XJFUm622b/MoH+wfx+CnW2J49uRAlAiAyJ8oW
 pBKvJF1b6kbLeWurQPQH6ecmmYy0H/Cr8Zy4IW+YP7XN5PbSpDe4HXH6GkLP41fv
 73kd0qHPFp42dmArImCqd8+9vAuh6C/taHSPV8klGaSfATUvvDIwgPrxGJnaGvwm
 3E+SOnGcvqRV1fkBi7CArdIa1DzZwyu9q9zvQKbElmL7lX/r5kAzkHZqlMr3ZyjO
 Gvuzvz9FIKvkU81IxtR8VXJh5RQ9WCXvsa00ZoP489jUz/lUoC2Rjofn55BcdAIh
 1V4N7yOM2KFjDo3RWGZo+fqNo6LXREMyVQetmXCWPzFzCkMTN5FCWuj182dnYIM=
 =9NpN
 -----END PGP SIGNATURE-----

Merge tag 'wireless-drivers-next-2020-10-09' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next

Kalle Valo says:

====================
wireless-drivers-next patches for v5.10

Fourth and last set of patches for v5.10. Most of these are iwlwifi
patches, but few small fixes to other drivers as well.

Major changes:

iwlwifi

* PNVM support (platform-specific phy config data)

* bump the FW API support to 59
====================

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2020-10-10 09:36:54 -07:00
Родитель 16573e7cb5 b7d96bca1f
Коммит 8df245c40a
66 изменённых файлов: 1440 добавлений и 320 удалений

Просмотреть файл

@ -6041,8 +6041,10 @@ static int ath11k_mac_setup_iface_combinations(struct ath11k *ar)
n_limits = 2;
limits = kcalloc(n_limits, sizeof(*limits), GFP_KERNEL);
if (!limits)
if (!limits) {
kfree(combinations);
return -ENOMEM;
}
limits[0].max = 1;
limits[0].types |= BIT(NL80211_IFTYPE_STATION);

Просмотреть файл

@ -16,7 +16,7 @@ iwlwifi-objs += iwl-trans.o
iwlwifi-objs += queue/tx.o
iwlwifi-objs += fw/img.o fw/notif-wait.o
iwlwifi-objs += fw/dbg.o
iwlwifi-objs += fw/dbg.o fw/pnvm.o
iwlwifi-$(CONFIG_IWLMVM) += fw/paging.o fw/smem.o fw/init.o
iwlwifi-$(CONFIG_ACPI) += fw/acpi.o
iwlwifi-$(CONFIG_IWLWIFI_DEBUGFS) += fw/debugfs.o

Просмотреть файл

@ -57,7 +57,7 @@
#include "iwl-prph.h"
/* Highest firmware API version supported */
#define IWL_22000_UCODE_API_MAX 57
#define IWL_22000_UCODE_API_MAX 59
/* Lowest firmware API version supported */
#define IWL_22000_UCODE_API_MIN 39
@ -253,7 +253,7 @@ const struct iwl_cfg_trans_params iwl_qu_trans_cfg = {
.device_family = IWL_DEVICE_FAMILY_22000,
.base_params = &iwl_22000_base_params,
.integrated = true,
.xtal_latency = 5000,
.xtal_latency = 500,
.ltr_delay = IWL_CFG_TRANS_LTR_DELAY_200US,
};

Просмотреть файл

@ -6,7 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2015-2017 Intel Deutschland GmbH
* Copyright (C) 2018 - 2019 Intel Corporation
* Copyright(c) 2018 - 2020 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@ -20,7 +20,7 @@
* BSD LICENSE
*
* Copyright(c) 2015-2017 Intel Deutschland GmbH
* Copyright (C) 2018 - 2019 Intel Corporation
* Copyright(c) 2018 - 2020 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -180,7 +180,16 @@ const struct iwl_cfg_trans_params iwl9560_trans_cfg = {
.mq_rx_supported = true,
.rf_id = true,
.integrated = true,
.xtal_latency = 5000,
.xtal_latency = 650,
};
const struct iwl_cfg_trans_params iwl9560_long_latency_trans_cfg = {
.device_family = IWL_DEVICE_FAMILY_9000,
.base_params = &iwl9000_base_params,
.mq_rx_supported = true,
.rf_id = true,
.integrated = true,
.xtal_latency = 2820,
};
const struct iwl_cfg_trans_params iwl9560_shared_clk_trans_cfg = {
@ -189,7 +198,7 @@ const struct iwl_cfg_trans_params iwl9560_shared_clk_trans_cfg = {
.mq_rx_supported = true,
.rf_id = true,
.integrated = true,
.xtal_latency = 5000,
.xtal_latency = 670,
.extra_phy_cfg_flags = FW_PHY_CFG_SHARED_CLK
};

Просмотреть файл

@ -761,7 +761,7 @@ static inline u8 find_first_chain(u8 mask)
return CHAIN_C;
}
/**
/*
* Run disconnected antenna algorithm to find out which antennas are
* disconnected.
*/

Просмотреть файл

@ -58,8 +58,8 @@ static void iwl1000_nic_config(struct iwl_priv *priv)
/**
* iwl_beacon_time_mask_low - mask of lower 32 bit of beacon time
* @priv -- pointer to iwl_priv data structure
* @tsf_bits -- number of bits need to shift for masking)
* @priv: pointer to iwl_priv data structure
* @tsf_bits: number of bits need to shift for masking)
*/
static inline u32 iwl_beacon_time_mask_low(struct iwl_priv *priv,
u16 tsf_bits)
@ -69,8 +69,8 @@ static inline u32 iwl_beacon_time_mask_low(struct iwl_priv *priv,
/**
* iwl_beacon_time_mask_high - mask of higher 32 bit of beacon time
* @priv -- pointer to iwl_priv data structure
* @tsf_bits -- number of bits need to shift for masking)
* @priv: pointer to iwl_priv data structure
* @tsf_bits: number of bits need to shift for masking)
*/
static inline u32 iwl_beacon_time_mask_high(struct iwl_priv *priv,
u16 tsf_bits)

Просмотреть файл

@ -110,7 +110,7 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv,
vif->bss_conf.bssid);
}
/**
/*
* iwlagn_txfifo_flush: send REPLY_TXFIFO_FLUSH command to uCode
*
* pre-requirements:
@ -769,7 +769,7 @@ static u8 iwl_count_chain_bitmap(u32 chain_bitmap)
return res;
}
/**
/*
* iwlagn_set_rxon_chain - Set up Rx chain usage in "staging" RXON image
*
* Selects how many and which Rx receivers/antennas/chains to use.

Просмотреть файл

@ -374,7 +374,7 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear)
&statistics_cmd);
}
/**
/*
* iwl_bg_statistics_periodic - Timer callback to queue statistics
*
* This callback is provided in order to send a statistics request.
@ -533,7 +533,7 @@ static void iwl_continuous_event_trace(struct iwl_priv *priv)
priv->event_log.next_entry = next_entry;
}
/**
/*
* iwl_bg_ucode_trace - Timer callback to log ucode event
*
* The timer is continually set to execute every
@ -762,7 +762,7 @@ static void iwl_send_bt_config(struct iwl_priv *priv)
IWL_ERR(priv, "failed to send BT Coex Config\n");
}
/**
/*
* iwl_alive_start - called after REPLY_ALIVE notification received
* from protocol/runtime uCode (initialization uCode's
* Alive gets handled by iwl_init_alive_start()).
@ -1682,9 +1682,8 @@ static void iwl_dump_nic_error_log(struct iwl_priv *priv)
#define EVENT_START_OFFSET (4 * sizeof(u32))
/**
/*
* iwl_print_event_log - Dump error event log to syslog
*
*/
static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
u32 num_events, u32 mode,
@ -1762,7 +1761,7 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
return pos;
}
/**
/*
* iwl_print_last_event_logs - Dump the newest # of event log to syslog
*/
static int iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity,

Просмотреть файл

@ -151,7 +151,7 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta,
{}
#endif
/**
/*
* The following tables contain the expected throughput metrics for all rates
*
* 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 60 MBits
@ -318,7 +318,7 @@ static u8 rs_tl_add_packet(struct iwl_lq_sta *lq_data,
}
#ifdef CONFIG_MAC80211_DEBUGFS
/**
/*
* Program the device to use fixed rate for frame transmit
* This is for debugging/testing only
* once the device start use fixed rate, we need to reload the module
@ -440,7 +440,7 @@ static s32 get_expected_tpt(struct iwl_scale_tbl_info *tbl, int rs_index)
return 0;
}
/**
/*
* rs_collect_tx_data - Update the success/failure sliding window
*
* We keep a sliding window of the last 62 packets transmitted
@ -673,7 +673,7 @@ static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags,
return 1;
}
/**
/*
* Green-field mode is valid if the station supports it and
* there are no non-GF stations present in the BSS.
*/
@ -689,7 +689,7 @@ static bool rs_use_green(struct ieee80211_sta *sta)
return false;
}
/**
/*
* rs_get_supported_rates - get the available rates
*
* if management frame or broadcast frame only return
@ -2612,7 +2612,7 @@ out:
lq_sta->last_txrate_idx = index;
}
/**
/*
* rs_initialize_lq - Initialize a station's hardware rate table
*
* The uCode's station table contains a table of fallback rates

Просмотреть файл

@ -132,7 +132,7 @@ static void iwlagn_rx_beacon_notif(struct iwl_priv *priv,
priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status);
}
/**
/*
* iwl_good_plcp_health - checks for plcp error.
*
* When the plcp error is exceeding the thresholds, reset the radio
@ -929,7 +929,7 @@ static void iwlagn_rx_noa_notification(struct iwl_priv *priv,
kfree_rcu(old_data, rcu_head);
}
/**
/*
* iwl_setup_rx_handlers - Initialize Rx handler callbacks
*
* Setup the RX handlers for each of the reply types sent from the uCode

Просмотреть файл

@ -689,7 +689,7 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf)
_iwl_set_rxon_ht(priv, ht_conf, ctx);
}
/**
/*
* iwl_set_rxon_channel - Set the band and channel values in staging RXON
* @ch: requested channel as a pointer to struct ieee80211_channel
@ -826,7 +826,7 @@ static int iwl_check_rxon_cmd(struct iwl_priv *priv,
return errors ? -EINVAL : 0;
}
/**
/*
* iwl_full_rxon_required - check if full RXON (vs RXON_ASSOC) cmd is needed
* @priv: staging_rxon is compared to active_rxon
*
@ -1007,7 +1007,7 @@ static void iwl_calc_basic_rates(struct iwl_priv *priv,
ctx->staging.ofdm_basic_rates = ofdm;
}
/**
/*
* iwlagn_commit_rxon - commit staging_rxon to hardware
*
* The RXON command in staging_rxon is committed to the hardware and

Просмотреть файл

@ -186,7 +186,7 @@ static void iwl_do_scan_abort(struct iwl_priv *priv)
IWL_DEBUG_SCAN(priv, "Successfully send scan abort\n");
}
/**
/*
* iwl_scan_cancel - Cancel any currently executing HW scan
*/
int iwl_scan_cancel(struct iwl_priv *priv)
@ -196,10 +196,9 @@ int iwl_scan_cancel(struct iwl_priv *priv)
return 0;
}
/**
/*
* iwl_scan_cancel_timeout - Cancel any currently executing HW scan
* @ms: amount of time to wait (in milliseconds) for scan to abort
*
*/
void iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms)
{
@ -560,10 +559,9 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv,
return added;
}
/**
/*
* iwl_fill_probe_req - fill in all required fields and IE for probe request
*/
static u16 iwl_fill_probe_req(struct ieee80211_mgmt *frame, const u8 *ta,
const u8 *ies, int ie_len, const u8 *ssid,
u8 ssid_len, int left)

Просмотреть файл

@ -234,7 +234,7 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
priv->stations[index].sta.station_flags |= flags;
}
/**
/*
* iwl_prep_station - Prepare station information for addition
*
* should be called with sta_lock held
@ -323,7 +323,7 @@ u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
#define STA_WAIT_TIMEOUT (HZ/2)
/**
/*
* iwl_add_station_common -
*/
int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
@ -383,7 +383,7 @@ int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
return ret;
}
/**
/*
* iwl_sta_ucode_deactivate - deactivate ucode status for a station
*/
static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, u8 sta_id)
@ -451,7 +451,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv,
return ret;
}
/**
/*
* iwl_remove_station - Remove driver's knowledge of station.
*/
int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
@ -601,7 +601,7 @@ static void iwl_sta_fill_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
link_cmd->sta_id = sta_id;
}
/**
/*
* iwl_clear_ucode_stations - clear ucode station table bits
*
* This function clears all the bits in the driver indicating
@ -636,7 +636,7 @@ void iwl_clear_ucode_stations(struct iwl_priv *priv,
"No active stations found to be cleared\n");
}
/**
/*
* iwl_restore_stations() - Restore driver known stations to device
*
* All stations considered active by driver, but not present in ucode, is
@ -773,7 +773,7 @@ static inline void iwl_dump_lq_cmd(struct iwl_priv *priv,
}
#endif
/**
/*
* is_lq_table_valid() - Test one aspect of LQ cmd for validity
*
* It sometimes happens when a HT rate has been in use and we
@ -807,7 +807,7 @@ static bool is_lq_table_valid(struct iwl_priv *priv,
return true;
}
/**
/*
* iwl_send_lq_cmd() - Send link quality command
* @init: This command is sent as part of station initialization right
* after station has been added.
@ -1258,7 +1258,7 @@ int iwl_set_dynamic_key(struct iwl_priv *priv,
return ret;
}
/**
/*
* iwlagn_alloc_bcast_station - add broadcast station into driver's station table.
*
* This adds the broadcast station into the driver's station table
@ -1298,7 +1298,7 @@ int iwlagn_alloc_bcast_station(struct iwl_priv *priv,
return 0;
}
/**
/*
* iwl_update_bcast_station - update broadcast station's LQ command
*
* Only used by iwlagn. Placed here to have all bcast station management
@ -1341,7 +1341,7 @@ int iwl_update_bcast_stations(struct iwl_priv *priv)
return ret;
}
/**
/*
* iwl_sta_tx_modify_enable_tid - Enable Tx for this TID in station table
*/
int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid)

Просмотреть файл

@ -803,7 +803,7 @@ static void iwlagn_non_agg_tx_status(struct iwl_priv *priv,
rcu_read_unlock();
}
/**
/*
* translate ucode response to mac80211 tx status control values
*/
static void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags,
@ -1256,7 +1256,7 @@ void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb)
}
}
/**
/*
* iwlagn_rx_reply_compressed_ba - Handler for REPLY_COMPRESSED_BA
*
* Handles block-acknowledge notification from device, which reports success

Просмотреть файл

@ -662,17 +662,25 @@ int iwl_sar_geo_init(struct iwl_fw_runtime *fwrt,
}
for (i = 0; i < ACPI_NUM_GEO_PROFILES; i++) {
struct iwl_per_chain_offset *chain =
(struct iwl_per_chain_offset *)&table[i];
for (j = 0; j < n_bands; j++) {
struct iwl_per_chain_offset *chain =
&table[i * n_bands + j];
u8 *value;
if (j * ACPI_GEO_PER_CHAIN_SIZE >=
ARRAY_SIZE(fwrt->geo_profiles[0].values))
/*
* Currently we only store lb an hb values, and
* don't have any special ones for uhb. So leave
* those empty for the time being
*/
break;
value = &fwrt->geo_profiles[i].values[j *
ACPI_GEO_PER_CHAIN_SIZE];
chain[j].max_tx_power = cpu_to_le16(value[0]);
chain[j].chain_a = value[1];
chain[j].chain_b = value[2];
chain->max_tx_power = cpu_to_le16(value[0]);
chain->chain_a = value[1];
chain->chain_b = value[2];
IWL_DEBUG_RADIO(fwrt,
"SAR geographic profile[%d] Band[%d]: chain A = %d chain B = %d max_tx_power = %d\n",
i, j, value[1], value[2], value[0]);

Просмотреть файл

@ -105,7 +105,6 @@
#define APCI_WTAS_BLACK_LIST_MAX 16
#define ACPI_WTAS_WIFI_DATA_SIZE (3 + APCI_WTAS_BLACK_LIST_MAX)
#define ACPI_WGDS_NUM_BANDS 2
#define ACPI_WGDS_TABLE_SIZE 3
#define ACPI_PPAG_WIFI_DATA_SIZE ((IWL_NUM_CHAIN_LIMITS * \

Просмотреть файл

@ -5,7 +5,7 @@
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2012 - 2014, 2020 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
*
@ -27,7 +27,7 @@
*
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2012 - 2014, 2020 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* All rights reserved.
@ -59,10 +59,12 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
#ifndef __iwl_fw_api_binding_h__
#define __iwl_fw_api_binding_h__
#include <fw/file.h>
#include <fw/img.h>
#define MAX_MACS_IN_BINDING (3)
#define MAX_BINDINGS (4)
@ -112,6 +114,14 @@ struct iwl_binding_cmd {
#define IWL_LMAC_24G_INDEX 0
#define IWL_LMAC_5G_INDEX 1
static inline u32 iwl_mvm_get_lmac_id(const struct iwl_fw *fw,
enum nl80211_band band){
if (!fw_has_capa(&fw->ucode_capa, IWL_UCODE_TLV_CAPA_CDB_SUPPORT) ||
band == NL80211_BAND_2GHZ)
return IWL_LMAC_24G_INDEX;
return IWL_LMAC_5G_INDEX;
}
/* The maximal number of fragments in the FW's schedule session */
#define IWL_MVM_MAX_QUOTA 128

Просмотреть файл

@ -411,7 +411,8 @@ enum iwl_legacy_cmds {
* one of &struct iwl_statistics_cmd,
* &struct iwl_notif_statistics_v11,
* &struct iwl_notif_statistics_v10,
* &struct iwl_notif_statistics
* &struct iwl_notif_statistics,
* &struct iwl_statistics_operational_ntfy
*/
STATISTICS_CMD = 0x9c,
@ -419,7 +420,8 @@ enum iwl_legacy_cmds {
* @STATISTICS_NOTIFICATION:
* one of &struct iwl_notif_statistics_v10,
* &struct iwl_notif_statistics_v11,
* &struct iwl_notif_statistics
* &struct iwl_notif_statistic,
* &struct iwl_statistics_operational_ntfy
*/
STATISTICS_NOTIFICATION = 0x9d,

Просмотреть файл

@ -70,7 +70,7 @@
#define NUM_MAC_INDEX (NUM_MAC_INDEX_DRIVER + 1)
#define NUM_MAC_INDEX_CDB (NUM_MAC_INDEX_DRIVER + 2)
#define IWL_MVM_STATION_COUNT 16
#define IWL_MVM_STATION_COUNT_MAX 16
#define IWL_MVM_INVALID_STA 0xFF
enum iwl_ac {

Просмотреть файл

@ -90,6 +90,11 @@ enum iwl_regulatory_and_nvm_subcmd_ids {
* @TAS_CONFIG: &struct iwl_tas_config_cmd
*/
TAS_CONFIG = 0x3,
/**
* @PNVM_INIT_COMPLETE_NTFY: &struct iwl_pnvm_init_complete_ntfy
*/
PNVM_INIT_COMPLETE_NTFY = 0xFE,
};
/**
@ -476,4 +481,12 @@ struct iwl_lari_config_change_cmd {
__le32 config_bitmap;
} __packed; /* LARI_CHANGE_CONF_CMD_S_VER_1 */
/**
* struct iwl_pnvm_init_complete_ntfy - PNVM initialization complete
* @status: PNVM image loading status
*/
struct iwl_pnvm_init_complete_ntfy {
__le32 status;
} __packed; /* PNVM_INIT_COMPLETE_NTFY_S_VER_1 */
#endif /* __iwl_fw_api_nvm_reg_h__ */

Просмотреть файл

@ -193,6 +193,8 @@ enum IWL_TLC_HT_BW_RATES {
* @sgi_ch_width_supp: bitmap of SGI support per channel width
* use BIT(@enum iwl_tlc_mng_cfg_cw)
* @reserved2: reserved
* @max_tx_op: max TXOP in uSecs for all AC (BK, BE, VO, VI),
* set zero for no limit.
*/
struct iwl_tlc_config_cmd {
u8 sta_id;
@ -206,8 +208,9 @@ struct iwl_tlc_config_cmd {
__le16 ht_rates[IWL_TLC_NSS_MAX][2];
__le16 max_mpdu_len;
u8 sgi_ch_width_supp;
u8 reserved2[1];
} __packed; /* TLC_MNG_CONFIG_CMD_API_S_VER_2 */
u8 reserved2;
__le32 max_tx_op;
} __packed; /* TLC_MNG_CONFIG_CMD_API_S_VER_3 */
/**
* enum iwl_tlc_update_flags - updated fields

Просмотреть файл

@ -380,7 +380,7 @@ struct iwl_mvm_add_sta_cmd {
u8 add_modify;
u8 awake_acs;
__le16 tid_disable_tx;
__le32 mac_id_n_color;
__le32 mac_id_n_color; /* can be used for lmac id when using cmd v12 */
u8 addr[ETH_ALEN]; /* _STA_ID_MODIFY_INFO_API_S_VER_1 */
__le16 reserved2;
u8 sta_id;

Просмотреть файл

@ -5,10 +5,9 @@
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* Copyright (C) 2018 Intel Corporation
* Copyright(c) 2012 - 2014, 2018, 2020 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@ -28,9 +27,8 @@
*
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright (C) 2018 Intel Corporation
* Copyright(c) 2012 - 2014, 2018, 2020 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -383,14 +381,14 @@ struct mvm_statistics_load {
__le32 air_time[MAC_INDEX_AUX];
__le32 byte_count[MAC_INDEX_AUX];
__le32 pkt_count[MAC_INDEX_AUX];
u8 avg_energy[IWL_MVM_STATION_COUNT];
u8 avg_energy[IWL_MVM_STATION_COUNT_MAX];
} __packed; /* STATISTICS_RX_MAC_STATION_S_VER_3 */
struct mvm_statistics_load_v1 {
__le32 air_time[NUM_MAC_INDEX];
__le32 byte_count[NUM_MAC_INDEX];
__le32 pkt_count[NUM_MAC_INDEX];
u8 avg_energy[IWL_MVM_STATION_COUNT];
u8 avg_energy[IWL_MVM_STATION_COUNT_MAX];
} __packed; /* STATISTICS_RX_MAC_STATION_S_VER_1 */
struct mvm_statistics_rx {
@ -466,4 +464,465 @@ struct iwl_statistics_cmd {
__le32 flags;
} __packed; /* STATISTICS_CMD_API_S_VER_1 */
#define MAX_BCAST_FILTER_NUM 8
/**
* enum iwl_fw_statistics_type
*
* @FW_STATISTICS_OPERATIONAL: operational statistics
* @FW_STATISTICS_PHY: phy statistics
* @FW_STATISTICS_MAC: mac statistics
* @FW_STATISTICS_RX: rx statistics
* @FW_STATISTICS_TX: tx statistics
* @FW_STATISTICS_DURATION: duration statistics
* @FW_STATISTICS_HE: he statistics
*/
enum iwl_fw_statistics_type {
FW_STATISTICS_OPERATIONAL,
FW_STATISTICS_PHY,
FW_STATISTICS_MAC,
FW_STATISTICS_RX,
FW_STATISTICS_TX,
FW_STATISTICS_DURATION,
FW_STATISTICS_HE,
}; /* FW_STATISTICS_TYPE_API_E_VER_1 */
/**
* struct iwl_statistics_ntfy_hdr
*
* @type: struct type
* @version: version of the struct
* @size: size in bytes
*/
struct iwl_statistics_ntfy_hdr {
u8 type;
u8 version;
__le16 size;
}; /* STATISTICS_NTFY_HDR_API_S_VER_1 */
/**
* struct iwl_statistics_operational_ntfy
*
* @hdr: general statistics header
* @flags: bitmap of possible notification structures
* @mac_id: mac on which the beacon was received
* @beacon_filter_average_energy: Average energy [-dBm] of the 2
* antennas.
* @beacon_filter_reason: beacon filter reason
* @radio_temperature: radio temperature
* @air_time: air time
* @beacon_counter: all beacons (both filtered and not filtered)
* @beacon_average_energy: all beacons (both filtered and not
* filtered)
* @beacon_rssi_a: beacon RSSI on antenna A
* @beacon_rssi_b: beacon RSSI on antenna B
* @rx_bytes: per MAC RX byte count
* @rx_time: rx time
* @tx_time: usec the radio is transmitting.
* @on_time_rf: The total time in usec the RF is awake.
* @on_time_scan: usec the radio is awake due to scan.
* @average_energy: in fact it is minus the energy..
* @reserved: reserved
*/
struct iwl_statistics_operational_ntfy {
struct iwl_statistics_ntfy_hdr hdr;
__le32 flags;
__le32 mac_id;
__le32 beacon_filter_average_energy;
__le32 beacon_filter_reason;
__le32 radio_temperature;
__le32 air_time[MAC_INDEX_AUX];
__le32 beacon_counter[MAC_INDEX_AUX];
__le32 beacon_average_energy[MAC_INDEX_AUX];
__le32 beacon_rssi_a;
__le32 beacon_rssi_b;
__le32 rx_bytes[MAC_INDEX_AUX];
__le64 rx_time;
__le64 tx_time;
__le64 on_time_rf;
__le64 on_time_scan;
__le32 average_energy[IWL_MVM_STATION_COUNT_MAX];
__le32 reserved;
} __packed; /* STATISTICS_OPERATIONAL_NTFY_API_S_VER_14 */
/**
* struct iwl_statistics_phy_ntfy
*
* @hdr: general statistics header
* RX PHY related statistics
* @energy_and_config: ???
* @rssi_band: @31:24 rssiAllBand_B, 23:16 rssiInBand_B, 15:8
* rssiAllBand_A, 7:0 rssiInBand_A
* @agc_word: @31:16 agcWord_B, 15:0 agcWord_A
* @agc_gain: @19:10 agcGain_B, 9:0 agcGain_A
* @dfe_gain: @19:10 dfeGain_B, 9:0 dfeGain_A
* @snr_calc_main: @18:0 snrCalcMain
* @energy_calc_main: @18:0 energyCalcMain
* @snr_calc_aux: @18:0 snrCalcAux
* @dsp_dc_estim_a: @27:14 dspDcEstimQA, 13:0 dspDcEstimIA
* @dsp_dc_estim_b: @27:14 dspDcEstimQB, 13:0 dspDcEstimIB
* @ina_detec_type_and_ofdm_corr_comb: @31:31 inaDetectCckMrc,
* 30:27 inaDetectType, 26:0 ofdmCorrComb
* @cw_corr_comb: @26:0 cwCorrComb
* @rssi_comb: @25:0 rssiComb
* @auto_corr_cck: @23:12 autoCck, 11:00 crossCck
* @ofdm_fine_freq_and_pina_freq_err: @18:7 ofdmFineFreq, 6:0
* ofdmPinaFreqErr
* @snrm_evm_main: @31:0 snrmEvmMain
* @snrm_evm_aux: @31:0 snrmEvmAux
* @rx_rate: @31:0 rate
* TX PHY related statistics
* @per_chain_enums_and_dsp_atten_a: @perChainEnumsAndDspAtten
* (per version)
* @target_power_and_power_meas_a: @31:16 targetPower_A, 15:0
* powerMeasuredCalc_A
* @tx_config_as_i_and_ac_a: @31:16 txConfigAsI_A, 15:0
* txConfigAc_A
* @predist_dcq_and_dci_a: @31:16 predist_dci_A, 15:0
* predist_dcq_A
* @per_chain_enums_and_dsp_atten_b: @perChainEnumsAndDspAtten
* (per version)
* @target_power_and_power_meas_b: @31:16 targetPower_B, 15:0
* powerMeasuredCalc_B
* @tx_config_as_i_and_ac_b: @31:16 txConfigAsI_B, 15:0
* txConfigAc_B
* @predist_dcq_and_dci_b: @31:16 predist_dci_B, 15:0
* predist_dcq_B
* @tx_rate: @31:0 rate
* @tlc_backoff: @31:0 tlcBackoff
* @mpapd_calib_mode_mpapd_calib_type_a: @31:16
* mpapdCalibMode_A, 15:0 mpapdCalibType_A
* @psat_and_phy_power_limit_a: @31:16 psat_A, 15:0
* phyPowerLimit_A
* @sar_and_regulatory_power_limit_a: @31:16 sarPowerLimit_A,
* 15:0 regulatoryPowerLimit_A
* @mpapd_calib_mode_mpapd_calib_type_b: @31:16
* mpapdCalibMode_B, 15:0 mpapdCalibType_B
* @psat_and_phy_power_limit_b: @31:16 psat_B, 15:0
* phyPowerLimit_B
* @sar_and_regulatory_power_limit_b: @31:16 sarPowerLimit_B,
* 15:0 regulatoryPowerLimit_B
* @srd_and_driver_power_limits: @31:16 srdPowerLimit, 15:0
* driverPowerLimit
* @reserved: reserved
*/
struct iwl_statistics_phy_ntfy {
struct iwl_statistics_ntfy_hdr hdr;
__le32 energy_and_config;
__le32 rssi_band;
__le32 agc_word;
__le32 agc_gain;
__le32 dfe_gain;
__le32 snr_calc_main;
__le32 energy_calc_main;
__le32 snr_calc_aux;
__le32 dsp_dc_estim_a;
__le32 dsp_dc_estim_b;
__le32 ina_detec_type_and_ofdm_corr_comb;
__le32 cw_corr_comb;
__le32 rssi_comb;
__le32 auto_corr_cck;
__le32 ofdm_fine_freq_and_pina_freq_err;
__le32 snrm_evm_main;
__le32 snrm_evm_aux;
__le32 rx_rate;
__le32 per_chain_enums_and_dsp_atten_a;
__le32 target_power_and_power_meas_a;
__le32 tx_config_as_i_and_ac_a;
__le32 predist_dcq_and_dci_a;
__le32 per_chain_enums_and_dsp_atten_b;
__le32 target_power_and_power_meas_b;
__le32 tx_config_as_i_and_ac_b;
__le32 predist_dcq_and_dci_b;
__le32 tx_rate;
__le32 tlc_backoff;
__le32 mpapd_calib_mode_mpapd_calib_type_a;
__le32 psat_and_phy_power_limit_a;
__le32 sar_and_regulatory_power_limit_a;
__le32 mpapd_calib_mode_mpapd_calib_type_b;
__le32 psat_and_phy_power_limit_b;
__le32 sar_and_regulatory_power_limit_b;
__le32 srd_and_driver_power_limits;
__le32 reserved;
} __packed; /* STATISTICS_PHY_NTFY_API_S_VER_1 */
/**
* struct iwl_statistics_mac_ntfy
*
* @hdr: general statistics header
* @bcast_filter_passed_per_mac: bcast filter passed per mac
* @bcast_filter_dropped_per_mac: bcast filter dropped per mac
* @bcast_filter_passed_per_filter: bcast filter passed per filter
* @bcast_filter_dropped_per_filter: bcast filter dropped per filter
* @reserved: reserved
*/
struct iwl_statistics_mac_ntfy {
struct iwl_statistics_ntfy_hdr hdr;
__le32 bcast_filter_passed_per_mac[NUM_MAC_INDEX_CDB];
__le32 bcast_filter_dropped_per_mac[NUM_MAC_INDEX_CDB];
__le32 bcast_filter_passed_per_filter[MAX_BCAST_FILTER_NUM];
__le32 bcast_filter_dropped_per_filter[MAX_BCAST_FILTER_NUM];
__le32 reserved;
} __packed; /* STATISTICS_MAC_NTFY_API_S_VER_1 */
/**
* struct iwl_statistics_rx_ntfy
*
* @hdr: general statistics header
* @rx_agg_mpdu_cnt: aggregation frame count (number of
* delimiters)
* @rx_agg_cnt: number of RX Aggregations
* @unsupported_mcs: number of PLCP headers that have rate which
* is unsupported by DSP
* @bogus_cts: CTS received when not expecting CTS
* @bogus_ack: ACK received when not expecting ACK
* @rx_byte_count: ???
* @rx_packet_count: ???
* @missed_beacons: ???
* @unresponded_rts: un-responded RTS, due to NAV not zero
* @rxe_frame_limit_overrun: RXE got frame limit overrun
* @sent_ba_rsp_cnt: BA response TX count
* @late_rx_handle: count the number of times the RX path was
* aborted due to late entry
* @num_bt_kills: ???
* @reserved: reserved
*/
struct iwl_statistics_rx_ntfy {
struct iwl_statistics_ntfy_hdr hdr;
__le32 rx_agg_mpdu_cnt;
__le32 rx_agg_cnt;
__le32 unsupported_mcs;
__le32 bogus_cts;
__le32 bogus_ack;
__le32 rx_byte_count[MAC_INDEX_AUX];
__le32 rx_packet_count[MAC_INDEX_AUX];
__le32 missed_beacons;
__le32 unresponded_rts;
__le32 rxe_frame_limit_overrun;
__le32 sent_ba_rsp_cnt;
__le32 late_rx_handle;
__le32 num_bt_kills;
__le32 reserved;
} __packed; /* STATISTICS_RX_NTFY_API_S_VER_1 */
/**
* struct iwl_statistics_tx_ntfy
*
* @hdr: general statistics header
* @cts_timeout: timeout when waiting for CTS
* @ack_timeout: timeout when waiting for ACK
* @dump_msdu_cnt: number of MSDUs that were dumped due to any
* reason
* @burst_abort_missing_next_frame_cnt: number of times a burst
* was aborted due to missing next frame bytes in txfifo
* number of times got timeout when waiting for CTS/ACK/BA and energy was
* detected just after sending the RTS/DATA. this statistics may help getting
* interesting indicators, like the likelihood of collision (so the benefit of
* protection may be estimated Vs. its cost). Or how many of the failures are
* due to collision and how many due to SNR.
* For Link-quality the CTS collision indication is more reliable then the ACK
* collision indication as the RTS frame is short and has more chance that the
* frame/s which caused the collision continue after the RTS was sent.
* @cts_timeout_collision: ???
* ACK/BA failed and energy as detected after DATA
* Note: to get the collision ratio need to:
* ackOrBaTimeoutCollision / (ack_timeout + ba_timeout)
* @ack_or_ba_timeout_collision: ???
* @ba_timeout: timeout when waiting for immediate BA response
* @ba_reschedule_frames: failed to get BA response and
* rescheduled all the non-ACKed frames
* gives the avarage number of frames inside aggregation
* @scd_query_agg_frame_cnt: ???
* @scd_query_no_agg: scheduler query prevented aggregation
* @scd_query_agg: scheduler query allowed aggregation
* @scd_query_mismatch: scheduler query inaccurate, either too
* short or too long
* @agg_terminated_underrun: aggregation was terminated due to
* underrun
* @agg_terminated_bt_prio_kill: aggregation was terminated due
* to BT
* @tx_kill_on_long_retry: count the tx frames dropped due to
* long retry limit (DATA frame failed)
* @tx_kill_on_short_retry: count the tx frames dropped due to
* short retry limit (RTS frame failed)
* TX deffer on energy. This counter is reset on each successful transmit.
* When timer exceed TX deffer limit than will be uCode assert.
* @tx_deffer_counter: ???
* @tx_deffer_base_time: Keep the time of the last successful
* transmit
* @tx_underrun: TX killed due to underrun
* @bt_defer: TX deferred due to BT priority, so probably TX was
* not started.
* @tx_kill_on_dsp_timeout: TX killed on DSP problem detected
* @tx_kill_on_immediate_quiet: TX killed due to immediate quiet
* @kill_ba_cnt: number of times sending BA failed
* @kill_ack_cnt: number of times sending ACK failed
* @kill_cts_cnt: number of times sending CTS failed
* @burst_terminated: Count burst or fragmentation termination
* occurrence
* @late_tx_vec_wr_cnt: ???
* TX is not sent because ucode failed to notify the TRM in SIFS-delta from
* ON_AIR deassertion.
* @late_rx2_tx_cnt: ???
* @scd_query_cnt: count the times SCD query was done to check
* for TX AGG
* @tx_frames_acked_in_agg: count the number of frames
* transmitted inside AGG and were successful
* @last_tx_ch_width_indx: ???
* number of deferred TX per channel width, 0 - 20, 1/2/3 - 40/80/160
* @rx_detected_per_ch_width: ???
* @success_per_ch_width: ???
* @fail_per_ch_width: ???
* @reserved: reserved
*/
struct iwl_statistics_tx_ntfy {
struct iwl_statistics_ntfy_hdr hdr;
__le32 cts_timeout;
__le32 ack_timeout;
__le32 dump_msdu_cnt;
__le32 burst_abort_missing_next_frame_cnt;
__le32 cts_timeout_collision;
__le32 ack_or_ba_timeout_collision;
__le32 ba_timeout;
__le32 ba_reschedule_frames;
__le32 scd_query_agg_frame_cnt;
__le32 scd_query_no_agg;
__le32 scd_query_agg;
__le32 scd_query_mismatch;
__le32 agg_terminated_underrun;
__le32 agg_terminated_bt_prio_kill;
__le32 tx_kill_on_long_retry;
__le32 tx_kill_on_short_retry;
__le32 tx_deffer_counter;
__le32 tx_deffer_base_time;
__le32 tx_underrun;
__le32 bt_defer;
__le32 tx_kill_on_dsp_timeout;
__le32 tx_kill_on_immediate_quiet;
__le32 kill_ba_cnt;
__le32 kill_ack_cnt;
__le32 kill_cts_cnt;
__le32 burst_terminated;
__le32 late_tx_vec_wr_cnt;
__le32 late_rx2_tx_cnt;
__le32 scd_query_cnt;
__le32 tx_frames_acked_in_agg;
__le32 last_tx_ch_width_indx;
__le32 rx_detected_per_ch_width[4];
__le32 success_per_ch_width[4];
__le32 fail_per_ch_width[4];
__le32 reserved;
} __packed; /* STATISTICS_TX_NTFY_API_S_VER_1 */
/**
* struct iwl_statistics_duration_ntfy
*
* @hdr: general statistics header
* @cont_burst_chk_cnt: number of times continuation or
* fragmentation or bursting was checked
* @cont_burst_cnt: number of times continuation or fragmentation
* or bursting was successful
* @wait_for_silence_timeout_cnt: ???
* @reserved: reserved
*/
struct iwl_statistics_duration_ntfy {
struct iwl_statistics_ntfy_hdr hdr;
__le32 cont_burst_chk_cnt;
__le32 cont_burst_cnt;
__le32 wait_for_silence_timeout_cnt;
__le32 reserved;
} __packed; /* STATISTICS_DURATION_NTFY_API_S_VER_1 */
/**
* struct iwl_statistics_he_ntfy
*
* @hdr: general statistics header
* received HE frames
* @rx_siga_valid_cnt: rx HE SIG-A valid
* @rx_siga_invalid_cnt: rx HE SIG-A invalid
* received HE frames w/ valid Sig-A
* @rx_trig_based_frame_cnt: rx HE-TB (trig-based)
* @rx_su_frame_cnt: rx HE-SU
* @rx_sigb_invalid_cnt: rx (suspected) HE-MU w/ bad SIG-B
* @rx_our_bss_color_cnt: rx valid HE SIG-A w/ our BSS color
* @rx_other_bss_color_cnt: rx valid HE SIG-A w/ other BSS color
* @rx_zero_bss_color_cnt: ???
* received HE-MU frames w/ good Sig-B
* @rx_mu_for_us_cnt: match AID
* @rx_mu_not_for_us_cnt: no matched AID
* received HE-MU frames for us (w/ our AID)
* @rx_mu_nss_ar: 0 - SISO, 1 - MIMO2
* @rx_mu_mimo_cnt: full BW RU, compressed SIG-B
* @rx_mu_ru_bw_ar: MU alloc, MHz: 0 - 2, 1 - 5, 2 - 10, 3 - 20,
* 4 - 40, 5 - 80, 6 - 160
* received trigger frames
* @rx_trig_for_us_cnt: ???
* @rx_trig_not_for_us_cnt: ???
* trigger for us
* @rx_trig_with_cs_req_cnt: ???
* @rx_trig_type_ar: ???
* @rx_trig_in_agg_cnt: ???
* basic trigger for us allocations
* @rx_basic_trig_alloc_nss_ar: ???
* @rx_basic_trig_alloc_mu_mimo_cnt: ???
* @rx_basic_trig_alloc_ru_bw_ar: ???
* @rx_basic_trig_total_byte_cnt: ???
* trig-based TX
* @tx_trig_based_cs_req_fail_cnt: ???
* @tx_trig_based_sifs_ok_cnt: ???
* @tx_trig_based_sifs_fail_cnt: ???
* @tx_trig_based_byte_cnt: ???
* @tx_trig_based_pad_byte_cnt: ???
* @tx_trig_based_frame_cnt: ???
* @tx_trig_based_acked_frame_cnt: ???
* @tx_trig_based_ack_timeout_cnt: ???
* HE-SU TX
* @tx_su_frame_cnt: ???
* EDCA <--> MU-EDCA transitions
* @tx_edca_to_mu_edca_cnt: ???
* @tx_mu_edca_to_edca_by_timeout_cnt: ???
* @tx_mu_edca_to_edca_by_ack_fail_cnt: ???
* @tx_mu_edca_to_edca_by_small_alloc_cnt: ???
* @reserved: reserved
*/
struct iwl_statistics_he_ntfy {
struct iwl_statistics_ntfy_hdr hdr;
__le32 rx_siga_valid_cnt;
__le32 rx_siga_invalid_cnt;
__le32 rx_trig_based_frame_cnt;
__le32 rx_su_frame_cnt;
__le32 rx_sigb_invalid_cnt;
__le32 rx_our_bss_color_cnt;
__le32 rx_other_bss_color_cnt;
__le32 rx_zero_bss_color_cnt;
__le32 rx_mu_for_us_cnt;
__le32 rx_mu_not_for_us_cnt;
__le32 rx_mu_nss_ar[2];
__le32 rx_mu_mimo_cnt;
__le32 rx_mu_ru_bw_ar[7];
__le32 rx_trig_for_us_cnt;
__le32 rx_trig_not_for_us_cnt;
__le32 rx_trig_with_cs_req_cnt;
__le32 rx_trig_type_ar[8 + 1];
__le32 rx_trig_in_agg_cnt;
__le32 rx_basic_trig_alloc_nss_ar[2];
__le32 rx_basic_trig_alloc_mu_mimo_cnt;
__le32 rx_basic_trig_alloc_ru_bw_ar[7];
__le32 rx_basic_trig_total_byte_cnt;
__le32 tx_trig_based_cs_req_fail_cnt;
__le32 tx_trig_based_sifs_ok_cnt;
__le32 tx_trig_based_sifs_fail_cnt;
__le32 tx_trig_based_byte_cnt;
__le32 tx_trig_based_pad_byte_cnt;
__le32 tx_trig_based_frame_cnt;
__le32 tx_trig_based_acked_frame_cnt;
__le32 tx_trig_based_ack_timeout_cnt;
__le32 tx_su_frame_cnt;
__le32 tx_edca_to_mu_edca_cnt;
__le32 tx_mu_edca_to_edca_by_timeout_cnt;
__le32 tx_mu_edca_to_edca_by_ack_fail_cnt;
__le32 tx_mu_edca_to_edca_by_small_alloc_cnt;
__le32 reserved;
} __packed; /* STATISTICS_HE_NTFY_API_S_VER_1 */
#endif /* __iwl_fw_api_stats_h__ */

Просмотреть файл

@ -90,6 +90,7 @@ struct iwl_ucode_header {
};
#define IWL_UCODE_TLV_DEBUG_BASE 0x1000005
#define IWL_UCODE_TLV_CONST_BASE 0x100
/*
* new TLV uCode file layout
@ -145,7 +146,13 @@ enum iwl_ucode_tlv_type {
IWL_UCODE_TLV_UMAC_DEBUG_ADDRS = 54,
IWL_UCODE_TLV_LMAC_DEBUG_ADDRS = 55,
IWL_UCODE_TLV_FW_RECOVERY_INFO = 57,
IWL_UCODE_TLV_FW_FSEQ_VERSION = 60,
IWL_UCODE_TLV_HW_TYPE = 58,
IWL_UCODE_TLV_FW_FSEQ_VERSION = 60,
IWL_UCODE_TLV_PNVM_VERSION = 62,
IWL_UCODE_TLV_PNVM_SKU = 64,
IWL_UCODE_TLV_FW_NUM_STATIONS = IWL_UCODE_TLV_CONST_BASE + 0,
IWL_UCODE_TLV_TYPE_DEBUG_INFO = IWL_UCODE_TLV_DEBUG_BASE + 0,
IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION = IWL_UCODE_TLV_DEBUG_BASE + 1,

Просмотреть файл

@ -106,6 +106,7 @@ struct iwl_ucode_capabilities {
u32 flags;
u32 error_log_addr;
u32 error_log_size;
u32 num_stations;
unsigned long _api[BITS_TO_LONGS(NUM_IWL_UCODE_TLV_API)];
unsigned long _capa[BITS_TO_LONGS(NUM_IWL_UCODE_TLV_CAPA)];

Просмотреть файл

@ -0,0 +1,274 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/******************************************************************************
*
* Copyright(c) 2020 Intel Corporation
*
*****************************************************************************/
#include "iwl-drv.h"
#include "pnvm.h"
#include "iwl-prph.h"
#include "iwl-io.h"
#include "fw/api/commands.h"
#include "fw/api/nvm-reg.h"
#include "fw/api/alive.h"
struct iwl_pnvm_section {
__le32 offset;
const u8 data[];
} __packed;
static bool iwl_pnvm_complete_fn(struct iwl_notif_wait_data *notif_wait,
struct iwl_rx_packet *pkt, void *data)
{
struct iwl_trans *trans = (struct iwl_trans *)data;
struct iwl_pnvm_init_complete_ntfy *pnvm_ntf = (void *)pkt->data;
IWL_DEBUG_FW(trans,
"PNVM complete notification received with status %d\n",
le32_to_cpu(pnvm_ntf->status));
return true;
}
static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data,
size_t len)
{
struct iwl_ucode_tlv *tlv;
u32 sha1 = 0;
u16 mac_type = 0, rf_id = 0;
u8 *pnvm_data = NULL, *tmp;
u32 size = 0;
int ret;
IWL_DEBUG_FW(trans, "Handling PNVM section\n");
while (len >= sizeof(*tlv)) {
u32 tlv_len, tlv_type;
len -= sizeof(*tlv);
tlv = (void *)data;
tlv_len = le32_to_cpu(tlv->length);
tlv_type = le32_to_cpu(tlv->type);
if (len < tlv_len) {
IWL_ERR(trans, "invalid TLV len: %zd/%u\n",
len, tlv_len);
ret = -EINVAL;
goto out;
}
data += sizeof(*tlv);
switch (tlv_type) {
case IWL_UCODE_TLV_PNVM_VERSION:
if (tlv_len < sizeof(__le32)) {
IWL_DEBUG_FW(trans,
"Invalid size for IWL_UCODE_TLV_PNVM_VERSION (expected %zd, got %d)\n",
sizeof(__le32), tlv_len);
break;
}
sha1 = le32_to_cpup((__le32 *)data);
IWL_DEBUG_FW(trans,
"Got IWL_UCODE_TLV_PNVM_VERSION %0x\n",
sha1);
break;
case IWL_UCODE_TLV_HW_TYPE:
if (tlv_len < 2 * sizeof(__le16)) {
IWL_DEBUG_FW(trans,
"Invalid size for IWL_UCODE_TLV_HW_TYPE (expected %zd, got %d)\n",
2 * sizeof(__le16), tlv_len);
break;
}
mac_type = le16_to_cpup((__le16 *)data);
rf_id = le16_to_cpup((__le16 *)(data + sizeof(__le16)));
IWL_DEBUG_FW(trans,
"Got IWL_UCODE_TLV_HW_TYPE mac_type 0x%0x rf_id 0x%0x\n",
mac_type, rf_id);
if (mac_type != CSR_HW_REV_TYPE(trans->hw_rev) ||
rf_id != CSR_HW_RFID_TYPE(trans->hw_rf_id)) {
IWL_DEBUG_FW(trans,
"HW mismatch, skipping PNVM section, mac_type 0x%0x, rf_id 0x%0x.\n",
CSR_HW_REV_TYPE(trans->hw_rev), trans->hw_rf_id);
ret = -ENOENT;
goto out;
}
break;
case IWL_UCODE_TLV_SEC_RT: {
struct iwl_pnvm_section *section = (void *)data;
u32 data_len = tlv_len - sizeof(*section);
IWL_DEBUG_FW(trans,
"Got IWL_UCODE_TLV_SEC_RT len %d\n",
tlv_len);
/* TODO: remove, this is a deprecated separator */
if (le32_to_cpup((__le32 *)data) == 0xddddeeee) {
IWL_DEBUG_FW(trans, "Ignoring separator.\n");
break;
}
IWL_DEBUG_FW(trans, "Adding data (size %d)\n",
data_len);
tmp = krealloc(pnvm_data, size + data_len, GFP_KERNEL);
if (!tmp) {
IWL_DEBUG_FW(trans,
"Couldn't allocate (more) pnvm_data\n");
ret = -ENOMEM;
goto out;
}
pnvm_data = tmp;
memcpy(pnvm_data + size, section->data, data_len);
size += data_len;
break;
}
case IWL_UCODE_TLV_PNVM_SKU:
IWL_DEBUG_FW(trans,
"New PNVM section started, stop parsing.\n");
goto done;
default:
IWL_DEBUG_FW(trans, "Found TLV 0x%0x, len %d\n",
tlv_type, tlv_len);
break;
}
len -= ALIGN(tlv_len, 4);
data += ALIGN(tlv_len, 4);
}
done:
if (!size) {
IWL_DEBUG_FW(trans, "Empty PNVM, skipping.\n");
ret = -ENOENT;
goto out;
}
IWL_INFO(trans, "loaded PNVM version 0x%0x\n", sha1);
ret = iwl_trans_set_pnvm(trans, pnvm_data, size);
out:
kfree(pnvm_data);
return ret;
}
static int iwl_pnvm_parse(struct iwl_trans *trans, const u8 *data,
size_t len)
{
struct iwl_ucode_tlv *tlv;
IWL_DEBUG_FW(trans, "Parsing PNVM file\n");
while (len >= sizeof(*tlv)) {
u32 tlv_len, tlv_type;
len -= sizeof(*tlv);
tlv = (void *)data;
tlv_len = le32_to_cpu(tlv->length);
tlv_type = le32_to_cpu(tlv->type);
if (len < tlv_len) {
IWL_ERR(trans, "invalid TLV len: %zd/%u\n",
len, tlv_len);
return -EINVAL;
}
if (tlv_type == IWL_UCODE_TLV_PNVM_SKU) {
struct iwl_sku_id *sku_id =
(void *)(data + sizeof(*tlv));
IWL_DEBUG_FW(trans,
"Got IWL_UCODE_TLV_PNVM_SKU len %d\n",
tlv_len);
IWL_DEBUG_FW(trans, "sku_id 0x%0x 0x%0x 0x%0x\n",
le32_to_cpu(sku_id->data[0]),
le32_to_cpu(sku_id->data[1]),
le32_to_cpu(sku_id->data[2]));
if (trans->sku_id[0] == le32_to_cpu(sku_id->data[0]) &&
trans->sku_id[1] == le32_to_cpu(sku_id->data[1]) &&
trans->sku_id[2] == le32_to_cpu(sku_id->data[2])) {
int ret;
data += sizeof(*tlv) + ALIGN(tlv_len, 4);
len -= ALIGN(tlv_len, 4);
ret = iwl_pnvm_handle_section(trans, data, len);
if (!ret)
return 0;
} else {
IWL_DEBUG_FW(trans, "SKU ID didn't match!\n");
}
} else {
data += sizeof(*tlv) + ALIGN(tlv_len, 4);
len -= ALIGN(tlv_len, 4);
}
}
return -ENOENT;
}
int iwl_pnvm_load(struct iwl_trans *trans,
struct iwl_notif_wait_data *notif_wait)
{
const struct firmware *pnvm;
struct iwl_notification_wait pnvm_wait;
static const u16 ntf_cmds[] = { WIDE_ID(REGULATORY_AND_NVM_GROUP,
PNVM_INIT_COMPLETE_NTFY) };
char pnvm_name[64];
int ret;
/* if the SKU_ID is empty, there's nothing to do */
if (!trans->sku_id[0] && !trans->sku_id[1] && !trans->sku_id[2])
return 0;
/* if we already have it, nothing to do either */
if (trans->pnvm_loaded)
return 0;
/*
* The prefix unfortunately includes a hyphen at the end, so
* don't add the dot here...
*/
snprintf(pnvm_name, sizeof(pnvm_name), "%spnvm",
trans->cfg->fw_name_pre);
/* ...but replace the hyphen with the dot here. */
if (strlen(trans->cfg->fw_name_pre) < sizeof(pnvm_name))
pnvm_name[strlen(trans->cfg->fw_name_pre) - 1] = '.';
ret = firmware_request_nowarn(&pnvm, pnvm_name, trans->dev);
if (ret) {
IWL_DEBUG_FW(trans, "PNVM file %s not found %d\n",
pnvm_name, ret);
} else {
iwl_pnvm_parse(trans, pnvm->data, pnvm->size);
release_firmware(pnvm);
}
iwl_init_notification_wait(notif_wait, &pnvm_wait,
ntf_cmds, ARRAY_SIZE(ntf_cmds),
iwl_pnvm_complete_fn, trans);
/* kick the doorbell */
iwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6,
UREG_DOORBELL_TO_ISR6_PNVM);
return iwl_wait_notification(notif_wait, &pnvm_wait,
MVM_UCODE_PNVM_TIMEOUT);
}
IWL_EXPORT_SYMBOL(iwl_pnvm_load);

Просмотреть файл

@ -0,0 +1,18 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/******************************************************************************
*
* Copyright(c) 2020 Intel Corporation
*
*****************************************************************************/
#ifndef __IWL_PNVM_H__
#define __IWL_PNVM_H__
#include "fw/notif-wait.h"
#define MVM_UCODE_PNVM_TIMEOUT (HZ / 10)
int iwl_pnvm_load(struct iwl_trans *trans,
struct iwl_notif_wait_data *notif_wait);
#endif /* __IWL_PNVM_H__ */

Просмотреть файл

@ -519,6 +519,7 @@ struct iwl_dev_info {
*/
extern const struct iwl_cfg_trans_params iwl9000_trans_cfg;
extern const struct iwl_cfg_trans_params iwl9560_trans_cfg;
extern const struct iwl_cfg_trans_params iwl9560_long_latency_trans_cfg;
extern const struct iwl_cfg_trans_params iwl9560_shared_clk_trans_cfg;
extern const struct iwl_cfg_trans_params iwl_qnj_trans_cfg;
extern const struct iwl_cfg_trans_params iwl_qu_trans_cfg;

Просмотреть файл

@ -138,16 +138,16 @@ struct iwl_prph_scratch_control {
} __packed; /* PERIPH_SCRATCH_CONTROL_S */
/*
* struct iwl_prph_scratch_ror_cfg - ror config
* @ror_base_addr: ror start address
* @ror_size: ror size in DWs
* struct iwl_prph_scratch_pnvm_cfg - ror config
* @pnvm_base_addr: PNVM start address
* @pnvm_size: PNVM size in DWs
* @reserved: reserved
*/
struct iwl_prph_scratch_ror_cfg {
__le64 ror_base_addr;
__le32 ror_size;
struct iwl_prph_scratch_pnvm_cfg {
__le64 pnvm_base_addr;
__le32 pnvm_size;
__le32 reserved;
} __packed; /* PERIPH_SCRATCH_ROR_CFG_S */
} __packed; /* PERIPH_SCRATCH_PNVM_CFG_S */
/*
* struct iwl_prph_scratch_hwm_cfg - hwm config
@ -175,14 +175,14 @@ struct iwl_prph_scratch_rbd_cfg {
* struct iwl_prph_scratch_ctrl_cfg - prph scratch ctrl and config
* @version: version information of context info and HW
* @control: control flags of FH configurations
* @ror_cfg: ror configuration
* @pnvm_cfg: ror configuration
* @hwm_cfg: hwm configuration
* @rbd_cfg: default RX queue configuration
*/
struct iwl_prph_scratch_ctrl_cfg {
struct iwl_prph_scratch_version version;
struct iwl_prph_scratch_control control;
struct iwl_prph_scratch_ror_cfg ror_cfg;
struct iwl_prph_scratch_pnvm_cfg pnvm_cfg;
struct iwl_prph_scratch_hwm_cfg hwm_cfg;
struct iwl_prph_scratch_rbd_cfg rbd_cfg;
} __packed; /* PERIPH_SCRATCH_CTRL_CFG_S */
@ -291,4 +291,7 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans,
const struct fw_img *fw);
void iwl_pcie_ctxt_info_gen3_free(struct iwl_trans *trans);
int iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans,
const void *data, u32 len);
#endif /* __iwl_context_info_file_gen3_h__ */

Просмотреть файл

@ -6,7 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2017 Intel Deutschland GmbH
* Copyright(c) 2018 - 2019 Intel Corporation
* Copyright(c) 2018 - 2020 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@ -20,7 +20,7 @@
* BSD LICENSE
*
* Copyright(c) 2017 Intel Deutschland GmbH
* Copyright(c) 2018 - 2019 Intel Corporation
* Copyright(c) 2018 - 2020 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -225,5 +225,8 @@ void iwl_pcie_ctxt_info_free_paging(struct iwl_trans *trans);
int iwl_pcie_init_fw_sec(struct iwl_trans *trans,
const struct fw_img *fw,
struct iwl_context_info_dram *ctxt_dram);
int iwl_pcie_ctxt_info_alloc_dma(struct iwl_trans *trans,
const void *data, u32 len,
struct iwl_dram_data *dram);
#endif /* __iwl_context_info_file_h__ */

Просмотреть файл

@ -76,6 +76,7 @@
#include "iwl-config.h"
#include "iwl-modparams.h"
#include "fw/api/alive.h"
#include "fw/api/mac.h"
/******************************************************************************
*
@ -102,6 +103,9 @@ static struct dentry *iwl_dbgfs_root;
* @fw_index: firmware revision to try loading
* @firmware_name: composite filename of ucode file to load
* @request_firmware_complete: the firmware has been obtained from user space
* @dbgfs_drv: debugfs root directory entry
* @dbgfs_trans: debugfs transport directory entry
* @dbgfs_op_mode: debugfs op_mode directory entry
*/
struct iwl_drv {
struct list_head list;
@ -1124,6 +1128,19 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
fseq_ver->version);
}
break;
case IWL_UCODE_TLV_FW_NUM_STATIONS:
if (tlv_len != sizeof(u32))
goto invalid_tlv_len;
if (le32_to_cpup((__le32 *)tlv_data) >
IWL_MVM_STATION_COUNT_MAX) {
IWL_ERR(drv,
"%d is an invalid number of station\n",
le32_to_cpup((__le32 *)tlv_data));
goto tlv_error;
}
capa->num_stations =
le32_to_cpup((__le32 *)tlv_data);
break;
case IWL_UCODE_TLV_UMAC_DEBUG_ADDRS: {
struct iwl_umac_debug_addrs *dbg_ptrs =
(void *)tlv_data;
@ -1319,7 +1336,7 @@ static void _iwl_op_mode_stop(struct iwl_drv *drv)
}
}
/**
/*
* iwl_req_fw_callback - callback when firmware was loaded
*
* If loaded successfully, copies the firmware into buffers
@ -1345,6 +1362,7 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
fw->ucode_capa.standard_phy_calibration_size =
IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE;
fw->ucode_capa.n_scan_channels = IWL_DEFAULT_SCAN_CHANNELS;
fw->ucode_capa.num_stations = IWL_MVM_STATION_COUNT_MAX;
/* dump all fw memory areas by default */
fw->dbg.dump_mask = 0xffffffff;

Просмотреть файл

@ -460,6 +460,7 @@ enum {
#define UREG_DOORBELL_TO_ISR6_NMI_BIT BIT(0)
#define UREG_DOORBELL_TO_ISR6_SUSPEND BIT(18)
#define UREG_DOORBELL_TO_ISR6_RESUME BIT(19)
#define UREG_DOORBELL_TO_ISR6_PNVM BIT(20)
#define FSEQ_ERROR_CODE 0xA340C8
#define FSEQ_TOP_INIT_VERSION 0xA34038

Просмотреть файл

@ -200,7 +200,7 @@ int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
if (!(cmd->flags & CMD_ASYNC))
lock_map_acquire_read(&trans->sync_cmd_lockdep_map);
if (!iwl_cmd_groupid(cmd->id))
if (trans->wide_cmd_header && !iwl_cmd_groupid(cmd->id))
cmd->id = DEF_ID(cmd->id);
ret = trans->ops->send_cmd(trans, cmd);

Просмотреть файл

@ -73,6 +73,7 @@
#include "iwl-config.h"
#include "fw/img.h"
#include "iwl-op-mode.h"
#include <linux/firmware.h>
#include "fw/api/cmdhdr.h"
#include "fw/api/txq.h"
#include "fw/api/dbg-tlv.h"
@ -568,6 +569,8 @@ struct iwl_trans_rxq_dma_data {
* Note that the transport must fill in the proper file headers.
* @debugfs_cleanup: used in the driver unload flow to make a proper cleanup
* of the trans debugfs
* @set_pnvm: set the pnvm data in the prph scratch buffer, inside the
* context info.
*/
struct iwl_trans_ops {
@ -640,6 +643,7 @@ struct iwl_trans_ops {
u32 dump_mask);
void (*debugfs_cleanup)(struct iwl_trans *trans);
void (*sync_nmi)(struct iwl_trans *trans);
int (*set_pnvm)(struct iwl_trans *trans, const void *data, u32 len);
};
/**
@ -964,6 +968,7 @@ struct iwl_trans_txqs {
* @hw_id_str: a string with info about HW ID. Set during transport allocation.
* @pm_support: set to true in start_hw if link pm is supported
* @ltr_enabled: set to true if the LTR is enabled
* @wide_cmd_header: true when ucode supports wide command header format
* @num_rx_queues: number of RX queues allocated by the transport;
* the transport must set this before calling iwl_drv_start()
* @iml_len: the length of the image loader
@ -995,14 +1000,17 @@ struct iwl_trans {
u32 hw_rf_id;
u32 hw_id;
char hw_id_str[52];
u32 sku_id[3];
u8 rx_mpdu_cmd, rx_mpdu_cmd_hdr_size;
bool pm_support;
bool ltr_enabled;
u8 pnvm_loaded:1;
const struct iwl_hcmd_arr *command_groups;
int command_groups_size;
bool wide_cmd_header;
u8 num_rx_queues;
@ -1448,6 +1456,21 @@ static inline void iwl_trans_sync_nmi(struct iwl_trans *trans)
trans->ops->sync_nmi(trans);
}
static inline int iwl_trans_set_pnvm(struct iwl_trans *trans,
const void *data, u32 len)
{
if (trans->ops->set_pnvm) {
int ret = trans->ops->set_pnvm(trans, data, len);
if (ret)
return ret;
}
trans->pnvm_loaded = true;
return 0;
}
static inline bool iwl_trans_dbg_ini_valid(struct iwl_trans *trans)
{
return trans->dbg.internal_ini_cfg != IWL_INI_CFG_STATE_NOT_LOADED ||

Просмотреть файл

@ -5,7 +5,7 @@
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2012 - 2014, 2020 Intel Corporation. All rights reserved.
* Copyright(c) 2016 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
@ -26,7 +26,7 @@
*
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2012 - 2014, 2020 Intel Corporation. All rights reserved.
* Copyright(c) 2016 Intel Deutschland GmbH
* All rights reserved.
*
@ -86,11 +86,8 @@ static int iwl_mvm_binding_cmd(struct iwl_mvm *mvm, u32 action,
if (fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT)) {
size = sizeof(cmd);
if (phyctxt->channel->band == NL80211_BAND_2GHZ ||
!iwl_mvm_is_cdb_supported(mvm))
cmd.lmac_id = cpu_to_le32(IWL_LMAC_24G_INDEX);
else
cmd.lmac_id = cpu_to_le32(IWL_LMAC_5G_INDEX);
cmd.lmac_id = cpu_to_le32(iwl_mvm_get_lmac_id(mvm->fw,
phyctxt->channel->band));
} else {
size = IWL_BINDING_CMD_SIZE_V1;
}

Просмотреть файл

@ -344,11 +344,12 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
const u8 *pn;
mvmsta = iwl_mvm_sta_from_mac80211(sta);
ptk_pn = rcu_dereference_protected(
mvmsta->ptk_pn[key->keyidx],
lockdep_is_held(&mvm->mutex));
if (WARN_ON(!ptk_pn))
rcu_read_lock();
ptk_pn = rcu_dereference(mvmsta->ptk_pn[key->keyidx]);
if (WARN_ON(!ptk_pn)) {
rcu_read_unlock();
break;
}
for (i = 0; i < IWL_MAX_TID_COUNT; i++) {
pn = iwl_mvm_find_max_pn(key, ptk_pn, &seq, i,
@ -360,6 +361,8 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
((u64)pn[1] << 32) |
((u64)pn[0] << 40));
}
rcu_read_unlock();
} else {
for (i = 0; i < IWL_NUM_RSC; i++) {
u8 *pn = seq.ccmp.pn;
@ -870,7 +873,6 @@ static int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,
else
cmd_size = sizeof(struct iwl_wowlan_kek_kck_material_cmd_v2);
memset(&kek_kck_cmd, 0, sizeof(kek_kck_cmd));
memcpy(kek_kck_cmd.kck, mvmvif->rekey_data.kck,
mvmvif->rekey_data.kck_len);
kek_kck_cmd.kck_len = cpu_to_le16(mvmvif->rekey_data.kck_len);
@ -1364,10 +1366,12 @@ static void iwl_mvm_set_aes_rx_seq(struct iwl_mvm *mvm, struct aes_sc *scs,
mvmsta = iwl_mvm_sta_from_mac80211(sta);
ptk_pn = rcu_dereference_protected(mvmsta->ptk_pn[key->keyidx],
lockdep_is_held(&mvm->mutex));
if (WARN_ON(!ptk_pn))
rcu_read_lock();
ptk_pn = rcu_dereference(mvmsta->ptk_pn[key->keyidx]);
if (WARN_ON(!ptk_pn)) {
rcu_read_unlock();
return;
}
for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) {
struct ieee80211_key_seq seq = {};
@ -1379,6 +1383,7 @@ static void iwl_mvm_set_aes_rx_seq(struct iwl_mvm *mvm, struct aes_sc *scs,
memcpy(ptk_pn->q[i].pn[tid],
seq.ccmp.pn, IEEE80211_CCMP_PN_LEN);
}
rcu_read_unlock();
} else {
for (tid = 0; tid < IWL_NUM_RSC; tid++) {
struct ieee80211_key_seq seq = {};

Просмотреть файл

@ -174,7 +174,7 @@ static ssize_t iwl_dbgfs_sta_drain_write(struct iwl_mvm *mvm, char *buf,
if (sscanf(buf, "%d %d", &sta_id, &drain) != 2)
return -EINVAL;
if (sta_id < 0 || sta_id >= IWL_MVM_STATION_COUNT)
if (sta_id < 0 || sta_id >= mvm->fw->ucode_capa.num_stations)
return -EINVAL;
if (drain < 0 || drain > 1)
return -EINVAL;
@ -403,7 +403,7 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
mutex_lock(&mvm->mutex);
for (i = 0; i < ARRAY_SIZE(mvm->fw_id_to_mac_id); i++) {
for (i = 0; i < mvm->fw->ucode_capa.num_stations; i++) {
pos += scnprintf(buf + pos, bufsz - pos, "%.2d: ", i);
sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
lockdep_is_held(&mvm->mutex));

Просмотреть файл

@ -354,18 +354,16 @@ int iwl_mvm_ftm_respoder_add_pasn_sta(struct iwl_mvm *mvm,
kfree(sta);
return ret;
}
memcpy(sta->addr, addr, ETH_ALEN);
list_add_tail(&sta->list, &mvm->resp_pasn_list);
}
ret = iwl_mvm_ftm_responder_dyn_cfg_v3(mvm, vif, NULL, &hltk_data);
if (ret) {
if (sta)
iwl_mvm_resp_del_pasn_sta(mvm, vif, sta);
return ret;
}
if (ret && sta)
iwl_mvm_resp_del_pasn_sta(mvm, vif, sta);
memcpy(sta->addr, addr, ETH_ALEN);
list_add_tail(&sta->list, &mvm->resp_pasn_list);
return 0;
return ret;
}
int iwl_mvm_ftm_resp_remove_pasn_sta(struct iwl_mvm *mvm,

Просмотреть файл

@ -70,6 +70,7 @@
#include "iwl-io.h" /* for iwl_mvm_rx_card_state_notif */
#include "iwl-prph.h"
#include "fw/acpi.h"
#include "fw/pnvm.h"
#include "mvm.h"
#include "fw/dbg.h"
@ -77,8 +78,8 @@
#include "iwl-modparams.h"
#include "iwl-nvm-parse.h"
#define MVM_UCODE_ALIVE_TIMEOUT HZ
#define MVM_UCODE_CALIB_TIMEOUT (2*HZ)
#define MVM_UCODE_ALIVE_TIMEOUT (HZ)
#define MVM_UCODE_CALIB_TIMEOUT (2 * HZ)
#define UCODE_VALID_OK cpu_to_le32(0x1)
@ -132,7 +133,14 @@ static int iwl_configure_rxq(struct iwl_mvm *mvm)
.dataflags[0] = IWL_HCMD_DFL_NOCOPY,
};
/* Do not configure default queue, it is configured via context info */
/*
* The default queue is configured via context info, so if we
* have a single queue, there's nothing to do here.
*/
if (mvm->trans->num_rx_queues == 1)
return 0;
/* skip the default queue */
num_queues = mvm->trans->num_rx_queues - 1;
size = struct_size(cmd, data, num_queues);
@ -216,10 +224,29 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
u16 status;
u32 lmac_error_event_table, umac_error_table;
/* we don't use the SKU ID from v5 yet, so handle it as v4 */
/*
* For v5 and above, we can check the version, for older
* versions we need to check the size.
*/
if (iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,
UCODE_ALIVE_NTFY, 0) == 5 ||
iwl_rx_packet_payload_len(pkt) == sizeof(struct iwl_alive_ntf_v4)) {
UCODE_ALIVE_NTFY, 0) == 5) {
struct iwl_alive_ntf_v5 *palive;
palive = (void *)pkt->data;
umac = &palive->umac_data;
lmac1 = &palive->lmac_data[0];
lmac2 = &palive->lmac_data[1];
status = le16_to_cpu(palive->status);
mvm->trans->sku_id[0] = le32_to_cpu(palive->sku_id.data[0]);
mvm->trans->sku_id[1] = le32_to_cpu(palive->sku_id.data[1]);
mvm->trans->sku_id[2] = le32_to_cpu(palive->sku_id.data[2]);
IWL_DEBUG_FW(mvm, "Got sku_id: 0x0%x 0x0%x 0x0%x\n",
mvm->trans->sku_id[0],
mvm->trans->sku_id[1],
mvm->trans->sku_id[2]);
} else if (iwl_rx_packet_payload_len(pkt) == sizeof(struct iwl_alive_ntf_v4)) {
struct iwl_alive_ntf_v4 *palive;
palive = (void *)pkt->data;
@ -397,6 +424,13 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
return -EIO;
}
ret = iwl_pnvm_load(mvm->trans, &mvm->notif_wait);
if (ret) {
IWL_ERR(mvm, "Timeout waiting for PNVM load!\n");
iwl_fw_set_current_image(&mvm->fwrt, old_type);
return ret;
}
iwl_trans_fw_alive(mvm->trans, alive_data.scd_base_addr);
/*
@ -846,14 +880,39 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
{
union iwl_geo_tx_power_profiles_cmd cmd;
u16 len;
u32 n_bands;
int ret;
u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, PHY_OPS_GROUP,
GEO_TX_POWER_LIMIT,
IWL_FW_CMD_VER_UNKNOWN);
/* the table is also at the same position both in v1 and v2 */
ret = iwl_sar_geo_init(&mvm->fwrt, &cmd.v1.table[0][0],
ACPI_WGDS_NUM_BANDS);
BUILD_BUG_ON(offsetof(struct iwl_geo_tx_power_profiles_cmd_v1, ops) !=
offsetof(struct iwl_geo_tx_power_profiles_cmd_v2, ops) ||
offsetof(struct iwl_geo_tx_power_profiles_cmd_v2, ops) !=
offsetof(struct iwl_geo_tx_power_profiles_cmd_v3, ops));
/* the ops field is at the same spot for all versions, so set in v1 */
cmd.v1.ops = cpu_to_le32(IWL_PER_CHAIN_OFFSET_SET_TABLES);
if (cmd_ver == 3) {
len = sizeof(cmd.v3);
n_bands = ARRAY_SIZE(cmd.v3.table[0]);
cmd.v3.table_revision = cpu_to_le32(mvm->fwrt.geo_rev);
} else if (fw_has_api(&mvm->fwrt.fw->ucode_capa,
IWL_UCODE_TLV_API_SAR_TABLE_VER)) {
len = sizeof(cmd.v2);
n_bands = ARRAY_SIZE(cmd.v2.table[0]);
cmd.v2.table_revision = cpu_to_le32(mvm->fwrt.geo_rev);
} else {
len = sizeof(cmd.v1);
n_bands = ARRAY_SIZE(cmd.v1.table[0]);
}
BUILD_BUG_ON(offsetof(struct iwl_geo_tx_power_profiles_cmd_v1, table) !=
offsetof(struct iwl_geo_tx_power_profiles_cmd_v2, table) ||
offsetof(struct iwl_geo_tx_power_profiles_cmd_v2, table) !=
offsetof(struct iwl_geo_tx_power_profiles_cmd_v3, table));
/* the table is at the same position for all versions, so set use v1 */
ret = iwl_sar_geo_init(&mvm->fwrt, &cmd.v1.table[0][0], n_bands);
/*
* It is a valid scenario to not support SAR, or miss wgds table,
@ -862,20 +921,6 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
if (ret)
return 0;
/* the ops field is at the same spot for all versions, so set in v1 */
cmd.v1.ops = cpu_to_le32(IWL_PER_CHAIN_OFFSET_SET_TABLES);
if (cmd_ver == 3) {
len = sizeof(cmd.v3);
cmd.v3.table_revision = cpu_to_le32(mvm->fwrt.geo_rev);
} else if (fw_has_api(&mvm->fwrt.fw->ucode_capa,
IWL_UCODE_TLV_API_SAR_TABLE_VER)) {
len = sizeof(cmd.v2);
cmd.v2.table_revision = cpu_to_le32(mvm->fwrt.geo_rev);
} else {
len = sizeof(cmd.v1);
}
return iwl_mvm_send_cmd_pdu(mvm,
WIDE_ID(PHY_OPS_GROUP, GEO_TX_POWER_LIMIT),
0, len, &cmd);
@ -1400,7 +1445,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
}
/* init the fw <-> mac80211 STA mapping */
for (i = 0; i < ARRAY_SIZE(mvm->fw_id_to_mac_id); i++)
for (i = 0; i < mvm->fw->ucode_capa.num_stations; i++)
RCU_INIT_POINTER(mvm->fw_id_to_mac_id[i], NULL);
mvm->tdls_cs.peer.sta_id = IWL_MVM_INVALID_STA;
@ -1414,10 +1459,23 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
goto error;
}
/* Add auxiliary station for scanning */
ret = iwl_mvm_add_aux_sta(mvm);
if (ret)
goto error;
/*
* Add auxiliary station for scanning.
* Newer versions of this command implies that the fw uses
* internal aux station for all aux activities that don't
* requires a dedicated data queue.
*/
if (iwl_fw_lookup_cmd_ver(mvm->fw, LONG_GROUP,
ADD_STA,
0) < 12) {
/*
* In old version the aux station uses mac id like other
* station and not lmac id
*/
ret = iwl_mvm_add_aux_sta(mvm, MAC_INDEX_AUX);
if (ret)
goto error;
}
/* Add all the PHY contexts */
i = 0;
@ -1563,13 +1621,24 @@ int iwl_mvm_load_d3_fw(struct iwl_mvm *mvm)
goto error;
/* init the fw <-> mac80211 STA mapping */
for (i = 0; i < ARRAY_SIZE(mvm->fw_id_to_mac_id); i++)
for (i = 0; i < mvm->fw->ucode_capa.num_stations; i++)
RCU_INIT_POINTER(mvm->fw_id_to_mac_id[i], NULL);
/* Add auxiliary station for scanning */
ret = iwl_mvm_add_aux_sta(mvm);
if (ret)
goto error;
if (iwl_fw_lookup_cmd_ver(mvm->fw, LONG_GROUP,
ADD_STA,
0) < 12) {
/*
* Add auxiliary station for scanning.
* Newer versions of this command implies that the fw uses
* internal aux station for all aux activities that don't
* requires a dedicated data queue.
* In old version the aux station uses mac id like other
* station and not lmac id
*/
ret = iwl_mvm_add_aux_sta(mvm, MAC_INDEX_AUX);
if (ret)
goto error;
}
return 0;
error:

Просмотреть файл

@ -663,7 +663,7 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
* allow multicast data frames only as long as the station is
* authorized, i.e., GTK keys are already installed (if needed)
*/
if (ap_sta_id < IWL_MVM_STATION_COUNT) {
if (ap_sta_id < mvm->fw->ucode_capa.num_stations) {
struct ieee80211_sta *sta;
rcu_read_lock();
@ -1597,9 +1597,7 @@ void iwl_mvm_channel_switch_noa_notif(struct iwl_mvm *mvm,
RCU_INIT_POINTER(mvm->csa_vif, NULL);
return;
case NL80211_IFTYPE_STATION:
if (!fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD))
iwl_mvm_csa_client_absent(mvm, vif);
iwl_mvm_csa_client_absent(mvm, vif);
cancel_delayed_work(&mvmvif->csa_work);
ieee80211_chswitch_done(vif, true);
break;

Просмотреть файл

@ -677,8 +677,6 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
NL80211_EXT_FEATURE_SCAN_START_TIME);
wiphy_ext_feature_set(hw->wiphy,
NL80211_EXT_FEATURE_BSS_PARENT_TSF);
wiphy_ext_feature_set(hw->wiphy,
NL80211_EXT_FEATURE_SET_SCAN_DWELL);
}
if (iwl_mvm_is_oce_supported(mvm)) {
@ -826,7 +824,7 @@ static void iwl_mvm_mac_tx(struct ieee80211_hw *hw,
iwl_mvm_vif_from_mac80211(info->control.vif);
u8 ap_sta_id = READ_ONCE(mvmvif->ap_sta_id);
if (ap_sta_id < IWL_MVM_STATION_COUNT) {
if (ap_sta_id < mvm->fw->ucode_capa.num_stations) {
/* mac80211 holds rcu read lock */
sta = rcu_dereference(mvm->fw_id_to_mac_id[ap_sta_id]);
if (IS_ERR_OR_NULL(sta))
@ -1225,13 +1223,8 @@ void __iwl_mvm_mac_stop(struct iwl_mvm *mvm)
/* async_handlers_wk is now blocked */
/*
* The work item could be running or queued if the
* ROC time event stops just as we get here.
*/
flush_work(&mvm->roc_done_wk);
iwl_mvm_rm_aux_sta(mvm);
if (iwl_fw_lookup_cmd_ver(mvm->fw, LONG_GROUP, ADD_STA, 0) < 12)
iwl_mvm_rm_aux_sta(mvm);
iwl_mvm_stop_device(mvm);
@ -1286,6 +1279,12 @@ static void iwl_mvm_mac_stop(struct ieee80211_hw *hw)
cancel_delayed_work_sync(&mvm->cs_tx_unblock_dwork);
cancel_delayed_work_sync(&mvm->scan_timeout_dwork);
/*
* The work item could be running or queued if the
* ROC time event stops just as we get here.
*/
flush_work(&mvm->roc_done_wk);
mutex_lock(&mvm->mutex);
__iwl_mvm_mac_stop(mvm);
mutex_unlock(&mvm->mutex);
@ -1372,9 +1371,7 @@ static int iwl_mvm_post_channel_switch(struct ieee80211_hw *hw,
goto out_unlock;
}
if (!fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD))
iwl_mvm_sta_modify_disable_tx(mvm, mvmsta, false);
iwl_mvm_sta_modify_disable_tx(mvm, mvmsta, false);
iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
@ -1412,10 +1409,14 @@ static void iwl_mvm_abort_channel_switch(struct ieee80211_hw *hw,
IWL_DEBUG_MAC80211(mvm, "Abort CSA on mac %d\n", mvmvif->id);
mutex_lock(&mvm->mutex);
WARN_ON(iwl_mvm_send_cmd_pdu(mvm,
WIDE_ID(MAC_CONF_GROUP,
CHANNEL_SWITCH_TIME_EVENT_CMD),
0, sizeof(cmd), &cmd));
if (!fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD))
iwl_mvm_remove_csa_period(mvm, vif);
else
WARN_ON(iwl_mvm_send_cmd_pdu(mvm,
WIDE_ID(MAC_CONF_GROUP,
CHANNEL_SWITCH_TIME_EVENT_CMD),
0, sizeof(cmd), &cmd));
mutex_unlock(&mvm->mutex);
WARN_ON(iwl_mvm_post_channel_switch(hw, vif));
@ -2886,7 +2887,7 @@ void iwl_mvm_sta_pm_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
struct iwl_mvm_sta *mvmsta;
bool sleeping = (notif->type != IWL_MVM_PM_EVENT_AWAKE);
if (WARN_ON(notif->sta_id >= ARRAY_SIZE(mvm->fw_id_to_mac_id)))
if (WARN_ON(notif->sta_id >= mvm->fw->ucode_capa.num_stations))
return;
rcu_read_lock();
@ -3808,6 +3809,17 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
if (fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_HOTSPOT_SUPPORT)) {
/* Use aux roc framework (HS20) */
if (iwl_fw_lookup_cmd_ver(mvm->fw, LONG_GROUP,
ADD_STA, 0) >= 12) {
u32 lmac_id;
lmac_id = iwl_mvm_get_lmac_id(mvm->fw,
channel->band);
ret = iwl_mvm_add_aux_sta(mvm, lmac_id);
if (WARN(ret,
"Failed to allocate aux station"))
goto out_unlock;
}
ret = iwl_mvm_send_aux_roc_cmd(mvm, channel,
vif, duration);
goto out_unlock;
@ -4686,7 +4698,7 @@ static void iwl_mvm_flush_no_vif(struct iwl_mvm *mvm, u32 queues, bool drop)
}
mutex_lock(&mvm->mutex);
for (i = 0; i < ARRAY_SIZE(mvm->fw_id_to_mac_id); i++) {
for (i = 0; i < mvm->fw->ucode_capa.num_stations; i++) {
struct ieee80211_sta *sta;
sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
@ -4728,7 +4740,7 @@ static void iwl_mvm_mac_flush(struct ieee80211_hw *hw,
mvmvif = iwl_mvm_vif_from_mac80211(vif);
/* flush the AP-station and all TDLS peers */
for (i = 0; i < ARRAY_SIZE(mvm->fw_id_to_mac_id); i++) {
for (i = 0; i < mvm->fw->ucode_capa.num_stations; i++) {
sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
lockdep_is_held(&mvm->mutex));
if (IS_ERR_OR_NULL(sta))
@ -4742,7 +4754,7 @@ static void iwl_mvm_mac_flush(struct ieee80211_hw *hw,
WARN_ON(i != mvmvif->ap_sta_id && !sta->tdls);
if (drop) {
if (iwl_mvm_flush_sta(mvm, mvmsta, false, 0))
if (iwl_mvm_flush_sta(mvm, mvmsta, false))
IWL_ERR(mvm, "flush request fail\n");
} else {
msk |= mvmsta->tfd_queue_msk;

Просмотреть файл

@ -888,7 +888,7 @@ 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];
struct ieee80211_sta __rcu *fw_id_to_mac_id[IWL_MVM_STATION_COUNT_MAX];
u8 rx_ba_sessions;
/* configured by mac80211 */
@ -1205,7 +1205,7 @@ iwl_mvm_sta_from_staid_rcu(struct iwl_mvm *mvm, u8 sta_id)
{
struct ieee80211_sta *sta;
if (sta_id >= ARRAY_SIZE(mvm->fw_id_to_mac_id))
if (sta_id >= mvm->fw->ucode_capa.num_stations)
return NULL;
sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);
@ -1222,7 +1222,7 @@ iwl_mvm_sta_from_staid_protected(struct iwl_mvm *mvm, u8 sta_id)
{
struct ieee80211_sta *sta;
if (sta_id >= ARRAY_SIZE(mvm->fw_id_to_mac_id))
if (sta_id >= mvm->fw->ucode_capa.num_stations)
return NULL;
sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],
@ -1528,7 +1528,7 @@ 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, u32 flags);
int iwl_mvm_flush_sta(struct iwl_mvm *mvm, void *sta, bool internal, u32 flags);
int iwl_mvm_flush_sta(struct iwl_mvm *mvm, void *sta, bool internal);
int iwl_mvm_flush_sta_tids(struct iwl_mvm *mvm, u32 sta_id,
u16 tids, u32 flags);

Просмотреть файл

@ -464,15 +464,6 @@ static const struct iwl_hcmd_names iwl_mvm_data_path_names[] = {
HCMD_NAME(RX_QUEUES_NOTIFICATION),
};
/* Please keep this array *SORTED* by hex value.
* Access is done through binary search
*/
static const struct iwl_hcmd_names iwl_mvm_debug_names[] = {
HCMD_NAME(DBGC_SUSPEND_RESUME),
HCMD_NAME(BUFFER_ALLOCATION),
HCMD_NAME(MFU_ASSERT_DUMP_NTF),
};
/* Please keep this array *SORTED* by hex value.
* Access is done through binary search
*/
@ -626,11 +617,12 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
enum iwl_amsdu_size rb_size_default;
/*
* We use IWL_MVM_STATION_COUNT to check the validity of the station
* We use IWL_MVM_STATION_COUNT_MAX to check the validity of the station
* index all over the driver - check that its value corresponds to the
* array size.
*/
BUILD_BUG_ON(ARRAY_SIZE(mvm->fw_id_to_mac_id) != IWL_MVM_STATION_COUNT);
BUILD_BUG_ON(ARRAY_SIZE(mvm->fw_id_to_mac_id) !=
IWL_MVM_STATION_COUNT_MAX);
/********************************
* 1. Allocating and configuring HW data
@ -769,6 +761,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
trans_cfg.rx_buf_size = rb_size_default;
}
trans->wide_cmd_header = true;
trans_cfg.bc_table_dword =
mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210;
@ -1118,7 +1111,7 @@ static void iwl_mvm_queue_state_change(struct iwl_op_mode *op_mode,
mvm->tvqm_info[hw_queue].sta_id :
mvm->queue_info[hw_queue].ra_sta_id;
if (WARN_ON_ONCE(sta_id >= ARRAY_SIZE(mvm->fw_id_to_mac_id)))
if (WARN_ON_ONCE(sta_id >= mvm->fw->ucode_capa.num_stations))
return;
rcu_read_lock();

Просмотреть файл

@ -194,11 +194,8 @@ static void iwl_mvm_phy_ctxt_cmd_data(struct iwl_mvm *mvm,
struct cfg80211_chan_def *chandef,
u8 chains_static, u8 chains_dynamic)
{
if (chandef->chan->band == NL80211_BAND_2GHZ ||
!iwl_mvm_is_cdb_supported(mvm))
cmd->lmac_id = cpu_to_le32(IWL_LMAC_24G_INDEX);
else
cmd->lmac_id = cpu_to_le32(IWL_LMAC_5G_INDEX);
cmd->lmac_id = cpu_to_le32(iwl_mvm_get_lmac_id(mvm->fw,
chandef->chan->band));
/* Set the channel info data */
iwl_mvm_set_chan_info_chandef(mvm, &cmd->ci, chandef);

Просмотреть файл

@ -468,6 +468,12 @@ void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
.amsdu = iwl_mvm_is_csum_supported(mvm),
};
int ret;
u16 cmd_size = sizeof(cfg_cmd);
/* In old versions of the API the struct is 4 bytes smaller */
if (iwl_fw_lookup_cmd_ver(mvm->fw, DATA_PATH_GROUP,
TLC_MNG_CONFIG_CMD, 0) < 3)
cmd_size -= 4;
memset(lq_sta, 0, offsetof(typeof(*lq_sta), pers));
@ -482,7 +488,7 @@ void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
*/
sta->max_amsdu_len = max_amsdu_len;
ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, CMD_ASYNC, sizeof(cfg_cmd),
ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, CMD_ASYNC, cmd_size,
&cfg_cmd);
if (ret)
IWL_ERR(mvm, "Failed to send rate scale config (%d)\n", ret);

Просмотреть файл

@ -420,7 +420,7 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi,
id >>= RX_MDPU_RES_STATUS_STA_ID_SHIFT;
if (!WARN_ON_ONCE(id >= ARRAY_SIZE(mvm->fw_id_to_mac_id))) {
if (!WARN_ON_ONCE(id >= mvm->fw->ucode_capa.num_stations)) {
sta = rcu_dereference(mvm->fw_id_to_mac_id[id]);
if (IS_ERR(sta))
sta = NULL;
@ -569,7 +569,8 @@ struct iwl_mvm_stat_data {
__le32 flags;
__le32 mac_id;
u8 beacon_filter_average_energy;
void *general;
__le32 *beacon_counter;
u8 *beacon_average_energy;
};
static void iwl_mvm_stat_iterator(void *_data, u8 *mac,
@ -589,23 +590,10 @@ static void iwl_mvm_stat_iterator(void *_data, u8 *mac,
* data copied into the "data" struct, but rather the data from
* the notification directly.
*/
if (iwl_mvm_has_new_rx_stats_api(mvm)) {
struct mvm_statistics_general *general =
data->general;
mvmvif->beacon_stats.num_beacons =
le32_to_cpu(general->beacon_counter[vif_id]);
mvmvif->beacon_stats.avg_signal =
-general->beacon_average_energy[vif_id];
} else {
struct mvm_statistics_general_v8 *general =
data->general;
mvmvif->beacon_stats.num_beacons =
le32_to_cpu(general->beacon_counter[vif_id]);
mvmvif->beacon_stats.avg_signal =
-general->beacon_average_energy[vif_id];
}
mvmvif->beacon_stats.num_beacons =
le32_to_cpu(data->beacon_counter[vif_id]);
mvmvif->beacon_stats.avg_signal =
-data->beacon_average_energy[vif_id];
/* make sure that beacon statistics don't go backwards with TCM
* request to clear statistics
@ -701,18 +689,136 @@ iwl_mvm_rx_stats_check_trigger(struct iwl_mvm *mvm, struct iwl_rx_packet *pkt)
iwl_fw_dbg_collect_trig(&mvm->fwrt, trig, NULL);
}
static void iwl_mvm_update_avg_energy(struct iwl_mvm *mvm,
u8 energy[IWL_MVM_STATION_COUNT_MAX])
{
int i;
if (WARN_ONCE(mvm->fw->ucode_capa.num_stations >
IWL_MVM_STATION_COUNT_MAX,
"Driver and FW station count mismatch %d\n",
mvm->fw->ucode_capa.num_stations))
return;
rcu_read_lock();
for (i = 0; i < mvm->fw->ucode_capa.num_stations; i++) {
struct iwl_mvm_sta *sta;
if (!energy[i])
continue;
sta = iwl_mvm_sta_from_staid_rcu(mvm, i);
if (!sta)
continue;
sta->avg_energy = energy[i];
}
rcu_read_unlock();
}
static void
iwl_mvm_update_tcm_from_stats(struct iwl_mvm *mvm, __le32 *air_time_le,
__le32 *rx_bytes_le)
{
int i;
spin_lock(&mvm->tcm.lock);
for (i = 0; i < NUM_MAC_INDEX_DRIVER; i++) {
struct iwl_mvm_tcm_mac *mdata = &mvm->tcm.data[i];
u32 rx_bytes = le32_to_cpu(rx_bytes_le[i]);
u32 airtime = le32_to_cpu(air_time_le[i]);
mdata->rx.airtime += airtime;
mdata->uapsd_nonagg_detect.rx_bytes += rx_bytes;
if (airtime) {
/* re-init every time to store rate from FW */
ewma_rate_init(&mdata->uapsd_nonagg_detect.rate);
ewma_rate_add(&mdata->uapsd_nonagg_detect.rate,
rx_bytes * 8 / airtime);
}
}
spin_unlock(&mvm->tcm.lock);
}
static void
iwl_mvm_handle_rx_statistics_tlv(struct iwl_mvm *mvm,
struct iwl_rx_packet *pkt)
{
struct iwl_mvm_stat_data data = {
.mvm = mvm,
};
u8 beacon_average_energy[MAC_INDEX_AUX];
u8 average_energy[IWL_MVM_STATION_COUNT_MAX];
struct iwl_statistics_operational_ntfy *stats;
int expected_size;
__le32 flags;
int i;
expected_size = sizeof(*stats);
if (WARN_ONCE(iwl_rx_packet_payload_len(pkt) < expected_size,
"received invalid statistics size (%d)!, expected_size: %d\n",
iwl_rx_packet_payload_len(pkt), expected_size))
return;
stats = (void *)&pkt->data;
if (WARN_ONCE(stats->hdr.type != FW_STATISTICS_OPERATIONAL ||
stats->hdr.version != 1,
"received unsupported hdr type %d, version %d\n",
stats->hdr.type, stats->hdr.version))
return;
flags = stats->flags;
mvm->radio_stats.rx_time = le64_to_cpu(stats->rx_time);
mvm->radio_stats.tx_time = le64_to_cpu(stats->tx_time);
mvm->radio_stats.on_time_rf = le64_to_cpu(stats->on_time_rf);
mvm->radio_stats.on_time_scan = le64_to_cpu(stats->on_time_scan);
iwl_mvm_rx_stats_check_trigger(mvm, pkt);
data.mac_id = stats->mac_id;
data.beacon_filter_average_energy =
le32_to_cpu(stats->beacon_filter_average_energy);
data.flags = flags;
data.beacon_counter = stats->beacon_counter;
for (i = 0; i < ARRAY_SIZE(beacon_average_energy); i++)
beacon_average_energy[i] =
le32_to_cpu(stats->beacon_average_energy[i]);
data.beacon_average_energy = beacon_average_energy;
ieee80211_iterate_active_interfaces(mvm->hw,
IEEE80211_IFACE_ITER_NORMAL,
iwl_mvm_stat_iterator,
&data);
for (i = 0; i < ARRAY_SIZE(average_energy); i++)
average_energy[i] = le32_to_cpu(stats->average_energy[i]);
iwl_mvm_update_avg_energy(mvm, average_energy);
/*
* Don't update in case the statistics are not cleared, since
* we will end up counting twice the same airtime, once in TCM
* request and once in statistics notification.
*/
if (le32_to_cpu(flags) & IWL_STATISTICS_REPLY_FLG_CLEAR)
iwl_mvm_update_tcm_from_stats(mvm, stats->air_time,
stats->rx_bytes);
}
void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm,
struct iwl_rx_packet *pkt)
{
struct iwl_mvm_stat_data data = {
.mvm = mvm,
};
__le32 *bytes, *air_time, flags;
int expected_size;
int i;
u8 *energy;
__le32 *bytes;
__le32 *air_time;
__le32 flags;
/* From ver 14 and up we use TLV statistics format */
if (iwl_fw_lookup_notif_ver(mvm->fw, LONG_GROUP,
STATISTICS_CMD, 0) >= 14)
return iwl_mvm_handle_rx_statistics_tlv(mvm, pkt);
if (!iwl_mvm_has_new_rx_stats_api(mvm)) {
if (iwl_mvm_has_new_rx_api(mvm))
@ -746,8 +852,9 @@ void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm,
mvm->radio_stats.on_time_scan =
le64_to_cpu(stats->general.common.on_time_scan);
data.general = &stats->general;
data.beacon_counter = stats->general.beacon_counter;
data.beacon_average_energy =
stats->general.beacon_average_energy;
flags = stats->flag;
} else {
struct iwl_notif_statistics *stats = (void *)&pkt->data;
@ -767,8 +874,9 @@ void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm,
mvm->radio_stats.on_time_scan =
le64_to_cpu(stats->general.common.on_time_scan);
data.general = &stats->general;
data.beacon_counter = stats->general.beacon_counter;
data.beacon_average_energy =
stats->general.beacon_average_energy;
flags = stats->flag;
}
data.flags = flags;
@ -797,45 +905,16 @@ void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm,
air_time = (void *)&stats->load_stats.air_time;
}
rcu_read_lock();
for (i = 0; i < ARRAY_SIZE(mvm->fw_id_to_mac_id); i++) {
struct iwl_mvm_sta *sta;
if (!energy[i])
continue;
sta = iwl_mvm_sta_from_staid_rcu(mvm, i);
if (!sta)
continue;
sta->avg_energy = energy[i];
}
rcu_read_unlock();
iwl_mvm_update_avg_energy(mvm, energy);
/*
* Don't update in case the statistics are not cleared, since
* we will end up counting twice the same airtime, once in TCM
* request and once in statistics notification.
*/
if (!(le32_to_cpu(flags) & IWL_STATISTICS_REPLY_FLG_CLEAR))
return;
if (le32_to_cpu(flags) & IWL_STATISTICS_REPLY_FLG_CLEAR)
iwl_mvm_update_tcm_from_stats(mvm, air_time, bytes);
spin_lock(&mvm->tcm.lock);
for (i = 0; i < NUM_MAC_INDEX_DRIVER; i++) {
struct iwl_mvm_tcm_mac *mdata = &mvm->tcm.data[i];
u32 airtime = le32_to_cpu(air_time[i]);
u32 rx_bytes = le32_to_cpu(bytes[i]);
mdata->uapsd_nonagg_detect.rx_bytes += rx_bytes;
if (airtime) {
/* re-init every time to store rate from FW */
ewma_rate_init(&mdata->uapsd_nonagg_detect.rate);
ewma_rate_add(&mdata->uapsd_nonagg_detect.rate,
rx_bytes * 8 / airtime);
}
mdata->rx.airtime += airtime;
}
spin_unlock(&mvm->tcm.lock);
}
void iwl_mvm_rx_statistics(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)

Просмотреть файл

@ -1773,7 +1773,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
if (desc->status & cpu_to_le32(IWL_RX_MPDU_STATUS_SRC_STA_FOUND)) {
u8 id = le32_get_bits(desc->status, IWL_RX_MPDU_STATUS_STA_ID);
if (!WARN_ON_ONCE(id >= ARRAY_SIZE(mvm->fw_id_to_mac_id))) {
if (!WARN_ON_ONCE(id >= mvm->fw->ucode_capa.num_stations)) {
sta = rcu_dereference(mvm->fw_id_to_mac_id[id]);
if (IS_ERR(sta))
sta = NULL;

Просмотреть файл

@ -698,14 +698,28 @@ static void iwl_mvm_scan_fill_tx_cmd(struct iwl_mvm *mvm,
tx_cmd[0].rate_n_flags = iwl_mvm_scan_rate_n_flags(mvm,
NL80211_BAND_2GHZ,
no_cck);
tx_cmd[0].sta_id = mvm->aux_sta.sta_id;
if (iwl_fw_lookup_cmd_ver(mvm->fw, LONG_GROUP,
ADD_STA,
0) < 12) {
tx_cmd[0].sta_id = mvm->aux_sta.sta_id;
tx_cmd[1].sta_id = mvm->aux_sta.sta_id;
/*
* Fw doesn't use this sta anymore, pending deprecation via HOST API
* change
*/
} else {
tx_cmd[0].sta_id = 0xff;
tx_cmd[1].sta_id = 0xff;
}
tx_cmd[1].tx_flags = cpu_to_le32(TX_CMD_FLG_SEQ_CTL |
TX_CMD_FLG_BT_DIS);
tx_cmd[1].rate_n_flags = iwl_mvm_scan_rate_n_flags(mvm,
NL80211_BAND_5GHZ,
no_cck);
tx_cmd[1].sta_id = mvm->aux_sta.sta_id;
}
static void
@ -1117,6 +1131,10 @@ static void iwl_mvm_fill_scan_config_v1(struct iwl_mvm *mvm, void *config,
memcpy(&cfg->mac_addr, &mvm->addresses[0].addr, ETH_ALEN);
/* This function should not be called when using ADD_STA ver >=12 */
WARN_ON_ONCE(iwl_fw_lookup_cmd_ver(mvm->fw, LONG_GROUP,
ADD_STA, 0) >= 12);
cfg->bcast_sta_id = mvm->aux_sta.sta_id;
cfg->channel_flags = channel_flags;
@ -1165,6 +1183,10 @@ static void iwl_mvm_fill_scan_config_v2(struct iwl_mvm *mvm, void *config,
memcpy(&cfg->mac_addr, &mvm->addresses[0].addr, ETH_ALEN);
/* This function should not be called when using ADD_STA ver >=12 */
WARN_ON_ONCE(iwl_fw_lookup_cmd_ver(mvm->fw, LONG_GROUP,
ADD_STA, 0) >= 12);
cfg->bcast_sta_id = mvm->aux_sta.sta_id;
cfg->channel_flags = channel_flags;
@ -1278,7 +1300,16 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm)
memset(&cfg, 0, sizeof(cfg));
cfg.bcast_sta_id = mvm->aux_sta.sta_id;
if (iwl_fw_lookup_cmd_ver(mvm->fw, LONG_GROUP,
ADD_STA, 0) < 12)
cfg.bcast_sta_id = mvm->aux_sta.sta_id;
/*
* Fw doesn't use this sta anymore, pending deprecation via HOST API
* change.
*/
else
cfg.bcast_sta_id = 0xff;
cfg.tx_chains = cpu_to_le32(iwl_mvm_get_valid_tx_ant(mvm));
cfg.rx_chains = cpu_to_le32(iwl_mvm_scan_rx_ant(mvm));

Просмотреть файл

@ -85,7 +85,7 @@ static int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm,
int sta_id;
u32 reserved_ids = 0;
BUILD_BUG_ON(IWL_MVM_STATION_COUNT > 32);
BUILD_BUG_ON(IWL_MVM_STATION_COUNT_MAX > 32);
WARN_ON_ONCE(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status));
lockdep_assert_held(&mvm->mutex);
@ -95,7 +95,7 @@ static int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm,
reserved_ids = BIT(0);
/* Don't take rcu_read_lock() since we are protected by mvm->mutex */
for (sta_id = 0; sta_id < ARRAY_SIZE(mvm->fw_id_to_mac_id); sta_id++) {
for (sta_id = 0; sta_id < mvm->fw->ucode_capa.num_stations; sta_id++) {
if (BIT(sta_id) & reserved_ids)
continue;
@ -1538,8 +1538,15 @@ static int iwl_mvm_add_int_sta_common(struct iwl_mvm *mvm,
memset(&cmd, 0, sizeof(cmd));
cmd.sta_id = sta->sta_id;
cmd.mac_id_n_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mac_id,
color));
if (iwl_fw_lookup_cmd_ver(mvm->fw, LONG_GROUP, ADD_STA,
0) >= 12 &&
sta->type == IWL_STA_AUX_ACTIVITY)
cmd.mac_id_n_color = cpu_to_le32(mac_id);
else
cmd.mac_id_n_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mac_id,
color));
if (fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_STA_TYPE))
cmd.station_type = sta->type;
@ -1856,7 +1863,7 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
return ret;
/* flush its queues here since we are freeing mvm_sta */
ret = iwl_mvm_flush_sta(mvm, mvm_sta, false, 0);
ret = iwl_mvm_flush_sta(mvm, mvm_sta, false);
if (ret)
return ret;
if (iwl_mvm_has_new_tx_api(mvm)) {
@ -2032,7 +2039,7 @@ static int iwl_mvm_add_int_sta_with_queue(struct iwl_mvm *mvm, int macidx,
return 0;
}
int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm)
int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm, u32 lmac_id)
{
int ret;
@ -2045,7 +2052,11 @@ int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm)
if (ret)
return ret;
ret = iwl_mvm_add_int_sta_with_queue(mvm, MAC_INDEX_AUX, 0, NULL,
/*
* In CDB NICs we need to specify which lmac to use for aux activity
* using the mac_id argument place to send lmac_id to the function
*/
ret = iwl_mvm_add_int_sta_with_queue(mvm, lmac_id, 0, NULL,
&mvm->aux_sta, &mvm->aux_queue,
IWL_MVM_TX_FIFO_MCAST);
if (ret) {
@ -2188,7 +2199,7 @@ static void iwl_mvm_free_bcast_sta_queues(struct iwl_mvm *mvm,
lockdep_assert_held(&mvm->mutex);
iwl_mvm_flush_sta(mvm, &mvmvif->bcast_sta, true, 0);
iwl_mvm_flush_sta(mvm, &mvmvif->bcast_sta, true);
switch (vif->type) {
case NL80211_IFTYPE_AP:
@ -2437,7 +2448,7 @@ int iwl_mvm_rm_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
lockdep_assert_held(&mvm->mutex);
iwl_mvm_flush_sta(mvm, &mvmvif->mcast_sta, true, 0);
iwl_mvm_flush_sta(mvm, &mvmvif->mcast_sta, true);
iwl_mvm_disable_txq(mvm, NULL, mvmvif->cab_queue, 0, 0);
@ -3760,7 +3771,7 @@ void iwl_mvm_rx_eosp_notif(struct iwl_mvm *mvm,
struct ieee80211_sta *sta;
u32 sta_id = le32_to_cpu(notif->sta_id);
if (WARN_ON_ONCE(sta_id >= IWL_MVM_STATION_COUNT))
if (WARN_ON_ONCE(sta_id >= mvm->fw->ucode_capa.num_stations))
return;
rcu_read_lock();
@ -3843,7 +3854,7 @@ void iwl_mvm_modify_all_sta_disable_tx(struct iwl_mvm *mvm,
lockdep_assert_held(&mvm->mutex);
/* Block/unblock all the stations of the given mvmvif */
for (i = 0; i < ARRAY_SIZE(mvm->fw_id_to_mac_id); i++) {
for (i = 0; i < mvm->fw->ucode_capa.num_stations; i++) {
sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
lockdep_is_held(&mvm->mutex));
if (IS_ERR_OR_NULL(sta))

Просмотреть файл

@ -70,7 +70,7 @@
#include <linux/wait.h>
#include "iwl-trans.h" /* for IWL_MAX_TID_COUNT */
#include "fw-api.h" /* IWL_MVM_STATION_COUNT */
#include "fw-api.h" /* IWL_MVM_STATION_COUNT_MAX */
#include "rs.h"
struct iwl_mvm;
@ -540,7 +540,7 @@ int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
int iwl_mvm_sta_tx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
int tid, u8 queue, bool start);
int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm);
int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm, u32 lmac_id);
int iwl_mvm_rm_aux_sta(struct iwl_mvm *mvm);
int iwl_mvm_alloc_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
@ -582,5 +582,4 @@ void iwl_mvm_add_new_dqa_stream_wk(struct work_struct *wk);
int iwl_mvm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct iwl_mvm_int_sta *sta, u8 *addr, u32 cipher,
u8 *key, u32 key_len);
#endif /* __sta_h__ */

Просмотреть файл

@ -7,7 +7,7 @@
*
* Copyright(c) 2014 Intel Mobile Communications GmbH
* Copyright(c) 2017 Intel Deutschland GmbH
* Copyright(C) 2018 - 2019 Intel Corporation
* Copyright(C) 2018 - 2020 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@ -29,7 +29,7 @@
*
* Copyright(c) 2014 Intel Mobile Communications GmbH
* Copyright(c) 2017 Intel Deutschland GmbH
* Copyright(C) 2018 - 2019 Intel Corporation
* Copyright(C) 2018 - 2020 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -77,7 +77,7 @@ void iwl_mvm_teardown_tdls_peers(struct iwl_mvm *mvm)
lockdep_assert_held(&mvm->mutex);
for (i = 0; i < ARRAY_SIZE(mvm->fw_id_to_mac_id); i++) {
for (i = 0; i < mvm->fw->ucode_capa.num_stations; i++) {
sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
lockdep_is_held(&mvm->mutex));
if (!sta || IS_ERR(sta) || !sta->tdls)
@ -100,7 +100,7 @@ int iwl_mvm_tdls_sta_count(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
lockdep_assert_held(&mvm->mutex);
for (i = 0; i < ARRAY_SIZE(mvm->fw_id_to_mac_id); i++) {
for (i = 0; i < mvm->fw->ucode_capa.num_stations; i++) {
sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
lockdep_is_held(&mvm->mutex));
if (!sta || IS_ERR(sta) || !sta->tdls)
@ -144,7 +144,7 @@ static void iwl_mvm_tdls_config(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
/* populate TDLS peer data */
cnt = 0;
for (i = 0; i < ARRAY_SIZE(mvm->fw_id_to_mac_id); i++) {
for (i = 0; i < mvm->fw->ucode_capa.num_stations; i++) {
sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
lockdep_is_held(&mvm->mutex));
if (IS_ERR_OR_NULL(sta) || !sta->tdls)
@ -273,7 +273,7 @@ void iwl_mvm_rx_tdls_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
return;
}
if (WARN_ON(sta_id >= IWL_MVM_STATION_COUNT))
if (WARN_ON(sta_id >= mvm->fw->ucode_capa.num_stations))
return;
sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],

Просмотреть файл

@ -5,10 +5,9 @@
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2017 Intel Deutschland GmbH
* Copyright(c) 2018 - 2019 Intel Corporation
* Copyright(c) 2012 - 2014, 2018 - 2020 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@ -28,10 +27,9 @@
*
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2017 Intel Deutschland GmbH
* Copyright(c) 2018 - 2019 Intel Corporation
* Copyright(c) 2012 - 2014, 2018 - 2020 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -116,14 +114,9 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk)
* event finishes or is canceled, so that frames queued for it
* won't get stuck on the queue and be transmitted in the next
* time event.
* We have to send the command asynchronously since this cannot
* be under the mutex for locking reasons, but that's not an
* issue as it will have to complete before the next command is
* executed, and a new time event means a new command.
*/
iwl_mvm_flush_sta(mvm, &mvm->aux_sta, true, CMD_ASYNC);
/* Do the same for the P2P device queue (STA) */
mutex_lock(&mvm->mutex);
if (test_and_clear_bit(IWL_MVM_STATUS_NEED_FLUSH_P2P, &mvm->status)) {
struct iwl_mvm_vif *mvmvif;
@ -136,10 +129,20 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk)
if (!WARN_ON(!mvm->p2p_device_vif)) {
mvmvif = iwl_mvm_vif_from_mac80211(mvm->p2p_device_vif);
iwl_mvm_flush_sta(mvm, &mvmvif->bcast_sta, true,
CMD_ASYNC);
iwl_mvm_flush_sta(mvm, &mvmvif->bcast_sta, true);
}
} else {
/* do the same in case of hot spot 2.0 */
iwl_mvm_flush_sta(mvm, &mvm->aux_sta, true);
/* In newer version of this command an aux station is added only
* in cases of dedicated tx queue and need to be removed in end
* of use */
if (iwl_fw_lookup_cmd_ver(mvm->fw, LONG_GROUP,
ADD_STA, 0) >= 12)
iwl_mvm_rm_aux_sta(mvm);
}
mutex_unlock(&mvm->mutex);
}
static void iwl_mvm_roc_finished(struct iwl_mvm *mvm)
@ -1013,6 +1016,28 @@ void iwl_mvm_stop_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
iwl_mvm_roc_finished(mvm);
}
void iwl_mvm_remove_csa_period(struct iwl_mvm *mvm,
struct ieee80211_vif *vif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data;
u32 id;
lockdep_assert_held(&mvm->mutex);
if (!te_data->running)
return;
spin_lock_bh(&mvm->time_event_lock);
id = te_data->id;
spin_unlock_bh(&mvm->time_event_lock);
if (id != TE_CHANNEL_SWITCH_PERIOD)
return;
iwl_mvm_remove_time_event(mvm, mvmvif, te_data);
}
int iwl_mvm_schedule_csa_period(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
u32 duration, u32 apply_time)

Просмотреть файл

@ -7,7 +7,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright (C) 2019 Intel Corporation
* Copyright (C) 2019 - 2020 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@ -29,7 +29,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright (C) 2019 Intel Corporation
* Copyright (C) 2019 - 2020 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -216,6 +216,9 @@ void iwl_mvm_te_clear_data(struct iwl_mvm *mvm,
void iwl_mvm_cleanup_roc_te(struct iwl_mvm *mvm);
void iwl_mvm_roc_done_wk(struct work_struct *wk);
void iwl_mvm_remove_csa_period(struct iwl_mvm *mvm,
struct ieee80211_vif *vif);
/**
* iwl_mvm_schedule_csa_period - request channel switch absence period
* @mvm: the mvm component

Просмотреть файл

@ -349,6 +349,8 @@ static void check_exit_ctkill(struct work_struct *work)
duration = tt->params.ct_kill_duration;
flush_work(&mvm->roc_done_wk);
mutex_lock(&mvm->mutex);
if (__iwl_mvm_mac_start(mvm))
@ -399,7 +401,7 @@ static void iwl_mvm_tt_tx_protection(struct iwl_mvm *mvm, bool enable)
struct iwl_mvm_sta *mvmsta;
int i, err;
for (i = 0; i < ARRAY_SIZE(mvm->fw_id_to_mac_id); i++) {
for (i = 0; i < mvm->fw->ucode_capa.num_stations; i++) {
mvmsta = iwl_mvm_sta_from_staid_protected(mvm, i);
if (!mvmsta)
continue;

Просмотреть файл

@ -793,11 +793,7 @@ unsigned int iwl_mvm_max_amsdu_size(struct iwl_mvm *mvm,
enum nl80211_band band = mvmsta->vif->bss_conf.chandef.chan->band;
u8 ac = tid_to_mac80211_ac[tid];
unsigned int txf;
int lmac = IWL_LMAC_24G_INDEX;
if (iwl_mvm_is_cdb_supported(mvm) &&
band == NL80211_BAND_5GHZ)
lmac = IWL_LMAC_5G_INDEX;
int lmac = iwl_mvm_get_lmac_id(mvm->fw, band);
/* For HE redirect to trigger based fifos */
if (sta->he_cap.has_he && !WARN_ON(!iwl_mvm_has_new_tx_api(mvm)))
@ -1371,7 +1367,7 @@ void iwl_mvm_hwrate_to_tx_rate(u32 rate_n_flags,
}
}
/**
/*
* translate ucode response to mac80211 tx status control values
*/
static void iwl_mvm_hwrate_to_tx_status(u32 rate_n_flags,
@ -1413,7 +1409,7 @@ static void iwl_mvm_tx_status_check_trigger(struct iwl_mvm *mvm,
}
}
/**
/*
* iwl_mvm_get_scd_ssn - returns the SSN of the SCD
* @tx_resp: the Tx response from the fw (agg or non-agg)
*
@ -1774,7 +1770,7 @@ static void iwl_mvm_tx_reclaim(struct iwl_mvm *mvm, int sta_id, int tid,
struct sk_buff *skb;
int freed;
if (WARN_ONCE(sta_id >= IWL_MVM_STATION_COUNT ||
if (WARN_ONCE(sta_id >= mvm->fw->ucode_capa.num_stations ||
tid > IWL_MAX_TID_COUNT,
"sta_id %d tid %d", sta_id, tid))
return;
@ -2059,7 +2055,7 @@ int iwl_mvm_flush_sta_tids(struct iwl_mvm *mvm, u32 sta_id,
return ret;
}
int iwl_mvm_flush_sta(struct iwl_mvm *mvm, void *sta, bool internal, u32 flags)
int iwl_mvm_flush_sta(struct iwl_mvm *mvm, void *sta, bool internal)
{
struct iwl_mvm_int_sta *int_sta = sta;
struct iwl_mvm_sta *mvm_sta = sta;
@ -2068,12 +2064,10 @@ int iwl_mvm_flush_sta(struct iwl_mvm *mvm, void *sta, bool internal, u32 flags)
offsetof(struct iwl_mvm_sta, sta_id));
if (iwl_mvm_has_new_tx_api(mvm))
return iwl_mvm_flush_sta_tids(mvm, mvm_sta->sta_id,
0xffff, flags);
return iwl_mvm_flush_sta_tids(mvm, mvm_sta->sta_id, 0xffff, 0);
if (internal)
return iwl_mvm_flush_tx_path(mvm, int_sta->tfd_queue_msk,
flags);
return iwl_mvm_flush_tx_path(mvm, int_sta->tfd_queue_msk, 0);
return iwl_mvm_flush_tx_path(mvm, mvm_sta->tfd_queue_msk, flags);
return iwl_mvm_flush_tx_path(mvm, mvm_sta->tfd_queue_msk, 0);
}

Просмотреть файл

@ -620,7 +620,8 @@ int iwl_mvm_reconfig_scd(struct iwl_mvm *mvm, int queue, int fifo, int sta_id,
/**
* iwl_mvm_send_lq_cmd() - Send link quality command
* @sync: This command can be sent synchronously.
* @mvm: Driver data.
* @lq: Link quality command to send.
*
* The link quality command is sent as the last step of station creation.
* This is the special case in which init is set and we call a callback in
@ -645,8 +646,10 @@ int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq)
/**
* iwl_mvm_update_smps - Get a request to change the SMPS mode
* @mvm: Driver data.
* @vif: Pointer to the ieee80211_vif structure
* @req_type: The part of the driver who call for a change.
* @smps_requests: The request to change the SMPS mode.
* @smps_request: The request to change the SMPS mode.
*
* Get a requst to change the SMPS mode,
* and change it according to all other requests in the driver.

Просмотреть файл

@ -301,3 +301,30 @@ void iwl_pcie_ctxt_info_gen3_free(struct iwl_trans *trans)
trans_pcie->prph_info_dma_addr = 0;
trans_pcie->prph_info = NULL;
}
int iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans,
const void *data, u32 len)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl =
&trans_pcie->prph_scratch->ctrl_cfg;
int ret;
if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
return 0;
ret = iwl_pcie_ctxt_info_alloc_dma(trans, data, len,
&trans_pcie->pnvm_dram);
if (ret < 0) {
IWL_DEBUG_FW(trans, "Failed to allocate PNVM DMA %d.\n",
ret);
return ret;
}
prph_sc_ctrl->pnvm_cfg.pnvm_base_addr =
cpu_to_le64(trans_pcie->pnvm_dram.physical);
prph_sc_ctrl->pnvm_cfg.pnvm_size =
cpu_to_le32(trans_pcie->pnvm_dram.size);
return 0;
}

Просмотреть файл

@ -93,17 +93,17 @@ static void *iwl_pcie_ctxt_info_dma_alloc_coherent(struct iwl_trans *trans,
return _iwl_pcie_ctxt_info_dma_alloc_coherent(trans, size, phys, 0);
}
static int iwl_pcie_ctxt_info_alloc_dma(struct iwl_trans *trans,
const struct fw_desc *sec,
struct iwl_dram_data *dram)
int iwl_pcie_ctxt_info_alloc_dma(struct iwl_trans *trans,
const void *data, u32 len,
struct iwl_dram_data *dram)
{
dram->block = iwl_pcie_ctxt_info_dma_alloc_coherent(trans, sec->len,
dram->block = iwl_pcie_ctxt_info_dma_alloc_coherent(trans, len,
&dram->physical);
if (!dram->block)
return -ENOMEM;
dram->size = sec->len;
memcpy(dram->block, sec->data, sec->len);
dram->size = len;
memcpy(dram->block, data, len);
return 0;
}
@ -156,7 +156,8 @@ int iwl_pcie_init_fw_sec(struct iwl_trans *trans,
/* initialize lmac sections */
for (i = 0; i < lmac_cnt; i++) {
ret = iwl_pcie_ctxt_info_alloc_dma(trans, &fw->sec[i],
ret = iwl_pcie_ctxt_info_alloc_dma(trans, fw->sec[i].data,
fw->sec[i].len,
&dram->fw[dram->fw_cnt]);
if (ret)
return ret;
@ -169,7 +170,8 @@ int iwl_pcie_init_fw_sec(struct iwl_trans *trans,
for (i = 0; i < umac_cnt; i++) {
/* access FW with +1 to make up for lmac separator */
ret = iwl_pcie_ctxt_info_alloc_dma(trans,
&fw->sec[dram->fw_cnt + 1],
fw->sec[dram->fw_cnt + 1].data,
fw->sec[dram->fw_cnt + 1].len,
&dram->fw[dram->fw_cnt]);
if (ret)
return ret;
@ -192,7 +194,8 @@ int iwl_pcie_init_fw_sec(struct iwl_trans *trans,
/* access FW with +2 to make up for lmac & umac separators */
int fw_idx = dram->fw_cnt + i + 2;
ret = iwl_pcie_ctxt_info_alloc_dma(trans, &fw->sec[fw_idx],
ret = iwl_pcie_ctxt_info_alloc_dma(trans, fw->sec[fw_idx].data,
fw->sec[fw_idx].len,
&dram->paging[i]);
if (ret)
return ret;

Просмотреть файл

@ -512,9 +512,9 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
/* 9000 Series */
{IWL_PCI_DEVICE(0x2526, PCI_ANY_ID, iwl9000_trans_cfg)},
{IWL_PCI_DEVICE(0x271B, PCI_ANY_ID, iwl9560_trans_cfg)},
{IWL_PCI_DEVICE(0x271C, PCI_ANY_ID, iwl9560_trans_cfg)},
{IWL_PCI_DEVICE(0x30DC, PCI_ANY_ID, iwl9560_trans_cfg)},
{IWL_PCI_DEVICE(0x271B, PCI_ANY_ID, iwl9000_trans_cfg)},
{IWL_PCI_DEVICE(0x271C, PCI_ANY_ID, iwl9000_trans_cfg)},
{IWL_PCI_DEVICE(0x30DC, PCI_ANY_ID, iwl9560_long_latency_trans_cfg)},
{IWL_PCI_DEVICE(0x31DC, PCI_ANY_ID, iwl9560_shared_clk_trans_cfg)},
{IWL_PCI_DEVICE(0x9DF0, PCI_ANY_ID, iwl9560_trans_cfg)},
{IWL_PCI_DEVICE(0xA370, PCI_ANY_ID, iwl9560_trans_cfg)},
@ -632,6 +632,7 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
IWL_DEV_INFO(0xA0F0, 0x4070, iwl_ax201_cfg_qu_hr, NULL),
IWL_DEV_INFO(0x02F0, 0x0070, iwl_ax201_cfg_quz_hr, NULL),
IWL_DEV_INFO(0x02F0, 0x0074, iwl_ax201_cfg_quz_hr, NULL),
IWL_DEV_INFO(0x02F0, 0x6074, iwl_ax201_cfg_quz_hr, NULL),
IWL_DEV_INFO(0x02F0, 0x0078, iwl_ax201_cfg_quz_hr, NULL),
IWL_DEV_INFO(0x02F0, 0x007C, iwl_ax201_cfg_quz_hr, NULL),
IWL_DEV_INFO(0x02F0, 0x0310, iwl_ax201_cfg_quz_hr, NULL),

Просмотреть файл

@ -339,6 +339,7 @@ struct cont_rec {
* @trans: pointer to the generic transport area
* @scd_base_addr: scheduler sram base address in SRAM
* @kw: keep warm address
* @pnvm_dram: DRAM area that contains the PNVM data
* @pci_dev: basic pci-network driver stuff
* @hw_base: pci hardware address support
* @ucode_write_complete: indicates that the ucode has been copied.
@ -410,6 +411,8 @@ struct iwl_trans_pcie {
u32 scd_base_addr;
struct iwl_dma_ptr kw;
struct iwl_dram_data pnvm_dram;
struct iwl_txq *txq_memory;
/* PCI bus related data */

Просмотреть файл

@ -81,6 +81,7 @@
#include "fw/api/tx.h"
#include "internal.h"
#include "iwl-fh.h"
#include "iwl-context-info-gen3.h"
/* extended range in FW SRAM */
#define IWL_FW_MEM_EXTENDED_START 0x40000
@ -1979,6 +1980,11 @@ void iwl_trans_pcie_free(struct iwl_trans *trans)
iwl_pcie_free_fw_monitor(trans);
if (trans_pcie->pnvm_dram.size)
dma_free_coherent(trans->dev, trans_pcie->pnvm_dram.size,
trans_pcie->pnvm_dram.block,
trans_pcie->pnvm_dram.physical);
mutex_destroy(&trans_pcie->mutex);
iwl_trans_free(trans);
}
@ -3451,6 +3457,7 @@ static const struct iwl_trans_ops trans_ops_pcie_gen2 = {
.txq_free = iwl_txq_dyn_free,
.wait_txq_empty = iwl_trans_pcie_wait_txq_empty,
.rxq_dma_data = iwl_trans_pcie_rxq_dma_data,
.set_pnvm = iwl_trans_pcie_ctx_info_gen3_set_pnvm,
#ifdef CONFIG_IWLWIFI_DEBUGFS
.debugfs_cleanup = iwl_trans_pcie_debugfs_cleanup,
#endif

Просмотреть файл

@ -1180,6 +1180,11 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
const u8 *cmddata[IWL_MAX_CMD_TBS_PER_TFD];
u16 cmdlen[IWL_MAX_CMD_TBS_PER_TFD];
if (WARN(!trans->wide_cmd_header &&
group_id > IWL_ALWAYS_LONG_GROUP,
"unsupported wide command %#x\n", cmd->id))
return -EINVAL;
if (group_id != 0) {
copy_size = sizeof(struct iwl_cmd_header_wide);
cmd_size = sizeof(struct iwl_cmd_header_wide);

Просмотреть файл

@ -2403,6 +2403,8 @@ error:
kfree(card->mpa_rx.buf);
card->mpa_tx.buf_size = 0;
card->mpa_rx.buf_size = 0;
card->mpa_tx.buf = NULL;
card->mpa_rx.buf = NULL;
}
return ret;

Просмотреть файл

@ -1905,7 +1905,7 @@ static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw)
* index diff of legacy to HT OFDM rate. */
tempval = hwinfo[EEPROM_RFIND_POWERDIFF] & 0xff;
rtlefuse->eeprom_txpowerdiff = tempval;
rtlefuse->legacy_httxpowerdiff =
rtlefuse->legacy_ht_txpowerdiff =
rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][0];
RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,

Просмотреть файл

@ -25,7 +25,7 @@ static void _rtl92s_get_powerbase(struct ieee80211_hw *hw, u8 *p_pwrlevel,
/* We only care about the path A for legacy. */
if (rtlefuse->eeprom_version < 2) {
pwrbase0 = pwrlevel[0] + (rtlefuse->legacy_httxpowerdiff & 0xf);
pwrbase0 = pwrlevel[0] + (rtlefuse->legacy_ht_txpowerdiff & 0xf);
} else {
legacy_pwrdiff = rtlefuse->txpwr_legacyhtdiff
[RF90_PATH_A][chnl - 1];

Просмотреть файл

@ -1966,7 +1966,6 @@ struct rtl_efuse {
u8 txpwr_safetyflag; /* Band edge enable flag */
u16 eeprom_txpowerdiff;
u8 legacy_httxpowerdiff; /* Legacy to HT rate power diff */
u8 antenna_txpwdiff[3];
u8 eeprom_regulatory;