Merge tag 'wireless-drivers-next-for-davem-2018-12-20' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next

Kalle Valo says:

====================
wireless-drivers-next patches for 4.21

Last set of patches for 4.21. mt76 is still in very active development
and having some refactoring as well as new features. But also other
drivers got few new features and fixes.

Major changes:

ath10k

* add amsdu support for QCA6174 monitor mode

* report tx rate using the new ieee80211_tx_rate_update() API

* wcn3990 support is not experimental anymore

iwlwifi

* support for FW version 43 for 9000 and 22000 series

brcmfmac

* add support for CYW43012 SDIO chipset

* add the raw 4354 PCIe device ID for unprogrammed Cypress boards

mwifiex

* add NL80211_STA_INFO_RX_BITRATE support

mt76

* use the same firmware for mt76x2e and mt76x2u

* mt76x0e survey support

* more unification between mt76x2 and mt76x0

* mt76x0e AP mode support

* mt76x0e DFS support

* rework and fix tx status handling for mt76x0 and mt76x2
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller
2018-12-20 16:47:10 -08:00
146 changed files with 5030 additions and 4327 deletions

View File

@@ -1811,8 +1811,7 @@ static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm,
n_matches = 0;
}
net_detect = kzalloc(sizeof(*net_detect) +
(n_matches * sizeof(net_detect->matches[0])),
net_detect = kzalloc(struct_size(net_detect, matches, n_matches),
GFP_KERNEL);
if (!net_detect || !n_matches)
goto out_report_nd;
@@ -1827,8 +1826,7 @@ static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm,
for (j = 0; j < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN; j++)
n_channels += hweight8(fw_match->matching_channels[j]);
match = kzalloc(sizeof(*match) +
(n_channels * sizeof(*match->channels)),
match = kzalloc(struct_size(match, channels, n_channels),
GFP_KERNEL);
if (!match)
goto out_report_nd;

View File

@@ -1284,7 +1284,7 @@ static ssize_t iwl_dbgfs_fw_dbg_collect_write(struct iwl_mvm *mvm,
return 0;
iwl_fw_dbg_collect(&mvm->fwrt, FW_DBG_TRIGGER_USER, buf,
(count - 1), NULL);
(count - 1));
iwl_mvm_unref(mvm, IWL_MVM_REF_PRPH_WRITE);

View File

@@ -547,7 +547,9 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
if (mvm->nvm_file_name)
iwl_mvm_load_nvm_to_nic(mvm);
WARN_ON(iwl_nvm_check_version(mvm->nvm_data, mvm->trans));
WARN_ONCE(mvm->nvm_data->nvm_version < mvm->trans->cfg->nvm_ver,
"Too old NVM version (0x%0x, required = 0x%0x)",
mvm->nvm_data->nvm_version, mvm->trans->cfg->nvm_ver);
/*
* abort after reading the nvm in case RF Kill is on, we will complete
@@ -1027,10 +1029,14 @@ static int iwl_mvm_load_rt_fw(struct iwl_mvm *mvm)
if (ret)
return ret;
iwl_fw_dbg_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_EARLY);
ret = iwl_mvm_load_ucode_wait_alive(mvm, IWL_UCODE_REGULAR);
if (ret)
return ret;
iwl_fw_dbg_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_AFTER_ALIVE);
return iwl_init_paging(&mvm->fwrt, mvm->fwrt.cur_fw_img);
}
@@ -1059,11 +1065,13 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
if (ret)
IWL_ERR(mvm, "Failed to initialize Smart Fifo\n");
mvm->fwrt.dump.conf = FW_DBG_INVALID;
/* if we have a destination, assume EARLY START */
if (mvm->fw->dbg.dest_tlv)
mvm->fwrt.dump.conf = FW_DBG_START_FROM_ALIVE;
iwl_fw_start_dbg_conf(&mvm->fwrt, FW_DBG_START_FROM_ALIVE);
if (!mvm->trans->ini_valid) {
mvm->fwrt.dump.conf = FW_DBG_INVALID;
/* if we have a destination, assume EARLY START */
if (mvm->fw->dbg.dest_tlv)
mvm->fwrt.dump.conf = FW_DBG_START_FROM_ALIVE;
iwl_fw_start_dbg_conf(&mvm->fwrt, FW_DBG_START_FROM_ALIVE);
}
ret = iwl_send_tx_ant_cfg(mvm, iwl_mvm_get_valid_tx_ant(mvm));
if (ret)

View File

@@ -1532,6 +1532,8 @@ void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
IEEE80211_IFACE_ITER_NORMAL,
iwl_mvm_beacon_loss_iterator,
mb);
iwl_fw_dbg_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_MISSED_BEACONS);
}
void iwl_mvm_rx_stored_beacon_notif(struct iwl_mvm *mvm,

View File

@@ -1129,6 +1129,8 @@ int __iwl_mvm_mac_start(struct iwl_mvm *mvm)
}
ret = iwl_mvm_up(mvm);
iwl_fw_dbg_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_POST_INIT);
if (ret && test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
/* Something went wrong - we need to finish some cleanup
* that normally iwl_mvm_mac_restart_complete() below
@@ -2021,7 +2023,13 @@ static void iwl_mvm_cfg_he_sta(struct iwl_mvm *mvm,
if (sta->he_cap.he_cap_elem.mac_cap_info[4] & IEEE80211_HE_MAC_CAP4_BQR)
sta_ctxt_cmd.htc_flags |= cpu_to_le32(IWL_HE_HTC_BQR_SUPP);
/* If PPE Thresholds exist, parse them into a FW-familiar format */
/*
* Initialize the PPE thresholds to "None" (7), as described in Table
* 9-262ac of 80211.ax/D3.0.
*/
memset(&sta_ctxt_cmd.pkt_ext, 7, sizeof(sta_ctxt_cmd.pkt_ext));
/* If PPE Thresholds exist, parse them into a FW-familiar format. */
if (sta->he_cap.he_cap_elem.phy_cap_info[6] &
IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) {
u8 nss = (sta->he_cap.ppe_thres[0] &
@@ -3386,7 +3394,7 @@ static bool iwl_mvm_rx_aux_roc(struct iwl_notif_wait_data *notif_wait,
resp = (void *)pkt->data;
IWL_DEBUG_TE(mvm,
"Aux ROC: Recieved response from ucode: status=%d uid=%d\n",
"Aux ROC: Received response from ucode: status=%d uid=%d\n",
resp->status, resp->event_unique_id);
te_data->uid = le32_to_cpu(resp->event_unique_id);

View File

@@ -1556,6 +1556,8 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi,
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_monitor_ndp(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,
struct iwl_rx_cmd_buffer *rxb, int queue);
int iwl_mvm_notify_rx_queue(struct iwl_mvm *mvm, u32 rxq_mask,

View File

@@ -1073,6 +1073,8 @@ static void iwl_mvm_rx_mq(struct iwl_op_mode *op_mode,
iwl_mvm_rx_queue_notif(mvm, rxb, 0);
else if (cmd == WIDE_ID(LEGACY_GROUP, FRAME_RELEASE))
iwl_mvm_rx_frame_release(mvm, napi, rxb, 0);
else if (cmd == WIDE_ID(DATA_PATH_GROUP, RX_NO_DATA_NOTIF))
iwl_mvm_rx_monitor_ndp(mvm, napi, rxb, 0);
else
iwl_mvm_rx_common(mvm, rxb, pkt);
}

View File

@@ -593,31 +593,28 @@ static void iwl_mvm_stat_iterator(void *_data, u8 *mac,
int hyst = vif->bss_conf.cqm_rssi_hyst;
u16 id = le32_to_cpu(data->mac_id);
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
u16 vif_id = mvmvif->id;
/* This doesn't need the MAC ID check since it's not taking the
* data copied into the "data" struct, but rather the data from
* the notification directly.
*/
if (data->general) {
u16 vif_id = mvmvif->id;
if (iwl_mvm_is_cdb_supported(mvm)) {
struct mvm_statistics_general_cdb *general =
data->general;
if (iwl_mvm_is_cdb_supported(mvm)) {
struct mvm_statistics_general_cdb *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];
} 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(general->beacon_counter[vif_id]);
mvmvif->beacon_stats.avg_signal =
-general->beacon_average_energy[vif_id];
}
if (mvmvif->id != id)

View File

@@ -200,7 +200,8 @@ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,
{
struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
if (iwl_mvm_check_pn(mvm, skb, queue, sta)) {
if (!(rx_status->flag & RX_FLAG_NO_PSDU) &&
iwl_mvm_check_pn(mvm, skb, queue, sta)) {
kfree_skb(skb);
} else {
unsigned int radiotap_len = 0;
@@ -863,68 +864,66 @@ static void iwl_mvm_flip_address(u8 *addr)
ether_addr_copy(addr, mac_addr);
}
static void iwl_mvm_decode_he_sigb(struct iwl_mvm *mvm,
struct iwl_rx_mpdu_desc *desc,
u32 rate_n_flags,
struct ieee80211_radiotap_he_mu *he_mu)
struct iwl_mvm_rx_phy_data {
enum iwl_rx_phy_info_type info_type;
__le32 d0, d1, d2, d3;
__le16 d4;
};
static void iwl_mvm_decode_he_mu_ext(struct iwl_mvm *mvm,
struct iwl_mvm_rx_phy_data *phy_data,
u32 rate_n_flags,
struct ieee80211_radiotap_he_mu *he_mu)
{
u32 sigb0, sigb1;
u16 sigb2;
u32 phy_data2 = le32_to_cpu(phy_data->d2);
u32 phy_data3 = le32_to_cpu(phy_data->d3);
u16 phy_data4 = le16_to_cpu(phy_data->d4);
if (mvm->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) {
sigb0 = le32_to_cpu(desc->v3.sigb_common0);
sigb1 = le32_to_cpu(desc->v3.sigb_common1);
} else {
sigb0 = le32_to_cpu(desc->v1.sigb_common0);
sigb1 = le32_to_cpu(desc->v1.sigb_common1);
}
sigb2 = le16_to_cpu(desc->sigb_common2);
if (FIELD_GET(IWL_RX_HE_SIGB_COMMON2_CH1_CRC_OK, sigb2)) {
if (FIELD_GET(IWL_RX_PHY_DATA4_HE_MU_EXT_CH1_CRC_OK, phy_data4)) {
he_mu->flags1 |=
cpu_to_le16(IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH1_RU_KNOWN |
IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH1_CTR_26T_RU_KNOWN);
he_mu->flags1 |=
le16_encode_bits(FIELD_GET(IWL_RX_HE_SIGB_COMMON2_CH1_CTR_RU,
sigb2),
le16_encode_bits(FIELD_GET(IWL_RX_PHY_DATA4_HE_MU_EXT_CH1_CTR_RU,
phy_data4),
IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH1_CTR_26T_RU);
he_mu->ru_ch1[0] = FIELD_GET(IWL_RX_HE_SIGB_COMMON0_CH1_RU0,
sigb0);
he_mu->ru_ch1[1] = FIELD_GET(IWL_RX_HE_SIGB_COMMON1_CH1_RU1,
sigb1);
he_mu->ru_ch1[2] = FIELD_GET(IWL_RX_HE_SIGB_COMMON0_CH1_RU2,
sigb0);
he_mu->ru_ch1[3] = FIELD_GET(IWL_RX_HE_SIGB_COMMON1_CH1_RU3,
sigb1);
he_mu->ru_ch1[0] = FIELD_GET(IWL_RX_PHY_DATA2_HE_MU_EXT_CH1_RU0,
phy_data2);
he_mu->ru_ch1[1] = FIELD_GET(IWL_RX_PHY_DATA3_HE_MU_EXT_CH1_RU1,
phy_data3);
he_mu->ru_ch1[2] = FIELD_GET(IWL_RX_PHY_DATA2_HE_MU_EXT_CH1_RU2,
phy_data2);
he_mu->ru_ch1[3] = FIELD_GET(IWL_RX_PHY_DATA3_HE_MU_EXT_CH1_RU3,
phy_data3);
}
if (FIELD_GET(IWL_RX_HE_SIGB_COMMON2_CH2_CRC_OK, sigb2) &&
if (FIELD_GET(IWL_RX_PHY_DATA4_HE_MU_EXT_CH2_CRC_OK, phy_data4) &&
(rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) != RATE_MCS_CHAN_WIDTH_20) {
he_mu->flags1 |=
cpu_to_le16(IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH2_RU_KNOWN |
IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH2_CTR_26T_RU_KNOWN);
he_mu->flags2 |=
le16_encode_bits(FIELD_GET(IWL_RX_HE_SIGB_COMMON2_CH2_CTR_RU,
sigb2),
le16_encode_bits(FIELD_GET(IWL_RX_PHY_DATA4_HE_MU_EXT_CH2_CTR_RU,
phy_data4),
IEEE80211_RADIOTAP_HE_MU_FLAGS2_CH2_CTR_26T_RU);
he_mu->ru_ch2[0] = FIELD_GET(IWL_RX_HE_SIGB_COMMON0_CH2_RU0,
sigb0);
he_mu->ru_ch2[1] = FIELD_GET(IWL_RX_HE_SIGB_COMMON1_CH2_RU1,
sigb1);
he_mu->ru_ch2[2] = FIELD_GET(IWL_RX_HE_SIGB_COMMON0_CH2_RU2,
sigb0);
he_mu->ru_ch2[3] = FIELD_GET(IWL_RX_HE_SIGB_COMMON1_CH2_RU3,
sigb1);
he_mu->ru_ch2[0] = FIELD_GET(IWL_RX_PHY_DATA2_HE_MU_EXT_CH2_RU0,
phy_data2);
he_mu->ru_ch2[1] = FIELD_GET(IWL_RX_PHY_DATA3_HE_MU_EXT_CH2_RU1,
phy_data3);
he_mu->ru_ch2[2] = FIELD_GET(IWL_RX_PHY_DATA2_HE_MU_EXT_CH2_RU2,
phy_data2);
he_mu->ru_ch2[3] = FIELD_GET(IWL_RX_PHY_DATA3_HE_MU_EXT_CH2_RU3,
phy_data3);
}
}
static void
iwl_mvm_decode_he_phy_ru_alloc(u64 he_phy_data, u32 rate_n_flags,
iwl_mvm_decode_he_phy_ru_alloc(struct iwl_mvm_rx_phy_data *phy_data,
u32 rate_n_flags,
struct ieee80211_radiotap_he *he,
struct ieee80211_radiotap_he_mu *he_mu,
struct ieee80211_rx_status *rx_status)
@@ -937,7 +936,7 @@ iwl_mvm_decode_he_phy_ru_alloc(u64 he_phy_data, u32 rate_n_flags,
* happen though as management frames where we need
* the TSF/timers are not be transmitted in HE-MU.
*/
u8 ru = FIELD_GET(IWL_RX_HE_PHY_RU_ALLOC_MASK, he_phy_data);
u8 ru = le32_get_bits(phy_data->d1, IWL_RX_PHY_DATA1_HE_RU_ALLOC_MASK);
u8 offs = 0;
rx_status->bw = RATE_INFO_BW_HE_RU;
@@ -976,7 +975,7 @@ iwl_mvm_decode_he_phy_ru_alloc(u64 he_phy_data, u32 rate_n_flags,
IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET);
he->data2 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_KNOWN |
IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET_KNOWN);
if (he_phy_data & IWL_RX_HE_PHY_RU_ALLOC_SEC80)
if (phy_data->d1 & cpu_to_le32(IWL_RX_PHY_DATA1_HE_RU_ALLOC_SEC80))
he->data2 |=
cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_SEC);
@@ -996,106 +995,122 @@ iwl_mvm_decode_he_phy_ru_alloc(u64 he_phy_data, u32 rate_n_flags,
}
static void iwl_mvm_decode_he_phy_data(struct iwl_mvm *mvm,
struct iwl_rx_mpdu_desc *desc,
struct iwl_mvm_rx_phy_data *phy_data,
struct ieee80211_radiotap_he *he,
struct ieee80211_radiotap_he_mu *he_mu,
struct ieee80211_rx_status *rx_status,
u64 he_phy_data, u32 rate_n_flags,
int queue)
u32 rate_n_flags, int queue)
{
u32 he_type = rate_n_flags & RATE_MCS_HE_TYPE_MSK;
bool sigb_data;
u16 d1known = IEEE80211_RADIOTAP_HE_DATA1_LDPC_XSYMSEG_KNOWN |
IEEE80211_RADIOTAP_HE_DATA1_UL_DL_KNOWN |
IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE_KNOWN |
IEEE80211_RADIOTAP_HE_DATA1_DOPPLER_KNOWN |
IEEE80211_RADIOTAP_HE_DATA1_BSS_COLOR_KNOWN;
u16 d2known = IEEE80211_RADIOTAP_HE_DATA2_PRE_FEC_PAD_KNOWN |
IEEE80211_RADIOTAP_HE_DATA2_PE_DISAMBIG_KNOWN |
IEEE80211_RADIOTAP_HE_DATA2_TXOP_KNOWN;
he->data1 |= cpu_to_le16(d1known);
he->data2 |= cpu_to_le16(d2known);
he->data3 |= le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_BSS_COLOR_MASK,
he_phy_data),
IEEE80211_RADIOTAP_HE_DATA3_BSS_COLOR);
he->data3 |= le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_UPLINK,
he_phy_data),
IEEE80211_RADIOTAP_HE_DATA3_UL_DL);
he->data3 |= le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_LDPC_EXT_SYM,
he_phy_data),
IEEE80211_RADIOTAP_HE_DATA3_LDPC_XSYMSEG);
he->data4 |= le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_SPATIAL_REUSE_MASK,
he_phy_data),
IEEE80211_RADIOTAP_HE_DATA4_SU_MU_SPTL_REUSE);
he->data5 |= le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_PRE_FEC_PAD_MASK,
he_phy_data),
IEEE80211_RADIOTAP_HE_DATA5_PRE_FEC_PAD);
he->data5 |= le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_PE_DISAMBIG,
he_phy_data),
IEEE80211_RADIOTAP_HE_DATA5_PE_DISAMBIG);
he->data6 |= le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_TXOP_DUR_MASK,
he_phy_data),
IEEE80211_RADIOTAP_HE_DATA6_TXOP);
he->data6 |= le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_DOPPLER,
he_phy_data),
IEEE80211_RADIOTAP_HE_DATA6_DOPPLER);
switch (he_type) {
case RATE_MCS_HE_TYPE_MU:
he_mu->flags1 |=
le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_MU_SIGB_DCM,
he_phy_data),
IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_DCM);
he_mu->flags1 |=
le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_MU_SIGB_MCS_MASK,
he_phy_data),
IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_MCS);
he_mu->flags2 |=
le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_MU_SIBG_SYM_OR_USER_NUM_MASK,
he_phy_data),
IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_SYMS_USERS);
he_mu->flags2 |=
le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_MU_SIGB_COMPRESSION,
he_phy_data),
IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_COMP);
he_mu->flags2 |=
le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_MU_PREAMBLE_PUNC_TYPE_MASK,
he_phy_data),
IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW);
sigb_data = FIELD_GET(IWL_RX_HE_PHY_INFO_TYPE_MASK,
he_phy_data) ==
IWL_RX_HE_PHY_INFO_TYPE_MU_EXT_INFO;
if (sigb_data)
iwl_mvm_decode_he_sigb(mvm, desc, rate_n_flags, he_mu);
switch (phy_data->info_type) {
case IWL_RX_PHY_INFO_TYPE_NONE:
case IWL_RX_PHY_INFO_TYPE_CCK:
case IWL_RX_PHY_INFO_TYPE_OFDM_LGCY:
case IWL_RX_PHY_INFO_TYPE_HT:
case IWL_RX_PHY_INFO_TYPE_VHT_SU:
case IWL_RX_PHY_INFO_TYPE_VHT_MU:
return;
case IWL_RX_PHY_INFO_TYPE_HE_TB_EXT:
he->data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE_KNOWN |
IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE2_KNOWN |
IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE3_KNOWN |
IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE4_KNOWN);
he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d0,
IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE1),
IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE1);
he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d0,
IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE2),
IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE2);
he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d0,
IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE3),
IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE3);
he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d0,
IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE4),
IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE4);
/* fall through */
case RATE_MCS_HE_TYPE_TRIG:
he->data2 |=
cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_NUM_LTF_SYMS_KNOWN);
he->data5 |=
le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_HE_LTF_NUM_MASK,
he_phy_data),
IEEE80211_RADIOTAP_HE_DATA5_NUM_LTF_SYMS);
break;
case RATE_MCS_HE_TYPE_SU:
case RATE_MCS_HE_TYPE_EXT_SU:
he->data1 |=
cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_BEAM_CHANGE_KNOWN);
he->data3 |=
le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_BEAM_CHNG,
he_phy_data),
IEEE80211_RADIOTAP_HE_DATA3_BEAM_CHANGE);
case IWL_RX_PHY_INFO_TYPE_HE_SU:
case IWL_RX_PHY_INFO_TYPE_HE_MU:
case IWL_RX_PHY_INFO_TYPE_HE_MU_EXT:
case IWL_RX_PHY_INFO_TYPE_HE_TB:
/* HE common */
he->data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_LDPC_XSYMSEG_KNOWN |
IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE_KNOWN |
IEEE80211_RADIOTAP_HE_DATA1_DOPPLER_KNOWN |
IEEE80211_RADIOTAP_HE_DATA1_BSS_COLOR_KNOWN);
he->data2 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRE_FEC_PAD_KNOWN |
IEEE80211_RADIOTAP_HE_DATA2_PE_DISAMBIG_KNOWN |
IEEE80211_RADIOTAP_HE_DATA2_TXOP_KNOWN |
IEEE80211_RADIOTAP_HE_DATA2_NUM_LTF_SYMS_KNOWN);
he->data3 |= le16_encode_bits(le32_get_bits(phy_data->d0,
IWL_RX_PHY_DATA0_HE_BSS_COLOR_MASK),
IEEE80211_RADIOTAP_HE_DATA3_BSS_COLOR);
if (phy_data->info_type != IWL_RX_PHY_INFO_TYPE_HE_TB &&
phy_data->info_type != IWL_RX_PHY_INFO_TYPE_HE_TB_EXT) {
he->data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_UL_DL_KNOWN);
he->data3 |= le16_encode_bits(le32_get_bits(phy_data->d0,
IWL_RX_PHY_DATA0_HE_UPLINK),
IEEE80211_RADIOTAP_HE_DATA3_UL_DL);
}
he->data3 |= le16_encode_bits(le32_get_bits(phy_data->d0,
IWL_RX_PHY_DATA0_HE_LDPC_EXT_SYM),
IEEE80211_RADIOTAP_HE_DATA3_LDPC_XSYMSEG);
he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d0,
IWL_RX_PHY_DATA0_HE_SPATIAL_REUSE_MASK),
IEEE80211_RADIOTAP_HE_DATA4_SU_MU_SPTL_REUSE);
he->data5 |= le16_encode_bits(le32_get_bits(phy_data->d0,
IWL_RX_PHY_DATA0_HE_PRE_FEC_PAD_MASK),
IEEE80211_RADIOTAP_HE_DATA5_PRE_FEC_PAD);
he->data5 |= le16_encode_bits(le32_get_bits(phy_data->d0,
IWL_RX_PHY_DATA0_HE_PE_DISAMBIG),
IEEE80211_RADIOTAP_HE_DATA5_PE_DISAMBIG);
he->data5 |= le16_encode_bits(le32_get_bits(phy_data->d1,
IWL_RX_PHY_DATA1_HE_LTF_NUM_MASK),
IEEE80211_RADIOTAP_HE_DATA5_NUM_LTF_SYMS);
he->data6 |= le16_encode_bits(le32_get_bits(phy_data->d0,
IWL_RX_PHY_DATA0_HE_TXOP_DUR_MASK),
IEEE80211_RADIOTAP_HE_DATA6_TXOP);
he->data6 |= le16_encode_bits(le32_get_bits(phy_data->d0,
IWL_RX_PHY_DATA0_HE_DOPPLER),
IEEE80211_RADIOTAP_HE_DATA6_DOPPLER);
break;
}
switch (FIELD_GET(IWL_RX_HE_PHY_INFO_TYPE_MASK, he_phy_data)) {
case IWL_RX_HE_PHY_INFO_TYPE_MU:
case IWL_RX_HE_PHY_INFO_TYPE_MU_EXT_INFO:
case IWL_RX_HE_PHY_INFO_TYPE_TB:
iwl_mvm_decode_he_phy_ru_alloc(he_phy_data, rate_n_flags,
switch (phy_data->info_type) {
case IWL_RX_PHY_INFO_TYPE_HE_MU_EXT:
he_mu->flags1 |=
le16_encode_bits(le16_get_bits(phy_data->d4,
IWL_RX_PHY_DATA4_HE_MU_EXT_SIGB_DCM),
IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_DCM);
he_mu->flags1 |=
le16_encode_bits(le16_get_bits(phy_data->d4,
IWL_RX_PHY_DATA4_HE_MU_EXT_SIGB_MCS_MASK),
IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_MCS);
he_mu->flags2 |=
le16_encode_bits(le16_get_bits(phy_data->d4,
IWL_RX_PHY_DATA4_HE_MU_EXT_PREAMBLE_PUNC_TYPE_MASK),
IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW);
iwl_mvm_decode_he_mu_ext(mvm, phy_data, rate_n_flags, he_mu);
/* fall through */
case IWL_RX_PHY_INFO_TYPE_HE_MU:
he_mu->flags2 |=
le16_encode_bits(le32_get_bits(phy_data->d1,
IWL_RX_PHY_DATA1_HE_MU_SIBG_SYM_OR_USER_NUM_MASK),
IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_SYMS_USERS);
he_mu->flags2 |=
le16_encode_bits(le32_get_bits(phy_data->d1,
IWL_RX_PHY_DATA1_HE_MU_SIGB_COMPRESSION),
IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_COMP);
/* fall through */
case IWL_RX_PHY_INFO_TYPE_HE_TB:
case IWL_RX_PHY_INFO_TYPE_HE_TB_EXT:
iwl_mvm_decode_he_phy_ru_alloc(phy_data, rate_n_flags,
he, he_mu, rx_status);
break;
case IWL_RX_PHY_INFO_TYPE_HE_SU:
he->data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_BEAM_CHANGE_KNOWN);
he->data3 |= le16_encode_bits(le32_get_bits(phy_data->d0,
IWL_RX_PHY_DATA0_HE_BEAM_CHNG),
IEEE80211_RADIOTAP_HE_DATA3_BEAM_CHANGE);
break;
default:
/* nothing */
break;
@@ -1103,13 +1118,10 @@ static void iwl_mvm_decode_he_phy_data(struct iwl_mvm *mvm,
}
static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb,
struct iwl_rx_mpdu_desc *desc,
struct iwl_mvm_rx_phy_data *phy_data,
u32 rate_n_flags, u16 phy_info, int queue)
{
struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
/* this is invalid e.g. because puncture type doesn't allow 0b11 */
#define HE_PHY_DATA_INVAL ((u64)-1)
u64 he_phy_data = HE_PHY_DATA_INVAL;
struct ieee80211_radiotap_he *he = NULL;
struct ieee80211_radiotap_he_mu *he_mu = NULL;
u32 he_type = rate_n_flags & RATE_MCS_HE_TYPE_MSK;
@@ -1136,49 +1148,41 @@ static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb,
radiotap_len += sizeof(known);
rx_status->flag |= RX_FLAG_RADIOTAP_HE;
if (phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD) {
if (mvm->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560)
he_phy_data = le64_to_cpu(desc->v3.he_phy_data);
else
he_phy_data = le64_to_cpu(desc->v1.he_phy_data);
if (he_type == RATE_MCS_HE_TYPE_MU) {
he_mu = skb_put_data(skb, &mu_known, sizeof(mu_known));
radiotap_len += sizeof(mu_known);
rx_status->flag |= RX_FLAG_RADIOTAP_HE_MU;
}
if (phy_data->info_type == IWL_RX_PHY_INFO_TYPE_HE_MU ||
phy_data->info_type == IWL_RX_PHY_INFO_TYPE_HE_MU_EXT) {
he_mu = skb_put_data(skb, &mu_known, sizeof(mu_known));
radiotap_len += sizeof(mu_known);
rx_status->flag |= RX_FLAG_RADIOTAP_HE_MU;
}
/* temporarily hide the radiotap data */
__skb_pull(skb, radiotap_len);
if (he_phy_data != HE_PHY_DATA_INVAL &&
he_type == RATE_MCS_HE_TYPE_SU) {
if (phy_data->info_type == IWL_RX_PHY_INFO_TYPE_HE_SU) {
/* report the AMPDU-EOF bit on single frames */
if (!queue && !(phy_info & IWL_RX_MPDU_PHY_AMPDU)) {
rx_status->flag |= RX_FLAG_AMPDU_DETAILS;
rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT_KNOWN;
if (FIELD_GET(IWL_RX_HE_PHY_DELIM_EOF, he_phy_data))
if (phy_data->d0 & cpu_to_le32(IWL_RX_PHY_DATA0_HE_DELIM_EOF))
rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT;
}
}
if (he_phy_data != HE_PHY_DATA_INVAL)
iwl_mvm_decode_he_phy_data(mvm, desc, he, he_mu, rx_status,
he_phy_data, rate_n_flags, queue);
if (phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD)
iwl_mvm_decode_he_phy_data(mvm, phy_data, he, he_mu, rx_status,
rate_n_flags, queue);
/* update aggregation data for monitor sake on default queue */
if (!queue && (phy_info & IWL_RX_MPDU_PHY_AMPDU)) {
if (!queue && (phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD) &&
(phy_info & IWL_RX_MPDU_PHY_AMPDU)) {
bool toggle_bit = phy_info & IWL_RX_MPDU_PHY_AMPDU_TOGGLE;
/* toggle is switched whenever new aggregation starts */
if (toggle_bit != mvm->ampdu_toggle &&
he_phy_data != HE_PHY_DATA_INVAL &&
(he_type == RATE_MCS_HE_TYPE_MU ||
he_type == RATE_MCS_HE_TYPE_SU)) {
rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT_KNOWN;
if (FIELD_GET(IWL_RX_HE_PHY_DELIM_EOF,
he_phy_data))
if (phy_data->d0 & cpu_to_le32(IWL_RX_PHY_DATA0_HE_DELIM_EOF))
rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT;
}
}
@@ -1261,43 +1265,34 @@ static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb,
break;
}
he->data5 |= le16_encode_bits(ltf, IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE);
he->data5 |= le16_encode_bits(ltf,
IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE);
}
if (he_type == RATE_MCS_HE_TYPE_SU ||
he_type == RATE_MCS_HE_TYPE_EXT_SU) {
u16 val;
static void iwl_mvm_decode_lsig(struct sk_buff *skb,
struct iwl_mvm_rx_phy_data *phy_data)
{
struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
struct ieee80211_radiotap_lsig *lsig;
/* LTF syms correspond to streams */
he->data2 |=
cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_NUM_LTF_SYMS_KNOWN);
switch (rx_status->nss) {
case 1:
val = 0;
break;
case 2:
val = 1;
break;
case 3:
case 4:
val = 2;
break;
case 5:
case 6:
val = 3;
break;
case 7:
case 8:
val = 4;
break;
default:
WARN_ONCE(1, "invalid nss: %d\n",
rx_status->nss);
val = 0;
}
he->data5 |=
le16_encode_bits(val,
IEEE80211_RADIOTAP_HE_DATA5_NUM_LTF_SYMS);
switch (phy_data->info_type) {
case IWL_RX_PHY_INFO_TYPE_HT:
case IWL_RX_PHY_INFO_TYPE_VHT_SU:
case IWL_RX_PHY_INFO_TYPE_VHT_MU:
case IWL_RX_PHY_INFO_TYPE_HE_TB_EXT:
case IWL_RX_PHY_INFO_TYPE_HE_SU:
case IWL_RX_PHY_INFO_TYPE_HE_MU:
case IWL_RX_PHY_INFO_TYPE_HE_MU_EXT:
case IWL_RX_PHY_INFO_TYPE_HE_TB:
lsig = skb_put(skb, sizeof(*lsig));
lsig->data1 = cpu_to_le16(IEEE80211_RADIOTAP_LSIG_DATA1_LENGTH_KNOWN);
lsig->data2 = le16_encode_bits(le32_get_bits(phy_data->d1,
IWL_RX_PHY_DATA1_LSIG_LEN_MASK),
IEEE80211_RADIOTAP_LSIG_DATA2_LENGTH);
rx_status->flag |= RX_FLAG_RADIOTAP_LSIG;
break;
default:
break;
}
}
@@ -1315,6 +1310,10 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
struct sk_buff *skb;
u8 crypt_len = 0, channel, energy_a, energy_b;
size_t desc_size;
struct iwl_mvm_rx_phy_data phy_data = {
.d4 = desc->phy_data4,
.info_type = IWL_RX_PHY_INFO_TYPE_NONE,
};
if (unlikely(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)))
return;
@@ -1326,6 +1325,11 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
energy_a = desc->v3.energy_a;
energy_b = desc->v3.energy_b;
desc_size = sizeof(*desc);
phy_data.d0 = desc->v3.phy_data0;
phy_data.d1 = desc->v3.phy_data1;
phy_data.d2 = desc->v3.phy_data2;
phy_data.d3 = desc->v3.phy_data3;
} else {
rate_n_flags = le32_to_cpu(desc->v1.rate_n_flags);
channel = desc->v1.channel;
@@ -1333,8 +1337,18 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
energy_a = desc->v1.energy_a;
energy_b = desc->v1.energy_b;
desc_size = IWL_RX_DESC_SIZE_V1;
phy_data.d0 = desc->v1.phy_data0;
phy_data.d1 = desc->v1.phy_data1;
phy_data.d2 = desc->v1.phy_data2;
phy_data.d3 = desc->v1.phy_data3;
}
if (phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD)
phy_data.info_type =
le32_get_bits(phy_data.d1,
IWL_RX_PHY_DATA1_INFO_TYPE_MASK);
hdr = (void *)(pkt->data + desc_size);
/* Dont use dev_alloc_skb(), we'll have enough headroom once
* ieee80211_hdr pulled.
@@ -1373,7 +1387,10 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
}
if (rate_n_flags & RATE_MCS_HE_MSK)
iwl_mvm_rx_he(mvm, skb, desc, rate_n_flags, phy_info, queue);
iwl_mvm_rx_he(mvm, skb, &phy_data, rate_n_flags,
phy_info, queue);
iwl_mvm_decode_lsig(skb, &phy_data);
rx_status = IEEE80211_SKB_RXCB(skb);
@@ -1590,6 +1607,129 @@ out:
rcu_read_unlock();
}
void iwl_mvm_rx_monitor_ndp(struct iwl_mvm *mvm, struct napi_struct *napi,
struct iwl_rx_cmd_buffer *rxb, int queue)
{
struct ieee80211_rx_status *rx_status;
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_rx_no_data *desc = (void *)pkt->data;
u32 rate_n_flags = le32_to_cpu(desc->rate);
u32 gp2_on_air_rise = le32_to_cpu(desc->on_air_rise_time);
u32 rssi = le32_to_cpu(desc->rssi);
u32 info_type = le32_to_cpu(desc->info) & RX_NO_DATA_INFO_TYPE_MSK;
u16 phy_info = IWL_RX_MPDU_PHY_TSF_OVERLOAD;
struct ieee80211_sta *sta = NULL;
struct sk_buff *skb;
u8 channel, energy_a, energy_b;
struct iwl_mvm_rx_phy_data phy_data = {
.d0 = desc->phy_info[0],
.info_type = IWL_RX_PHY_INFO_TYPE_NONE,
};
if (unlikely(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)))
return;
/* Currently only NDP type is supported */
if (info_type != RX_NO_DATA_INFO_TYPE_NDP)
return;
energy_a = (rssi & RX_NO_DATA_CHAIN_A_MSK) >> RX_NO_DATA_CHAIN_A_POS;
energy_b = (rssi & RX_NO_DATA_CHAIN_B_MSK) >> RX_NO_DATA_CHAIN_B_POS;
channel = (rssi & RX_NO_DATA_CHANNEL_MSK) >> RX_NO_DATA_CHANNEL_POS;
phy_data.info_type =
le32_get_bits(desc->phy_info[1],
IWL_RX_PHY_DATA1_INFO_TYPE_MASK);
/* Dont use dev_alloc_skb(), we'll have enough headroom once
* ieee80211_hdr pulled.
*/
skb = alloc_skb(128, GFP_ATOMIC);
if (!skb) {
IWL_ERR(mvm, "alloc_skb failed\n");
return;
}
rx_status = IEEE80211_SKB_RXCB(skb);
/* 0-length PSDU */
rx_status->flag |= RX_FLAG_NO_PSDU;
/* currently this is the only type for which we get this notif */
rx_status->zero_length_psdu_type =
IEEE80211_RADIOTAP_ZERO_LEN_PSDU_SOUNDING;
/* This may be overridden by iwl_mvm_rx_he() to HE_RU */
switch (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) {
case RATE_MCS_CHAN_WIDTH_20:
break;
case RATE_MCS_CHAN_WIDTH_40:
rx_status->bw = RATE_INFO_BW_40;
break;
case RATE_MCS_CHAN_WIDTH_80:
rx_status->bw = RATE_INFO_BW_80;
break;
case RATE_MCS_CHAN_WIDTH_160:
rx_status->bw = RATE_INFO_BW_160;
break;
}
if (rate_n_flags & RATE_MCS_HE_MSK)
iwl_mvm_rx_he(mvm, skb, &phy_data, rate_n_flags,
phy_info, queue);
iwl_mvm_decode_lsig(skb, &phy_data);
rx_status->device_timestamp = gp2_on_air_rise;
rx_status->band = channel > 14 ? NL80211_BAND_5GHZ :
NL80211_BAND_2GHZ;
rx_status->freq = ieee80211_channel_to_frequency(channel,
rx_status->band);
iwl_mvm_get_signal_strength(mvm, rx_status, rate_n_flags, energy_a,
energy_b);
rcu_read_lock();
if (!(rate_n_flags & RATE_MCS_CCK_MSK) &&
rate_n_flags & RATE_MCS_SGI_MSK)
rx_status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
if (rate_n_flags & RATE_HT_MCS_GF_MSK)
rx_status->enc_flags |= RX_ENC_FLAG_HT_GF;
if (rate_n_flags & RATE_MCS_LDPC_MSK)
rx_status->enc_flags |= RX_ENC_FLAG_LDPC;
if (rate_n_flags & RATE_MCS_HT_MSK) {
u8 stbc = (rate_n_flags & RATE_MCS_STBC_MSK) >>
RATE_MCS_STBC_POS;
rx_status->encoding = RX_ENC_HT;
rx_status->rate_idx = rate_n_flags & RATE_HT_MCS_INDEX_MSK;
rx_status->enc_flags |= stbc << RX_ENC_FLAG_STBC_SHIFT;
} else if (rate_n_flags & RATE_MCS_VHT_MSK) {
u8 stbc = (rate_n_flags & RATE_MCS_STBC_MSK) >>
RATE_MCS_STBC_POS;
rx_status->nss =
((rate_n_flags & RATE_VHT_MCS_NSS_MSK) >>
RATE_VHT_MCS_NSS_POS) + 1;
rx_status->rate_idx = rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK;
rx_status->encoding = RX_ENC_VHT;
rx_status->enc_flags |= stbc << RX_ENC_FLAG_STBC_SHIFT;
if (rate_n_flags & RATE_MCS_BF_MSK)
rx_status->enc_flags |= RX_ENC_FLAG_BF;
} else if (!(rate_n_flags & RATE_MCS_HE_MSK)) {
int rate = iwl_mvm_legacy_rate_to_mac80211_idx(rate_n_flags,
rx_status->band);
if (WARN(rate < 0 || rate > 0xFF,
"Invalid rate flags 0x%x, band %d,\n",
rate_n_flags, rx_status->band)) {
kfree_skb(skb);
goto out;
}
rx_status->rate_idx = rate;
}
iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb, queue, sta);
out:
rcu_read_unlock();
}
void iwl_mvm_rx_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,
struct iwl_rx_cmd_buffer *rxb, int queue)
{

View File

@@ -1893,6 +1893,8 @@ void iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm,
mvm->last_ebs_successful = false;
mvm->scan_uid_status[uid] = 0;
iwl_fw_dbg_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_SCAN_COMPLETE);
}
void iwl_mvm_rx_umac_scan_iter_complete_notif(struct iwl_mvm *mvm,

View File

@@ -1254,6 +1254,7 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm,
spin_lock_bh(&mvmsta->lock);
tfd_queue_mask = mvmsta->tfd_queue_msk;
ssn = IEEE80211_SEQ_TO_SN(mvmsta->tid_data[tid].seq_number);
spin_unlock_bh(&mvmsta->lock);
/*
@@ -1340,13 +1341,8 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm,
}
}
ssn = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));
inc_ssn = iwl_mvm_enable_txq(mvm, queue, mac_queue,
ssn, &cfg, wdg_timeout);
if (inc_ssn) {
ssn = (ssn + 1) & IEEE80211_SCTL_SEQ;
le16_add_cpu(&hdr->seq_ctrl, 0x10);
}
/*
* Mark queue as shared in transport if shared
@@ -1363,8 +1359,10 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm,
* this ra/tid in our Tx path since we stop the Qdisc when we
* need to allocate a new TFD queue.
*/
if (inc_ssn)
if (inc_ssn) {
mvmsta->tid_data[tid].seq_number += 0x10;
ssn = (ssn + 1) & IEEE80211_SCTL_SEQ;
}
mvmsta->tid_data[tid].txq_id = queue;
mvmsta->tfd_queue_msk |= BIT(queue);
queue_state = mvmsta->tid_data[tid].state;

View File

@@ -708,22 +708,12 @@ out:
int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb);
struct ieee80211_tx_info info;
struct iwl_device_cmd *dev_cmd;
u8 sta_id;
int hdrlen = ieee80211_hdrlen(hdr->frame_control);
__le16 fc = hdr->frame_control;
int queue;
/* IWL_MVM_OFFCHANNEL_QUEUE is used for ROC packets that can be used
* in 2 different types of vifs, P2P & STATION. P2P uses the offchannel
* queue. STATION (HS2.0) uses the auxiliary context of the FW,
* and hence needs to be sent on the aux queue
*/
if (skb_info->hw_queue == IWL_MVM_OFFCHANNEL_QUEUE &&
skb_info->control.vif->type == NL80211_IFTYPE_STATION)
skb_info->hw_queue = mvm->aux_queue;
int queue = -1;
memcpy(&info, skb->cb, sizeof(info));
@@ -735,18 +725,6 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
info.hw_queue != info.control.vif->cab_queue)))
return -1;
queue = info.hw_queue;
/*
* If the interface on which the frame is sent is the P2P_DEVICE
* or an AP/GO interface use the broadcast station associated
* with it; otherwise if the interface is a managed interface
* use the AP station associated with it for multicast traffic
* (this is not possible for unicast packets as a TLDS discovery
* response are sent without a station entry); otherwise use the
* AUX station.
*/
sta_id = mvm->aux_sta.sta_id;
if (info.control.vif) {
struct iwl_mvm_vif *mvmvif =
iwl_mvm_vif_from_mac80211(info.control.vif);
@@ -761,20 +739,28 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
queue = iwl_mvm_get_ctrl_vif_queue(mvm, &info,
hdr->frame_control);
if (queue < 0)
return -1;
} else if (info.control.vif->type == NL80211_IFTYPE_STATION &&
is_multicast_ether_addr(hdr->addr1)) {
u8 ap_sta_id = READ_ONCE(mvmvif->ap_sta_id);
if (ap_sta_id != IWL_MVM_INVALID_STA)
sta_id = ap_sta_id;
} else if (info.control.vif->type == NL80211_IFTYPE_MONITOR) {
queue = mvm->snif_queue;
sta_id = mvm->snif_sta.sta_id;
} else if (info.control.vif->type == NL80211_IFTYPE_STATION &&
info.hw_queue == IWL_MVM_OFFCHANNEL_QUEUE) {
/*
* IWL_MVM_OFFCHANNEL_QUEUE is used for ROC packets
* that can be used in 2 different types of vifs, P2P &
* STATION.
* P2P uses the offchannel queue.
* STATION (HS2.0) uses the auxiliary context of the FW,
* and hence needs to be sent on the aux queue.
*/
sta_id = mvm->aux_sta.sta_id;
queue = mvm->aux_queue;
}
}
if (queue < 0)
return -1;
if (unlikely(ieee80211_is_probe_resp(fc)))
iwl_mvm_probe_resp_set_noa(mvm, skb);
@@ -1478,7 +1464,6 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
iwl_mvm_get_agg_status(mvm, tx_resp);
u32 status = le16_to_cpu(agg_status->status);
u16 ssn = iwl_mvm_get_scd_ssn(mvm, tx_resp);
struct iwl_mvm_sta *mvmsta;
struct sk_buff_head skbs;
u8 skb_freed = 0;
u8 lq_color;
@@ -1626,7 +1611,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
goto out;
if (!IS_ERR(sta)) {
mvmsta = iwl_mvm_sta_from_mac80211(sta);
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
iwl_mvm_tx_airtime(mvm, mvmsta,
le16_to_cpu(tx_resp->wireless_media_time));
@@ -1689,10 +1674,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
mvmsta->next_status_eosp = false;
ieee80211_sta_eosp(sta);
}
} else {
mvmsta = NULL;
}
out:
rcu_read_unlock();
}
@@ -1835,8 +1817,6 @@ static void iwl_mvm_tx_reclaim(struct iwl_mvm *mvm, int sta_id, int tid,
return;
}
spin_lock_bh(&mvmsta->lock);
__skb_queue_head_init(&reclaimed_skbs);
/*
@@ -1846,6 +1826,8 @@ static void iwl_mvm_tx_reclaim(struct iwl_mvm *mvm, int sta_id, int tid,
*/
iwl_trans_reclaim(mvm->trans, txq, index, &reclaimed_skbs);
spin_lock_bh(&mvmsta->lock);
tid_data->next_reclaimed = index;
iwl_mvm_check_ratid_empty(mvm, sta, tid);

View File

@@ -540,6 +540,9 @@ static void iwl_mvm_dump_lmac_error_log(struct iwl_mvm *mvm, u32 base)
iwl_trans_read_mem_bytes(trans, base, &table, sizeof(table));
if (table.valid)
mvm->fwrt.dump.rt_status = table.error_id;
if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) {
IWL_ERR(trans, "Start IWL Error Log Dump:\n");
IWL_ERR(trans, "Status: 0x%08lX, count: %d\n",
@@ -1378,6 +1381,7 @@ void iwl_mvm_pause_tcm(struct iwl_mvm *mvm, bool with_cancel)
void iwl_mvm_resume_tcm(struct iwl_mvm *mvm)
{
int mac;
bool low_latency = false;
spin_lock_bh(&mvm->tcm.lock);
mvm->tcm.ts = jiffies;
@@ -1389,10 +1393,23 @@ void iwl_mvm_resume_tcm(struct iwl_mvm *mvm)
memset(&mdata->tx.pkts, 0, sizeof(mdata->tx.pkts));
memset(&mdata->rx.airtime, 0, sizeof(mdata->rx.airtime));
memset(&mdata->tx.airtime, 0, sizeof(mdata->tx.airtime));
if (mvm->tcm.result.low_latency[mac])
low_latency = true;
}
/* The TCM data needs to be reset before "paused" flag changes */
smp_mb();
mvm->tcm.paused = false;
/*
* if the current load is not low or low latency is active, force
* re-evaluation to cover the case of no traffic.
*/
if (mvm->tcm.result.global_load > IWL_MVM_TRAFFIC_LOW)
schedule_delayed_work(&mvm->tcm.work, MVM_TCM_PERIOD);
else if (low_latency)
schedule_delayed_work(&mvm->tcm.work, MVM_LL_PERIOD);
spin_unlock_bh(&mvm->tcm.lock);
}