mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-28 11:18:45 +07:00
* More work on the RX path for the 9000 device series
* Some more dynamic queue allocation work * A few bugfixes and other improvements -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJXds8vAAoJEKFHnKIaPMX6GNIQAILXaocLMp7DEdzGcw4FLeub d7EjnuM7NN/daqxdPJFQv1Q044CNt57L1cRIlmoMQQB2jQuHgRPFVWtz4j/2nIl0 h+V6WhBCAgsSSiooRUR4Ck+9Chb3DJBBm85rt1lGXwa0S4QTl21bH2n8zfwp80A4 tXIeTlaxDlnAFmDcDc+QEEjj6ph3Bfu9rgGM3cqHFfYwLfGU6Ny9lnr4HMWOE2JW QjCKEgF+6eQpzFigHdHIfvjnkSay/LiZ0jNjPzn4Svn5yUHWYx/ldFq72Veyg4L7 ceEQpDWGoEdMMgYue2igf8dFx//9OuQXNdoBCIYs+RY5sGn3gHjRu3GhTiBD5pUN nLSyGOgwqaXNyF4fumI4CgJwjQmEpa7RCsY+59IAEl/tYZh9kNNrmEfl99k2YruT 5IZeF3D6qjZZs89upxId03bLyEZ4oSLGTbxOq0xOt7GbaE7BIWBRALHe8mNseV+P 4Y3AVks98W1q4iyERpBIMhAWptFt/Tcwt2jGDrFzJHCDBFI5RBLw9NdzEdjxOxsO GRits9CTARg5R20BSoqcTs1vBC9ymvCvuLcQooRDdLJWbjXURn43rLQ9PTao+lzN 8OJbMz1OzaxIa0QTe3RVPuoTudjlmrAfmAaK2O2LrydSf/7W9g+OZOgn64Z2S5uj Y5IdAN9cpRHYGbFnbsuQ =XZrY -----END PGP SIGNATURE----- Merge tag 'iwlwifi-next-for-kalle-2016-07-01' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next * More work on the RX path for the 9000 device series * Some more dynamic queue allocation work * A few bugfixes and other improvements
This commit is contained in:
commit
df42919519
@ -1317,6 +1317,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
|
||||
trans_cfg.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds);
|
||||
|
||||
switch (iwlwifi_mod_params.amsdu_size) {
|
||||
case IWL_AMSDU_DEF:
|
||||
case IWL_AMSDU_4K:
|
||||
trans_cfg.rx_buf_size = IWL_AMSDU_4K;
|
||||
break;
|
||||
|
@ -178,6 +178,7 @@ const struct iwl_cfg iwl5165_2ac_cfg = {
|
||||
.nvm_ver = IWL9000_NVM_VERSION,
|
||||
.nvm_calib_ver = IWL9000_TX_POWER_VERSION,
|
||||
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
|
||||
.integrated = true,
|
||||
};
|
||||
|
||||
MODULE_FIRMWARE(IWL9000_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX));
|
||||
|
@ -319,6 +319,7 @@ struct iwl_pwr_tx_backoff {
|
||||
* @mq_rx_supported: multi-queue rx support
|
||||
* @vht_mu_mimo_supported: VHT MU-MIMO support
|
||||
* @rf_id: need to read rf_id to determine the firmware image
|
||||
* @integrated: discrete or integrated
|
||||
*
|
||||
* We enable the driver to be backward compatible wrt. hardware features.
|
||||
* API differences in uCode shouldn't be handled here but through TLVs
|
||||
@ -362,7 +363,8 @@ struct iwl_cfg {
|
||||
apmg_not_supported:1,
|
||||
mq_rx_supported:1,
|
||||
vht_mu_mimo_supported:1,
|
||||
rf_id:1;
|
||||
rf_id:1,
|
||||
integrated:1;
|
||||
u8 valid_tx_ant;
|
||||
u8 valid_rx_ant;
|
||||
u8 non_shared_ant;
|
||||
|
@ -145,8 +145,10 @@
|
||||
|
||||
#define CSR_LED_REG (CSR_BASE+0x094)
|
||||
#define CSR_DRAM_INT_TBL_REG (CSR_BASE+0x0A0)
|
||||
#define CSR_MAC_SHADOW_REG_CTRL (CSR_BASE+0x0A8) /* 6000 and up */
|
||||
|
||||
#define CSR_MAC_SHADOW_REG_CTRL (CSR_BASE + 0x0A8) /* 6000 and up */
|
||||
#define CSR_MAC_SHADOW_REG_CTRL_RX_WAKE BIT(20)
|
||||
#define CSR_MAC_SHADOW_REG_CTL2 (CSR_BASE + 0x0AC)
|
||||
#define CSR_MAC_SHADOW_REG_CTL2_RX_WAKE 0xFFFF
|
||||
|
||||
/* GIO Chicken Bits (PCI Express bus link power management) */
|
||||
#define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100)
|
||||
|
@ -1658,7 +1658,8 @@ MODULE_PARM_DESC(11n_disable,
|
||||
"disable 11n functionality, bitmap: 1: full, 2: disable agg TX, 4: disable agg RX, 8 enable agg TX");
|
||||
module_param_named(amsdu_size, iwlwifi_mod_params.amsdu_size,
|
||||
int, S_IRUGO);
|
||||
MODULE_PARM_DESC(amsdu_size, "amsdu size 0:4K 1:8K 2:12K (default 0)");
|
||||
MODULE_PARM_DESC(amsdu_size,
|
||||
"amsdu size 0: 12K for multi Rx queue devices, 4K for other devices 1:4K 2:8K 3:12K (default 0)");
|
||||
module_param_named(fw_restart, iwlwifi_mod_params.restart_fw, bool, S_IRUGO);
|
||||
MODULE_PARM_DESC(fw_restart, "restart firmware in case of error (default true)");
|
||||
|
||||
|
@ -766,7 +766,9 @@ void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg,
|
||||
if (cfg->ht_params->ldpc)
|
||||
ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING;
|
||||
|
||||
if (iwlwifi_mod_params.amsdu_size >= IWL_AMSDU_8K)
|
||||
if ((cfg->mq_rx_supported &&
|
||||
iwlwifi_mod_params.amsdu_size != IWL_AMSDU_4K) ||
|
||||
iwlwifi_mod_params.amsdu_size >= IWL_AMSDU_8K)
|
||||
ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU;
|
||||
|
||||
ht_info->ampdu_factor = cfg->max_ht_ampdu_exponent;
|
||||
|
@ -384,7 +384,9 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(unsigned int chnl)
|
||||
#define RFH_GEN_CFG 0xA09800
|
||||
#define RFH_GEN_CFG_SERVICE_DMA_SNOOP BIT(0)
|
||||
#define RFH_GEN_CFG_RFH_DMA_SNOOP BIT(1)
|
||||
#define RFH_GEN_CFG_RB_CHUNK_SIZE BIT(4) /* 0 - 64B, 1- 128B */
|
||||
#define RFH_GEN_CFG_RB_CHUNK_SIZE_POS 4
|
||||
#define RFH_GEN_CFG_RB_CHUNK_SIZE_128 1
|
||||
#define RFH_GEN_CFG_RB_CHUNK_SIZE_64 0
|
||||
#define RFH_GEN_CFG_DEFAULT_RXQ_NUM_MASK 0xF00
|
||||
#define RFH_GEN_CFG_DEFAULT_RXQ_NUM_POS 8
|
||||
|
||||
|
@ -301,7 +301,8 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_capa_t;
|
||||
* @IWL_UCODE_TLV_CAPA_DC2DC_SUPPORT: supports DC2DC Command
|
||||
* @IWL_UCODE_TLV_CAPA_CSUM_SUPPORT: supports TCP Checksum Offload
|
||||
* @IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS: support radio and beacon statistics
|
||||
* @IWL_UCODE_TLV_CAPA_P2P_STANDALONE_UAPSD: support p2p standalone U-APSD
|
||||
* @IWL_UCODE_TLV_CAPA_P2P_SCM_UAPSD: supports U-APSD on p2p interface when it
|
||||
* is standalone or with a BSS station interface in the same binding.
|
||||
* @IWL_UCODE_TLV_CAPA_BT_COEX_PLCR: enabled BT Coex packet level co-running
|
||||
* @IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC: ucode supports LAR updates with different
|
||||
* sources for the MCC. This TLV bit is a future replacement to
|
||||
@ -312,6 +313,9 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_capa_t;
|
||||
* @IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE: extended DTS measurement
|
||||
* @IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS: supports short PM timeouts
|
||||
* @IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT: supports bt-coex Multi-priority LUT
|
||||
* @IWL_UCODE_TLV_CAPA_CSA_AND_TBTT_OFFLOAD: the firmware supports CSA
|
||||
* countdown offloading. Beacon notifications are not sent to the host.
|
||||
* The fw also offloads TBTT alignment.
|
||||
* @IWL_UCODE_TLV_CAPA_BEACON_ANT_SELECTION: firmware will decide on what
|
||||
* antenna the beacon should be transmitted
|
||||
* @IWL_UCODE_TLV_CAPA_BEACON_STORING: firmware will store the latest beacon
|
||||
@ -347,7 +351,7 @@ enum iwl_ucode_tlv_capa {
|
||||
IWL_UCODE_TLV_CAPA_DC2DC_CONFIG_SUPPORT = (__force iwl_ucode_tlv_capa_t)19,
|
||||
IWL_UCODE_TLV_CAPA_CSUM_SUPPORT = (__force iwl_ucode_tlv_capa_t)21,
|
||||
IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS = (__force iwl_ucode_tlv_capa_t)22,
|
||||
IWL_UCODE_TLV_CAPA_P2P_STANDALONE_UAPSD = (__force iwl_ucode_tlv_capa_t)26,
|
||||
IWL_UCODE_TLV_CAPA_P2P_SCM_UAPSD = (__force iwl_ucode_tlv_capa_t)26,
|
||||
IWL_UCODE_TLV_CAPA_BT_COEX_PLCR = (__force iwl_ucode_tlv_capa_t)28,
|
||||
IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC = (__force iwl_ucode_tlv_capa_t)29,
|
||||
IWL_UCODE_TLV_CAPA_BT_COEX_RRC = (__force iwl_ucode_tlv_capa_t)30,
|
||||
@ -356,6 +360,7 @@ enum iwl_ucode_tlv_capa {
|
||||
IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS = (__force iwl_ucode_tlv_capa_t)65,
|
||||
IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT = (__force iwl_ucode_tlv_capa_t)67,
|
||||
IWL_UCODE_TLV_CAPA_MULTI_QUEUE_RX_SUPPORT = (__force iwl_ucode_tlv_capa_t)68,
|
||||
IWL_UCODE_TLV_CAPA_CSA_AND_TBTT_OFFLOAD = (__force iwl_ucode_tlv_capa_t)70,
|
||||
IWL_UCODE_TLV_CAPA_BEACON_ANT_SELECTION = (__force iwl_ucode_tlv_capa_t)71,
|
||||
IWL_UCODE_TLV_CAPA_BEACON_STORING = (__force iwl_ucode_tlv_capa_t)72,
|
||||
IWL_UCODE_TLV_CAPA_LAR_SUPPORT_V2 = (__force iwl_ucode_tlv_capa_t)73,
|
||||
|
@ -87,9 +87,10 @@ enum iwl_disable_11n {
|
||||
};
|
||||
|
||||
enum iwl_amsdu_size {
|
||||
IWL_AMSDU_4K = 0,
|
||||
IWL_AMSDU_8K = 1,
|
||||
IWL_AMSDU_12K = 2,
|
||||
IWL_AMSDU_DEF = 0,
|
||||
IWL_AMSDU_4K = 1,
|
||||
IWL_AMSDU_8K = 2,
|
||||
IWL_AMSDU_12K = 3,
|
||||
};
|
||||
|
||||
enum iwl_uapsd_disable {
|
||||
@ -105,7 +106,7 @@ enum iwl_uapsd_disable {
|
||||
* @sw_crypto: using hardware encryption, default = 0
|
||||
* @disable_11n: disable 11n capabilities, default = 0,
|
||||
* use IWL_[DIS,EN]ABLE_HT_* constants
|
||||
* @amsdu_size: enable 8K amsdu size, default = 4K. enum iwl_amsdu_size.
|
||||
* @amsdu_size: See &enum iwl_amsdu_size.
|
||||
* @restart_fw: restart firmware, default = 1
|
||||
* @bt_coex_active: enable bt coex, default = true
|
||||
* @led_mode: system default, default = 0
|
||||
|
@ -397,6 +397,13 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg,
|
||||
vht_cap->cap |= IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN;
|
||||
|
||||
switch (iwlwifi_mod_params.amsdu_size) {
|
||||
case IWL_AMSDU_DEF:
|
||||
if (cfg->mq_rx_supported)
|
||||
vht_cap->cap |=
|
||||
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
|
||||
else
|
||||
vht_cap->cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895;
|
||||
break;
|
||||
case IWL_AMSDU_4K:
|
||||
vht_cap->cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895;
|
||||
break;
|
||||
|
@ -211,6 +211,9 @@ struct iwl_cmd_header_wide {
|
||||
#define FH_RSCSR_FRAME_SIZE_MSK 0x00003FFF /* bits 0-13 */
|
||||
#define FH_RSCSR_FRAME_INVALID 0x55550000
|
||||
#define FH_RSCSR_FRAME_ALIGN 0x40
|
||||
#define FH_RSCSR_RPA_EN BIT(25)
|
||||
#define FH_RSCSR_RXQ_POS 16
|
||||
#define FH_RSCSR_RXQ_MASK 0x3F0000
|
||||
|
||||
struct iwl_rx_packet {
|
||||
/*
|
||||
@ -220,7 +223,13 @@ struct iwl_rx_packet {
|
||||
* 31: flag flush RB request
|
||||
* 30: flag ignore TC (terminal counter) request
|
||||
* 29: flag fast IRQ request
|
||||
* 28-14: Reserved
|
||||
* 28-26: Reserved
|
||||
* 25: Offload enabled
|
||||
* 24: RPF enabled
|
||||
* 23: RSS enabled
|
||||
* 22: Checksum enabled
|
||||
* 21-16: RX queue
|
||||
* 15-14: Reserved
|
||||
* 13-00: RX frame size
|
||||
*/
|
||||
__le32 len_n_flags;
|
||||
|
@ -336,6 +336,18 @@ enum iwl_rx_mpdu_reorder_data {
|
||||
IWL_RX_MPDU_REORDER_BA_OLD_SN = 0x80000000,
|
||||
};
|
||||
|
||||
enum iwl_rx_mpdu_phy_info {
|
||||
IWL_RX_MPDU_PHY_AMPDU = BIT(5),
|
||||
IWL_RX_MPDU_PHY_AMPDU_TOGGLE = BIT(6),
|
||||
IWL_RX_MPDU_PHY_SHORT_PREAMBLE = BIT(7),
|
||||
IWL_RX_MPDU_PHY_TSF_OVERLOAD = BIT(8),
|
||||
};
|
||||
|
||||
enum iwl_rx_mpdu_mac_info {
|
||||
IWL_RX_MPDU_PHY_MAC_INDEX_MASK = 0x0f,
|
||||
IWL_RX_MPDU_PHY_PHY_INDEX_MASK = 0xf0,
|
||||
};
|
||||
|
||||
struct iwl_rx_mpdu_desc {
|
||||
/* DW2 */
|
||||
__le16 mpdu_len;
|
||||
@ -343,9 +355,9 @@ struct iwl_rx_mpdu_desc {
|
||||
u8 mac_flags2;
|
||||
/* DW3 */
|
||||
u8 amsdu_info;
|
||||
__le16 reserved_for_software;
|
||||
__le16 phy_info;
|
||||
u8 mac_phy_idx;
|
||||
/* DW4 */
|
||||
/* DW4 - carries csum data only when rpa_en == 1 */
|
||||
__le16 raw_csum; /* alledgedly unreliable */
|
||||
__le16 l3l4_flags;
|
||||
/* DW5 */
|
||||
@ -354,17 +366,17 @@ struct iwl_rx_mpdu_desc {
|
||||
u8 sta_id_flags;
|
||||
/* DW6 */
|
||||
__le32 reorder_data;
|
||||
/* DW7 */
|
||||
/* DW7 - carries rss_hash only when rpa_en == 1 */
|
||||
__le32 rss_hash;
|
||||
/* DW8 */
|
||||
/* DW8 - carries filter_match only when rpa_en == 1 */
|
||||
__le32 filter_match;
|
||||
/* DW9 */
|
||||
__le32 rate_n_flags;
|
||||
/* DW10 */
|
||||
u8 energy_a, energy_b, channel, reserved;
|
||||
u8 energy_a, energy_b, channel, mac_context;
|
||||
/* DW11 */
|
||||
__le32 gp2_on_air_rise;
|
||||
/* DW12 & DW13 */
|
||||
/* DW12 & DW13 - carries TSF only TSF_OVERLOAD bit == 0 */
|
||||
__le64 tsf_on_air_rise;
|
||||
} __packed;
|
||||
|
||||
@ -435,26 +447,26 @@ struct iwl_rxq_sync_notification {
|
||||
} __packed; /* MULTI_QUEUE_DRV_SYNC_HDR_CMD_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* Internal message identifier
|
||||
*
|
||||
* @IWL_MVM_RXQ_EMPTY: empty sync notification
|
||||
* @IWL_MVM_RXQ_NOTIF_DEL_BA: notify RSS queues of delBA
|
||||
*/
|
||||
* Internal message identifier
|
||||
*
|
||||
* @IWL_MVM_RXQ_EMPTY: empty sync notification
|
||||
* @IWL_MVM_RXQ_NOTIF_DEL_BA: notify RSS queues of delBA
|
||||
*/
|
||||
enum iwl_mvm_rxq_notif_type {
|
||||
IWL_MVM_RXQ_EMPTY,
|
||||
IWL_MVM_RXQ_NOTIF_DEL_BA,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_internal_rxq_notif - Internal representation of the data sent
|
||||
* in &iwl_rxq_sync_cmd. Should be DWORD aligned.
|
||||
* FW is agnostic to the payload, so there are no endianity requirements.
|
||||
*
|
||||
* @type: value from &iwl_mvm_rxq_notif_type
|
||||
* @sync: ctrl path is waiting for all notifications to be received
|
||||
* @cookie: internal cookie to identify old notifications
|
||||
* @data: payload
|
||||
*/
|
||||
* struct iwl_mvm_internal_rxq_notif - Internal representation of the data sent
|
||||
* in &iwl_rxq_sync_cmd. Should be DWORD aligned.
|
||||
* FW is agnostic to the payload, so there are no endianity requirements.
|
||||
*
|
||||
* @type: value from &iwl_mvm_rxq_notif_type
|
||||
* @sync: ctrl path is waiting for all notifications to be received
|
||||
* @cookie: internal cookie to identify old notifications
|
||||
* @data: payload
|
||||
*/
|
||||
struct iwl_mvm_internal_rxq_notif {
|
||||
u16 type;
|
||||
u16 sync;
|
||||
|
@ -562,8 +562,8 @@ struct iwl_mvm_ba_notif {
|
||||
u8 reserved1;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* struct iwl_mac_beacon_cmd - beacon template command
|
||||
/**
|
||||
* struct iwl_mac_beacon_cmd_v6 - beacon template command
|
||||
* @tx: the tx commands associated with the beacon frame
|
||||
* @template_id: currently equal to the mac context id of the coresponding
|
||||
* mac.
|
||||
@ -571,13 +571,34 @@ struct iwl_mvm_ba_notif {
|
||||
* @tim_size: the length of the tim IE
|
||||
* @frame: the template of the beacon frame
|
||||
*/
|
||||
struct iwl_mac_beacon_cmd {
|
||||
struct iwl_mac_beacon_cmd_v6 {
|
||||
struct iwl_tx_cmd tx;
|
||||
__le32 template_id;
|
||||
__le32 tim_idx;
|
||||
__le32 tim_size;
|
||||
struct ieee80211_hdr frame[0];
|
||||
} __packed;
|
||||
} __packed; /* BEACON_TEMPLATE_CMD_API_S_VER_6 */
|
||||
|
||||
/**
|
||||
* struct iwl_mac_beacon_cmd - beacon template command with offloaded CSA
|
||||
* @tx: the tx commands associated with the beacon frame
|
||||
* @template_id: currently equal to the mac context id of the coresponding
|
||||
* mac.
|
||||
* @tim_idx: the offset of the tim IE in the beacon
|
||||
* @tim_size: the length of the tim IE
|
||||
* @ecsa_offset: offset to the ECSA IE if present
|
||||
* @csa_offset: offset to the CSA IE if present
|
||||
* @frame: the template of the beacon frame
|
||||
*/
|
||||
struct iwl_mac_beacon_cmd {
|
||||
struct iwl_tx_cmd tx;
|
||||
__le32 template_id;
|
||||
__le32 tim_idx;
|
||||
__le32 tim_size;
|
||||
__le32 ecsa_offset;
|
||||
__le32 csa_offset;
|
||||
struct ieee80211_hdr frame[0];
|
||||
} __packed; /* BEACON_TEMPLATE_CMD_API_S_VER_7 */
|
||||
|
||||
struct iwl_beacon_notif {
|
||||
struct iwl_mvm_tx_resp beacon_notify_hdr;
|
||||
|
@ -314,6 +314,7 @@ enum {
|
||||
enum iwl_mac_conf_subcmd_ids {
|
||||
LINK_QUALITY_MEASUREMENT_CMD = 0x1,
|
||||
LINK_QUALITY_MEASUREMENT_COMPLETE_NOTIF = 0xFE,
|
||||
CHANNEL_SWITCH_NOA_NOTIF = 0xFF,
|
||||
};
|
||||
|
||||
enum iwl_phy_ops_subcmd_ids {
|
||||
@ -732,7 +733,7 @@ enum iwl_time_event_type {
|
||||
|
||||
/* P2P GO Events */
|
||||
TE_P2P_GO_ASSOC_PROT,
|
||||
TE_P2P_GO_REPETITIVE_NOA,
|
||||
TE_P2P_GO_REPETITIVET_NOA,
|
||||
TE_P2P_GO_CT_WINDOW,
|
||||
|
||||
/* WiDi Sync Events */
|
||||
@ -2111,4 +2112,13 @@ struct iwl_link_qual_msrmnt_notif {
|
||||
__le32 reserved[3];
|
||||
} __packed; /* LQM_MEASUREMENT_COMPLETE_NTF_API_S_VER1 */
|
||||
|
||||
/**
|
||||
* Channel switch NOA notification
|
||||
*
|
||||
* @id_and_color: ID and color of the MAC
|
||||
*/
|
||||
struct iwl_channel_switch_noa_notif {
|
||||
__le32 id_and_color;
|
||||
} __packed; /* CHANNEL_SWITCH_START_NTFY_API_S_VER_1 */
|
||||
|
||||
#endif /* __fw_api_h__ */
|
||||
|
@ -1006,7 +1006,7 @@ static int iwl_mvm_mac_ctxt_cmd_p2p_device(struct iwl_mvm *mvm,
|
||||
}
|
||||
|
||||
static void iwl_mvm_mac_ctxt_set_tim(struct iwl_mvm *mvm,
|
||||
struct iwl_mac_beacon_cmd *beacon_cmd,
|
||||
struct iwl_mac_beacon_cmd_v6 *beacon_cmd,
|
||||
u8 *beacon, u32 frame_size)
|
||||
{
|
||||
u32 tim_idx;
|
||||
@ -1030,6 +1030,23 @@ static void iwl_mvm_mac_ctxt_set_tim(struct iwl_mvm *mvm,
|
||||
}
|
||||
}
|
||||
|
||||
static u32 iwl_mvm_find_ie_offset(u8 *beacon, u8 eid, u32 frame_size)
|
||||
{
|
||||
struct ieee80211_mgmt *mgmt = (void *)beacon;
|
||||
const u8 *ie;
|
||||
|
||||
if (WARN_ON_ONCE(frame_size <= (mgmt->u.beacon.variable - beacon)))
|
||||
return 0;
|
||||
|
||||
frame_size -= mgmt->u.beacon.variable - beacon;
|
||||
|
||||
ie = cfg80211_find_ie(eid, mgmt->u.beacon.variable, frame_size);
|
||||
if (!ie)
|
||||
return 0;
|
||||
|
||||
return ie - beacon;
|
||||
}
|
||||
|
||||
static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct sk_buff *beacon)
|
||||
@ -1039,7 +1056,10 @@ static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
|
||||
.id = BEACON_TEMPLATE_CMD,
|
||||
.flags = CMD_ASYNC,
|
||||
};
|
||||
struct iwl_mac_beacon_cmd beacon_cmd = {};
|
||||
union {
|
||||
struct iwl_mac_beacon_cmd_v6 beacon_cmd_v6;
|
||||
struct iwl_mac_beacon_cmd beacon_cmd;
|
||||
} u = {};
|
||||
struct ieee80211_tx_info *info;
|
||||
u32 beacon_skb_len;
|
||||
u32 rate, tx_flags;
|
||||
@ -1051,18 +1071,18 @@ static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
|
||||
|
||||
/* TODO: for now the beacon template id is set to be the mac context id.
|
||||
* Might be better to handle it as another resource ... */
|
||||
beacon_cmd.template_id = cpu_to_le32((u32)mvmvif->id);
|
||||
u.beacon_cmd_v6.template_id = cpu_to_le32((u32)mvmvif->id);
|
||||
info = IEEE80211_SKB_CB(beacon);
|
||||
|
||||
/* Set up TX command fields */
|
||||
beacon_cmd.tx.len = cpu_to_le16((u16)beacon_skb_len);
|
||||
beacon_cmd.tx.sta_id = mvmvif->bcast_sta.sta_id;
|
||||
beacon_cmd.tx.life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE);
|
||||
u.beacon_cmd_v6.tx.len = cpu_to_le16((u16)beacon_skb_len);
|
||||
u.beacon_cmd_v6.tx.sta_id = mvmvif->bcast_sta.sta_id;
|
||||
u.beacon_cmd_v6.tx.life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE);
|
||||
tx_flags = TX_CMD_FLG_SEQ_CTL | TX_CMD_FLG_TSF;
|
||||
tx_flags |=
|
||||
iwl_mvm_bt_coex_tx_prio(mvm, (void *)beacon->data, info, 0) <<
|
||||
TX_CMD_FLG_BT_PRIO_POS;
|
||||
beacon_cmd.tx.tx_flags = cpu_to_le32(tx_flags);
|
||||
u.beacon_cmd_v6.tx.tx_flags = cpu_to_le32(tx_flags);
|
||||
|
||||
if (!fw_has_capa(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_BEACON_ANT_SELECTION)) {
|
||||
@ -1071,7 +1091,7 @@ static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
|
||||
mvm->mgmt_last_antenna_idx);
|
||||
}
|
||||
|
||||
beacon_cmd.tx.rate_n_flags =
|
||||
u.beacon_cmd_v6.tx.rate_n_flags =
|
||||
cpu_to_le32(BIT(mvm->mgmt_last_antenna_idx) <<
|
||||
RATE_MCS_ANT_POS);
|
||||
|
||||
@ -1079,20 +1099,37 @@ static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
|
||||
rate = IWL_FIRST_OFDM_RATE;
|
||||
} else {
|
||||
rate = IWL_FIRST_CCK_RATE;
|
||||
beacon_cmd.tx.rate_n_flags |= cpu_to_le32(RATE_MCS_CCK_MSK);
|
||||
u.beacon_cmd_v6.tx.rate_n_flags |=
|
||||
cpu_to_le32(RATE_MCS_CCK_MSK);
|
||||
}
|
||||
beacon_cmd.tx.rate_n_flags |=
|
||||
u.beacon_cmd_v6.tx.rate_n_flags |=
|
||||
cpu_to_le32(iwl_mvm_mac80211_idx_to_hwrate(rate));
|
||||
|
||||
/* Set up TX beacon command fields */
|
||||
if (vif->type == NL80211_IFTYPE_AP)
|
||||
iwl_mvm_mac_ctxt_set_tim(mvm, &beacon_cmd,
|
||||
iwl_mvm_mac_ctxt_set_tim(mvm, &u.beacon_cmd_v6,
|
||||
beacon->data,
|
||||
beacon_skb_len);
|
||||
|
||||
/* Submit command */
|
||||
cmd.len[0] = sizeof(beacon_cmd);
|
||||
cmd.data[0] = &beacon_cmd;
|
||||
|
||||
if (fw_has_capa(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_CSA_AND_TBTT_OFFLOAD)) {
|
||||
u.beacon_cmd.csa_offset =
|
||||
cpu_to_le32(iwl_mvm_find_ie_offset(beacon->data,
|
||||
WLAN_EID_CHANNEL_SWITCH,
|
||||
beacon_skb_len));
|
||||
u.beacon_cmd.ecsa_offset =
|
||||
cpu_to_le32(iwl_mvm_find_ie_offset(beacon->data,
|
||||
WLAN_EID_EXT_CHANSWITCH_ANN,
|
||||
beacon_skb_len));
|
||||
|
||||
cmd.len[0] = sizeof(u.beacon_cmd);
|
||||
} else {
|
||||
cmd.len[0] = sizeof(u.beacon_cmd_v6);
|
||||
}
|
||||
|
||||
cmd.data[0] = &u;
|
||||
cmd.dataflags[0] = 0;
|
||||
cmd.len[1] = beacon_skb_len;
|
||||
cmd.data[1] = beacon->data;
|
||||
@ -1538,3 +1575,48 @@ void iwl_mvm_rx_stored_beacon_notif(struct iwl_mvm *mvm,
|
||||
/* pass it as regular rx to mac80211 */
|
||||
ieee80211_rx_napi(mvm->hw, NULL, skb, NULL);
|
||||
}
|
||||
|
||||
void iwl_mvm_channel_switch_noa_notif(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_channel_switch_noa_notif *notif = (void *)pkt->data;
|
||||
struct ieee80211_vif *csa_vif;
|
||||
struct iwl_mvm_vif *mvmvif;
|
||||
int len = iwl_rx_packet_payload_len(pkt);
|
||||
u32 id_n_color;
|
||||
|
||||
if (WARN_ON_ONCE(len < sizeof(*notif)))
|
||||
return;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
csa_vif = rcu_dereference(mvm->csa_vif);
|
||||
if (WARN_ON(!csa_vif || !csa_vif->csa_active))
|
||||
goto out_unlock;
|
||||
|
||||
id_n_color = le32_to_cpu(notif->id_and_color);
|
||||
|
||||
mvmvif = iwl_mvm_vif_from_mac80211(csa_vif);
|
||||
if (WARN(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color) != id_n_color,
|
||||
"channel switch noa notification on unexpected vif (csa_vif=%d, notif=%d)",
|
||||
FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color), id_n_color))
|
||||
goto out_unlock;
|
||||
|
||||
IWL_DEBUG_INFO(mvm, "Channel Switch Started Notification\n");
|
||||
|
||||
queue_delayed_work(system_wq, &mvm->cs_tx_unblock_dwork,
|
||||
msecs_to_jiffies(IWL_MVM_CS_UNBLOCK_TX_TIMEOUT *
|
||||
csa_vif->bss_conf.beacon_int));
|
||||
|
||||
ieee80211_csa_finish(csa_vif);
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
RCU_INIT_POINTER(mvm->csa_vif, NULL);
|
||||
|
||||
return;
|
||||
|
||||
out_unlock:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
@ -1199,6 +1199,7 @@ static void iwl_mvm_mac_stop(struct ieee80211_hw *hw)
|
||||
flush_work(&mvm->async_handlers_wk);
|
||||
flush_work(&mvm->add_stream_wk);
|
||||
cancel_delayed_work_sync(&mvm->fw_dump_wk);
|
||||
cancel_delayed_work_sync(&mvm->cs_tx_unblock_dwork);
|
||||
iwl_mvm_free_fw_dump_desc(mvm);
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
@ -2360,7 +2361,7 @@ static void iwl_mvm_check_uapsd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT))
|
||||
return;
|
||||
|
||||
if (vif->p2p && !iwl_mvm_is_p2p_standalone_uapsd_supported(mvm)) {
|
||||
if (vif->p2p && !iwl_mvm_is_p2p_scm_uapsd_supported(mvm)) {
|
||||
vif->driver_flags &= ~IEEE80211_VIF_SUPPORTS_UAPSD;
|
||||
return;
|
||||
}
|
||||
@ -3687,6 +3688,13 @@ static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
/* we still didn't unblock tx. prevent new CS meanwhile */
|
||||
if (rcu_dereference_protected(mvm->csa_tx_blocked_vif,
|
||||
lockdep_is_held(&mvm->mutex))) {
|
||||
ret = -EBUSY;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
rcu_assign_pointer(mvm->csa_vif, vif);
|
||||
|
||||
if (WARN_ONCE(mvmvif->csa_countdown,
|
||||
@ -3695,6 +3703,8 @@ static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
mvmvif->csa_target_freq = chsw->chandef.chan->center_freq;
|
||||
|
||||
break;
|
||||
case NL80211_IFTYPE_STATION:
|
||||
if (mvmvif->lqm_active)
|
||||
|
@ -452,6 +452,7 @@ struct iwl_mvm_vif {
|
||||
/* Indicates that CSA countdown may be started */
|
||||
bool csa_countdown;
|
||||
bool csa_failed;
|
||||
u16 csa_target_freq;
|
||||
|
||||
/* TCP Checksum Offload */
|
||||
netdev_features_t features;
|
||||
@ -731,6 +732,7 @@ struct iwl_mvm {
|
||||
struct iwl_sf_region sf_space;
|
||||
|
||||
u32 ampdu_ref;
|
||||
bool ampdu_toggle;
|
||||
|
||||
struct iwl_notif_wait_data notif_wait;
|
||||
|
||||
@ -1006,6 +1008,8 @@ struct iwl_mvm {
|
||||
* clients.
|
||||
*/
|
||||
bool drop_bcn_ap_mode;
|
||||
|
||||
struct delayed_work cs_tx_unblock_dwork;
|
||||
};
|
||||
|
||||
/* Extract MVM priv from op_mode and _hw */
|
||||
@ -1158,10 +1162,10 @@ static inline bool iwl_mvm_is_mplut_supported(struct iwl_mvm *mvm)
|
||||
}
|
||||
|
||||
static inline
|
||||
bool iwl_mvm_is_p2p_standalone_uapsd_supported(struct iwl_mvm *mvm)
|
||||
bool iwl_mvm_is_p2p_scm_uapsd_supported(struct iwl_mvm *mvm)
|
||||
{
|
||||
return fw_has_capa(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_P2P_STANDALONE_UAPSD) &&
|
||||
IWL_UCODE_TLV_CAPA_P2P_SCM_UAPSD) &&
|
||||
!(iwlwifi_mod_params.uapsd_disable &
|
||||
IWL_DISABLE_UAPSD_P2P_CLIENT);
|
||||
}
|
||||
@ -1321,7 +1325,6 @@ bool iwl_mvm_bcast_filter_build_cmd(struct iwl_mvm *mvm,
|
||||
void iwl_mvm_rx_rx_phy_cmd(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb);
|
||||
void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi,
|
||||
struct iwl_rx_cmd_buffer *rxb);
|
||||
void iwl_mvm_rx_phy_cmd_mq(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb);
|
||||
void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
|
||||
struct iwl_rx_cmd_buffer *rxb, int queue);
|
||||
void iwl_mvm_rx_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,
|
||||
@ -1381,6 +1384,8 @@ void iwl_mvm_mac_ctxt_recalc_tsf_id(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif);
|
||||
unsigned long iwl_mvm_get_used_hw_queues(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *exclude_vif);
|
||||
void iwl_mvm_channel_switch_noa_notif(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb);
|
||||
/* Bindings */
|
||||
int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
|
@ -431,6 +431,7 @@ static const struct iwl_hcmd_names iwl_mvm_system_names[] = {
|
||||
static const struct iwl_hcmd_names iwl_mvm_mac_conf_names[] = {
|
||||
HCMD_NAME(LINK_QUALITY_MEASUREMENT_CMD),
|
||||
HCMD_NAME(LINK_QUALITY_MEASUREMENT_COMPLETE_NOTIF),
|
||||
HCMD_NAME(CHANNEL_SWITCH_NOA_NOTIF),
|
||||
};
|
||||
|
||||
/* Please keep this array *SORTED* by hex value.
|
||||
@ -494,6 +495,29 @@ static u32 calc_min_backoff(struct iwl_trans *trans, const struct iwl_cfg *cfg)
|
||||
|
||||
static void iwl_mvm_fw_error_dump_wk(struct work_struct *work);
|
||||
|
||||
static void iwl_mvm_tx_unblock_dwork(struct work_struct *work)
|
||||
{
|
||||
struct iwl_mvm *mvm =
|
||||
container_of(work, struct iwl_mvm, cs_tx_unblock_dwork.work);
|
||||
struct ieee80211_vif *tx_blocked_vif;
|
||||
struct iwl_mvm_vif *mvmvif;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
|
||||
tx_blocked_vif =
|
||||
rcu_dereference_protected(mvm->csa_tx_blocked_vif,
|
||||
lockdep_is_held(&mvm->mutex));
|
||||
|
||||
if (!tx_blocked_vif)
|
||||
goto unlock;
|
||||
|
||||
mvmvif = iwl_mvm_vif_from_mac80211(tx_blocked_vif);
|
||||
iwl_mvm_modify_all_sta_disable_tx(mvm, mvmvif, false);
|
||||
RCU_INIT_POINTER(mvm->csa_tx_blocked_vif, NULL);
|
||||
unlock:
|
||||
mutex_unlock(&mvm->mutex);
|
||||
}
|
||||
|
||||
static struct iwl_op_mode *
|
||||
iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
const struct iwl_fw *fw, struct dentry *dbgfs_dir)
|
||||
@ -595,6 +619,8 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
|
||||
SET_IEEE80211_DEV(mvm->hw, mvm->trans->dev);
|
||||
|
||||
INIT_DELAYED_WORK(&mvm->cs_tx_unblock_dwork, iwl_mvm_tx_unblock_dwork);
|
||||
|
||||
/*
|
||||
* Populate the state variables that the transport layer needs
|
||||
* to know about.
|
||||
@ -603,6 +629,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
trans_cfg.no_reclaim_cmds = no_reclaim_cmds;
|
||||
trans_cfg.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds);
|
||||
switch (iwlwifi_mod_params.amsdu_size) {
|
||||
case IWL_AMSDU_DEF:
|
||||
case IWL_AMSDU_4K:
|
||||
trans_cfg.rx_buf_size = IWL_AMSDU_4K;
|
||||
break;
|
||||
@ -617,6 +644,10 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
iwlwifi_mod_params.amsdu_size);
|
||||
trans_cfg.rx_buf_size = IWL_AMSDU_4K;
|
||||
}
|
||||
|
||||
/* the hardware splits the A-MSDU */
|
||||
if (mvm->cfg->mq_rx_supported)
|
||||
trans_cfg.rx_buf_size = IWL_AMSDU_4K;
|
||||
trans_cfg.wide_cmd_header = fw_has_api(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_API_WIDE_CMD_HDR);
|
||||
|
||||
@ -936,8 +967,6 @@ static void iwl_mvm_rx(struct iwl_op_mode *op_mode,
|
||||
|
||||
if (likely(pkt->hdr.cmd == REPLY_RX_MPDU_CMD))
|
||||
iwl_mvm_rx_rx_mpdu(mvm, napi, rxb);
|
||||
else if (pkt->hdr.cmd == FRAME_RELEASE)
|
||||
iwl_mvm_rx_frame_release(mvm, napi, rxb, 0);
|
||||
else if (pkt->hdr.cmd == REPLY_RX_PHY_CMD)
|
||||
iwl_mvm_rx_rx_phy_cmd(mvm, rxb);
|
||||
else
|
||||
@ -953,11 +982,11 @@ static void iwl_mvm_rx_mq(struct iwl_op_mode *op_mode,
|
||||
|
||||
if (likely(pkt->hdr.cmd == REPLY_RX_MPDU_CMD))
|
||||
iwl_mvm_rx_mpdu_mq(mvm, napi, rxb, 0);
|
||||
else if (pkt->hdr.cmd == REPLY_RX_PHY_CMD)
|
||||
iwl_mvm_rx_phy_cmd_mq(mvm, rxb);
|
||||
else if (unlikely(pkt->hdr.group_id == DATA_PATH_GROUP &&
|
||||
pkt->hdr.cmd == RX_QUEUES_NOTIFICATION))
|
||||
iwl_mvm_rx_queue_notif(mvm, rxb, 0);
|
||||
else if (pkt->hdr.cmd == FRAME_RELEASE)
|
||||
iwl_mvm_rx_frame_release(mvm, napi, rxb, 0);
|
||||
else
|
||||
iwl_mvm_rx_common(mvm, rxb, pkt);
|
||||
}
|
||||
|
@ -308,7 +308,7 @@ static bool iwl_mvm_power_allow_uapsd(struct iwl_mvm *mvm,
|
||||
/* Allow U-APSD only if p2p is stand alone */
|
||||
bool is_p2p_standalone = true;
|
||||
|
||||
if (!iwl_mvm_is_p2p_standalone_uapsd_supported(mvm))
|
||||
if (!iwl_mvm_is_p2p_scm_uapsd_supported(mvm))
|
||||
return false;
|
||||
|
||||
ieee80211_iterate_active_interfaces_atomic(mvm->hw,
|
||||
|
@ -354,13 +354,22 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi,
|
||||
|
||||
if (sta) {
|
||||
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
struct ieee80211_vif *tx_blocked_vif =
|
||||
rcu_dereference(mvm->csa_tx_blocked_vif);
|
||||
|
||||
/* We have tx blocked stations (with CS bit). If we heard
|
||||
* frames from a blocked station on a new channel we can
|
||||
* TX to it again.
|
||||
*/
|
||||
if (unlikely(mvm->csa_tx_block_bcn_timeout))
|
||||
iwl_mvm_sta_modify_disable_tx_ap(mvm, sta, false);
|
||||
if (unlikely(tx_blocked_vif) &&
|
||||
mvmsta->vif == tx_blocked_vif) {
|
||||
struct iwl_mvm_vif *mvmvif =
|
||||
iwl_mvm_vif_from_mac80211(tx_blocked_vif);
|
||||
|
||||
if (mvmvif->csa_target_freq == rx_status->freq)
|
||||
iwl_mvm_sta_modify_disable_tx_ap(mvm, sta,
|
||||
false);
|
||||
}
|
||||
|
||||
rs_update_last_rssi(mvm, &mvmsta->lq_sta, rx_status);
|
||||
|
||||
|
@ -65,19 +65,6 @@
|
||||
#include "fw-api.h"
|
||||
#include "fw-dbg.h"
|
||||
|
||||
void iwl_mvm_rx_phy_cmd_mq(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
|
||||
{
|
||||
mvm->ampdu_ref++;
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
if (mvm->last_phy_info.phy_flags & cpu_to_le16(RX_RES_PHY_FLAGS_AGG)) {
|
||||
spin_lock(&mvm->drv_stats_lock);
|
||||
mvm->drv_rx_stats.ampdu_count++;
|
||||
spin_unlock(&mvm->drv_stats_lock);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline int iwl_mvm_check_pn(struct iwl_mvm *mvm, struct sk_buff *skb,
|
||||
int queue, struct ieee80211_sta *sta)
|
||||
{
|
||||
@ -587,6 +574,8 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
|
||||
struct sk_buff *tail;
|
||||
u32 reorder = le32_to_cpu(desc->reorder_data);
|
||||
bool amsdu = desc->mac_flags2 & IWL_RX_MPDU_MFLG2_AMSDU;
|
||||
bool last_subframe =
|
||||
desc->amsdu_info & IWL_RX_MPDU_AMSDU_LAST_SUBFRAME;
|
||||
u8 tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
|
||||
u8 sub_frame_idx = desc->amsdu_info &
|
||||
IWL_RX_MPDU_AMSDU_SUBFRAME_IDX_MASK;
|
||||
@ -651,7 +640,8 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
|
||||
/* release immediately if allowed by nssn and no stored frames */
|
||||
if (!buffer->num_stored && ieee80211_sn_less(sn, nssn)) {
|
||||
if (iwl_mvm_is_sn_less(buffer->head_sn, nssn,
|
||||
buffer->buf_size))
|
||||
buffer->buf_size) &&
|
||||
(!amsdu || last_subframe))
|
||||
buffer->head_sn = nssn;
|
||||
/* No need to update AMSDU last SN - we are moving the head */
|
||||
spin_unlock_bh(&buffer->lock);
|
||||
@ -685,7 +675,20 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
|
||||
buffer->last_sub_index = sub_frame_idx;
|
||||
}
|
||||
|
||||
iwl_mvm_release_frames(mvm, sta, napi, buffer, nssn);
|
||||
/*
|
||||
* We cannot trust NSSN for AMSDU sub-frames that are not the last.
|
||||
* The reason is that NSSN advances on the first sub-frame, and may
|
||||
* cause the reorder buffer to advance before all the sub-frames arrive.
|
||||
* Example: reorder buffer contains SN 0 & 2, and we receive AMSDU with
|
||||
* SN 1. NSSN for first sub frame will be 3 with the result of driver
|
||||
* releasing SN 0,1, 2. When sub-frame 1 arrives - reorder buffer is
|
||||
* already ahead and it will be dropped.
|
||||
* If the last sub-frame is not on this queue - we will get frame
|
||||
* release notification with up to date NSSN.
|
||||
*/
|
||||
if (!amsdu || last_subframe)
|
||||
iwl_mvm_release_frames(mvm, sta, napi, buffer, nssn);
|
||||
|
||||
spin_unlock_bh(&buffer->lock);
|
||||
return true;
|
||||
|
||||
@ -734,6 +737,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
|
||||
struct ieee80211_hdr *hdr = (void *)(pkt->data + sizeof(*desc));
|
||||
u32 len = le16_to_cpu(desc->mpdu_len);
|
||||
u32 rate_n_flags = le32_to_cpu(desc->rate_n_flags);
|
||||
u16 phy_info = le16_to_cpu(desc->phy_info);
|
||||
struct ieee80211_sta *sta = NULL;
|
||||
struct sk_buff *skb;
|
||||
u8 crypt_len = 0;
|
||||
@ -764,16 +768,34 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
|
||||
le16_to_cpu(desc->status));
|
||||
rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
|
||||
}
|
||||
/* set the preamble flag if appropriate */
|
||||
if (phy_info & IWL_RX_MPDU_PHY_SHORT_PREAMBLE)
|
||||
rx_status->flag |= RX_FLAG_SHORTPRE;
|
||||
|
||||
rx_status->mactime = le64_to_cpu(desc->tsf_on_air_rise);
|
||||
if (likely(!(phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD))) {
|
||||
rx_status->mactime = le64_to_cpu(desc->tsf_on_air_rise);
|
||||
/* TSF as indicated by the firmware is at INA time */
|
||||
rx_status->flag |= RX_FLAG_MACTIME_PLCP_START;
|
||||
}
|
||||
rx_status->device_timestamp = le32_to_cpu(desc->gp2_on_air_rise);
|
||||
rx_status->band = desc->channel > 14 ? NL80211_BAND_5GHZ :
|
||||
NL80211_BAND_2GHZ;
|
||||
rx_status->freq = ieee80211_channel_to_frequency(desc->channel,
|
||||
rx_status->band);
|
||||
iwl_mvm_get_signal_strength(mvm, desc, rx_status);
|
||||
/* TSF as indicated by the firmware is at INA time */
|
||||
rx_status->flag |= RX_FLAG_MACTIME_PLCP_START;
|
||||
|
||||
/* update aggregation data for monitor sake on default queue */
|
||||
if (!queue && (phy_info & IWL_RX_MPDU_PHY_AMPDU)) {
|
||||
bool toggle_bit = phy_info & IWL_RX_MPDU_PHY_AMPDU_TOGGLE;
|
||||
|
||||
rx_status->flag |= RX_FLAG_AMPDU_DETAILS;
|
||||
rx_status->ampdu_reference = mvm->ampdu_ref;
|
||||
/* toggle is switched whenever new aggregation starts */
|
||||
if (toggle_bit != mvm->ampdu_toggle) {
|
||||
mvm->ampdu_ref++;
|
||||
mvm->ampdu_toggle = toggle_bit;
|
||||
}
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
@ -795,6 +817,8 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
|
||||
|
||||
if (sta) {
|
||||
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
struct ieee80211_vif *tx_blocked_vif =
|
||||
rcu_dereference(mvm->csa_tx_blocked_vif);
|
||||
u8 baid = (u8)((le32_to_cpu(desc->reorder_data) &
|
||||
IWL_RX_MPDU_REORDER_BAID_MASK) >>
|
||||
IWL_RX_MPDU_REORDER_BAID_SHIFT);
|
||||
@ -804,8 +828,15 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
|
||||
* frames from a blocked station on a new channel we can
|
||||
* TX to it again.
|
||||
*/
|
||||
if (unlikely(mvm->csa_tx_block_bcn_timeout))
|
||||
iwl_mvm_sta_modify_disable_tx_ap(mvm, sta, false);
|
||||
if (unlikely(tx_blocked_vif) &&
|
||||
tx_blocked_vif == mvmsta->vif) {
|
||||
struct iwl_mvm_vif *mvmvif =
|
||||
iwl_mvm_vif_from_mac80211(tx_blocked_vif);
|
||||
|
||||
if (mvmvif->csa_target_freq == rx_status->freq)
|
||||
iwl_mvm_sta_modify_disable_tx_ap(mvm, sta,
|
||||
false);
|
||||
}
|
||||
|
||||
rs_update_last_rssi(mvm, &mvmsta->lq_sta, rx_status);
|
||||
|
||||
@ -828,8 +859,6 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
|
||||
iwl_mvm_fw_dbg_collect_trig(mvm, trig, NULL);
|
||||
}
|
||||
|
||||
/* TODO: multi queue TCM */
|
||||
|
||||
if (ieee80211_is_data(hdr->frame_control))
|
||||
iwl_mvm_rx_csum(sta, skb, desc);
|
||||
|
||||
@ -854,14 +883,6 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
|
||||
iwl_mvm_agg_rx_received(mvm, baid);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: PHY info.
|
||||
* Verify we don't have the information in the MPDU descriptor and
|
||||
* that it is not needed.
|
||||
* Make sure for monitor mode that we are on default queue, update
|
||||
* ampdu_ref and the rest of phy info then
|
||||
*/
|
||||
|
||||
/* Set up the HT phy flags */
|
||||
switch (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) {
|
||||
case RATE_MCS_CHAN_WIDTH_20:
|
||||
@ -905,8 +926,18 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
|
||||
rx_status->band);
|
||||
}
|
||||
|
||||
/* TODO: PHY info - update ampdu queue statistics (for debugfs) */
|
||||
/* TODO: PHY info - gscan */
|
||||
/* management stuff on default queue */
|
||||
if (!queue) {
|
||||
if (unlikely((ieee80211_is_beacon(hdr->frame_control) ||
|
||||
ieee80211_is_probe_resp(hdr->frame_control)) &&
|
||||
mvm->sched_scan_pass_all ==
|
||||
SCHED_SCAN_PASS_ALL_ENABLED))
|
||||
mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_FOUND;
|
||||
|
||||
if (unlikely(ieee80211_is_beacon(hdr->frame_control) ||
|
||||
ieee80211_is_probe_resp(hdr->frame_control)))
|
||||
rx_status->boottime_ns = ktime_get_boot_ns();
|
||||
}
|
||||
|
||||
iwl_mvm_create_skb(skb, hdr, len, crypt_len, rxb);
|
||||
if (!iwl_mvm_reorder(mvm, napi, queue, sta, skb, desc))
|
||||
|
@ -819,8 +819,9 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
|
||||
if (iwl_mvm_has_new_rx_api(mvm))
|
||||
kfree(mvm_sta->dup_data);
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_STATION &&
|
||||
mvmvif->ap_sta_id == mvm_sta->sta_id) {
|
||||
if ((vif->type == NL80211_IFTYPE_STATION &&
|
||||
mvmvif->ap_sta_id == mvm_sta->sta_id) ||
|
||||
iwl_mvm_is_dqa_supported(mvm)){
|
||||
ret = iwl_mvm_drain_sta(mvm, mvm_sta, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -673,4 +673,6 @@ static inline int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans)
|
||||
int iwl_pci_fw_exit_d0i3(struct iwl_trans *trans);
|
||||
int iwl_pci_fw_enter_d0i3(struct iwl_trans *trans);
|
||||
|
||||
void iwl_pcie_enable_rx_wake(struct iwl_trans *trans, bool enable);
|
||||
|
||||
#endif /* __iwl_trans_int_pcie_h__ */
|
||||
|
@ -211,12 +211,8 @@ static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans,
|
||||
if (trans->cfg->mq_rx_supported)
|
||||
iwl_write32(trans, RFH_Q_FRBDCB_WIDX_TRG(rxq->id),
|
||||
rxq->write_actual);
|
||||
/*
|
||||
* write to FH_RSCSR_CHNL0_WPTR register even in MQ as a W/A to
|
||||
* hardware shadow registers bug - writing to RFH_Q_FRBDCB_WIDX will
|
||||
* not wake the NIC.
|
||||
*/
|
||||
iwl_write32(trans, FH_RSCSR_CHNL0_WPTR, rxq->write_actual);
|
||||
else
|
||||
iwl_write32(trans, FH_RSCSR_CHNL0_WPTR, rxq->write_actual);
|
||||
}
|
||||
|
||||
static void iwl_pcie_rxq_check_wrptr(struct iwl_trans *trans)
|
||||
@ -764,6 +760,23 @@ static void iwl_pcie_rx_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq)
|
||||
iwl_set_bit(trans, CSR_INT_COALESCING, IWL_HOST_INT_OPER_MODE);
|
||||
}
|
||||
|
||||
void iwl_pcie_enable_rx_wake(struct iwl_trans *trans, bool enable)
|
||||
{
|
||||
/*
|
||||
* Turn on the chicken-bits that cause MAC wakeup for RX-related
|
||||
* values.
|
||||
* This costs some power, but needed for W/A 9000 integrated A-step
|
||||
* bug where shadow registers are not in the retention list and their
|
||||
* value is lost when NIC powers down
|
||||
*/
|
||||
if (trans->cfg->integrated) {
|
||||
iwl_set_bit(trans, CSR_MAC_SHADOW_REG_CTRL,
|
||||
CSR_MAC_SHADOW_REG_CTRL_RX_WAKE);
|
||||
iwl_set_bit(trans, CSR_MAC_SHADOW_REG_CTL2,
|
||||
CSR_MAC_SHADOW_REG_CTL2_RX_WAKE);
|
||||
}
|
||||
}
|
||||
|
||||
static void iwl_pcie_rx_mq_hw_init(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
@ -820,28 +833,30 @@ static void iwl_pcie_rx_mq_hw_init(struct iwl_trans *trans)
|
||||
|
||||
/*
|
||||
* Enable Rx DMA
|
||||
* Single frame mode
|
||||
* Rx buffer size 4 or 8k or 12k
|
||||
* Min RB size 4 or 8
|
||||
* Drop frames that exceed RB size
|
||||
* 512 RBDs
|
||||
*/
|
||||
iwl_write_prph_no_grab(trans, RFH_RXF_DMA_CFG,
|
||||
RFH_DMA_EN_ENABLE_VAL |
|
||||
rb_size | RFH_RXF_DMA_SINGLE_FRAME_MASK |
|
||||
RFH_DMA_EN_ENABLE_VAL | rb_size |
|
||||
RFH_RXF_DMA_MIN_RB_4_8 |
|
||||
RFH_RXF_DMA_DROP_TOO_LARGE_MASK |
|
||||
RFH_RXF_DMA_RBDCB_SIZE_512);
|
||||
|
||||
/*
|
||||
* Activate DMA snooping.
|
||||
* Set RX DMA chunk size to 64B
|
||||
* Set RX DMA chunk size to 64B for IOSF and 128B for PCIe
|
||||
* Default queue is 0
|
||||
*/
|
||||
iwl_write_prph_no_grab(trans, RFH_GEN_CFG, RFH_GEN_CFG_RFH_DMA_SNOOP |
|
||||
(DEFAULT_RXQ_NUM <<
|
||||
RFH_GEN_CFG_DEFAULT_RXQ_NUM_POS) |
|
||||
RFH_GEN_CFG_SERVICE_DMA_SNOOP);
|
||||
RFH_GEN_CFG_SERVICE_DMA_SNOOP |
|
||||
(trans->cfg->integrated ?
|
||||
RFH_GEN_CFG_RB_CHUNK_SIZE_64 :
|
||||
RFH_GEN_CFG_RB_CHUNK_SIZE_128) <<
|
||||
RFH_GEN_CFG_RB_CHUNK_SIZE_POS);
|
||||
/* Enable the relevant rx queues */
|
||||
iwl_write_prph_no_grab(trans, RFH_RXF_RXQ_ACTIVE, enabled);
|
||||
|
||||
@ -849,6 +864,8 @@ static void iwl_pcie_rx_mq_hw_init(struct iwl_trans *trans)
|
||||
|
||||
/* Set interrupt coalescing timer to default (2048 usecs) */
|
||||
iwl_write8(trans, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF);
|
||||
|
||||
iwl_pcie_enable_rx_wake(trans, true);
|
||||
}
|
||||
|
||||
static void iwl_pcie_rx_init_rxb_lists(struct iwl_rxq *rxq)
|
||||
@ -1087,6 +1104,9 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,
|
||||
if (pkt->len_n_flags == cpu_to_le32(FH_RSCSR_FRAME_INVALID))
|
||||
break;
|
||||
|
||||
WARN_ON((le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_RXQ_MASK) >>
|
||||
FH_RSCSR_RXQ_POS != rxq->id);
|
||||
|
||||
IWL_DEBUG_RX(trans,
|
||||
"cmd at offset %d: %s (0x%.2x, seq 0x%x)\n",
|
||||
rxcb._offset,
|
||||
|
@ -1286,6 +1286,8 @@ static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test,
|
||||
iwl_clear_bit(trans, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
|
||||
|
||||
iwl_pcie_enable_rx_wake(trans, false);
|
||||
|
||||
if (reset) {
|
||||
/*
|
||||
* reset TX queues -- some of their registers reset during S3
|
||||
@ -1311,6 +1313,8 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
|
||||
return 0;
|
||||
}
|
||||
|
||||
iwl_pcie_enable_rx_wake(trans, true);
|
||||
|
||||
/*
|
||||
* Also enables interrupts - none will happen as the device doesn't
|
||||
* know we're waking it up, only when the opmode actually tells it
|
||||
|
Loading…
Reference in New Issue
Block a user