1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
2 | /* |
3 | * This file is part of wl1271 |
4 | * |
5 | * Copyright (C) 1998-2009 Texas Instruments. All rights reserved. |
6 | * Copyright (C) 2009 Nokia Corporation |
7 | * |
8 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> |
9 | */ |
10 | |
11 | #ifndef __TX_H__ |
12 | #define __TX_H__ |
13 | |
14 | #define TX_HW_MGMT_PKT_LIFETIME_TU 2000 |
15 | #define TX_HW_AP_MODE_PKT_LIFETIME_TU 8000 |
16 | |
17 | #define TX_HW_ATTR_SAVE_RETRIES BIT(0) |
18 | #define BIT(1) |
19 | #define TX_HW_ATTR_SESSION_COUNTER (BIT(2) | BIT(3) | BIT(4)) |
20 | #define TX_HW_ATTR_RATE_POLICY (BIT(5) | BIT(6) | BIT(7) | \ |
21 | BIT(8) | BIT(9)) |
22 | #define TX_HW_ATTR_LAST_WORD_PAD (BIT(10) | BIT(11)) |
23 | #define TX_HW_ATTR_TX_CMPLT_REQ BIT(12) |
24 | #define TX_HW_ATTR_TX_DUMMY_REQ BIT(13) |
25 | #define TX_HW_ATTR_HOST_ENCRYPT BIT(14) |
26 | #define TX_HW_ATTR_EAPOL_FRAME BIT(15) |
27 | |
28 | #define TX_HW_ATTR_OFST_SAVE_RETRIES 0 |
29 | #define 1 |
30 | #define TX_HW_ATTR_OFST_SESSION_COUNTER 2 |
31 | #define TX_HW_ATTR_OFST_RATE_POLICY 5 |
32 | #define TX_HW_ATTR_OFST_LAST_WORD_PAD 10 |
33 | #define TX_HW_ATTR_OFST_TX_CMPLT_REQ 12 |
34 | |
35 | #define TX_HW_RESULT_QUEUE_LEN 16 |
36 | #define TX_HW_RESULT_QUEUE_LEN_MASK 0xf |
37 | |
38 | #define WL1271_TX_ALIGN_TO 4 |
39 | #define 4 |
40 | #define 8 |
41 | #define 8 |
42 | |
43 | /* Used for management frames and dummy packets */ |
44 | #define WL1271_TID_MGMT 7 |
45 | |
46 | /* stop a ROC for pending authentication reply after this time (ms) */ |
47 | #define WLCORE_PEND_AUTH_ROC_TIMEOUT 1000 |
48 | |
49 | struct wl127x_tx_mem { |
50 | /* |
51 | * Number of extra memory blocks to allocate for this packet |
52 | * in addition to the number of blocks derived from the packet |
53 | * length. |
54 | */ |
55 | u8 ; |
56 | /* |
57 | * Total number of memory blocks allocated by the host for |
58 | * this packet. Must be equal or greater than the actual |
59 | * blocks number allocated by HW. |
60 | */ |
61 | u8 total_mem_blocks; |
62 | } __packed; |
63 | |
64 | struct wl128x_tx_mem { |
65 | /* |
66 | * Total number of memory blocks allocated by the host for |
67 | * this packet. |
68 | */ |
69 | u8 total_mem_blocks; |
70 | /* |
71 | * Number of extra bytes, at the end of the frame. the host |
72 | * uses this padding to complete each frame to integer number |
73 | * of SDIO blocks. |
74 | */ |
75 | u8 ; |
76 | } __packed; |
77 | |
78 | struct wl18xx_tx_mem { |
79 | /* |
80 | * Total number of memory blocks allocated by the host for |
81 | * this packet. |
82 | */ |
83 | u8 total_mem_blocks; |
84 | |
85 | /* |
86 | * control bits |
87 | */ |
88 | u8 ctrl; |
89 | } __packed; |
90 | |
91 | /* |
92 | * On wl128x based devices, when TX packets are aggregated, each packet |
93 | * size must be aligned to the SDIO block size. The maximum block size |
94 | * is bounded by the type of the padded bytes field that is sent to the |
95 | * FW. Currently the type is u8, so the maximum block size is 256 bytes. |
96 | */ |
97 | #define WL12XX_BUS_BLOCK_SIZE min(512u, \ |
98 | (1u << (8 * sizeof(((struct wl128x_tx_mem *) 0)->extra_bytes)))) |
99 | |
100 | struct wl1271_tx_hw_descr { |
101 | /* Length of packet in words, including descriptor+header+data */ |
102 | __le16 length; |
103 | union { |
104 | struct wl127x_tx_mem wl127x_mem; |
105 | struct wl128x_tx_mem wl128x_mem; |
106 | struct wl18xx_tx_mem wl18xx_mem; |
107 | } __packed; |
108 | /* Device time (in us) when the packet arrived to the driver */ |
109 | __le32 start_time; |
110 | /* |
111 | * Max delay in TUs until transmission. The last device time the |
112 | * packet can be transmitted is: start_time + (1024 * life_time) |
113 | */ |
114 | __le16 life_time; |
115 | /* Bitwise fields - see TX_ATTR... definitions above. */ |
116 | __le16 tx_attr; |
117 | /* Packet identifier used also in the Tx-Result. */ |
118 | u8 id; |
119 | /* The packet TID value (as User-Priority) */ |
120 | u8 tid; |
121 | /* host link ID (HLID) */ |
122 | u8 hlid; |
123 | |
124 | union { |
125 | u8 wl12xx_reserved; |
126 | |
127 | /* |
128 | * bit 0 -> 0 = udp, 1 = tcp |
129 | * bit 1:7 -> IP header offset |
130 | */ |
131 | u8 wl18xx_checksum_data; |
132 | } __packed; |
133 | } __packed; |
134 | |
135 | enum wl1271_tx_hw_res_status { |
136 | TX_SUCCESS = 0, |
137 | TX_HW_ERROR = 1, |
138 | TX_DISABLED = 2, |
139 | TX_RETRY_EXCEEDED = 3, |
140 | TX_TIMEOUT = 4, |
141 | TX_KEY_NOT_FOUND = 5, |
142 | TX_PEER_NOT_FOUND = 6, |
143 | TX_SESSION_MISMATCH = 7, |
144 | TX_LINK_NOT_VALID = 8, |
145 | }; |
146 | |
147 | struct wl1271_tx_hw_res_descr { |
148 | /* Packet Identifier - same value used in the Tx descriptor.*/ |
149 | u8 id; |
150 | /* The status of the transmission, indicating success or one of |
151 | several possible reasons for failure. */ |
152 | u8 status; |
153 | /* Total air access duration including all retrys and overheads.*/ |
154 | __le16 medium_usage; |
155 | /* The time passed from host xfer to Tx-complete.*/ |
156 | __le32 fw_handling_time; |
157 | /* Total media delay |
158 | (from 1st EDCA AIFS counter until TX Complete). */ |
159 | __le32 medium_delay; |
160 | /* LS-byte of last TKIP seq-num (saved per AC for recovery). */ |
161 | u8 tx_security_sequence_number_lsb; |
162 | /* Retry count - number of transmissions without successful ACK.*/ |
163 | u8 ack_failures; |
164 | /* The rate that succeeded getting ACK |
165 | (Valid only if status=SUCCESS). */ |
166 | u8 rate_class_index; |
167 | /* for 4-byte alignment. */ |
168 | u8 spare; |
169 | } __packed; |
170 | |
171 | struct wl1271_tx_hw_res_if { |
172 | __le32 tx_result_fw_counter; |
173 | __le32 tx_result_host_counter; |
174 | struct wl1271_tx_hw_res_descr tx_results_queue[TX_HW_RESULT_QUEUE_LEN]; |
175 | } __packed; |
176 | |
177 | enum wlcore_queue_stop_reason { |
178 | WLCORE_QUEUE_STOP_REASON_WATERMARK, |
179 | WLCORE_QUEUE_STOP_REASON_FW_RESTART, |
180 | WLCORE_QUEUE_STOP_REASON_FLUSH, |
181 | WLCORE_QUEUE_STOP_REASON_SPARE_BLK, /* 18xx specific */ |
182 | }; |
183 | |
184 | static inline int wl1271_tx_get_queue(int queue) |
185 | { |
186 | switch (queue) { |
187 | case 0: |
188 | return CONF_TX_AC_VO; |
189 | case 1: |
190 | return CONF_TX_AC_VI; |
191 | case 2: |
192 | return CONF_TX_AC_BE; |
193 | case 3: |
194 | return CONF_TX_AC_BK; |
195 | default: |
196 | return CONF_TX_AC_BE; |
197 | } |
198 | } |
199 | |
200 | static inline |
201 | int wlcore_tx_get_mac80211_queue(struct wl12xx_vif *wlvif, int queue) |
202 | { |
203 | int mac_queue = wlvif->hw_queue_base; |
204 | |
205 | switch (queue) { |
206 | case CONF_TX_AC_VO: |
207 | return mac_queue + 0; |
208 | case CONF_TX_AC_VI: |
209 | return mac_queue + 1; |
210 | case CONF_TX_AC_BE: |
211 | return mac_queue + 2; |
212 | case CONF_TX_AC_BK: |
213 | return mac_queue + 3; |
214 | default: |
215 | return mac_queue + 2; |
216 | } |
217 | } |
218 | |
219 | static inline int wl1271_tx_total_queue_count(struct wl1271 *wl) |
220 | { |
221 | int i, count = 0; |
222 | |
223 | for (i = 0; i < NUM_TX_QUEUES; i++) |
224 | count += wl->tx_queue_count[i]; |
225 | |
226 | return count; |
227 | } |
228 | |
229 | void wl1271_tx_work(struct work_struct *work); |
230 | int wlcore_tx_work_locked(struct wl1271 *wl); |
231 | int wlcore_tx_complete(struct wl1271 *wl); |
232 | void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif); |
233 | void wl12xx_tx_reset(struct wl1271 *wl); |
234 | void wl1271_tx_flush(struct wl1271 *wl); |
235 | u8 wlcore_rate_to_idx(struct wl1271 *wl, u8 rate, enum nl80211_band band); |
236 | u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set, |
237 | enum nl80211_band rate_band); |
238 | u32 wl1271_tx_min_rate_get(struct wl1271 *wl, u32 rate_set); |
239 | u8 wl12xx_tx_get_hlid(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
240 | struct sk_buff *skb, struct ieee80211_sta *sta); |
241 | void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid); |
242 | void wl1271_handle_tx_low_watermark(struct wl1271 *wl); |
243 | bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb); |
244 | void wl12xx_rearm_rx_streaming(struct wl1271 *wl, unsigned long *active_hlids); |
245 | unsigned int wlcore_calc_packet_alignment(struct wl1271 *wl, |
246 | unsigned int packet_length); |
247 | void wl1271_free_tx_id(struct wl1271 *wl, int id); |
248 | void wlcore_stop_queue_locked(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
249 | u8 queue, enum wlcore_queue_stop_reason reason); |
250 | void wlcore_stop_queue(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 queue, |
251 | enum wlcore_queue_stop_reason reason); |
252 | void wlcore_wake_queue(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 queue, |
253 | enum wlcore_queue_stop_reason reason); |
254 | void wlcore_stop_queues(struct wl1271 *wl, |
255 | enum wlcore_queue_stop_reason reason); |
256 | void wlcore_wake_queues(struct wl1271 *wl, |
257 | enum wlcore_queue_stop_reason reason); |
258 | bool wlcore_is_queue_stopped_by_reason(struct wl1271 *wl, |
259 | struct wl12xx_vif *wlvif, u8 queue, |
260 | enum wlcore_queue_stop_reason reason); |
261 | bool |
262 | wlcore_is_queue_stopped_by_reason_locked(struct wl1271 *wl, |
263 | struct wl12xx_vif *wlvif, |
264 | u8 queue, |
265 | enum wlcore_queue_stop_reason reason); |
266 | bool wlcore_is_queue_stopped_locked(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
267 | u8 queue); |
268 | |
269 | /* from main.c */ |
270 | void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid); |
271 | void wl12xx_rearm_tx_watchdog_locked(struct wl1271 *wl); |
272 | |
273 | #endif |
274 | |