2 ******************************************************************************
6 * Copyright (C) ESWIN 2015-2020
8 ******************************************************************************
13 #include <linux/ieee80211.h>
14 #include <net/cfg80211.h>
15 #include <linux/netdevice.h>
16 #include "lmac_types.h"
17 #include "ipc_shared.h"
18 #include "ecrnx_txq.h"
21 #define ECRNX_HWQ_BK 0
22 #define ECRNX_HWQ_BE 1
23 #define ECRNX_HWQ_VI 2
24 #define ECRNX_HWQ_VO 3
25 #define ECRNX_HWQ_BCMC 4
26 #define ECRNX_HWQ_NB NX_TXQ_CNT
27 #define ECRNX_HWQ_ALL_ACS (ECRNX_HWQ_BK | ECRNX_HWQ_BE | ECRNX_HWQ_VI | ECRNX_HWQ_VO)
28 #define ECRNX_HWQ_ALL_ACS_BIT ( BIT(ECRNX_HWQ_BK) | BIT(ECRNX_HWQ_BE) | \
29 BIT(ECRNX_HWQ_VI) | BIT(ECRNX_HWQ_VO) )
31 #define ECRNX_TX_LIFETIME_MS 100
32 #define ECRNX_TX_MAX_RATES NX_TX_MAX_RATES
35 #define AMSDU_PADDING(x) ((4 - ((x) & 0x3)) & 0x3)
37 #define TXU_CNTRL_RETRY BIT(0)
38 #define TXU_CNTRL_MORE_DATA BIT(2)
39 #define TXU_CNTRL_MGMT BIT(3)
40 #define TXU_CNTRL_MGMT_NO_CCK BIT(4)
41 #define TXU_CNTRL_AMSDU BIT(6)
42 #define TXU_CNTRL_MGMT_ROBUST BIT(7)
43 #define TXU_CNTRL_USE_4ADDR BIT(8)
44 #define TXU_CNTRL_EOSP BIT(9)
45 #define TXU_CNTRL_MESH_FWD BIT(10)
46 #define TXU_CNTRL_TDLS BIT(11)
47 #define TXU_CNTRL_NO_ENCRYPT BIT(15)
49 extern const int ecrnx_tid2hwq[IEEE80211_NUM_TIDS];
52 * struct ecrnx_amsdu_txhdr - Structure added in skb headroom (instead of
53 * ecrnx_txhdr) for amsdu subframe buffer (except for the first subframe
54 * that has a normal ecrnx_txhdr)
56 * @list List of other amsdu subframe (ecrnx_sw_txhdr.amsdu.hdrs)
57 * @map_len Length to be downloaded for this subframe
58 * @dma_addr Buffer address form embedded point of view
60 * @pad padding added before this subframe
61 * (only use when amsdu must be dismantled)
62 * @msdu_len Size, in bytes, of the MSDU (without padding nor amsdu header)
64 struct ecrnx_amsdu_txhdr {
65 struct list_head list;
67 #ifdef CONFIG_ECRNX_ESWIN
68 u8 *send_pos; // offset from skb->data for send to slave.
78 * struct ecrnx_amsdu - Structure to manage creation of an A-MSDU, updated
79 * only In the first subframe of an A-MSDU
81 * @hdrs List of subframe of ecrnx_amsdu_txhdr
82 * @len Current size for this A-MDSU (doesn't take padding into account)
83 * 0 means that no amsdu is in progress
84 * @nb Number of subframe in the amsdu
85 * @pad Padding to add before adding a new subframe
88 struct list_head hdrs;
95 * struct ecrnx_sw_txhdr - Software part of tx header
97 * @ecrnx_sta sta to which this buffer is addressed
98 * @ecrnx_vif vif that send the buffer
99 * @txq pointer to TXQ used to send the buffer
100 * @hw_queue Index of the HWQ used to push the buffer.
101 * May be different than txq->hwq->id on confirmation.
102 * @frame_len Size of the frame (doesn't not include mac header)
103 * (Only used to update stat, can't we use skb->len instead ?)
104 * @headroom Headroom added in skb to add ecrnx_txhdr
105 * (Only used to remove it before freeing skb, is it needed ?)
106 * @amsdu Description of amsdu whose first subframe is this buffer
107 * (amsdu.nb = 0 means this buffer is not part of amsdu)
108 * @skb skb received from transmission
109 * @map_len Length mapped for DMA (only ecrnx_hw_txhdr and data are mapped)
110 * @dma_addr DMA address after mapping
111 * @desc Buffer description that will be copied in shared mem for FW
113 struct ecrnx_sw_txhdr {
114 struct ecrnx_sta *ecrnx_sta;
115 struct ecrnx_vif *ecrnx_vif;
116 struct ecrnx_txq *txq;
120 #ifdef CONFIG_ECRNX_AMSDUS_TX
121 struct ecrnx_amsdu amsdu;
125 #ifdef CONFIG_ECRNX_ESWIN
126 u32 offset; // offset from skb->data for send to slave.
131 struct txdesc_api desc;
132 unsigned long jiffies;
136 * struct ecrnx_txhdr - Stucture to control transimission of packet
137 * (Added in skb headroom)
139 * @sw_hdr: Information from driver
141 * @hw_hdr: Information for/from hardware
144 struct ecrnx_sw_txhdr *sw_hdr;
145 char cache_guard[L1_CACHE_BYTES];
146 struct ecrnx_hw_txhdr hw_hdr;
148 #define ECRNX_TX_ALIGN_SIZE 4
149 #define ECRNX_TX_ALIGN_MASK (ECRNX_TX_ALIGN_SIZE - 1)
150 #define ECRNX_SWTXHDR_ALIGN_PADS(x) \
151 ((ECRNX_TX_ALIGN_SIZE - ((x) & ECRNX_TX_ALIGN_MASK)) \
152 & ECRNX_TX_ALIGN_MASK)
154 #define ECRNX_TX_TXDESC_API_ALIGN ((sizeof(struct txdesc_api) + 3) & (~ECRNX_TX_ALIGN_MASK))
156 * ECRNX_TX_MAX_HEADROOM - Maximum size needed in skb headroom to prepare a buffer
158 * The headroom is used to store the 'struct ecrnx_txhdr' and moreover the part that is used
159 * by the firmware to provide tx status (i.e. struct ecrnx_hw_txhdr) must be aligned on
160 * 32bits because firmware used DMA to update it.
162 #ifdef CONFIG_ECRNX_ESWIN
163 #define ECRNX_TX_MAX_HEADROOM (ECRNX_TX_TXDESC_API_ALIGN + sizeof(struct ecrnx_txhdr) + ECRNX_TX_ALIGN_SIZE)
165 #define ECRNX_TX_MAX_HEADROOM (sizeof(struct ecrnx_txhdr) + ECRNX_TX_ALIGN_SIZE)
169 * ECRNX_TX_HEADROOM - Headroom to use to store struct ecrnx_txhdr
171 * Takes into account current aligment of data buffer to ensure that struct ecrnx_txhdr
172 * (and as a consequence its field hw_hdr) will be aligned on 32bits boundary.
174 #ifdef CONFIG_ECRNX_ESWIN
175 #define ECRNX_TX_HEADROOM(skb) (ECRNX_TX_TXDESC_API_ALIGN + sizeof(struct ecrnx_txhdr) + ((long)skb->data & ECRNX_TX_ALIGN_MASK))
177 #define ECRNX_TX_HEADROOM(skb) (sizeof(struct ecrnx_txhdr) + ((long)skb->data & ECRNX_TX_ALIGN_MASK))
181 * ECRNX_TX_DMA_MAP_LEN - Length, in bytes, to map for DMA transfer
182 * To be called with skb BEFORE reserving headroom to store struct ecrnx_txhdr.
184 #define ECRNX_TX_DMA_MAP_LEN(skb) ( \
185 (sizeof(struct ecrnx_txhdr) - offsetof(struct ecrnx_txhdr, hw_hdr)) + \
186 ((long)skb->data & ECRNX_TX_ALIGN_MASK) + skb->len)
189 * ECRNX_TX_DATA_OFT - Offset, in bytes, between the location of the 'struct ecrnx_hw_txhdr'
190 * and the beginning of frame (i.e. ethernet of 802.11 header). Cannot simply use
191 * sizeof(struct ecrnx_hw_txhdr) because of padding added by compiler to align fields
194 #define ECRNX_TX_DATA_OFT(sw_txhdr) ( \
195 (sizeof(struct ecrnx_txhdr) - offsetof(struct ecrnx_txhdr, hw_hdr)) \
196 + (sw_txhdr->headroom & ECRNX_TX_ALIGN_MASK))
199 * SKB buffer format before it is pushed to MACSW
202 * |--------------------|
204 * skb->data ----> |--------------------| <------ skb->data
205 * | struct ecrnx_txhdr |
206 * | * ecrnx_sw_txhdr * |
208 * +--> | * ecrnx_hw_txhdr | <---- desc.host.status_desc_addr
210 * memory : |--------------------|
211 * mapped : | padding (optional) |
212 * for DMA : |--------------------|
213 * : | Ethernet Header |
214 * : |--------------------| <---- desc.host.packet_addr[0]
219 * +--> |--------------------|
221 * |--------------------|
224 * For MGMT frame (skb is created by the driver so buffer is always aligned
225 * with no headroom/tailroom)
227 * skb->data ----> |--------------------| <------ skb->data
228 * | struct ecrnx_txhdr |
229 * | * ecrnx_sw_txhdr * |
231 * +--> | * ecrnx_hw_txhdr | <---- desc.host.status_desc_addr
233 * mapped : |--------------------| <---- desc.host.packet_addr[0]
234 * for DMA : | 802.11 HDR |
235 * : |--------------------|
238 * +--> |--------------------|
242 u16 ecrnx_select_txq(struct ecrnx_vif *ecrnx_vif, struct sk_buff *skb);
243 int ecrnx_start_xmit(struct sk_buff *skb, struct net_device *dev);
245 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
246 int ecrnx_start_mgmt_xmit(struct ecrnx_vif *vif, struct ecrnx_sta *sta,
247 struct cfg80211_mgmt_tx_params *params, bool offchan,
250 int ecrnx_start_mgmt_xmit(struct ecrnx_vif *vif, struct ecrnx_sta *sta,
251 struct ieee80211_channel *channel, bool offchan,
252 unsigned int wait, const u8* buf, size_t len,
253 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
256 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
257 bool dont_wait_for_ack,
260 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */
262 int ecrnx_txdatacfm(void *pthis, void *host_id);
263 int ecrnx_handle_tx_datacfm(void *priv, void *host_id);
267 void ecrnx_set_traffic_status(struct ecrnx_hw *ecrnx_hw,
268 struct ecrnx_sta *sta,
271 void ecrnx_ps_bh_enable(struct ecrnx_hw *ecrnx_hw, struct ecrnx_sta *sta,
273 void ecrnx_ps_bh_traffic_req(struct ecrnx_hw *ecrnx_hw, struct ecrnx_sta *sta,
274 u16 pkt_req, u8 ps_id);
276 void ecrnx_switch_vif_sta_txq(struct ecrnx_sta *sta, struct ecrnx_vif *old_vif,
277 struct ecrnx_vif *new_vif);
279 int ecrnx_dbgfs_print_sta(char *buf, size_t size, struct ecrnx_sta *sta,
280 struct ecrnx_hw *ecrnx_hw);
281 void ecrnx_txq_credit_update(struct ecrnx_hw *ecrnx_hw, int sta_idx, u8 tid,
283 void ecrnx_tx_push(struct ecrnx_hw *ecrnx_hw, struct ecrnx_txhdr *txhdr, int flags);
285 #endif /* _ECRNX_TX_H_ */