Merge ath-next from git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
ath.git patches for v5.18. Major changes: ath11k * add LDPC FEC type in 802.11 radiotap header * enable RX PPDU stats in monitor co-exist mode wcn36xx * implement survey reporting
This commit is contained in:
commit
3898da3ba4
@ -75,6 +75,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.board_size = QCA988X_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA988X_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
.rx_desc_ops = &qca988x_rx_desc_ops,
|
||||
.hw_ops = &qca988x_ops,
|
||||
.decap_align_bytes = 4,
|
||||
.spectral_bin_discard = 0,
|
||||
@ -111,6 +112,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.board_size = QCA988X_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA988X_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
.rx_desc_ops = &qca988x_rx_desc_ops,
|
||||
.hw_ops = &qca988x_ops,
|
||||
.decap_align_bytes = 4,
|
||||
.spectral_bin_discard = 0,
|
||||
@ -148,6 +150,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.board_size = QCA9887_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA9887_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
.rx_desc_ops = &qca988x_rx_desc_ops,
|
||||
.hw_ops = &qca988x_ops,
|
||||
.decap_align_bytes = 4,
|
||||
.spectral_bin_discard = 0,
|
||||
@ -184,6 +187,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.board_size = QCA6174_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA6174_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
.rx_desc_ops = &qca988x_rx_desc_ops,
|
||||
.hw_ops = &qca6174_sdio_ops,
|
||||
.hw_clk = qca6174_clk,
|
||||
.target_cpu_freq = 176000000,
|
||||
@ -216,6 +220,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.board_size = QCA6174_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA6174_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
.rx_desc_ops = &qca988x_rx_desc_ops,
|
||||
.hw_ops = &qca988x_ops,
|
||||
.decap_align_bytes = 4,
|
||||
.spectral_bin_discard = 0,
|
||||
@ -252,6 +257,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.board_size = QCA6174_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA6174_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
.rx_desc_ops = &qca988x_rx_desc_ops,
|
||||
.hw_ops = &qca988x_ops,
|
||||
.decap_align_bytes = 4,
|
||||
.spectral_bin_discard = 0,
|
||||
@ -288,6 +294,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.board_size = QCA6174_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA6174_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
.rx_desc_ops = &qca988x_rx_desc_ops,
|
||||
.hw_ops = &qca988x_ops,
|
||||
.decap_align_bytes = 4,
|
||||
.spectral_bin_discard = 0,
|
||||
@ -325,6 +332,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.board_size = QCA6174_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA6174_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
.rx_desc_ops = &qca988x_rx_desc_ops,
|
||||
.hw_ops = &qca6174_ops,
|
||||
.hw_clk = qca6174_clk,
|
||||
.target_cpu_freq = 176000000,
|
||||
@ -370,6 +378,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
.sw_decrypt_mcast_mgmt = true,
|
||||
.rx_desc_ops = &qca99x0_rx_desc_ops,
|
||||
.hw_ops = &qca99x0_ops,
|
||||
.decap_align_bytes = 1,
|
||||
.spectral_bin_discard = 4,
|
||||
@ -415,6 +424,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.ext_board_size = QCA99X0_EXT_BOARD_DATA_SZ,
|
||||
},
|
||||
.sw_decrypt_mcast_mgmt = true,
|
||||
.rx_desc_ops = &qca99x0_rx_desc_ops,
|
||||
.hw_ops = &qca99x0_ops,
|
||||
.decap_align_bytes = 1,
|
||||
.spectral_bin_discard = 12,
|
||||
@ -461,6 +471,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
.sw_decrypt_mcast_mgmt = true,
|
||||
.rx_desc_ops = &qca99x0_rx_desc_ops,
|
||||
.hw_ops = &qca99x0_ops,
|
||||
.decap_align_bytes = 1,
|
||||
.spectral_bin_discard = 12,
|
||||
@ -501,6 +512,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.board_size = QCA9377_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA9377_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
.rx_desc_ops = &qca988x_rx_desc_ops,
|
||||
.hw_ops = &qca988x_ops,
|
||||
.decap_align_bytes = 4,
|
||||
.spectral_bin_discard = 0,
|
||||
@ -537,6 +549,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.board_size = QCA9377_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA9377_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
.rx_desc_ops = &qca988x_rx_desc_ops,
|
||||
.hw_ops = &qca6174_ops,
|
||||
.hw_clk = qca6174_clk,
|
||||
.target_cpu_freq = 176000000,
|
||||
@ -575,6 +588,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.board_size = QCA9377_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA9377_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
.rx_desc_ops = &qca988x_rx_desc_ops,
|
||||
.hw_ops = &qca6174_ops,
|
||||
.hw_clk = qca6174_clk,
|
||||
.target_cpu_freq = 176000000,
|
||||
@ -611,6 +625,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.board_ext_size = QCA4019_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
.sw_decrypt_mcast_mgmt = true,
|
||||
.rx_desc_ops = &qca99x0_rx_desc_ops,
|
||||
.hw_ops = &qca99x0_ops,
|
||||
.decap_align_bytes = 1,
|
||||
.spectral_bin_discard = 4,
|
||||
@ -643,6 +658,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.dir = WCN3990_HW_1_0_FW_DIR,
|
||||
},
|
||||
.sw_decrypt_mcast_mgmt = true,
|
||||
.rx_desc_ops = &wcn3990_rx_desc_ops,
|
||||
.hw_ops = &wcn3990_ops,
|
||||
.decap_align_bytes = 1,
|
||||
.num_peers = TARGET_HL_TLV_NUM_PEERS,
|
||||
|
@ -131,6 +131,159 @@ static const enum htt_t2h_msg_type htt_10_4_t2h_msg_types[] = {
|
||||
HTT_T2H_MSG_TYPE_PEER_STATS,
|
||||
};
|
||||
|
||||
const struct ath10k_htt_rx_desc_ops qca988x_rx_desc_ops = {
|
||||
.rx_desc_size = sizeof(struct htt_rx_desc_v1),
|
||||
.rx_desc_msdu_payload_offset = offsetof(struct htt_rx_desc_v1, msdu_payload)
|
||||
};
|
||||
|
||||
static int ath10k_qca99x0_rx_desc_get_l3_pad_bytes(struct htt_rx_desc *rxd)
|
||||
{
|
||||
struct htt_rx_desc_v1 *rx_desc = container_of(rxd,
|
||||
struct htt_rx_desc_v1,
|
||||
base);
|
||||
|
||||
return MS(__le32_to_cpu(rx_desc->msdu_end.qca99x0.info1),
|
||||
RX_MSDU_END_INFO1_L3_HDR_PAD);
|
||||
}
|
||||
|
||||
static bool ath10k_qca99x0_rx_desc_msdu_limit_error(struct htt_rx_desc *rxd)
|
||||
{
|
||||
struct htt_rx_desc_v1 *rx_desc = container_of(rxd,
|
||||
struct htt_rx_desc_v1,
|
||||
base);
|
||||
|
||||
return !!(rx_desc->msdu_end.common.info0 &
|
||||
__cpu_to_le32(RX_MSDU_END_INFO0_MSDU_LIMIT_ERR));
|
||||
}
|
||||
|
||||
const struct ath10k_htt_rx_desc_ops qca99x0_rx_desc_ops = {
|
||||
.rx_desc_size = sizeof(struct htt_rx_desc_v1),
|
||||
.rx_desc_msdu_payload_offset = offsetof(struct htt_rx_desc_v1, msdu_payload),
|
||||
|
||||
.rx_desc_get_l3_pad_bytes = ath10k_qca99x0_rx_desc_get_l3_pad_bytes,
|
||||
.rx_desc_get_msdu_limit_error = ath10k_qca99x0_rx_desc_msdu_limit_error,
|
||||
};
|
||||
|
||||
static void ath10k_rx_desc_wcn3990_get_offsets(struct htt_rx_ring_rx_desc_offsets *off)
|
||||
{
|
||||
#define desc_offset(x) (offsetof(struct htt_rx_desc_v2, x) / 4)
|
||||
off->mac80211_hdr_offset = __cpu_to_le16(desc_offset(rx_hdr_status));
|
||||
off->msdu_payload_offset = __cpu_to_le16(desc_offset(msdu_payload));
|
||||
off->ppdu_start_offset = __cpu_to_le16(desc_offset(ppdu_start));
|
||||
off->ppdu_end_offset = __cpu_to_le16(desc_offset(ppdu_end));
|
||||
off->mpdu_start_offset = __cpu_to_le16(desc_offset(mpdu_start));
|
||||
off->mpdu_end_offset = __cpu_to_le16(desc_offset(mpdu_end));
|
||||
off->msdu_start_offset = __cpu_to_le16(desc_offset(msdu_start));
|
||||
off->msdu_end_offset = __cpu_to_le16(desc_offset(msdu_end));
|
||||
off->rx_attention_offset = __cpu_to_le16(desc_offset(attention));
|
||||
off->frag_info_offset = __cpu_to_le16(desc_offset(frag_info));
|
||||
#undef desc_offset
|
||||
}
|
||||
|
||||
static struct htt_rx_desc *
|
||||
ath10k_rx_desc_wcn3990_from_raw_buffer(void *buff)
|
||||
{
|
||||
return &((struct htt_rx_desc_v2 *)buff)->base;
|
||||
}
|
||||
|
||||
static struct rx_attention *
|
||||
ath10k_rx_desc_wcn3990_get_attention(struct htt_rx_desc *rxd)
|
||||
{
|
||||
struct htt_rx_desc_v2 *rx_desc = container_of(rxd, struct htt_rx_desc_v2, base);
|
||||
|
||||
return &rx_desc->attention;
|
||||
}
|
||||
|
||||
static struct rx_frag_info_common *
|
||||
ath10k_rx_desc_wcn3990_get_frag_info(struct htt_rx_desc *rxd)
|
||||
{
|
||||
struct htt_rx_desc_v2 *rx_desc = container_of(rxd, struct htt_rx_desc_v2, base);
|
||||
|
||||
return &rx_desc->frag_info.common;
|
||||
}
|
||||
|
||||
static struct rx_mpdu_start *
|
||||
ath10k_rx_desc_wcn3990_get_mpdu_start(struct htt_rx_desc *rxd)
|
||||
{
|
||||
struct htt_rx_desc_v2 *rx_desc = container_of(rxd, struct htt_rx_desc_v2, base);
|
||||
|
||||
return &rx_desc->mpdu_start;
|
||||
}
|
||||
|
||||
static struct rx_mpdu_end *
|
||||
ath10k_rx_desc_wcn3990_get_mpdu_end(struct htt_rx_desc *rxd)
|
||||
{
|
||||
struct htt_rx_desc_v2 *rx_desc = container_of(rxd, struct htt_rx_desc_v2, base);
|
||||
|
||||
return &rx_desc->mpdu_end;
|
||||
}
|
||||
|
||||
static struct rx_msdu_start_common *
|
||||
ath10k_rx_desc_wcn3990_get_msdu_start(struct htt_rx_desc *rxd)
|
||||
{
|
||||
struct htt_rx_desc_v2 *rx_desc = container_of(rxd, struct htt_rx_desc_v2, base);
|
||||
|
||||
return &rx_desc->msdu_start.common;
|
||||
}
|
||||
|
||||
static struct rx_msdu_end_common *
|
||||
ath10k_rx_desc_wcn3990_get_msdu_end(struct htt_rx_desc *rxd)
|
||||
{
|
||||
struct htt_rx_desc_v2 *rx_desc = container_of(rxd, struct htt_rx_desc_v2, base);
|
||||
|
||||
return &rx_desc->msdu_end.common;
|
||||
}
|
||||
|
||||
static struct rx_ppdu_start *
|
||||
ath10k_rx_desc_wcn3990_get_ppdu_start(struct htt_rx_desc *rxd)
|
||||
{
|
||||
struct htt_rx_desc_v2 *rx_desc = container_of(rxd, struct htt_rx_desc_v2, base);
|
||||
|
||||
return &rx_desc->ppdu_start;
|
||||
}
|
||||
|
||||
static struct rx_ppdu_end_common *
|
||||
ath10k_rx_desc_wcn3990_get_ppdu_end(struct htt_rx_desc *rxd)
|
||||
{
|
||||
struct htt_rx_desc_v2 *rx_desc = container_of(rxd, struct htt_rx_desc_v2, base);
|
||||
|
||||
return &rx_desc->ppdu_end.common;
|
||||
}
|
||||
|
||||
static u8 *
|
||||
ath10k_rx_desc_wcn3990_get_rx_hdr_status(struct htt_rx_desc *rxd)
|
||||
{
|
||||
struct htt_rx_desc_v2 *rx_desc = container_of(rxd, struct htt_rx_desc_v2, base);
|
||||
|
||||
return rx_desc->rx_hdr_status;
|
||||
}
|
||||
|
||||
static u8 *
|
||||
ath10k_rx_desc_wcn3990_get_msdu_payload(struct htt_rx_desc *rxd)
|
||||
{
|
||||
struct htt_rx_desc_v2 *rx_desc = container_of(rxd, struct htt_rx_desc_v2, base);
|
||||
|
||||
return rx_desc->msdu_payload;
|
||||
}
|
||||
|
||||
const struct ath10k_htt_rx_desc_ops wcn3990_rx_desc_ops = {
|
||||
.rx_desc_size = sizeof(struct htt_rx_desc_v2),
|
||||
.rx_desc_msdu_payload_offset = offsetof(struct htt_rx_desc_v2, msdu_payload),
|
||||
|
||||
.rx_desc_from_raw_buffer = ath10k_rx_desc_wcn3990_from_raw_buffer,
|
||||
.rx_desc_get_offsets = ath10k_rx_desc_wcn3990_get_offsets,
|
||||
.rx_desc_get_attention = ath10k_rx_desc_wcn3990_get_attention,
|
||||
.rx_desc_get_frag_info = ath10k_rx_desc_wcn3990_get_frag_info,
|
||||
.rx_desc_get_mpdu_start = ath10k_rx_desc_wcn3990_get_mpdu_start,
|
||||
.rx_desc_get_mpdu_end = ath10k_rx_desc_wcn3990_get_mpdu_end,
|
||||
.rx_desc_get_msdu_start = ath10k_rx_desc_wcn3990_get_msdu_start,
|
||||
.rx_desc_get_msdu_end = ath10k_rx_desc_wcn3990_get_msdu_end,
|
||||
.rx_desc_get_ppdu_start = ath10k_rx_desc_wcn3990_get_ppdu_start,
|
||||
.rx_desc_get_ppdu_end = ath10k_rx_desc_wcn3990_get_ppdu_end,
|
||||
.rx_desc_get_rx_hdr_status = ath10k_rx_desc_wcn3990_get_rx_hdr_status,
|
||||
.rx_desc_get_msdu_payload = ath10k_rx_desc_wcn3990_get_msdu_payload,
|
||||
};
|
||||
|
||||
int ath10k_htt_connect(struct ath10k_htt *htt)
|
||||
{
|
||||
struct ath10k_htc_svc_conn_req conn_req;
|
||||
|
@ -240,14 +240,7 @@ enum htt_rx_ring_flags {
|
||||
#define HTT_RX_RING_FILL_LEVEL (((HTT_RX_RING_SIZE) / 2) - 1)
|
||||
#define HTT_RX_RING_FILL_LEVEL_DUAL_MAC (HTT_RX_RING_SIZE - 1)
|
||||
|
||||
struct htt_rx_ring_setup_ring32 {
|
||||
__le32 fw_idx_shadow_reg_paddr;
|
||||
__le32 rx_ring_base_paddr;
|
||||
__le16 rx_ring_len; /* in 4-byte words */
|
||||
__le16 rx_ring_bufsize; /* rx skb size - in bytes */
|
||||
__le16 flags; /* %HTT_RX_RING_FLAGS_ */
|
||||
__le16 fw_idx_init_val;
|
||||
|
||||
struct htt_rx_ring_rx_desc_offsets {
|
||||
/* the following offsets are in 4-byte units */
|
||||
__le16 mac80211_hdr_offset;
|
||||
__le16 msdu_payload_offset;
|
||||
@ -261,6 +254,17 @@ struct htt_rx_ring_setup_ring32 {
|
||||
__le16 frag_info_offset;
|
||||
} __packed;
|
||||
|
||||
struct htt_rx_ring_setup_ring32 {
|
||||
__le32 fw_idx_shadow_reg_paddr;
|
||||
__le32 rx_ring_base_paddr;
|
||||
__le16 rx_ring_len; /* in 4-byte words */
|
||||
__le16 rx_ring_bufsize; /* rx skb size - in bytes */
|
||||
__le16 flags; /* %HTT_RX_RING_FLAGS_ */
|
||||
__le16 fw_idx_init_val;
|
||||
|
||||
struct htt_rx_ring_rx_desc_offsets offsets;
|
||||
} __packed;
|
||||
|
||||
struct htt_rx_ring_setup_ring64 {
|
||||
__le64 fw_idx_shadow_reg_paddr;
|
||||
__le64 rx_ring_base_paddr;
|
||||
@ -269,17 +273,7 @@ struct htt_rx_ring_setup_ring64 {
|
||||
__le16 flags; /* %HTT_RX_RING_FLAGS_ */
|
||||
__le16 fw_idx_init_val;
|
||||
|
||||
/* the following offsets are in 4-byte units */
|
||||
__le16 mac80211_hdr_offset;
|
||||
__le16 msdu_payload_offset;
|
||||
__le16 ppdu_start_offset;
|
||||
__le16 ppdu_end_offset;
|
||||
__le16 mpdu_start_offset;
|
||||
__le16 mpdu_end_offset;
|
||||
__le16 msdu_start_offset;
|
||||
__le16 msdu_end_offset;
|
||||
__le16 rx_attention_offset;
|
||||
__le16 frag_info_offset;
|
||||
struct htt_rx_ring_rx_desc_offsets offsets;
|
||||
} __packed;
|
||||
|
||||
struct htt_rx_ring_setup_hdr {
|
||||
@ -2075,12 +2069,22 @@ static inline bool ath10k_htt_rx_proc_rx_frag_ind(struct ath10k_htt *htt,
|
||||
return htt->rx_ops->htt_rx_proc_rx_frag_ind(htt, rx, skb);
|
||||
}
|
||||
|
||||
/* the driver strongly assumes that the rx header status be 64 bytes long,
|
||||
* so all possible rx_desc structures must respect this assumption.
|
||||
*/
|
||||
#define RX_HTT_HDR_STATUS_LEN 64
|
||||
|
||||
/* This structure layout is programmed via rx ring setup
|
||||
/* The rx descriptor structure layout is programmed via rx ring setup
|
||||
* so that FW knows how to transfer the rx descriptor to the host.
|
||||
* Buffers like this are placed on the rx ring.
|
||||
* Unfortunately, though, QCA6174's firmware doesn't currently behave correctly
|
||||
* when modifying the structure layout of the rx descriptor beyond what it expects
|
||||
* (even if it correctly programmed during the rx ring setup).
|
||||
* Therefore we must keep two different memory layouts, abstract the rx descriptor
|
||||
* representation and use ath10k_rx_desc_ops
|
||||
* for correctly accessing rx descriptor data.
|
||||
*/
|
||||
|
||||
/* base struct used for abstracting the rx descritor representation */
|
||||
struct htt_rx_desc {
|
||||
union {
|
||||
/* This field is filled on the host using the msdu buffer
|
||||
@ -2089,6 +2093,13 @@ struct htt_rx_desc {
|
||||
struct fw_rx_desc_base fw_desc;
|
||||
u32 pad;
|
||||
} __packed;
|
||||
} __packed;
|
||||
|
||||
/* rx descriptor for wcn3990 and possibly extensible for newer cards
|
||||
* Buffers like this are placed on the rx ring.
|
||||
*/
|
||||
struct htt_rx_desc_v2 {
|
||||
struct htt_rx_desc base;
|
||||
struct {
|
||||
struct rx_attention attention;
|
||||
struct rx_frag_info frag_info;
|
||||
@ -2103,6 +2114,240 @@ struct htt_rx_desc {
|
||||
u8 msdu_payload[];
|
||||
};
|
||||
|
||||
/* QCA6174, QCA988x, QCA99x0 dedicated rx descriptor to make sure their firmware
|
||||
* works correctly. We keep a single rx descriptor for all these three
|
||||
* families of cards because from tests it seems to be the most stable solution,
|
||||
* e.g. having a rx descriptor only for QCA6174 seldom caused firmware crashes
|
||||
* during some tests.
|
||||
* Buffers like this are placed on the rx ring.
|
||||
*/
|
||||
struct htt_rx_desc_v1 {
|
||||
struct htt_rx_desc base;
|
||||
struct {
|
||||
struct rx_attention attention;
|
||||
struct rx_frag_info_v1 frag_info;
|
||||
struct rx_mpdu_start mpdu_start;
|
||||
struct rx_msdu_start_v1 msdu_start;
|
||||
struct rx_msdu_end_v1 msdu_end;
|
||||
struct rx_mpdu_end mpdu_end;
|
||||
struct rx_ppdu_start ppdu_start;
|
||||
struct rx_ppdu_end_v1 ppdu_end;
|
||||
} __packed;
|
||||
u8 rx_hdr_status[RX_HTT_HDR_STATUS_LEN];
|
||||
u8 msdu_payload[];
|
||||
};
|
||||
|
||||
/* rx_desc abstraction */
|
||||
struct ath10k_htt_rx_desc_ops {
|
||||
/* These fields are mandatory, they must be specified in any instance */
|
||||
|
||||
/* sizeof() of the rx_desc structure used by this hw */
|
||||
size_t rx_desc_size;
|
||||
|
||||
/* offset of msdu_payload inside the rx_desc structure used by this hw */
|
||||
size_t rx_desc_msdu_payload_offset;
|
||||
|
||||
/* These fields are options.
|
||||
* When a field is not provided the default implementation gets used
|
||||
* (see the ath10k_rx_desc_* operations below for more info about the defaults)
|
||||
*/
|
||||
bool (*rx_desc_get_msdu_limit_error)(struct htt_rx_desc *rxd);
|
||||
int (*rx_desc_get_l3_pad_bytes)(struct htt_rx_desc *rxd);
|
||||
|
||||
/* Safely cast from a void* buffer containing an rx descriptor
|
||||
* to the proper rx_desc structure
|
||||
*/
|
||||
struct htt_rx_desc *(*rx_desc_from_raw_buffer)(void *buff);
|
||||
|
||||
void (*rx_desc_get_offsets)(struct htt_rx_ring_rx_desc_offsets *offs);
|
||||
struct rx_attention *(*rx_desc_get_attention)(struct htt_rx_desc *rxd);
|
||||
struct rx_frag_info_common *(*rx_desc_get_frag_info)(struct htt_rx_desc *rxd);
|
||||
struct rx_mpdu_start *(*rx_desc_get_mpdu_start)(struct htt_rx_desc *rxd);
|
||||
struct rx_mpdu_end *(*rx_desc_get_mpdu_end)(struct htt_rx_desc *rxd);
|
||||
struct rx_msdu_start_common *(*rx_desc_get_msdu_start)(struct htt_rx_desc *rxd);
|
||||
struct rx_msdu_end_common *(*rx_desc_get_msdu_end)(struct htt_rx_desc *rxd);
|
||||
struct rx_ppdu_start *(*rx_desc_get_ppdu_start)(struct htt_rx_desc *rxd);
|
||||
struct rx_ppdu_end_common *(*rx_desc_get_ppdu_end)(struct htt_rx_desc *rxd);
|
||||
u8 *(*rx_desc_get_rx_hdr_status)(struct htt_rx_desc *rxd);
|
||||
u8 *(*rx_desc_get_msdu_payload)(struct htt_rx_desc *rxd);
|
||||
};
|
||||
|
||||
extern const struct ath10k_htt_rx_desc_ops qca988x_rx_desc_ops;
|
||||
extern const struct ath10k_htt_rx_desc_ops qca99x0_rx_desc_ops;
|
||||
extern const struct ath10k_htt_rx_desc_ops wcn3990_rx_desc_ops;
|
||||
|
||||
static inline int
|
||||
ath10k_htt_rx_desc_get_l3_pad_bytes(struct ath10k_hw_params *hw, struct htt_rx_desc *rxd)
|
||||
{
|
||||
if (hw->rx_desc_ops->rx_desc_get_l3_pad_bytes)
|
||||
return hw->rx_desc_ops->rx_desc_get_l3_pad_bytes(rxd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
ath10k_htt_rx_desc_msdu_limit_error(struct ath10k_hw_params *hw, struct htt_rx_desc *rxd)
|
||||
{
|
||||
if (hw->rx_desc_ops->rx_desc_get_msdu_limit_error)
|
||||
return hw->rx_desc_ops->rx_desc_get_msdu_limit_error(rxd);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* The default implementation of all these getters is using the old rx_desc,
|
||||
* so that it is easier to define the ath10k_htt_rx_desc_ops instances.
|
||||
* But probably, if new wireless cards must be supported, it would be better
|
||||
* to switch the default implementation to the new rx_desc, since this would
|
||||
* make the extension easier .
|
||||
*/
|
||||
static inline struct htt_rx_desc *
|
||||
ath10k_htt_rx_desc_from_raw_buffer(struct ath10k_hw_params *hw, void *buff)
|
||||
{
|
||||
if (hw->rx_desc_ops->rx_desc_from_raw_buffer)
|
||||
return hw->rx_desc_ops->rx_desc_from_raw_buffer(buff);
|
||||
return &((struct htt_rx_desc_v1 *)buff)->base;
|
||||
}
|
||||
|
||||
static inline void
|
||||
ath10k_htt_rx_desc_get_offsets(struct ath10k_hw_params *hw,
|
||||
struct htt_rx_ring_rx_desc_offsets *off)
|
||||
{
|
||||
if (hw->rx_desc_ops->rx_desc_get_offsets) {
|
||||
hw->rx_desc_ops->rx_desc_get_offsets(off);
|
||||
} else {
|
||||
#define desc_offset(x) (offsetof(struct htt_rx_desc_v1, x) / 4)
|
||||
off->mac80211_hdr_offset = __cpu_to_le16(desc_offset(rx_hdr_status));
|
||||
off->msdu_payload_offset = __cpu_to_le16(desc_offset(msdu_payload));
|
||||
off->ppdu_start_offset = __cpu_to_le16(desc_offset(ppdu_start));
|
||||
off->ppdu_end_offset = __cpu_to_le16(desc_offset(ppdu_end));
|
||||
off->mpdu_start_offset = __cpu_to_le16(desc_offset(mpdu_start));
|
||||
off->mpdu_end_offset = __cpu_to_le16(desc_offset(mpdu_end));
|
||||
off->msdu_start_offset = __cpu_to_le16(desc_offset(msdu_start));
|
||||
off->msdu_end_offset = __cpu_to_le16(desc_offset(msdu_end));
|
||||
off->rx_attention_offset = __cpu_to_le16(desc_offset(attention));
|
||||
off->frag_info_offset = __cpu_to_le16(desc_offset(frag_info));
|
||||
#undef desc_offset
|
||||
}
|
||||
}
|
||||
|
||||
static inline struct rx_attention *
|
||||
ath10k_htt_rx_desc_get_attention(struct ath10k_hw_params *hw, struct htt_rx_desc *rxd)
|
||||
{
|
||||
struct htt_rx_desc_v1 *rx_desc;
|
||||
|
||||
if (hw->rx_desc_ops->rx_desc_get_attention)
|
||||
return hw->rx_desc_ops->rx_desc_get_attention(rxd);
|
||||
|
||||
rx_desc = container_of(rxd, struct htt_rx_desc_v1, base);
|
||||
return &rx_desc->attention;
|
||||
}
|
||||
|
||||
static inline struct rx_frag_info_common *
|
||||
ath10k_htt_rx_desc_get_frag_info(struct ath10k_hw_params *hw, struct htt_rx_desc *rxd)
|
||||
{
|
||||
struct htt_rx_desc_v1 *rx_desc;
|
||||
|
||||
if (hw->rx_desc_ops->rx_desc_get_frag_info)
|
||||
return hw->rx_desc_ops->rx_desc_get_frag_info(rxd);
|
||||
|
||||
rx_desc = container_of(rxd, struct htt_rx_desc_v1, base);
|
||||
return &rx_desc->frag_info.common;
|
||||
}
|
||||
|
||||
static inline struct rx_mpdu_start *
|
||||
ath10k_htt_rx_desc_get_mpdu_start(struct ath10k_hw_params *hw, struct htt_rx_desc *rxd)
|
||||
{
|
||||
struct htt_rx_desc_v1 *rx_desc;
|
||||
|
||||
if (hw->rx_desc_ops->rx_desc_get_mpdu_start)
|
||||
return hw->rx_desc_ops->rx_desc_get_mpdu_start(rxd);
|
||||
|
||||
rx_desc = container_of(rxd, struct htt_rx_desc_v1, base);
|
||||
return &rx_desc->mpdu_start;
|
||||
}
|
||||
|
||||
static inline struct rx_mpdu_end *
|
||||
ath10k_htt_rx_desc_get_mpdu_end(struct ath10k_hw_params *hw, struct htt_rx_desc *rxd)
|
||||
{
|
||||
struct htt_rx_desc_v1 *rx_desc;
|
||||
|
||||
if (hw->rx_desc_ops->rx_desc_get_mpdu_end)
|
||||
return hw->rx_desc_ops->rx_desc_get_mpdu_end(rxd);
|
||||
|
||||
rx_desc = container_of(rxd, struct htt_rx_desc_v1, base);
|
||||
return &rx_desc->mpdu_end;
|
||||
}
|
||||
|
||||
static inline struct rx_msdu_start_common *
|
||||
ath10k_htt_rx_desc_get_msdu_start(struct ath10k_hw_params *hw, struct htt_rx_desc *rxd)
|
||||
{
|
||||
struct htt_rx_desc_v1 *rx_desc;
|
||||
|
||||
if (hw->rx_desc_ops->rx_desc_get_msdu_start)
|
||||
return hw->rx_desc_ops->rx_desc_get_msdu_start(rxd);
|
||||
|
||||
rx_desc = container_of(rxd, struct htt_rx_desc_v1, base);
|
||||
return &rx_desc->msdu_start.common;
|
||||
}
|
||||
|
||||
static inline struct rx_msdu_end_common *
|
||||
ath10k_htt_rx_desc_get_msdu_end(struct ath10k_hw_params *hw, struct htt_rx_desc *rxd)
|
||||
{
|
||||
struct htt_rx_desc_v1 *rx_desc;
|
||||
|
||||
if (hw->rx_desc_ops->rx_desc_get_msdu_end)
|
||||
return hw->rx_desc_ops->rx_desc_get_msdu_end(rxd);
|
||||
|
||||
rx_desc = container_of(rxd, struct htt_rx_desc_v1, base);
|
||||
return &rx_desc->msdu_end.common;
|
||||
}
|
||||
|
||||
static inline struct rx_ppdu_start *
|
||||
ath10k_htt_rx_desc_get_ppdu_start(struct ath10k_hw_params *hw, struct htt_rx_desc *rxd)
|
||||
{
|
||||
struct htt_rx_desc_v1 *rx_desc;
|
||||
|
||||
if (hw->rx_desc_ops->rx_desc_get_ppdu_start)
|
||||
return hw->rx_desc_ops->rx_desc_get_ppdu_start(rxd);
|
||||
|
||||
rx_desc = container_of(rxd, struct htt_rx_desc_v1, base);
|
||||
return &rx_desc->ppdu_start;
|
||||
}
|
||||
|
||||
static inline struct rx_ppdu_end_common *
|
||||
ath10k_htt_rx_desc_get_ppdu_end(struct ath10k_hw_params *hw, struct htt_rx_desc *rxd)
|
||||
{
|
||||
struct htt_rx_desc_v1 *rx_desc;
|
||||
|
||||
if (hw->rx_desc_ops->rx_desc_get_ppdu_end)
|
||||
return hw->rx_desc_ops->rx_desc_get_ppdu_end(rxd);
|
||||
|
||||
rx_desc = container_of(rxd, struct htt_rx_desc_v1, base);
|
||||
return &rx_desc->ppdu_end.common;
|
||||
}
|
||||
|
||||
static inline u8 *
|
||||
ath10k_htt_rx_desc_get_rx_hdr_status(struct ath10k_hw_params *hw, struct htt_rx_desc *rxd)
|
||||
{
|
||||
struct htt_rx_desc_v1 *rx_desc;
|
||||
|
||||
if (hw->rx_desc_ops->rx_desc_get_rx_hdr_status)
|
||||
return hw->rx_desc_ops->rx_desc_get_rx_hdr_status(rxd);
|
||||
|
||||
rx_desc = container_of(rxd, struct htt_rx_desc_v1, base);
|
||||
return rx_desc->rx_hdr_status;
|
||||
}
|
||||
|
||||
static inline u8 *
|
||||
ath10k_htt_rx_desc_get_msdu_payload(struct ath10k_hw_params *hw, struct htt_rx_desc *rxd)
|
||||
{
|
||||
struct htt_rx_desc_v1 *rx_desc;
|
||||
|
||||
if (hw->rx_desc_ops->rx_desc_get_msdu_payload)
|
||||
return hw->rx_desc_ops->rx_desc_get_msdu_payload(rxd);
|
||||
|
||||
rx_desc = container_of(rxd, struct htt_rx_desc_v1, base);
|
||||
return rx_desc->msdu_payload;
|
||||
}
|
||||
|
||||
#define HTT_RX_DESC_HL_INFO_SEQ_NUM_MASK 0x00000fff
|
||||
#define HTT_RX_DESC_HL_INFO_SEQ_NUM_LSB 0
|
||||
#define HTT_RX_DESC_HL_INFO_ENCRYPTED_MASK 0x00001000
|
||||
@ -2136,7 +2381,14 @@ struct htt_rx_chan_info {
|
||||
* rounded up to a cache line size.
|
||||
*/
|
||||
#define HTT_RX_BUF_SIZE 2048
|
||||
#define HTT_RX_MSDU_SIZE (HTT_RX_BUF_SIZE - (int)sizeof(struct htt_rx_desc))
|
||||
|
||||
/* The HTT_RX_MSDU_SIZE can't be statically computed anymore,
|
||||
* because it depends on the underlying device rx_desc representation
|
||||
*/
|
||||
static inline int ath10k_htt_rx_msdu_size(struct ath10k_hw_params *hw)
|
||||
{
|
||||
return HTT_RX_BUF_SIZE - (int)hw->rx_desc_ops->rx_desc_size;
|
||||
}
|
||||
|
||||
/* Refill a bunch of RX buffers for each refill round so that FW/HW can handle
|
||||
* aggregated traffic more nicely.
|
||||
|
@ -21,7 +21,10 @@
|
||||
|
||||
#define HTT_RX_RING_REFILL_RESCHED_MS 5
|
||||
|
||||
static int ath10k_htt_rx_get_csum_state(struct sk_buff *skb);
|
||||
/* shortcut to interpret a raw memory buffer as a rx descriptor */
|
||||
#define HTT_RX_BUF_TO_RX_DESC(hw, buf) ath10k_htt_rx_desc_from_raw_buffer(hw, buf)
|
||||
|
||||
static int ath10k_htt_rx_get_csum_state(struct ath10k_hw_params *hw, struct sk_buff *skb);
|
||||
|
||||
static struct sk_buff *
|
||||
ath10k_htt_rx_find_skb_paddr(struct ath10k *ar, u64 paddr)
|
||||
@ -128,6 +131,7 @@ static void *ath10k_htt_get_vaddr_ring_64(struct ath10k_htt *htt)
|
||||
|
||||
static int __ath10k_htt_rx_ring_fill_n(struct ath10k_htt *htt, int num)
|
||||
{
|
||||
struct ath10k_hw_params *hw = &htt->ar->hw_params;
|
||||
struct htt_rx_desc *rx_desc;
|
||||
struct ath10k_skb_rxcb *rxcb;
|
||||
struct sk_buff *skb;
|
||||
@ -163,8 +167,8 @@ static int __ath10k_htt_rx_ring_fill_n(struct ath10k_htt *htt, int num)
|
||||
skb->data);
|
||||
|
||||
/* Clear rx_desc attention word before posting to Rx ring */
|
||||
rx_desc = (struct htt_rx_desc *)skb->data;
|
||||
rx_desc->attention.flags = __cpu_to_le32(0);
|
||||
rx_desc = HTT_RX_BUF_TO_RX_DESC(hw, skb->data);
|
||||
ath10k_htt_rx_desc_get_attention(hw, rx_desc)->flags = __cpu_to_le32(0);
|
||||
|
||||
paddr = dma_map_single(htt->ar->dev, skb->data,
|
||||
skb->len + skb_tailroom(skb),
|
||||
@ -343,9 +347,14 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
|
||||
struct sk_buff_head *amsdu)
|
||||
{
|
||||
struct ath10k *ar = htt->ar;
|
||||
struct ath10k_hw_params *hw = &ar->hw_params;
|
||||
int msdu_len, msdu_chaining = 0;
|
||||
struct sk_buff *msdu;
|
||||
struct htt_rx_desc *rx_desc;
|
||||
struct rx_attention *rx_desc_attention;
|
||||
struct rx_frag_info_common *rx_desc_frag_info_common;
|
||||
struct rx_msdu_start_common *rx_desc_msdu_start_common;
|
||||
struct rx_msdu_end_common *rx_desc_msdu_end_common;
|
||||
|
||||
lockdep_assert_held(&htt->rx_ring.lock);
|
||||
|
||||
@ -360,13 +369,18 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
|
||||
|
||||
__skb_queue_tail(amsdu, msdu);
|
||||
|
||||
rx_desc = (struct htt_rx_desc *)msdu->data;
|
||||
rx_desc = HTT_RX_BUF_TO_RX_DESC(hw, msdu->data);
|
||||
rx_desc_attention = ath10k_htt_rx_desc_get_attention(hw, rx_desc);
|
||||
rx_desc_msdu_start_common = ath10k_htt_rx_desc_get_msdu_start(hw,
|
||||
rx_desc);
|
||||
rx_desc_msdu_end_common = ath10k_htt_rx_desc_get_msdu_end(hw, rx_desc);
|
||||
rx_desc_frag_info_common = ath10k_htt_rx_desc_get_frag_info(hw, rx_desc);
|
||||
|
||||
/* FIXME: we must report msdu payload since this is what caller
|
||||
* expects now
|
||||
*/
|
||||
skb_put(msdu, offsetof(struct htt_rx_desc, msdu_payload));
|
||||
skb_pull(msdu, offsetof(struct htt_rx_desc, msdu_payload));
|
||||
skb_put(msdu, hw->rx_desc_ops->rx_desc_msdu_payload_offset);
|
||||
skb_pull(msdu, hw->rx_desc_ops->rx_desc_msdu_payload_offset);
|
||||
|
||||
/*
|
||||
* Sanity check - confirm the HW is finished filling in the
|
||||
@ -376,24 +390,24 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
|
||||
* To prevent the case that we handle a stale Rx descriptor,
|
||||
* just assert for now until we have a way to recover.
|
||||
*/
|
||||
if (!(__le32_to_cpu(rx_desc->attention.flags)
|
||||
if (!(__le32_to_cpu(rx_desc_attention->flags)
|
||||
& RX_ATTENTION_FLAGS_MSDU_DONE)) {
|
||||
__skb_queue_purge(amsdu);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
msdu_len_invalid = !!(__le32_to_cpu(rx_desc->attention.flags)
|
||||
msdu_len_invalid = !!(__le32_to_cpu(rx_desc_attention->flags)
|
||||
& (RX_ATTENTION_FLAGS_MPDU_LENGTH_ERR |
|
||||
RX_ATTENTION_FLAGS_MSDU_LENGTH_ERR));
|
||||
msdu_len = MS(__le32_to_cpu(rx_desc->msdu_start.common.info0),
|
||||
msdu_len = MS(__le32_to_cpu(rx_desc_msdu_start_common->info0),
|
||||
RX_MSDU_START_INFO0_MSDU_LENGTH);
|
||||
msdu_chained = rx_desc->frag_info.ring2_more_count;
|
||||
msdu_chained = rx_desc_frag_info_common->ring2_more_count;
|
||||
|
||||
if (msdu_len_invalid)
|
||||
msdu_len = 0;
|
||||
|
||||
skb_trim(msdu, 0);
|
||||
skb_put(msdu, min(msdu_len, HTT_RX_MSDU_SIZE));
|
||||
skb_put(msdu, min(msdu_len, ath10k_htt_rx_msdu_size(hw)));
|
||||
msdu_len -= msdu->len;
|
||||
|
||||
/* Note: Chained buffers do not contain rx descriptor */
|
||||
@ -411,11 +425,12 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
|
||||
msdu_chaining = 1;
|
||||
}
|
||||
|
||||
last_msdu = __le32_to_cpu(rx_desc->msdu_end.common.info0) &
|
||||
last_msdu = __le32_to_cpu(rx_desc_msdu_end_common->info0) &
|
||||
RX_MSDU_END_INFO0_LAST_MSDU;
|
||||
|
||||
trace_ath10k_htt_rx_desc(ar, &rx_desc->attention,
|
||||
sizeof(*rx_desc) - sizeof(u32));
|
||||
/* FIXME: why are we skipping the first part of the rx_desc? */
|
||||
trace_ath10k_htt_rx_desc(ar, rx_desc + sizeof(u32),
|
||||
hw->rx_desc_ops->rx_desc_size - sizeof(u32));
|
||||
|
||||
if (last_msdu)
|
||||
break;
|
||||
@ -480,6 +495,7 @@ static int ath10k_htt_rx_handle_amsdu_mon_32(struct ath10k_htt *htt,
|
||||
struct htt_rx_in_ord_msdu_desc **msdu_desc)
|
||||
{
|
||||
struct ath10k *ar = htt->ar;
|
||||
struct ath10k_hw_params *hw = &ar->hw_params;
|
||||
u32 paddr;
|
||||
struct sk_buff *frag_buf;
|
||||
struct sk_buff *prev_frag_buf;
|
||||
@ -488,12 +504,12 @@ static int ath10k_htt_rx_handle_amsdu_mon_32(struct ath10k_htt *htt,
|
||||
struct htt_rx_desc *rxd;
|
||||
int amsdu_len = __le16_to_cpu(ind_desc->msdu_len);
|
||||
|
||||
rxd = (void *)msdu->data;
|
||||
trace_ath10k_htt_rx_desc(ar, rxd, sizeof(*rxd));
|
||||
rxd = HTT_RX_BUF_TO_RX_DESC(hw, msdu->data);
|
||||
trace_ath10k_htt_rx_desc(ar, rxd, hw->rx_desc_ops->rx_desc_size);
|
||||
|
||||
skb_put(msdu, sizeof(struct htt_rx_desc));
|
||||
skb_pull(msdu, sizeof(struct htt_rx_desc));
|
||||
skb_put(msdu, min(amsdu_len, HTT_RX_MSDU_SIZE));
|
||||
skb_put(msdu, hw->rx_desc_ops->rx_desc_size);
|
||||
skb_pull(msdu, hw->rx_desc_ops->rx_desc_size);
|
||||
skb_put(msdu, min(amsdu_len, ath10k_htt_rx_msdu_size(hw)));
|
||||
amsdu_len -= msdu->len;
|
||||
|
||||
last_frag = ind_desc->reserved;
|
||||
@ -556,6 +572,7 @@ ath10k_htt_rx_handle_amsdu_mon_64(struct ath10k_htt *htt,
|
||||
struct htt_rx_in_ord_msdu_desc_ext **msdu_desc)
|
||||
{
|
||||
struct ath10k *ar = htt->ar;
|
||||
struct ath10k_hw_params *hw = &ar->hw_params;
|
||||
u64 paddr;
|
||||
struct sk_buff *frag_buf;
|
||||
struct sk_buff *prev_frag_buf;
|
||||
@ -564,12 +581,12 @@ ath10k_htt_rx_handle_amsdu_mon_64(struct ath10k_htt *htt,
|
||||
struct htt_rx_desc *rxd;
|
||||
int amsdu_len = __le16_to_cpu(ind_desc->msdu_len);
|
||||
|
||||
rxd = (void *)msdu->data;
|
||||
trace_ath10k_htt_rx_desc(ar, rxd, sizeof(*rxd));
|
||||
rxd = HTT_RX_BUF_TO_RX_DESC(hw, msdu->data);
|
||||
trace_ath10k_htt_rx_desc(ar, rxd, hw->rx_desc_ops->rx_desc_size);
|
||||
|
||||
skb_put(msdu, sizeof(struct htt_rx_desc));
|
||||
skb_pull(msdu, sizeof(struct htt_rx_desc));
|
||||
skb_put(msdu, min(amsdu_len, HTT_RX_MSDU_SIZE));
|
||||
skb_put(msdu, hw->rx_desc_ops->rx_desc_size);
|
||||
skb_pull(msdu, hw->rx_desc_ops->rx_desc_size);
|
||||
skb_put(msdu, min(amsdu_len, ath10k_htt_rx_msdu_size(hw)));
|
||||
amsdu_len -= msdu->len;
|
||||
|
||||
last_frag = ind_desc->reserved;
|
||||
@ -631,8 +648,10 @@ static int ath10k_htt_rx_pop_paddr32_list(struct ath10k_htt *htt,
|
||||
struct sk_buff_head *list)
|
||||
{
|
||||
struct ath10k *ar = htt->ar;
|
||||
struct ath10k_hw_params *hw = &ar->hw_params;
|
||||
struct htt_rx_in_ord_msdu_desc *msdu_desc = ev->msdu_descs32;
|
||||
struct htt_rx_desc *rxd;
|
||||
struct rx_attention *rxd_attention;
|
||||
struct sk_buff *msdu;
|
||||
int msdu_count, ret;
|
||||
bool is_offload;
|
||||
@ -667,15 +686,16 @@ static int ath10k_htt_rx_pop_paddr32_list(struct ath10k_htt *htt,
|
||||
__skb_queue_tail(list, msdu);
|
||||
|
||||
if (!is_offload) {
|
||||
rxd = (void *)msdu->data;
|
||||
rxd = HTT_RX_BUF_TO_RX_DESC(hw, msdu->data);
|
||||
rxd_attention = ath10k_htt_rx_desc_get_attention(hw, rxd);
|
||||
|
||||
trace_ath10k_htt_rx_desc(ar, rxd, sizeof(*rxd));
|
||||
trace_ath10k_htt_rx_desc(ar, rxd, hw->rx_desc_ops->rx_desc_size);
|
||||
|
||||
skb_put(msdu, sizeof(*rxd));
|
||||
skb_pull(msdu, sizeof(*rxd));
|
||||
skb_put(msdu, hw->rx_desc_ops->rx_desc_size);
|
||||
skb_pull(msdu, hw->rx_desc_ops->rx_desc_size);
|
||||
skb_put(msdu, __le16_to_cpu(msdu_desc->msdu_len));
|
||||
|
||||
if (!(__le32_to_cpu(rxd->attention.flags) &
|
||||
if (!(__le32_to_cpu(rxd_attention->flags) &
|
||||
RX_ATTENTION_FLAGS_MSDU_DONE)) {
|
||||
ath10k_warn(htt->ar, "tried to pop an incomplete frame, oops!\n");
|
||||
return -EIO;
|
||||
@ -693,8 +713,10 @@ static int ath10k_htt_rx_pop_paddr64_list(struct ath10k_htt *htt,
|
||||
struct sk_buff_head *list)
|
||||
{
|
||||
struct ath10k *ar = htt->ar;
|
||||
struct ath10k_hw_params *hw = &ar->hw_params;
|
||||
struct htt_rx_in_ord_msdu_desc_ext *msdu_desc = ev->msdu_descs64;
|
||||
struct htt_rx_desc *rxd;
|
||||
struct rx_attention *rxd_attention;
|
||||
struct sk_buff *msdu;
|
||||
int msdu_count, ret;
|
||||
bool is_offload;
|
||||
@ -728,15 +750,16 @@ static int ath10k_htt_rx_pop_paddr64_list(struct ath10k_htt *htt,
|
||||
__skb_queue_tail(list, msdu);
|
||||
|
||||
if (!is_offload) {
|
||||
rxd = (void *)msdu->data;
|
||||
rxd = HTT_RX_BUF_TO_RX_DESC(hw, msdu->data);
|
||||
rxd_attention = ath10k_htt_rx_desc_get_attention(hw, rxd);
|
||||
|
||||
trace_ath10k_htt_rx_desc(ar, rxd, sizeof(*rxd));
|
||||
trace_ath10k_htt_rx_desc(ar, rxd, hw->rx_desc_ops->rx_desc_size);
|
||||
|
||||
skb_put(msdu, sizeof(*rxd));
|
||||
skb_pull(msdu, sizeof(*rxd));
|
||||
skb_put(msdu, hw->rx_desc_ops->rx_desc_size);
|
||||
skb_pull(msdu, hw->rx_desc_ops->rx_desc_size);
|
||||
skb_put(msdu, __le16_to_cpu(msdu_desc->msdu_len));
|
||||
|
||||
if (!(__le32_to_cpu(rxd->attention.flags) &
|
||||
if (!(__le32_to_cpu(rxd_attention->flags) &
|
||||
RX_ATTENTION_FLAGS_MSDU_DONE)) {
|
||||
ath10k_warn(htt->ar, "tried to pop an incomplete frame, oops!\n");
|
||||
return -EIO;
|
||||
@ -944,16 +967,32 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar,
|
||||
struct ieee80211_rx_status *status,
|
||||
struct htt_rx_desc *rxd)
|
||||
{
|
||||
struct ath10k_hw_params *hw = &ar->hw_params;
|
||||
struct rx_attention *rxd_attention;
|
||||
struct rx_mpdu_start *rxd_mpdu_start;
|
||||
struct rx_mpdu_end *rxd_mpdu_end;
|
||||
struct rx_msdu_start_common *rxd_msdu_start_common;
|
||||
struct rx_msdu_end_common *rxd_msdu_end_common;
|
||||
struct rx_ppdu_start *rxd_ppdu_start;
|
||||
struct ieee80211_supported_band *sband;
|
||||
u8 cck, rate, bw, sgi, mcs, nss;
|
||||
u8 *rxd_msdu_payload;
|
||||
u8 preamble = 0;
|
||||
u8 group_id;
|
||||
u32 info1, info2, info3;
|
||||
u32 stbc, nsts_su;
|
||||
|
||||
info1 = __le32_to_cpu(rxd->ppdu_start.info1);
|
||||
info2 = __le32_to_cpu(rxd->ppdu_start.info2);
|
||||
info3 = __le32_to_cpu(rxd->ppdu_start.info3);
|
||||
rxd_attention = ath10k_htt_rx_desc_get_attention(hw, rxd);
|
||||
rxd_mpdu_start = ath10k_htt_rx_desc_get_mpdu_start(hw, rxd);
|
||||
rxd_mpdu_end = ath10k_htt_rx_desc_get_mpdu_end(hw, rxd);
|
||||
rxd_msdu_start_common = ath10k_htt_rx_desc_get_msdu_start(hw, rxd);
|
||||
rxd_msdu_end_common = ath10k_htt_rx_desc_get_msdu_end(hw, rxd);
|
||||
rxd_ppdu_start = ath10k_htt_rx_desc_get_ppdu_start(hw, rxd);
|
||||
rxd_msdu_payload = ath10k_htt_rx_desc_get_msdu_payload(hw, rxd);
|
||||
|
||||
info1 = __le32_to_cpu(rxd_ppdu_start->info1);
|
||||
info2 = __le32_to_cpu(rxd_ppdu_start->info2);
|
||||
info3 = __le32_to_cpu(rxd_ppdu_start->info3);
|
||||
|
||||
preamble = MS(info1, RX_PPDU_START_INFO1_PREAMBLE_TYPE);
|
||||
|
||||
@ -1022,24 +1061,24 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar,
|
||||
if (mcs > 0x09) {
|
||||
ath10k_warn(ar, "invalid MCS received %u\n", mcs);
|
||||
ath10k_warn(ar, "rxd %08x mpdu start %08x %08x msdu start %08x %08x ppdu start %08x %08x %08x %08x %08x\n",
|
||||
__le32_to_cpu(rxd->attention.flags),
|
||||
__le32_to_cpu(rxd->mpdu_start.info0),
|
||||
__le32_to_cpu(rxd->mpdu_start.info1),
|
||||
__le32_to_cpu(rxd->msdu_start.common.info0),
|
||||
__le32_to_cpu(rxd->msdu_start.common.info1),
|
||||
rxd->ppdu_start.info0,
|
||||
__le32_to_cpu(rxd->ppdu_start.info1),
|
||||
__le32_to_cpu(rxd->ppdu_start.info2),
|
||||
__le32_to_cpu(rxd->ppdu_start.info3),
|
||||
__le32_to_cpu(rxd->ppdu_start.info4));
|
||||
__le32_to_cpu(rxd_attention->flags),
|
||||
__le32_to_cpu(rxd_mpdu_start->info0),
|
||||
__le32_to_cpu(rxd_mpdu_start->info1),
|
||||
__le32_to_cpu(rxd_msdu_start_common->info0),
|
||||
__le32_to_cpu(rxd_msdu_start_common->info1),
|
||||
rxd_ppdu_start->info0,
|
||||
__le32_to_cpu(rxd_ppdu_start->info1),
|
||||
__le32_to_cpu(rxd_ppdu_start->info2),
|
||||
__le32_to_cpu(rxd_ppdu_start->info3),
|
||||
__le32_to_cpu(rxd_ppdu_start->info4));
|
||||
|
||||
ath10k_warn(ar, "msdu end %08x mpdu end %08x\n",
|
||||
__le32_to_cpu(rxd->msdu_end.common.info0),
|
||||
__le32_to_cpu(rxd->mpdu_end.info0));
|
||||
__le32_to_cpu(rxd_msdu_end_common->info0),
|
||||
__le32_to_cpu(rxd_mpdu_end->info0));
|
||||
|
||||
ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL,
|
||||
"rx desc msdu payload: ",
|
||||
rxd->msdu_payload, 50);
|
||||
rxd_msdu_payload, 50);
|
||||
}
|
||||
|
||||
status->rate_idx = mcs;
|
||||
@ -1059,6 +1098,10 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar,
|
||||
static struct ieee80211_channel *
|
||||
ath10k_htt_rx_h_peer_channel(struct ath10k *ar, struct htt_rx_desc *rxd)
|
||||
{
|
||||
struct ath10k_hw_params *hw = &ar->hw_params;
|
||||
struct rx_attention *rxd_attention;
|
||||
struct rx_msdu_end_common *rxd_msdu_end_common;
|
||||
struct rx_mpdu_start *rxd_mpdu_start;
|
||||
struct ath10k_peer *peer;
|
||||
struct ath10k_vif *arvif;
|
||||
struct cfg80211_chan_def def;
|
||||
@ -1069,15 +1112,19 @@ ath10k_htt_rx_h_peer_channel(struct ath10k *ar, struct htt_rx_desc *rxd)
|
||||
if (!rxd)
|
||||
return NULL;
|
||||
|
||||
if (rxd->attention.flags &
|
||||
rxd_attention = ath10k_htt_rx_desc_get_attention(hw, rxd);
|
||||
rxd_msdu_end_common = ath10k_htt_rx_desc_get_msdu_end(hw, rxd);
|
||||
rxd_mpdu_start = ath10k_htt_rx_desc_get_mpdu_start(hw, rxd);
|
||||
|
||||
if (rxd_attention->flags &
|
||||
__cpu_to_le32(RX_ATTENTION_FLAGS_PEER_IDX_INVALID))
|
||||
return NULL;
|
||||
|
||||
if (!(rxd->msdu_end.common.info0 &
|
||||
if (!(rxd_msdu_end_common->info0 &
|
||||
__cpu_to_le32(RX_MSDU_END_INFO0_FIRST_MSDU)))
|
||||
return NULL;
|
||||
|
||||
peer_id = MS(__le32_to_cpu(rxd->mpdu_start.info0),
|
||||
peer_id = MS(__le32_to_cpu(rxd_mpdu_start->info0),
|
||||
RX_MPDU_START_INFO0_PEER_IDX);
|
||||
|
||||
peer = ath10k_peer_find_by_id(ar, peer_id);
|
||||
@ -1167,14 +1214,16 @@ static void ath10k_htt_rx_h_signal(struct ath10k *ar,
|
||||
struct ieee80211_rx_status *status,
|
||||
struct htt_rx_desc *rxd)
|
||||
{
|
||||
struct ath10k_hw_params *hw = &ar->hw_params;
|
||||
struct rx_ppdu_start *rxd_ppdu_start = ath10k_htt_rx_desc_get_ppdu_start(hw, rxd);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < IEEE80211_MAX_CHAINS ; i++) {
|
||||
status->chains &= ~BIT(i);
|
||||
|
||||
if (rxd->ppdu_start.rssi_chains[i].pri20_mhz != 0x80) {
|
||||
if (rxd_ppdu_start->rssi_chains[i].pri20_mhz != 0x80) {
|
||||
status->chain_signal[i] = ATH10K_DEFAULT_NOISE_FLOOR +
|
||||
rxd->ppdu_start.rssi_chains[i].pri20_mhz;
|
||||
rxd_ppdu_start->rssi_chains[i].pri20_mhz;
|
||||
|
||||
status->chains |= BIT(i);
|
||||
}
|
||||
@ -1182,7 +1231,7 @@ static void ath10k_htt_rx_h_signal(struct ath10k *ar,
|
||||
|
||||
/* FIXME: Get real NF */
|
||||
status->signal = ATH10K_DEFAULT_NOISE_FLOOR +
|
||||
rxd->ppdu_start.rssi_comb;
|
||||
rxd_ppdu_start->rssi_comb;
|
||||
status->flag &= ~RX_FLAG_NO_SIGNAL_VAL;
|
||||
}
|
||||
|
||||
@ -1190,13 +1239,18 @@ static void ath10k_htt_rx_h_mactime(struct ath10k *ar,
|
||||
struct ieee80211_rx_status *status,
|
||||
struct htt_rx_desc *rxd)
|
||||
{
|
||||
struct ath10k_hw_params *hw = &ar->hw_params;
|
||||
struct rx_ppdu_end_common *rxd_ppdu_end_common;
|
||||
|
||||
rxd_ppdu_end_common = ath10k_htt_rx_desc_get_ppdu_end(hw, rxd);
|
||||
|
||||
/* FIXME: TSF is known only at the end of PPDU, in the last MPDU. This
|
||||
* means all prior MSDUs in a PPDU are reported to mac80211 without the
|
||||
* TSF. Is it worth holding frames until end of PPDU is known?
|
||||
*
|
||||
* FIXME: Can we get/compute 64bit TSF?
|
||||
*/
|
||||
status->mactime = __le32_to_cpu(rxd->ppdu_end.common.tsf_timestamp);
|
||||
status->mactime = __le32_to_cpu(rxd_ppdu_end_common->tsf_timestamp);
|
||||
status->flag |= RX_FLAG_MACTIME_END;
|
||||
}
|
||||
|
||||
@ -1206,7 +1260,9 @@ static void ath10k_htt_rx_h_ppdu(struct ath10k *ar,
|
||||
u32 vdev_id)
|
||||
{
|
||||
struct sk_buff *first;
|
||||
struct ath10k_hw_params *hw = &ar->hw_params;
|
||||
struct htt_rx_desc *rxd;
|
||||
struct rx_attention *rxd_attention;
|
||||
bool is_first_ppdu;
|
||||
bool is_last_ppdu;
|
||||
|
||||
@ -1214,11 +1270,14 @@ static void ath10k_htt_rx_h_ppdu(struct ath10k *ar,
|
||||
return;
|
||||
|
||||
first = skb_peek(amsdu);
|
||||
rxd = (void *)first->data - sizeof(*rxd);
|
||||
rxd = HTT_RX_BUF_TO_RX_DESC(hw,
|
||||
(void *)first->data - hw->rx_desc_ops->rx_desc_size);
|
||||
|
||||
is_first_ppdu = !!(rxd->attention.flags &
|
||||
rxd_attention = ath10k_htt_rx_desc_get_attention(hw, rxd);
|
||||
|
||||
is_first_ppdu = !!(rxd_attention->flags &
|
||||
__cpu_to_le32(RX_ATTENTION_FLAGS_FIRST_MPDU));
|
||||
is_last_ppdu = !!(rxd->attention.flags &
|
||||
is_last_ppdu = !!(rxd_attention->flags &
|
||||
__cpu_to_le32(RX_ATTENTION_FLAGS_LAST_MPDU));
|
||||
|
||||
if (is_first_ppdu) {
|
||||
@ -1357,7 +1416,9 @@ static void ath10k_htt_rx_h_undecap_raw(struct ath10k *ar,
|
||||
const u8 first_hdr[64])
|
||||
{
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ath10k_hw_params *hw = &ar->hw_params;
|
||||
struct htt_rx_desc *rxd;
|
||||
struct rx_msdu_end_common *rxd_msdu_end_common;
|
||||
size_t hdr_len;
|
||||
size_t crypto_len;
|
||||
bool is_first;
|
||||
@ -1366,10 +1427,13 @@ static void ath10k_htt_rx_h_undecap_raw(struct ath10k *ar,
|
||||
int bytes_aligned = ar->hw_params.decap_align_bytes;
|
||||
u8 *qos;
|
||||
|
||||
rxd = (void *)msdu->data - sizeof(*rxd);
|
||||
is_first = !!(rxd->msdu_end.common.info0 &
|
||||
rxd = HTT_RX_BUF_TO_RX_DESC(hw,
|
||||
(void *)msdu->data - hw->rx_desc_ops->rx_desc_size);
|
||||
|
||||
rxd_msdu_end_common = ath10k_htt_rx_desc_get_msdu_end(hw, rxd);
|
||||
is_first = !!(rxd_msdu_end_common->info0 &
|
||||
__cpu_to_le32(RX_MSDU_END_INFO0_FIRST_MSDU));
|
||||
is_last = !!(rxd->msdu_end.common.info0 &
|
||||
is_last = !!(rxd_msdu_end_common->info0 &
|
||||
__cpu_to_le32(RX_MSDU_END_INFO0_LAST_MSDU));
|
||||
|
||||
/* Delivered decapped frame:
|
||||
@ -1387,7 +1451,7 @@ static void ath10k_htt_rx_h_undecap_raw(struct ath10k *ar,
|
||||
* error packets. If limit exceeds, hw sends all remaining MSDUs as
|
||||
* a single last MSDU with this msdu limit error set.
|
||||
*/
|
||||
msdu_limit_err = ath10k_rx_desc_msdu_limit_error(&ar->hw_params, rxd);
|
||||
msdu_limit_err = ath10k_htt_rx_desc_msdu_limit_error(hw, rxd);
|
||||
|
||||
/* If MSDU limit error happens, then don't warn on, the partial raw MSDU
|
||||
* without first MSDU is expected in that case, and handled later here.
|
||||
@ -1479,6 +1543,7 @@ static void ath10k_htt_rx_h_undecap_nwifi(struct ath10k *ar,
|
||||
const u8 first_hdr[64],
|
||||
enum htt_rx_mpdu_encrypt_type enctype)
|
||||
{
|
||||
struct ath10k_hw_params *hw = &ar->hw_params;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct htt_rx_desc *rxd;
|
||||
size_t hdr_len;
|
||||
@ -1499,9 +1564,10 @@ static void ath10k_htt_rx_h_undecap_nwifi(struct ath10k *ar,
|
||||
*/
|
||||
|
||||
/* pull decapped header and copy SA & DA */
|
||||
rxd = (void *)msdu->data - sizeof(*rxd);
|
||||
rxd = HTT_RX_BUF_TO_RX_DESC(hw, (void *)msdu->data -
|
||||
hw->rx_desc_ops->rx_desc_size);
|
||||
|
||||
l3_pad_bytes = ath10k_rx_desc_get_l3_pad_bytes(&ar->hw_params, rxd);
|
||||
l3_pad_bytes = ath10k_htt_rx_desc_get_l3_pad_bytes(&ar->hw_params, rxd);
|
||||
skb_put(msdu, l3_pad_bytes);
|
||||
|
||||
hdr = (struct ieee80211_hdr *)(msdu->data + l3_pad_bytes);
|
||||
@ -1537,18 +1603,25 @@ static void *ath10k_htt_rx_h_find_rfc1042(struct ath10k *ar,
|
||||
enum htt_rx_mpdu_encrypt_type enctype)
|
||||
{
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ath10k_hw_params *hw = &ar->hw_params;
|
||||
struct htt_rx_desc *rxd;
|
||||
struct rx_msdu_end_common *rxd_msdu_end_common;
|
||||
u8 *rxd_rx_hdr_status;
|
||||
size_t hdr_len, crypto_len;
|
||||
void *rfc1042;
|
||||
bool is_first, is_last, is_amsdu;
|
||||
int bytes_aligned = ar->hw_params.decap_align_bytes;
|
||||
|
||||
rxd = (void *)msdu->data - sizeof(*rxd);
|
||||
hdr = (void *)rxd->rx_hdr_status;
|
||||
rxd = HTT_RX_BUF_TO_RX_DESC(hw,
|
||||
(void *)msdu->data - hw->rx_desc_ops->rx_desc_size);
|
||||
|
||||
is_first = !!(rxd->msdu_end.common.info0 &
|
||||
rxd_msdu_end_common = ath10k_htt_rx_desc_get_msdu_end(hw, rxd);
|
||||
rxd_rx_hdr_status = ath10k_htt_rx_desc_get_rx_hdr_status(hw, rxd);
|
||||
hdr = (void *)rxd_rx_hdr_status;
|
||||
|
||||
is_first = !!(rxd_msdu_end_common->info0 &
|
||||
__cpu_to_le32(RX_MSDU_END_INFO0_FIRST_MSDU));
|
||||
is_last = !!(rxd->msdu_end.common.info0 &
|
||||
is_last = !!(rxd_msdu_end_common->info0 &
|
||||
__cpu_to_le32(RX_MSDU_END_INFO0_LAST_MSDU));
|
||||
is_amsdu = !(is_first && is_last);
|
||||
|
||||
@ -1574,6 +1647,7 @@ static void ath10k_htt_rx_h_undecap_eth(struct ath10k *ar,
|
||||
const u8 first_hdr[64],
|
||||
enum htt_rx_mpdu_encrypt_type enctype)
|
||||
{
|
||||
struct ath10k_hw_params *hw = &ar->hw_params;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ethhdr *eth;
|
||||
size_t hdr_len;
|
||||
@ -1593,8 +1667,10 @@ static void ath10k_htt_rx_h_undecap_eth(struct ath10k *ar,
|
||||
if (WARN_ON_ONCE(!rfc1042))
|
||||
return;
|
||||
|
||||
rxd = (void *)msdu->data - sizeof(*rxd);
|
||||
l3_pad_bytes = ath10k_rx_desc_get_l3_pad_bytes(&ar->hw_params, rxd);
|
||||
rxd = HTT_RX_BUF_TO_RX_DESC(hw,
|
||||
(void *)msdu->data - hw->rx_desc_ops->rx_desc_size);
|
||||
|
||||
l3_pad_bytes = ath10k_htt_rx_desc_get_l3_pad_bytes(&ar->hw_params, rxd);
|
||||
skb_put(msdu, l3_pad_bytes);
|
||||
skb_pull(msdu, l3_pad_bytes);
|
||||
|
||||
@ -1635,6 +1711,7 @@ static void ath10k_htt_rx_h_undecap_snap(struct ath10k *ar,
|
||||
const u8 first_hdr[64],
|
||||
enum htt_rx_mpdu_encrypt_type enctype)
|
||||
{
|
||||
struct ath10k_hw_params *hw = &ar->hw_params;
|
||||
struct ieee80211_hdr *hdr;
|
||||
size_t hdr_len;
|
||||
int l3_pad_bytes;
|
||||
@ -1647,8 +1724,10 @@ static void ath10k_htt_rx_h_undecap_snap(struct ath10k *ar,
|
||||
* [payload]
|
||||
*/
|
||||
|
||||
rxd = (void *)msdu->data - sizeof(*rxd);
|
||||
l3_pad_bytes = ath10k_rx_desc_get_l3_pad_bytes(&ar->hw_params, rxd);
|
||||
rxd = HTT_RX_BUF_TO_RX_DESC(hw,
|
||||
(void *)msdu->data - hw->rx_desc_ops->rx_desc_size);
|
||||
|
||||
l3_pad_bytes = ath10k_htt_rx_desc_get_l3_pad_bytes(&ar->hw_params, rxd);
|
||||
|
||||
skb_put(msdu, l3_pad_bytes);
|
||||
skb_pull(msdu, sizeof(struct amsdu_subframe_hdr) + l3_pad_bytes);
|
||||
@ -1673,7 +1752,9 @@ static void ath10k_htt_rx_h_undecap(struct ath10k *ar,
|
||||
enum htt_rx_mpdu_encrypt_type enctype,
|
||||
bool is_decrypted)
|
||||
{
|
||||
struct ath10k_hw_params *hw = &ar->hw_params;
|
||||
struct htt_rx_desc *rxd;
|
||||
struct rx_msdu_start_common *rxd_msdu_start_common;
|
||||
enum rx_msdu_decap_format decap;
|
||||
|
||||
/* First msdu's decapped header:
|
||||
@ -1687,8 +1768,11 @@ static void ath10k_htt_rx_h_undecap(struct ath10k *ar,
|
||||
* [rfc1042/llc]
|
||||
*/
|
||||
|
||||
rxd = (void *)msdu->data - sizeof(*rxd);
|
||||
decap = MS(__le32_to_cpu(rxd->msdu_start.common.info1),
|
||||
rxd = HTT_RX_BUF_TO_RX_DESC(hw,
|
||||
(void *)msdu->data - hw->rx_desc_ops->rx_desc_size);
|
||||
|
||||
rxd_msdu_start_common = ath10k_htt_rx_desc_get_msdu_start(hw, rxd);
|
||||
decap = MS(__le32_to_cpu(rxd_msdu_start_common->info1),
|
||||
RX_MSDU_START_INFO1_DECAP_FORMAT);
|
||||
|
||||
switch (decap) {
|
||||
@ -1710,17 +1794,23 @@ static void ath10k_htt_rx_h_undecap(struct ath10k *ar,
|
||||
}
|
||||
}
|
||||
|
||||
static int ath10k_htt_rx_get_csum_state(struct sk_buff *skb)
|
||||
static int ath10k_htt_rx_get_csum_state(struct ath10k_hw_params *hw, struct sk_buff *skb)
|
||||
{
|
||||
struct htt_rx_desc *rxd;
|
||||
struct rx_attention *rxd_attention;
|
||||
struct rx_msdu_start_common *rxd_msdu_start_common;
|
||||
u32 flags, info;
|
||||
bool is_ip4, is_ip6;
|
||||
bool is_tcp, is_udp;
|
||||
bool ip_csum_ok, tcpudp_csum_ok;
|
||||
|
||||
rxd = (void *)skb->data - sizeof(*rxd);
|
||||
flags = __le32_to_cpu(rxd->attention.flags);
|
||||
info = __le32_to_cpu(rxd->msdu_start.common.info1);
|
||||
rxd = HTT_RX_BUF_TO_RX_DESC(hw,
|
||||
(void *)skb->data - hw->rx_desc_ops->rx_desc_size);
|
||||
|
||||
rxd_attention = ath10k_htt_rx_desc_get_attention(hw, rxd);
|
||||
rxd_msdu_start_common = ath10k_htt_rx_desc_get_msdu_start(hw, rxd);
|
||||
flags = __le32_to_cpu(rxd_attention->flags);
|
||||
info = __le32_to_cpu(rxd_msdu_start_common->info1);
|
||||
|
||||
is_ip4 = !!(info & RX_MSDU_START_INFO1_IPV4_PROTO);
|
||||
is_ip6 = !!(info & RX_MSDU_START_INFO1_IPV6_PROTO);
|
||||
@ -1741,9 +1831,10 @@ static int ath10k_htt_rx_get_csum_state(struct sk_buff *skb)
|
||||
return CHECKSUM_UNNECESSARY;
|
||||
}
|
||||
|
||||
static void ath10k_htt_rx_h_csum_offload(struct sk_buff *msdu)
|
||||
static void ath10k_htt_rx_h_csum_offload(struct ath10k_hw_params *hw,
|
||||
struct sk_buff *msdu)
|
||||
{
|
||||
msdu->ip_summed = ath10k_htt_rx_get_csum_state(msdu);
|
||||
msdu->ip_summed = ath10k_htt_rx_get_csum_state(hw, msdu);
|
||||
}
|
||||
|
||||
static u64 ath10k_htt_rx_h_get_pn(struct ath10k *ar, struct sk_buff *skb,
|
||||
@ -1835,7 +1926,11 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
|
||||
struct sk_buff *first;
|
||||
struct sk_buff *last;
|
||||
struct sk_buff *msdu, *temp;
|
||||
struct ath10k_hw_params *hw = &ar->hw_params;
|
||||
struct htt_rx_desc *rxd;
|
||||
struct rx_attention *rxd_attention;
|
||||
struct rx_mpdu_start *rxd_mpdu_start;
|
||||
|
||||
struct ieee80211_hdr *hdr;
|
||||
enum htt_rx_mpdu_encrypt_type enctype;
|
||||
u8 first_hdr[64];
|
||||
@ -1853,18 +1948,22 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
|
||||
return;
|
||||
|
||||
first = skb_peek(amsdu);
|
||||
rxd = (void *)first->data - sizeof(*rxd);
|
||||
rxd = HTT_RX_BUF_TO_RX_DESC(hw,
|
||||
(void *)first->data - hw->rx_desc_ops->rx_desc_size);
|
||||
|
||||
is_mgmt = !!(rxd->attention.flags &
|
||||
rxd_attention = ath10k_htt_rx_desc_get_attention(hw, rxd);
|
||||
rxd_mpdu_start = ath10k_htt_rx_desc_get_mpdu_start(hw, rxd);
|
||||
|
||||
is_mgmt = !!(rxd_attention->flags &
|
||||
__cpu_to_le32(RX_ATTENTION_FLAGS_MGMT_TYPE));
|
||||
|
||||
enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0),
|
||||
enctype = MS(__le32_to_cpu(rxd_mpdu_start->info0),
|
||||
RX_MPDU_START_INFO0_ENCRYPT_TYPE);
|
||||
|
||||
/* First MSDU's Rx descriptor in an A-MSDU contains full 802.11
|
||||
* decapped header. It'll be used for undecapping of each MSDU.
|
||||
*/
|
||||
hdr = (void *)rxd->rx_hdr_status;
|
||||
hdr = (void *)ath10k_htt_rx_desc_get_rx_hdr_status(hw, rxd);
|
||||
memcpy(first_hdr, hdr, RX_HTT_HDR_STATUS_LEN);
|
||||
|
||||
if (rx_hdr)
|
||||
@ -1882,8 +1981,11 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
|
||||
|
||||
/* Some attention flags are valid only in the last MSDU. */
|
||||
last = skb_peek_tail(amsdu);
|
||||
rxd = (void *)last->data - sizeof(*rxd);
|
||||
attention = __le32_to_cpu(rxd->attention.flags);
|
||||
rxd = HTT_RX_BUF_TO_RX_DESC(hw,
|
||||
(void *)last->data - hw->rx_desc_ops->rx_desc_size);
|
||||
|
||||
rxd_attention = ath10k_htt_rx_desc_get_attention(hw, rxd);
|
||||
attention = __le32_to_cpu(rxd_attention->flags);
|
||||
|
||||
has_fcs_err = !!(attention & RX_ATTENTION_FLAGS_FCS_ERR);
|
||||
has_crypto_err = !!(attention & RX_ATTENTION_FLAGS_DECRYPT_ERR);
|
||||
@ -1971,7 +2073,7 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
|
||||
continue;
|
||||
}
|
||||
|
||||
ath10k_htt_rx_h_csum_offload(msdu);
|
||||
ath10k_htt_rx_h_csum_offload(&ar->hw_params, msdu);
|
||||
|
||||
if (frag && !fill_crypt_header &&
|
||||
enctype == HTT_RX_MPDU_ENCRYPT_TKIP_WPA)
|
||||
@ -2083,12 +2185,19 @@ static void ath10k_htt_rx_h_unchain(struct ath10k *ar,
|
||||
unsigned long *unchain_cnt)
|
||||
{
|
||||
struct sk_buff *first;
|
||||
struct ath10k_hw_params *hw = &ar->hw_params;
|
||||
struct htt_rx_desc *rxd;
|
||||
struct rx_msdu_start_common *rxd_msdu_start_common;
|
||||
struct rx_frag_info_common *rxd_frag_info;
|
||||
enum rx_msdu_decap_format decap;
|
||||
|
||||
first = skb_peek(amsdu);
|
||||
rxd = (void *)first->data - sizeof(*rxd);
|
||||
decap = MS(__le32_to_cpu(rxd->msdu_start.common.info1),
|
||||
rxd = HTT_RX_BUF_TO_RX_DESC(hw,
|
||||
(void *)first->data - hw->rx_desc_ops->rx_desc_size);
|
||||
|
||||
rxd_msdu_start_common = ath10k_htt_rx_desc_get_msdu_start(hw, rxd);
|
||||
rxd_frag_info = ath10k_htt_rx_desc_get_frag_info(hw, rxd);
|
||||
decap = MS(__le32_to_cpu(rxd_msdu_start_common->info1),
|
||||
RX_MSDU_START_INFO1_DECAP_FORMAT);
|
||||
|
||||
/* FIXME: Current unchaining logic can only handle simple case of raw
|
||||
@ -2097,7 +2206,7 @@ static void ath10k_htt_rx_h_unchain(struct ath10k *ar,
|
||||
* try re-constructing such frames - it'll be pretty much garbage.
|
||||
*/
|
||||
if (decap != RX_MSDU_DECAP_RAW ||
|
||||
skb_queue_len(amsdu) != 1 + rxd->frag_info.ring2_more_count) {
|
||||
skb_queue_len(amsdu) != 1 + rxd_frag_info->ring2_more_count) {
|
||||
*drop_cnt += skb_queue_len(amsdu);
|
||||
__skb_queue_purge(amsdu);
|
||||
return;
|
||||
@ -2112,7 +2221,10 @@ static bool ath10k_htt_rx_validate_amsdu(struct ath10k *ar,
|
||||
u8 *subframe_hdr;
|
||||
struct sk_buff *first;
|
||||
bool is_first, is_last;
|
||||
struct ath10k_hw_params *hw = &ar->hw_params;
|
||||
struct htt_rx_desc *rxd;
|
||||
struct rx_msdu_end_common *rxd_msdu_end_common;
|
||||
struct rx_mpdu_start *rxd_mpdu_start;
|
||||
struct ieee80211_hdr *hdr;
|
||||
size_t hdr_len, crypto_len;
|
||||
enum htt_rx_mpdu_encrypt_type enctype;
|
||||
@ -2120,12 +2232,16 @@ static bool ath10k_htt_rx_validate_amsdu(struct ath10k *ar,
|
||||
|
||||
first = skb_peek(amsdu);
|
||||
|
||||
rxd = (void *)first->data - sizeof(*rxd);
|
||||
hdr = (void *)rxd->rx_hdr_status;
|
||||
rxd = HTT_RX_BUF_TO_RX_DESC(hw,
|
||||
(void *)first->data - hw->rx_desc_ops->rx_desc_size);
|
||||
|
||||
is_first = !!(rxd->msdu_end.common.info0 &
|
||||
rxd_msdu_end_common = ath10k_htt_rx_desc_get_msdu_end(hw, rxd);
|
||||
rxd_mpdu_start = ath10k_htt_rx_desc_get_mpdu_start(hw, rxd);
|
||||
hdr = (void *)ath10k_htt_rx_desc_get_rx_hdr_status(hw, rxd);
|
||||
|
||||
is_first = !!(rxd_msdu_end_common->info0 &
|
||||
__cpu_to_le32(RX_MSDU_END_INFO0_FIRST_MSDU));
|
||||
is_last = !!(rxd->msdu_end.common.info0 &
|
||||
is_last = !!(rxd_msdu_end_common->info0 &
|
||||
__cpu_to_le32(RX_MSDU_END_INFO0_LAST_MSDU));
|
||||
|
||||
/* Return in case of non-aggregated msdu */
|
||||
@ -2136,7 +2252,7 @@ static bool ath10k_htt_rx_validate_amsdu(struct ath10k *ar,
|
||||
if (!is_first)
|
||||
return false;
|
||||
|
||||
enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0),
|
||||
enctype = MS(__le32_to_cpu(rxd_mpdu_start->info0),
|
||||
RX_MPDU_START_INFO0_ENCRYPT_TYPE);
|
||||
|
||||
hdr_len = ieee80211_hdrlen(hdr->frame_control);
|
||||
@ -3028,11 +3144,13 @@ static void ath10k_htt_rx_delba(struct ath10k *ar, struct htt_resp *resp)
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
}
|
||||
|
||||
static int ath10k_htt_rx_extract_amsdu(struct sk_buff_head *list,
|
||||
static int ath10k_htt_rx_extract_amsdu(struct ath10k_hw_params *hw,
|
||||
struct sk_buff_head *list,
|
||||
struct sk_buff_head *amsdu)
|
||||
{
|
||||
struct sk_buff *msdu;
|
||||
struct htt_rx_desc *rxd;
|
||||
struct rx_msdu_end_common *rxd_msdu_end_common;
|
||||
|
||||
if (skb_queue_empty(list))
|
||||
return -ENOBUFS;
|
||||
@ -3043,15 +3161,22 @@ static int ath10k_htt_rx_extract_amsdu(struct sk_buff_head *list,
|
||||
while ((msdu = __skb_dequeue(list))) {
|
||||
__skb_queue_tail(amsdu, msdu);
|
||||
|
||||
rxd = (void *)msdu->data - sizeof(*rxd);
|
||||
if (rxd->msdu_end.common.info0 &
|
||||
rxd = HTT_RX_BUF_TO_RX_DESC(hw,
|
||||
(void *)msdu->data -
|
||||
hw->rx_desc_ops->rx_desc_size);
|
||||
|
||||
rxd_msdu_end_common = ath10k_htt_rx_desc_get_msdu_end(hw, rxd);
|
||||
if (rxd_msdu_end_common->info0 &
|
||||
__cpu_to_le32(RX_MSDU_END_INFO0_LAST_MSDU))
|
||||
break;
|
||||
}
|
||||
|
||||
msdu = skb_peek_tail(amsdu);
|
||||
rxd = (void *)msdu->data - sizeof(*rxd);
|
||||
if (!(rxd->msdu_end.common.info0 &
|
||||
rxd = HTT_RX_BUF_TO_RX_DESC(hw,
|
||||
(void *)msdu->data - hw->rx_desc_ops->rx_desc_size);
|
||||
|
||||
rxd_msdu_end_common = ath10k_htt_rx_desc_get_msdu_end(hw, rxd);
|
||||
if (!(rxd_msdu_end_common->info0 &
|
||||
__cpu_to_le32(RX_MSDU_END_INFO0_LAST_MSDU))) {
|
||||
skb_queue_splice_init(amsdu, list);
|
||||
return -EAGAIN;
|
||||
@ -3194,7 +3319,7 @@ static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb)
|
||||
|
||||
while (!skb_queue_empty(&list)) {
|
||||
__skb_queue_head_init(&amsdu);
|
||||
ret = ath10k_htt_rx_extract_amsdu(&list, &amsdu);
|
||||
ret = ath10k_htt_rx_extract_amsdu(&ar->hw_params, &list, &amsdu);
|
||||
switch (ret) {
|
||||
case 0:
|
||||
/* Note: The in-order indication may report interleaved
|
||||
|
@ -796,47 +796,26 @@ static int ath10k_htt_send_frag_desc_bank_cfg_64(struct ath10k_htt *htt)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath10k_htt_fill_rx_desc_offset_32(void *rx_ring)
|
||||
static void ath10k_htt_fill_rx_desc_offset_32(struct ath10k_hw_params *hw, void *rx_ring)
|
||||
{
|
||||
struct htt_rx_ring_setup_ring32 *ring =
|
||||
(struct htt_rx_ring_setup_ring32 *)rx_ring;
|
||||
|
||||
#define desc_offset(x) (offsetof(struct htt_rx_desc, x) / 4)
|
||||
ring->mac80211_hdr_offset = __cpu_to_le16(desc_offset(rx_hdr_status));
|
||||
ring->msdu_payload_offset = __cpu_to_le16(desc_offset(msdu_payload));
|
||||
ring->ppdu_start_offset = __cpu_to_le16(desc_offset(ppdu_start));
|
||||
ring->ppdu_end_offset = __cpu_to_le16(desc_offset(ppdu_end));
|
||||
ring->mpdu_start_offset = __cpu_to_le16(desc_offset(mpdu_start));
|
||||
ring->mpdu_end_offset = __cpu_to_le16(desc_offset(mpdu_end));
|
||||
ring->msdu_start_offset = __cpu_to_le16(desc_offset(msdu_start));
|
||||
ring->msdu_end_offset = __cpu_to_le16(desc_offset(msdu_end));
|
||||
ring->rx_attention_offset = __cpu_to_le16(desc_offset(attention));
|
||||
ring->frag_info_offset = __cpu_to_le16(desc_offset(frag_info));
|
||||
#undef desc_offset
|
||||
ath10k_htt_rx_desc_get_offsets(hw, &ring->offsets);
|
||||
}
|
||||
|
||||
static void ath10k_htt_fill_rx_desc_offset_64(void *rx_ring)
|
||||
static void ath10k_htt_fill_rx_desc_offset_64(struct ath10k_hw_params *hw, void *rx_ring)
|
||||
{
|
||||
struct htt_rx_ring_setup_ring64 *ring =
|
||||
(struct htt_rx_ring_setup_ring64 *)rx_ring;
|
||||
|
||||
#define desc_offset(x) (offsetof(struct htt_rx_desc, x) / 4)
|
||||
ring->mac80211_hdr_offset = __cpu_to_le16(desc_offset(rx_hdr_status));
|
||||
ring->msdu_payload_offset = __cpu_to_le16(desc_offset(msdu_payload));
|
||||
ring->ppdu_start_offset = __cpu_to_le16(desc_offset(ppdu_start));
|
||||
ring->ppdu_end_offset = __cpu_to_le16(desc_offset(ppdu_end));
|
||||
ring->mpdu_start_offset = __cpu_to_le16(desc_offset(mpdu_start));
|
||||
ring->mpdu_end_offset = __cpu_to_le16(desc_offset(mpdu_end));
|
||||
ring->msdu_start_offset = __cpu_to_le16(desc_offset(msdu_start));
|
||||
ring->msdu_end_offset = __cpu_to_le16(desc_offset(msdu_end));
|
||||
ring->rx_attention_offset = __cpu_to_le16(desc_offset(attention));
|
||||
ring->frag_info_offset = __cpu_to_le16(desc_offset(frag_info));
|
||||
#undef desc_offset
|
||||
ath10k_htt_rx_desc_get_offsets(hw, &ring->offsets);
|
||||
}
|
||||
|
||||
static int ath10k_htt_send_rx_ring_cfg_32(struct ath10k_htt *htt)
|
||||
{
|
||||
struct ath10k *ar = htt->ar;
|
||||
struct ath10k_hw_params *hw = &ar->hw_params;
|
||||
struct sk_buff *skb;
|
||||
struct htt_cmd *cmd;
|
||||
struct htt_rx_ring_setup_ring32 *ring;
|
||||
@ -896,7 +875,7 @@ static int ath10k_htt_send_rx_ring_cfg_32(struct ath10k_htt *htt)
|
||||
ring->flags = __cpu_to_le16(flags);
|
||||
ring->fw_idx_init_val = __cpu_to_le16(fw_idx);
|
||||
|
||||
ath10k_htt_fill_rx_desc_offset_32(ring);
|
||||
ath10k_htt_fill_rx_desc_offset_32(hw, ring);
|
||||
ret = ath10k_htc_send(&htt->ar->htc, htt->eid, skb);
|
||||
if (ret) {
|
||||
dev_kfree_skb_any(skb);
|
||||
@ -909,6 +888,7 @@ static int ath10k_htt_send_rx_ring_cfg_32(struct ath10k_htt *htt)
|
||||
static int ath10k_htt_send_rx_ring_cfg_64(struct ath10k_htt *htt)
|
||||
{
|
||||
struct ath10k *ar = htt->ar;
|
||||
struct ath10k_hw_params *hw = &ar->hw_params;
|
||||
struct sk_buff *skb;
|
||||
struct htt_cmd *cmd;
|
||||
struct htt_rx_ring_setup_ring64 *ring;
|
||||
@ -965,7 +945,7 @@ static int ath10k_htt_send_rx_ring_cfg_64(struct ath10k_htt *htt)
|
||||
ring->flags = __cpu_to_le16(flags);
|
||||
ring->fw_idx_init_val = __cpu_to_le16(fw_idx);
|
||||
|
||||
ath10k_htt_fill_rx_desc_offset_64(ring);
|
||||
ath10k_htt_fill_rx_desc_offset_64(hw, ring);
|
||||
ret = ath10k_htc_send(&htt->ar->htc, htt->eid, skb);
|
||||
if (ret) {
|
||||
dev_kfree_skb_any(skb);
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "hif.h"
|
||||
#include "wmi-ops.h"
|
||||
#include "bmi.h"
|
||||
#include "rx_desc.h"
|
||||
|
||||
const struct ath10k_hw_regs qca988x_regs = {
|
||||
.rtc_soc_base_address = 0x00004000,
|
||||
@ -1134,21 +1135,7 @@ const struct ath10k_hw_ops qca988x_ops = {
|
||||
.is_rssi_enable = ath10k_htt_tx_rssi_enable,
|
||||
};
|
||||
|
||||
static int ath10k_qca99x0_rx_desc_get_l3_pad_bytes(struct htt_rx_desc *rxd)
|
||||
{
|
||||
return MS(__le32_to_cpu(rxd->msdu_end.qca99x0.info1),
|
||||
RX_MSDU_END_INFO1_L3_HDR_PAD);
|
||||
}
|
||||
|
||||
static bool ath10k_qca99x0_rx_desc_msdu_limit_error(struct htt_rx_desc *rxd)
|
||||
{
|
||||
return !!(rxd->msdu_end.common.info0 &
|
||||
__cpu_to_le32(RX_MSDU_END_INFO0_MSDU_LIMIT_ERR));
|
||||
}
|
||||
|
||||
const struct ath10k_hw_ops qca99x0_ops = {
|
||||
.rx_desc_get_l3_pad_bytes = ath10k_qca99x0_rx_desc_get_l3_pad_bytes,
|
||||
.rx_desc_get_msdu_limit_error = ath10k_qca99x0_rx_desc_msdu_limit_error,
|
||||
.is_rssi_enable = ath10k_htt_tx_rssi_enable,
|
||||
};
|
||||
|
||||
|
@ -510,6 +510,8 @@ struct ath10k_hw_clk_params {
|
||||
u32 outdiv;
|
||||
};
|
||||
|
||||
struct htt_rx_desc_ops;
|
||||
|
||||
struct ath10k_hw_params {
|
||||
u32 id;
|
||||
u16 dev_id;
|
||||
@ -562,6 +564,9 @@ struct ath10k_hw_params {
|
||||
*/
|
||||
bool sw_decrypt_mcast_mgmt;
|
||||
|
||||
/* Rx descriptor abstraction */
|
||||
const struct ath10k_htt_rx_desc_ops *rx_desc_ops;
|
||||
|
||||
const struct ath10k_hw_ops *hw_ops;
|
||||
|
||||
/* Number of bytes used for alignment in rx_hdr_status of rx desc. */
|
||||
@ -630,16 +635,14 @@ struct ath10k_hw_params {
|
||||
bool dynamic_sar_support;
|
||||
};
|
||||
|
||||
struct htt_rx_desc;
|
||||
struct htt_resp;
|
||||
struct htt_data_tx_completion_ext;
|
||||
struct htt_rx_ring_rx_desc_offsets;
|
||||
|
||||
/* Defines needed for Rx descriptor abstraction */
|
||||
struct ath10k_hw_ops {
|
||||
int (*rx_desc_get_l3_pad_bytes)(struct htt_rx_desc *rxd);
|
||||
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);
|
||||
};
|
||||
@ -652,24 +655,6 @@ extern const struct ath10k_hw_ops wcn3990_ops;
|
||||
|
||||
extern const struct ath10k_hw_clk_params qca6174_clk[];
|
||||
|
||||
static inline int
|
||||
ath10k_rx_desc_get_l3_pad_bytes(struct ath10k_hw_params *hw,
|
||||
struct htt_rx_desc *rxd)
|
||||
{
|
||||
if (hw->hw_ops->rx_desc_get_l3_pad_bytes)
|
||||
return hw->hw_ops->rx_desc_get_l3_pad_bytes(rxd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
ath10k_rx_desc_msdu_limit_error(struct ath10k_hw_params *hw,
|
||||
struct htt_rx_desc *rxd)
|
||||
{
|
||||
if (hw->hw_ops->rx_desc_get_msdu_limit_error)
|
||||
return hw->hw_ops->rx_desc_get_msdu_limit_error(rxd);
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline int
|
||||
ath10k_tx_data_rssi_get_pad_bytes(struct ath10k_hw_params *hw,
|
||||
struct htt_resp *htt)
|
||||
|
@ -196,17 +196,31 @@ struct rx_attention {
|
||||
* descriptor.
|
||||
*/
|
||||
|
||||
struct rx_frag_info {
|
||||
struct rx_frag_info_common {
|
||||
u8 ring0_more_count;
|
||||
u8 ring1_more_count;
|
||||
u8 ring2_more_count;
|
||||
u8 ring3_more_count;
|
||||
} __packed;
|
||||
|
||||
struct rx_frag_info_wcn3990 {
|
||||
u8 ring4_more_count;
|
||||
u8 ring5_more_count;
|
||||
u8 ring6_more_count;
|
||||
u8 ring7_more_count;
|
||||
} __packed;
|
||||
|
||||
struct rx_frag_info {
|
||||
struct rx_frag_info_common common;
|
||||
union {
|
||||
struct rx_frag_info_wcn3990 wcn3990;
|
||||
} __packed;
|
||||
} __packed;
|
||||
|
||||
struct rx_frag_info_v1 {
|
||||
struct rx_frag_info_common common;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* ring0_more_count
|
||||
* Indicates the number of more buffers associated with RX DMA
|
||||
@ -474,11 +488,17 @@ struct rx_msdu_start_wcn3990 {
|
||||
struct rx_msdu_start {
|
||||
struct rx_msdu_start_common common;
|
||||
union {
|
||||
struct rx_msdu_start_qca99x0 qca99x0;
|
||||
struct rx_msdu_start_wcn3990 wcn3990;
|
||||
} __packed;
|
||||
} __packed;
|
||||
|
||||
struct rx_msdu_start_v1 {
|
||||
struct rx_msdu_start_common common;
|
||||
union {
|
||||
struct rx_msdu_start_qca99x0 qca99x0;
|
||||
} __packed;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* msdu_length
|
||||
* MSDU length in bytes after decapsulation. This field is
|
||||
@ -612,11 +632,17 @@ struct rx_msdu_end_wcn3990 {
|
||||
struct rx_msdu_end {
|
||||
struct rx_msdu_end_common common;
|
||||
union {
|
||||
struct rx_msdu_end_qca99x0 qca99x0;
|
||||
struct rx_msdu_end_wcn3990 wcn3990;
|
||||
} __packed;
|
||||
} __packed;
|
||||
|
||||
struct rx_msdu_end_v1 {
|
||||
struct rx_msdu_end_common common;
|
||||
union {
|
||||
struct rx_msdu_end_qca99x0 qca99x0;
|
||||
} __packed;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
*ip_hdr_chksum
|
||||
* This can include the IP header checksum or the pseudo header
|
||||
@ -1134,13 +1160,19 @@ struct rx_ppdu_end_wcn3990 {
|
||||
} __packed;
|
||||
|
||||
struct rx_ppdu_end {
|
||||
struct rx_ppdu_end_common common;
|
||||
union {
|
||||
struct rx_ppdu_end_wcn3990 wcn3990;
|
||||
} __packed;
|
||||
} __packed;
|
||||
|
||||
struct rx_ppdu_end_v1 {
|
||||
struct rx_ppdu_end_common common;
|
||||
union {
|
||||
struct rx_ppdu_end_qca988x qca988x;
|
||||
struct rx_ppdu_end_qca6174 qca6174;
|
||||
struct rx_ppdu_end_qca99x0 qca99x0;
|
||||
struct rx_ppdu_end_qca9984 qca9984;
|
||||
struct rx_ppdu_end_wcn3990 wcn3990;
|
||||
} __packed;
|
||||
} __packed;
|
||||
|
||||
|
@ -1306,13 +1306,10 @@ static int ath10k_snoc_resource_init(struct ath10k *ar)
|
||||
}
|
||||
|
||||
for (i = 0; i < CE_COUNT; i++) {
|
||||
res = platform_get_resource(ar_snoc->dev, IORESOURCE_IRQ, i);
|
||||
if (!res) {
|
||||
ath10k_err(ar, "failed to get IRQ%d\n", i);
|
||||
ret = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
ar_snoc->ce_irqs[i].irq_line = res->start;
|
||||
ret = platform_get_irq(ar_snoc->dev, i);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ar_snoc->ce_irqs[i].irq_line = ret;
|
||||
}
|
||||
|
||||
ret = device_property_read_u32(&pdev->dev, "qcom,xo-cal-data",
|
||||
@ -1323,10 +1320,8 @@ static int ath10k_snoc_resource_init(struct ath10k *ar)
|
||||
ath10k_dbg(ar, ATH10K_DBG_SNOC, "xo cal data %x\n",
|
||||
ar_snoc->xo_cal_data);
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath10k_snoc_quirks_init(struct ath10k *ar)
|
||||
|
@ -337,14 +337,15 @@ static int ath10k_vif_wow_set_wakeups(struct ath10k_vif *arvif,
|
||||
if (patterns[i].mask[j / 8] & BIT(j % 8))
|
||||
bitmask[j] = 0xff;
|
||||
old_pattern.mask = bitmask;
|
||||
new_pattern = old_pattern;
|
||||
|
||||
if (ar->wmi.rx_decap_mode == ATH10K_HW_TXRX_NATIVE_WIFI) {
|
||||
if (patterns[i].pkt_offset < ETH_HLEN)
|
||||
if (patterns[i].pkt_offset < ETH_HLEN) {
|
||||
ath10k_wow_convert_8023_to_80211(&new_pattern,
|
||||
&old_pattern);
|
||||
else
|
||||
} else {
|
||||
new_pattern = old_pattern;
|
||||
new_pattern.pkt_offset += WOW_HDR_LEN - ETH_HLEN;
|
||||
}
|
||||
}
|
||||
|
||||
if (WARN_ON(new_pattern.pattern_len > WOW_MAX_PATTERN_SIZE))
|
||||
|
@ -1,6 +1,7 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
@ -97,6 +98,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
||||
.wakeup_mhi = false,
|
||||
.supports_rssi_stats = false,
|
||||
.fw_wmi_diag_event = false,
|
||||
.current_cc_support = false,
|
||||
},
|
||||
{
|
||||
.hw_rev = ATH11K_HW_IPQ6018_HW10,
|
||||
@ -161,6 +163,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
||||
.wakeup_mhi = false,
|
||||
.supports_rssi_stats = false,
|
||||
.fw_wmi_diag_event = false,
|
||||
.current_cc_support = false,
|
||||
},
|
||||
{
|
||||
.name = "qca6390 hw2.0",
|
||||
@ -224,6 +227,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
||||
.wakeup_mhi = true,
|
||||
.supports_rssi_stats = true,
|
||||
.fw_wmi_diag_event = true,
|
||||
.current_cc_support = true,
|
||||
},
|
||||
{
|
||||
.name = "qcn9074 hw1.0",
|
||||
@ -287,6 +291,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
||||
.wakeup_mhi = false,
|
||||
.supports_rssi_stats = false,
|
||||
.fw_wmi_diag_event = false,
|
||||
.current_cc_support = false,
|
||||
},
|
||||
{
|
||||
.name = "wcn6855 hw2.0",
|
||||
@ -350,6 +355,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
||||
.wakeup_mhi = true,
|
||||
.supports_rssi_stats = true,
|
||||
.fw_wmi_diag_event = true,
|
||||
.current_cc_support = true,
|
||||
},
|
||||
{
|
||||
.name = "wcn6855 hw2.1",
|
||||
@ -412,6 +418,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
||||
.wakeup_mhi = true,
|
||||
.supports_rssi_stats = true,
|
||||
.fw_wmi_diag_event = true,
|
||||
.current_cc_support = true,
|
||||
},
|
||||
};
|
||||
|
||||
@ -1404,6 +1411,9 @@ EXPORT_SYMBOL(ath11k_core_deinit);
|
||||
|
||||
void ath11k_core_free(struct ath11k_base *ab)
|
||||
{
|
||||
flush_workqueue(ab->workqueue);
|
||||
destroy_workqueue(ab->workqueue);
|
||||
|
||||
kfree(ab);
|
||||
}
|
||||
EXPORT_SYMBOL(ath11k_core_free);
|
||||
|
@ -603,6 +603,7 @@ struct ath11k {
|
||||
struct completion finish_11d_ch_list;
|
||||
bool pending_11d;
|
||||
bool regdom_set_by_user;
|
||||
int hw_rate_code;
|
||||
};
|
||||
|
||||
struct ath11k_band_cap {
|
||||
|
@ -666,6 +666,12 @@ static ssize_t ath11k_write_extd_rx_stats(struct file *file,
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (test_bit(ATH11K_FLAG_MONITOR_STARTED, &ar->monitor_flags)) {
|
||||
ar->debug.extd_rx_stats = enable;
|
||||
ret = count;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (enable) {
|
||||
rx_filter = HTT_RX_FILTER_TLV_FLAGS_MPDU_START;
|
||||
rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_START;
|
||||
|
@ -42,6 +42,13 @@ static inline u8 ath11k_dp_rx_h_msdu_start_decap_type(struct ath11k_base *ab,
|
||||
return ab->hw_params.hw_ops->rx_desc_get_decap_type(desc);
|
||||
}
|
||||
|
||||
static inline
|
||||
bool ath11k_dp_rx_h_msdu_start_ldpc_support(struct ath11k_base *ab,
|
||||
struct hal_rx_desc *desc)
|
||||
{
|
||||
return ab->hw_params.hw_ops->rx_desc_get_ldpc_support(desc);
|
||||
}
|
||||
|
||||
static inline
|
||||
u8 ath11k_dp_rx_h_msdu_start_mesh_ctl_present(struct ath11k_base *ab,
|
||||
struct hal_rx_desc *desc)
|
||||
@ -2313,7 +2320,7 @@ static void ath11k_dp_rx_h_rate(struct ath11k *ar, struct hal_rx_desc *rx_desc,
|
||||
u8 bw;
|
||||
u8 rate_mcs, nss;
|
||||
u8 sgi;
|
||||
bool is_cck;
|
||||
bool is_cck, is_ldpc;
|
||||
|
||||
pkt_type = ath11k_dp_rx_h_msdu_start_pkt_type(ar->ab, rx_desc);
|
||||
bw = ath11k_dp_rx_h_msdu_start_rx_bw(ar->ab, rx_desc);
|
||||
@ -2355,6 +2362,9 @@ static void ath11k_dp_rx_h_rate(struct ath11k *ar, struct hal_rx_desc *rx_desc,
|
||||
if (sgi)
|
||||
rx_status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
|
||||
rx_status->bw = ath11k_mac_bw_to_mac80211_bw(bw);
|
||||
is_ldpc = ath11k_dp_rx_h_msdu_start_ldpc_support(ar->ab, rx_desc);
|
||||
if (is_ldpc)
|
||||
rx_status->enc_flags |= RX_ENC_FLAG_LDPC;
|
||||
break;
|
||||
case RX_MSDU_START_PKT_TYPE_11AX:
|
||||
rx_status->rate_idx = rate_mcs;
|
||||
@ -3080,79 +3090,6 @@ move_next:
|
||||
return num_buffs_reaped;
|
||||
}
|
||||
|
||||
int ath11k_dp_rx_process_mon_status(struct ath11k_base *ab, int mac_id,
|
||||
struct napi_struct *napi, int budget)
|
||||
{
|
||||
struct ath11k *ar = ath11k_ab_to_ar(ab, mac_id);
|
||||
enum hal_rx_mon_status hal_status;
|
||||
struct sk_buff *skb;
|
||||
struct sk_buff_head skb_list;
|
||||
struct hal_rx_mon_ppdu_info ppdu_info;
|
||||
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);
|
||||
|
||||
num_buffs_reaped = ath11k_dp_rx_reap_mon_status_ring(ab, mac_id, &budget,
|
||||
&skb_list);
|
||||
if (!num_buffs_reaped)
|
||||
goto exit;
|
||||
|
||||
memset(&ppdu_info, 0, sizeof(ppdu_info));
|
||||
ppdu_info.peer_id = HAL_INVALID_PEERID;
|
||||
|
||||
while ((skb = __skb_dequeue(&skb_list))) {
|
||||
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);
|
||||
|
||||
if (ppdu_info.peer_id == HAL_INVALID_PEERID ||
|
||||
hal_status != HAL_RX_MON_STATUS_PPDU_DONE) {
|
||||
dev_kfree_skb_any(skb);
|
||||
continue;
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
spin_lock_bh(&ab->base_lock);
|
||||
peer = ath11k_peer_find_by_id(ab, ppdu_info.peer_id);
|
||||
|
||||
if (!peer || !peer->sta) {
|
||||
ath11k_dbg(ab, ATH11K_DBG_DATA,
|
||||
"failed to find the peer with peer_id %d\n",
|
||||
ppdu_info.peer_id);
|
||||
goto next_skb;
|
||||
}
|
||||
|
||||
arsta = (struct ath11k_sta *)peer->sta->drv_priv;
|
||||
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, log_type, rx_buf_sz);
|
||||
|
||||
next_skb:
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
rcu_read_unlock();
|
||||
|
||||
dev_kfree_skb_any(skb);
|
||||
memset(&ppdu_info, 0, sizeof(ppdu_info));
|
||||
ppdu_info.peer_id = HAL_INVALID_PEERID;
|
||||
}
|
||||
exit:
|
||||
return num_buffs_reaped;
|
||||
}
|
||||
|
||||
static void ath11k_dp_rx_frag_timer(struct timer_list *timer)
|
||||
{
|
||||
struct dp_rx_tid *rx_tid = from_timer(rx_tid, timer, frag_timer);
|
||||
@ -5106,36 +5043,88 @@ static void ath11k_dp_rx_mon_dest_process(struct ath11k *ar, int mac_id,
|
||||
}
|
||||
}
|
||||
|
||||
static void ath11k_dp_rx_mon_status_process_tlv(struct ath11k *ar,
|
||||
int mac_id, u32 quota,
|
||||
struct napi_struct *napi)
|
||||
int ath11k_dp_rx_process_mon_status(struct ath11k_base *ab, int mac_id,
|
||||
struct napi_struct *napi, int budget)
|
||||
{
|
||||
struct ath11k_pdev_dp *dp = &ar->dp;
|
||||
struct ath11k_mon_data *pmon = (struct ath11k_mon_data *)&dp->mon_data;
|
||||
struct hal_rx_mon_ppdu_info *ppdu_info;
|
||||
struct sk_buff *status_skb;
|
||||
u32 tlv_status = HAL_TLV_STATUS_BUF_DONE;
|
||||
struct ath11k_pdev_mon_stats *rx_mon_stats;
|
||||
struct ath11k *ar = ath11k_ab_to_ar(ab, mac_id);
|
||||
enum hal_rx_mon_status hal_status;
|
||||
struct sk_buff *skb;
|
||||
struct sk_buff_head skb_list;
|
||||
struct ath11k_peer *peer;
|
||||
struct ath11k_sta *arsta;
|
||||
int num_buffs_reaped = 0;
|
||||
u32 rx_buf_sz;
|
||||
u16 log_type = 0;
|
||||
struct ath11k_mon_data *pmon = (struct ath11k_mon_data *)&ar->dp.mon_data;
|
||||
struct ath11k_pdev_mon_stats *rx_mon_stats = &pmon->rx_mon_stats;
|
||||
struct hal_rx_mon_ppdu_info *ppdu_info = &pmon->mon_ppdu_info;
|
||||
|
||||
ppdu_info = &pmon->mon_ppdu_info;
|
||||
rx_mon_stats = &pmon->rx_mon_stats;
|
||||
__skb_queue_head_init(&skb_list);
|
||||
|
||||
if (pmon->mon_ppdu_status != DP_PPDU_STATUS_START)
|
||||
return;
|
||||
num_buffs_reaped = ath11k_dp_rx_reap_mon_status_ring(ab, mac_id, &budget,
|
||||
&skb_list);
|
||||
if (!num_buffs_reaped)
|
||||
goto exit;
|
||||
|
||||
while (!skb_queue_empty(&pmon->rx_status_q)) {
|
||||
status_skb = skb_dequeue(&pmon->rx_status_q);
|
||||
memset(ppdu_info, 0, sizeof(*ppdu_info));
|
||||
ppdu_info->peer_id = HAL_INVALID_PEERID;
|
||||
|
||||
tlv_status = ath11k_hal_rx_parse_mon_status(ar->ab, ppdu_info,
|
||||
status_skb);
|
||||
if (tlv_status == HAL_TLV_STATUS_PPDU_DONE) {
|
||||
while ((skb = __skb_dequeue(&skb_list))) {
|
||||
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);
|
||||
|
||||
if (test_bit(ATH11K_FLAG_MONITOR_STARTED, &ar->monitor_flags) &&
|
||||
pmon->mon_ppdu_status == DP_PPDU_STATUS_START &&
|
||||
hal_status == HAL_TLV_STATUS_PPDU_DONE) {
|
||||
rx_mon_stats->status_ppdu_done++;
|
||||
pmon->mon_ppdu_status = DP_PPDU_STATUS_DONE;
|
||||
ath11k_dp_rx_mon_dest_process(ar, mac_id, quota, napi);
|
||||
ath11k_dp_rx_mon_dest_process(ar, mac_id, budget, napi);
|
||||
pmon->mon_ppdu_status = DP_PPDU_STATUS_START;
|
||||
}
|
||||
dev_kfree_skb_any(status_skb);
|
||||
|
||||
if (ppdu_info->peer_id == HAL_INVALID_PEERID ||
|
||||
hal_status != HAL_RX_MON_STATUS_PPDU_DONE) {
|
||||
dev_kfree_skb_any(skb);
|
||||
continue;
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
spin_lock_bh(&ab->base_lock);
|
||||
peer = ath11k_peer_find_by_id(ab, ppdu_info->peer_id);
|
||||
|
||||
if (!peer || !peer->sta) {
|
||||
ath11k_dbg(ab, ATH11K_DBG_DATA,
|
||||
"failed to find the peer with peer_id %d\n",
|
||||
ppdu_info->peer_id);
|
||||
goto next_skb;
|
||||
}
|
||||
|
||||
arsta = (struct ath11k_sta *)peer->sta->drv_priv;
|
||||
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, log_type, rx_buf_sz);
|
||||
|
||||
next_skb:
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
rcu_read_unlock();
|
||||
|
||||
dev_kfree_skb_any(skb);
|
||||
memset(ppdu_info, 0, sizeof(*ppdu_info));
|
||||
ppdu_info->peer_id = HAL_INVALID_PEERID;
|
||||
}
|
||||
exit:
|
||||
return num_buffs_reaped;
|
||||
}
|
||||
|
||||
static u32
|
||||
@ -5489,22 +5478,6 @@ reap_status_ring:
|
||||
return quota;
|
||||
}
|
||||
|
||||
static int ath11k_dp_mon_process_rx(struct ath11k_base *ab, int mac_id,
|
||||
struct napi_struct *napi, int budget)
|
||||
{
|
||||
struct ath11k *ar = ath11k_ab_to_ar(ab, mac_id);
|
||||
struct ath11k_pdev_dp *dp = &ar->dp;
|
||||
struct ath11k_mon_data *pmon = (struct ath11k_mon_data *)&dp->mon_data;
|
||||
int num_buffs_reaped = 0;
|
||||
|
||||
num_buffs_reaped = ath11k_dp_rx_reap_mon_status_ring(ar->ab, mac_id, &budget,
|
||||
&pmon->rx_status_q);
|
||||
if (num_buffs_reaped)
|
||||
ath11k_dp_rx_mon_status_process_tlv(ar, mac_id, budget, napi);
|
||||
|
||||
return num_buffs_reaped;
|
||||
}
|
||||
|
||||
int ath11k_dp_rx_process_mon_rings(struct ath11k_base *ab, int mac_id,
|
||||
struct napi_struct *napi, int budget)
|
||||
{
|
||||
@ -5514,8 +5487,6 @@ int ath11k_dp_rx_process_mon_rings(struct ath11k_base *ab, int mac_id,
|
||||
if (test_bit(ATH11K_FLAG_MONITOR_STARTED, &ar->monitor_flags) &&
|
||||
ab->hw_params.full_monitor_mode)
|
||||
ret = ath11k_dp_full_mon_process_rx(ab, mac_id, napi, budget);
|
||||
else 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);
|
||||
|
||||
|
@ -65,10 +65,6 @@ enum hal_rx_reception_type {
|
||||
HAL_RX_RECEPTION_TYPE_MAX,
|
||||
};
|
||||
|
||||
#define HAL_TLV_STATUS_PPDU_NOT_DONE 0
|
||||
#define HAL_TLV_STATUS_PPDU_DONE 1
|
||||
#define HAL_TLV_STATUS_BUF_DONE 2
|
||||
#define HAL_TLV_STATUS_PPDU_NON_STD_DONE 3
|
||||
#define HAL_RX_FCS_LEN 4
|
||||
|
||||
enum hal_rx_mon_status {
|
||||
@ -77,6 +73,10 @@ enum hal_rx_mon_status {
|
||||
HAL_RX_MON_STATUS_BUF_DONE,
|
||||
};
|
||||
|
||||
#define HAL_TLV_STATUS_PPDU_NOT_DONE HAL_RX_MON_STATUS_PPDU_NOT_DONE
|
||||
#define HAL_TLV_STATUS_PPDU_DONE HAL_RX_MON_STATUS_PPDU_DONE
|
||||
#define HAL_TLV_STATUS_BUF_DONE HAL_RX_MON_STATUS_BUF_DONE
|
||||
|
||||
struct hal_sw_mon_ring_entries {
|
||||
dma_addr_t mon_dst_paddr;
|
||||
dma_addr_t mon_status_paddr;
|
||||
|
@ -273,6 +273,12 @@ static u8 ath11k_hw_ipq8074_rx_desc_get_mesh_ctl(struct hal_rx_desc *desc)
|
||||
__le32_to_cpu(desc->u.ipq8074.msdu_start.info2));
|
||||
}
|
||||
|
||||
static bool ath11k_hw_ipq8074_rx_desc_get_ldpc_support(struct hal_rx_desc *desc)
|
||||
{
|
||||
return FIELD_GET(RX_MSDU_START_INFO2_LDPC,
|
||||
__le32_to_cpu(desc->u.ipq8074.msdu_start.info2));
|
||||
}
|
||||
|
||||
static bool ath11k_hw_ipq8074_rx_desc_get_mpdu_seq_ctl_vld(struct hal_rx_desc *desc)
|
||||
{
|
||||
return !!FIELD_GET(RX_MPDU_START_INFO1_MPDU_SEQ_CTRL_VALID,
|
||||
@ -444,6 +450,12 @@ static u8 ath11k_hw_qcn9074_rx_desc_get_mesh_ctl(struct hal_rx_desc *desc)
|
||||
__le32_to_cpu(desc->u.qcn9074.msdu_start.info2));
|
||||
}
|
||||
|
||||
static bool ath11k_hw_qcn9074_rx_desc_get_ldpc_support(struct hal_rx_desc *desc)
|
||||
{
|
||||
return FIELD_GET(RX_MSDU_START_INFO2_LDPC,
|
||||
__le32_to_cpu(desc->u.qcn9074.msdu_start.info2));
|
||||
}
|
||||
|
||||
static bool ath11k_hw_qcn9074_rx_desc_get_mpdu_seq_ctl_vld(struct hal_rx_desc *desc)
|
||||
{
|
||||
return !!FIELD_GET(RX_MPDU_START_INFO11_MPDU_SEQ_CTRL_VALID,
|
||||
@ -815,6 +827,7 @@ const struct ath11k_hw_ops ipq8074_ops = {
|
||||
.rx_desc_get_encrypt_type = ath11k_hw_ipq8074_rx_desc_get_encrypt_type,
|
||||
.rx_desc_get_decap_type = ath11k_hw_ipq8074_rx_desc_get_decap_type,
|
||||
.rx_desc_get_mesh_ctl = ath11k_hw_ipq8074_rx_desc_get_mesh_ctl,
|
||||
.rx_desc_get_ldpc_support = ath11k_hw_ipq8074_rx_desc_get_ldpc_support,
|
||||
.rx_desc_get_mpdu_seq_ctl_vld = ath11k_hw_ipq8074_rx_desc_get_mpdu_seq_ctl_vld,
|
||||
.rx_desc_get_mpdu_fc_valid = ath11k_hw_ipq8074_rx_desc_get_mpdu_fc_valid,
|
||||
.rx_desc_get_mpdu_start_seq_no = ath11k_hw_ipq8074_rx_desc_get_mpdu_start_seq_no,
|
||||
@ -853,6 +866,7 @@ const struct ath11k_hw_ops ipq6018_ops = {
|
||||
.rx_desc_get_encrypt_type = ath11k_hw_ipq8074_rx_desc_get_encrypt_type,
|
||||
.rx_desc_get_decap_type = ath11k_hw_ipq8074_rx_desc_get_decap_type,
|
||||
.rx_desc_get_mesh_ctl = ath11k_hw_ipq8074_rx_desc_get_mesh_ctl,
|
||||
.rx_desc_get_ldpc_support = ath11k_hw_ipq8074_rx_desc_get_ldpc_support,
|
||||
.rx_desc_get_mpdu_seq_ctl_vld = ath11k_hw_ipq8074_rx_desc_get_mpdu_seq_ctl_vld,
|
||||
.rx_desc_get_mpdu_fc_valid = ath11k_hw_ipq8074_rx_desc_get_mpdu_fc_valid,
|
||||
.rx_desc_get_mpdu_start_seq_no = ath11k_hw_ipq8074_rx_desc_get_mpdu_start_seq_no,
|
||||
@ -891,6 +905,7 @@ const struct ath11k_hw_ops qca6390_ops = {
|
||||
.rx_desc_get_encrypt_type = ath11k_hw_ipq8074_rx_desc_get_encrypt_type,
|
||||
.rx_desc_get_decap_type = ath11k_hw_ipq8074_rx_desc_get_decap_type,
|
||||
.rx_desc_get_mesh_ctl = ath11k_hw_ipq8074_rx_desc_get_mesh_ctl,
|
||||
.rx_desc_get_ldpc_support = ath11k_hw_ipq8074_rx_desc_get_ldpc_support,
|
||||
.rx_desc_get_mpdu_seq_ctl_vld = ath11k_hw_ipq8074_rx_desc_get_mpdu_seq_ctl_vld,
|
||||
.rx_desc_get_mpdu_fc_valid = ath11k_hw_ipq8074_rx_desc_get_mpdu_fc_valid,
|
||||
.rx_desc_get_mpdu_start_seq_no = ath11k_hw_ipq8074_rx_desc_get_mpdu_start_seq_no,
|
||||
@ -929,6 +944,7 @@ const struct ath11k_hw_ops qcn9074_ops = {
|
||||
.rx_desc_get_encrypt_type = ath11k_hw_qcn9074_rx_desc_get_encrypt_type,
|
||||
.rx_desc_get_decap_type = ath11k_hw_qcn9074_rx_desc_get_decap_type,
|
||||
.rx_desc_get_mesh_ctl = ath11k_hw_qcn9074_rx_desc_get_mesh_ctl,
|
||||
.rx_desc_get_ldpc_support = ath11k_hw_qcn9074_rx_desc_get_ldpc_support,
|
||||
.rx_desc_get_mpdu_seq_ctl_vld = ath11k_hw_qcn9074_rx_desc_get_mpdu_seq_ctl_vld,
|
||||
.rx_desc_get_mpdu_fc_valid = ath11k_hw_qcn9074_rx_desc_get_mpdu_fc_valid,
|
||||
.rx_desc_get_mpdu_start_seq_no = ath11k_hw_qcn9074_rx_desc_get_mpdu_start_seq_no,
|
||||
|
@ -192,6 +192,7 @@ struct ath11k_hw_params {
|
||||
bool wakeup_mhi;
|
||||
bool supports_rssi_stats;
|
||||
bool fw_wmi_diag_event;
|
||||
bool current_cc_support;
|
||||
};
|
||||
|
||||
struct ath11k_hw_ops {
|
||||
@ -210,6 +211,7 @@ struct ath11k_hw_ops {
|
||||
u32 (*rx_desc_get_encrypt_type)(struct hal_rx_desc *desc);
|
||||
u8 (*rx_desc_get_decap_type)(struct hal_rx_desc *desc);
|
||||
u8 (*rx_desc_get_mesh_ctl)(struct hal_rx_desc *desc);
|
||||
bool (*rx_desc_get_ldpc_support)(struct hal_rx_desc *desc);
|
||||
bool (*rx_desc_get_mpdu_seq_ctl_vld)(struct hal_rx_desc *desc);
|
||||
bool (*rx_desc_get_mpdu_fc_valid)(struct hal_rx_desc *desc);
|
||||
u16 (*rx_desc_get_mpdu_start_seq_no)(struct hal_rx_desc *desc);
|
||||
|
@ -2319,6 +2319,9 @@ static void ath11k_peer_assoc_h_he_6ghz(struct ath11k *ar,
|
||||
if (!arg->he_flag || band != NL80211_BAND_6GHZ || !sta->he_6ghz_capa.capa)
|
||||
return;
|
||||
|
||||
if (sta->bandwidth == IEEE80211_STA_RX_BW_40)
|
||||
arg->bw_40 = true;
|
||||
|
||||
if (sta->bandwidth == IEEE80211_STA_RX_BW_80)
|
||||
arg->bw_80 = true;
|
||||
|
||||
@ -2862,6 +2865,11 @@ static void ath11k_recalculate_mgmt_rate(struct ath11k *ar,
|
||||
if (ret)
|
||||
ath11k_warn(ar->ab, "failed to set mgmt tx rate %d\n", ret);
|
||||
|
||||
/* For WCN6855, firmware will clear this param when vdev starts, hence
|
||||
* cache it here so that we can reconfigure it once vdev starts.
|
||||
*/
|
||||
ar->hw_rate_code = hw_rate_code;
|
||||
|
||||
vdev_param = WMI_VDEV_PARAM_BEACON_RATE;
|
||||
ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, vdev_param,
|
||||
hw_rate_code);
|
||||
@ -4504,24 +4512,30 @@ static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw,
|
||||
sta->addr, arvif->vdev_id);
|
||||
} else if ((old_state == IEEE80211_STA_NONE &&
|
||||
new_state == IEEE80211_STA_NOTEXIST)) {
|
||||
bool skip_peer_delete = ar->ab->hw_params.vdev_start_delay &&
|
||||
vif->type == NL80211_IFTYPE_STATION;
|
||||
|
||||
ath11k_dp_peer_cleanup(ar, arvif->vdev_id, sta->addr);
|
||||
|
||||
if (ar->ab->hw_params.vdev_start_delay &&
|
||||
vif->type == NL80211_IFTYPE_STATION)
|
||||
goto free;
|
||||
|
||||
ret = ath11k_peer_delete(ar, arvif->vdev_id, sta->addr);
|
||||
if (ret)
|
||||
ath11k_warn(ar->ab, "Failed to delete peer: %pM for VDEV: %d\n",
|
||||
sta->addr, arvif->vdev_id);
|
||||
else
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "Removed peer: %pM for VDEV: %d\n",
|
||||
sta->addr, arvif->vdev_id);
|
||||
if (!skip_peer_delete) {
|
||||
ret = ath11k_peer_delete(ar, arvif->vdev_id, sta->addr);
|
||||
if (ret)
|
||||
ath11k_warn(ar->ab,
|
||||
"Failed to delete peer: %pM for VDEV: %d\n",
|
||||
sta->addr, arvif->vdev_id);
|
||||
else
|
||||
ath11k_dbg(ar->ab,
|
||||
ATH11K_DBG_MAC,
|
||||
"Removed peer: %pM for VDEV: %d\n",
|
||||
sta->addr, arvif->vdev_id);
|
||||
}
|
||||
|
||||
ath11k_mac_dec_num_stations(arvif, sta);
|
||||
spin_lock_bh(&ar->ab->base_lock);
|
||||
peer = ath11k_peer_find(ar->ab, arvif->vdev_id, sta->addr);
|
||||
if (peer && peer->sta == sta) {
|
||||
if (skip_peer_delete && peer) {
|
||||
peer->sta = NULL;
|
||||
} else if (peer && peer->sta == sta) {
|
||||
ath11k_warn(ar->ab, "Found peer entry %pM n vdev %i after it was supposedly removed\n",
|
||||
vif->addr, arvif->vdev_id);
|
||||
peer->sta = NULL;
|
||||
@ -4531,7 +4545,6 @@ static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw,
|
||||
}
|
||||
spin_unlock_bh(&ar->ab->base_lock);
|
||||
|
||||
free:
|
||||
kfree(arsta->tx_stats);
|
||||
arsta->tx_stats = NULL;
|
||||
|
||||
@ -6955,6 +6968,19 @@ static int ath11k_start_vdev_delay(struct ieee80211_hw *hw,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Reconfigure hardware rate code since it is cleared by firmware.
|
||||
*/
|
||||
if (ar->hw_rate_code > 0) {
|
||||
u32 vdev_param = WMI_VDEV_PARAM_MGMT_RATE;
|
||||
|
||||
ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, vdev_param,
|
||||
ar->hw_rate_code);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to set mgmt tx rate %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
|
||||
ret = ath11k_wmi_vdev_up(ar, arvif->vdev_id, 0, ar->mac_addr);
|
||||
if (ret) {
|
||||
|
@ -332,6 +332,7 @@ static int ath11k_mhi_read_addr_from_dt(struct mhi_controller *mhi_ctrl)
|
||||
return -ENOENT;
|
||||
|
||||
ret = of_address_to_resource(np, 0, &res);
|
||||
of_node_put(np);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -252,7 +252,7 @@ int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif,
|
||||
{
|
||||
struct ath11k_peer *peer;
|
||||
struct ath11k_sta *arsta;
|
||||
int ret;
|
||||
int ret, fbret;
|
||||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
@ -291,22 +291,8 @@ int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif,
|
||||
ath11k_warn(ar->ab, "failed to find peer %pM on vdev %i after creation\n",
|
||||
param->peer_addr, param->vdev_id);
|
||||
|
||||
reinit_completion(&ar->peer_delete_done);
|
||||
|
||||
ret = ath11k_wmi_send_peer_delete_cmd(ar, param->peer_addr,
|
||||
param->vdev_id);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to delete peer vdev_id %d addr %pM\n",
|
||||
param->vdev_id, param->peer_addr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ath11k_wait_for_peer_delete_done(ar, param->vdev_id,
|
||||
param->peer_addr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return -ENOENT;
|
||||
ret = -ENOENT;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
peer->pdev_idx = ar->pdev_idx;
|
||||
@ -335,4 +321,24 @@ int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif,
|
||||
spin_unlock_bh(&ar->ab->base_lock);
|
||||
|
||||
return 0;
|
||||
|
||||
cleanup:
|
||||
reinit_completion(&ar->peer_delete_done);
|
||||
|
||||
fbret = ath11k_wmi_send_peer_delete_cmd(ar, param->peer_addr,
|
||||
param->vdev_id);
|
||||
if (fbret) {
|
||||
ath11k_warn(ar->ab, "failed to delete peer vdev_id %d addr %pM\n",
|
||||
param->vdev_id, param->peer_addr);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
fbret = ath11k_wait_for_peer_delete_done(ar, param->vdev_id,
|
||||
param->peer_addr);
|
||||
if (fbret)
|
||||
ath11k_warn(ar->ab, "failed wait for peer %pM delete done id %d fallback ret %d\n",
|
||||
param->peer_addr, param->vdev_id, fbret);
|
||||
|
||||
exit:
|
||||
return ret;
|
||||
}
|
||||
|
@ -1932,10 +1932,11 @@ static int ath11k_qmi_assign_target_mem_chunk(struct ath11k_base *ab)
|
||||
if (!hremote_node) {
|
||||
ath11k_dbg(ab, ATH11K_DBG_QMI,
|
||||
"qmi fail to get hremote_node\n");
|
||||
return ret;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = of_address_to_resource(hremote_node, 0, &res);
|
||||
of_node_put(hremote_node);
|
||||
if (ret) {
|
||||
ath11k_dbg(ab, ATH11K_DBG_QMI,
|
||||
"qmi fail to get reg from hremote\n");
|
||||
|
@ -48,6 +48,7 @@ ath11k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
|
||||
{
|
||||
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
|
||||
struct wmi_init_country_params init_country_param;
|
||||
struct wmi_set_current_country_params set_current_param = {};
|
||||
struct ath11k *ar = hw->priv;
|
||||
int ret;
|
||||
|
||||
@ -76,18 +77,26 @@ ath11k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set the country code to the firmware and wait for
|
||||
/* Set the country code to the firmware and will receive
|
||||
* the WMI_REG_CHAN_LIST_CC EVENT for updating the
|
||||
* reg info
|
||||
*/
|
||||
init_country_param.flags = ALPHA_IS_SET;
|
||||
memcpy(&init_country_param.cc_info.alpha2, request->alpha2, 2);
|
||||
init_country_param.cc_info.alpha2[2] = 0;
|
||||
if (ar->ab->hw_params.current_cc_support) {
|
||||
memcpy(&set_current_param.alpha2, request->alpha2, 2);
|
||||
ret = ath11k_wmi_send_set_current_country_cmd(ar, &set_current_param);
|
||||
if (ret)
|
||||
ath11k_warn(ar->ab,
|
||||
"failed set current country code: %d\n", ret);
|
||||
} else {
|
||||
init_country_param.flags = ALPHA_IS_SET;
|
||||
memcpy(&init_country_param.cc_info.alpha2, request->alpha2, 2);
|
||||
init_country_param.cc_info.alpha2[2] = 0;
|
||||
|
||||
ret = ath11k_wmi_send_init_country_cmd(ar, init_country_param);
|
||||
if (ret)
|
||||
ath11k_warn(ar->ab,
|
||||
"INIT Country code set to fw failed : %d\n", ret);
|
||||
ret = ath11k_wmi_send_init_country_cmd(ar, init_country_param);
|
||||
if (ret)
|
||||
ath11k_warn(ar->ab,
|
||||
"INIT Country code set to fw failed : %d\n", ret);
|
||||
}
|
||||
|
||||
ath11k_mac_11d_scan_stop(ar);
|
||||
ar->regdom_set_by_user = true;
|
||||
|
@ -1395,10 +1395,6 @@ struct ath5k_hw {
|
||||
u32 ah_txq_imr_nofrm;
|
||||
|
||||
u32 ah_txq_isr_txok_all;
|
||||
u32 ah_txq_isr_txurn;
|
||||
u32 ah_txq_isr_qcborn;
|
||||
u32 ah_txq_isr_qcburn;
|
||||
u32 ah_txq_isr_qtrig;
|
||||
|
||||
u32 *ah_rf_banks;
|
||||
size_t ah_rf_banks_size;
|
||||
|
@ -650,6 +650,7 @@ ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask)
|
||||
*/
|
||||
*interrupt_mask = (pisr & AR5K_INT_COMMON) & ah->ah_imr;
|
||||
|
||||
ah->ah_txq_isr_txok_all = 0;
|
||||
|
||||
/* We treat TXOK,TXDESC, TXERR and TXEOL
|
||||
* the same way (schedule the tx tasklet)
|
||||
@ -670,13 +671,6 @@ ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask)
|
||||
ah->ah_txq_isr_txok_all |= AR5K_REG_MS(sisr1,
|
||||
AR5K_SISR1_QCU_TXEOL);
|
||||
|
||||
/* Currently this is not much useful since we treat
|
||||
* all queues the same way if we get a TXURN (update
|
||||
* tx trigger level) but we might need it later on*/
|
||||
if (pisr & AR5K_ISR_TXURN)
|
||||
ah->ah_txq_isr_txurn |= AR5K_REG_MS(sisr2,
|
||||
AR5K_SISR2_QCU_TXURN);
|
||||
|
||||
/* Misc Beacon related interrupts */
|
||||
|
||||
/* For AR5211 */
|
||||
@ -709,25 +703,16 @@ ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask)
|
||||
*interrupt_mask |= AR5K_INT_BNR;
|
||||
|
||||
/* A queue got CBR overrun */
|
||||
if (unlikely(pisr & (AR5K_ISR_QCBRORN))) {
|
||||
if (unlikely(pisr & (AR5K_ISR_QCBRORN)))
|
||||
*interrupt_mask |= AR5K_INT_QCBRORN;
|
||||
ah->ah_txq_isr_qcborn |= AR5K_REG_MS(sisr3,
|
||||
AR5K_SISR3_QCBRORN);
|
||||
}
|
||||
|
||||
/* A queue got CBR underrun */
|
||||
if (unlikely(pisr & (AR5K_ISR_QCBRURN))) {
|
||||
if (unlikely(pisr & (AR5K_ISR_QCBRURN)))
|
||||
*interrupt_mask |= AR5K_INT_QCBRURN;
|
||||
ah->ah_txq_isr_qcburn |= AR5K_REG_MS(sisr3,
|
||||
AR5K_SISR3_QCBRURN);
|
||||
}
|
||||
|
||||
/* A queue got triggered */
|
||||
if (unlikely(pisr & (AR5K_ISR_QTRIG))) {
|
||||
if (unlikely(pisr & (AR5K_ISR_QTRIG)))
|
||||
*interrupt_mask |= AR5K_INT_QTRIG;
|
||||
ah->ah_txq_isr_qtrig |= AR5K_REG_MS(sisr4,
|
||||
AR5K_SISR4_QTRIG);
|
||||
}
|
||||
|
||||
data = pisr;
|
||||
}
|
||||
|
@ -746,6 +746,9 @@ ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode,
|
||||
}
|
||||
}
|
||||
|
||||
if (idx == AR5K_EEPROM_N_PD_CURVES)
|
||||
goto err_out;
|
||||
|
||||
ee->ee_pd_gains[mode] = 1;
|
||||
|
||||
pd = &chinfo[pier].pd_curves[idx];
|
||||
|
@ -670,8 +670,6 @@ void ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hw *ah,
|
||||
|
||||
int ath9k_hw_eeprom_init(struct ath_hw *ah)
|
||||
{
|
||||
int status;
|
||||
|
||||
if (AR_SREV_9300_20_OR_LATER(ah))
|
||||
ah->eep_ops = &eep_ar9300_ops;
|
||||
else if (AR_SREV_9287(ah)) {
|
||||
@ -685,7 +683,5 @@ int ath9k_hw_eeprom_init(struct ath_hw *ah)
|
||||
if (!ah->eep_ops->fill_eeprom(ah))
|
||||
return -EIO;
|
||||
|
||||
status = ah->eep_ops->check_eeprom(ah);
|
||||
|
||||
return status;
|
||||
return ah->eep_ops->check_eeprom(ah);
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ static int htc_issue_send(struct htc_target *target, struct sk_buff* skb,
|
||||
hdr->endpoint_id = epid;
|
||||
hdr->flags = flags;
|
||||
hdr->payload_len = cpu_to_be16(len);
|
||||
memset(hdr->control, 0, sizeof(hdr->control));
|
||||
|
||||
status = target->hif->send(target->hif_dev, endpoint->ul_pipeid, skb);
|
||||
|
||||
@ -272,6 +273,10 @@ int htc_connect_service(struct htc_target *target,
|
||||
conn_msg->dl_pipeid = endpoint->dl_pipeid;
|
||||
conn_msg->ul_pipeid = endpoint->ul_pipeid;
|
||||
|
||||
/* To prevent infoleak */
|
||||
conn_msg->svc_meta_len = 0;
|
||||
conn_msg->pad = 0;
|
||||
|
||||
ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
@ -197,7 +197,7 @@ static void channel_detector_exit(struct dfs_pattern_detector *dpd,
|
||||
static struct channel_detector *
|
||||
channel_detector_create(struct dfs_pattern_detector *dpd, u16 freq)
|
||||
{
|
||||
u32 sz, i;
|
||||
u32 i;
|
||||
struct channel_detector *cd;
|
||||
|
||||
cd = kmalloc(sizeof(*cd), GFP_ATOMIC);
|
||||
@ -206,8 +206,8 @@ channel_detector_create(struct dfs_pattern_detector *dpd, u16 freq)
|
||||
|
||||
INIT_LIST_HEAD(&cd->head);
|
||||
cd->freq = freq;
|
||||
sz = sizeof(cd->detectors) * dpd->num_radar_types;
|
||||
cd->detectors = kzalloc(sz, GFP_ATOMIC);
|
||||
cd->detectors = kmalloc_array(dpd->num_radar_types,
|
||||
sizeof(*cd->detectors), GFP_ATOMIC);
|
||||
if (cd->detectors == NULL)
|
||||
goto fail;
|
||||
|
||||
|
@ -331,6 +331,7 @@ static int wcn36xx_start(struct ieee80211_hw *hw)
|
||||
|
||||
INIT_LIST_HEAD(&wcn->vif_list);
|
||||
spin_lock_init(&wcn->dxe_lock);
|
||||
spin_lock_init(&wcn->survey_lock);
|
||||
|
||||
return 0;
|
||||
|
||||
@ -392,11 +393,41 @@ static void wcn36xx_change_opchannel(struct wcn36xx *wcn, int ch)
|
||||
{
|
||||
struct ieee80211_vif *vif = NULL;
|
||||
struct wcn36xx_vif *tmp;
|
||||
struct ieee80211_supported_band *band;
|
||||
struct ieee80211_channel *channel;
|
||||
unsigned long flags;
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(wcn->hw->wiphy->bands); i++) {
|
||||
band = wcn->hw->wiphy->bands[i];
|
||||
if (!band)
|
||||
break;
|
||||
for (j = 0; j < band->n_channels; j++) {
|
||||
if (HW_VALUE_CHANNEL(band->channels[j].hw_value) == ch) {
|
||||
channel = &band->channels[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (channel)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!channel) {
|
||||
wcn36xx_err("Cannot tune to channel %d\n", ch);
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&wcn->survey_lock, flags);
|
||||
wcn->band = band;
|
||||
wcn->channel = channel;
|
||||
spin_unlock_irqrestore(&wcn->survey_lock, flags);
|
||||
|
||||
list_for_each_entry(tmp, &wcn->vif_list, list) {
|
||||
vif = wcn36xx_priv_to_vif(tmp);
|
||||
wcn36xx_smd_switch_channel(wcn, vif, ch);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed)
|
||||
@ -1326,6 +1357,49 @@ static void wcn36xx_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
}
|
||||
}
|
||||
|
||||
static int wcn36xx_get_survey(struct ieee80211_hw *hw, int idx,
|
||||
struct survey_info *survey)
|
||||
{
|
||||
struct wcn36xx *wcn = hw->priv;
|
||||
struct ieee80211_supported_band *sband;
|
||||
struct wcn36xx_chan_survey *chan_survey;
|
||||
int band_idx;
|
||||
unsigned long flags;
|
||||
|
||||
sband = wcn->hw->wiphy->bands[NL80211_BAND_2GHZ];
|
||||
band_idx = idx;
|
||||
if (band_idx >= sband->n_channels) {
|
||||
band_idx -= sband->n_channels;
|
||||
sband = wcn->hw->wiphy->bands[NL80211_BAND_5GHZ];
|
||||
}
|
||||
|
||||
if (!sband || band_idx >= sband->n_channels)
|
||||
return -ENOENT;
|
||||
|
||||
spin_lock_irqsave(&wcn->survey_lock, flags);
|
||||
|
||||
chan_survey = &wcn->chan_survey[idx];
|
||||
survey->channel = &sband->channels[band_idx];
|
||||
survey->noise = chan_survey->rssi - chan_survey->snr;
|
||||
survey->filled = 0;
|
||||
|
||||
if (chan_survey->rssi > -100 && chan_survey->rssi < 0)
|
||||
survey->filled |= SURVEY_INFO_NOISE_DBM;
|
||||
|
||||
if (survey->channel == wcn->channel)
|
||||
survey->filled |= SURVEY_INFO_IN_USE;
|
||||
|
||||
spin_unlock_irqrestore(&wcn->survey_lock, flags);
|
||||
|
||||
wcn36xx_dbg(WCN36XX_DBG_MAC,
|
||||
"ch %d rssi %d snr %d noise %d filled %x freq %d\n",
|
||||
HW_VALUE_CHANNEL(survey->channel->hw_value),
|
||||
chan_survey->rssi, chan_survey->snr, survey->noise,
|
||||
survey->filled, survey->channel->center_freq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ieee80211_ops wcn36xx_ops = {
|
||||
.start = wcn36xx_start,
|
||||
.stop = wcn36xx_stop,
|
||||
@ -1354,6 +1428,7 @@ static const struct ieee80211_ops wcn36xx_ops = {
|
||||
.ipv6_addr_change = wcn36xx_ipv6_addr_change,
|
||||
#endif
|
||||
.flush = wcn36xx_flush,
|
||||
.get_survey = wcn36xx_get_survey,
|
||||
|
||||
CFG80211_TESTMODE_CMD(wcn36xx_tm_cmd)
|
||||
};
|
||||
@ -1446,25 +1521,20 @@ static int wcn36xx_platform_get_resources(struct wcn36xx *wcn,
|
||||
{
|
||||
struct device_node *mmio_node;
|
||||
struct device_node *iris_node;
|
||||
struct resource *res;
|
||||
int index;
|
||||
int ret;
|
||||
|
||||
/* Set TX IRQ */
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "tx");
|
||||
if (!res) {
|
||||
wcn36xx_err("failed to get tx_irq\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
wcn->tx_irq = res->start;
|
||||
ret = platform_get_irq_byname(pdev, "tx");
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
wcn->tx_irq = ret;
|
||||
|
||||
/* Set RX IRQ */
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "rx");
|
||||
if (!res) {
|
||||
wcn36xx_err("failed to get rx_irq\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
wcn->rx_irq = res->start;
|
||||
ret = platform_get_irq_byname(pdev, "rx");
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
wcn->rx_irq = ret;
|
||||
|
||||
/* Acquire SMSM tx enable handle */
|
||||
wcn->tx_enable_state = qcom_smem_state_get(&pdev->dev,
|
||||
@ -1535,6 +1605,7 @@ static int wcn36xx_probe(struct platform_device *pdev)
|
||||
void *wcnss;
|
||||
int ret;
|
||||
const u8 *addr;
|
||||
int n_channels;
|
||||
|
||||
wcn36xx_dbg(WCN36XX_DBG_MAC, "platform probe\n");
|
||||
|
||||
@ -1562,6 +1633,13 @@ static int wcn36xx_probe(struct platform_device *pdev)
|
||||
goto out_wq;
|
||||
}
|
||||
|
||||
n_channels = wcn_band_2ghz.n_channels + wcn_band_5ghz.n_channels;
|
||||
wcn->chan_survey = devm_kmalloc(wcn->dev, n_channels, GFP_KERNEL);
|
||||
if (!wcn->chan_survey) {
|
||||
ret = -ENOMEM;
|
||||
goto out_wq;
|
||||
}
|
||||
|
||||
ret = dma_set_mask_and_coherent(wcn->dev, DMA_BIT_MASK(32));
|
||||
if (ret < 0) {
|
||||
wcn36xx_err("failed to set DMA mask: %d\n", ret);
|
||||
|
@ -23,6 +23,11 @@ static inline int get_rssi0(struct wcn36xx_rx_bd *bd)
|
||||
return 100 - ((bd->phy_stat0 >> 24) & 0xff);
|
||||
}
|
||||
|
||||
static inline int get_snr(struct wcn36xx_rx_bd *bd)
|
||||
{
|
||||
return ((bd->phy_stat1 >> 24) & 0xff);
|
||||
}
|
||||
|
||||
struct wcn36xx_rate {
|
||||
u16 bitrate;
|
||||
u16 mcs_or_legacy_index;
|
||||
@ -266,6 +271,34 @@ static void __skb_queue_purge_irq(struct sk_buff_head *list)
|
||||
dev_kfree_skb_irq(skb);
|
||||
}
|
||||
|
||||
static void wcn36xx_update_survey(struct wcn36xx *wcn, int rssi, int snr,
|
||||
int band, int freq)
|
||||
{
|
||||
static struct ieee80211_channel *channel;
|
||||
struct ieee80211_supported_band *sband;
|
||||
int idx;
|
||||
int i;
|
||||
|
||||
idx = 0;
|
||||
if (band == NL80211_BAND_5GHZ)
|
||||
idx = wcn->hw->wiphy->bands[NL80211_BAND_2GHZ]->n_channels;
|
||||
|
||||
sband = wcn->hw->wiphy->bands[band];
|
||||
channel = sband->channels;
|
||||
|
||||
for (i = 0; i < sband->n_channels; i++, channel++) {
|
||||
if (channel->center_freq == freq) {
|
||||
idx += i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock(&wcn->survey_lock);
|
||||
wcn->chan_survey[idx].rssi = rssi;
|
||||
wcn->chan_survey[idx].snr = snr;
|
||||
spin_unlock(&wcn->survey_lock);
|
||||
}
|
||||
|
||||
int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_rx_status status;
|
||||
@ -343,6 +376,9 @@ int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb)
|
||||
status.freq = WCN36XX_CENTER_FREQ(wcn);
|
||||
}
|
||||
|
||||
wcn36xx_update_survey(wcn, status.signal, get_snr(bd),
|
||||
status.band, status.freq);
|
||||
|
||||
if (bd->rate_id < ARRAY_SIZE(wcn36xx_rate_table)) {
|
||||
rate = &wcn36xx_rate_table[bd->rate_id];
|
||||
status.encoding = rate->encoding;
|
||||
|
@ -194,7 +194,14 @@ struct wcn36xx_sta {
|
||||
enum wcn36xx_ampdu_state ampdu_state[16];
|
||||
int non_agg_frame_ct;
|
||||
};
|
||||
|
||||
struct wcn36xx_dxe_ch;
|
||||
|
||||
struct wcn36xx_chan_survey {
|
||||
s8 rssi;
|
||||
u8 snr;
|
||||
};
|
||||
|
||||
struct wcn36xx {
|
||||
struct ieee80211_hw *hw;
|
||||
struct device *dev;
|
||||
@ -281,6 +288,12 @@ struct wcn36xx {
|
||||
/* Debug file system entry */
|
||||
struct wcn36xx_dfs_entry dfs;
|
||||
#endif /* CONFIG_WCN36XX_DEBUGFS */
|
||||
|
||||
struct ieee80211_supported_band *band;
|
||||
struct ieee80211_channel *channel;
|
||||
|
||||
spinlock_t survey_lock; /* protects chan_survey */
|
||||
struct wcn36xx_chan_survey *chan_survey;
|
||||
};
|
||||
|
||||
static inline bool wcn36xx_is_fw_version(struct wcn36xx *wcn,
|
||||
|
Loading…
Reference in New Issue
Block a user