diff --git a/core.c b/core.c index 72a366a..abbd67d 100644 --- a/core.c +++ b/core.c @@ -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, @@ -110,6 +111,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, @@ -146,6 +148,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, @@ -181,6 +184,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, @@ -212,6 +216,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, @@ -247,6 +252,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, @@ -282,6 +288,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, @@ -318,6 +325,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, @@ -362,6 +370,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, @@ -406,6 +415,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, @@ -451,6 +461,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, @@ -490,6 +501,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, @@ -525,6 +537,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, @@ -562,6 +575,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, @@ -597,6 +611,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, @@ -628,6 +643,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, diff --git a/htt.c b/htt.c index 127b4e4..e21fccb 100644 --- a/htt.c +++ b/htt.c @@ -131,6 +131,138 @@ 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_old_qca), + .rx_desc_msdu_payload_offset = offsetof(struct htt_rx_desc_old_qca, msdu_payload) +}; + +static int ath10k_qca99x0_rx_desc_get_l3_pad_bytes(void *rxd) +{ + struct htt_rx_desc_old_qca *rx_desc = rxd; + 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(void *rxd) +{ + struct htt_rx_desc_old_qca *rx_desc = rxd; + 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_old_qca), + .rx_desc_msdu_payload_offset = offsetof(struct htt_rx_desc_old_qca, 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, 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_metadata_offset +#undef metadata_offset +#undef desc_offset +} + +static struct rx_attention * +ath10k_rx_desc_wcn3990_get_attention(void *rxd) +{ + struct htt_rx_desc *rx_desc = rxd; + return &rx_desc->attention; +} + +static struct rx_frag_info_common * +ath10k_rx_desc_wcn3990_get_frag_info(void *rxd) +{ + struct htt_rx_desc *rx_desc = rxd; + return &rx_desc->frag_info.common; +} + +static struct rx_mpdu_start * +ath10k_rx_desc_wcn3990_get_mpdu_start(void *rxd) +{ + struct htt_rx_desc *rx_desc = rxd; + return &rx_desc->mpdu_start; +} + +static struct rx_mpdu_end * +ath10k_rx_desc_wcn3990_get_mpdu_end(void *rxd) +{ + struct htt_rx_desc *rx_desc = rxd; + return &rx_desc->mpdu_end; +} + +static struct rx_msdu_start_common * +ath10k_rx_desc_wcn3990_get_msdu_start(void *rxd) +{ + struct htt_rx_desc *rx_desc = rxd; + return &rx_desc->msdu_start.common; +} + +static struct rx_msdu_end_common * +ath10k_rx_desc_wcn3990_get_msdu_end(void *rxd) +{ + struct htt_rx_desc *rx_desc = rxd; + return &rx_desc->msdu_end.common; +} + +static struct rx_ppdu_start * +ath10k_rx_desc_wcn3990_get_ppdu_start(void *rxd) +{ + struct htt_rx_desc *rx_desc = rxd; + return &rx_desc->ppdu_start; +} + +static struct rx_ppdu_end_common * +ath10k_rx_desc_wcn3990_get_ppdu_end(void *rxd) +{ + struct htt_rx_desc *rx_desc = rxd; + return &rx_desc->ppdu_end.common; +} + +static u8 * +ath10k_rx_desc_wcn3990_get_rx_hdr_status(void *rxd) +{ + struct htt_rx_desc *rx_desc = rxd; + return rx_desc->rx_hdr_status; +} + +static u8 * +ath10k_rx_desc_wcn3990_get_msdu_payload(void *rxd) +{ + struct htt_rx_desc *rx_desc = rxd; + return rx_desc->msdu_payload; +} + +const struct ath10k_htt_rx_desc_ops wcn3990_rx_desc_ops = { + .rx_desc_size = sizeof(struct htt_rx_desc), + .rx_desc_msdu_payload_offset = offsetof(struct htt_rx_desc, msdu_payload), + + .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; diff --git a/htt.h b/htt.h index 612b700..5b15c42 100644 --- a/htt.h +++ b/htt.h @@ -2176,17 +2176,23 @@ 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 * (even if it correctly programmed during the rx ring setup). - * Therefore we must keep two different memory layouts and use - * ath10k_hw_ops for correctly accessing rx descriptor metadata (msdu_start, msdu_end, etc..). + * 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. */ + +/* rx descriptor for wcn3990 and possibly extensible for newer cards */ struct htt_rx_desc { union { /* This field is filled on the host using the msdu buffer @@ -2195,14 +2201,247 @@ struct htt_rx_desc { struct fw_rx_desc_base fw_desc; u32 pad; } __packed; - union { - struct rx_metadata metadata; - struct rx_metadata_for_qca6174 metadata_for_qca6174; + struct { + struct rx_attention attention; + struct rx_frag_info frag_info; + struct rx_mpdu_start mpdu_start; + struct rx_msdu_start msdu_start; + struct rx_msdu_end msdu_end; + struct rx_mpdu_end mpdu_end; + struct rx_ppdu_start ppdu_start; + struct rx_ppdu_end ppdu_end; } __packed; u8 rx_hdr_status[RX_HTT_HDR_STATUS_LEN]; u8 msdu_payload[]; }; +/* QCA6174, QCA988x, QCA99x0 dedicated rx descriptor to make sure their firmware + * works correctly. + */ +struct htt_rx_desc_old_qca { + union { + /* This field is filled on the host using the msdu buffer + * from htt_rx_indication + */ + struct fw_rx_desc_base fw_desc; + u32 pad; + } __packed; + struct { + struct rx_attention attention; + struct rx_frag_info_old_qca frag_info; + struct rx_mpdu_start mpdu_start; + struct rx_msdu_start_old_qca msdu_start; + struct rx_msdu_end_old_qca msdu_end; + struct rx_mpdu_end mpdu_end; + struct rx_ppdu_start ppdu_start; + struct rx_ppdu_end_old_qca 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)(void *rxd); + int (*rx_desc_get_l3_pad_bytes)(void *rxd); + void (*rx_desc_get_offsets)(struct htt_rx_ring_rx_desc_offsets *offs); + struct rx_attention *(*rx_desc_get_attention)(void *rxd); + struct rx_frag_info_common *(*rx_desc_get_frag_info)(void *rxd); + struct rx_mpdu_start *(*rx_desc_get_mpdu_start)(void *rxd); + struct rx_mpdu_end *(*rx_desc_get_mpdu_end)(void *rxd); + struct rx_msdu_start_common *(*rx_desc_get_msdu_start)(void *rxd); + struct rx_msdu_end_common *(*rx_desc_get_msdu_end)(void *rxd); + struct rx_ppdu_start *(*rx_desc_get_ppdu_start)(void *rxd); + struct rx_ppdu_end_common *(*rx_desc_get_ppdu_end)(void *rxd); + u8 *(*rx_desc_get_rx_hdr_status)(void *rxd); + u8 *(*rx_desc_get_msdu_payload)(void *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_rx_desc_get_l3_pad_bytes(struct ath10k_hw_params *hw, + void *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_rx_desc_msdu_limit_error(struct ath10k_hw_params *hw, + void *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 void +ath10k_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_old_qca, 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_rx_desc_get_attention(struct ath10k_hw_params *hw, + void *rxd) +{ + struct htt_rx_desc_old_qca *rx_desc = rxd; + + if(hw->rx_desc_ops->rx_desc_get_attention) + return hw->rx_desc_ops->rx_desc_get_attention(rxd); + + return &rx_desc->attention; +} + +static inline struct rx_frag_info_common * +ath10k_rx_desc_get_frag_info(struct ath10k_hw_params *hw, + void *rxd) +{ + struct htt_rx_desc_old_qca *rx_desc = rxd; + + if(hw->rx_desc_ops->rx_desc_get_frag_info) + return hw->rx_desc_ops->rx_desc_get_frag_info(rxd); + + return &rx_desc->frag_info.common; +} + +static inline struct rx_mpdu_start * +ath10k_rx_desc_get_mpdu_start(struct ath10k_hw_params *hw, + void *rxd) +{ + struct htt_rx_desc_old_qca *rx_desc = rxd; + + if(hw->rx_desc_ops->rx_desc_get_mpdu_start) + return hw->rx_desc_ops->rx_desc_get_mpdu_start(rxd); + + return &rx_desc->mpdu_start; +} + +static inline struct rx_mpdu_end * +ath10k_rx_desc_get_mpdu_end(struct ath10k_hw_params *hw, + void *rxd) +{ + struct htt_rx_desc_old_qca *rx_desc = rxd; + + if(hw->rx_desc_ops->rx_desc_get_mpdu_end) + return hw->rx_desc_ops->rx_desc_get_mpdu_end(rxd); + + return &rx_desc->mpdu_end; +} + +static inline struct rx_msdu_start_common * +ath10k_rx_desc_get_msdu_start(struct ath10k_hw_params *hw, + void *rxd) +{ + struct htt_rx_desc_old_qca *rx_desc = rxd; + + if(hw->rx_desc_ops->rx_desc_get_msdu_start) + return hw->rx_desc_ops->rx_desc_get_msdu_start(rxd); + + return &rx_desc->msdu_start.common; +} + +static inline struct rx_msdu_end_common * +ath10k_rx_desc_get_msdu_end(struct ath10k_hw_params *hw, + void *rxd) +{ + struct htt_rx_desc_old_qca *rx_desc = rxd; + + if(hw->rx_desc_ops->rx_desc_get_msdu_end) + return hw->rx_desc_ops->rx_desc_get_msdu_end(rxd); + + return &rx_desc->msdu_end.common; +} + +static inline struct rx_ppdu_start * +ath10k_rx_desc_get_ppdu_start(struct ath10k_hw_params *hw, + void *rxd) +{ + struct htt_rx_desc_old_qca *rx_desc = rxd; + + if(hw->rx_desc_ops->rx_desc_get_ppdu_start) + return hw->rx_desc_ops->rx_desc_get_ppdu_start(rxd); + + return &rx_desc->ppdu_start; +} + +static inline struct rx_ppdu_end_common * +ath10k_rx_desc_get_ppdu_end(struct ath10k_hw_params *hw, + void *rxd) +{ + struct htt_rx_desc_old_qca *rx_desc = rxd; + + if(hw->rx_desc_ops->rx_desc_get_ppdu_end) + return hw->rx_desc_ops->rx_desc_get_ppdu_end(rxd); + + return &rx_desc->ppdu_end.common; +} + +static inline u8 * +ath10k_rx_desc_get_rx_hdr_status(struct ath10k_hw_params *hw, + void *rxd) +{ + struct htt_rx_desc_old_qca *rx_desc = rxd; + + if(hw->rx_desc_ops->rx_desc_get_rx_hdr_status) + return hw->rx_desc_ops->rx_desc_get_rx_hdr_status(rxd); + + return rx_desc->rx_hdr_status; +} + +static inline u8 * +ath10k_rx_desc_get_msdu_payload(struct ath10k_hw_params *hw, + void *rxd) +{ + struct htt_rx_desc_old_qca *rx_desc = rxd; + + if(hw->rx_desc_ops->rx_desc_get_msdu_payload) + return hw->rx_desc_ops->rx_desc_get_msdu_payload(rxd); + + 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 @@ -2236,7 +2475,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. diff --git a/htt_rx.c b/htt_rx.c index f3f791f..78a27d4 100644 --- a/htt_rx.c +++ b/htt_rx.c @@ -129,7 +129,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; + void *rx_desc; struct ath10k_skb_rxcb *rxcb; struct sk_buff *skb; dma_addr_t paddr; @@ -164,7 +164,7 @@ 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 = skb->data; ath10k_rx_desc_get_attention(hw, rx_desc)->flags = __cpu_to_le32(0); paddr = dma_map_single(htt->ar->dev, skb->data, @@ -347,7 +347,7 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, struct ath10k_hw_params *hw = &ar->hw_params; int msdu_len, msdu_chaining = 0; struct sk_buff *msdu; - struct htt_rx_desc *rx_desc; + void *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; @@ -366,7 +366,7 @@ 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 = msdu->data; rx_desc_attention = ath10k_rx_desc_get_attention(hw, rx_desc); rx_desc_msdu_start_common = ath10k_rx_desc_get_msdu_start(hw, rx_desc); rx_desc_msdu_end_common = ath10k_rx_desc_get_msdu_end(hw, rx_desc); @@ -375,8 +375,8 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, /* 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 @@ -403,7 +403,7 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, 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 */ @@ -425,8 +425,11 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, RX_MSDU_END_INFO0_LAST_MSDU; // FIXME: why are we skipping the first part of the rx_desc? + // Note that here we are making assumptions about the internal + // layout of rx_desc, as things are now this works correctly + // in all cases, but FIXME! trace_ath10k_htt_rx_desc(ar, rx_desc + sizeof(u32), - sizeof(*rx_desc) - sizeof(u32)); + hw->rx_desc_ops->rx_desc_size - sizeof(u32)); if (last_msdu) break; @@ -491,20 +494,21 @@ 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; u8 last_frag; struct htt_rx_in_ord_msdu_desc *ind_desc = *msdu_desc; - struct htt_rx_desc *rxd; + void *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 = 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; @@ -567,20 +571,21 @@ 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; u8 last_frag; struct htt_rx_in_ord_msdu_desc_ext *ind_desc = *msdu_desc; - struct htt_rx_desc *rxd; + void *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 = 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; @@ -644,7 +649,7 @@ static int ath10k_htt_rx_pop_paddr32_list(struct ath10k_htt *htt, 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; + void *rxd; struct rx_attention *rxd_attention; struct sk_buff *msdu; int msdu_count, ret; @@ -680,13 +685,13 @@ 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 = msdu->data; rxd_attention = ath10k_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) & @@ -709,7 +714,7 @@ static int ath10k_htt_rx_pop_paddr64_list(struct ath10k_htt *htt, 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; + void *rxd; struct rx_attention *rxd_attention; struct sk_buff *msdu; int msdu_count, ret; @@ -744,13 +749,13 @@ 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 = msdu->data; rxd_attention = ath10k_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) & @@ -959,7 +964,7 @@ static inline u8 ath10k_bw_to_mac80211_bw(u8 bw) static void ath10k_htt_rx_h_rates(struct ath10k *ar, struct ieee80211_rx_status *status, - struct htt_rx_desc *rxd) + void *rxd) { struct ath10k_hw_params *hw = &ar->hw_params; struct rx_attention *rxd_attention = ath10k_rx_desc_get_attention(hw, rxd); @@ -968,6 +973,7 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar, struct rx_msdu_start_common *rxd_msdu_start_common = ath10k_rx_desc_get_msdu_start(hw, rxd); struct rx_msdu_end_common *rxd_msdu_end_common = ath10k_rx_desc_get_msdu_end(hw, rxd); struct rx_ppdu_start *rxd_ppdu_start = ath10k_rx_desc_get_ppdu_start(hw, rxd); + u8 *rxd_msdu_payload = ath10k_rx_desc_get_msdu_payload(hw, rxd); struct ieee80211_supported_band *sband; u8 cck, rate, bw, sgi, mcs, nss; u8 preamble = 0; @@ -1063,7 +1069,7 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar, 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; @@ -1081,7 +1087,7 @@ 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) +ath10k_htt_rx_h_peer_channel(struct ath10k *ar, void *rxd) { struct ath10k_hw_params *hw = &ar->hw_params; struct rx_attention *rxd_attention = ath10k_rx_desc_get_attention(hw, rxd); @@ -1163,7 +1169,7 @@ ath10k_htt_rx_h_any_channel(struct ath10k *ar) static bool ath10k_htt_rx_h_channel(struct ath10k *ar, struct ieee80211_rx_status *status, - struct htt_rx_desc *rxd, + void *rxd, u32 vdev_id) { struct ieee80211_channel *ch; @@ -1193,7 +1199,7 @@ static bool ath10k_htt_rx_h_channel(struct ath10k *ar, static void ath10k_htt_rx_h_signal(struct ath10k *ar, struct ieee80211_rx_status *status, - struct htt_rx_desc *rxd) + void *rxd) { struct ath10k_hw_params *hw = &ar->hw_params; struct rx_ppdu_start *rxd_ppdu_start = ath10k_rx_desc_get_ppdu_start(hw, rxd); @@ -1218,7 +1224,7 @@ static void ath10k_htt_rx_h_signal(struct ath10k *ar, static void ath10k_htt_rx_h_mactime(struct ath10k *ar, struct ieee80211_rx_status *status, - struct htt_rx_desc *rxd) + void *rxd) { struct ath10k_hw_params *hw = &ar->hw_params; struct rx_ppdu_end_common *rxd_ppdu_end_common = ath10k_rx_desc_get_ppdu_end(hw, rxd); @@ -1239,7 +1245,7 @@ static void ath10k_htt_rx_h_ppdu(struct ath10k *ar, { struct sk_buff *first; struct ath10k_hw_params *hw = &ar->hw_params; - struct htt_rx_desc *rxd; + void *rxd; struct rx_attention *rxd_attention; bool is_first_ppdu; bool is_last_ppdu; @@ -1248,7 +1254,7 @@ static void ath10k_htt_rx_h_ppdu(struct ath10k *ar, return; first = skb_peek(amsdu); - rxd = (void *)first->data - sizeof(*rxd); + rxd = (void *)first->data - hw->rx_desc_ops->rx_desc_size; rxd_attention = ath10k_rx_desc_get_attention(hw, rxd); is_first_ppdu = !!(rxd_attention->flags & @@ -1393,7 +1399,7 @@ static void ath10k_htt_rx_h_undecap_raw(struct ath10k *ar, { struct ieee80211_hdr *hdr; struct ath10k_hw_params *hw = &ar->hw_params; - struct htt_rx_desc *rxd; + void *rxd; struct rx_msdu_end_common *rxd_msdu_end_common; size_t hdr_len; size_t crypto_len; @@ -1403,7 +1409,7 @@ 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); + rxd = (void *)msdu->data - hw->rx_desc_ops->rx_desc_size; rxd_msdu_end_common = ath10k_rx_desc_get_msdu_end(hw, rxd); is_first = !!(rxd_msdu_end_common->info0 & __cpu_to_le32(RX_MSDU_END_INFO0_FIRST_MSDU)); @@ -1517,8 +1523,9 @@ 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; + void *rxd; size_t hdr_len; u8 da[ETH_ALEN]; u8 sa[ETH_ALEN]; @@ -1537,7 +1544,7 @@ 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 = (void *)msdu->data - hw->rx_desc_ops->rx_desc_size; l3_pad_bytes = ath10k_rx_desc_get_l3_pad_bytes(&ar->hw_params, rxd); skb_put(msdu, l3_pad_bytes); @@ -1576,16 +1583,18 @@ static void *ath10k_htt_rx_h_find_rfc1042(struct ath10k *ar, { struct ieee80211_hdr *hdr; struct ath10k_hw_params *hw = &ar->hw_params; - struct htt_rx_desc *rxd; + void *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); + rxd = (void *)msdu->data - hw->rx_desc_ops->rx_desc_size; rxd_msdu_end_common = ath10k_rx_desc_get_msdu_end(hw, rxd); - hdr = (void *)rxd->rx_hdr_status; + rxd_rx_hdr_status = ath10k_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)); @@ -1615,6 +1624,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; @@ -1622,7 +1632,7 @@ static void ath10k_htt_rx_h_undecap_eth(struct ath10k *ar, u8 da[ETH_ALEN]; u8 sa[ETH_ALEN]; int l3_pad_bytes; - struct htt_rx_desc *rxd; + void *rxd; int bytes_aligned = ar->hw_params.decap_align_bytes; /* Delivered decapped frame: @@ -1634,7 +1644,7 @@ static void ath10k_htt_rx_h_undecap_eth(struct ath10k *ar, if (WARN_ON_ONCE(!rfc1042)) return; - rxd = (void *)msdu->data - sizeof(*rxd); + rxd = (void *)msdu->data - hw->rx_desc_ops->rx_desc_size; l3_pad_bytes = ath10k_rx_desc_get_l3_pad_bytes(&ar->hw_params, rxd); skb_put(msdu, l3_pad_bytes); skb_pull(msdu, l3_pad_bytes); @@ -1676,10 +1686,11 @@ 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; - struct htt_rx_desc *rxd; + void *rxd; int bytes_aligned = ar->hw_params.decap_align_bytes; /* Delivered decapped frame: @@ -1688,7 +1699,7 @@ static void ath10k_htt_rx_h_undecap_snap(struct ath10k *ar, * [payload] */ - rxd = (void *)msdu->data - sizeof(*rxd); + rxd = (void *)msdu->data - hw->rx_desc_ops->rx_desc_size; l3_pad_bytes = ath10k_rx_desc_get_l3_pad_bytes(&ar->hw_params, rxd); skb_put(msdu, l3_pad_bytes); @@ -1714,7 +1725,8 @@ static void ath10k_htt_rx_h_undecap(struct ath10k *ar, enum htt_rx_mpdu_encrypt_type enctype, bool is_decrypted) { - struct htt_rx_desc *rxd; + struct ath10k_hw_params *hw = &ar->hw_params; + void *rxd; struct rx_msdu_start_common *rxd_msdu_start_common; enum rx_msdu_decap_format decap; @@ -1729,8 +1741,8 @@ static void ath10k_htt_rx_h_undecap(struct ath10k *ar, * [rfc1042/llc] */ - rxd = (void *)msdu->data - sizeof(*rxd); - rxd_msdu_start_common = ath10k_rx_desc_get_msdu_start(&ar->hw_params, rxd); + rxd = (void *)msdu->data - hw->rx_desc_ops->rx_desc_size; + rxd_msdu_start_common = ath10k_rx_desc_get_msdu_start(hw, rxd); decap = MS(__le32_to_cpu(rxd_msdu_start_common->info1), RX_MSDU_START_INFO1_DECAP_FORMAT); @@ -1755,7 +1767,7 @@ static void ath10k_htt_rx_h_undecap(struct ath10k *ar, static int ath10k_htt_rx_get_csum_state(struct ath10k_hw_params *hw, struct sk_buff *skb) { - struct htt_rx_desc *rxd; + void *rxd; struct rx_attention *rxd_attention; struct rx_msdu_start_common *rxd_msdu_start_common; u32 flags, info; @@ -1763,7 +1775,7 @@ static int ath10k_htt_rx_get_csum_state(struct ath10k_hw_params *hw, struct sk_b bool is_tcp, is_udp; bool ip_csum_ok, tcpudp_csum_ok; - rxd = (void *)skb->data - sizeof(*rxd); + rxd = (void *)skb->data - hw->rx_desc_ops->rx_desc_size; rxd_attention = ath10k_rx_desc_get_attention(hw, rxd); rxd_msdu_start_common = ath10k_rx_desc_get_msdu_start(hw, rxd); flags = __le32_to_cpu(rxd_attention->flags); @@ -1883,7 +1895,7 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar, struct sk_buff *last; struct sk_buff *msdu, *temp; struct ath10k_hw_params *hw = &ar->hw_params; - struct htt_rx_desc *rxd; + void *rxd; struct rx_attention *rxd_attention; struct rx_mpdu_start *rxd_mpdu_start; @@ -1904,7 +1916,7 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar, return; first = skb_peek(amsdu); - rxd = (void *)first->data - sizeof(*rxd); + rxd = (void *)first->data - hw->rx_desc_ops->rx_desc_size; rxd_attention = ath10k_rx_desc_get_attention(hw, rxd); rxd_mpdu_start = ath10k_rx_desc_get_mpdu_start(hw, rxd); @@ -1917,7 +1929,7 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar, /* 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_rx_desc_get_rx_hdr_status(hw, rxd); memcpy(first_hdr, hdr, RX_HTT_HDR_STATUS_LEN); if (rx_hdr) @@ -1935,7 +1947,7 @@ 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); + rxd = (void *)last->data - hw->rx_desc_ops->rx_desc_size; rxd_attention = ath10k_rx_desc_get_attention(hw, rxd); attention = __le32_to_cpu(rxd_attention->flags); @@ -2138,13 +2150,13 @@ static void ath10k_htt_rx_h_unchain(struct ath10k *ar, { struct sk_buff *first; struct ath10k_hw_params *hw = &ar->hw_params; - struct htt_rx_desc *rxd; + void *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); + rxd = (void *)first->data - hw->rx_desc_ops->rx_desc_size; rxd_msdu_start_common = ath10k_rx_desc_get_msdu_start(hw, rxd); rxd_frag_info = ath10k_rx_desc_get_frag_info(hw, rxd); decap = MS(__le32_to_cpu(rxd_msdu_start_common->info1), @@ -2172,7 +2184,7 @@ static bool ath10k_htt_rx_validate_amsdu(struct ath10k *ar, struct sk_buff *first; bool is_first, is_last; struct ath10k_hw_params *hw = &ar->hw_params; - struct htt_rx_desc *rxd; + void *rxd; struct rx_msdu_end_common *rxd_msdu_end_common; struct rx_mpdu_start *rxd_mpdu_start; struct ieee80211_hdr *hdr; @@ -2182,10 +2194,10 @@ static bool ath10k_htt_rx_validate_amsdu(struct ath10k *ar, first = skb_peek(amsdu); - rxd = (void *)first->data - sizeof(*rxd); + rxd = (void *)first->data - hw->rx_desc_ops->rx_desc_size; rxd_msdu_end_common = ath10k_rx_desc_get_msdu_end(hw, rxd); rxd_mpdu_start = ath10k_rx_desc_get_mpdu_start(hw, rxd); - hdr = (void *)rxd->rx_hdr_status; + hdr = (void *)ath10k_rx_desc_get_rx_hdr_status(hw, rxd); is_first = !!(rxd_msdu_end_common->info0 & __cpu_to_le32(RX_MSDU_END_INFO0_FIRST_MSDU)); @@ -3097,7 +3109,7 @@ static int ath10k_htt_rx_extract_amsdu(struct ath10k_hw_params *hw, struct sk_buff_head *amsdu) { struct sk_buff *msdu; - struct htt_rx_desc *rxd; + void *rxd; struct rx_msdu_end_common *rxd_msdu_end_common; if (skb_queue_empty(list)) @@ -3109,7 +3121,7 @@ static int ath10k_htt_rx_extract_amsdu(struct ath10k_hw_params *hw, while ((msdu = __skb_dequeue(list))) { __skb_queue_tail(amsdu, msdu); - rxd = (void *)msdu->data - sizeof(*rxd); + rxd = (void *)msdu->data - hw->rx_desc_ops->rx_desc_size; rxd_msdu_end_common = ath10k_rx_desc_get_msdu_end(hw, rxd); if (rxd_msdu_end_common->info0 & __cpu_to_le32(RX_MSDU_END_INFO0_LAST_MSDU)) @@ -3117,7 +3129,7 @@ static int ath10k_htt_rx_extract_amsdu(struct ath10k_hw_params *hw, } msdu = skb_peek_tail(amsdu); - rxd = (void *)msdu->data - sizeof(*rxd); + rxd = (void *)msdu->data - hw->rx_desc_ops->rx_desc_size; rxd_msdu_end_common = ath10k_rx_desc_get_msdu_end(hw, rxd); if (!(rxd_msdu_end_common->info0 & __cpu_to_le32(RX_MSDU_END_INFO0_LAST_MSDU))) { diff --git a/hw.c b/hw.c index 060012b..e52e41a 100644 --- a/hw.c +++ b/hw.c @@ -1130,217 +1130,19 @@ static int ath10k_get_htt_tx_data_rssi_pad(struct htt_resp *resp) return pad_bytes; } -static inline void ath10k_rx_desc_default_get_offsets(struct htt_rx_ring_rx_desc_offsets *off) -{ -/* In the current memory layout, rx metadata are not direct members of htt_rx_desc, - * so we need to get their offset in two steps - */ -#define desc_offset(x) (offsetof(struct htt_rx_desc, x) / 4) -#define metadata_offset(x) (offsetof(struct rx_metadata, x) / 4) -#define desc_metadata_offset(x) (desc_offset(metadata) + metadata_offset(x)) - 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_metadata_offset(ppdu_start)); - off->ppdu_end_offset = __cpu_to_le16(desc_metadata_offset(ppdu_end)); - off->mpdu_start_offset = __cpu_to_le16(desc_metadata_offset(mpdu_start)); - off->mpdu_end_offset = __cpu_to_le16(desc_metadata_offset(mpdu_end)); - off->msdu_start_offset = __cpu_to_le16(desc_metadata_offset(msdu_start)); - off->msdu_end_offset = __cpu_to_le16(desc_metadata_offset(msdu_end)); - off->rx_attention_offset = __cpu_to_le16(desc_metadata_offset(attention)); - off->frag_info_offset = __cpu_to_le16(desc_metadata_offset(frag_info)); -#undef desc_metadata_offset -#undef metadata_offset -#undef desc_offset -} - -void ath10k_rx_desc_get_offsets(struct ath10k_hw_params *hw, - struct htt_rx_ring_rx_desc_offsets *off) -{ - if(hw->hw_ops->rx_desc_get_offsets) - hw->hw_ops->rx_desc_get_offsets(off); - else - ath10k_rx_desc_default_get_offsets(off); -} - -struct rx_attention * -ath10k_rx_desc_get_attention(struct ath10k_hw_params *hw, - struct htt_rx_desc *rxd) -{ - if(hw->hw_ops->rx_desc_get_attention) - return hw->hw_ops->rx_desc_get_attention(rxd); - return &rxd->metadata.attention; -} - -struct rx_frag_info_common * -ath10k_rx_desc_get_frag_info(struct ath10k_hw_params *hw, - struct htt_rx_desc *rxd) -{ - if(hw->hw_ops->rx_desc_get_frag_info) - return hw->hw_ops->rx_desc_get_frag_info(rxd); - return &rxd->metadata.frag_info.common; -} - -struct rx_mpdu_start * -ath10k_rx_desc_get_mpdu_start(struct ath10k_hw_params *hw, - struct htt_rx_desc *rxd) -{ - if(hw->hw_ops->rx_desc_get_mpdu_start) - return hw->hw_ops->rx_desc_get_mpdu_start(rxd); - return &rxd->metadata.mpdu_start; -} - -struct rx_mpdu_end * -ath10k_rx_desc_get_mpdu_end(struct ath10k_hw_params *hw, - struct htt_rx_desc *rxd) -{ - if(hw->hw_ops->rx_desc_get_mpdu_end) - return hw->hw_ops->rx_desc_get_mpdu_end(rxd); - return &rxd->metadata.mpdu_end; -} - -struct rx_msdu_start_common * -ath10k_rx_desc_get_msdu_start(struct ath10k_hw_params *hw, - struct htt_rx_desc *rxd) -{ - if(hw->hw_ops->rx_desc_get_msdu_start) - return hw->hw_ops->rx_desc_get_msdu_start(rxd); - return &rxd->metadata.msdu_start.common; -} - -struct rx_msdu_end_common * -ath10k_rx_desc_get_msdu_end(struct ath10k_hw_params *hw, - struct htt_rx_desc *rxd) -{ - if(hw->hw_ops->rx_desc_get_msdu_end) - return hw->hw_ops->rx_desc_get_msdu_end(rxd); - return &rxd->metadata.msdu_end.common; -} - -struct rx_ppdu_start * -ath10k_rx_desc_get_ppdu_start(struct ath10k_hw_params *hw, - struct htt_rx_desc *rxd) -{ - if(hw->hw_ops->rx_desc_get_ppdu_start) - return hw->hw_ops->rx_desc_get_ppdu_start(rxd); - return &rxd->metadata.ppdu_start; -} - -struct rx_ppdu_end_common * -ath10k_rx_desc_get_ppdu_end(struct ath10k_hw_params *hw, - struct htt_rx_desc *rxd) -{ - if(hw->hw_ops->rx_desc_get_ppdu_end) - return hw->hw_ops->rx_desc_get_ppdu_end(rxd); - return &rxd->metadata.ppdu_end.common; -} - const struct ath10k_hw_ops qca988x_ops = { .set_coverage_class = ath10k_hw_qca988x_set_coverage_class, .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->metadata.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->metadata.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, }; -static void ath10k_rx_desc_qca6174_get_offsets(struct htt_rx_ring_rx_desc_offsets *off) -{ -/* In the current memory layout, rx metadata are not direct members of htt_rx_desc, - * so we need to get their offset in two steps - */ -#define desc_offset(x) (offsetof(struct htt_rx_desc, x) / 4) -#define metadata_offset(x) (offsetof(struct rx_metadata_for_qca6174, x) / 4) -#define desc_metadata_offset(x) (desc_offset(metadata_for_qca6174) + metadata_offset(x)) - 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_metadata_offset(ppdu_start)); - off->ppdu_end_offset = __cpu_to_le16(desc_metadata_offset(ppdu_end)); - off->mpdu_start_offset = __cpu_to_le16(desc_metadata_offset(mpdu_start)); - off->mpdu_end_offset = __cpu_to_le16(desc_metadata_offset(mpdu_end)); - off->msdu_start_offset = __cpu_to_le16(desc_metadata_offset(msdu_start)); - off->msdu_end_offset = __cpu_to_le16(desc_metadata_offset(msdu_end)); - off->rx_attention_offset = __cpu_to_le16(desc_metadata_offset(attention)); - off->frag_info_offset = __cpu_to_le16(desc_metadata_offset(frag_info)); -#undef desc_metadata_offset -#undef metadata_offset -#undef desc_offset -} - -static struct rx_attention * -ath10k_rx_desc_qca6174_get_attention(struct htt_rx_desc *rxd) -{ - return &rxd->metadata_for_qca6174.attention; -} - -static struct rx_frag_info_common * -ath10k_rx_desc_qca6174_get_frag_info(struct htt_rx_desc *rxd) -{ - return &rxd->metadata_for_qca6174.frag_info.common; -} - -static struct rx_mpdu_start * -ath10k_rx_desc_qca6174_get_mpdu_start(struct htt_rx_desc *rxd) -{ - return &rxd->metadata_for_qca6174.mpdu_start; -} - -static struct rx_mpdu_end * -ath10k_rx_desc_qca6174_get_mpdu_end(struct htt_rx_desc *rxd) -{ - return &rxd->metadata_for_qca6174.mpdu_end; -} - -static struct rx_msdu_start_common * -ath10k_rx_desc_qca6174_get_msdu_start(struct htt_rx_desc *rxd) -{ - return &rxd->metadata_for_qca6174.msdu_start.common; -} - -static struct rx_msdu_end_common * -ath10k_rx_desc_qca6174_get_msdu_end(struct htt_rx_desc *rxd) -{ - return &rxd->metadata_for_qca6174.msdu_end.common; -} - -static struct rx_ppdu_start * -ath10k_rx_desc_qca6174_get_ppdu_start(struct htt_rx_desc *rxd) -{ - return &rxd->metadata_for_qca6174.ppdu_start; -} - -static struct rx_ppdu_end_common * -ath10k_rx_desc_qca6174_get_ppdu_end(struct htt_rx_desc *rxd) -{ - return &rxd->metadata_for_qca6174.ppdu_end.common; -} - const struct ath10k_hw_ops qca6174_ops = { .set_coverage_class = ath10k_hw_qca988x_set_coverage_class, .enable_pll_clk = ath10k_hw_qca6174_enable_pll_clock, .is_rssi_enable = ath10k_htt_tx_rssi_enable, - .rx_desc_get_offsets = ath10k_rx_desc_qca6174_get_offsets, - .rx_desc_get_attention = ath10k_rx_desc_qca6174_get_attention, - .rx_desc_get_frag_info = ath10k_rx_desc_qca6174_get_frag_info, - .rx_desc_get_mpdu_start = ath10k_rx_desc_qca6174_get_mpdu_start, - .rx_desc_get_mpdu_end = ath10k_rx_desc_qca6174_get_mpdu_end, - .rx_desc_get_msdu_start = ath10k_rx_desc_qca6174_get_msdu_start, - .rx_desc_get_msdu_end = ath10k_rx_desc_qca6174_get_msdu_end, - .rx_desc_get_ppdu_start = ath10k_rx_desc_qca6174_get_ppdu_start, - .rx_desc_get_ppdu_end = ath10k_rx_desc_qca6174_get_ppdu_end, }; const struct ath10k_hw_ops qca6174_sdio_ops = { diff --git a/hw.h b/hw.h index 3e3aee7..62db171 100644 --- a/hw.h +++ b/hw.h @@ -562,6 +562,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. */ @@ -627,37 +630,21 @@ struct ath10k_hw_params { bool dynamic_sar_support; }; -struct htt_rx_desc; +struct htt_rx_desc_ops; struct htt_resp; struct htt_data_tx_completion_ext; struct htt_rx_ring_rx_desc_offsets; -struct rx_attention; -struct rx_frag_info_common; -struct rx_mpdu_start; -struct rx_mpdu_end; -struct rx_msdu_start_common; -struct rx_msdu_end_common; -struct rx_ppdu_start; -struct rx_ppdu_end_common; /* 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); - 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); + /* Rx descriptor operations */ + + }; extern const struct ath10k_hw_ops qca988x_ops; @@ -668,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) @@ -705,50 +674,6 @@ ath10k_is_rssi_enable(struct ath10k_hw_params *hw, } -void ath10k_rx_desc_get_offsets(struct ath10k_hw_params *hw, - struct htt_rx_ring_rx_desc_offsets *off); - - -struct rx_attention * -ath10k_rx_desc_get_attention(struct ath10k_hw_params *hw, - struct htt_rx_desc *rxd); - - -struct rx_frag_info_common * -ath10k_rx_desc_get_frag_info(struct ath10k_hw_params *hw, - struct htt_rx_desc *rxd); - - -struct rx_mpdu_start * -ath10k_rx_desc_get_mpdu_start(struct ath10k_hw_params *hw, - struct htt_rx_desc *rxd); - - -struct rx_mpdu_end * -ath10k_rx_desc_get_mpdu_end(struct ath10k_hw_params *hw, - struct htt_rx_desc *rxd); - - -struct rx_msdu_start_common * -ath10k_rx_desc_get_msdu_start(struct ath10k_hw_params *hw, - struct htt_rx_desc *rxd); - - -struct rx_msdu_end_common * -ath10k_rx_desc_get_msdu_end(struct ath10k_hw_params *hw, - struct htt_rx_desc *rxd); - - -struct rx_ppdu_start * -ath10k_rx_desc_get_ppdu_start(struct ath10k_hw_params *hw, - struct htt_rx_desc *rxd); - - -struct rx_ppdu_end_common * -ath10k_rx_desc_get_ppdu_end(struct ath10k_hw_params *hw, - struct htt_rx_desc *rxd); - - /* Target specific defines for MAIN firmware */ #define TARGET_NUM_VDEVS 8 #define TARGET_NUM_PEER_AST 2 diff --git a/rx_desc.h b/rx_desc.h index 20b8170..dfa9e0b 100644 --- a/rx_desc.h +++ b/rx_desc.h @@ -217,7 +217,7 @@ struct rx_frag_info { } __packed; } __packed; -struct rx_frag_info_for_qca6174 { +struct rx_frag_info_old_qca { struct rx_frag_info_common common; } __packed; @@ -488,12 +488,11 @@ 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_for_qca6174 { +struct rx_msdu_start_old_qca { struct rx_msdu_start_common common; union { struct rx_msdu_start_qca99x0 qca99x0; @@ -633,12 +632,11 @@ 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_for_qca6174 { +struct rx_msdu_end_old_qca { struct rx_msdu_end_common common; union { struct rx_msdu_end_qca99x0 qca99x0; @@ -1164,15 +1162,11 @@ struct rx_ppdu_end_wcn3990 { struct rx_ppdu_end { 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; -struct rx_ppdu_end_for_qca6174 { +struct rx_ppdu_end_old_qca { struct rx_ppdu_end_common common; union { struct rx_ppdu_end_qca988x qca988x; @@ -1301,31 +1295,6 @@ struct rx_ppdu_end_for_qca6174 { * to 0. */ -struct rx_metadata { - struct rx_attention attention; - struct rx_frag_info frag_info; - struct rx_mpdu_start mpdu_start; - struct rx_msdu_start msdu_start; - struct rx_msdu_end msdu_end; - struct rx_mpdu_end mpdu_end; - struct rx_ppdu_start ppdu_start; - struct rx_ppdu_end ppdu_end; -} __packed; - -/* QCA6174's dedicated rx descriptor metadata to make sure the firmware - * works correctly. - */ -struct rx_metadata_for_qca6174 { - struct rx_attention attention; - struct rx_frag_info_for_qca6174 frag_info; - struct rx_mpdu_start mpdu_start; - struct rx_msdu_start_for_qca6174 msdu_start; - struct rx_msdu_end_for_qca6174 msdu_end; - struct rx_mpdu_end mpdu_end; - struct rx_ppdu_start ppdu_start; - struct rx_ppdu_end_for_qca6174 ppdu_end; -} __packed; - #define FW_RX_DESC_INFO0_DISCARD BIT(0) #define FW_RX_DESC_INFO0_FORWARD BIT(1) #define FW_RX_DESC_INFO0_INSPECT BIT(5)