Merge ath-next from git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git

ath.git patches for v5.16. Major changes:

ath9k

* load calibration data and pci init values via nvmem subsystem

ath11k

* include channel rx and tx time in survey dump statistics

* support for setting fixed Wi-Fi 6 rates from user space

* support for 80P80 and 160 MHz bandwidths

* spectral scan support for QCN9074

* support for calibration data files per radio

* support for calibration data via eeprom

* support for rx decapsulation offload (data frames in 802.3 format)

* support channel 2 in 6 GHz band

ath10k

* include frame time stamp in beacon and probe response frames

wcn36xx

* enable Idle Mode Power Save (IMPS) to reduce power consumption during idle
This commit is contained in:
Kalle Valo 2021-10-05 09:23:01 +03:00
commit b3fcf9c5fa
41 changed files with 4900 additions and 2671 deletions

View File

@ -993,8 +993,12 @@ static void ath10k_mac_vif_beacon_cleanup(struct ath10k_vif *arvif)
ath10k_mac_vif_beacon_free(arvif);
if (arvif->beacon_buf) {
dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN,
arvif->beacon_buf, arvif->beacon_paddr);
if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL)
kfree(arvif->beacon_buf);
else
dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN,
arvif->beacon_buf,
arvif->beacon_paddr);
arvif->beacon_buf = NULL;
}
}
@ -5576,10 +5580,17 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
if (vif->type == NL80211_IFTYPE_ADHOC ||
vif->type == NL80211_IFTYPE_MESH_POINT ||
vif->type == NL80211_IFTYPE_AP) {
arvif->beacon_buf = dma_alloc_coherent(ar->dev,
IEEE80211_MAX_FRAME_LEN,
&arvif->beacon_paddr,
GFP_ATOMIC);
if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL) {
arvif->beacon_buf = kmalloc(IEEE80211_MAX_FRAME_LEN,
GFP_KERNEL);
arvif->beacon_paddr = (dma_addr_t)arvif->beacon_buf;
} else {
arvif->beacon_buf =
dma_alloc_coherent(ar->dev,
IEEE80211_MAX_FRAME_LEN,
&arvif->beacon_paddr,
GFP_ATOMIC);
}
if (!arvif->beacon_buf) {
ret = -ENOMEM;
ath10k_warn(ar, "failed to allocate beacon buffer: %d\n",
@ -5794,8 +5805,12 @@ err_vdev_delete:
err:
if (arvif->beacon_buf) {
dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN,
arvif->beacon_buf, arvif->beacon_paddr);
if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL)
kfree(arvif->beacon_buf);
else
dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN,
arvif->beacon_buf,
arvif->beacon_paddr);
arvif->beacon_buf = NULL;
}

View File

@ -1363,8 +1363,11 @@ static void ath10k_rx_indication_async_work(struct work_struct *work)
ep->ep_ops.ep_rx_complete(ar, skb);
}
if (test_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags))
if (test_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags)) {
local_bh_disable();
napi_schedule(&ar->napi);
local_bh_enable();
}
}
static int ath10k_sdio_read_rtc_state(struct ath10k_sdio *ar_sdio, unsigned char *state)

View File

@ -2610,6 +2610,10 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
if (ieee80211_is_beacon(hdr->frame_control))
ath10k_mac_handle_beacon(ar, skb);
if (ieee80211_is_beacon(hdr->frame_control) ||
ieee80211_is_probe_resp(hdr->frame_control))
status->boottime_ns = ktime_get_boottime_ns();
ath10k_dbg(ar, ATH10K_DBG_MGMT,
"event mgmt rx skb %pK len %d ftype %02x stype %02x\n",
skb, skb->len,

View File

@ -37,7 +37,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.fw = {
.dir = "IPQ8074/hw2.0",
.board_size = 256 * 1024,
.cal_size = 256 * 1024,
.cal_offset = 128 * 1024,
},
.max_radios = 3,
.bdf_addr = 0x4B0C0000,
@ -59,7 +59,17 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.vdev_start_delay = false,
.htt_peer_map_v2 = true,
.tcl_0_only = false,
.spectral_fft_sz = 2,
.spectral = {
.fft_sz = 2,
/* HW bug, expected BIN size is 2 bytes but HW report as 4 bytes.
* so added pad size as 2 bytes to compensate the BIN size
*/
.fft_pad_sz = 2,
.summary_pad_sz = 0,
.fft_hdr_len = 16,
.max_fft_bins = 512,
},
.interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP) |
@ -78,7 +88,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.fw = {
.dir = "IPQ6018/hw1.0",
.board_size = 256 * 1024,
.cal_size = 256 * 1024,
.cal_offset = 128 * 1024,
},
.max_radios = 2,
.bdf_addr = 0x4ABC0000,
@ -100,7 +110,14 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.vdev_start_delay = false,
.htt_peer_map_v2 = true,
.tcl_0_only = false,
.spectral_fft_sz = 4,
.spectral = {
.fft_sz = 4,
.fft_pad_sz = 0,
.summary_pad_sz = 0,
.fft_hdr_len = 16,
.max_fft_bins = 512,
},
.interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP) |
@ -119,7 +136,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.fw = {
.dir = "QCA6390/hw2.0",
.board_size = 256 * 1024,
.cal_size = 256 * 1024,
.cal_offset = 128 * 1024,
},
.max_radios = 3,
.bdf_addr = 0x4B0C0000,
@ -141,7 +158,14 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.vdev_start_delay = true,
.htt_peer_map_v2 = false,
.tcl_0_only = true,
.spectral_fft_sz = 0,
.spectral = {
.fft_sz = 0,
.fft_pad_sz = 0,
.summary_pad_sz = 0,
.fft_hdr_len = 0,
.max_fft_bins = 0,
},
.interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP),
@ -159,7 +183,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.fw = {
.dir = "QCN9074/hw1.0",
.board_size = 256 * 1024,
.cal_size = 256 * 1024,
.cal_offset = 128 * 1024,
},
.max_radios = 1,
.single_pdev_only = false,
@ -180,6 +204,15 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.vdev_start_delay = false,
.htt_peer_map_v2 = true,
.tcl_0_only = false,
.spectral = {
.fft_sz = 2,
.fft_pad_sz = 0,
.summary_pad_sz = 16,
.fft_hdr_len = 24,
.max_fft_bins = 1024,
},
.interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_MESH_POINT),
@ -197,7 +230,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.fw = {
.dir = "WCN6855/hw2.0",
.board_size = 256 * 1024,
.cal_size = 256 * 1024,
.cal_offset = 128 * 1024,
},
.max_radios = 3,
.bdf_addr = 0x4B0C0000,
@ -219,7 +252,14 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.vdev_start_delay = true,
.htt_peer_map_v2 = false,
.tcl_0_only = true,
.spectral_fft_sz = 0,
.spectral = {
.fft_sz = 0,
.fft_pad_sz = 0,
.summary_pad_sz = 0,
.fft_hdr_len = 0,
.max_fft_bins = 0,
},
.interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP),

View File

@ -93,6 +93,8 @@ struct ath11k_skb_rxcb {
bool is_first_msdu;
bool is_last_msdu;
bool is_continuation;
bool is_mcbc;
bool is_eapol;
struct hal_rx_desc *rx_desc;
u8 err_rel_src;
u8 err_code;
@ -100,6 +102,8 @@ struct ath11k_skb_rxcb {
u8 unmapped;
u8 is_frag;
u8 tid;
u16 peer_id;
u16 seq_no;
};
enum ath11k_hw_rev {
@ -193,7 +197,9 @@ enum ath11k_dev_flags {
};
enum ath11k_monitor_flags {
ATH11K_FLAG_MONITOR_ENABLED,
ATH11K_FLAG_MONITOR_CONF_ENABLED,
ATH11K_FLAG_MONITOR_STARTED,
ATH11K_FLAG_MONITOR_VDEV_CREATED,
};
struct ath11k_vif {
@ -362,6 +368,7 @@ struct ath11k_sta {
enum hal_pn_type pn_type;
struct work_struct update_wk;
struct work_struct set_4addr_wk;
struct rate_info txrate;
struct rate_info last_txrate;
u64 rx_duration;
@ -374,12 +381,15 @@ struct ath11k_sta {
/* protected by conf_mutex */
bool aggr_mode;
#endif
bool use_4addr_set;
u16 tcl_metadata;
};
#define ATH11K_MIN_5G_FREQ 4150
#define ATH11K_MIN_6G_FREQ 5945
#define ATH11K_MIN_6G_FREQ 5925
#define ATH11K_MAX_6G_FREQ 7115
#define ATH11K_NUM_CHANS 100
#define ATH11K_NUM_CHANS 101
#define ATH11K_MAX_5G_CHAN 173
enum ath11k_state {
@ -484,7 +494,6 @@ struct ath11k {
u32 chan_tx_pwr;
u32 num_stations;
u32 max_num_stations;
bool monitor_present;
/* To synchronize concurrent synchronous mac80211 callback operations,
* concurrent debugfs configuration and concurrent FW statistics events.
*/
@ -559,6 +568,7 @@ struct ath11k {
struct ath11k_per_peer_tx_stats cached_stats;
u32 last_ppdu_id;
u32 cached_ppdu_id;
int monitor_vdev_id;
#ifdef CONFIG_ATH11K_DEBUGFS
struct ath11k_debug debug;
#endif
@ -591,6 +601,8 @@ struct ath11k_pdev_cap {
u32 tx_chain_mask_shift;
u32 rx_chain_mask_shift;
struct ath11k_band_cap band[NUM_NL80211_BANDS];
bool nss_ratio_enabled;
u8 nss_ratio_info;
};
struct ath11k_pdev {
@ -794,12 +806,15 @@ struct ath11k_fw_stats_pdev {
s32 hw_reaped;
/* Num underruns */
s32 underrun;
/* Num hw paused */
u32 hw_paused;
/* Num PPDUs cleaned up in TX abort */
s32 tx_abort;
/* Num MPDUs requeued by SW */
s32 mpdus_requeued;
/* excessive retries */
u32 tx_ko;
u32 tx_xretry;
/* data hw rate code */
u32 data_rc;
/* Scheduler self triggers */
@ -820,6 +835,30 @@ struct ath11k_fw_stats_pdev {
u32 phy_underrun;
/* MPDU is more than txop limit */
u32 txop_ovf;
/* Num sequences posted */
u32 seq_posted;
/* Num sequences failed in queueing */
u32 seq_failed_queueing;
/* Num sequences completed */
u32 seq_completed;
/* Num sequences restarted */
u32 seq_restarted;
/* Num of MU sequences posted */
u32 mu_seq_posted;
/* Num MPDUs flushed by SW, HWPAUSED, SW TXABORT
* (Reset,channel change)
*/
s32 mpdus_sw_flush;
/* Num MPDUs filtered by HW, all filter condition (TTL expired) */
s32 mpdus_hw_filter;
/* Num MPDUs truncated by PDG (TXOP, TBTT,
* PPDU_duration based on rate, dyn_bw)
*/
s32 mpdus_truncated;
/* Num MPDUs that was tried but didn't receive ACK or BA */
s32 mpdus_ack_failed;
/* Num MPDUs that was dropped du to expiry. */
s32 mpdus_expired;
/* PDEV RX stats */
/* Cnts any change in ring routing mid-ppdu */
@ -845,6 +884,8 @@ struct ath11k_fw_stats_pdev {
s32 phy_err_drop;
/* Number of mpdu errors - FCS, MIC, ENC etc. */
s32 mpdu_errs;
/* Num overflow errors */
s32 rx_ovfl_errs;
};
struct ath11k_fw_stats_vdev {

View File

@ -8,8 +8,7 @@
static int ath11k_dbring_bufs_replenish(struct ath11k *ar,
struct ath11k_dbring *ring,
struct ath11k_dbring_element *buff,
gfp_t gfp)
struct ath11k_dbring_element *buff)
{
struct ath11k_base *ab = ar->ab;
struct hal_srng *srng;
@ -35,7 +34,7 @@ static int ath11k_dbring_bufs_replenish(struct ath11k *ar,
goto err;
spin_lock_bh(&ring->idr_lock);
buf_id = idr_alloc(&ring->bufs_idr, buff, 0, ring->bufs_max, gfp);
buf_id = idr_alloc(&ring->bufs_idr, buff, 0, ring->bufs_max, GFP_ATOMIC);
spin_unlock_bh(&ring->idr_lock);
if (buf_id < 0) {
ret = -ENOBUFS;
@ -72,8 +71,7 @@ err:
}
static int ath11k_dbring_fill_bufs(struct ath11k *ar,
struct ath11k_dbring *ring,
gfp_t gfp)
struct ath11k_dbring *ring)
{
struct ath11k_dbring_element *buff;
struct hal_srng *srng;
@ -92,11 +90,11 @@ static int ath11k_dbring_fill_bufs(struct ath11k *ar,
size = sizeof(*buff) + ring->buf_sz + align - 1;
while (num_remain > 0) {
buff = kzalloc(size, gfp);
buff = kzalloc(size, GFP_ATOMIC);
if (!buff)
break;
ret = ath11k_dbring_bufs_replenish(ar, ring, buff, gfp);
ret = ath11k_dbring_bufs_replenish(ar, ring, buff);
if (ret) {
ath11k_warn(ar->ab, "failed to replenish db ring num_remain %d req_ent %d\n",
num_remain, req_entries);
@ -176,7 +174,7 @@ int ath11k_dbring_buf_setup(struct ath11k *ar,
ring->hp_addr = ath11k_hal_srng_get_hp_addr(ar->ab, srng);
ring->tp_addr = ath11k_hal_srng_get_tp_addr(ar->ab, srng);
ret = ath11k_dbring_fill_bufs(ar, ring, GFP_KERNEL);
ret = ath11k_dbring_fill_bufs(ar, ring);
return ret;
}
@ -322,7 +320,7 @@ int ath11k_dbring_buffer_release_event(struct ath11k_base *ab,
}
memset(buff, 0, size);
ath11k_dbring_bufs_replenish(ar, ring, buff, GFP_ATOMIC);
ath11k_dbring_bufs_replenish(ar, ring, buff);
}
spin_unlock_bh(&srng->lock);

View File

@ -902,7 +902,7 @@ static ssize_t ath11k_write_pktlog_filter(struct file *file,
struct htt_rx_ring_tlv_filter tlv_filter = {0};
u32 rx_filter = 0, ring_id, filter, mode;
u8 buf[128] = {0};
int i, ret;
int i, ret, rx_buf_sz = 0;
ssize_t rc;
mutex_lock(&ar->conf_mutex);
@ -940,6 +940,17 @@ static ssize_t ath11k_write_pktlog_filter(struct file *file,
}
}
/* Clear rx filter set for monitor mode and rx status */
for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
ring_id = ar->dp.rx_mon_status_refill_ring[i].refill_buf_ring.ring_id;
ret = ath11k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, ar->dp.mac_id,
HAL_RXDMA_MONITOR_STATUS,
rx_buf_sz, &tlv_filter);
if (ret) {
ath11k_warn(ar->ab, "failed to set rx filter for monitor status ring\n");
goto out;
}
}
#define HTT_RX_FILTER_TLV_LITE_MODE \
(HTT_RX_FILTER_TLV_FLAGS_PPDU_START | \
HTT_RX_FILTER_TLV_FLAGS_PPDU_END | \
@ -955,6 +966,7 @@ static ssize_t ath11k_write_pktlog_filter(struct file *file,
HTT_RX_FILTER_TLV_FLAGS_MPDU_END |
HTT_RX_FILTER_TLV_FLAGS_PACKET_HEADER |
HTT_RX_FILTER_TLV_FLAGS_ATTENTION;
rx_buf_sz = DP_RX_BUFFER_SIZE;
} else if (mode == ATH11K_PKTLOG_MODE_LITE) {
ret = ath11k_dp_tx_htt_h2t_ppdu_stats_req(ar,
HTT_PPDU_STATS_TAG_PKTLOG);
@ -964,7 +976,12 @@ static ssize_t ath11k_write_pktlog_filter(struct file *file,
}
rx_filter = HTT_RX_FILTER_TLV_LITE_MODE;
rx_buf_sz = DP_RX_BUFFER_SIZE_LITE;
} else {
rx_buf_sz = DP_RX_BUFFER_SIZE;
tlv_filter = ath11k_mac_mon_status_filter_default;
rx_filter = tlv_filter.rx_filter;
ret = ath11k_dp_tx_htt_h2t_ppdu_stats_req(ar,
HTT_PPDU_STATS_TAG_DEFAULT);
if (ret) {
@ -988,7 +1005,7 @@ static ssize_t ath11k_write_pktlog_filter(struct file *file,
ret = ath11k_dp_tx_htt_rx_filter_setup(ab, ring_id,
ar->dp.mac_id + i,
HAL_RXDMA_MONITOR_STATUS,
DP_RX_BUFFER_SIZE, &tlv_filter);
rx_buf_sz, &tlv_filter);
if (ret) {
ath11k_warn(ab, "failed to set rx filter for monitor status ring\n");
@ -996,8 +1013,8 @@ static ssize_t ath11k_write_pktlog_filter(struct file *file,
}
}
ath11k_dbg(ab, ATH11K_DBG_WMI, "pktlog filter %d mode %s\n",
filter, ((mode == ATH11K_PKTLOG_MODE_FULL) ? "full" : "lite"));
ath11k_info(ab, "pktlog mode %s\n",
((mode == ATH11K_PKTLOG_MODE_FULL) ? "full" : "lite"));
ar->debug.pktlog_filter = filter;
ar->debug.pktlog_mode = mode;

View File

@ -38,6 +38,10 @@ enum ath11k_dbg_htt_ext_stats_type {
ATH11K_DBG_HTT_EXT_STATS_TX_SOUNDING_INFO = 22,
ATH11K_DBG_HTT_EXT_STATS_PDEV_OBSS_PD_STATS = 23,
ATH11K_DBG_HTT_EXT_STATS_RING_BACKPRESSURE_STATS = 24,
ATH11K_DBG_HTT_EXT_STATS_PEER_CTRL_PATH_TXRX_STATS = 29,
ATH11K_DBG_HTT_EXT_STATS_PDEV_TX_RATE_TXBF_STATS = 31,
ATH11K_DBG_HTT_EXT_STATS_TXBF_OFDMA = 32,
ATH11K_DBG_HTT_EXT_PHY_COUNTERS_AND_PHY_STATS = 37,
/* keep this last */
ATH11K_DBG_HTT_NUM_EXT_STATS,

File diff suppressed because it is too large Load Diff

View File

@ -102,6 +102,14 @@ enum htt_tlv_tag_t {
HTT_STATS_PDEV_OBSS_PD_TAG = 88,
HTT_STATS_HW_WAR_TAG = 89,
HTT_STATS_RING_BACKPRESSURE_STATS_TAG = 90,
HTT_STATS_PEER_CTRL_PATH_TXRX_STATS_TAG = 101,
HTT_STATS_PDEV_TX_RATE_TXBF_STATS_TAG = 108,
HTT_STATS_TXBF_OFDMA_NDPA_STATS_TAG = 113,
HTT_STATS_TXBF_OFDMA_NDP_STATS_TAG = 114,
HTT_STATS_TXBF_OFDMA_BRP_STATS_TAG = 115,
HTT_STATS_TXBF_OFDMA_STEER_STATS_TAG = 116,
HTT_STATS_PHY_COUNTERS_TAG = 121,
HTT_STATS_PHY_STATS_TAG = 122,
HTT_STATS_MAX_TAG,
};
@ -137,6 +145,8 @@ struct htt_stats_string_tlv {
u32 data[0]; /* Can be variable length */
} __packed;
#define HTT_STATS_MAC_ID GENMASK(7, 0)
/* == TX PDEV STATS == */
struct htt_tx_pdev_stats_cmn_tlv {
u32 mac_id__word;
@ -290,6 +300,10 @@ struct htt_hw_stats_whal_tx_tlv {
};
/* ============ PEER STATS ============ */
#define HTT_MSDU_FLOW_STATS_TX_FLOW_NO GENMASK(15, 0)
#define HTT_MSDU_FLOW_STATS_TID_NUM GENMASK(19, 16)
#define HTT_MSDU_FLOW_STATS_DROP_RULE BIT(20)
struct htt_msdu_flow_stats_tlv {
u32 last_update_timestamp;
u32 last_add_timestamp;
@ -306,6 +320,11 @@ struct htt_msdu_flow_stats_tlv {
#define MAX_HTT_TID_NAME 8
#define HTT_TX_TID_STATS_SW_PEER_ID GENMASK(15, 0)
#define HTT_TX_TID_STATS_TID_NUM GENMASK(31, 16)
#define HTT_TX_TID_STATS_NUM_SCHED_PENDING GENMASK(7, 0)
#define HTT_TX_TID_STATS_NUM_PPDU_IN_HWQ GENMASK(15, 8)
/* Tidq stats */
struct htt_tx_tid_stats_tlv {
/* Stored as little endian */
@ -326,6 +345,11 @@ struct htt_tx_tid_stats_tlv {
u32 tid_tx_airtime;
};
#define HTT_TX_TID_STATS_V1_SW_PEER_ID GENMASK(15, 0)
#define HTT_TX_TID_STATS_V1_TID_NUM GENMASK(31, 16)
#define HTT_TX_TID_STATS_V1_NUM_SCHED_PENDING GENMASK(7, 0)
#define HTT_TX_TID_STATS_V1_NUM_PPDU_IN_HWQ GENMASK(15, 8)
/* Tidq stats */
struct htt_tx_tid_stats_v1_tlv {
/* Stored as little endian */
@ -348,6 +372,9 @@ struct htt_tx_tid_stats_v1_tlv {
u32 sendn_frms_allowed;
};
#define HTT_RX_TID_STATS_SW_PEER_ID GENMASK(15, 0)
#define HTT_RX_TID_STATS_TID_NUM GENMASK(31, 16)
struct htt_rx_tid_stats_tlv {
u32 sw_peer_id__tid_num;
u8 tid_name[MAX_HTT_TID_NAME];
@ -386,6 +413,10 @@ struct htt_peer_stats_cmn_tlv {
u32 inactive_time;
};
#define HTT_PEER_DETAILS_VDEV_ID GENMASK(7, 0)
#define HTT_PEER_DETAILS_PDEV_ID GENMASK(15, 8)
#define HTT_PEER_DETAILS_AST_IDX GENMASK(31, 16)
struct htt_peer_details_tlv {
u32 peer_type;
u32 sw_peer_id;
@ -510,6 +541,9 @@ struct htt_tx_hwq_mu_mimo_mpdu_stats_tlv {
u32 mu_mimo_ampdu_underrun_usr;
};
#define HTT_TX_HWQ_STATS_MAC_ID GENMASK(7, 0)
#define HTT_TX_HWQ_STATS_HWQ_ID GENMASK(15, 8)
struct htt_tx_hwq_mu_mimo_cmn_stats_tlv {
u32 mac_id__hwq_id__word;
};
@ -789,6 +823,9 @@ struct htt_sched_txq_sched_ineligibility_tlv_v {
u32 sched_ineligibility[0];
};
#define HTT_TX_PDEV_STATS_SCHED_PER_TXQ_MAC_ID GENMASK(7, 0)
#define HTT_TX_PDEV_STATS_SCHED_PER_TXQ_ID GENMASK(15, 8)
struct htt_tx_pdev_stats_sched_per_txq_tlv {
u32 mac_id__txq_id__word;
u32 sched_policy;
@ -910,6 +947,9 @@ struct htt_tx_tqm_error_stats_tlv {
};
/* == TQM CMDQ stats == */
#define HTT_TX_TQM_CMDQ_STATUS_MAC_ID GENMASK(7, 0)
#define HTT_TX_TQM_CMDQ_STATUS_CMDQ_ID GENMASK(15, 8)
struct htt_tx_tqm_cmdq_status_tlv {
u32 mac_id__cmdq_id__word;
u32 sync_cmd;
@ -1055,6 +1095,15 @@ struct htt_tx_de_cmn_stats_tlv {
#define HTT_STATS_LOW_WM_BINS 5
#define HTT_STATS_HIGH_WM_BINS 5
#define HTT_RING_IF_STATS_NUM_ELEMS GENMASK(15, 0)
#define HTT_RING_IF_STATS_PREFETCH_TAIL_INDEX GENMASK(31, 16)
#define HTT_RING_IF_STATS_HEAD_IDX GENMASK(15, 0)
#define HTT_RING_IF_STATS_TAIL_IDX GENMASK(31, 16)
#define HTT_RING_IF_STATS_SHADOW_HEAD_IDX GENMASK(15, 0)
#define HTT_RING_IF_STATS_SHADOW_TAIL_IDX GENMASK(31, 16)
#define HTT_RING_IF_STATS_LWM_THRESH GENMASK(15, 0)
#define HTT_RING_IF_STATS_HWM_THRESH GENMASK(31, 16)
struct htt_ring_if_stats_tlv {
u32 base_addr; /* DWORD aligned base memory address of the ring */
u32 elem_size;
@ -1117,6 +1166,19 @@ struct htt_sfm_cmn_tlv {
};
/* == SRNG STATS == */
#define HTT_SRING_STATS_MAC_ID GENMASK(7, 0)
#define HTT_SRING_STATS_RING_ID GENMASK(15, 8)
#define HTT_SRING_STATS_ARENA GENMASK(23, 16)
#define HTT_SRING_STATS_EP BIT(24)
#define HTT_SRING_STATS_NUM_AVAIL_WORDS GENMASK(15, 0)
#define HTT_SRING_STATS_NUM_VALID_WORDS GENMASK(31, 16)
#define HTT_SRING_STATS_HEAD_PTR GENMASK(15, 0)
#define HTT_SRING_STATS_TAIL_PTR GENMASK(31, 16)
#define HTT_SRING_STATS_CONSUMER_EMPTY GENMASK(15, 0)
#define HTT_SRING_STATS_PRODUCER_FULL GENMASK(31, 16)
#define HTT_SRING_STATS_PREFETCH_COUNT GENMASK(15, 0)
#define HTT_SRING_STATS_INTERNAL_TAIL_PTR GENMASK(31, 16)
struct htt_sring_stats_tlv {
u32 mac_id__ring_id__arena__ep;
u32 base_addr_lsb; /* DWORD aligned base memory address of the ring */
@ -1696,6 +1758,170 @@ struct htt_ring_backpressure_stats_tlv {
u32 backpressure_hist[5];
};
#define HTT_TX_TXBF_RATE_STATS_NUM_MCS_COUNTERS 14
#define HTT_TX_TXBF_RATE_STATS_NUM_BW_COUNTERS 5
#define HTT_TX_PDEV_STATS_NUM_SPATIAL_STREAMS 8
struct htt_pdev_txrate_txbf_stats_tlv {
/* SU TxBF TX MCS stats */
u32 tx_su_txbf_mcs[HTT_TX_TXBF_RATE_STATS_NUM_MCS_COUNTERS];
/* Implicit BF TX MCS stats */
u32 tx_su_ibf_mcs[HTT_TX_TXBF_RATE_STATS_NUM_MCS_COUNTERS];
/* Open loop TX MCS stats */
u32 tx_su_ol_mcs[HTT_TX_TXBF_RATE_STATS_NUM_MCS_COUNTERS];
/* SU TxBF TX NSS stats */
u32 tx_su_txbf_nss[HTT_TX_PDEV_STATS_NUM_SPATIAL_STREAMS];
/* Implicit BF TX NSS stats */
u32 tx_su_ibf_nss[HTT_TX_PDEV_STATS_NUM_SPATIAL_STREAMS];
/* Open loop TX NSS stats */
u32 tx_su_ol_nss[HTT_TX_PDEV_STATS_NUM_SPATIAL_STREAMS];
/* SU TxBF TX BW stats */
u32 tx_su_txbf_bw[HTT_TX_TXBF_RATE_STATS_NUM_BW_COUNTERS];
/* Implicit BF TX BW stats */
u32 tx_su_ibf_bw[HTT_TX_TXBF_RATE_STATS_NUM_BW_COUNTERS];
/* Open loop TX BW stats */
u32 tx_su_ol_bw[HTT_TX_TXBF_RATE_STATS_NUM_BW_COUNTERS];
};
struct htt_txbf_ofdma_ndpa_stats_tlv {
/* 11AX HE OFDMA NDPA frame queued to the HW */
u32 ax_ofdma_ndpa_queued[HTT_TX_PDEV_STATS_NUM_OFDMA_USER_STATS];
/* 11AX HE OFDMA NDPA frame sent over the air */
u32 ax_ofdma_ndpa_tried[HTT_TX_PDEV_STATS_NUM_OFDMA_USER_STATS];
/* 11AX HE OFDMA NDPA frame flushed by HW */
u32 ax_ofdma_ndpa_flushed[HTT_TX_PDEV_STATS_NUM_OFDMA_USER_STATS];
/* 11AX HE OFDMA NDPA frame completed with error(s) */
u32 ax_ofdma_ndpa_err[HTT_TX_PDEV_STATS_NUM_OFDMA_USER_STATS];
};
struct htt_txbf_ofdma_ndp_stats_tlv {
/* 11AX HE OFDMA NDP frame queued to the HW */
u32 ax_ofdma_ndp_queued[HTT_TX_PDEV_STATS_NUM_OFDMA_USER_STATS];
/* 11AX HE OFDMA NDPA frame sent over the air */
u32 ax_ofdma_ndp_tried[HTT_TX_PDEV_STATS_NUM_OFDMA_USER_STATS];
/* 11AX HE OFDMA NDPA frame flushed by HW */
u32 ax_ofdma_ndp_flushed[HTT_TX_PDEV_STATS_NUM_OFDMA_USER_STATS];
/* 11AX HE OFDMA NDPA frame completed with error(s) */
u32 ax_ofdma_ndp_err[HTT_TX_PDEV_STATS_NUM_OFDMA_USER_STATS];
};
struct htt_txbf_ofdma_brp_stats_tlv {
/* 11AX HE OFDMA MU BRPOLL frame queued to the HW */
u32 ax_ofdma_brpoll_queued[HTT_TX_PDEV_STATS_NUM_OFDMA_USER_STATS];
/* 11AX HE OFDMA MU BRPOLL frame sent over the air */
u32 ax_ofdma_brpoll_tried[HTT_TX_PDEV_STATS_NUM_OFDMA_USER_STATS];
/* 11AX HE OFDMA MU BRPOLL frame flushed by HW */
u32 ax_ofdma_brpoll_flushed[HTT_TX_PDEV_STATS_NUM_OFDMA_USER_STATS];
/* 11AX HE OFDMA MU BRPOLL frame completed with error(s) */
u32 ax_ofdma_brp_err[HTT_TX_PDEV_STATS_NUM_OFDMA_USER_STATS];
/* Number of CBF(s) received when 11AX HE OFDMA MU BRPOLL frame
* completed with error(s).
*/
u32 ax_ofdma_brp_err_num_cbf_rcvd[HTT_TX_PDEV_STATS_NUM_OFDMA_USER_STATS + 1];
};
struct htt_txbf_ofdma_steer_stats_tlv {
/* 11AX HE OFDMA PPDUs that were sent over the air with steering (TXBF + OFDMA) */
u32 ax_ofdma_num_ppdu_steer[HTT_TX_PDEV_STATS_NUM_OFDMA_USER_STATS];
/* 11AX HE OFDMA PPDUs that were sent over the air in open loop */
u32 ax_ofdma_num_ppdu_ol[HTT_TX_PDEV_STATS_NUM_OFDMA_USER_STATS];
/* 11AX HE OFDMA number of users for which CBF prefetch was
* initiated to PHY HW during TX.
*/
u32 ax_ofdma_num_usrs_prefetch[HTT_TX_PDEV_STATS_NUM_OFDMA_USER_STATS];
/* 11AX HE OFDMA number of users for which sounding was initiated during TX */
u32 ax_ofdma_num_usrs_sound[HTT_TX_PDEV_STATS_NUM_OFDMA_USER_STATS];
/* 11AX HE OFDMA number of users for which sounding was forced during TX */
u32 ax_ofdma_num_usrs_force_sound[HTT_TX_PDEV_STATS_NUM_OFDMA_USER_STATS];
};
#define HTT_MAX_RX_PKT_CNT 8
#define HTT_MAX_RX_PKT_CRC_PASS_CNT 8
#define HTT_MAX_PER_BLK_ERR_CNT 20
#define HTT_MAX_RX_OTA_ERR_CNT 14
#define HTT_STATS_MAX_CHAINS 8
#define ATH11K_STATS_MGMT_FRM_TYPE_MAX 16
struct htt_phy_counters_tlv {
/* number of RXTD OFDMA OTA error counts except power surge and drop */
u32 rx_ofdma_timing_err_cnt;
/* rx_cck_fail_cnt:
* number of cck error counts due to rx reception failure because of
* timing error in cck
*/
u32 rx_cck_fail_cnt;
/* number of times tx abort initiated by mac */
u32 mactx_abort_cnt;
/* number of times rx abort initiated by mac */
u32 macrx_abort_cnt;
/* number of times tx abort initiated by phy */
u32 phytx_abort_cnt;
/* number of times rx abort initiated by phy */
u32 phyrx_abort_cnt;
/* number of rx defered count initiated by phy */
u32 phyrx_defer_abort_cnt;
/* number of sizing events generated at LSTF */
u32 rx_gain_adj_lstf_event_cnt;
/* number of sizing events generated at non-legacy LTF */
u32 rx_gain_adj_non_legacy_cnt;
/* rx_pkt_cnt -
* Received EOP (end-of-packet) count per packet type;
* [0] = 11a; [1] = 11b; [2] = 11n; [3] = 11ac; [4] = 11ax; [5] = GF
* [6-7]=RSVD
*/
u32 rx_pkt_cnt[HTT_MAX_RX_PKT_CNT];
/* rx_pkt_crc_pass_cnt -
* Received EOP (end-of-packet) count per packet type;
* [0] = 11a; [1] = 11b; [2] = 11n; [3] = 11ac; [4] = 11ax; [5] = GF
* [6-7]=RSVD
*/
u32 rx_pkt_crc_pass_cnt[HTT_MAX_RX_PKT_CRC_PASS_CNT];
/* per_blk_err_cnt -
* Error count per error source;
* [0] = unknown; [1] = LSIG; [2] = HTSIG; [3] = VHTSIG; [4] = HESIG;
* [5] = RXTD_OTA; [6] = RXTD_FATAL; [7] = DEMF; [8] = ROBE;
* [9] = PMI; [10] = TXFD; [11] = TXTD; [12] = PHYRF
* [13-19]=RSVD
*/
u32 per_blk_err_cnt[HTT_MAX_PER_BLK_ERR_CNT];
/* rx_ota_err_cnt -
* RXTD OTA (over-the-air) error count per error reason;
* [0] = voting fail; [1] = weak det fail; [2] = strong sig fail;
* [3] = cck fail; [4] = power surge; [5] = power drop;
* [6] = btcf timing timeout error; [7] = btcf packet detect error;
* [8] = coarse timing timeout error
* [9-13]=RSVD
*/
u32 rx_ota_err_cnt[HTT_MAX_RX_OTA_ERR_CNT];
};
struct htt_phy_stats_tlv {
/* per chain hw noise floor values in dBm */
s32 nf_chain[HTT_STATS_MAX_CHAINS];
/* number of false radars detected */
u32 false_radar_cnt;
/* number of channel switches happened due to radar detection */
u32 radar_cs_cnt;
/* ani_level -
* ANI level (noise interference) corresponds to the channel
* the desense levels range from -5 to 15 in dB units,
* higher values indicating more noise interference.
*/
s32 ani_level;
/* running time in minutes since FW boot */
u32 fw_run_time;
};
struct htt_peer_ctrl_path_txrx_stats_tlv {
/* peer mac address */
u8 peer_mac_addr[ETH_ALEN];
u8 rsvd[2];
/* Num of tx mgmt frames with subtype on peer level */
u32 peer_tx_mgmt_subtype[ATH11K_STATS_MGMT_FRM_TYPE_MAX];
/* Num of rx mgmt frames with subtype on peer level */
u32 peer_rx_mgmt_subtype[ATH11K_STATS_MGMT_FRM_TYPE_MAX];
};
#ifdef CONFIG_ATH11K_DEBUGFS
void ath11k_debugfs_htt_stats_init(struct ath11k *ar);

View File

@ -419,15 +419,21 @@ ath11k_dbg_sta_open_htt_peer_stats(struct inode *inode, struct file *file)
struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
struct ath11k *ar = arsta->arvif->ar;
struct debug_htt_stats_req *stats_req;
int type = ar->debug.htt_stats.type;
int ret;
if ((type != ATH11K_DBG_HTT_EXT_STATS_PEER_INFO &&
type != ATH11K_DBG_HTT_EXT_STATS_PEER_CTRL_PATH_TXRX_STATS) ||
type == ATH11K_DBG_HTT_EXT_STATS_RESET)
return -EPERM;
stats_req = vzalloc(sizeof(*stats_req) + ATH11K_HTT_STATS_BUF_SIZE);
if (!stats_req)
return -ENOMEM;
mutex_lock(&ar->conf_mutex);
ar->debug.htt_stats.stats_req = stats_req;
stats_req->type = ATH11K_DBG_HTT_EXT_STATS_PEER_INFO;
stats_req->type = type;
memcpy(stats_req->peer_addr, sta->addr, ETH_ALEN);
ret = ath11k_debugfs_htt_stats_req(ar);
mutex_unlock(&ar->conf_mutex);

View File

@ -195,6 +195,7 @@ struct ath11k_pdev_dp {
#define DP_RXDMA_MONITOR_DESC_RING_SIZE 4096
#define DP_RX_BUFFER_SIZE 2048
#define DP_RX_BUFFER_SIZE_LITE 1024
#define DP_RX_BUFFER_ALIGN_SIZE 128
#define DP_RXDMA_BUF_COOKIE_BUF_ID GENMASK(17, 0)
@ -1592,6 +1593,13 @@ struct ath11k_htt_extd_stats_msg {
u8 data[0];
} __packed;
#define HTT_MAC_ADDR_L32_0 GENMASK(7, 0)
#define HTT_MAC_ADDR_L32_1 GENMASK(15, 8)
#define HTT_MAC_ADDR_L32_2 GENMASK(23, 16)
#define HTT_MAC_ADDR_L32_3 GENMASK(31, 24)
#define HTT_MAC_ADDR_H16_0 GENMASK(7, 0)
#define HTT_MAC_ADDR_H16_1 GENMASK(15, 8)
struct htt_mac_addr {
u32 mac_addr_l32;
u32 mac_addr_h16;

View File

@ -142,6 +142,18 @@ static u32 ath11k_dp_rx_h_attn_mpdu_err(struct rx_attention *attn)
return errmap;
}
static bool ath11k_dp_rx_h_attn_msdu_len_err(struct ath11k_base *ab,
struct hal_rx_desc *desc)
{
struct rx_attention *rx_attention;
u32 errmap;
rx_attention = ath11k_dp_rx_get_attention(ab, desc);
errmap = ath11k_dp_rx_h_attn_mpdu_err(rx_attention);
return errmap & DP_RX_MPDU_ERR_MSDU_LEN;
}
static u16 ath11k_dp_rx_h_msdu_start_msdu_len(struct ath11k_base *ab,
struct hal_rx_desc *desc)
{
@ -270,6 +282,18 @@ static bool ath11k_dp_rx_h_attn_is_mcbc(struct ath11k_base *ab,
__le32_to_cpu(attn->info1)));
}
static bool ath11k_dp_rxdesc_mac_addr2_valid(struct ath11k_base *ab,
struct hal_rx_desc *desc)
{
return ab->hw_params.hw_ops->rx_desc_mac_addr2_valid(desc);
}
static u8 *ath11k_dp_rxdesc_mpdu_start_addr2(struct ath11k_base *ab,
struct hal_rx_desc *desc)
{
return ab->hw_params.hw_ops->rx_desc_mpdu_start_addr2(desc);
}
static void ath11k_dp_service_mon_ring(struct timer_list *t)
{
struct ath11k_base *ab = from_timer(ab, t, mon_reap_timer);
@ -2156,6 +2180,7 @@ static void ath11k_dp_rx_h_undecap(struct ath11k *ar, struct sk_buff *msdu,
{
u8 *first_hdr;
u8 decap;
struct ethhdr *ehdr;
first_hdr = ath11k_dp_rx_h_80211_hdr(ar->ab, rx_desc);
decap = ath11k_dp_rx_h_msdu_start_decap_type(ar->ab, rx_desc);
@ -2170,9 +2195,22 @@ static void ath11k_dp_rx_h_undecap(struct ath11k *ar, struct sk_buff *msdu,
decrypted);
break;
case DP_RX_DECAP_TYPE_ETHERNET2_DIX:
/* TODO undecap support for middle/last msdu's of amsdu */
ath11k_dp_rx_h_undecap_eth(ar, msdu, first_hdr,
enctype, status);
ehdr = (struct ethhdr *)msdu->data;
/* mac80211 allows fast path only for authorized STA */
if (ehdr->h_proto == cpu_to_be16(ETH_P_PAE)) {
ATH11K_SKB_RXCB(msdu)->is_eapol = true;
ath11k_dp_rx_h_undecap_eth(ar, msdu, first_hdr,
enctype, status);
break;
}
/* PN for mcast packets will be validated in mac80211;
* remove eth header and add 802.11 header.
*/
if (ATH11K_SKB_RXCB(msdu)->is_mcbc && decrypted)
ath11k_dp_rx_h_undecap_eth(ar, msdu, first_hdr,
enctype, status);
break;
case DP_RX_DECAP_TYPE_8023:
/* TODO: Handle undecap for these formats */
@ -2180,35 +2218,62 @@ static void ath11k_dp_rx_h_undecap(struct ath11k *ar, struct sk_buff *msdu,
}
}
static struct ath11k_peer *
ath11k_dp_rx_h_find_peer(struct ath11k_base *ab, struct sk_buff *msdu)
{
struct ath11k_skb_rxcb *rxcb = ATH11K_SKB_RXCB(msdu);
struct hal_rx_desc *rx_desc = rxcb->rx_desc;
struct ath11k_peer *peer = NULL;
lockdep_assert_held(&ab->base_lock);
if (rxcb->peer_id)
peer = ath11k_peer_find_by_id(ab, rxcb->peer_id);
if (peer)
return peer;
if (!rx_desc || !(ath11k_dp_rxdesc_mac_addr2_valid(ab, rx_desc)))
return NULL;
peer = ath11k_peer_find_by_addr(ab,
ath11k_dp_rxdesc_mpdu_start_addr2(ab, rx_desc));
return peer;
}
static void ath11k_dp_rx_h_mpdu(struct ath11k *ar,
struct sk_buff *msdu,
struct hal_rx_desc *rx_desc,
struct ieee80211_rx_status *rx_status)
{
bool fill_crypto_hdr, mcast;
bool fill_crypto_hdr;
enum hal_encrypt_type enctype;
bool is_decrypted = false;
struct ath11k_skb_rxcb *rxcb;
struct ieee80211_hdr *hdr;
struct ath11k_peer *peer;
struct rx_attention *rx_attention;
u32 err_bitmap;
hdr = (struct ieee80211_hdr *)msdu->data;
/* PN for multicast packets will be checked in mac80211 */
rxcb = ATH11K_SKB_RXCB(msdu);
fill_crypto_hdr = ath11k_dp_rx_h_attn_is_mcbc(ar->ab, rx_desc);
rxcb->is_mcbc = fill_crypto_hdr;
mcast = is_multicast_ether_addr(hdr->addr1);
fill_crypto_hdr = mcast;
if (rxcb->is_mcbc) {
rxcb->peer_id = ath11k_dp_rx_h_mpdu_start_peer_id(ar->ab, rx_desc);
rxcb->seq_no = ath11k_dp_rx_h_mpdu_start_seq_no(ar->ab, rx_desc);
}
spin_lock_bh(&ar->ab->base_lock);
peer = ath11k_peer_find_by_addr(ar->ab, hdr->addr2);
peer = ath11k_dp_rx_h_find_peer(ar->ab, msdu);
if (peer) {
if (mcast)
if (rxcb->is_mcbc)
enctype = peer->sec_type_grp;
else
enctype = peer->sec_type;
} else {
enctype = HAL_ENCRYPT_TYPE_OPEN;
enctype = ath11k_dp_rx_h_mpdu_start_enctype(ar->ab, rx_desc);
}
spin_unlock_bh(&ar->ab->base_lock);
@ -2247,8 +2312,11 @@ static void ath11k_dp_rx_h_mpdu(struct ath11k *ar,
if (!is_decrypted || fill_crypto_hdr)
return;
hdr = (void *)msdu->data;
hdr->frame_control &= ~__cpu_to_le16(IEEE80211_FCTL_PROTECTED);
if (ath11k_dp_rx_h_msdu_start_decap_type(ar->ab, rx_desc) !=
DP_RX_DECAP_TYPE_ETHERNET2_DIX) {
hdr = (void *)msdu->data;
hdr->frame_control &= ~__cpu_to_le16(IEEE80211_FCTL_PROTECTED);
}
}
static void ath11k_dp_rx_h_rate(struct ath11k *ar, struct hal_rx_desc *rx_desc,
@ -2337,8 +2405,10 @@ static void ath11k_dp_rx_h_ppdu(struct ath11k *ar, struct hal_rx_desc *rx_desc,
channel_num = meta_data;
center_freq = meta_data >> 16;
if (center_freq >= 5935 && center_freq <= 7105) {
if (center_freq >= ATH11K_MIN_6G_FREQ &&
center_freq <= ATH11K_MAX_6G_FREQ) {
rx_status->band = NL80211_BAND_6GHZ;
rx_status->freq = center_freq;
} else if (channel_num >= 1 && channel_num <= 14) {
rx_status->band = NL80211_BAND_2GHZ;
} else if (channel_num >= 36 && channel_num <= 173) {
@ -2356,57 +2426,56 @@ static void ath11k_dp_rx_h_ppdu(struct ath11k *ar, struct hal_rx_desc *rx_desc,
rx_desc, sizeof(struct hal_rx_desc));
}
rx_status->freq = ieee80211_channel_to_frequency(channel_num,
rx_status->band);
if (rx_status->band != NL80211_BAND_6GHZ)
rx_status->freq = ieee80211_channel_to_frequency(channel_num,
rx_status->band);
ath11k_dp_rx_h_rate(ar, rx_desc, rx_status);
}
static char *ath11k_print_get_tid(struct ieee80211_hdr *hdr, char *out,
size_t size)
{
u8 *qc;
int tid;
if (!ieee80211_is_data_qos(hdr->frame_control))
return "";
qc = ieee80211_get_qos_ctl(hdr);
tid = *qc & IEEE80211_QOS_CTL_TID_MASK;
snprintf(out, size, "tid %d", tid);
return out;
}
static void ath11k_dp_rx_deliver_msdu(struct ath11k *ar, struct napi_struct *napi,
struct sk_buff *msdu)
struct sk_buff *msdu,
struct ieee80211_rx_status *status)
{
static const struct ieee80211_radiotap_he known = {
.data1 = cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_DATA_MCS_KNOWN |
IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN),
.data2 = cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_GI_KNOWN),
};
struct ieee80211_rx_status *status;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data;
struct ieee80211_rx_status *rx_status;
struct ieee80211_radiotap_he *he = NULL;
char tid[32];
struct ieee80211_sta *pubsta = NULL;
struct ath11k_peer *peer;
struct ath11k_skb_rxcb *rxcb = ATH11K_SKB_RXCB(msdu);
u8 decap = DP_RX_DECAP_TYPE_RAW;
bool is_mcbc = rxcb->is_mcbc;
bool is_eapol = rxcb->is_eapol;
status = IEEE80211_SKB_RXCB(msdu);
if (status->encoding == RX_ENC_HE) {
if (status->encoding == RX_ENC_HE &&
!(status->flag & RX_FLAG_RADIOTAP_HE) &&
!(status->flag & RX_FLAG_SKIP_MONITOR)) {
he = skb_push(msdu, sizeof(known));
memcpy(he, &known, sizeof(known));
status->flag |= RX_FLAG_RADIOTAP_HE;
}
if (!(status->flag & RX_FLAG_ONLY_MONITOR))
decap = ath11k_dp_rx_h_msdu_start_decap_type(ar->ab, rxcb->rx_desc);
spin_lock_bh(&ar->ab->base_lock);
peer = ath11k_dp_rx_h_find_peer(ar->ab, msdu);
if (peer && peer->sta)
pubsta = peer->sta;
spin_unlock_bh(&ar->ab->base_lock);
ath11k_dbg(ar->ab, ATH11K_DBG_DATA,
"rx skb %pK len %u peer %pM %s %s sn %u %s%s%s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n",
"rx skb %pK len %u peer %pM %d %s sn %u %s%s%s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n",
msdu,
msdu->len,
ieee80211_get_SA(hdr),
ath11k_print_get_tid(hdr, tid, sizeof(tid)),
is_multicast_ether_addr(ieee80211_get_DA(hdr)) ?
"mcast" : "ucast",
(__le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4,
peer ? peer->addr : NULL,
rxcb->tid,
is_mcbc ? "mcast" : "ucast",
rxcb->seq_no,
(status->encoding == RX_ENC_LEGACY) ? "legacy" : "",
(status->encoding == RX_ENC_HT) ? "ht" : "",
(status->encoding == RX_ENC_VHT) ? "vht" : "",
@ -2426,22 +2495,32 @@ static void ath11k_dp_rx_deliver_msdu(struct ath11k *ar, struct napi_struct *nap
ath11k_dbg_dump(ar->ab, ATH11K_DBG_DP_RX, NULL, "dp rx msdu: ",
msdu->data, msdu->len);
rx_status = IEEE80211_SKB_RXCB(msdu);
*rx_status = *status;
/* TODO: trace rx packet */
ieee80211_rx_napi(ar->hw, NULL, msdu, napi);
/* PN for multicast packets are not validate in HW,
* so skip 802.3 rx path
* Also, fast_rx expectes the STA to be authorized, hence
* eapol packets are sent in slow path.
*/
if (decap == DP_RX_DECAP_TYPE_ETHERNET2_DIX && !is_eapol &&
!(is_mcbc && rx_status->flag & RX_FLAG_DECRYPTED))
rx_status->flag |= RX_FLAG_8023;
ieee80211_rx_napi(ar->hw, pubsta, msdu, napi);
}
static int ath11k_dp_rx_process_msdu(struct ath11k *ar,
struct sk_buff *msdu,
struct sk_buff_head *msdu_list)
struct sk_buff_head *msdu_list,
struct ieee80211_rx_status *rx_status)
{
struct ath11k_base *ab = ar->ab;
struct hal_rx_desc *rx_desc, *lrx_desc;
struct rx_attention *rx_attention;
struct ieee80211_rx_status rx_status = {0};
struct ieee80211_rx_status *status;
struct ath11k_skb_rxcb *rxcb;
struct ieee80211_hdr *hdr;
struct sk_buff *last_buf;
u8 l3_pad_bytes;
u8 *hdr_status;
@ -2458,6 +2537,12 @@ static int ath11k_dp_rx_process_msdu(struct ath11k *ar,
}
rx_desc = (struct hal_rx_desc *)msdu->data;
if (ath11k_dp_rx_h_attn_msdu_len_err(ab, rx_desc)) {
ath11k_warn(ar->ab, "msdu len not valid\n");
ret = -EIO;
goto free_out;
}
lrx_desc = (struct hal_rx_desc *)last_buf->data;
rx_attention = ath11k_dp_rx_get_attention(ab, lrx_desc);
if (!ath11k_dp_rx_h_attn_msdu_done(rx_attention)) {
@ -2497,19 +2582,11 @@ static int ath11k_dp_rx_process_msdu(struct ath11k *ar,
}
}
hdr = (struct ieee80211_hdr *)msdu->data;
ath11k_dp_rx_h_ppdu(ar, rx_desc, rx_status);
ath11k_dp_rx_h_mpdu(ar, msdu, rx_desc, rx_status);
/* Process only data frames */
if (!ieee80211_is_data(hdr->frame_control))
return -EINVAL;
rx_status->flag |= RX_FLAG_SKIP_MONITOR | RX_FLAG_DUP_VALIDATED;
ath11k_dp_rx_h_ppdu(ar, rx_desc, &rx_status);
ath11k_dp_rx_h_mpdu(ar, msdu, rx_desc, &rx_status);
rx_status.flag |= RX_FLAG_SKIP_MONITOR | RX_FLAG_DUP_VALIDATED;
status = IEEE80211_SKB_RXCB(msdu);
*status = rx_status;
return 0;
free_out:
@ -2524,6 +2601,7 @@ static void ath11k_dp_rx_process_received_packets(struct ath11k_base *ab,
struct ath11k_skb_rxcb *rxcb;
struct sk_buff *msdu;
struct ath11k *ar;
struct ieee80211_rx_status rx_status = {0};
u8 mac_id;
int ret;
@ -2546,7 +2624,7 @@ static void ath11k_dp_rx_process_received_packets(struct ath11k_base *ab,
continue;
}
ret = ath11k_dp_rx_process_msdu(ar, msdu, msdu_list);
ret = ath11k_dp_rx_process_msdu(ar, msdu, msdu_list, &rx_status);
if (ret) {
ath11k_dbg(ab, ATH11K_DBG_DATA,
"Unable to process msdu %d", ret);
@ -2554,7 +2632,7 @@ static void ath11k_dp_rx_process_received_packets(struct ath11k_base *ab,
continue;
}
ath11k_dp_rx_deliver_msdu(ar, napi, msdu);
ath11k_dp_rx_deliver_msdu(ar, napi, msdu, &rx_status);
(*quota)--;
}
@ -2636,10 +2714,14 @@ try_again:
RX_MSDU_DESC_INFO0_LAST_MSDU_IN_MPDU);
rxcb->is_continuation = !!(desc.rx_msdu_info.info0 &
RX_MSDU_DESC_INFO0_MSDU_CONTINUATION);
rxcb->mac_id = mac_id;
rxcb->peer_id = FIELD_GET(RX_MPDU_DESC_META_DATA_PEER_ID,
desc.rx_mpdu_info.meta_data);
rxcb->seq_no = FIELD_GET(RX_MPDU_DESC_INFO0_SEQ_NUM,
desc.rx_mpdu_info.info0);
rxcb->tid = FIELD_GET(HAL_REO_DEST_RING_INFO0_RX_QUEUE_NUM,
desc.info0);
rxcb->mac_id = mac_id;
__skb_queue_tail(&msdu_list, msdu);
if (total_msdu_reaped >= quota && !rxcb->is_continuation) {
@ -2969,6 +3051,8 @@ int ath11k_dp_rx_process_mon_status(struct ath11k_base *ab, int mac_id,
struct ath11k_peer *peer;
struct ath11k_sta *arsta;
int num_buffs_reaped = 0;
u32 rx_buf_sz;
u16 log_type = 0;
__skb_queue_head_init(&skb_list);
@ -2981,8 +3065,16 @@ int ath11k_dp_rx_process_mon_status(struct ath11k_base *ab, int mac_id,
memset(&ppdu_info, 0, sizeof(ppdu_info));
ppdu_info.peer_id = HAL_INVALID_PEERID;
if (ath11k_debugfs_is_pktlog_rx_stats_enabled(ar))
trace_ath11k_htt_rxdesc(ar, skb->data, DP_RX_BUFFER_SIZE);
if (ath11k_debugfs_is_pktlog_lite_mode_enabled(ar)) {
log_type = ATH11K_PKTLOG_TYPE_LITE_RX;
rx_buf_sz = DP_RX_BUFFER_SIZE_LITE;
} else if (ath11k_debugfs_is_pktlog_rx_stats_enabled(ar)) {
log_type = ATH11K_PKTLOG_TYPE_RX_STATBUF;
rx_buf_sz = DP_RX_BUFFER_SIZE;
}
if (log_type)
trace_ath11k_htt_rxdesc(ar, skb->data, log_type, rx_buf_sz);
hal_status = ath11k_hal_rx_parse_mon_status(ab, &ppdu_info, skb);
@ -3010,7 +3102,7 @@ int ath11k_dp_rx_process_mon_status(struct ath11k_base *ab, int mac_id,
ath11k_dp_rx_update_peer_stats(arsta, &ppdu_info);
if (ath11k_debugfs_is_pktlog_peer_valid(ar, peer->addr))
trace_ath11k_htt_rxdesc(ar, skb->data, DP_RX_BUFFER_SIZE);
trace_ath11k_htt_rxdesc(ar, skb->data, log_type, rx_buf_sz);
spin_unlock_bh(&ab->base_lock);
rcu_read_unlock();
@ -3310,7 +3402,7 @@ static int ath11k_dp_rx_h_defrag_reo_reinject(struct ath11k *ar, struct dp_rx_ti
paddr = dma_map_single(ab->dev, defrag_skb->data,
defrag_skb->len + skb_tailroom(defrag_skb),
DMA_FROM_DEVICE);
DMA_TO_DEVICE);
if (dma_mapping_error(ab->dev, paddr))
return -ENOMEM;
@ -3375,7 +3467,7 @@ err_free_idr:
spin_unlock_bh(&rx_refill_ring->idr_lock);
err_unmap_dma:
dma_unmap_single(ab->dev, paddr, defrag_skb->len + skb_tailroom(defrag_skb),
DMA_FROM_DEVICE);
DMA_TO_DEVICE);
return ret;
}
@ -3941,7 +4033,6 @@ static void ath11k_dp_rx_wbm_err(struct ath11k *ar,
{
struct ath11k_skb_rxcb *rxcb = ATH11K_SKB_RXCB(msdu);
struct ieee80211_rx_status rxs = {0};
struct ieee80211_rx_status *status;
bool drop = true;
switch (rxcb->err_rel_src) {
@ -3961,10 +4052,7 @@ static void ath11k_dp_rx_wbm_err(struct ath11k *ar,
return;
}
status = IEEE80211_SKB_RXCB(msdu);
*status = rxs;
ath11k_dp_rx_deliver_msdu(ar, napi, msdu);
ath11k_dp_rx_deliver_msdu(ar, napi, msdu, &rxs);
}
int ath11k_dp_rx_process_wbm_err(struct ath11k_base *ab,
@ -4848,7 +4936,7 @@ static int ath11k_dp_rx_mon_deliver(struct ath11k *ar, u32 mac_id,
{
struct ath11k_pdev_dp *dp = &ar->dp;
struct sk_buff *mon_skb, *skb_next, *header;
struct ieee80211_rx_status *rxs = &dp->rx_status, *status;
struct ieee80211_rx_status *rxs = &dp->rx_status;
mon_skb = ath11k_dp_rx_mon_merg_msdus(ar, mac_id, head_msdu,
tail_msdu, rxs);
@ -4874,10 +4962,7 @@ static int ath11k_dp_rx_mon_deliver(struct ath11k *ar, u32 mac_id,
}
rxs->flag |= RX_FLAG_ONLY_MONITOR;
status = IEEE80211_SKB_RXCB(mon_skb);
*status = *rxs;
ath11k_dp_rx_deliver_msdu(ar, napi, mon_skb);
ath11k_dp_rx_deliver_msdu(ar, napi, mon_skb, rxs);
mon_skb = skb_next;
} while (mon_skb);
rxs->flag = 0;
@ -5029,7 +5114,7 @@ int ath11k_dp_rx_process_mon_rings(struct ath11k_base *ab, int mac_id,
struct ath11k *ar = ath11k_ab_to_ar(ab, mac_id);
int ret = 0;
if (test_bit(ATH11K_FLAG_MONITOR_ENABLED, &ar->monitor_flags))
if (test_bit(ATH11K_FLAG_MONITOR_STARTED, &ar->monitor_flags))
ret = ath11k_dp_mon_process_rx(ab, mac_id, napi, budget);
else
ret = ath11k_dp_rx_process_mon_status(ab, mac_id, napi, budget);

View File

@ -78,7 +78,7 @@ enum hal_encrypt_type ath11k_dp_tx_get_encrypt_type(u32 cipher)
}
int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
struct sk_buff *skb)
struct ath11k_sta *arsta, struct sk_buff *skb)
{
struct ath11k_base *ab = ar->ab;
struct ath11k_dp *dp = &ab->dp;
@ -145,7 +145,15 @@ tcl_ring_sel:
FIELD_PREP(DP_TX_DESC_ID_MSDU_ID, ret) |
FIELD_PREP(DP_TX_DESC_ID_POOL_ID, pool_id);
ti.encap_type = ath11k_dp_tx_get_encap_type(arvif, skb);
ti.meta_data_flags = arvif->tcl_metadata;
if (ieee80211_has_a4(hdr->frame_control) &&
is_multicast_ether_addr(hdr->addr3) && arsta &&
arsta->use_4addr_set) {
ti.meta_data_flags = arsta->tcl_metadata;
ti.flags0 |= FIELD_PREP(HAL_TCL_DATA_CMD_INFO1_TO_FW, 1);
} else {
ti.meta_data_flags = arvif->tcl_metadata;
}
if (ti.encap_type == HAL_TCL_ENCAP_TYPE_RAW) {
if (skb_cb->flags & ATH11K_SKB_CIPHER_SET) {
@ -614,6 +622,9 @@ int ath11k_dp_tx_send_reo_cmd(struct ath11k_base *ab, struct dp_rx_tid *rx_tid,
struct hal_srng *cmd_ring;
int cmd_num;
if (test_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags))
return -ESHUTDOWN;
cmd_ring = &ab->hal.srng_list[dp->reo_cmd_ring.ring_id];
cmd_num = ath11k_hal_reo_cmd_send(ab, cmd_ring, type, cmd);
@ -1068,12 +1079,16 @@ int ath11k_dp_tx_htt_monitor_mode_ring_config(struct ath11k *ar, bool reset)
for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
ring_id = dp->rx_mon_status_refill_ring[i].refill_buf_ring.ring_id;
if (!reset)
if (!reset) {
tlv_filter.rx_filter =
HTT_RX_MON_FILTER_TLV_FLAGS_MON_STATUS_RING;
else
} else {
tlv_filter = ath11k_mac_mon_status_filter_default;
if (ath11k_debugfs_is_extd_rx_stats_enabled(ar))
tlv_filter.rx_filter = ath11k_debugfs_rx_filter(ar);
}
ret = ath11k_dp_tx_htt_rx_filter_setup(ab, ring_id,
dp->mac_id + i,
HAL_RXDMA_MONITOR_STATUS,

View File

@ -17,7 +17,7 @@ struct ath11k_dp_htt_wbm_tx_status {
int ath11k_dp_tx_htt_h2t_ver_req_msg(struct ath11k_base *ab);
int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
struct sk_buff *skb);
struct ath11k_sta *arsta, struct sk_buff *skb);
void ath11k_dp_tx_completion_handler(struct ath11k_base *ab, int ring_id);
int ath11k_dp_tx_send_reo_cmd(struct ath11k_base *ab, struct dp_rx_tid *rx_tid,
enum hal_reo_cmd_type type,

View File

@ -496,6 +496,8 @@ struct hal_tlv_hdr {
#define RX_MPDU_DESC_INFO0_DA_IDX_TIMEOUT BIT(29)
#define RX_MPDU_DESC_INFO0_RAW_MPDU BIT(30)
#define RX_MPDU_DESC_META_DATA_PEER_ID GENMASK(15, 0)
struct rx_mpdu_desc {
u32 info0; /* %RX_MPDU_DESC_INFO */
u32 meta_data;

View File

@ -97,6 +97,7 @@ static void ath11k_init_wmi_config_qca6390(struct ath11k_base *ab,
config->num_multicast_filter_entries = 0x20;
config->num_wow_filters = 0x16;
config->num_keep_alive_pattern = 0;
config->flag1 |= WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64;
}
static void ath11k_hw_ipq8074_reo_setup(struct ath11k_base *ab)
@ -197,6 +198,7 @@ static void ath11k_init_wmi_config_ipq8074(struct ath11k_base *ab,
config->peer_map_unmap_v2_support = 1;
config->twt_ap_pdev_count = ab->num_radios;
config->twt_ap_sta_count = 1000;
config->flag1 |= WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64;
}
static int ath11k_hw_mac_id_to_pdev_id_ipq8074(struct ath11k_hw_params *hw,
@ -372,6 +374,17 @@ static void ath11k_hw_ipq8074_rx_desc_set_msdu_len(struct hal_rx_desc *desc, u16
desc->u.ipq8074.msdu_start.info1 = __cpu_to_le32(info);
}
static bool ath11k_hw_ipq8074_rx_desc_mac_addr2_valid(struct hal_rx_desc *desc)
{
return __le32_to_cpu(desc->u.ipq8074.mpdu_start.info1) &
RX_MPDU_START_INFO1_MAC_ADDR2_VALID;
}
static u8 *ath11k_hw_ipq8074_rx_desc_mpdu_start_addr2(struct hal_rx_desc *desc)
{
return desc->u.ipq8074.mpdu_start.addr2;
}
static
struct rx_attention *ath11k_hw_ipq8074_rx_desc_get_attention(struct hal_rx_desc *desc)
{
@ -543,6 +556,17 @@ static u8 *ath11k_hw_qcn9074_rx_desc_get_msdu_payload(struct hal_rx_desc *desc)
return &desc->u.qcn9074.msdu_payload[0];
}
static bool ath11k_hw_ipq9074_rx_desc_mac_addr2_valid(struct hal_rx_desc *desc)
{
return __le32_to_cpu(desc->u.qcn9074.mpdu_start.info11) &
RX_MPDU_START_INFO11_MAC_ADDR2_VALID;
}
static u8 *ath11k_hw_ipq9074_rx_desc_mpdu_start_addr2(struct hal_rx_desc *desc)
{
return desc->u.qcn9074.mpdu_start.addr2;
}
static bool ath11k_hw_wcn6855_rx_desc_get_first_msdu(struct hal_rx_desc *desc)
{
return !!FIELD_GET(RX_MSDU_END_INFO2_FIRST_MSDU_WCN6855,
@ -703,6 +727,17 @@ static u8 *ath11k_hw_wcn6855_rx_desc_get_msdu_payload(struct hal_rx_desc *desc)
return &desc->u.wcn6855.msdu_payload[0];
}
static bool ath11k_hw_wcn6855_rx_desc_mac_addr2_valid(struct hal_rx_desc *desc)
{
return __le32_to_cpu(desc->u.wcn6855.mpdu_start.info1) &
RX_MPDU_START_INFO1_MAC_ADDR2_VALID;
}
static u8 *ath11k_hw_wcn6855_rx_desc_mpdu_start_addr2(struct hal_rx_desc *desc)
{
return desc->u.wcn6855.mpdu_start.addr2;
}
static void ath11k_hw_wcn6855_reo_setup(struct ath11k_base *ab)
{
u32 reo_base = HAL_SEQ_WCSS_UMAC_REO_REG;
@ -799,6 +834,8 @@ const struct ath11k_hw_ops ipq8074_ops = {
.rx_desc_get_msdu_payload = ath11k_hw_ipq8074_rx_desc_get_msdu_payload,
.reo_setup = ath11k_hw_ipq8074_reo_setup,
.mpdu_info_get_peerid = ath11k_hw_ipq8074_mpdu_info_get_peerid,
.rx_desc_mac_addr2_valid = ath11k_hw_ipq8074_rx_desc_mac_addr2_valid,
.rx_desc_mpdu_start_addr2 = ath11k_hw_ipq8074_rx_desc_mpdu_start_addr2,
};
const struct ath11k_hw_ops ipq6018_ops = {
@ -835,6 +872,8 @@ const struct ath11k_hw_ops ipq6018_ops = {
.rx_desc_get_msdu_payload = ath11k_hw_ipq8074_rx_desc_get_msdu_payload,
.reo_setup = ath11k_hw_ipq8074_reo_setup,
.mpdu_info_get_peerid = ath11k_hw_ipq8074_mpdu_info_get_peerid,
.rx_desc_mac_addr2_valid = ath11k_hw_ipq8074_rx_desc_mac_addr2_valid,
.rx_desc_mpdu_start_addr2 = ath11k_hw_ipq8074_rx_desc_mpdu_start_addr2,
};
const struct ath11k_hw_ops qca6390_ops = {
@ -871,6 +910,8 @@ const struct ath11k_hw_ops qca6390_ops = {
.rx_desc_get_msdu_payload = ath11k_hw_ipq8074_rx_desc_get_msdu_payload,
.reo_setup = ath11k_hw_ipq8074_reo_setup,
.mpdu_info_get_peerid = ath11k_hw_ipq8074_mpdu_info_get_peerid,
.rx_desc_mac_addr2_valid = ath11k_hw_ipq8074_rx_desc_mac_addr2_valid,
.rx_desc_mpdu_start_addr2 = ath11k_hw_ipq8074_rx_desc_mpdu_start_addr2,
};
const struct ath11k_hw_ops qcn9074_ops = {
@ -907,6 +948,8 @@ const struct ath11k_hw_ops qcn9074_ops = {
.rx_desc_get_msdu_payload = ath11k_hw_qcn9074_rx_desc_get_msdu_payload,
.reo_setup = ath11k_hw_ipq8074_reo_setup,
.mpdu_info_get_peerid = ath11k_hw_ipq8074_mpdu_info_get_peerid,
.rx_desc_mac_addr2_valid = ath11k_hw_ipq9074_rx_desc_mac_addr2_valid,
.rx_desc_mpdu_start_addr2 = ath11k_hw_ipq9074_rx_desc_mpdu_start_addr2,
};
const struct ath11k_hw_ops wcn6855_ops = {
@ -943,6 +986,8 @@ const struct ath11k_hw_ops wcn6855_ops = {
.rx_desc_get_msdu_payload = ath11k_hw_wcn6855_rx_desc_get_msdu_payload,
.reo_setup = ath11k_hw_wcn6855_reo_setup,
.mpdu_info_get_peerid = ath11k_hw_wcn6855_mpdu_info_get_peerid,
.rx_desc_mac_addr2_valid = ath11k_hw_wcn6855_rx_desc_mac_addr2_valid,
.rx_desc_mpdu_start_addr2 = ath11k_hw_wcn6855_rx_desc_mpdu_start_addr2,
};
#define ATH11K_TX_RING_MASK_0 0x1

View File

@ -128,7 +128,7 @@ struct ath11k_hw_params {
struct {
const char *dir;
size_t board_size;
size_t cal_size;
size_t cal_offset;
} fw;
const struct ath11k_hw_ops *hw_ops;
@ -153,7 +153,14 @@ struct ath11k_hw_params {
bool vdev_start_delay;
bool htt_peer_map_v2;
bool tcl_0_only;
u8 spectral_fft_sz;
struct {
u8 fft_sz;
u8 fft_pad_sz;
u8 summary_pad_sz;
u8 fft_hdr_len;
u16 max_fft_bins;
} spectral;
u16 interface_modes;
bool supports_monitor;
@ -202,6 +209,8 @@ struct ath11k_hw_ops {
u8 *(*rx_desc_get_msdu_payload)(struct hal_rx_desc *desc);
void (*reo_setup)(struct ath11k_base *ab);
u16 (*mpdu_info_get_peerid)(u8 *tlv_data);
bool (*rx_desc_mac_addr2_valid)(struct hal_rx_desc *desc);
u8* (*rx_desc_mpdu_start_addr2)(struct hal_rx_desc *desc);
};
extern const struct ath11k_hw_ops ipq8074_ops;

File diff suppressed because it is too large Load Diff

View File

@ -115,6 +115,9 @@ struct ath11k_generic_iter {
#define WMI_MAX_SPATIAL_STREAM 3
#define ATH11K_CHAN_WIDTH_NUM 8
#define ATH11K_BW_NSS_MAP_ENABLE BIT(31)
#define ATH11K_PEER_RX_NSS_160MHZ GENMASK(2, 0)
#define ATH11K_PEER_RX_NSS_80_80MHZ GENMASK(5, 3)
#define ATH11K_OBSS_PD_MAX_THRESHOLD -82
#define ATH11K_OBSS_PD_NON_SRG_MAX_THRESHOLD -62

View File

@ -430,6 +430,8 @@ static void ath11k_pci_force_wake(struct ath11k_base *ab)
static void ath11k_pci_sw_reset(struct ath11k_base *ab, bool power_on)
{
mdelay(100);
if (power_on) {
ath11k_pci_enable_ltssm(ab);
ath11k_pci_clear_all_intrs(ab);
@ -439,9 +441,9 @@ static void ath11k_pci_sw_reset(struct ath11k_base *ab, bool power_on)
}
ath11k_mhi_clear_vector(ab);
ath11k_pci_clear_dbg_registers(ab);
ath11k_pci_soc_global_reset(ab);
ath11k_mhi_set_mhictrl_reset(ab);
ath11k_pci_clear_dbg_registers(ab);
}
int ath11k_pci_get_msi_irq(struct device *dev, unsigned int vector)

View File

@ -251,6 +251,7 @@ int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif,
struct ieee80211_sta *sta, struct peer_create_params *param)
{
struct ath11k_peer *peer;
struct ath11k_sta *arsta;
int ret;
lockdep_assert_held(&ar->conf_mutex);
@ -319,6 +320,16 @@ int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif,
peer->sec_type = HAL_ENCRYPT_TYPE_OPEN;
peer->sec_type_grp = HAL_ENCRYPT_TYPE_OPEN;
if (sta) {
arsta = (struct ath11k_sta *)sta->drv_priv;
arsta->tcl_metadata |= FIELD_PREP(HTT_TCL_META_DATA_TYPE, 0) |
FIELD_PREP(HTT_TCL_META_DATA_PEER_ID,
peer->peer_id);
/* set HTT extension valid bit to 0 by default */
arsta->tcl_metadata &= ~HTT_TCL_META_DATA_VALID_HTT;
}
ar->num_peers++;
spin_unlock_bh(&ar->ab->base_lock);

View File

@ -950,6 +950,78 @@ static struct qmi_elem_info qmi_wlanfw_cap_resp_msg_v01_ei[] = {
.offset = offsetof(struct qmi_wlanfw_cap_resp_msg_v01,
num_macs),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x16,
.offset = offsetof(struct qmi_wlanfw_cap_resp_msg_v01,
voltage_mv_valid),
},
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size = sizeof(u32),
.array_type = NO_ARRAY,
.tlv_type = 0x16,
.offset = offsetof(struct qmi_wlanfw_cap_resp_msg_v01,
voltage_mv),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x17,
.offset = offsetof(struct qmi_wlanfw_cap_resp_msg_v01,
time_freq_hz_valid),
},
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size = sizeof(u32),
.array_type = NO_ARRAY,
.tlv_type = 0x17,
.offset = offsetof(struct qmi_wlanfw_cap_resp_msg_v01,
time_freq_hz),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x18,
.offset = offsetof(struct qmi_wlanfw_cap_resp_msg_v01,
otp_version_valid),
},
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size = sizeof(u32),
.array_type = NO_ARRAY,
.tlv_type = 0x18,
.offset = offsetof(struct qmi_wlanfw_cap_resp_msg_v01,
otp_version),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x19,
.offset = offsetof(struct qmi_wlanfw_cap_resp_msg_v01,
eeprom_read_timeout_valid),
},
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size = sizeof(u32),
.array_type = NO_ARRAY,
.tlv_type = 0x19,
.offset = offsetof(struct qmi_wlanfw_cap_resp_msg_v01,
eeprom_read_timeout),
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
@ -1770,7 +1842,7 @@ static int ath11k_qmi_alloc_target_mem_chunk(struct ath11k_base *ab)
chunk->vaddr = dma_alloc_coherent(ab->dev,
chunk->size,
&chunk->paddr,
GFP_KERNEL);
GFP_KERNEL | __GFP_NOWARN);
if (!chunk->vaddr) {
if (ab->qmi.mem_seg_count <= ATH11K_QMI_FW_MEM_REQ_SEGMENT_CNT) {
ath11k_dbg(ab, ATH11K_DBG_QMI,
@ -1846,8 +1918,8 @@ static int ath11k_qmi_request_target_cap(struct ath11k_base *ab)
memset(&req, 0, sizeof(req));
memset(&resp, 0, sizeof(resp));
ret = qmi_txn_init(&ab->qmi.handle, &txn,
qmi_wlanfw_cap_resp_msg_v01_ei, &resp);
ret = qmi_txn_init(&ab->qmi.handle, &txn, qmi_wlanfw_cap_resp_msg_v01_ei,
&resp);
if (ret < 0)
goto out;
@ -1900,6 +1972,12 @@ static int ath11k_qmi_request_target_cap(struct ath11k_base *ab)
strlcpy(ab->qmi.target.fw_build_id, resp.fw_build_id,
sizeof(ab->qmi.target.fw_build_id));
if (resp.eeprom_read_timeout_valid) {
ab->qmi.target.eeprom_caldata =
resp.eeprom_read_timeout;
ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi cal data supported from eeprom\n");
}
ath11k_info(ab, "chip_id 0x%x chip_family 0x%x board_id 0x%x soc_id 0x%x\n",
ab->qmi.target.chip_id, ab->qmi.target.chip_family,
ab->qmi.target.board_id, ab->qmi.target.soc_id);
@ -1917,173 +1995,41 @@ out:
return ret;
}
static int
ath11k_qmi_prepare_bdf_download(struct ath11k_base *ab, int type,
struct qmi_wlanfw_bdf_download_req_msg_v01 *req,
void __iomem *bdf_addr)
{
const struct firmware *fw_entry;
struct ath11k_board_data bd;
u32 fw_size;
int ret;
switch (type) {
case ATH11K_QMI_FILE_TYPE_BDF_GOLDEN:
memset(&bd, 0, sizeof(bd));
ret = ath11k_core_fetch_bdf(ab, &bd);
if (ret) {
ath11k_warn(ab, "failed to load board file: %d\n", ret);
return ret;
}
fw_size = min_t(u32, ab->hw_params.fw.board_size, bd.len);
memcpy_toio(bdf_addr, bd.data, fw_size);
ath11k_core_free_bdf(ab, &bd);
break;
case ATH11K_QMI_FILE_TYPE_CALDATA:
fw_entry = ath11k_core_firmware_request(ab, ATH11K_DEFAULT_CAL_FILE);
if (IS_ERR(fw_entry)) {
ret = PTR_ERR(fw_entry);
ath11k_warn(ab, "failed to load %s: %d\n",
ATH11K_DEFAULT_CAL_FILE, ret);
return ret;
}
fw_size = min_t(u32, ab->hw_params.fw.board_size,
fw_entry->size);
memcpy_toio(bdf_addr + ATH11K_QMI_CALDATA_OFFSET,
fw_entry->data, fw_size);
release_firmware(fw_entry);
break;
default:
return -EINVAL;
}
req->total_size = fw_size;
return 0;
}
static int ath11k_qmi_load_bdf_fixed_addr(struct ath11k_base *ab)
static int ath11k_qmi_load_file_target_mem(struct ath11k_base *ab,
const u8 *data, u32 len, u8 type)
{
struct qmi_wlanfw_bdf_download_req_msg_v01 *req;
struct qmi_wlanfw_bdf_download_resp_msg_v01 resp;
struct qmi_txn txn = {};
const u8 *temp = data;
void __iomem *bdf_addr = NULL;
int type, ret;
req = kzalloc(sizeof(*req), GFP_KERNEL);
if (!req)
return -ENOMEM;
memset(&resp, 0, sizeof(resp));
bdf_addr = ioremap(ab->hw_params.bdf_addr, ATH11K_QMI_BDF_MAX_SIZE);
if (!bdf_addr) {
ath11k_warn(ab, "failed ioremap for board file\n");
ret = -EIO;
goto out;
}
for (type = 0; type < ATH11K_QMI_MAX_FILE_TYPE; type++) {
req->valid = 1;
req->file_id_valid = 1;
req->file_id = ab->qmi.target.board_id;
req->total_size_valid = 1;
req->seg_id_valid = 1;
req->seg_id = type;
req->data_valid = 0;
req->data_len = ATH11K_QMI_MAX_BDF_FILE_NAME_SIZE;
req->bdf_type = 0;
req->bdf_type_valid = 0;
req->end_valid = 1;
req->end = 1;
ret = ath11k_qmi_prepare_bdf_download(ab, type, req, bdf_addr);
if (ret < 0)
goto out_qmi_bdf;
ret = qmi_txn_init(&ab->qmi.handle, &txn,
qmi_wlanfw_bdf_download_resp_msg_v01_ei,
&resp);
if (ret < 0)
goto out_qmi_bdf;
ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi bdf download req fixed addr type %d\n",
type);
ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
QMI_WLANFW_BDF_DOWNLOAD_REQ_V01,
QMI_WLANFW_BDF_DOWNLOAD_REQ_MSG_V01_MAX_LEN,
qmi_wlanfw_bdf_download_req_msg_v01_ei, req);
if (ret < 0) {
qmi_txn_cancel(&txn);
goto out_qmi_bdf;
}
ret = qmi_txn_wait(&txn, msecs_to_jiffies(ATH11K_QMI_WLANFW_TIMEOUT_MS));
if (ret < 0)
goto out_qmi_bdf;
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
ath11k_warn(ab, "board file download request failed: %d %d\n",
resp.resp.result, resp.resp.error);
ret = -EINVAL;
goto out_qmi_bdf;
}
}
out_qmi_bdf:
iounmap(bdf_addr);
out:
kfree(req);
return ret;
}
static int ath11k_qmi_load_bdf_qmi(struct ath11k_base *ab)
{
struct qmi_wlanfw_bdf_download_req_msg_v01 *req;
struct qmi_wlanfw_bdf_download_resp_msg_v01 resp;
struct ath11k_board_data bd;
unsigned int remaining;
struct qmi_txn txn = {};
int ret;
const u8 *temp;
int bdf_type;
u32 remaining = len;
req = kzalloc(sizeof(*req), GFP_KERNEL);
if (!req)
return -ENOMEM;
memset(&resp, 0, sizeof(resp));
memset(&bd, 0, sizeof(bd));
ret = ath11k_core_fetch_bdf(ab, &bd);
if (ret) {
ath11k_warn(ab, "failed to fetch board file: %d\n", ret);
goto out;
if (ab->bus_params.fixed_bdf_addr) {
bdf_addr = ioremap(ab->hw_params.bdf_addr, ab->hw_params.fw.board_size);
if (!bdf_addr) {
ath11k_warn(ab, "qmi ioremap error for bdf_addr\n");
ret = -EIO;
goto err_free_req;
}
}
temp = bd.data;
remaining = bd.len;
if (bd.len >= SELFMAG && memcmp(bd.data, ELFMAG, SELFMAG) == 0)
bdf_type = ATH11K_QMI_BDF_TYPE_ELF;
else
bdf_type = ATH11K_QMI_BDF_TYPE_BIN;
ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi bdf_type %d\n", bdf_type);
while (remaining) {
req->valid = 1;
req->file_id_valid = 1;
req->file_id = ab->qmi.target.board_id;
req->total_size_valid = 1;
req->total_size = bd.len;
req->total_size = remaining;
req->seg_id_valid = 1;
req->data_valid = 1;
req->data_len = ATH11K_QMI_MAX_BDF_FILE_NAME_SIZE;
req->bdf_type = bdf_type;
req->bdf_type = type;
req->bdf_type_valid = 1;
req->end_valid = 1;
req->end = 0;
@ -2095,16 +2041,30 @@ static int ath11k_qmi_load_bdf_qmi(struct ath11k_base *ab)
req->end = 1;
}
memcpy(req->data, temp, req->data_len);
if (ab->bus_params.fixed_bdf_addr ||
type == ATH11K_QMI_FILE_TYPE_EEPROM) {
req->data_valid = 0;
req->end = 1;
req->data_len = ATH11K_QMI_MAX_BDF_FILE_NAME_SIZE;
} else {
memcpy(req->data, temp, req->data_len);
}
if (ab->bus_params.fixed_bdf_addr) {
if (type == ATH11K_QMI_FILE_TYPE_CALDATA)
bdf_addr += ab->hw_params.fw.cal_offset;
memcpy_toio(bdf_addr, temp, len);
}
ret = qmi_txn_init(&ab->qmi.handle, &txn,
qmi_wlanfw_bdf_download_resp_msg_v01_ei,
&resp);
if (ret < 0)
goto out_qmi_bdf;
goto err_iounmap;
ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi bdf download request remaining %i\n",
remaining);
ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi bdf download req fixed addr type %d\n",
type);
ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
QMI_WLANFW_BDF_DOWNLOAD_REQ_V01,
@ -2112,29 +2072,124 @@ static int ath11k_qmi_load_bdf_qmi(struct ath11k_base *ab)
qmi_wlanfw_bdf_download_req_msg_v01_ei, req);
if (ret < 0) {
qmi_txn_cancel(&txn);
goto out_qmi_bdf;
goto err_iounmap;
}
ret = qmi_txn_wait(&txn, msecs_to_jiffies(ATH11K_QMI_WLANFW_TIMEOUT_MS));
if (ret < 0)
goto out_qmi_bdf;
if (ret < 0) {
ath11k_warn(ab, "failed to wait board file download request: %d\n",
ret);
goto err_iounmap;
}
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
ath11k_warn(ab, "bdf download request failed: %d %d\n",
ath11k_warn(ab, "board file download request failed: %d %d\n",
resp.resp.result, resp.resp.error);
ret = resp.resp.result;
goto out_qmi_bdf;
ret = -EINVAL;
goto err_iounmap;
}
if (ab->bus_params.fixed_bdf_addr ||
type == ATH11K_QMI_FILE_TYPE_EEPROM) {
remaining = 0;
} else {
remaining -= req->data_len;
temp += req->data_len;
req->seg_id++;
ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi bdf download request remaining %i\n",
remaining);
}
remaining -= req->data_len;
temp += req->data_len;
req->seg_id++;
}
out_qmi_bdf:
ath11k_core_free_bdf(ab, &bd);
err_iounmap:
if (ab->bus_params.fixed_bdf_addr)
iounmap(bdf_addr);
out:
err_free_req:
kfree(req);
return ret;
}
static int ath11k_qmi_load_bdf_qmi(struct ath11k_base *ab)
{
struct device *dev = ab->dev;
char filename[ATH11K_QMI_MAX_BDF_FILE_NAME_SIZE];
const struct firmware *fw_entry;
struct ath11k_board_data bd;
u32 fw_size, file_type;
int ret = 0, bdf_type;
const u8 *tmp;
memset(&bd, 0, sizeof(bd));
ret = ath11k_core_fetch_bdf(ab, &bd);
if (ret) {
ath11k_warn(ab, "qmi failed to fetch board file: %d\n", ret);
goto out;
}
if (bd.len >= SELFMAG && memcmp(bd.data, ELFMAG, SELFMAG) == 0)
bdf_type = ATH11K_QMI_BDF_TYPE_ELF;
else
bdf_type = ATH11K_QMI_BDF_TYPE_BIN;
ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi bdf_type %d\n", bdf_type);
fw_size = bd.len;
fw_size = min_t(u32, ab->hw_params.fw.board_size, bd.len);
ret = ath11k_qmi_load_file_target_mem(ab, bd.data, fw_size, bdf_type);
if (ret < 0) {
ath11k_warn(ab, "qmi failed to load bdf file\n");
goto out;
}
/* QCA6390 does not support cal data, skip it */
if (bdf_type == ATH11K_QMI_BDF_TYPE_ELF)
goto out;
if (ab->qmi.target.eeprom_caldata) {
file_type = ATH11K_QMI_FILE_TYPE_EEPROM;
tmp = filename;
fw_size = ATH11K_QMI_MAX_BDF_FILE_NAME_SIZE;
} else {
file_type = ATH11K_QMI_FILE_TYPE_CALDATA;
/* cal-<bus>-<id>.bin */
snprintf(filename, sizeof(filename), "cal-%s-%s.bin",
ath11k_bus_str(ab->hif.bus), dev_name(dev));
fw_entry = ath11k_core_firmware_request(ab, filename);
if (!IS_ERR(fw_entry))
goto success;
fw_entry = ath11k_core_firmware_request(ab, ATH11K_DEFAULT_CAL_FILE);
if (IS_ERR(fw_entry)) {
ret = PTR_ERR(fw_entry);
ath11k_warn(ab,
"qmi failed to load CAL data file:%s\n",
filename);
goto out;
}
success:
fw_size = min_t(u32, ab->hw_params.fw.board_size, fw_entry->size);
tmp = fw_entry->data;
}
ret = ath11k_qmi_load_file_target_mem(ab, tmp, fw_size, file_type);
if (ret < 0) {
ath11k_warn(ab, "qmi failed to load caldata\n");
goto out_qmi_cal;
}
ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi caldata type: %u\n", file_type);
out_qmi_cal:
if (!ab->qmi.target.eeprom_caldata)
release_firmware(fw_entry);
out:
ath11k_core_free_bdf(ab, &bd);
ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi BDF download sequence completed\n");
return ret;
}
@ -2519,10 +2574,7 @@ static int ath11k_qmi_event_load_bdf(struct ath11k_qmi *qmi)
return ret;
}
if (ab->bus_params.fixed_bdf_addr)
ret = ath11k_qmi_load_bdf_fixed_addr(ab);
else
ret = ath11k_qmi_load_bdf_qmi(ab);
ret = ath11k_qmi_load_bdf_qmi(ab);
if (ret < 0) {
ath11k_warn(ab, "failed to load board data file: %d\n", ret);
return ret;
@ -2707,8 +2759,10 @@ static void ath11k_qmi_driver_event_work(struct work_struct *work)
list_del(&event->list);
spin_unlock(&qmi->event_lock);
if (test_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags))
if (test_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags)) {
kfree(event);
return;
}
switch (event->type) {
case ATH11K_QMI_EVENT_SERVER_ARRIVE:

View File

@ -10,11 +10,9 @@
#include <linux/soc/qcom/qmi.h>
#define ATH11K_HOST_VERSION_STRING "WIN"
#define ATH11K_QMI_WLANFW_TIMEOUT_MS 5000
#define ATH11K_QMI_WLANFW_TIMEOUT_MS 10000
#define ATH11K_QMI_MAX_BDF_FILE_NAME_SIZE 64
#define ATH11K_QMI_CALDB_ADDRESS 0x4BA00000
#define ATH11K_QMI_BDF_MAX_SIZE (256 * 1024)
#define ATH11K_QMI_CALDATA_OFFSET (128 * 1024)
#define ATH11K_QMI_WLANFW_MAX_BUILD_ID_LEN_V01 128
#define ATH11K_QMI_WLFW_SERVICE_ID_V01 0x45
#define ATH11K_QMI_WLFW_SERVICE_VERS_V01 0x01
@ -44,6 +42,7 @@ struct ath11k_base;
enum ath11k_qmi_file_type {
ATH11K_QMI_FILE_TYPE_BDF_GOLDEN,
ATH11K_QMI_FILE_TYPE_CALDATA,
ATH11K_QMI_FILE_TYPE_EEPROM,
ATH11K_QMI_MAX_FILE_TYPE,
};
@ -104,6 +103,7 @@ struct target_info {
u32 board_id;
u32 soc_id;
u32 fw_version;
u32 eeprom_caldata;
char fw_build_timestamp[ATH11K_QMI_WLANFW_MAX_TIMESTAMP_LEN_V01 + 1];
char fw_build_id[ATH11K_QMI_WLANFW_MAX_BUILD_ID_LEN_V01 + 1];
char bdf_ext[ATH11K_QMI_BDF_EXT_STR_LENGTH];
@ -135,7 +135,7 @@ struct ath11k_qmi {
wait_queue_head_t cold_boot_waitq;
};
#define QMI_WLANFW_HOST_CAP_REQ_MSG_V01_MAX_LEN 189
#define QMI_WLANFW_HOST_CAP_REQ_MSG_V01_MAX_LEN 261
#define QMI_WLANFW_HOST_CAP_REQ_V01 0x0034
#define QMI_WLANFW_HOST_CAP_RESP_MSG_V01_MAX_LEN 7
#define QMI_WLFW_HOST_CAP_RESP_V01 0x0034
@ -285,7 +285,7 @@ struct qmi_wlanfw_fw_cold_cal_done_ind_msg_v01 {
};
#define QMI_WLANFW_CAP_REQ_MSG_V01_MAX_LEN 0
#define QMI_WLANFW_CAP_RESP_MSG_V01_MAX_LEN 207
#define QMI_WLANFW_CAP_RESP_MSG_V01_MAX_LEN 235
#define QMI_WLANFW_CAP_REQ_V01 0x0024
#define QMI_WLANFW_CAP_RESP_V01 0x0024
@ -366,6 +366,14 @@ struct qmi_wlanfw_cap_resp_msg_v01 {
char fw_build_id[ATH11K_QMI_WLANFW_MAX_BUILD_ID_LEN_V01 + 1];
u8 num_macs_valid;
u8 num_macs;
u8 voltage_mv_valid;
u32 voltage_mv;
u8 time_freq_hz_valid;
u32 time_freq_hz;
u8 otp_version_valid;
u32 otp_version;
u8 eeprom_read_timeout_valid;
u32 eeprom_read_timeout;
};
struct qmi_wlanfw_cap_req_msg_v01 {

View File

@ -97,7 +97,6 @@ int ath11k_reg_update_chan_list(struct ath11k *ar)
struct channel_param *ch;
enum nl80211_band band;
int num_channels = 0;
int params_len;
int i, ret;
bands = hw->wiphy->bands;
@ -117,10 +116,8 @@ int ath11k_reg_update_chan_list(struct ath11k *ar)
if (WARN_ON(!num_channels))
return -EINVAL;
params_len = sizeof(struct scan_chan_list_params) +
num_channels * sizeof(struct channel_param);
params = kzalloc(params_len, GFP_KERNEL);
params = kzalloc(struct_size(params, ch_param, num_channels),
GFP_KERNEL);
if (!params)
return -ENOMEM;
@ -198,7 +195,7 @@ static void ath11k_copy_regd(struct ieee80211_regdomain *regd_orig,
sizeof(struct ieee80211_reg_rule));
}
int ath11k_regd_update(struct ath11k *ar, bool init)
int ath11k_regd_update(struct ath11k *ar)
{
struct ieee80211_regdomain *regd, *regd_copy = NULL;
int ret, regd_len, pdev_id;
@ -209,7 +206,10 @@ int ath11k_regd_update(struct ath11k *ar, bool init)
spin_lock_bh(&ab->base_lock);
if (init) {
/* Prefer the latest regd update over default if it's available */
if (ab->new_regd[pdev_id]) {
regd = ab->new_regd[pdev_id];
} else {
/* Apply the regd received during init through
* WMI_REG_CHAN_LIST_CC event. In case of failure to
* receive the regd, initialize with a default world
@ -222,8 +222,6 @@ int ath11k_regd_update(struct ath11k *ar, bool init)
"failed to receive default regd during init\n");
regd = (struct ieee80211_regdomain *)&ath11k_world_regd;
}
} else {
regd = ab->new_regd[pdev_id];
}
if (!regd) {
@ -683,7 +681,7 @@ void ath11k_regd_update_work(struct work_struct *work)
regd_update_work);
int ret;
ret = ath11k_regd_update(ar, false);
ret = ath11k_regd_update(ar);
if (ret) {
/* Firmware has already moved to the new regd. We need
* to maintain channel consistency across FW, Host driver

View File

@ -31,6 +31,6 @@ void ath11k_regd_update_work(struct work_struct *work);
struct ieee80211_regdomain *
ath11k_reg_build_regd(struct ath11k_base *ab,
struct cur_regulatory_info *reg_info, bool intersect);
int ath11k_regd_update(struct ath11k *ar, bool init);
int ath11k_regd_update(struct ath11k *ar);
int ath11k_reg_update_chan_list(struct ath11k *ar);
#endif

View File

@ -11,22 +11,20 @@
#define ATH11K_SPECTRAL_EVENT_TIMEOUT_MS 1
#define ATH11K_SPECTRAL_DWORD_SIZE 4
/* HW bug, expected BIN size is 2 bytes but HW report as 4 bytes */
#define ATH11K_SPECTRAL_BIN_SIZE 4
#define ATH11K_SPECTRAL_ATH11K_MIN_BINS 64
#define ATH11K_SPECTRAL_ATH11K_MIN_IB_BINS 32
#define ATH11K_SPECTRAL_ATH11K_MAX_IB_BINS 256
#define ATH11K_SPECTRAL_MIN_BINS 32
#define ATH11K_SPECTRAL_MIN_IB_BINS (ATH11K_SPECTRAL_MIN_BINS >> 1)
#define ATH11K_SPECTRAL_MAX_IB_BINS(x) ((x)->hw_params.spectral.max_fft_bins >> 1)
#define ATH11K_SPECTRAL_SCAN_COUNT_MAX 4095
/* Max channel computed by sum of 2g and 5g band channels */
#define ATH11K_SPECTRAL_TOTAL_CHANNEL 41
#define ATH11K_SPECTRAL_SAMPLES_PER_CHANNEL 70
#define ATH11K_SPECTRAL_PER_SAMPLE_SIZE (sizeof(struct fft_sample_ath11k) + \
ATH11K_SPECTRAL_ATH11K_MAX_IB_BINS)
#define ATH11K_SPECTRAL_PER_SAMPLE_SIZE(x) (sizeof(struct fft_sample_ath11k) + \
ATH11K_SPECTRAL_MAX_IB_BINS(x))
#define ATH11K_SPECTRAL_TOTAL_SAMPLE (ATH11K_SPECTRAL_TOTAL_CHANNEL * \
ATH11K_SPECTRAL_SAMPLES_PER_CHANNEL)
#define ATH11K_SPECTRAL_SUB_BUFF_SIZE ATH11K_SPECTRAL_PER_SAMPLE_SIZE
#define ATH11K_SPECTRAL_SUB_BUFF_SIZE(x) ATH11K_SPECTRAL_PER_SAMPLE_SIZE(x)
#define ATH11K_SPECTRAL_NUM_SUB_BUF ATH11K_SPECTRAL_TOTAL_SAMPLE
#define ATH11K_SPECTRAL_20MHZ 20
@ -444,8 +442,8 @@ static ssize_t ath11k_write_file_spectral_bins(struct file *file,
if (kstrtoul(buf, 0, &val))
return -EINVAL;
if (val < ATH11K_SPECTRAL_ATH11K_MIN_BINS ||
val > SPECTRAL_ATH11K_MAX_NUM_BINS)
if (val < ATH11K_SPECTRAL_MIN_BINS ||
val > ar->ab->hw_params.spectral.max_fft_bins)
return -EINVAL;
if (!is_power_of_2(val))
@ -581,12 +579,12 @@ int ath11k_spectral_process_fft(struct ath11k *ar,
struct spectral_tlv *tlv;
int tlv_len, bin_len, num_bins;
u16 length, freq;
u8 chan_width_mhz;
u8 chan_width_mhz, bin_sz;
int ret;
lockdep_assert_held(&ar->spectral.lock);
if (!ab->hw_params.spectral_fft_sz) {
if (!ab->hw_params.spectral.fft_sz) {
ath11k_warn(ab, "invalid bin size type for hw rev %d\n",
ab->hw_rev);
return -EINVAL;
@ -596,7 +594,7 @@ int ath11k_spectral_process_fft(struct ath11k *ar,
tlv_len = FIELD_GET(SPECTRAL_TLV_HDR_LEN, __le32_to_cpu(tlv->header));
/* convert Dword into bytes */
tlv_len *= ATH11K_SPECTRAL_DWORD_SIZE;
bin_len = tlv_len - (sizeof(*fft_report) - sizeof(*tlv));
bin_len = tlv_len - ab->hw_params.spectral.fft_hdr_len;
if (data_len < (bin_len + sizeof(*fft_report))) {
ath11k_warn(ab, "mismatch in expected bin len %d and data len %d\n",
@ -604,12 +602,13 @@ int ath11k_spectral_process_fft(struct ath11k *ar,
return -EINVAL;
}
num_bins = bin_len / ATH11K_SPECTRAL_BIN_SIZE;
bin_sz = ab->hw_params.spectral.fft_sz + ab->hw_params.spectral.fft_pad_sz;
num_bins = bin_len / bin_sz;
/* Only In-band bins are useful to user for visualize */
num_bins >>= 1;
if (num_bins < ATH11K_SPECTRAL_ATH11K_MIN_IB_BINS ||
num_bins > ATH11K_SPECTRAL_ATH11K_MAX_IB_BINS ||
if (num_bins < ATH11K_SPECTRAL_MIN_IB_BINS ||
num_bins > ATH11K_SPECTRAL_MAX_IB_BINS(ab) ||
!is_power_of_2(num_bins)) {
ath11k_warn(ab, "Invalid num of bins %d\n", num_bins);
return -EINVAL;
@ -654,7 +653,7 @@ int ath11k_spectral_process_fft(struct ath11k *ar,
fft_sample->freq2 = __cpu_to_be16(freq);
ath11k_spectral_parse_fft(fft_sample->data, fft_report->bins, num_bins,
ab->hw_params.spectral_fft_sz);
ab->hw_params.spectral.fft_sz);
fft_sample->max_exp = ath11k_spectral_get_max_exp(fft_sample->max_index,
search.peak_mag,
@ -690,7 +689,7 @@ static int ath11k_spectral_process_data(struct ath11k *ar,
goto unlock;
}
sample_sz = sizeof(*fft_sample) + ATH11K_SPECTRAL_ATH11K_MAX_IB_BINS;
sample_sz = sizeof(*fft_sample) + ATH11K_SPECTRAL_MAX_IB_BINS(ab);
fft_sample = kmalloc(sample_sz, GFP_ATOMIC);
if (!fft_sample) {
ret = -ENOBUFS;
@ -738,7 +737,8 @@ static int ath11k_spectral_process_data(struct ath11k *ar,
* is 4 DWORD size (16 bytes).
* Need to remove this workaround once HW bug fixed
*/
tlv_len = sizeof(*summary) - sizeof(*tlv);
tlv_len = sizeof(*summary) - sizeof(*tlv) +
ab->hw_params.spectral.summary_pad_sz;
if (tlv_len < (sizeof(*summary) - sizeof(*tlv))) {
ath11k_warn(ab, "failed to parse spectral summary at bytes %d tlv_len:%d\n",
@ -901,7 +901,7 @@ static inline int ath11k_spectral_debug_register(struct ath11k *ar)
ar->spectral.rfs_scan = relay_open("spectral_scan",
ar->debug.debugfs_pdev,
ATH11K_SPECTRAL_SUB_BUFF_SIZE,
ATH11K_SPECTRAL_SUB_BUFF_SIZE(ar->ab),
ATH11K_SPECTRAL_NUM_SUB_BUF,
&rfs_scan_cb, NULL);
if (!ar->spectral.rfs_scan) {
@ -962,7 +962,7 @@ int ath11k_spectral_init(struct ath11k_base *ab)
ab->wmi_ab.svc_map))
return 0;
if (!ab->hw_params.spectral_fft_sz)
if (!ab->hw_params.spectral.fft_sz)
return 0;
for (i = 0; i < ab->num_radios; i++) {

View File

@ -79,14 +79,15 @@ TRACE_EVENT(ath11k_htt_ppdu_stats,
);
TRACE_EVENT(ath11k_htt_rxdesc,
TP_PROTO(struct ath11k *ar, const void *data, size_t len),
TP_PROTO(struct ath11k *ar, const void *data, size_t log_type, size_t len),
TP_ARGS(ar, data, len),
TP_ARGS(ar, data, log_type, len),
TP_STRUCT__entry(
__string(device, dev_name(ar->ab->dev))
__string(driver, dev_driver_string(ar->ab->dev))
__field(u16, len)
__field(u16, log_type)
__dynamic_array(u8, rxdesc, len)
),
@ -94,14 +95,16 @@ TRACE_EVENT(ath11k_htt_rxdesc,
__assign_str(device, dev_name(ar->ab->dev));
__assign_str(driver, dev_driver_string(ar->ab->dev));
__entry->len = len;
__entry->log_type = log_type;
memcpy(__get_dynamic_array(rxdesc), data, len);
),
TP_printk(
"%s %s rxdesc len %d",
"%s %s rxdesc len %d type %d",
__get_str(driver),
__get_str(device),
__entry->len
__entry->len,
__entry->log_type
)
);

View File

@ -360,6 +360,10 @@ ath11k_pull_mac_phy_cap_svc_ready_ext(struct ath11k_pdev_wmi *wmi_handle,
pdev_cap->he_mcs = mac_phy_caps->he_supp_mcs_5g;
pdev_cap->tx_chain_mask = mac_phy_caps->tx_chain_mask_5g;
pdev_cap->rx_chain_mask = mac_phy_caps->rx_chain_mask_5g;
pdev_cap->nss_ratio_enabled =
WMI_NSS_RATIO_ENABLE_DISABLE_GET(mac_phy_caps->nss_ratio);
pdev_cap->nss_ratio_info =
WMI_NSS_RATIO_INFO_GET(mac_phy_caps->nss_ratio);
} else {
return -EINVAL;
}
@ -403,18 +407,18 @@ ath11k_pull_mac_phy_cap_svc_ready_ext(struct ath11k_pdev_wmi *wmi_handle,
sizeof(u32) * PSOC_HOST_MAX_PHY_SIZE);
memcpy(&cap_band->he_ppet, &mac_phy_caps->he_ppet5g,
sizeof(struct ath11k_ppe_threshold));
}
cap_band = &pdev_cap->band[NL80211_BAND_6GHZ];
cap_band->max_bw_supported = mac_phy_caps->max_bw_supported_5g;
cap_band->ht_cap_info = mac_phy_caps->ht_cap_info_5g;
cap_band->he_cap_info[0] = mac_phy_caps->he_cap_info_5g;
cap_band->he_cap_info[1] = mac_phy_caps->he_cap_info_5g_ext;
cap_band->he_mcs = mac_phy_caps->he_supp_mcs_5g;
memcpy(cap_band->he_cap_phy_info, &mac_phy_caps->he_cap_phy_info_5g,
sizeof(u32) * PSOC_HOST_MAX_PHY_SIZE);
memcpy(&cap_band->he_ppet, &mac_phy_caps->he_ppet5g,
sizeof(struct ath11k_ppe_threshold));
cap_band = &pdev_cap->band[NL80211_BAND_6GHZ];
cap_band->max_bw_supported = mac_phy_caps->max_bw_supported_5g;
cap_band->ht_cap_info = mac_phy_caps->ht_cap_info_5g;
cap_band->he_cap_info[0] = mac_phy_caps->he_cap_info_5g;
cap_band->he_cap_info[1] = mac_phy_caps->he_cap_info_5g_ext;
cap_band->he_mcs = mac_phy_caps->he_supp_mcs_5g;
memcpy(cap_band->he_cap_phy_info, &mac_phy_caps->he_cap_phy_info_5g,
sizeof(u32) * PSOC_HOST_MAX_PHY_SIZE);
memcpy(&cap_band->he_ppet, &mac_phy_caps->he_ppet5g,
sizeof(struct ath11k_ppe_threshold));
}
return 0;
}
@ -783,14 +787,26 @@ int ath11k_wmi_vdev_down(struct ath11k *ar, u8 vdev_id)
static void ath11k_wmi_put_wmi_channel(struct wmi_channel *chan,
struct wmi_vdev_start_req_arg *arg)
{
u32 center_freq1 = arg->channel.band_center_freq1;
memset(chan, 0, sizeof(*chan));
chan->mhz = arg->channel.freq;
chan->band_center_freq1 = arg->channel.band_center_freq1;
if (arg->channel.mode == MODE_11AC_VHT80_80)
if (arg->channel.mode == MODE_11AX_HE160) {
if (arg->channel.freq > arg->channel.band_center_freq1)
chan->band_center_freq1 = center_freq1 + 40;
else
chan->band_center_freq1 = center_freq1 - 40;
chan->band_center_freq2 = arg->channel.band_center_freq1;
} else if (arg->channel.mode == MODE_11AC_VHT80_80) {
chan->band_center_freq2 = arg->channel.band_center_freq2;
else
} else {
chan->band_center_freq2 = 0;
}
chan->info |= FIELD_PREP(WMI_CHAN_INFO_MODE, arg->channel.mode);
if (arg->channel.passive)
@ -868,6 +884,8 @@ int ath11k_wmi_vdev_start(struct ath11k *ar, struct wmi_vdev_start_req_arg *arg,
}
cmd->flags |= WMI_VDEV_START_LDPC_RX_ENABLED;
if (test_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags))
cmd->flags |= WMI_VDEV_START_HW_ENCRYPTION_DISABLED;
ptr = skb->data + sizeof(*cmd);
chan = ptr;
@ -1339,6 +1357,7 @@ int ath11k_wmi_pdev_bss_chan_info_request(struct ath11k *ar,
WMI_TAG_PDEV_BSS_CHAN_INFO_REQUEST) |
FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
cmd->req_type = type;
cmd->pdev_id = ar->pdev->pdev_id;
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
"WMI bss chan info req type %d\n", type);
@ -1903,8 +1922,8 @@ int ath11k_wmi_send_peer_assoc_cmd(struct ath11k *ar,
FIELD_PREP(WMI_TLV_LEN,
sizeof(*he_mcs) - TLV_HDR_SIZE);
he_mcs->rx_mcs_set = param->peer_he_rx_mcs_set[i];
he_mcs->tx_mcs_set = param->peer_he_tx_mcs_set[i];
he_mcs->rx_mcs_set = param->peer_he_tx_mcs_set[i];
he_mcs->tx_mcs_set = param->peer_he_rx_mcs_set[i];
ptr += sizeof(*he_mcs);
}
@ -2285,7 +2304,7 @@ int ath11k_wmi_send_scan_chan_list_cmd(struct ath11k *ar,
u16 num_send_chans, num_sends = 0, max_chan_limit = 0;
u32 *reg1, *reg2;
tchan_info = &chan_list->ch_param[0];
tchan_info = chan_list->ch_param;
while (chan_list->nallchans) {
len = sizeof(*cmd) + TLV_HDR_SIZE;
max_chan_limit = (wmi->wmi_ab->max_msg_len[ar->pdev_idx] - len) /
@ -3495,7 +3514,7 @@ ath11k_wmi_copy_resource_config(struct wmi_resource_config *wmi_cfg,
wmi_cfg->bpf_instruction_size = tg_cfg->bpf_instruction_size;
wmi_cfg->max_bssid_rx_filters = tg_cfg->max_bssid_rx_filters;
wmi_cfg->use_pdev_id = tg_cfg->use_pdev_id;
wmi_cfg->flag1 = tg_cfg->atf_config;
wmi_cfg->flag1 = tg_cfg->flag1;
wmi_cfg->peer_map_unmap_v2_support = tg_cfg->peer_map_unmap_v2_support;
wmi_cfg->sched_params = tg_cfg->sched_params;
wmi_cfg->twt_ap_pdev_count = tg_cfg->twt_ap_pdev_count;
@ -5234,9 +5253,11 @@ ath11k_wmi_pull_pdev_stats_tx(const struct wmi_pdev_stats_tx *src,
dst->hw_queued = src->hw_queued;
dst->hw_reaped = src->hw_reaped;
dst->underrun = src->underrun;
dst->hw_paused = src->hw_paused;
dst->tx_abort = src->tx_abort;
dst->mpdus_requeued = src->mpdus_requeued;
dst->tx_ko = src->tx_ko;
dst->tx_xretry = src->tx_xretry;
dst->data_rc = src->data_rc;
dst->self_triggers = src->self_triggers;
dst->sw_retry_failure = src->sw_retry_failure;
@ -5247,6 +5268,16 @@ ath11k_wmi_pull_pdev_stats_tx(const struct wmi_pdev_stats_tx *src,
dst->stateless_tid_alloc_failure = src->stateless_tid_alloc_failure;
dst->phy_underrun = src->phy_underrun;
dst->txop_ovf = src->txop_ovf;
dst->seq_posted = src->seq_posted;
dst->seq_failed_queueing = src->seq_failed_queueing;
dst->seq_completed = src->seq_completed;
dst->seq_restarted = src->seq_restarted;
dst->mu_seq_posted = src->mu_seq_posted;
dst->mpdus_sw_flush = src->mpdus_sw_flush;
dst->mpdus_hw_filter = src->mpdus_hw_filter;
dst->mpdus_truncated = src->mpdus_truncated;
dst->mpdus_ack_failed = src->mpdus_ack_failed;
dst->mpdus_expired = src->mpdus_expired;
}
static void ath11k_wmi_pull_pdev_stats_rx(const struct wmi_pdev_stats_rx *src,
@ -5266,6 +5297,7 @@ static void ath11k_wmi_pull_pdev_stats_rx(const struct wmi_pdev_stats_rx *src,
dst->phy_errs = src->phy_errs;
dst->phy_err_drop = src->phy_err_drop;
dst->mpdu_errs = src->mpdu_errs;
dst->rx_ovfl_errs = src->rx_ovfl_errs;
}
static void
@ -5502,12 +5534,16 @@ ath11k_wmi_fw_pdev_tx_stats_fill(const struct ath11k_fw_stats_pdev *pdev,
"PPDUs reaped", pdev->hw_reaped);
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
"Num underruns", pdev->underrun);
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
"Num HW Paused", pdev->hw_paused);
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
"PPDUs cleaned", pdev->tx_abort);
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
"MPDUs requeued", pdev->mpdus_requeued);
len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
"Excessive retries", pdev->tx_ko);
"PPDU OK", pdev->tx_ko);
len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
"Excessive retries", pdev->tx_xretry);
len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
"HW rate", pdev->data_rc);
len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
@ -5531,6 +5567,26 @@ ath11k_wmi_fw_pdev_tx_stats_fill(const struct ath11k_fw_stats_pdev *pdev,
"PHY underrun", pdev->phy_underrun);
len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
"MPDU is more than txop limit", pdev->txop_ovf);
len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
"Num sequences posted", pdev->seq_posted);
len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
"Num seq failed queueing ", pdev->seq_failed_queueing);
len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
"Num sequences completed ", pdev->seq_completed);
len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
"Num sequences restarted ", pdev->seq_restarted);
len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
"Num of MU sequences posted ", pdev->mu_seq_posted);
len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
"Num of MPDUS SW flushed ", pdev->mpdus_sw_flush);
len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
"Num of MPDUS HW filtered ", pdev->mpdus_hw_filter);
len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
"Num of MPDUS truncated ", pdev->mpdus_truncated);
len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
"Num of MPDUS ACK failed ", pdev->mpdus_ack_failed);
len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
"Num of MPDUS expired ", pdev->mpdus_expired);
*length = len;
}
@ -5575,6 +5631,8 @@ ath11k_wmi_fw_pdev_rx_stats_fill(const struct ath11k_fw_stats_pdev *pdev,
"PHY errors drops", pdev->phy_err_drop);
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
"MPDU errors (FCS, MIC, ENC)", pdev->mpdu_errs);
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
"Overflow errors", pdev->rx_ovfl_errs);
*length = len;
}
@ -5792,6 +5850,17 @@ static int ath11k_reg_chan_list_event(struct ath11k_base *ab, struct sk_buff *sk
pdev_idx = reg_info->phy_id;
/* Avoid default reg rule updates sent during FW recovery if
* it is already available
*/
spin_lock(&ab->base_lock);
if (test_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags) &&
ab->default_regd[pdev_idx]) {
spin_unlock(&ab->base_lock);
goto mem_free;
}
spin_unlock(&ab->base_lock);
if (pdev_idx >= ab->num_radios) {
/* Process the event for phy0 only if single_pdev_only
* is true. If pdev_idx is valid but not 0, discard the
@ -5829,10 +5898,10 @@ static int ath11k_reg_chan_list_event(struct ath11k_base *ab, struct sk_buff *sk
}
spin_lock(&ab->base_lock);
if (test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags)) {
/* Once mac is registered, ar is valid and all CC events from
* fw is considered to be received due to user requests
* currently.
if (ab->default_regd[pdev_idx]) {
/* The initial rules from FW after WMI Init is to build
* the default regd. From then on, any rules updated for
* the pdev could be due to user reg changes.
* Free previously built regd before assigning the newly
* generated regd to ar. NULL pointer handling will be
* taken care by kfree itself.
@ -5842,13 +5911,9 @@ static int ath11k_reg_chan_list_event(struct ath11k_base *ab, struct sk_buff *sk
ab->new_regd[pdev_idx] = regd;
ieee80211_queue_work(ar->hw, &ar->regd_update_work);
} else {
/* Multiple events for the same *ar is not expected. But we
* can still clear any previously stored default_regd if we
* are receiving this event for the same radio by mistake.
* NULL pointer handling will be taken care by kfree itself.
/* This regd would be applied during mac registration and is
* held constant throughout for regd intersection purpose
*/
kfree(ab->default_regd[pdev_idx]);
/* This regd would be applied during mac registration */
ab->default_regd[pdev_idx] = regd;
}
ab->dfs_region = reg_info->dfs_region;
@ -6119,8 +6184,10 @@ static void ath11k_mgmt_rx_event(struct ath11k_base *ab, struct sk_buff *skb)
if (rx_ev.status & WMI_RX_STATUS_ERR_MIC)
status->flag |= RX_FLAG_MMIC_ERROR;
if (rx_ev.chan_freq >= ATH11K_MIN_6G_FREQ) {
if (rx_ev.chan_freq >= ATH11K_MIN_6G_FREQ &&
rx_ev.chan_freq <= ATH11K_MAX_6G_FREQ) {
status->band = NL80211_BAND_6GHZ;
status->freq = rx_ev.chan_freq;
} else if (rx_ev.channel >= 1 && rx_ev.channel <= 14) {
status->band = NL80211_BAND_2GHZ;
} else if (rx_ev.channel >= 36 && rx_ev.channel <= ATH11K_MAX_5G_CHAN) {
@ -6141,8 +6208,10 @@ static void ath11k_mgmt_rx_event(struct ath11k_base *ab, struct sk_buff *skb)
sband = &ar->mac.sbands[status->band];
status->freq = ieee80211_channel_to_frequency(rx_ev.channel,
status->band);
if (status->band != NL80211_BAND_6GHZ)
status->freq = ieee80211_channel_to_frequency(rx_ev.channel,
status->band);
status->signal = rx_ev.snr + ATH11K_DEFAULT_NOISE_FLOOR;
status->rate_idx = ath11k_mac_bitrate_to_idx(sband, rx_ev.rate / 100);
@ -6220,8 +6289,9 @@ exit:
rcu_read_unlock();
}
static struct ath11k *ath11k_get_ar_on_scan_abort(struct ath11k_base *ab,
u32 vdev_id)
static struct ath11k *ath11k_get_ar_on_scan_state(struct ath11k_base *ab,
u32 vdev_id,
enum ath11k_scan_state state)
{
int i;
struct ath11k_pdev *pdev;
@ -6233,7 +6303,7 @@ static struct ath11k *ath11k_get_ar_on_scan_abort(struct ath11k_base *ab,
ar = pdev->ar;
spin_lock_bh(&ar->data_lock);
if (ar->scan.state == ATH11K_SCAN_ABORTING &&
if (ar->scan.state == state &&
ar->scan.vdev_id == vdev_id) {
spin_unlock_bh(&ar->data_lock);
return ar;
@ -6263,10 +6333,15 @@ static void ath11k_scan_event(struct ath11k_base *ab, struct sk_buff *skb)
* aborting scan's vdev id matches this event info.
*/
if (scan_ev.event_type == WMI_SCAN_EVENT_COMPLETED &&
scan_ev.reason == WMI_SCAN_REASON_CANCELLED)
ar = ath11k_get_ar_on_scan_abort(ab, scan_ev.vdev_id);
else
scan_ev.reason == WMI_SCAN_REASON_CANCELLED) {
ar = ath11k_get_ar_on_scan_state(ab, scan_ev.vdev_id,
ATH11K_SCAN_ABORTING);
if (!ar)
ar = ath11k_get_ar_on_scan_state(ab, scan_ev.vdev_id,
ATH11K_SCAN_RUNNING);
} else {
ar = ath11k_mac_get_ar_by_vdev_id(ab, scan_ev.vdev_id);
}
if (!ar) {
ath11k_warn(ab, "Received scan event for unknown vdev");
@ -6301,6 +6376,8 @@ static void ath11k_scan_event(struct ath11k_base *ab, struct sk_buff *skb)
ath11k_wmi_event_scan_start_failed(ar);
break;
case WMI_SCAN_EVENT_DEQUEUED:
__ath11k_mac_scan_finish(ar);
break;
case WMI_SCAN_EVENT_PREEMPTED:
case WMI_SCAN_EVENT_RESTARTED:
case WMI_SCAN_EVENT_FOREIGN_CHAN_EXIT:
@ -7065,6 +7142,7 @@ static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb)
case WMI_TWT_ENABLE_EVENTID:
case WMI_TWT_DISABLE_EVENTID:
case WMI_PDEV_DMA_RING_CFG_RSP_EVENTID:
case WMI_PEER_CREATE_CONF_EVENTID:
ath11k_dbg(ab, ATH11K_DBG_WMI,
"ignoring unsupported event 0x%x\n", id);
break;

View File

@ -119,6 +119,22 @@ enum {
WMI_HOST_WLAN_2G_5G_CAP = 0x3,
};
/* Parameters used for WMI_VDEV_PARAM_AUTORATE_MISC_CFG command.
* Used only for HE auto rate mode.
*/
enum {
/* HE LTF related configuration */
WMI_HE_AUTORATE_LTF_1X = BIT(0),
WMI_HE_AUTORATE_LTF_2X = BIT(1),
WMI_HE_AUTORATE_LTF_4X = BIT(2),
/* HE GI related configuration */
WMI_AUTORATE_400NS_GI = BIT(8),
WMI_AUTORATE_800NS_GI = BIT(9),
WMI_AUTORATE_1600NS_GI = BIT(10),
WMI_AUTORATE_3200NS_GI = BIT(11),
};
/*
* wmi command groups.
*/
@ -647,6 +663,9 @@ enum wmi_tlv_event_id {
WMI_PEER_RESERVED9_EVENTID,
WMI_PEER_RESERVED10_EVENTID,
WMI_PEER_OPER_MODE_CHANGE_EVENTID,
WMI_PEER_TX_PN_RESPONSE_EVENTID,
WMI_PEER_CFR_CAPTURE_EVENTID,
WMI_PEER_CREATE_CONF_EVENTID,
WMI_MGMT_RX_EVENTID = WMI_TLV_CMD(WMI_GRP_MGMT),
WMI_HOST_SWBA_EVENTID,
WMI_TBTTOFFSET_UPDATE_EVENTID,
@ -1044,7 +1063,9 @@ enum wmi_tlv_vdev_param {
WMI_VDEV_PARAM_HE_RANGE_EXT,
WMI_VDEV_PARAM_ENABLE_BCAST_PROBE_RESPONSE,
WMI_VDEV_PARAM_FILS_MAX_CHANNEL_GUARD_TIME,
WMI_VDEV_PARAM_HE_LTF = 0x74,
WMI_VDEV_PARAM_BA_MODE = 0x7e,
WMI_VDEV_PARAM_AUTORATE_MISC_CFG = 0x80,
WMI_VDEV_PARAM_SET_HE_SOUNDING_MODE = 0x87,
WMI_VDEV_PARAM_6GHZ_PARAMS = 0x99,
WMI_VDEV_PARAM_PROTOTYPE = 0x8000,
@ -2128,6 +2149,24 @@ enum wmi_direct_buffer_module {
WMI_DIRECT_BUF_MAX
};
/* enum wmi_nss_ratio - NSS ratio received from FW during service ready ext
* event
* WMI_NSS_RATIO_1BY2_NSS -Max nss of 160MHz is equals to half of the max nss
* of 80MHz
* WMI_NSS_RATIO_3BY4_NSS - Max nss of 160MHz is equals to 3/4 of the max nss
* of 80MHz
* WMI_NSS_RATIO_1_NSS - Max nss of 160MHz is equals to the max nss of 80MHz
* WMI_NSS_RATIO_2_NSS - Max nss of 160MHz is equals to two times the max
* nss of 80MHz
*/
enum wmi_nss_ratio {
WMI_NSS_RATIO_1BY2_NSS = 0x0,
WMI_NSS_RATIO_3BY4_NSS = 0x1,
WMI_NSS_RATIO_1_NSS = 0x2,
WMI_NSS_RATIO_2_NSS = 0x3,
};
struct wmi_host_pdev_band_to_mac {
u32 pdev_id;
u32 start_freq;
@ -2244,6 +2283,8 @@ struct wmi_init_cmd {
u32 num_host_mem_chunks;
} __packed;
#define WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64 BIT(5)
struct wmi_resource_config {
u32 tlv_header;
u32 num_vdevs;
@ -2370,6 +2411,12 @@ struct wmi_hw_mode_capabilities {
} __packed;
#define WMI_MAX_HECAP_PHY_SIZE (3)
#define WMI_NSS_RATIO_ENABLE_DISABLE_BITPOS BIT(0)
#define WMI_NSS_RATIO_ENABLE_DISABLE_GET(_val) \
FIELD_GET(WMI_NSS_RATIO_ENABLE_DISABLE_BITPOS, _val)
#define WMI_NSS_RATIO_INFO_BITPOS GENMASK(4, 1)
#define WMI_NSS_RATIO_INFO_GET(_val) \
FIELD_GET(WMI_NSS_RATIO_INFO_BITPOS, _val)
struct wmi_mac_phy_capabilities {
u32 hw_mode_id;
@ -2403,6 +2450,12 @@ struct wmi_mac_phy_capabilities {
u32 he_cap_info_2g_ext;
u32 he_cap_info_5g_ext;
u32 he_cap_info_internal;
u32 wireless_modes;
u32 low_2ghz_chan_freq;
u32 high_2ghz_chan_freq;
u32 low_5ghz_chan_freq;
u32 high_5ghz_chan_freq;
u32 nss_ratio;
} __packed;
struct wmi_hal_reg_capabilities_ext {
@ -2527,6 +2580,7 @@ struct wmi_vdev_down_cmd {
#define WMI_VDEV_START_HIDDEN_SSID BIT(0)
#define WMI_VDEV_START_PMF_ENABLED BIT(1)
#define WMI_VDEV_START_LDPC_RX_ENABLED BIT(3)
#define WMI_VDEV_START_HW_ENCRYPTION_DISABLED BIT(4)
struct wmi_ssid {
u32 ssid_len;
@ -2960,6 +3014,7 @@ struct wmi_pdev_bss_chan_info_req_cmd {
u32 tlv_header;
/* ref wmi_bss_chan_info_req_type */
u32 req_type;
u32 pdev_id;
} __packed;
struct wmi_ap_ps_peer_cmd {
@ -3608,7 +3663,7 @@ struct wmi_stop_scan_cmd {
struct scan_chan_list_params {
u32 pdev_id;
u16 nallchans;
struct channel_param ch_param[1];
struct channel_param ch_param[];
};
struct wmi_scan_chan_list_cmd {
@ -3917,7 +3972,11 @@ struct wmi_vht_rate_set {
struct wmi_he_rate_set {
u32 tlv_header;
/* MCS at which the peer can receive */
u32 rx_mcs_set;
/* MCS at which the peer can transmit */
u32 tx_mcs_set;
} __packed;
@ -4056,7 +4115,6 @@ struct wmi_vdev_stopped_event {
} __packed;
struct wmi_pdev_bss_chan_info_event {
u32 pdev_id;
u32 freq; /* Units in MHz */
u32 noise_floor; /* units are dBm */
/* rx clear - how often the channel was unused */
@ -4074,6 +4132,7 @@ struct wmi_pdev_bss_chan_info_event {
/*rx_cycle cnt for my bss in 64bits format */
u32 rx_bss_cycle_count_low;
u32 rx_bss_cycle_count_high;
u32 pdev_id;
} __packed;
#define WMI_VDEV_INSTALL_KEY_COMPL_STATUS_SUCCESS 0
@ -4168,6 +4227,9 @@ struct wmi_pdev_stats_tx {
/* Num underruns */
s32 underrun;
/* Num hw paused */
u32 hw_paused;
/* Num PPDUs cleaned up in TX abort */
s32 tx_abort;
@ -4177,6 +4239,8 @@ struct wmi_pdev_stats_tx {
/* excessive retries */
u32 tx_ko;
u32 tx_xretry;
/* data hw rate code */
u32 data_rc;
@ -4206,6 +4270,40 @@ struct wmi_pdev_stats_tx {
/* MPDU is more than txop limit */
u32 txop_ovf;
/* Num sequences posted */
u32 seq_posted;
/* Num sequences failed in queueing */
u32 seq_failed_queueing;
/* Num sequences completed */
u32 seq_completed;
/* Num sequences restarted */
u32 seq_restarted;
/* Num of MU sequences posted */
u32 mu_seq_posted;
/* Num MPDUs flushed by SW, HWPAUSED, SW TXABORT
* (Reset,channel change)
*/
s32 mpdus_sw_flush;
/* Num MPDUs filtered by HW, all filter condition (TTL expired) */
s32 mpdus_hw_filter;
/* Num MPDUs truncated by PDG (TXOP, TBTT,
* PPDU_duration based on rate, dyn_bw)
*/
s32 mpdus_truncated;
/* Num MPDUs that was tried but didn't receive ACK or BA */
s32 mpdus_ack_failed;
/* Num MPDUs that was dropped du to expiry. */
s32 mpdus_expired;
} __packed;
struct wmi_pdev_stats_rx {
@ -4240,6 +4338,9 @@ struct wmi_pdev_stats_rx {
/* Number of mpdu errors - FCS, MIC, ENC etc. */
s32 mpdu_errs;
/* Num overflow errors */
s32 rx_ovfl_errs;
} __packed;
struct wmi_pdev_stats {
@ -5014,7 +5115,7 @@ struct target_resource_config {
u32 vo_minfree;
u32 rx_batchmode;
u32 tt_support;
u32 atf_config;
u32 flag1;
u32 iphdr_pad_config;
u32 qwrap_config:16,
alloc_frag_desc_for_data_pkt:16;

View File

@ -19,9 +19,14 @@
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/ath9k_platform.h>
#include <linux/nvmem-consumer.h>
#include <linux/workqueue.h>
struct owl_ctx {
struct pci_dev *pdev;
struct completion eeprom_load;
struct work_struct work;
struct nvmem_cell *cell;
};
#define EEPROM_FILENAME_LEN 100
@ -42,6 +47,12 @@ static int ath9k_pci_fixup(struct pci_dev *pdev, const u16 *cal_data,
u32 bar0;
bool swap_needed = false;
/* also note that we are doing *u16 operations on the file */
if (cal_len > 4096 || cal_len < 0x200 || (cal_len & 1) == 1) {
dev_err(&pdev->dev, "eeprom has an invalid size.\n");
return -EINVAL;
}
if (*cal_data != AR5416_EEPROM_MAGIC) {
if (*cal_data != swab16(AR5416_EEPROM_MAGIC)) {
dev_err(&pdev->dev, "invalid calibration data\n");
@ -99,38 +110,31 @@ static int ath9k_pci_fixup(struct pci_dev *pdev, const u16 *cal_data,
return 0;
}
static void owl_fw_cb(const struct firmware *fw, void *context)
static void owl_rescan(struct pci_dev *pdev)
{
struct pci_dev *pdev = (struct pci_dev *)context;
struct owl_ctx *ctx = (struct owl_ctx *)pci_get_drvdata(pdev);
struct pci_bus *bus;
complete(&ctx->eeprom_load);
if (!fw) {
dev_err(&pdev->dev, "no eeprom data received.\n");
goto release;
}
/* also note that we are doing *u16 operations on the file */
if (fw->size > 4096 || fw->size < 0x200 || (fw->size & 1) == 1) {
dev_err(&pdev->dev, "eeprom file has an invalid size.\n");
goto release;
}
if (ath9k_pci_fixup(pdev, (const u16 *)fw->data, fw->size))
goto release;
struct pci_bus *bus = pdev->bus;
pci_lock_rescan_remove();
bus = pdev->bus;
pci_stop_and_remove_bus_device(pdev);
/* the device should come back with the proper
* ProductId. But we have to initiate a rescan.
*/
pci_rescan_bus(bus);
pci_unlock_rescan_remove();
}
release:
static void owl_fw_cb(const struct firmware *fw, void *context)
{
struct owl_ctx *ctx = (struct owl_ctx *)context;
complete(&ctx->eeprom_load);
if (fw) {
ath9k_pci_fixup(ctx->pdev, (const u16 *)fw->data, fw->size);
owl_rescan(ctx->pdev);
} else {
dev_err(&ctx->pdev->dev, "no eeprom data received.\n");
}
release_firmware(fw);
}
@ -152,6 +156,43 @@ static const char *owl_get_eeprom_name(struct pci_dev *pdev)
return eeprom_name;
}
static void owl_nvmem_work(struct work_struct *work)
{
struct owl_ctx *ctx = container_of(work, struct owl_ctx, work);
void *buf;
size_t len;
complete(&ctx->eeprom_load);
buf = nvmem_cell_read(ctx->cell, &len);
if (!IS_ERR(buf)) {
ath9k_pci_fixup(ctx->pdev, buf, len);
kfree(buf);
owl_rescan(ctx->pdev);
} else {
dev_err(&ctx->pdev->dev, "no nvmem data received.\n");
}
}
static int owl_nvmem_probe(struct owl_ctx *ctx)
{
int err;
ctx->cell = devm_nvmem_cell_get(&ctx->pdev->dev, "calibration");
if (IS_ERR(ctx->cell)) {
err = PTR_ERR(ctx->cell);
if (err == -ENOENT || err == -EOPNOTSUPP)
return 1; /* not present, try firmware_request */
return err;
}
INIT_WORK(&ctx->work, owl_nvmem_work);
schedule_work(&ctx->work);
return 0;
}
static int owl_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
@ -164,21 +205,27 @@ static int owl_probe(struct pci_dev *pdev,
pcim_pin_device(pdev);
ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
if (!ctx)
return -ENOMEM;
init_completion(&ctx->eeprom_load);
ctx->pdev = pdev;
pci_set_drvdata(pdev, ctx);
err = owl_nvmem_probe(ctx);
if (err <= 0)
return err;
eeprom_name = owl_get_eeprom_name(pdev);
if (!eeprom_name) {
dev_err(&pdev->dev, "no eeprom filename found.\n");
return -ENODEV;
}
ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
if (!ctx)
return -ENOMEM;
init_completion(&ctx->eeprom_load);
pci_set_drvdata(pdev, ctx);
err = request_firmware_nowait(THIS_MODULE, true, eeprom_name,
&pdev->dev, GFP_KERNEL, pdev, owl_fw_cb);
&pdev->dev, GFP_KERNEL, ctx, owl_fw_cb);
if (err)
dev_err(&pdev->dev, "failed to request caldata (%d).\n", err);

View File

@ -135,13 +135,23 @@ static bool ath9k_hw_nvram_read_firmware(const struct firmware *eeprom_blob,
offset, data);
}
static bool ath9k_hw_nvram_read_nvmem(struct ath_hw *ah, off_t offset,
u16 *data)
{
return ath9k_hw_nvram_read_array(ah->nvmem_blob,
ah->nvmem_blob_len / sizeof(u16),
offset, data);
}
bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data)
{
struct ath_common *common = ath9k_hw_common(ah);
struct ath9k_platform_data *pdata = ah->dev->platform_data;
bool ret;
if (ah->eeprom_blob)
if (ah->nvmem_blob)
ret = ath9k_hw_nvram_read_nvmem(ah, off, data);
else if (ah->eeprom_blob)
ret = ath9k_hw_nvram_read_firmware(ah->eeprom_blob, off, data);
else if (pdata && !pdata->use_eeprom)
ret = ath9k_hw_nvram_read_pdata(pdata, off, data);

View File

@ -977,6 +977,8 @@ struct ath_hw {
bool disable_5ghz;
const struct firmware *eeprom_blob;
u16 *nvmem_blob; /* devres managed */
size_t nvmem_blob_len;
struct ath_dynack dynack;

View File

@ -22,6 +22,7 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_net.h>
#include <linux/nvmem-consumer.h>
#include <linux/relay.h>
#include <linux/dmi.h>
#include <net/ieee80211_radiotap.h>
@ -568,6 +569,57 @@ static void ath9k_eeprom_release(struct ath_softc *sc)
release_firmware(sc->sc_ah->eeprom_blob);
}
static int ath9k_nvmem_request_eeprom(struct ath_softc *sc)
{
struct ath_hw *ah = sc->sc_ah;
struct nvmem_cell *cell;
void *buf;
size_t len;
int err;
cell = devm_nvmem_cell_get(sc->dev, "calibration");
if (IS_ERR(cell)) {
err = PTR_ERR(cell);
/* nvmem cell might not be defined, or the nvmem
* subsystem isn't included. In this case, follow
* the established "just return 0;" convention of
* ath9k_init_platform to say:
* "All good. Nothing to see here. Please go on."
*/
if (err == -ENOENT || err == -EOPNOTSUPP)
return 0;
return err;
}
buf = nvmem_cell_read(cell, &len);
if (IS_ERR(buf))
return PTR_ERR(buf);
/* run basic sanity checks on the returned nvram cell length.
* That length has to be a multiple of a "u16" (i.e.: & 1).
* Furthermore, it has to be more than "let's say" 512 bytes
* but less than the maximum of AR9300_EEPROM_SIZE (16kb).
*/
if ((len & 1) == 1 || len < 512 || len >= AR9300_EEPROM_SIZE) {
kfree(buf);
return -EINVAL;
}
/* devres manages the calibration values release on shutdown */
ah->nvmem_blob = (u16 *)devm_kmemdup(sc->dev, buf, len, GFP_KERNEL);
kfree(buf);
if (IS_ERR(ah->nvmem_blob))
return PTR_ERR(ah->nvmem_blob);
ah->nvmem_blob_len = len;
ah->ah_flags &= ~AH_USE_EEPROM;
ah->ah_flags |= AH_NO_EEP_SWAP;
return 0;
}
static int ath9k_init_platform(struct ath_softc *sc)
{
struct ath9k_platform_data *pdata = sc->dev->platform_data;
@ -704,6 +756,10 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
if (ret)
return ret;
ret = ath9k_nvmem_request_eeprom(sc);
if (ret)
return ret;
if (ath9k_led_active_high != -1)
ah->config.led_active_high = ath9k_led_active_high == 1;

View File

@ -24,7 +24,6 @@
* could be acquired so far.
*/
#define SPECTRAL_ATH10K_MAX_NUM_BINS 256
#define SPECTRAL_ATH11K_MAX_NUM_BINS 512
/* FFT sample format given to userspace via debugfs.
*

View File

@ -120,7 +120,7 @@ static ssize_t write_file_dump(struct file *file,
if (begin == NULL)
break;
if (kstrtou32(begin, 0, &arg[i]) != 0)
if (kstrtos32(begin, 0, &arg[i]) != 0)
break;
}

View File

@ -3384,11 +3384,11 @@ struct tl_hal_flush_ac_rsp_msg {
struct wcn36xx_hal_enter_imps_req_msg {
struct wcn36xx_hal_msg_header header;
};
} __packed;
struct wcn36xx_hal_exit_imps_req {
struct wcn36xx_hal_exit_imps_req_msg {
struct wcn36xx_hal_msg_header header;
};
} __packed;
struct wcn36xx_hal_enter_bmps_req_msg {
struct wcn36xx_hal_msg_header header;

View File

@ -432,6 +432,13 @@ static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed)
if (changed & IEEE80211_CONF_CHANGE_PS)
wcn36xx_change_ps(wcn, hw->conf.flags & IEEE80211_CONF_PS);
if (changed & IEEE80211_CONF_CHANGE_IDLE) {
if (hw->conf.flags & IEEE80211_CONF_IDLE)
wcn36xx_smd_enter_imps(wcn);
else
wcn36xx_smd_exit_imps(wcn);
}
mutex_unlock(&wcn->conf_mutex);
return 0;
@ -569,12 +576,14 @@ static int wcn36xx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
if (IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags) {
sta_priv->is_data_encrypted = true;
/* Reconfigure bss with encrypt_type */
if (NL80211_IFTYPE_STATION == vif->type)
if (NL80211_IFTYPE_STATION == vif->type) {
wcn36xx_smd_config_bss(wcn,
vif,
sta,
sta->addr,
true);
wcn36xx_smd_config_sta(wcn, vif, sta);
}
wcn36xx_smd_set_stakey(wcn,
vif_priv->encrypt_type,

View File

@ -2184,6 +2184,59 @@ out:
return ret;
}
int wcn36xx_smd_enter_imps(struct wcn36xx *wcn)
{
struct wcn36xx_hal_enter_imps_req_msg msg_body;
int ret;
mutex_lock(&wcn->hal_mutex);
INIT_HAL_MSG(msg_body, WCN36XX_HAL_ENTER_IMPS_REQ);
PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
if (ret) {
wcn36xx_err("Sending hal_enter_imps failed\n");
goto out;
}
ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
if (ret) {
wcn36xx_err("hal_enter_imps response failed err=%d\n", ret);
goto out;
}
wcn36xx_dbg(WCN36XX_DBG_HAL, "Entered idle mode\n");
out:
mutex_unlock(&wcn->hal_mutex);
return ret;
}
int wcn36xx_smd_exit_imps(struct wcn36xx *wcn)
{
struct wcn36xx_hal_exit_imps_req_msg msg_body;
int ret;
mutex_lock(&wcn->hal_mutex);
INIT_HAL_MSG(msg_body, WCN36XX_HAL_EXIT_IMPS_REQ);
PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
if (ret) {
wcn36xx_err("Sending hal_exit_imps failed\n");
goto out;
}
ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
if (ret) {
wcn36xx_err("hal_exit_imps response failed err=%d\n", ret);
goto out;
}
wcn36xx_dbg(WCN36XX_DBG_HAL, "Exited idle mode\n");
out:
mutex_unlock(&wcn->hal_mutex);
return ret;
}
int wcn36xx_smd_set_power_params(struct wcn36xx *wcn, bool ignore_dtim)
{
struct wcn36xx_hal_set_power_params_req_msg msg_body;
@ -2623,30 +2676,52 @@ static int wcn36xx_smd_delete_sta_context_ind(struct wcn36xx *wcn,
size_t len)
{
struct wcn36xx_hal_delete_sta_context_ind_msg *rsp = buf;
struct wcn36xx_vif *tmp;
struct wcn36xx_vif *vif_priv;
struct ieee80211_vif *vif;
struct ieee80211_bss_conf *bss_conf;
struct ieee80211_sta *sta;
bool found = false;
if (len != sizeof(*rsp)) {
wcn36xx_warn("Corrupted delete sta indication\n");
return -EIO;
}
wcn36xx_dbg(WCN36XX_DBG_HAL, "delete station indication %pM index %d\n",
rsp->addr2, rsp->sta_id);
wcn36xx_dbg(WCN36XX_DBG_HAL,
"delete station indication %pM index %d reason %d\n",
rsp->addr2, rsp->sta_id, rsp->reason_code);
list_for_each_entry(tmp, &wcn->vif_list, list) {
list_for_each_entry(vif_priv, &wcn->vif_list, list) {
rcu_read_lock();
sta = ieee80211_find_sta(wcn36xx_priv_to_vif(tmp), rsp->addr2);
if (sta)
ieee80211_report_low_ack(sta, 0);
vif = wcn36xx_priv_to_vif(vif_priv);
if (vif->type == NL80211_IFTYPE_STATION) {
/* We could call ieee80211_find_sta too, but checking
* bss_conf is clearer.
*/
bss_conf = &vif->bss_conf;
if (vif_priv->sta_assoc &&
!memcmp(bss_conf->bssid, rsp->addr2, ETH_ALEN)) {
found = true;
wcn36xx_dbg(WCN36XX_DBG_HAL,
"connection loss bss_index %d\n",
vif_priv->bss_index);
ieee80211_connection_loss(vif);
}
} else {
sta = ieee80211_find_sta(vif, rsp->addr2);
if (sta) {
found = true;
ieee80211_report_low_ack(sta, 0);
}
}
rcu_read_unlock();
if (sta)
if (found)
return 0;
}
wcn36xx_warn("STA with addr %pM and index %d not found\n",
rsp->addr2,
rsp->sta_id);
wcn36xx_warn("BSS or STA with addr %pM not found\n", rsp->addr2);
return -ENOENT;
}
@ -3060,6 +3135,8 @@ int wcn36xx_smd_rsp_process(struct rpmsg_device *rpdev,
case WCN36XX_HAL_GTK_OFFLOAD_RSP:
case WCN36XX_HAL_GTK_OFFLOAD_GETINFO_RSP:
case WCN36XX_HAL_HOST_RESUME_RSP:
case WCN36XX_HAL_ENTER_IMPS_RSP:
case WCN36XX_HAL_EXIT_IMPS_RSP:
memcpy(wcn->hal_buf, buf, len);
wcn->hal_rsp_len = len;
complete(&wcn->hal_rsp_compl);

View File

@ -163,4 +163,7 @@ int wcn36xx_smd_wlan_host_suspend_ind(struct wcn36xx *wcn);
int wcn36xx_smd_host_resume(struct wcn36xx *wcn);
int wcn36xx_smd_enter_imps(struct wcn36xx *wcn);
int wcn36xx_smd_exit_imps(struct wcn36xx *wcn);
#endif /* _SMD_H_ */

View File

@ -2084,6 +2084,7 @@ int ieee80211_get_vht_max_nss(struct ieee80211_vht_cap *cap,
#define IEEE80211_HE_VHT_MAX_AMPDU_FACTOR 20
#define IEEE80211_HE_HT_MAX_AMPDU_FACTOR 16
#define IEEE80211_HE_6GHZ_MAX_AMPDU_FACTOR 13
/* 802.11ax HE PHY capabilities */
#define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G 0x02