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:
commit
b3fcf9c5fa
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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
|
||||
)
|
||||
);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue