Merge ath-next from git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
ath.git patches for 5.1. Major changes: ath10k * more preparation for SDIO support wil6210 * support up to 20 stations in AP mode
This commit is contained in:
Коммит
501faf7102
|
@ -1066,8 +1066,8 @@ EXPORT_SYMBOL(ath10k_ce_revoke_recv_next);
|
|||
* Guts of ath10k_ce_completed_send_next.
|
||||
* The caller takes responsibility for any necessary locking.
|
||||
*/
|
||||
int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
|
||||
void **per_transfer_contextp)
|
||||
static int _ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
|
||||
void **per_transfer_contextp)
|
||||
{
|
||||
struct ath10k_ce_ring *src_ring = ce_state->src_ring;
|
||||
u32 ctrl_addr = ce_state->ctrl_addr;
|
||||
|
@ -1118,6 +1118,66 @@ int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _ath10k_ce_completed_send_next_nolock_64(struct ath10k_ce_pipe *ce_state,
|
||||
void **per_transfer_contextp)
|
||||
{
|
||||
struct ath10k_ce_ring *src_ring = ce_state->src_ring;
|
||||
u32 ctrl_addr = ce_state->ctrl_addr;
|
||||
struct ath10k *ar = ce_state->ar;
|
||||
unsigned int nentries_mask = src_ring->nentries_mask;
|
||||
unsigned int sw_index = src_ring->sw_index;
|
||||
unsigned int read_index;
|
||||
struct ce_desc_64 *desc;
|
||||
|
||||
if (src_ring->hw_index == sw_index) {
|
||||
/*
|
||||
* The SW completion index has caught up with the cached
|
||||
* version of the HW completion index.
|
||||
* Update the cached HW completion index to see whether
|
||||
* the SW has really caught up to the HW, or if the cached
|
||||
* value of the HW index has become stale.
|
||||
*/
|
||||
|
||||
read_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr);
|
||||
if (read_index == 0xffffffff)
|
||||
return -ENODEV;
|
||||
|
||||
read_index &= nentries_mask;
|
||||
src_ring->hw_index = read_index;
|
||||
}
|
||||
|
||||
if (ar->hw_params.rri_on_ddr)
|
||||
read_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr);
|
||||
else
|
||||
read_index = src_ring->hw_index;
|
||||
|
||||
if (read_index == sw_index)
|
||||
return -EIO;
|
||||
|
||||
if (per_transfer_contextp)
|
||||
*per_transfer_contextp =
|
||||
src_ring->per_transfer_context[sw_index];
|
||||
|
||||
/* sanity */
|
||||
src_ring->per_transfer_context[sw_index] = NULL;
|
||||
desc = CE_SRC_RING_TO_DESC_64(src_ring->base_addr_owner_space,
|
||||
sw_index);
|
||||
desc->nbytes = 0;
|
||||
|
||||
/* Update sw_index */
|
||||
sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index);
|
||||
src_ring->sw_index = sw_index;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
|
||||
void **per_transfer_contextp)
|
||||
{
|
||||
return ce_state->ops->ce_completed_send_next_nolock(ce_state,
|
||||
per_transfer_contextp);
|
||||
}
|
||||
EXPORT_SYMBOL(ath10k_ce_completed_send_next_nolock);
|
||||
|
||||
static void ath10k_ce_extract_desc_data(struct ath10k *ar,
|
||||
|
@ -1839,6 +1899,7 @@ static const struct ath10k_ce_ops ce_ops = {
|
|||
.ce_send_nolock = _ath10k_ce_send_nolock,
|
||||
.ce_set_src_ring_base_addr_hi = NULL,
|
||||
.ce_set_dest_ring_base_addr_hi = NULL,
|
||||
.ce_completed_send_next_nolock = _ath10k_ce_completed_send_next_nolock,
|
||||
};
|
||||
|
||||
static const struct ath10k_ce_ops ce_64_ops = {
|
||||
|
@ -1853,6 +1914,7 @@ static const struct ath10k_ce_ops ce_64_ops = {
|
|||
.ce_send_nolock = _ath10k_ce_send_nolock_64,
|
||||
.ce_set_src_ring_base_addr_hi = ath10k_ce_set_src_ring_base_addr_hi,
|
||||
.ce_set_dest_ring_base_addr_hi = ath10k_ce_set_dest_ring_base_addr_hi,
|
||||
.ce_completed_send_next_nolock = _ath10k_ce_completed_send_next_nolock_64,
|
||||
};
|
||||
|
||||
static void ath10k_ce_set_ops(struct ath10k *ar,
|
||||
|
|
|
@ -329,6 +329,8 @@ struct ath10k_ce_ops {
|
|||
void (*ce_set_dest_ring_base_addr_hi)(struct ath10k *ar,
|
||||
u32 ce_ctrl_addr,
|
||||
u64 addr);
|
||||
int (*ce_completed_send_next_nolock)(struct ath10k_ce_pipe *ce_state,
|
||||
void **per_transfer_contextp);
|
||||
};
|
||||
|
||||
static inline u32 ath10k_ce_base_address(struct ath10k *ar, unsigned int ce_id)
|
||||
|
|
|
@ -549,10 +549,10 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
|||
.sw_decrypt_mcast_mgmt = true,
|
||||
.hw_ops = &wcn3990_ops,
|
||||
.decap_align_bytes = 1,
|
||||
.num_peers = TARGET_HL_10_TLV_NUM_PEERS,
|
||||
.num_peers = TARGET_HL_TLV_NUM_PEERS,
|
||||
.n_cipher_suites = 11,
|
||||
.ast_skid_limit = TARGET_HL_10_TLV_AST_SKID_LIMIT,
|
||||
.num_wds_entries = TARGET_HL_10_TLV_NUM_WDS_ENTRIES,
|
||||
.ast_skid_limit = TARGET_HL_TLV_AST_SKID_LIMIT,
|
||||
.num_wds_entries = TARGET_HL_TLV_NUM_WDS_ENTRIES,
|
||||
.target_64bit = true,
|
||||
.rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL_DUAL_MAC,
|
||||
.per_ce_irq = true,
|
||||
|
@ -637,11 +637,24 @@ static void ath10k_init_sdio(struct ath10k *ar)
|
|||
ath10k_bmi_write32(ar, hi_mbox_isr_yield_limit, 99);
|
||||
ath10k_bmi_read32(ar, hi_acs_flags, ¶m);
|
||||
|
||||
param |= (HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_SET |
|
||||
HI_ACS_FLAGS_SDIO_REDUCE_TX_COMPL_SET |
|
||||
HI_ACS_FLAGS_ALT_DATA_CREDIT_SIZE);
|
||||
/* Data transfer is not initiated, when reduced Tx completion
|
||||
* is used for SDIO. disable it until fixed
|
||||
*/
|
||||
param &= ~HI_ACS_FLAGS_SDIO_REDUCE_TX_COMPL_SET;
|
||||
|
||||
/* Alternate credit size of 1544 as used by SDIO firmware is
|
||||
* not big enough for mac80211 / native wifi frames. disable it
|
||||
*/
|
||||
param &= ~HI_ACS_FLAGS_ALT_DATA_CREDIT_SIZE;
|
||||
param |= HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_SET;
|
||||
ath10k_bmi_write32(ar, hi_acs_flags, param);
|
||||
|
||||
/* Explicitly set fwlog prints to zero as target may turn it on
|
||||
* based on scratch registers.
|
||||
*/
|
||||
ath10k_bmi_read32(ar, hi_option_flag, ¶m);
|
||||
param |= HI_OPTION_DISABLE_DBGLOG;
|
||||
ath10k_bmi_write32(ar, hi_option_flag, param);
|
||||
}
|
||||
|
||||
static int ath10k_init_configure_target(struct ath10k *ar)
|
||||
|
@ -2304,8 +2317,8 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
|
|||
else
|
||||
ar->htt.max_num_pending_tx = TARGET_TLV_NUM_MSDU_DESC;
|
||||
ar->wow.max_num_patterns = TARGET_TLV_NUM_WOW_PATTERNS;
|
||||
ar->fw_stats_req_mask = WMI_STAT_PDEV | WMI_STAT_VDEV |
|
||||
WMI_STAT_PEER;
|
||||
ar->fw_stats_req_mask = WMI_TLV_STAT_PDEV | WMI_TLV_STAT_VDEV |
|
||||
WMI_TLV_STAT_PEER | WMI_TLV_STAT_PEER_EXTD;
|
||||
ar->max_spatial_stream = WMI_MAX_SPATIAL_STREAM;
|
||||
ar->wmi.mgmt_max_num_pending_tx = TARGET_TLV_MGMT_NUM_MSDU_DESC;
|
||||
break;
|
||||
|
|
|
@ -189,7 +189,7 @@ struct ath10k_fw_stats_peer {
|
|||
u32 peer_rssi;
|
||||
u32 peer_tx_rate;
|
||||
u32 peer_rx_rate; /* 10x only */
|
||||
u32 rx_duration;
|
||||
u64 rx_duration;
|
||||
};
|
||||
|
||||
struct ath10k_fw_extd_stats_peer {
|
||||
|
|
|
@ -1252,6 +1252,9 @@ static int ath10k_debug_cal_data_fetch(struct ath10k *ar)
|
|||
if (WARN_ON(ar->hw_params.cal_data_len > ATH10K_DEBUG_CAL_DATA_LEN))
|
||||
return -EINVAL;
|
||||
|
||||
if (ar->hw_params.cal_data_len == 0)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
hi_addr = host_interest_item_address(HI_ITEM(hi_board_data));
|
||||
|
||||
ret = ath10k_hif_diag_read(ar, hi_addr, &addr, sizeof(addr));
|
||||
|
|
|
@ -685,11 +685,12 @@ static ssize_t ath10k_dbg_sta_dump_tx_stats(struct file *file,
|
|||
" %llu ", stats->ht[j][i]);
|
||||
len += scnprintf(buf + len, size - len, "\n");
|
||||
len += scnprintf(buf + len, size - len,
|
||||
" BW %s (20,40,80,160 MHz)\n", str[j]);
|
||||
" BW %s (20,5,10,40,80,160 MHz)\n", str[j]);
|
||||
len += scnprintf(buf + len, size - len,
|
||||
" %llu %llu %llu %llu\n",
|
||||
" %llu %llu %llu %llu %llu %llu\n",
|
||||
stats->bw[j][0], stats->bw[j][1],
|
||||
stats->bw[j][2], stats->bw[j][3]);
|
||||
stats->bw[j][2], stats->bw[j][3],
|
||||
stats->bw[j][4], stats->bw[j][5]);
|
||||
len += scnprintf(buf + len, size - len,
|
||||
" NSS %s (1x1,2x2,3x3,4x4)\n", str[j]);
|
||||
len += scnprintf(buf + len, size - len,
|
||||
|
|
|
@ -578,6 +578,10 @@ struct htt_mgmt_tx_completion {
|
|||
#define HTT_TX_CMPL_FLAG_PA_PRESENT BIT(2)
|
||||
#define HTT_TX_CMPL_FLAG_PPDU_DURATION_PRESENT BIT(3)
|
||||
|
||||
#define HTT_TX_DATA_RSSI_ENABLE_WCN3990 BIT(3)
|
||||
#define HTT_TX_DATA_APPEND_RETRIES BIT(0)
|
||||
#define HTT_TX_DATA_APPEND_TIMESTAMP BIT(1)
|
||||
|
||||
struct htt_rx_indication_hdr {
|
||||
u8 info0; /* %HTT_RX_INDICATION_INFO0_ */
|
||||
__le16 peer_id;
|
||||
|
@ -852,6 +856,88 @@ enum htt_data_tx_flags {
|
|||
|
||||
#define HTT_TX_COMPL_INV_MSDU_ID 0xFFFF
|
||||
|
||||
struct htt_append_retries {
|
||||
__le16 msdu_id;
|
||||
u8 tx_retries;
|
||||
u8 flag;
|
||||
} __packed;
|
||||
|
||||
struct htt_data_tx_completion_ext {
|
||||
struct htt_append_retries a_retries;
|
||||
__le32 t_stamp;
|
||||
__le16 msdus_rssi[0];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* @brief target -> host TX completion indication message definition
|
||||
*
|
||||
* @details
|
||||
* The following diagram shows the format of the TX completion indication sent
|
||||
* from the target to the host
|
||||
*
|
||||
* |31 28|27|26|25|24|23 16| 15 |14 11|10 8|7 0|
|
||||
* |-------------------------------------------------------------|
|
||||
* header: |rsvd |A2|TP|A1|A0| num | t_i| tid |status| msg_type |
|
||||
* |-------------------------------------------------------------|
|
||||
* payload: | MSDU1 ID | MSDU0 ID |
|
||||
* |-------------------------------------------------------------|
|
||||
* : MSDU3 ID : MSDU2 ID :
|
||||
* |-------------------------------------------------------------|
|
||||
* | struct htt_tx_compl_ind_append_retries |
|
||||
* |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
|
||||
* | struct htt_tx_compl_ind_append_tx_tstamp |
|
||||
* |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
|
||||
* | MSDU1 ACK RSSI | MSDU0 ACK RSSI |
|
||||
* |-------------------------------------------------------------|
|
||||
* : MSDU3 ACK RSSI : MSDU2 ACK RSSI :
|
||||
* |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
|
||||
* -msg_type
|
||||
* Bits 7:0
|
||||
* Purpose: identifies this as HTT TX completion indication
|
||||
* -status
|
||||
* Bits 10:8
|
||||
* Purpose: the TX completion status of payload fragmentations descriptors
|
||||
* Value: could be HTT_TX_COMPL_IND_STAT_OK or HTT_TX_COMPL_IND_STAT_DISCARD
|
||||
* -tid
|
||||
* Bits 14:11
|
||||
* Purpose: the tid associated with those fragmentation descriptors. It is
|
||||
* valid or not, depending on the tid_invalid bit.
|
||||
* Value: 0 to 15
|
||||
* -tid_invalid
|
||||
* Bits 15:15
|
||||
* Purpose: this bit indicates whether the tid field is valid or not
|
||||
* Value: 0 indicates valid, 1 indicates invalid
|
||||
* -num
|
||||
* Bits 23:16
|
||||
* Purpose: the number of payload in this indication
|
||||
* Value: 1 to 255
|
||||
* -A0 = append
|
||||
* Bits 24:24
|
||||
* Purpose: append the struct htt_tx_compl_ind_append_retries which contains
|
||||
* the number of tx retries for one MSDU at the end of this message
|
||||
* Value: 0 indicates no appending, 1 indicates appending
|
||||
* -A1 = append1
|
||||
* Bits 25:25
|
||||
* Purpose: Append the struct htt_tx_compl_ind_append_tx_tstamp which
|
||||
* contains the timestamp info for each TX msdu id in payload.
|
||||
* Value: 0 indicates no appending, 1 indicates appending
|
||||
* -TP = MSDU tx power presence
|
||||
* Bits 26:26
|
||||
* Purpose: Indicate whether the TX_COMPL_IND includes a tx power report
|
||||
* for each MSDU referenced by the TX_COMPL_IND message.
|
||||
* The order of the per-MSDU tx power reports matches the order
|
||||
* of the MSDU IDs.
|
||||
* Value: 0 indicates not appending, 1 indicates appending
|
||||
* -A2 = append2
|
||||
* Bits 27:27
|
||||
* Purpose: Indicate whether data ACK RSSI is appended for each MSDU in
|
||||
* TX_COMP_IND message. The order of the per-MSDU ACK RSSI report
|
||||
* matches the order of the MSDU IDs.
|
||||
* The ACK RSSI values are valid when status is COMPLETE_OK (and
|
||||
* this append2 bit is set).
|
||||
* Value: 0 indicates not appending, 1 indicates appending
|
||||
*/
|
||||
|
||||
struct htt_data_tx_completion {
|
||||
union {
|
||||
u8 flags;
|
||||
|
|
|
@ -2119,9 +2119,15 @@ static bool ath10k_htt_rx_proc_rx_ind_hl(struct ath10k_htt *htt,
|
|||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
rx_status = IEEE80211_SKB_RXCB(skb);
|
||||
rx_status->chains |= BIT(0);
|
||||
rx_status->signal = ATH10K_DEFAULT_NOISE_FLOOR +
|
||||
rx->ppdu.combined_rssi;
|
||||
rx_status->flag &= ~RX_FLAG_NO_SIGNAL_VAL;
|
||||
if (rx->ppdu.combined_rssi == 0) {
|
||||
/* SDIO firmware does not provide signal */
|
||||
rx_status->signal = 0;
|
||||
rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
|
||||
} else {
|
||||
rx_status->signal = ATH10K_DEFAULT_NOISE_FLOOR +
|
||||
rx->ppdu.combined_rssi;
|
||||
rx_status->flag &= ~RX_FLAG_NO_SIGNAL_VAL;
|
||||
}
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
ch = ar->scan_channel;
|
||||
|
@ -2210,7 +2216,7 @@ static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar,
|
|||
__le16 msdu_id, *msdus;
|
||||
bool rssi_enabled = false;
|
||||
u8 msdu_count = 0, num_airtime_records, tid;
|
||||
int i;
|
||||
int i, htt_pad = 0;
|
||||
struct htt_data_tx_compl_ppdu_dur *ppdu_info;
|
||||
struct ath10k_peer *peer;
|
||||
u16 ppdu_info_offset = 0, peer_id;
|
||||
|
@ -2239,9 +2245,11 @@ static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar,
|
|||
|
||||
msdu_count = resp->data_tx_completion.num_msdus;
|
||||
msdus = resp->data_tx_completion.msdus;
|
||||
rssi_enabled = ath10k_is_rssi_enable(&ar->hw_params, resp);
|
||||
|
||||
if (resp->data_tx_completion.flags2 & HTT_TX_CMPL_FLAG_DATA_RSSI)
|
||||
rssi_enabled = true;
|
||||
if (rssi_enabled)
|
||||
htt_pad = ath10k_tx_data_rssi_get_pad_bytes(&ar->hw_params,
|
||||
resp);
|
||||
|
||||
for (i = 0; i < msdu_count; i++) {
|
||||
msdu_id = msdus[i];
|
||||
|
@ -2253,10 +2261,10 @@ static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar,
|
|||
* last msdu id with 0xffff
|
||||
*/
|
||||
if (msdu_count & 0x01) {
|
||||
msdu_id = msdus[msdu_count + i + 1];
|
||||
msdu_id = msdus[msdu_count + i + 1 + htt_pad];
|
||||
tx_done.ack_rssi = __le16_to_cpu(msdu_id);
|
||||
} else {
|
||||
msdu_id = msdus[msdu_count + i];
|
||||
msdu_id = msdus[msdu_count + i + htt_pad];
|
||||
tx_done.ack_rssi = __le16_to_cpu(msdu_id);
|
||||
}
|
||||
}
|
||||
|
@ -2913,17 +2921,19 @@ ath10k_accumulate_per_peer_tx_stats(struct ath10k *ar,
|
|||
struct rate_info *txrate = &arsta->txrate;
|
||||
struct ath10k_htt_tx_stats *tx_stats;
|
||||
int idx, ht_idx, gi, mcs, bw, nss;
|
||||
unsigned long flags;
|
||||
|
||||
if (!arsta->tx_stats)
|
||||
return;
|
||||
|
||||
tx_stats = arsta->tx_stats;
|
||||
gi = (arsta->txrate.flags & RATE_INFO_FLAGS_SHORT_GI);
|
||||
ht_idx = txrate->mcs + txrate->nss * 8;
|
||||
mcs = txrate->mcs;
|
||||
flags = txrate->flags;
|
||||
gi = test_bit(ATH10K_RATE_INFO_FLAGS_SGI_BIT, &flags);
|
||||
mcs = ATH10K_HW_MCS_RATE(pstats->ratecode);
|
||||
bw = txrate->bw;
|
||||
nss = txrate->nss;
|
||||
idx = mcs * 8 + 8 * 10 * nss;
|
||||
ht_idx = mcs + (nss - 1) * 8;
|
||||
idx = mcs * 8 + 8 * 10 * (nss - 1);
|
||||
idx += bw * 2 + gi;
|
||||
|
||||
#define STATS_OP_FMT(name) tx_stats->stats[ATH10K_STATS_TYPE_##name]
|
||||
|
@ -2969,7 +2979,7 @@ ath10k_accumulate_per_peer_tx_stats(struct ath10k *ar,
|
|||
}
|
||||
STATS_OP_FMT(AMPDU).bw[0][bw] +=
|
||||
pstats->succ_bytes + pstats->retry_bytes;
|
||||
STATS_OP_FMT(AMPDU).nss[0][nss] +=
|
||||
STATS_OP_FMT(AMPDU).nss[0][nss - 1] +=
|
||||
pstats->succ_bytes + pstats->retry_bytes;
|
||||
STATS_OP_FMT(AMPDU).gi[0][gi] +=
|
||||
pstats->succ_bytes + pstats->retry_bytes;
|
||||
|
@ -2977,7 +2987,7 @@ ath10k_accumulate_per_peer_tx_stats(struct ath10k *ar,
|
|||
pstats->succ_bytes + pstats->retry_bytes;
|
||||
STATS_OP_FMT(AMPDU).bw[1][bw] +=
|
||||
pstats->succ_pkts + pstats->retry_pkts;
|
||||
STATS_OP_FMT(AMPDU).nss[1][nss] +=
|
||||
STATS_OP_FMT(AMPDU).nss[1][nss - 1] +=
|
||||
pstats->succ_pkts + pstats->retry_pkts;
|
||||
STATS_OP_FMT(AMPDU).gi[1][gi] +=
|
||||
pstats->succ_pkts + pstats->retry_pkts;
|
||||
|
@ -2989,27 +2999,27 @@ ath10k_accumulate_per_peer_tx_stats(struct ath10k *ar,
|
|||
}
|
||||
|
||||
STATS_OP_FMT(SUCC).bw[0][bw] += pstats->succ_bytes;
|
||||
STATS_OP_FMT(SUCC).nss[0][nss] += pstats->succ_bytes;
|
||||
STATS_OP_FMT(SUCC).nss[0][nss - 1] += pstats->succ_bytes;
|
||||
STATS_OP_FMT(SUCC).gi[0][gi] += pstats->succ_bytes;
|
||||
|
||||
STATS_OP_FMT(SUCC).bw[1][bw] += pstats->succ_pkts;
|
||||
STATS_OP_FMT(SUCC).nss[1][nss] += pstats->succ_pkts;
|
||||
STATS_OP_FMT(SUCC).nss[1][nss - 1] += pstats->succ_pkts;
|
||||
STATS_OP_FMT(SUCC).gi[1][gi] += pstats->succ_pkts;
|
||||
|
||||
STATS_OP_FMT(FAIL).bw[0][bw] += pstats->failed_bytes;
|
||||
STATS_OP_FMT(FAIL).nss[0][nss] += pstats->failed_bytes;
|
||||
STATS_OP_FMT(FAIL).nss[0][nss - 1] += pstats->failed_bytes;
|
||||
STATS_OP_FMT(FAIL).gi[0][gi] += pstats->failed_bytes;
|
||||
|
||||
STATS_OP_FMT(FAIL).bw[1][bw] += pstats->failed_pkts;
|
||||
STATS_OP_FMT(FAIL).nss[1][nss] += pstats->failed_pkts;
|
||||
STATS_OP_FMT(FAIL).nss[1][nss - 1] += pstats->failed_pkts;
|
||||
STATS_OP_FMT(FAIL).gi[1][gi] += pstats->failed_pkts;
|
||||
|
||||
STATS_OP_FMT(RETRY).bw[0][bw] += pstats->retry_bytes;
|
||||
STATS_OP_FMT(RETRY).nss[0][nss] += pstats->retry_bytes;
|
||||
STATS_OP_FMT(RETRY).nss[0][nss - 1] += pstats->retry_bytes;
|
||||
STATS_OP_FMT(RETRY).gi[0][gi] += pstats->retry_bytes;
|
||||
|
||||
STATS_OP_FMT(RETRY).bw[1][bw] += pstats->retry_pkts;
|
||||
STATS_OP_FMT(RETRY).nss[1][nss] += pstats->retry_pkts;
|
||||
STATS_OP_FMT(RETRY).nss[1][nss - 1] += pstats->retry_pkts;
|
||||
STATS_OP_FMT(RETRY).gi[1][gi] += pstats->retry_pkts;
|
||||
|
||||
if (txrate->flags >= RATE_INFO_FLAGS_MCS) {
|
||||
|
|
|
@ -1100,6 +1100,32 @@ int ath10k_hw_diag_fast_download(struct ath10k *ar,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int ath10k_htt_tx_rssi_enable(struct htt_resp *resp)
|
||||
{
|
||||
return (resp->data_tx_completion.flags2 & HTT_TX_CMPL_FLAG_DATA_RSSI);
|
||||
}
|
||||
|
||||
static int ath10k_htt_tx_rssi_enable_wcn3990(struct htt_resp *resp)
|
||||
{
|
||||
return (resp->data_tx_completion.flags2 &
|
||||
HTT_TX_DATA_RSSI_ENABLE_WCN3990);
|
||||
}
|
||||
|
||||
static int ath10k_get_htt_tx_data_rssi_pad(struct htt_resp *resp)
|
||||
{
|
||||
struct htt_data_tx_completion_ext extd;
|
||||
int pad_bytes = 0;
|
||||
|
||||
if (resp->data_tx_completion.flags2 & HTT_TX_DATA_APPEND_RETRIES)
|
||||
pad_bytes += sizeof(extd.a_retries) /
|
||||
sizeof(extd.msdus_rssi[0]);
|
||||
|
||||
if (resp->data_tx_completion.flags2 & HTT_TX_DATA_APPEND_TIMESTAMP)
|
||||
pad_bytes += sizeof(extd.t_stamp) / sizeof(extd.msdus_rssi[0]);
|
||||
|
||||
return pad_bytes;
|
||||
}
|
||||
|
||||
const struct ath10k_hw_ops qca988x_ops = {
|
||||
.set_coverage_class = ath10k_hw_qca988x_set_coverage_class,
|
||||
};
|
||||
|
@ -1124,6 +1150,10 @@ const struct ath10k_hw_ops qca99x0_ops = {
|
|||
const struct ath10k_hw_ops qca6174_ops = {
|
||||
.set_coverage_class = ath10k_hw_qca988x_set_coverage_class,
|
||||
.enable_pll_clk = ath10k_hw_qca6174_enable_pll_clock,
|
||||
.is_rssi_enable = ath10k_htt_tx_rssi_enable,
|
||||
};
|
||||
|
||||
const struct ath10k_hw_ops wcn3990_ops = {};
|
||||
const struct ath10k_hw_ops wcn3990_ops = {
|
||||
.tx_data_rssi_pad_bytes = ath10k_get_htt_tx_data_rssi_pad,
|
||||
.is_rssi_enable = ath10k_htt_tx_rssi_enable_wcn3990,
|
||||
};
|
||||
|
|
|
@ -609,6 +609,8 @@ struct ath10k_hw_params {
|
|||
};
|
||||
|
||||
struct htt_rx_desc;
|
||||
struct htt_resp;
|
||||
struct htt_data_tx_completion_ext;
|
||||
|
||||
/* Defines needed for Rx descriptor abstraction */
|
||||
struct ath10k_hw_ops {
|
||||
|
@ -616,6 +618,8 @@ struct ath10k_hw_ops {
|
|||
void (*set_coverage_class)(struct ath10k *ar, s16 value);
|
||||
int (*enable_pll_clk)(struct ath10k *ar);
|
||||
bool (*rx_desc_get_msdu_limit_error)(struct htt_rx_desc *rxd);
|
||||
int (*tx_data_rssi_pad_bytes)(struct htt_resp *htt);
|
||||
int (*is_rssi_enable)(struct htt_resp *resp);
|
||||
};
|
||||
|
||||
extern const struct ath10k_hw_ops qca988x_ops;
|
||||
|
@ -643,6 +647,24 @@ ath10k_rx_desc_msdu_limit_error(struct ath10k_hw_params *hw,
|
|||
return false;
|
||||
}
|
||||
|
||||
static inline int
|
||||
ath10k_tx_data_rssi_get_pad_bytes(struct ath10k_hw_params *hw,
|
||||
struct htt_resp *htt)
|
||||
{
|
||||
if (hw->hw_ops->tx_data_rssi_pad_bytes)
|
||||
return hw->hw_ops->tx_data_rssi_pad_bytes(htt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
ath10k_is_rssi_enable(struct ath10k_hw_params *hw,
|
||||
struct htt_resp *resp)
|
||||
{
|
||||
if (hw->hw_ops->is_rssi_enable)
|
||||
return hw->hw_ops->is_rssi_enable(resp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Target specific defines for MAIN firmware */
|
||||
#define TARGET_NUM_VDEVS 8
|
||||
#define TARGET_NUM_PEER_AST 2
|
||||
|
@ -730,9 +752,9 @@ ath10k_rx_desc_msdu_limit_error(struct ath10k_hw_params *hw,
|
|||
#define TARGET_TLV_MGMT_NUM_MSDU_DESC (50)
|
||||
|
||||
/* Target specific defines for WMI-HL-1.0 firmware */
|
||||
#define TARGET_HL_10_TLV_NUM_PEERS 14
|
||||
#define TARGET_HL_10_TLV_AST_SKID_LIMIT 6
|
||||
#define TARGET_HL_10_TLV_NUM_WDS_ENTRIES 2
|
||||
#define TARGET_HL_TLV_NUM_PEERS 33
|
||||
#define TARGET_HL_TLV_AST_SKID_LIMIT 16
|
||||
#define TARGET_HL_TLV_NUM_WDS_ENTRIES 2
|
||||
|
||||
/* Diagnostic Window */
|
||||
#define CE_DIAG_PIPE 7
|
||||
|
|
|
@ -1382,6 +1382,12 @@ static int ath10k_sdio_hif_power_up(struct ath10k *ar,
|
|||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "sdio power on\n");
|
||||
|
||||
ret = ath10k_sdio_config(ar);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to config sdio: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
sdio_claim_host(func);
|
||||
|
||||
ret = sdio_enable_func(func);
|
||||
|
@ -1419,11 +1425,19 @@ static void ath10k_sdio_hif_power_down(struct ath10k *ar)
|
|||
|
||||
/* Disable the card */
|
||||
sdio_claim_host(ar_sdio->func);
|
||||
ret = sdio_disable_func(ar_sdio->func);
|
||||
sdio_release_host(ar_sdio->func);
|
||||
|
||||
if (ret)
|
||||
ret = sdio_disable_func(ar_sdio->func);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "unable to disable sdio function: %d\n", ret);
|
||||
sdio_release_host(ar_sdio->func);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = mmc_hw_reset(ar_sdio->func->card->host);
|
||||
if (ret)
|
||||
ath10k_warn(ar, "unable to reset sdio: %d\n", ret);
|
||||
|
||||
sdio_release_host(ar_sdio->func);
|
||||
|
||||
ar_sdio->is_disabled = true;
|
||||
}
|
||||
|
@ -2028,12 +2042,6 @@ static int ath10k_sdio_probe(struct sdio_func *func,
|
|||
|
||||
ath10k_sdio_set_mbox_info(ar);
|
||||
|
||||
ret = ath10k_sdio_config(ar);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to config sdio: %d\n", ret);
|
||||
goto err_free_wq;
|
||||
}
|
||||
|
||||
bus_params.dev_type = ATH10K_DEV_TYPE_HL;
|
||||
/* TODO: don't know yet how to get chip_id with SDIO */
|
||||
bus_params.chip_id = 0;
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "wmi-tlv.h"
|
||||
#include "p2p.h"
|
||||
#include "testmode.h"
|
||||
#include <linux/bitfield.h>
|
||||
|
||||
/***************/
|
||||
/* TLV helpers */
|
||||
|
@ -673,6 +674,10 @@ ath10k_wmi_tlv_op_pull_mgmt_tx_compl_ev(struct ath10k *ar, struct sk_buff *skb,
|
|||
arg->desc_id = ev->desc_id;
|
||||
arg->status = ev->status;
|
||||
arg->pdev_id = ev->pdev_id;
|
||||
arg->ppdu_id = ev->ppdu_id;
|
||||
|
||||
if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map))
|
||||
arg->ack_rssi = ev->ack_rssi;
|
||||
|
||||
kfree(tb);
|
||||
return 0;
|
||||
|
@ -682,8 +687,12 @@ struct wmi_tlv_tx_bundle_compl_parse {
|
|||
const __le32 *num_reports;
|
||||
const __le32 *desc_ids;
|
||||
const __le32 *status;
|
||||
const __le32 *ppdu_ids;
|
||||
const __le32 *ack_rssi;
|
||||
bool desc_ids_done;
|
||||
bool status_done;
|
||||
bool ppdu_ids_done;
|
||||
bool ack_rssi_done;
|
||||
};
|
||||
|
||||
static int
|
||||
|
@ -703,6 +712,12 @@ ath10k_wmi_tlv_mgmt_tx_bundle_compl_parse(struct ath10k *ar, u16 tag, u16 len,
|
|||
} else if (!bundle_tx_compl->status_done) {
|
||||
bundle_tx_compl->status_done = true;
|
||||
bundle_tx_compl->status = ptr;
|
||||
} else if (!bundle_tx_compl->ppdu_ids_done) {
|
||||
bundle_tx_compl->ppdu_ids_done = true;
|
||||
bundle_tx_compl->ppdu_ids = ptr;
|
||||
} else if (!bundle_tx_compl->ack_rssi_done) {
|
||||
bundle_tx_compl->ack_rssi_done = true;
|
||||
bundle_tx_compl->ack_rssi = ptr;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -733,6 +748,10 @@ static int ath10k_wmi_tlv_op_pull_mgmt_tx_bundle_compl_ev(
|
|||
arg->num_reports = *bundle_tx_compl.num_reports;
|
||||
arg->desc_ids = bundle_tx_compl.desc_ids;
|
||||
arg->status = bundle_tx_compl.status;
|
||||
arg->ppdu_ids = bundle_tx_compl.ppdu_ids;
|
||||
|
||||
if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map))
|
||||
arg->ack_rssi = bundle_tx_compl.ack_rssi;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1278,6 +1297,7 @@ static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar,
|
|||
{
|
||||
const void **tb;
|
||||
const struct wmi_tlv_stats_ev *ev;
|
||||
u32 num_peer_stats_extd;
|
||||
const void *data;
|
||||
u32 num_pdev_stats;
|
||||
u32 num_vdev_stats;
|
||||
|
@ -1285,6 +1305,7 @@ static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar,
|
|||
u32 num_bcnflt_stats;
|
||||
u32 num_chan_stats;
|
||||
size_t data_len;
|
||||
u32 stats_id;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
|
@ -1309,11 +1330,13 @@ static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar,
|
|||
num_peer_stats = __le32_to_cpu(ev->num_peer_stats);
|
||||
num_bcnflt_stats = __le32_to_cpu(ev->num_bcnflt_stats);
|
||||
num_chan_stats = __le32_to_cpu(ev->num_chan_stats);
|
||||
stats_id = __le32_to_cpu(ev->stats_id);
|
||||
num_peer_stats_extd = __le32_to_cpu(ev->num_peer_stats_extd);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI,
|
||||
"wmi tlv stats update pdev %i vdev %i peer %i bcnflt %i chan %i\n",
|
||||
"wmi tlv stats update pdev %i vdev %i peer %i bcnflt %i chan %i peer_extd %i\n",
|
||||
num_pdev_stats, num_vdev_stats, num_peer_stats,
|
||||
num_bcnflt_stats, num_chan_stats);
|
||||
num_bcnflt_stats, num_chan_stats, num_peer_stats_extd);
|
||||
|
||||
for (i = 0; i < num_pdev_stats; i++) {
|
||||
const struct wmi_pdev_stats *src;
|
||||
|
@ -1378,6 +1401,28 @@ static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar,
|
|||
|
||||
ath10k_wmi_pull_peer_stats(&src->old, dst);
|
||||
dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate);
|
||||
|
||||
if (stats_id & WMI_TLV_STAT_PEER_EXTD) {
|
||||
const struct wmi_tlv_peer_stats_extd *extd;
|
||||
unsigned long rx_duration_high;
|
||||
|
||||
extd = data + sizeof(*src) * (num_peer_stats - i - 1)
|
||||
+ sizeof(*extd) * i;
|
||||
|
||||
dst->rx_duration = __le32_to_cpu(extd->rx_duration);
|
||||
rx_duration_high = __le32_to_cpu
|
||||
(extd->rx_duration_high);
|
||||
|
||||
if (test_bit(WMI_TLV_PEER_RX_DURATION_HIGH_VALID_BIT,
|
||||
&rx_duration_high)) {
|
||||
rx_duration_high =
|
||||
FIELD_GET(WMI_TLV_PEER_RX_DURATION_HIGH_MASK,
|
||||
rx_duration_high);
|
||||
dst->rx_duration |= (u64)rx_duration_high <<
|
||||
WMI_TLV_PEER_RX_DURATION_SHIFT;
|
||||
}
|
||||
}
|
||||
|
||||
list_add_tail(&dst->list, &stats->peers);
|
||||
}
|
||||
|
||||
|
@ -1565,21 +1610,55 @@ ath10k_wmi_tlv_op_gen_pdev_set_param(struct ath10k *ar, u32 param_id,
|
|||
cmd->param_id = __cpu_to_le32(param_id);
|
||||
cmd->param_value = __cpu_to_le32(param_value);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev set param\n");
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev set param %d value 0x%x\n",
|
||||
param_id, param_value);
|
||||
return skb;
|
||||
}
|
||||
|
||||
static void
|
||||
ath10k_wmi_tlv_put_host_mem_chunks(struct ath10k *ar, void *host_mem_chunks)
|
||||
{
|
||||
struct host_memory_chunk *chunk;
|
||||
struct wmi_tlv *tlv;
|
||||
int i;
|
||||
__le16 tlv_len, tlv_tag;
|
||||
|
||||
tlv_tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_WLAN_HOST_MEMORY_CHUNK);
|
||||
tlv_len = __cpu_to_le16(sizeof(*chunk));
|
||||
for (i = 0; i < ar->wmi.num_mem_chunks; i++) {
|
||||
tlv = host_mem_chunks;
|
||||
tlv->tag = tlv_tag;
|
||||
tlv->len = tlv_len;
|
||||
chunk = (void *)tlv->value;
|
||||
|
||||
chunk->ptr = __cpu_to_le32(ar->wmi.mem_chunks[i].paddr);
|
||||
chunk->size = __cpu_to_le32(ar->wmi.mem_chunks[i].len);
|
||||
chunk->req_id = __cpu_to_le32(ar->wmi.mem_chunks[i].req_id);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI,
|
||||
"wmi-tlv chunk %d len %d, addr 0x%llx, id 0x%x\n",
|
||||
i,
|
||||
ar->wmi.mem_chunks[i].len,
|
||||
(unsigned long long)ar->wmi.mem_chunks[i].paddr,
|
||||
ar->wmi.mem_chunks[i].req_id);
|
||||
|
||||
host_mem_chunks += sizeof(*tlv);
|
||||
host_mem_chunks += sizeof(*chunk);
|
||||
}
|
||||
}
|
||||
|
||||
static struct sk_buff *ath10k_wmi_tlv_op_gen_init(struct ath10k *ar)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct wmi_tlv *tlv;
|
||||
struct wmi_tlv_init_cmd *cmd;
|
||||
struct wmi_tlv_resource_config *cfg;
|
||||
struct wmi_host_mem_chunks *chunks;
|
||||
void *chunks;
|
||||
size_t len, chunks_len;
|
||||
void *ptr;
|
||||
|
||||
chunks_len = ar->wmi.num_mem_chunks * sizeof(struct host_memory_chunk);
|
||||
chunks_len = ar->wmi.num_mem_chunks *
|
||||
(sizeof(struct host_memory_chunk) + sizeof(*tlv));
|
||||
len = (sizeof(*tlv) + sizeof(*cmd)) +
|
||||
(sizeof(*tlv) + sizeof(*cfg)) +
|
||||
(sizeof(*tlv) + chunks_len);
|
||||
|
@ -1679,7 +1758,10 @@ static struct sk_buff *ath10k_wmi_tlv_op_gen_init(struct ath10k *ar)
|
|||
cfg->num_ocb_schedules = __cpu_to_le32(0);
|
||||
cfg->host_capab = __cpu_to_le32(WMI_TLV_FLAG_MGMT_BUNDLE_TX_COMPL);
|
||||
|
||||
ath10k_wmi_put_host_mem_chunks(ar, chunks);
|
||||
if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map))
|
||||
cfg->host_capab |= __cpu_to_le32(WMI_RSRC_CFG_FLAG_TX_ACK_RSSI);
|
||||
|
||||
ath10k_wmi_tlv_put_host_mem_chunks(ar, chunks);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv init\n");
|
||||
return skb;
|
||||
|
@ -2035,7 +2117,8 @@ ath10k_wmi_tlv_op_gen_vdev_set_param(struct ath10k *ar, u32 vdev_id,
|
|||
cmd->param_id = __cpu_to_le32(param_id);
|
||||
cmd->param_value = __cpu_to_le32(param_value);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev set param\n");
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev %d set param %d value 0x%x\n",
|
||||
vdev_id, param_id, param_value);
|
||||
return skb;
|
||||
}
|
||||
|
||||
|
@ -2351,7 +2434,9 @@ ath10k_wmi_tlv_op_gen_peer_set_param(struct ath10k *ar, u32 vdev_id,
|
|||
cmd->param_value = __cpu_to_le32(param_value);
|
||||
ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer set param\n");
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI,
|
||||
"wmi tlv vdev %d peer %pM set param %d value 0x%x\n",
|
||||
vdev_id, peer_addr, param_id, param_value);
|
||||
return skb;
|
||||
}
|
||||
|
||||
|
@ -2745,7 +2830,9 @@ ath10k_wmi_tlv_op_gen_mgmt_tx_send(struct ath10k *ar, struct sk_buff *msdu,
|
|||
arvif = (void *)cb->vif->drv_priv;
|
||||
vdev_id = arvif->vdev_id;
|
||||
|
||||
if (WARN_ON_ONCE(!ieee80211_is_mgmt(hdr->frame_control)))
|
||||
if (WARN_ON_ONCE(!ieee80211_is_mgmt(hdr->frame_control) &&
|
||||
(!(ieee80211_is_nullfunc(hdr->frame_control) ||
|
||||
ieee80211_is_qos_nullfunc(hdr->frame_control)))))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
len = sizeof(*cmd) + 2 * sizeof(*tlv);
|
||||
|
@ -2753,10 +2840,8 @@ ath10k_wmi_tlv_op_gen_mgmt_tx_send(struct ath10k *ar, struct sk_buff *msdu,
|
|||
if ((ieee80211_is_action(hdr->frame_control) ||
|
||||
ieee80211_is_deauth(hdr->frame_control) ||
|
||||
ieee80211_is_disassoc(hdr->frame_control)) &&
|
||||
ieee80211_has_protected(hdr->frame_control)) {
|
||||
len += IEEE80211_CCMP_MIC_LEN;
|
||||
ieee80211_has_protected(hdr->frame_control))
|
||||
buf_len += IEEE80211_CCMP_MIC_LEN;
|
||||
}
|
||||
|
||||
buf_len = min_t(u32, buf_len, WMI_TLV_MGMT_TX_FRAME_MAX_LEN);
|
||||
buf_len = round_up(buf_len, 4);
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
#define WMI_TLV_VDEV_PARAM_UNSUPPORTED 0
|
||||
#define WMI_TLV_MGMT_TX_FRAME_MAX_LEN 64
|
||||
|
||||
#define WMI_RSRC_CFG_FLAG_TX_ACK_RSSI BIT(18)
|
||||
|
||||
enum wmi_tlv_grp_id {
|
||||
WMI_TLV_GRP_START = 0x3,
|
||||
WMI_TLV_GRP_SCAN = WMI_TLV_GRP_START,
|
||||
|
@ -1384,6 +1386,25 @@ enum wmi_tlv_service {
|
|||
WMI_TLV_SERVICE_AP_TWT = 153,
|
||||
WMI_TLV_SERVICE_GMAC_OFFLOAD_SUPPORT = 154,
|
||||
WMI_TLV_SERVICE_SPOOF_MAC_SUPPORT = 155,
|
||||
WMI_TLV_SERVICE_PEER_TID_CONFIGS_SUPPORT = 156,
|
||||
WMI_TLV_SERVICE_VDEV_SWRETRY_PER_AC_CONFIG_SUPPORT = 157,
|
||||
WMI_TLV_SERVICE_DUAL_BEACON_ON_SINGLE_MAC_SCC_SUPPORT = 158,
|
||||
WMI_TLV_SERVICE_DUAL_BEACON_ON_SINGLE_MAC_MCC_SUPPORT = 159,
|
||||
WMI_TLV_SERVICE_MOTION_DET = 160,
|
||||
WMI_TLV_SERVICE_INFRA_MBSSID = 161,
|
||||
WMI_TLV_SERVICE_OBSS_SPATIAL_REUSE = 162,
|
||||
WMI_TLV_SERVICE_VDEV_DIFFERENT_BEACON_INTERVAL_SUPPORT = 163,
|
||||
WMI_TLV_SERVICE_NAN_DBS_SUPPORT = 164,
|
||||
WMI_TLV_SERVICE_NDI_DBS_SUPPORT = 165,
|
||||
WMI_TLV_SERVICE_NAN_SAP_SUPPORT = 166,
|
||||
WMI_TLV_SERVICE_NDI_SAP_SUPPORT = 167,
|
||||
WMI_TLV_SERVICE_CFR_CAPTURE_SUPPORT = 168,
|
||||
WMI_TLV_SERVICE_CFR_CAPTURE_IND_MSG_TYPE_1 = 169,
|
||||
WMI_TLV_SERVICE_ESP_SUPPORT = 170,
|
||||
WMI_TLV_SERVICE_PEER_CHWIDTH_CHANGE = 171,
|
||||
WMI_TLV_SERVICE_WLAN_HPCS_PULSE = 172,
|
||||
WMI_TLV_SERVICE_PER_VDEV_CHAINMASK_CONFIG_SUPPORT = 173,
|
||||
WMI_TLV_SERVICE_TX_DATA_MGMT_ACK_RSSI = 174,
|
||||
|
||||
WMI_TLV_MAX_EXT_SERVICE = 256,
|
||||
};
|
||||
|
@ -1557,6 +1578,8 @@ wmi_tlv_svc_map_ext(const __le32 *in, unsigned long *out, size_t len)
|
|||
SVCMAP(WMI_TLV_SERVICE_THERM_THROT,
|
||||
WMI_SERVICE_THERM_THROT,
|
||||
WMI_TLV_MAX_SERVICE);
|
||||
SVCMAP(WMI_TLV_SERVICE_TX_DATA_MGMT_ACK_RSSI,
|
||||
WMI_SERVICE_TX_DATA_ACK_RSSI, WMI_TLV_MAX_SERVICE);
|
||||
}
|
||||
|
||||
#undef SVCMAP
|
||||
|
@ -1588,6 +1611,8 @@ struct wmi_tlv_mgmt_tx_compl_ev {
|
|||
__le32 desc_id;
|
||||
__le32 status;
|
||||
__le32 pdev_id;
|
||||
__le32 ppdu_id;
|
||||
__le32 ack_rssi;
|
||||
};
|
||||
|
||||
#define WMI_TLV_MGMT_RX_NUM_RSSI 4
|
||||
|
@ -1864,6 +1889,22 @@ struct wmi_tlv_req_stats_cmd {
|
|||
struct wmi_mac_addr peer_macaddr;
|
||||
} __packed;
|
||||
|
||||
#define WMI_TLV_PEER_RX_DURATION_HIGH_VALID_BIT 31
|
||||
#define WMI_TLV_PEER_RX_DURATION_HIGH_MASK GENMASK(30, 0)
|
||||
#define WMI_TLV_PEER_RX_DURATION_SHIFT 32
|
||||
|
||||
struct wmi_tlv_peer_stats_extd {
|
||||
struct wmi_mac_addr peer_macaddr;
|
||||
__le32 rx_duration;
|
||||
__le32 peer_tx_bytes;
|
||||
__le32 peer_rx_bytes;
|
||||
__le32 last_tx_rate_code;
|
||||
__le32 last_tx_power;
|
||||
__le32 rx_mc_bc_cnt;
|
||||
__le32 rx_duration_high;
|
||||
__le32 reserved[2];
|
||||
} __packed;
|
||||
|
||||
struct wmi_tlv_vdev_stats {
|
||||
__le32 vdev_id;
|
||||
__le32 beacon_snr;
|
||||
|
@ -1957,6 +1998,10 @@ struct wmi_tlv_stats_ev {
|
|||
__le32 num_peer_stats;
|
||||
__le32 num_bcnflt_stats;
|
||||
__le32 num_chan_stats;
|
||||
__le32 num_mib_stats;
|
||||
__le32 pdev_id;
|
||||
__le32 num_bcn_stats;
|
||||
__le32 num_peer_stats_extd;
|
||||
} __packed;
|
||||
|
||||
struct wmi_tlv_p2p_noa_ev {
|
||||
|
|
|
@ -2342,8 +2342,8 @@ static bool ath10k_wmi_rx_is_decrypted(struct ath10k *ar,
|
|||
return true;
|
||||
}
|
||||
|
||||
static int wmi_process_mgmt_tx_comp(struct ath10k *ar, u32 desc_id,
|
||||
u32 status)
|
||||
static int
|
||||
wmi_process_mgmt_tx_comp(struct ath10k *ar, struct mgmt_tx_compl_params *param)
|
||||
{
|
||||
struct ath10k_mgmt_tx_pkt_addr *pkt_addr;
|
||||
struct ath10k_wmi *wmi = &ar->wmi;
|
||||
|
@ -2353,10 +2353,10 @@ static int wmi_process_mgmt_tx_comp(struct ath10k *ar, u32 desc_id,
|
|||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
|
||||
pkt_addr = idr_find(&wmi->mgmt_pending_tx, desc_id);
|
||||
pkt_addr = idr_find(&wmi->mgmt_pending_tx, param->desc_id);
|
||||
if (!pkt_addr) {
|
||||
ath10k_warn(ar, "received mgmt tx completion for invalid msdu_id: %d\n",
|
||||
desc_id);
|
||||
param->desc_id);
|
||||
ret = -ENOENT;
|
||||
goto out;
|
||||
}
|
||||
|
@ -2366,17 +2366,21 @@ static int wmi_process_mgmt_tx_comp(struct ath10k *ar, u32 desc_id,
|
|||
msdu->len, DMA_TO_DEVICE);
|
||||
info = IEEE80211_SKB_CB(msdu);
|
||||
|
||||
if (status)
|
||||
if (param->status) {
|
||||
info->flags &= ~IEEE80211_TX_STAT_ACK;
|
||||
else
|
||||
} else {
|
||||
info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
info->status.ack_signal = ATH10K_DEFAULT_NOISE_FLOOR +
|
||||
param->ack_rssi;
|
||||
info->status.is_valid_ack_signal = true;
|
||||
}
|
||||
|
||||
ieee80211_tx_status_irqsafe(ar->hw, msdu);
|
||||
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
idr_remove(&wmi->mgmt_pending_tx, desc_id);
|
||||
idr_remove(&wmi->mgmt_pending_tx, param->desc_id);
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
return ret;
|
||||
}
|
||||
|
@ -2384,6 +2388,7 @@ out:
|
|||
int ath10k_wmi_event_mgmt_tx_compl(struct ath10k *ar, struct sk_buff *skb)
|
||||
{
|
||||
struct wmi_tlv_mgmt_tx_compl_ev_arg arg;
|
||||
struct mgmt_tx_compl_params param;
|
||||
int ret;
|
||||
|
||||
ret = ath10k_wmi_pull_mgmt_tx_compl(ar, skb, &arg);
|
||||
|
@ -2392,8 +2397,14 @@ int ath10k_wmi_event_mgmt_tx_compl(struct ath10k *ar, struct sk_buff *skb)
|
|||
return ret;
|
||||
}
|
||||
|
||||
wmi_process_mgmt_tx_comp(ar, __le32_to_cpu(arg.desc_id),
|
||||
__le32_to_cpu(arg.status));
|
||||
memset(¶m, 0, sizeof(struct mgmt_tx_compl_params));
|
||||
param.desc_id = __le32_to_cpu(arg.desc_id);
|
||||
param.status = __le32_to_cpu(arg.status);
|
||||
|
||||
if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map))
|
||||
param.ack_rssi = __le32_to_cpu(arg.ack_rssi);
|
||||
|
||||
wmi_process_mgmt_tx_comp(ar, ¶m);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv evnt mgmt tx completion\n");
|
||||
|
||||
|
@ -2403,6 +2414,7 @@ int ath10k_wmi_event_mgmt_tx_compl(struct ath10k *ar, struct sk_buff *skb)
|
|||
int ath10k_wmi_event_mgmt_tx_bundle_compl(struct ath10k *ar, struct sk_buff *skb)
|
||||
{
|
||||
struct wmi_tlv_mgmt_tx_bundle_compl_ev_arg arg;
|
||||
struct mgmt_tx_compl_params param;
|
||||
u32 num_reports;
|
||||
int i, ret;
|
||||
|
||||
|
@ -2414,9 +2426,15 @@ int ath10k_wmi_event_mgmt_tx_bundle_compl(struct ath10k *ar, struct sk_buff *skb
|
|||
|
||||
num_reports = __le32_to_cpu(arg.num_reports);
|
||||
|
||||
for (i = 0; i < num_reports; i++)
|
||||
wmi_process_mgmt_tx_comp(ar, __le32_to_cpu(arg.desc_ids[i]),
|
||||
__le32_to_cpu(arg.status[i]));
|
||||
for (i = 0; i < num_reports; i++) {
|
||||
memset(¶m, 0, sizeof(struct mgmt_tx_compl_params));
|
||||
param.desc_id = __le32_to_cpu(arg.desc_ids[i]);
|
||||
param.status = __le32_to_cpu(arg.desc_ids[i]);
|
||||
|
||||
if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map))
|
||||
param.ack_rssi = __le32_to_cpu(arg.ack_rssi[i]);
|
||||
wmi_process_mgmt_tx_comp(ar, ¶m);
|
||||
}
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv event bundle mgmt tx completion\n");
|
||||
|
||||
|
@ -8304,7 +8322,7 @@ ath10k_wmi_fw_peer_stats_fill(const struct ath10k_fw_stats_peer *peer,
|
|||
"Peer TX rate", peer->peer_tx_rate);
|
||||
len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
|
||||
"Peer RX rate", peer->peer_rx_rate);
|
||||
len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
|
||||
len += scnprintf(buf + len, buf_len - len, "%30s %llu\n",
|
||||
"Peer RX duration", peer->rx_duration);
|
||||
|
||||
len += scnprintf(buf + len, buf_len - len, "\n");
|
||||
|
|
|
@ -4534,6 +4534,13 @@ enum wmi_10_4_stats_id {
|
|||
WMI_10_4_STAT_VDEV_EXTD = BIT(4),
|
||||
};
|
||||
|
||||
enum wmi_tlv_stats_id {
|
||||
WMI_TLV_STAT_PDEV = BIT(0),
|
||||
WMI_TLV_STAT_VDEV = BIT(1),
|
||||
WMI_TLV_STAT_PEER = BIT(2),
|
||||
WMI_TLV_STAT_PEER_EXTD = BIT(10),
|
||||
};
|
||||
|
||||
struct wlan_inst_rssi_args {
|
||||
__le16 cfg_retry_count;
|
||||
__le16 retry_count;
|
||||
|
@ -5045,12 +5052,13 @@ enum wmi_rate_preamble {
|
|||
#define ATH10K_FW_SKIPPED_RATE_CTRL(flags) (((flags) >> 6) & 0x1)
|
||||
|
||||
#define ATH10K_VHT_MCS_NUM 10
|
||||
#define ATH10K_BW_NUM 4
|
||||
#define ATH10K_BW_NUM 6
|
||||
#define ATH10K_NSS_NUM 4
|
||||
#define ATH10K_LEGACY_NUM 12
|
||||
#define ATH10K_GI_NUM 2
|
||||
#define ATH10K_HT_MCS_NUM 32
|
||||
#define ATH10K_RATE_TABLE_NUM 320
|
||||
#define ATH10K_RATE_INFO_FLAGS_SGI_BIT 2
|
||||
|
||||
/* Value to disable fixed rate setting */
|
||||
#define WMI_FIXED_RATE_NONE (0xff)
|
||||
|
@ -6725,16 +6733,27 @@ struct wmi_scan_ev_arg {
|
|||
__le32 vdev_id;
|
||||
};
|
||||
|
||||
struct mgmt_tx_compl_params {
|
||||
u32 desc_id;
|
||||
u32 status;
|
||||
u32 ppdu_id;
|
||||
int ack_rssi;
|
||||
};
|
||||
|
||||
struct wmi_tlv_mgmt_tx_compl_ev_arg {
|
||||
__le32 desc_id;
|
||||
__le32 status;
|
||||
__le32 pdev_id;
|
||||
__le32 ppdu_id;
|
||||
__le32 ack_rssi;
|
||||
};
|
||||
|
||||
struct wmi_tlv_mgmt_tx_bundle_compl_ev_arg {
|
||||
__le32 num_reports;
|
||||
const __le32 *desc_ids;
|
||||
const __le32 *status;
|
||||
const __le32 *ppdu_ids;
|
||||
const __le32 *ack_rssi;
|
||||
};
|
||||
|
||||
struct wmi_mgmt_rx_ev_arg {
|
||||
|
|
|
@ -148,7 +148,7 @@ static ssize_t read_file_ani(struct file *file, char __user *user_buf,
|
|||
{ "OFDM LEVEL", ah->ani.ofdmNoiseImmunityLevel },
|
||||
{ "CCK LEVEL", ah->ani.cckNoiseImmunityLevel },
|
||||
{ "SPUR UP", ah->stats.ast_ani_spurup },
|
||||
{ "SPUR DOWN", ah->stats.ast_ani_spurup },
|
||||
{ "SPUR DOWN", ah->stats.ast_ani_spurdown },
|
||||
{ "OFDM WS-DET ON", ah->stats.ast_ani_ofdmon },
|
||||
{ "OFDM WS-DET OFF", ah->stats.ast_ani_ofdmoff },
|
||||
{ "MRC-CCK ON", ah->stats.ast_ani_ccklow },
|
||||
|
|
|
@ -1006,9 +1006,6 @@ static void ath_rx_count_airtime(struct ath_softc *sc,
|
|||
struct ath_rx_status *rs,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct ath_node *an;
|
||||
struct ath_acq *acq;
|
||||
struct ath_vif *avp;
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
|
@ -1019,7 +1016,7 @@ static void ath_rx_count_airtime(struct ath_softc *sc,
|
|||
int phy;
|
||||
u16 len = rs->rs_datalen;
|
||||
u32 airtime = 0;
|
||||
u8 tidno, acno;
|
||||
u8 tidno;
|
||||
|
||||
if (!ieee80211_is_data(hdr->frame_control))
|
||||
return;
|
||||
|
@ -1029,11 +1026,7 @@ static void ath_rx_count_airtime(struct ath_softc *sc,
|
|||
sta = ieee80211_find_sta_by_ifaddr(sc->hw, hdr->addr2, NULL);
|
||||
if (!sta)
|
||||
goto exit;
|
||||
an = (struct ath_node *) sta->drv_priv;
|
||||
avp = (struct ath_vif *) an->vif->drv_priv;
|
||||
tidno = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
|
||||
acno = TID_TO_WME_AC(tidno);
|
||||
acq = &avp->chanctx->acq[acno];
|
||||
|
||||
rxs = IEEE80211_SKB_RXCB(skb);
|
||||
|
||||
|
|
|
@ -2552,6 +2552,9 @@ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
|
|||
}
|
||||
|
||||
tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1;
|
||||
|
||||
/* we report airtime in ath_tx_count_airtime(), don't report twice */
|
||||
tx_info->status.tx_time = 0;
|
||||
}
|
||||
|
||||
static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -395,7 +395,7 @@ static int wil_find_cid_by_idx(struct wil6210_priv *wil, u8 mid, int idx)
|
|||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
|
||||
for (i = 0; i < max_assoc_sta; i++) {
|
||||
if (wil->sta[i].status == wil_sta_unused)
|
||||
continue;
|
||||
if (wil->sta[i].mid != mid)
|
||||
|
@ -1580,6 +1580,12 @@ static int _wil_cfg80211_merge_extra_ies(const u8 *ies1, u16 ies1_len,
|
|||
u8 *buf, *dpos;
|
||||
const u8 *spos;
|
||||
|
||||
if (!ies1)
|
||||
ies1_len = 0;
|
||||
|
||||
if (!ies2)
|
||||
ies2_len = 0;
|
||||
|
||||
if (ies1_len == 0 && ies2_len == 0) {
|
||||
*merged_ies = NULL;
|
||||
*merged_len = 0;
|
||||
|
@ -1589,17 +1595,19 @@ static int _wil_cfg80211_merge_extra_ies(const u8 *ies1, u16 ies1_len,
|
|||
buf = kmalloc(ies1_len + ies2_len, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
memcpy(buf, ies1, ies1_len);
|
||||
if (ies1)
|
||||
memcpy(buf, ies1, ies1_len);
|
||||
dpos = buf + ies1_len;
|
||||
spos = ies2;
|
||||
while (spos + 1 < ies2 + ies2_len) {
|
||||
while (spos && (spos + 1 < ies2 + ies2_len)) {
|
||||
/* IE tag at offset 0, length at offset 1 */
|
||||
u16 ielen = 2 + spos[1];
|
||||
|
||||
if (spos + ielen > ies2 + ies2_len)
|
||||
break;
|
||||
if (spos[0] == WLAN_EID_VENDOR_SPECIFIC &&
|
||||
!_wil_cfg80211_find_ie(ies1, ies1_len, spos, ielen)) {
|
||||
(!ies1 || !_wil_cfg80211_find_ie(ies1, ies1_len,
|
||||
spos, ielen))) {
|
||||
memcpy(dpos, spos, ielen);
|
||||
dpos += ielen;
|
||||
}
|
||||
|
@ -3007,7 +3015,7 @@ static int wil_rf_sector_set_selected(struct wiphy *wiphy,
|
|||
wil, vif->mid, WMI_INVALID_RF_SECTOR_INDEX,
|
||||
sector_type, WIL_CID_ALL);
|
||||
if (rc == -EINVAL) {
|
||||
for (i = 0; i < WIL6210_MAX_CID; i++) {
|
||||
for (i = 0; i < max_assoc_sta; i++) {
|
||||
if (wil->sta[i].mid != vif->mid)
|
||||
continue;
|
||||
rc = wil_rf_sector_wmi_set_selected(
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -162,7 +162,7 @@ static int ring_show(struct seq_file *s, void *data)
|
|||
|
||||
snprintf(name, sizeof(name), "tx_%2d", i);
|
||||
|
||||
if (cid < WIL6210_MAX_CID)
|
||||
if (cid < max_assoc_sta)
|
||||
seq_printf(s,
|
||||
"\n%pM CID %d TID %d 1x%s BACK([%u] %u TU A%s) [%3d|%3d] idle %s\n",
|
||||
wil->sta[cid].addr, cid, tid,
|
||||
|
@ -792,14 +792,14 @@ static ssize_t wil_write_back(struct file *file, const char __user *buf,
|
|||
"BACK: del_rx require at least 2 params\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (p1 < 0 || p1 >= WIL6210_MAX_CID) {
|
||||
if (p1 < 0 || p1 >= max_assoc_sta) {
|
||||
wil_err(wil, "BACK: invalid CID %d\n", p1);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (rc < 4)
|
||||
p3 = WLAN_REASON_QSTA_LEAVE_QBSS;
|
||||
sta = &wil->sta[p1];
|
||||
wmi_delba_rx(wil, sta->mid, mk_cidxtid(p1, p2), p3);
|
||||
wmi_delba_rx(wil, sta->mid, p1, p2, p3);
|
||||
} else {
|
||||
wil_err(wil, "BACK: Unrecognized command \"%s\"\n", cmd);
|
||||
return -EINVAL;
|
||||
|
@ -1243,7 +1243,7 @@ static int bf_show(struct seq_file *s, void *data)
|
|||
|
||||
memset(&reply, 0, sizeof(reply));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
|
||||
for (i = 0; i < max_assoc_sta; i++) {
|
||||
u32 status;
|
||||
|
||||
cmd.cid = i;
|
||||
|
@ -1340,7 +1340,7 @@ static int link_show(struct seq_file *s, void *data)
|
|||
if (!sinfo)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
|
||||
for (i = 0; i < max_assoc_sta; i++) {
|
||||
struct wil_sta_info *p = &wil->sta[i];
|
||||
char *status = "unknown";
|
||||
struct wil6210_vif *vif;
|
||||
|
@ -1542,7 +1542,7 @@ __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock)
|
|||
struct wil6210_priv *wil = s->private;
|
||||
int i, tid, mcs;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
|
||||
for (i = 0; i < max_assoc_sta; i++) {
|
||||
struct wil_sta_info *p = &wil->sta[i];
|
||||
char *status = "unknown";
|
||||
u8 aid = 0;
|
||||
|
@ -1651,7 +1651,7 @@ __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock)
|
|||
struct wil6210_priv *wil = s->private;
|
||||
int i, bin;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
|
||||
for (i = 0; i < max_assoc_sta; i++) {
|
||||
struct wil_sta_info *p = &wil->sta[i];
|
||||
char *status = "unknown";
|
||||
u8 aid = 0;
|
||||
|
@ -1740,7 +1740,7 @@ static ssize_t wil_tx_latency_write(struct file *file, const char __user *buf,
|
|||
size_t sz = sizeof(u64) * WIL_NUM_LATENCY_BINS;
|
||||
|
||||
wil->tx_latency_res = val;
|
||||
for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
|
||||
for (i = 0; i < max_assoc_sta; i++) {
|
||||
struct wil_sta_info *sta = &wil->sta[i];
|
||||
|
||||
kfree(sta->tx_latency_bins);
|
||||
|
@ -1825,7 +1825,7 @@ static void wil_link_stats_debugfs_show_vif(struct wil6210_vif *vif,
|
|||
}
|
||||
|
||||
seq_printf(s, "TSF %lld\n", vif->fw_stats_tsf);
|
||||
for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
|
||||
for (i = 0; i < max_assoc_sta; i++) {
|
||||
if (wil->sta[i].status == wil_sta_unused)
|
||||
continue;
|
||||
if (wil->sta[i].mid != vif->mid)
|
||||
|
@ -2386,6 +2386,7 @@ static const struct dbg_off dbg_statics[] = {
|
|||
{"led_polarity", 0644, (ulong)&led_polarity, doff_u8},
|
||||
{"status_index", 0644, (ulong)&dbg_status_msg_index, doff_u32},
|
||||
{"sring_index", 0644, (ulong)&dbg_sring_index, doff_u32},
|
||||
{"drop_if_ring_full", 0644, (ulong)&drop_if_ring_full, doff_u8},
|
||||
{},
|
||||
};
|
||||
|
||||
|
@ -2439,7 +2440,7 @@ void wil6210_debugfs_remove(struct wil6210_priv *wil)
|
|||
wil->debug = NULL;
|
||||
|
||||
kfree(wil->dbg_data.data_arr);
|
||||
for (i = 0; i < ARRAY_SIZE(wil->sta); i++)
|
||||
for (i = 0; i < max_assoc_sta; i++)
|
||||
kfree(wil->sta[i].tx_latency_bins);
|
||||
|
||||
/* free pmc memory without sending command to fw, as it will
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -575,10 +575,14 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie)
|
|||
}
|
||||
|
||||
if (isr & BIT_DMA_EP_MISC_ICR_HALP) {
|
||||
wil_dbg_irq(wil, "irq_misc: HALP IRQ invoked\n");
|
||||
wil6210_mask_halp(wil);
|
||||
isr &= ~BIT_DMA_EP_MISC_ICR_HALP;
|
||||
complete(&wil->halp.comp);
|
||||
if (wil->halp.handle_icr) {
|
||||
/* no need to handle HALP ICRs until next vote */
|
||||
wil->halp.handle_icr = false;
|
||||
wil_dbg_irq(wil, "irq_misc: HALP IRQ invoked\n");
|
||||
wil6210_mask_halp(wil);
|
||||
complete(&wil->halp.comp);
|
||||
}
|
||||
}
|
||||
|
||||
wil->isr_misc = isr;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -219,7 +219,7 @@ static bool wil_vif_is_connected(struct wil6210_priv *wil, u8 mid)
|
|||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < WIL6210_MAX_CID; i++) {
|
||||
for (i = 0; i < max_assoc_sta; i++) {
|
||||
if (wil->sta[i].mid == mid &&
|
||||
wil->sta[i].status == wil_sta_connected)
|
||||
return true;
|
||||
|
@ -322,7 +322,7 @@ static void _wil6210_disconnect_complete(struct wil6210_vif *vif,
|
|||
wil_disconnect_cid_complete(vif, cid, reason_code);
|
||||
} else { /* all */
|
||||
wil_dbg_misc(wil, "Disconnect complete all\n");
|
||||
for (cid = 0; cid < WIL6210_MAX_CID; cid++)
|
||||
for (cid = 0; cid < max_assoc_sta; cid++)
|
||||
wil_disconnect_cid_complete(vif, cid, reason_code);
|
||||
}
|
||||
|
||||
|
@ -434,7 +434,7 @@ static void _wil6210_disconnect(struct wil6210_vif *vif, const u8 *bssid,
|
|||
wil_disconnect_cid(vif, cid, reason_code);
|
||||
} else { /* all */
|
||||
wil_dbg_misc(wil, "Disconnect all\n");
|
||||
for (cid = 0; cid < WIL6210_MAX_CID; cid++)
|
||||
for (cid = 0; cid < max_assoc_sta; cid++)
|
||||
wil_disconnect_cid(vif, cid, reason_code);
|
||||
}
|
||||
|
||||
|
@ -1895,7 +1895,7 @@ int wil_find_cid(struct wil6210_priv *wil, u8 mid, const u8 *mac)
|
|||
int i;
|
||||
int rc = -ENOENT;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
|
||||
for (i = 0; i < max_assoc_sta; i++) {
|
||||
if (wil->sta[i].mid == mid &&
|
||||
wil->sta[i].status != wil_sta_unused &&
|
||||
ether_addr_equal(wil->sta[i].addr, mac)) {
|
||||
|
@ -1919,11 +1919,14 @@ void wil_halp_vote(struct wil6210_priv *wil)
|
|||
|
||||
if (++wil->halp.ref_cnt == 1) {
|
||||
reinit_completion(&wil->halp.comp);
|
||||
/* mark to IRQ context to handle HALP ICR */
|
||||
wil->halp.handle_icr = true;
|
||||
wil6210_set_halp(wil);
|
||||
rc = wait_for_completion_timeout(&wil->halp.comp, to_jiffies);
|
||||
if (!rc) {
|
||||
wil_err(wil, "HALP vote timed out\n");
|
||||
/* Mask HALP as done in case the interrupt is raised */
|
||||
wil->halp.handle_icr = false;
|
||||
wil6210_mask_halp(wil);
|
||||
} else {
|
||||
wil_dbg_irq(wil,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2014-2017 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -307,8 +307,8 @@ static u16 wil_agg_size(struct wil6210_priv *wil, u16 req_agg_wsize)
|
|||
}
|
||||
|
||||
/* Block Ack - Rx side (recipient) */
|
||||
int wil_addba_rx_request(struct wil6210_priv *wil, u8 mid,
|
||||
u8 cidxtid, u8 dialog_token, __le16 ba_param_set,
|
||||
int wil_addba_rx_request(struct wil6210_priv *wil, u8 mid, u8 cid, u8 tid,
|
||||
u8 dialog_token, __le16 ba_param_set,
|
||||
__le16 ba_timeout, __le16 ba_seq_ctrl)
|
||||
__acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
|
||||
{
|
||||
|
@ -316,7 +316,6 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
|
|||
u16 agg_timeout = le16_to_cpu(ba_timeout);
|
||||
u16 seq_ctrl = le16_to_cpu(ba_seq_ctrl);
|
||||
struct wil_sta_info *sta;
|
||||
u8 cid, tid;
|
||||
u16 agg_wsize = 0;
|
||||
/* bit 0: A-MSDU supported
|
||||
* bit 1: policy (should be 0 for us)
|
||||
|
@ -335,10 +334,9 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
|
|||
int rc = 0;
|
||||
|
||||
might_sleep();
|
||||
parse_cidxtid(cidxtid, &cid, &tid);
|
||||
|
||||
/* sanity checks */
|
||||
if (cid >= WIL6210_MAX_CID) {
|
||||
if (cid >= max_assoc_sta) {
|
||||
wil_err(wil, "BACK: invalid CID %d\n", cid);
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2016 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -181,7 +182,7 @@ TRACE_EVENT(wil6210_rx,
|
|||
__entry->seq = wil_rxdesc_seq(d);
|
||||
__entry->mcs = wil_rxdesc_mcs(d);
|
||||
),
|
||||
TP_printk("index %d len %d mid %d cid %d tid %d mcs %d seq 0x%03x"
|
||||
TP_printk("index %d len %d mid %d cid (%%8) %d tid %d mcs %d seq 0x%03x"
|
||||
" type 0x%1x subtype 0x%1x", __entry->index, __entry->len,
|
||||
__entry->mid, __entry->cid, __entry->tid, __entry->mcs,
|
||||
__entry->seq, __entry->type, __entry->subtype)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -30,11 +30,6 @@
|
|||
#include "trace.h"
|
||||
#include "txrx_edma.h"
|
||||
|
||||
static bool rtap_include_phy_info;
|
||||
module_param(rtap_include_phy_info, bool, 0444);
|
||||
MODULE_PARM_DESC(rtap_include_phy_info,
|
||||
" Include PHY info in the radiotap header, default - no");
|
||||
|
||||
bool rx_align_2;
|
||||
module_param(rx_align_2, bool, 0444);
|
||||
MODULE_PARM_DESC(rx_align_2, " align Rx buffers on 4*n+2, default - no");
|
||||
|
@ -43,6 +38,9 @@ bool rx_large_buf;
|
|||
module_param(rx_large_buf, bool, 0444);
|
||||
MODULE_PARM_DESC(rx_large_buf, " allocate 8KB RX buffers, default - no");
|
||||
|
||||
/* Drop Tx packets in case Tx ring is full */
|
||||
bool drop_if_ring_full;
|
||||
|
||||
static inline uint wil_rx_snaplen(void)
|
||||
{
|
||||
return rx_align_2 ? 6 : 0;
|
||||
|
@ -332,87 +330,34 @@ static void wil_rx_add_radiotap_header(struct wil6210_priv *wil,
|
|||
u8 mcs_flags;
|
||||
u8 mcs_index;
|
||||
} __packed;
|
||||
struct wil6210_rtap_vendor {
|
||||
struct wil6210_rtap rtap;
|
||||
/* vendor */
|
||||
u8 vendor_oui[3] __aligned(2);
|
||||
u8 vendor_ns;
|
||||
__le16 vendor_skip;
|
||||
u8 vendor_data[0];
|
||||
} __packed;
|
||||
struct vring_rx_desc *d = wil_skb_rxdesc(skb);
|
||||
struct wil6210_rtap_vendor *rtap_vendor;
|
||||
struct wil6210_rtap *rtap;
|
||||
int rtap_len = sizeof(struct wil6210_rtap);
|
||||
int phy_length = 0; /* phy info header size, bytes */
|
||||
static char phy_data[128];
|
||||
struct ieee80211_channel *ch = wil->monitor_chandef.chan;
|
||||
|
||||
if (rtap_include_phy_info) {
|
||||
rtap_len = sizeof(*rtap_vendor) + sizeof(*d);
|
||||
/* calculate additional length */
|
||||
if (d->dma.status & RX_DMA_STATUS_PHY_INFO) {
|
||||
/**
|
||||
* PHY info starts from 8-byte boundary
|
||||
* there are 8-byte lines, last line may be partially
|
||||
* written (HW bug), thus FW configures for last line
|
||||
* to be excessive. Driver skips this last line.
|
||||
*/
|
||||
int len = min_t(int, 8 + sizeof(phy_data),
|
||||
wil_rxdesc_phy_length(d));
|
||||
|
||||
if (len > 8) {
|
||||
void *p = skb_tail_pointer(skb);
|
||||
void *pa = PTR_ALIGN(p, 8);
|
||||
|
||||
if (skb_tailroom(skb) >= len + (pa - p)) {
|
||||
phy_length = len - 8;
|
||||
memcpy(phy_data, pa, phy_length);
|
||||
}
|
||||
}
|
||||
}
|
||||
rtap_len += phy_length;
|
||||
}
|
||||
|
||||
if (skb_headroom(skb) < rtap_len &&
|
||||
pskb_expand_head(skb, rtap_len, 0, GFP_ATOMIC)) {
|
||||
wil_err(wil, "Unable to expand headroom to %d\n", rtap_len);
|
||||
return;
|
||||
}
|
||||
|
||||
rtap_vendor = skb_push(skb, rtap_len);
|
||||
memset(rtap_vendor, 0, rtap_len);
|
||||
rtap = skb_push(skb, rtap_len);
|
||||
memset(rtap, 0, rtap_len);
|
||||
|
||||
rtap_vendor->rtap.rthdr.it_version = PKTHDR_RADIOTAP_VERSION;
|
||||
rtap_vendor->rtap.rthdr.it_len = cpu_to_le16(rtap_len);
|
||||
rtap_vendor->rtap.rthdr.it_present = cpu_to_le32(
|
||||
(1 << IEEE80211_RADIOTAP_FLAGS) |
|
||||
rtap->rthdr.it_version = PKTHDR_RADIOTAP_VERSION;
|
||||
rtap->rthdr.it_len = cpu_to_le16(rtap_len);
|
||||
rtap->rthdr.it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
|
||||
(1 << IEEE80211_RADIOTAP_CHANNEL) |
|
||||
(1 << IEEE80211_RADIOTAP_MCS));
|
||||
if (d->dma.status & RX_DMA_STATUS_ERROR)
|
||||
rtap_vendor->rtap.flags |= IEEE80211_RADIOTAP_F_BADFCS;
|
||||
rtap->flags |= IEEE80211_RADIOTAP_F_BADFCS;
|
||||
|
||||
rtap_vendor->rtap.chnl_freq = cpu_to_le16(ch ? ch->center_freq : 58320);
|
||||
rtap_vendor->rtap.chnl_flags = cpu_to_le16(0);
|
||||
rtap->chnl_freq = cpu_to_le16(ch ? ch->center_freq : 58320);
|
||||
rtap->chnl_flags = cpu_to_le16(0);
|
||||
|
||||
rtap_vendor->rtap.mcs_present = IEEE80211_RADIOTAP_MCS_HAVE_MCS;
|
||||
rtap_vendor->rtap.mcs_flags = 0;
|
||||
rtap_vendor->rtap.mcs_index = wil_rxdesc_mcs(d);
|
||||
|
||||
if (rtap_include_phy_info) {
|
||||
rtap_vendor->rtap.rthdr.it_present |= cpu_to_le32(1 <<
|
||||
IEEE80211_RADIOTAP_VENDOR_NAMESPACE);
|
||||
/* OUI for Wilocity 04:ce:14 */
|
||||
rtap_vendor->vendor_oui[0] = 0x04;
|
||||
rtap_vendor->vendor_oui[1] = 0xce;
|
||||
rtap_vendor->vendor_oui[2] = 0x14;
|
||||
rtap_vendor->vendor_ns = 1;
|
||||
/* Rx descriptor + PHY data */
|
||||
rtap_vendor->vendor_skip = cpu_to_le16(sizeof(*d) +
|
||||
phy_length);
|
||||
memcpy(rtap_vendor->vendor_data, (void *)d, sizeof(*d));
|
||||
memcpy(rtap_vendor->vendor_data + sizeof(*d), phy_data,
|
||||
phy_length);
|
||||
}
|
||||
rtap->mcs_present = IEEE80211_RADIOTAP_MCS_HAVE_MCS;
|
||||
rtap->mcs_flags = 0;
|
||||
rtap->mcs_index = wil_rxdesc_mcs(d);
|
||||
}
|
||||
|
||||
static bool wil_is_rx_idle(struct wil6210_priv *wil)
|
||||
|
@ -427,6 +372,76 @@ static bool wil_is_rx_idle(struct wil6210_priv *wil)
|
|||
return true;
|
||||
}
|
||||
|
||||
static int wil_rx_get_cid_by_skb(struct wil6210_priv *wil, struct sk_buff *skb)
|
||||
{
|
||||
struct vring_rx_desc *d = wil_skb_rxdesc(skb);
|
||||
int mid = wil_rxdesc_mid(d);
|
||||
struct wil6210_vif *vif = wil->vifs[mid];
|
||||
/* cid from DMA descriptor is limited to 3 bits.
|
||||
* In case of cid>=8, the value would be cid modulo 8 and we need to
|
||||
* find real cid by locating the transmitter (ta) inside sta array
|
||||
*/
|
||||
int cid = wil_rxdesc_cid(d);
|
||||
unsigned int snaplen = wil_rx_snaplen();
|
||||
struct ieee80211_hdr_3addr *hdr;
|
||||
int i;
|
||||
unsigned char *ta;
|
||||
u8 ftype;
|
||||
|
||||
/* in monitor mode there are no connections */
|
||||
if (vif->wdev.iftype == NL80211_IFTYPE_MONITOR)
|
||||
return cid;
|
||||
|
||||
ftype = wil_rxdesc_ftype(d) << 2;
|
||||
if (likely(ftype == IEEE80211_FTYPE_DATA)) {
|
||||
if (unlikely(skb->len < ETH_HLEN + snaplen)) {
|
||||
wil_err_ratelimited(wil,
|
||||
"Short data frame, len = %d\n",
|
||||
skb->len);
|
||||
return -ENOENT;
|
||||
}
|
||||
ta = wil_skb_get_sa(skb);
|
||||
} else {
|
||||
if (unlikely(skb->len < sizeof(struct ieee80211_hdr_3addr))) {
|
||||
wil_err_ratelimited(wil, "Short frame, len = %d\n",
|
||||
skb->len);
|
||||
return -ENOENT;
|
||||
}
|
||||
hdr = (void *)skb->data;
|
||||
ta = hdr->addr2;
|
||||
}
|
||||
|
||||
if (max_assoc_sta <= WIL6210_RX_DESC_MAX_CID)
|
||||
return cid;
|
||||
|
||||
/* assuming no concurrency between AP interfaces and STA interfaces.
|
||||
* multista is used only in P2P_GO or AP mode. In other modes return
|
||||
* cid from the rx descriptor
|
||||
*/
|
||||
if (vif->wdev.iftype != NL80211_IFTYPE_P2P_GO &&
|
||||
vif->wdev.iftype != NL80211_IFTYPE_AP)
|
||||
return cid;
|
||||
|
||||
/* For Rx packets cid from rx descriptor is limited to 3 bits (0..7),
|
||||
* to find the real cid, compare transmitter address with the stored
|
||||
* stations mac address in the driver sta array
|
||||
*/
|
||||
for (i = cid; i < max_assoc_sta; i += WIL6210_RX_DESC_MAX_CID) {
|
||||
if (wil->sta[i].status != wil_sta_unused &&
|
||||
ether_addr_equal(wil->sta[i].addr, ta)) {
|
||||
cid = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i >= max_assoc_sta) {
|
||||
wil_err_ratelimited(wil, "Could not find cid for frame with transmit addr = %pM, iftype = %d, frametype = %d, len = %d\n",
|
||||
ta, vif->wdev.iftype, ftype, skb->len);
|
||||
cid = -ENOENT;
|
||||
}
|
||||
|
||||
return cid;
|
||||
}
|
||||
|
||||
/**
|
||||
* reap 1 frame from @swhead
|
||||
*
|
||||
|
@ -452,7 +467,7 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
|
|||
int i;
|
||||
struct wil_net_stats *stats;
|
||||
|
||||
BUILD_BUG_ON(sizeof(struct vring_rx_desc) > sizeof(skb->cb));
|
||||
BUILD_BUG_ON(sizeof(struct skb_rx_info) > sizeof(skb->cb));
|
||||
|
||||
again:
|
||||
if (unlikely(wil_ring_is_empty(vring)))
|
||||
|
@ -484,7 +499,6 @@ again:
|
|||
wil_hex_dump_txrx("RxD ", DUMP_PREFIX_NONE, 32, 4,
|
||||
(const void *)d, sizeof(*d), false);
|
||||
|
||||
cid = wil_rxdesc_cid(d);
|
||||
mid = wil_rxdesc_mid(d);
|
||||
vif = wil->vifs[mid];
|
||||
|
||||
|
@ -495,11 +509,9 @@ again:
|
|||
goto again;
|
||||
}
|
||||
ndev = vif_to_ndev(vif);
|
||||
stats = &wil->sta[cid].stats;
|
||||
|
||||
if (unlikely(dmalen > sz)) {
|
||||
wil_err(wil, "Rx size too large: %d bytes!\n", dmalen);
|
||||
stats->rx_large_frame++;
|
||||
wil_err_ratelimited(wil, "Rx size too large: %d bytes!\n",
|
||||
dmalen);
|
||||
kfree_skb(skb);
|
||||
goto again;
|
||||
}
|
||||
|
@ -510,6 +522,14 @@ again:
|
|||
wil_hex_dump_txrx("Rx ", DUMP_PREFIX_OFFSET, 16, 1,
|
||||
skb->data, skb_headlen(skb), false);
|
||||
|
||||
cid = wil_rx_get_cid_by_skb(wil, skb);
|
||||
if (cid == -ENOENT) {
|
||||
kfree_skb(skb);
|
||||
goto again;
|
||||
}
|
||||
wil_skb_set_cid(skb, (u8)cid);
|
||||
stats = &wil->sta[cid].stats;
|
||||
|
||||
stats->last_mcs_rx = wil_rxdesc_mcs(d);
|
||||
if (stats->last_mcs_rx < ARRAY_SIZE(stats->rx_per_mcs))
|
||||
stats->rx_per_mcs[stats->last_mcs_rx]++;
|
||||
|
@ -556,13 +576,6 @@ again:
|
|||
goto again;
|
||||
}
|
||||
|
||||
if (unlikely(skb->len < ETH_HLEN + snaplen)) {
|
||||
wil_err(wil, "Short frame, len = %d\n", skb->len);
|
||||
stats->rx_short_frame++;
|
||||
kfree_skb(skb);
|
||||
goto again;
|
||||
}
|
||||
|
||||
/* L4 IDENT is on when HW calculated checksum, check status
|
||||
* and in case of error drop the packet
|
||||
* higher stack layers will handle retransmission (if required)
|
||||
|
@ -659,7 +672,7 @@ int reverse_memcmp(const void *cs, const void *ct, size_t count)
|
|||
static int wil_rx_crypto_check(struct wil6210_priv *wil, struct sk_buff *skb)
|
||||
{
|
||||
struct vring_rx_desc *d = wil_skb_rxdesc(skb);
|
||||
int cid = wil_rxdesc_cid(d);
|
||||
int cid = wil_skb_get_cid(skb);
|
||||
int tid = wil_rxdesc_tid(d);
|
||||
int key_id = wil_rxdesc_key_id(d);
|
||||
int mc = wil_rxdesc_mcast(d);
|
||||
|
@ -707,7 +720,7 @@ static void wil_get_netif_rx_params(struct sk_buff *skb, int *cid,
|
|||
{
|
||||
struct vring_rx_desc *d = wil_skb_rxdesc(skb);
|
||||
|
||||
*cid = wil_rxdesc_cid(d); /* always 0..7, no need to check */
|
||||
*cid = wil_skb_get_cid(skb);
|
||||
*security = wil_rxdesc_security(d);
|
||||
}
|
||||
|
||||
|
@ -724,11 +737,11 @@ void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev)
|
|||
unsigned int len = skb->len;
|
||||
int cid;
|
||||
int security;
|
||||
struct ethhdr *eth = (void *)skb->data;
|
||||
u8 *sa, *da = wil_skb_get_da(skb);
|
||||
/* here looking for DA, not A1, thus Rxdesc's 'mcast' indication
|
||||
* is not suitable, need to look at data
|
||||
*/
|
||||
int mcast = is_multicast_ether_addr(eth->h_dest);
|
||||
int mcast = is_multicast_ether_addr(da);
|
||||
struct wil_net_stats *stats;
|
||||
struct sk_buff *xmit_skb = NULL;
|
||||
static const char * const gro_res_str[] = {
|
||||
|
@ -759,7 +772,8 @@ void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev)
|
|||
}
|
||||
|
||||
if (wdev->iftype == NL80211_IFTYPE_STATION) {
|
||||
if (mcast && ether_addr_equal(eth->h_source, ndev->dev_addr)) {
|
||||
sa = wil_skb_get_sa(skb);
|
||||
if (mcast && ether_addr_equal(sa, ndev->dev_addr)) {
|
||||
/* mcast packet looped back to us */
|
||||
rc = GRO_DROP;
|
||||
dev_kfree_skb(skb);
|
||||
|
@ -772,8 +786,7 @@ void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev)
|
|||
*/
|
||||
xmit_skb = skb_copy(skb, GFP_ATOMIC);
|
||||
} else {
|
||||
int xmit_cid = wil_find_cid(wil, vif->mid,
|
||||
eth->h_dest);
|
||||
int xmit_cid = wil_find_cid(wil, vif->mid, da);
|
||||
|
||||
if (xmit_cid >= 0) {
|
||||
/* The destination station is associated to
|
||||
|
@ -971,7 +984,6 @@ static int wil_vring_init_tx(struct wil6210_vif *vif, int id, int size,
|
|||
.ring_size = cpu_to_le16(size),
|
||||
},
|
||||
.ringid = id,
|
||||
.cidxtid = mk_cidxtid(cid, tid),
|
||||
.encap_trans_type = WMI_VRING_ENC_TYPE_802_3,
|
||||
.mac_ctrl = 0,
|
||||
.to_resolution = 0,
|
||||
|
@ -991,6 +1003,14 @@ static int wil_vring_init_tx(struct wil6210_vif *vif, int id, int size,
|
|||
struct wil_ring *vring = &wil->ring_tx[id];
|
||||
struct wil_ring_tx_data *txdata = &wil->ring_tx_data[id];
|
||||
|
||||
if (cid >= WIL6210_RX_DESC_MAX_CID) {
|
||||
cmd.vring_cfg.cidxtid = CIDXTID_EXTENDED_CID_TID;
|
||||
cmd.vring_cfg.cid = cid;
|
||||
cmd.vring_cfg.tid = tid;
|
||||
} else {
|
||||
cmd.vring_cfg.cidxtid = mk_cidxtid(cid, tid);
|
||||
}
|
||||
|
||||
wil_dbg_misc(wil, "vring_init_tx: max_mpdu_size %d\n",
|
||||
cmd.vring_cfg.tx_sw_ring.max_mpdu_size);
|
||||
lockdep_assert_held(&wil->mutex);
|
||||
|
@ -1043,7 +1063,7 @@ static int wil_vring_init_tx(struct wil6210_vif *vif, int id, int size,
|
|||
txdata->enabled = 0;
|
||||
spin_unlock_bh(&txdata->lock);
|
||||
wil_vring_free(wil, vring);
|
||||
wil->ring2cid_tid[id][0] = WIL6210_MAX_CID;
|
||||
wil->ring2cid_tid[id][0] = max_assoc_sta;
|
||||
wil->ring2cid_tid[id][1] = 0;
|
||||
|
||||
out:
|
||||
|
@ -1128,7 +1148,7 @@ fail:
|
|||
txdata->dot1x_open = false;
|
||||
txdata->enabled = 0;
|
||||
spin_unlock_bh(&txdata->lock);
|
||||
wil->ring2cid_tid[ring_id][0] = WIL6210_MAX_CID;
|
||||
wil->ring2cid_tid[ring_id][0] = max_assoc_sta;
|
||||
wil->ring2cid_tid[ring_id][1] = 0;
|
||||
return rc;
|
||||
}
|
||||
|
@ -1175,7 +1195,7 @@ int wil_vring_init_bcast(struct wil6210_vif *vif, int id, int size)
|
|||
if (rc)
|
||||
goto out;
|
||||
|
||||
wil->ring2cid_tid[id][0] = WIL6210_MAX_CID; /* CID */
|
||||
wil->ring2cid_tid[id][0] = max_assoc_sta; /* CID */
|
||||
wil->ring2cid_tid[id][1] = 0; /* TID */
|
||||
|
||||
cmd.vring_cfg.tx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa);
|
||||
|
@ -1217,12 +1237,13 @@ static struct wil_ring *wil_find_tx_ucast(struct wil6210_priv *wil,
|
|||
struct wil6210_vif *vif,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
int i;
|
||||
struct ethhdr *eth = (void *)skb->data;
|
||||
int cid = wil_find_cid(wil, vif->mid, eth->h_dest);
|
||||
int i, cid;
|
||||
const u8 *da = wil_skb_get_da(skb);
|
||||
int min_ring_id = wil_get_min_tx_ring_id(wil);
|
||||
|
||||
if (cid < 0)
|
||||
cid = wil_find_cid(wil, vif->mid, da);
|
||||
|
||||
if (cid < 0 || cid >= max_assoc_sta)
|
||||
return NULL;
|
||||
|
||||
/* TODO: fix for multiple TID */
|
||||
|
@ -1235,7 +1256,7 @@ static struct wil_ring *wil_find_tx_ucast(struct wil6210_priv *wil,
|
|||
struct wil_ring_tx_data *txdata = &wil->ring_tx_data[i];
|
||||
|
||||
wil_dbg_txrx(wil, "find_tx_ucast: (%pM) -> [%d]\n",
|
||||
eth->h_dest, i);
|
||||
da, i);
|
||||
if (v->va && txdata->enabled) {
|
||||
return v;
|
||||
} else {
|
||||
|
@ -1274,7 +1295,7 @@ static struct wil_ring *wil_find_tx_ring_sta(struct wil6210_priv *wil,
|
|||
continue;
|
||||
|
||||
cid = wil->ring2cid_tid[i][0];
|
||||
if (cid >= WIL6210_MAX_CID) /* skip BCAST */
|
||||
if (cid >= max_assoc_sta) /* skip BCAST */
|
||||
continue;
|
||||
|
||||
if (!wil->ring_tx_data[i].dot1x_open &&
|
||||
|
@ -1326,10 +1347,10 @@ static struct wil_ring *wil_find_tx_bcast_1(struct wil6210_priv *wil,
|
|||
static void wil_set_da_for_vring(struct wil6210_priv *wil,
|
||||
struct sk_buff *skb, int vring_index)
|
||||
{
|
||||
struct ethhdr *eth = (void *)skb->data;
|
||||
u8 *da = wil_skb_get_da(skb);
|
||||
int cid = wil->ring2cid_tid[vring_index][0];
|
||||
|
||||
ether_addr_copy(eth->h_dest, wil->sta[cid].addr);
|
||||
ether_addr_copy(da, wil->sta[cid].addr);
|
||||
}
|
||||
|
||||
static struct wil_ring *wil_find_tx_bcast_2(struct wil6210_priv *wil,
|
||||
|
@ -1340,8 +1361,7 @@ static struct wil_ring *wil_find_tx_bcast_2(struct wil6210_priv *wil,
|
|||
struct sk_buff *skb2;
|
||||
int i;
|
||||
u8 cid;
|
||||
struct ethhdr *eth = (void *)skb->data;
|
||||
char *src = eth->h_source;
|
||||
const u8 *src = wil_skb_get_sa(skb);
|
||||
struct wil_ring_tx_data *txdata, *txdata2;
|
||||
int min_ring_id = wil_get_min_tx_ring_id(wil);
|
||||
|
||||
|
@ -1353,7 +1373,7 @@ static struct wil_ring *wil_find_tx_bcast_2(struct wil6210_priv *wil,
|
|||
continue;
|
||||
|
||||
cid = wil->ring2cid_tid[i][0];
|
||||
if (cid >= WIL6210_MAX_CID) /* skip BCAST */
|
||||
if (cid >= max_assoc_sta) /* skip BCAST */
|
||||
continue;
|
||||
if (!wil->ring_tx_data[i].dot1x_open &&
|
||||
skb->protocol != cpu_to_be16(ETH_P_PAE))
|
||||
|
@ -1381,7 +1401,7 @@ found:
|
|||
if (!v2->va || txdata2->mid != vif->mid)
|
||||
continue;
|
||||
cid = wil->ring2cid_tid[i][0];
|
||||
if (cid >= WIL6210_MAX_CID) /* skip BCAST */
|
||||
if (cid >= max_assoc_sta) /* skip BCAST */
|
||||
continue;
|
||||
if (!wil->ring_tx_data[i].dot1x_open &&
|
||||
skb->protocol != cpu_to_be16(ETH_P_PAE))
|
||||
|
@ -2032,6 +2052,10 @@ static inline void __wil_update_net_queues(struct wil6210_priv *wil,
|
|||
wil_dbg_txrx(wil, "check_stop=%d, mid=%d, stopped=%d",
|
||||
check_stop, vif->mid, vif->net_queue_stopped);
|
||||
|
||||
if (ring && drop_if_ring_full)
|
||||
/* no need to stop/wake net queues */
|
||||
return;
|
||||
|
||||
if (check_stop == vif->net_queue_stopped)
|
||||
/* net queues already in desired state */
|
||||
return;
|
||||
|
@ -2095,8 +2119,8 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
|||
{
|
||||
struct wil6210_vif *vif = ndev_to_vif(ndev);
|
||||
struct wil6210_priv *wil = vif_to_wil(vif);
|
||||
struct ethhdr *eth = (void *)skb->data;
|
||||
bool bcast = is_multicast_ether_addr(eth->h_dest);
|
||||
const u8 *da = wil_skb_get_da(skb);
|
||||
bool bcast = is_multicast_ether_addr(da);
|
||||
struct wil_ring *ring;
|
||||
static bool pr_once_fw;
|
||||
int rc;
|
||||
|
@ -2143,7 +2167,7 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
|||
ring = wil_find_tx_ucast(wil, vif, skb);
|
||||
}
|
||||
if (unlikely(!ring)) {
|
||||
wil_dbg_txrx(wil, "No Tx RING found for %pM\n", eth->h_dest);
|
||||
wil_dbg_txrx(wil, "No Tx RING found for %pM\n", da);
|
||||
goto drop;
|
||||
}
|
||||
/* set up vring entry */
|
||||
|
@ -2157,6 +2181,8 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
|||
dev_kfree_skb_any(skb);
|
||||
return NETDEV_TX_OK;
|
||||
case -ENOMEM:
|
||||
if (drop_if_ring_full)
|
||||
goto drop;
|
||||
return NETDEV_TX_BUSY;
|
||||
default:
|
||||
break; /* goto drop; */
|
||||
|
@ -2228,7 +2254,7 @@ int wil_tx_complete(struct wil6210_vif *vif, int ringid)
|
|||
|
||||
used_before_complete = wil_ring_used_tx(vring);
|
||||
|
||||
if (cid < WIL6210_MAX_CID)
|
||||
if (cid < max_assoc_sta)
|
||||
stats = &wil->sta[cid].stats;
|
||||
|
||||
while (!wil_ring_is_empty(vring)) {
|
||||
|
@ -2337,7 +2363,7 @@ static void wil_get_reorder_params(struct wil6210_priv *wil,
|
|||
struct vring_rx_desc *d = wil_skb_rxdesc(skb);
|
||||
|
||||
*tid = wil_rxdesc_tid(d);
|
||||
*cid = wil_rxdesc_cid(d);
|
||||
*cid = wil_skb_get_cid(skb);
|
||||
*mid = wil_rxdesc_mid(d);
|
||||
*seq = wil_rxdesc_seq(d);
|
||||
*mcast = wil_rxdesc_mcast(d);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2016 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -458,6 +458,18 @@ union wil_ring_desc {
|
|||
union wil_rx_desc rx;
|
||||
} __packed;
|
||||
|
||||
struct packet_rx_info {
|
||||
u8 cid;
|
||||
};
|
||||
|
||||
/* this struct will be stored in the skb cb buffer
|
||||
* max length of the struct is limited to 48 bytes
|
||||
*/
|
||||
struct skb_rx_info {
|
||||
struct vring_rx_desc rx_desc;
|
||||
struct packet_rx_info rx_info;
|
||||
};
|
||||
|
||||
static inline int wil_rxdesc_tid(struct vring_rx_desc *d)
|
||||
{
|
||||
return WIL_GET_BITS(d->mac.d0, 0, 3);
|
||||
|
@ -530,11 +542,6 @@ static inline int wil_rxdesc_mcast(struct vring_rx_desc *d)
|
|||
return WIL_GET_BITS(d->mac.d1, 13, 14);
|
||||
}
|
||||
|
||||
static inline int wil_rxdesc_phy_length(struct vring_rx_desc *d)
|
||||
{
|
||||
return WIL_GET_BITS(d->dma.d0, 16, 29);
|
||||
}
|
||||
|
||||
static inline struct vring_rx_desc *wil_skb_rxdesc(struct sk_buff *skb)
|
||||
{
|
||||
return (void *)skb->cb;
|
||||
|
@ -560,11 +567,25 @@ static inline int wil_ring_is_full(struct wil_ring *ring)
|
|||
return wil_ring_next_tail(ring) == ring->swhead;
|
||||
}
|
||||
|
||||
static inline bool wil_need_txstat(struct sk_buff *skb)
|
||||
static inline u8 *wil_skb_get_da(struct sk_buff *skb)
|
||||
{
|
||||
struct ethhdr *eth = (void *)skb->data;
|
||||
|
||||
return is_unicast_ether_addr(eth->h_dest) && skb->sk &&
|
||||
return eth->h_dest;
|
||||
}
|
||||
|
||||
static inline u8 *wil_skb_get_sa(struct sk_buff *skb)
|
||||
{
|
||||
struct ethhdr *eth = (void *)skb->data;
|
||||
|
||||
return eth->h_source;
|
||||
}
|
||||
|
||||
static inline bool wil_need_txstat(struct sk_buff *skb)
|
||||
{
|
||||
const u8 *da = wil_skb_get_da(skb);
|
||||
|
||||
return is_unicast_ether_addr(da) && skb->sk &&
|
||||
(skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS);
|
||||
}
|
||||
|
||||
|
@ -610,6 +631,20 @@ static inline bool wil_val_in_range(int val, int min, int max)
|
|||
return val >= min && val < max;
|
||||
}
|
||||
|
||||
static inline u8 wil_skb_get_cid(struct sk_buff *skb)
|
||||
{
|
||||
struct skb_rx_info *skb_rx_info = (void *)skb->cb;
|
||||
|
||||
return skb_rx_info->rx_info.cid;
|
||||
}
|
||||
|
||||
static inline void wil_skb_set_cid(struct sk_buff *skb, u8 cid)
|
||||
{
|
||||
struct skb_rx_info *skb_rx_info = (void *)skb->cb;
|
||||
|
||||
skb_rx_info->rx_info.cid = cid;
|
||||
}
|
||||
|
||||
void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev);
|
||||
void wil_rx_reorder(struct wil6210_priv *wil, struct sk_buff *skb);
|
||||
void wil_rx_bar(struct wil6210_priv *wil, struct wil6210_vif *vif,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2012-2019 The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -727,7 +727,7 @@ static int wil_ring_init_tx_edma(struct wil6210_vif *vif, int ring_id,
|
|||
txdata->enabled = 0;
|
||||
spin_unlock_bh(&txdata->lock);
|
||||
wil_ring_free_edma(wil, ring);
|
||||
wil->ring2cid_tid[ring_id][0] = WIL6210_MAX_CID;
|
||||
wil->ring2cid_tid[ring_id][0] = max_assoc_sta;
|
||||
wil->ring2cid_tid[ring_id][1] = 0;
|
||||
|
||||
out:
|
||||
|
@ -932,7 +932,7 @@ again:
|
|||
eop = wil_rx_status_get_eop(msg);
|
||||
|
||||
cid = wil_rx_status_get_cid(msg);
|
||||
if (unlikely(!wil_val_in_range(cid, 0, WIL6210_MAX_CID))) {
|
||||
if (unlikely(!wil_val_in_range(cid, 0, max_assoc_sta))) {
|
||||
wil_err(wil, "Corrupt cid=%d, sring->swhead=%d\n",
|
||||
cid, sring->swhead);
|
||||
rxdata->skipping = true;
|
||||
|
@ -1137,7 +1137,7 @@ int wil_tx_sring_handler(struct wil6210_priv *wil,
|
|||
/* Total number of completed descriptors in all descriptor rings */
|
||||
int desc_cnt = 0;
|
||||
int cid;
|
||||
struct wil_net_stats *stats = NULL;
|
||||
struct wil_net_stats *stats;
|
||||
struct wil_tx_enhanced_desc *_d;
|
||||
unsigned int ring_id;
|
||||
unsigned int num_descs;
|
||||
|
@ -1187,8 +1187,7 @@ int wil_tx_sring_handler(struct wil6210_priv *wil,
|
|||
ndev = vif_to_ndev(vif);
|
||||
|
||||
cid = wil->ring2cid_tid[ring_id][0];
|
||||
if (cid < WIL6210_MAX_CID)
|
||||
stats = &wil->sta[cid].stats;
|
||||
stats = (cid < max_assoc_sta ? &wil->sta[cid].stats : NULL);
|
||||
|
||||
wil_dbg_txrx(wil,
|
||||
"tx_status: completed desc_ring (%d), num_descs (%d)\n",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -38,6 +38,8 @@ extern bool rx_large_buf;
|
|||
extern bool debug_fw;
|
||||
extern bool disable_ap_sme;
|
||||
extern bool ftm_mode;
|
||||
extern bool drop_if_ring_full;
|
||||
extern uint max_assoc_sta;
|
||||
|
||||
struct wil6210_priv;
|
||||
struct wil6210_vif;
|
||||
|
@ -89,7 +91,8 @@ static inline u32 WIL_GET_BITS(u32 x, int b0, int b1)
|
|||
#define WIL_RING_SIZE_ORDER_MIN (5)
|
||||
#define WIL_RING_SIZE_ORDER_MAX (15)
|
||||
#define WIL6210_MAX_TX_RINGS (24) /* HW limit */
|
||||
#define WIL6210_MAX_CID (8) /* HW limit */
|
||||
#define WIL6210_MAX_CID (20) /* max number of stations */
|
||||
#define WIL6210_RX_DESC_MAX_CID (8) /* HW limit */
|
||||
#define WIL6210_NAPI_BUDGET (16) /* arbitrary */
|
||||
#define WIL_MAX_AMPDU_SIZE (64 * 1024) /* FW/HW limit */
|
||||
#define WIL_MAX_AGG_WSIZE (32) /* FW/HW limit */
|
||||
|
@ -457,7 +460,7 @@ static inline void parse_cidxtid(u8 cidxtid, u8 *cid, u8 *tid)
|
|||
*/
|
||||
static inline bool wil_cid_valid(u8 cid)
|
||||
{
|
||||
return cid < WIL6210_MAX_CID;
|
||||
return (cid >= 0 && cid < max_assoc_sta);
|
||||
}
|
||||
|
||||
struct wil6210_mbox_ring {
|
||||
|
@ -791,6 +794,7 @@ struct wil_halp {
|
|||
struct mutex lock; /* protect halp ref_cnt */
|
||||
unsigned int ref_cnt;
|
||||
struct completion comp;
|
||||
u8 handle_icr;
|
||||
};
|
||||
|
||||
struct wil_blob_wrapper {
|
||||
|
@ -1235,7 +1239,7 @@ int wmi_disconnect_sta(struct wil6210_vif *vif, const u8 *mac, u16 reason,
|
|||
int wmi_addba(struct wil6210_priv *wil, u8 mid,
|
||||
u8 ringid, u8 size, u16 timeout);
|
||||
int wmi_delba_tx(struct wil6210_priv *wil, u8 mid, u8 ringid, u16 reason);
|
||||
int wmi_delba_rx(struct wil6210_priv *wil, u8 mid, u8 cidxtid, u16 reason);
|
||||
int wmi_delba_rx(struct wil6210_priv *wil, u8 mid, u8 cid, u8 tid, u16 reason);
|
||||
int wmi_addba_rx_resp(struct wil6210_priv *wil,
|
||||
u8 mid, u8 cid, u8 tid, u8 token,
|
||||
u16 status, bool amsdu, u16 agg_wsize, u16 timeout);
|
||||
|
@ -1248,8 +1252,8 @@ int wmi_port_allocate(struct wil6210_priv *wil, u8 mid,
|
|||
const u8 *mac, enum nl80211_iftype iftype);
|
||||
int wmi_port_delete(struct wil6210_priv *wil, u8 mid);
|
||||
int wmi_link_stats_cfg(struct wil6210_vif *vif, u32 type, u8 cid, u32 interval);
|
||||
int wil_addba_rx_request(struct wil6210_priv *wil, u8 mid,
|
||||
u8 cidxtid, u8 dialog_token, __le16 ba_param_set,
|
||||
int wil_addba_rx_request(struct wil6210_priv *wil, u8 mid, u8 cid, u8 tid,
|
||||
u8 dialog_token, __le16 ba_param_set,
|
||||
__le16 ba_timeout, __le16 ba_seq_ctrl);
|
||||
int wil_addba_tx_request(struct wil6210_priv *wil, u8 ringid, u16 wsize);
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -24,8 +24,9 @@
|
|||
#include "wmi.h"
|
||||
#include "trace.h"
|
||||
|
||||
static uint max_assoc_sta = WIL6210_MAX_CID;
|
||||
module_param(max_assoc_sta, uint, 0644);
|
||||
/* set the default max assoc sta to max supported by driver */
|
||||
uint max_assoc_sta = WIL6210_MAX_CID;
|
||||
module_param(max_assoc_sta, uint, 0444);
|
||||
MODULE_PARM_DESC(max_assoc_sta, " Max number of stations associated to the AP");
|
||||
|
||||
int agg_wsize; /* = 0; */
|
||||
|
@ -770,6 +771,7 @@ static void wmi_evt_ready(struct wil6210_vif *vif, int id, void *d, int len)
|
|||
struct wil6210_priv *wil = vif_to_wil(vif);
|
||||
struct wiphy *wiphy = wil_to_wiphy(wil);
|
||||
struct wmi_ready_event *evt = d;
|
||||
u8 fw_max_assoc_sta;
|
||||
|
||||
wil_info(wil, "FW ver. %s(SW %d); MAC %pM; %d MID's\n",
|
||||
wil->fw_version, le32_to_cpu(evt->sw_version),
|
||||
|
@ -787,6 +789,25 @@ static void wmi_evt_ready(struct wil6210_vif *vif, int id, void *d, int len)
|
|||
evt->rfc_read_calib_result);
|
||||
wil->fw_calib_result = evt->rfc_read_calib_result;
|
||||
}
|
||||
|
||||
fw_max_assoc_sta = WIL6210_RX_DESC_MAX_CID;
|
||||
if (len > offsetof(struct wmi_ready_event, max_assoc_sta) &&
|
||||
evt->max_assoc_sta > 0) {
|
||||
fw_max_assoc_sta = evt->max_assoc_sta;
|
||||
wil_dbg_wmi(wil, "fw reported max assoc sta %d\n",
|
||||
fw_max_assoc_sta);
|
||||
|
||||
if (fw_max_assoc_sta > WIL6210_MAX_CID) {
|
||||
wil_dbg_wmi(wil,
|
||||
"fw max assoc sta %d exceeds max driver supported %d\n",
|
||||
fw_max_assoc_sta, WIL6210_MAX_CID);
|
||||
fw_max_assoc_sta = WIL6210_MAX_CID;
|
||||
}
|
||||
}
|
||||
|
||||
max_assoc_sta = min_t(uint, max_assoc_sta, fw_max_assoc_sta);
|
||||
wil_dbg_wmi(wil, "setting max assoc sta to %d\n", max_assoc_sta);
|
||||
|
||||
wil_set_recovery_state(wil, fw_recovery_idle);
|
||||
set_bit(wil_status_fwready, wil->status);
|
||||
/* let the reset sequence continue */
|
||||
|
@ -952,7 +973,7 @@ static void wmi_evt_connect(struct wil6210_vif *vif, int id, void *d, int len)
|
|||
evt->assoc_req_len, evt->assoc_resp_len);
|
||||
return;
|
||||
}
|
||||
if (evt->cid >= WIL6210_MAX_CID) {
|
||||
if (evt->cid >= max_assoc_sta) {
|
||||
wil_err(wil, "Connect CID invalid : %d\n", evt->cid);
|
||||
return;
|
||||
}
|
||||
|
@ -1271,9 +1292,16 @@ static void wmi_evt_addba_rx_req(struct wil6210_vif *vif, int id,
|
|||
void *d, int len)
|
||||
{
|
||||
struct wil6210_priv *wil = vif_to_wil(vif);
|
||||
u8 cid, tid;
|
||||
struct wmi_rcp_addba_req_event *evt = d;
|
||||
|
||||
wil_addba_rx_request(wil, vif->mid, evt->cidxtid, evt->dialog_token,
|
||||
if (evt->cidxtid != CIDXTID_EXTENDED_CID_TID) {
|
||||
parse_cidxtid(evt->cidxtid, &cid, &tid);
|
||||
} else {
|
||||
cid = evt->cid;
|
||||
tid = evt->tid;
|
||||
}
|
||||
wil_addba_rx_request(wil, vif->mid, cid, tid, evt->dialog_token,
|
||||
evt->ba_param_set, evt->ba_timeout,
|
||||
evt->ba_seq_ctrl);
|
||||
}
|
||||
|
@ -1289,7 +1317,13 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
|
|||
struct wil_tid_ampdu_rx *r;
|
||||
|
||||
might_sleep();
|
||||
parse_cidxtid(evt->cidxtid, &cid, &tid);
|
||||
|
||||
if (evt->cidxtid != CIDXTID_EXTENDED_CID_TID) {
|
||||
parse_cidxtid(evt->cidxtid, &cid, &tid);
|
||||
} else {
|
||||
cid = evt->cid;
|
||||
tid = evt->tid;
|
||||
}
|
||||
wil_dbg_wmi(wil, "DELBA MID %d CID %d TID %d from %s reason %d\n",
|
||||
vif->mid, cid, tid,
|
||||
evt->from_initiator ? "originator" : "recipient",
|
||||
|
@ -1404,7 +1438,7 @@ static void wil_link_stats_store_basic(struct wil6210_vif *vif,
|
|||
u8 cid = basic->cid;
|
||||
struct wil_sta_info *sta;
|
||||
|
||||
if (cid < 0 || cid >= WIL6210_MAX_CID) {
|
||||
if (cid < 0 || cid >= max_assoc_sta) {
|
||||
wil_err(wil, "invalid cid %d\n", cid);
|
||||
return;
|
||||
}
|
||||
|
@ -1554,7 +1588,7 @@ static int wil_find_cid_ringid_sta(struct wil6210_priv *wil,
|
|||
continue;
|
||||
|
||||
lcid = wil->ring2cid_tid[i][0];
|
||||
if (lcid >= WIL6210_MAX_CID) /* skip BCAST */
|
||||
if (lcid >= max_assoc_sta) /* skip BCAST */
|
||||
continue;
|
||||
|
||||
wil_dbg_wmi(wil, "find sta -> ringid %d cid %d\n", i, lcid);
|
||||
|
@ -2120,10 +2154,9 @@ int wmi_pcp_start(struct wil6210_vif *vif,
|
|||
|
||||
if ((cmd.pcp_max_assoc_sta > WIL6210_MAX_CID) ||
|
||||
(cmd.pcp_max_assoc_sta <= 0)) {
|
||||
wil_info(wil,
|
||||
"Requested connection limit %u, valid values are 1 - %d. Setting to %d\n",
|
||||
max_assoc_sta, WIL6210_MAX_CID, WIL6210_MAX_CID);
|
||||
cmd.pcp_max_assoc_sta = WIL6210_MAX_CID;
|
||||
wil_err(wil, "unexpected max_assoc_sta %d\n",
|
||||
cmd.pcp_max_assoc_sta);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (disable_ap_sme &&
|
||||
|
@ -2516,7 +2549,7 @@ int wmi_rx_chain_add(struct wil6210_priv *wil, struct wil_ring *vring)
|
|||
if (ch)
|
||||
cmd.sniffer_cfg.channel = ch->hw_value - 1;
|
||||
cmd.sniffer_cfg.phy_info_mode =
|
||||
cpu_to_le32(ndev->type == ARPHRD_IEEE80211_RADIOTAP);
|
||||
cpu_to_le32(WMI_SNIFFER_PHY_INFO_DISABLED);
|
||||
cmd.sniffer_cfg.phy_support =
|
||||
cpu_to_le32((wil->monitor_flags & MONITOR_FLAG_CONTROL)
|
||||
? WMI_SNIFFER_CP : WMI_SNIFFER_BOTH_PHYS);
|
||||
|
@ -2651,15 +2684,22 @@ int wmi_delba_tx(struct wil6210_priv *wil, u8 mid, u8 ringid, u16 reason)
|
|||
return wmi_send(wil, WMI_RING_BA_DIS_CMDID, mid, &cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
int wmi_delba_rx(struct wil6210_priv *wil, u8 mid, u8 cidxtid, u16 reason)
|
||||
int wmi_delba_rx(struct wil6210_priv *wil, u8 mid, u8 cid, u8 tid, u16 reason)
|
||||
{
|
||||
struct wmi_rcp_delba_cmd cmd = {
|
||||
.cidxtid = cidxtid,
|
||||
.reason = cpu_to_le16(reason),
|
||||
};
|
||||
|
||||
wil_dbg_wmi(wil, "delba_rx: (CID %d TID %d reason %d)\n", cidxtid & 0xf,
|
||||
(cidxtid >> 4) & 0xf, reason);
|
||||
if (cid >= WIL6210_RX_DESC_MAX_CID) {
|
||||
cmd.cidxtid = CIDXTID_EXTENDED_CID_TID;
|
||||
cmd.cid = cid;
|
||||
cmd.tid = tid;
|
||||
} else {
|
||||
cmd.cidxtid = mk_cidxtid(cid, tid);
|
||||
}
|
||||
|
||||
wil_dbg_wmi(wil, "delba_rx: (CID %d TID %d reason %d)\n", cid,
|
||||
tid, reason);
|
||||
|
||||
return wmi_send(wil, WMI_RCP_DELBA_CMDID, mid, &cmd, sizeof(cmd));
|
||||
}
|
||||
|
@ -2670,7 +2710,6 @@ int wmi_addba_rx_resp(struct wil6210_priv *wil,
|
|||
{
|
||||
int rc;
|
||||
struct wmi_rcp_addba_resp_cmd cmd = {
|
||||
.cidxtid = mk_cidxtid(cid, tid),
|
||||
.dialog_token = token,
|
||||
.status_code = cpu_to_le16(status),
|
||||
/* bit 0: A-MSDU supported
|
||||
|
@ -2689,6 +2728,14 @@ int wmi_addba_rx_resp(struct wil6210_priv *wil,
|
|||
.evt = {.status = cpu_to_le16(WMI_FW_STATUS_FAILURE)},
|
||||
};
|
||||
|
||||
if (cid >= WIL6210_RX_DESC_MAX_CID) {
|
||||
cmd.cidxtid = CIDXTID_EXTENDED_CID_TID;
|
||||
cmd.cid = cid;
|
||||
cmd.tid = tid;
|
||||
} else {
|
||||
cmd.cidxtid = mk_cidxtid(cid, tid);
|
||||
}
|
||||
|
||||
wil_dbg_wmi(wil,
|
||||
"ADDBA response for MID %d CID %d TID %d size %d timeout %d status %d AMSDU%s\n",
|
||||
mid, cid, tid, agg_wsize,
|
||||
|
|
Загрузка…
Ссылка в новой задаче