1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* Copyright(c) 2009-2012 Realtek Corporation.*/ |
3 | |
4 | #include "../wifi.h" |
5 | #include "../usb.h" |
6 | #include "../ps.h" |
7 | #include "../base.h" |
8 | #include "reg.h" |
9 | #include "def.h" |
10 | #include "phy.h" |
11 | #include "rf.h" |
12 | #include "dm.h" |
13 | #include "mac.h" |
14 | #include "trx.h" |
15 | #include "../rtl8192c/fw_common.h" |
16 | |
17 | static int configvertoutep(struct ieee80211_hw *hw) |
18 | { |
19 | u8 ep_cfg, txqsele; |
20 | u8 ep_nums = 0; |
21 | |
22 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
23 | struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw); |
24 | struct rtl_usb *rtlusb = rtl_usbdev(usb_priv); |
25 | |
26 | rtlusb->out_queue_sel = 0; |
27 | ep_cfg = rtl_read_byte(rtlpriv, REG_TEST_SIE_OPTIONAL); |
28 | ep_cfg = (ep_cfg & USB_TEST_EP_MASK) >> USB_TEST_EP_SHIFT; |
29 | switch (ep_cfg) { |
30 | case 0: /* 2 bulk OUT, 1 bulk IN */ |
31 | case 3: |
32 | rtlusb->out_queue_sel = TX_SELE_HQ | TX_SELE_LQ; |
33 | ep_nums = 2; |
34 | break; |
35 | case 1: /* 1 bulk IN/OUT => map all endpoint to Low queue */ |
36 | case 2: /* 1 bulk IN, 1 bulk OUT => map all endpoint to High queue */ |
37 | txqsele = rtl_read_byte(rtlpriv, REG_TEST_USB_TXQS); |
38 | if (txqsele & 0x0F) /* /map all endpoint to High queue */ |
39 | rtlusb->out_queue_sel = TX_SELE_HQ; |
40 | else if (txqsele&0xF0) /* map all endpoint to Low queue */ |
41 | rtlusb->out_queue_sel = TX_SELE_LQ; |
42 | ep_nums = 1; |
43 | break; |
44 | default: |
45 | break; |
46 | } |
47 | return (rtlusb->out_ep_nums == ep_nums) ? 0 : -EINVAL; |
48 | } |
49 | |
50 | static int configvernoutep(struct ieee80211_hw *hw) |
51 | { |
52 | u8 ep_cfg; |
53 | u8 ep_nums = 0; |
54 | |
55 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
56 | struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw); |
57 | struct rtl_usb *rtlusb = rtl_usbdev(usb_priv); |
58 | |
59 | rtlusb->out_queue_sel = 0; |
60 | /* Normal and High queue */ |
61 | ep_cfg = rtl_read_byte(rtlpriv, addr: (REG_NORMAL_SIE_EP + 1)); |
62 | if (ep_cfg & USB_NORMAL_SIE_EP_MASK) { |
63 | rtlusb->out_queue_sel |= TX_SELE_HQ; |
64 | ep_nums++; |
65 | } |
66 | if ((ep_cfg >> USB_NORMAL_SIE_EP_SHIFT) & USB_NORMAL_SIE_EP_MASK) { |
67 | rtlusb->out_queue_sel |= TX_SELE_NQ; |
68 | ep_nums++; |
69 | } |
70 | /* Low queue */ |
71 | ep_cfg = rtl_read_byte(rtlpriv, addr: (REG_NORMAL_SIE_EP + 2)); |
72 | if (ep_cfg & USB_NORMAL_SIE_EP_MASK) { |
73 | rtlusb->out_queue_sel |= TX_SELE_LQ; |
74 | ep_nums++; |
75 | } |
76 | return (rtlusb->out_ep_nums == ep_nums) ? 0 : -EINVAL; |
77 | } |
78 | |
79 | static void twooutepmapping(struct ieee80211_hw *hw, bool is_chip8, |
80 | bool bwificfg, struct rtl_ep_map *ep_map) |
81 | { |
82 | struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw); |
83 | struct rtl_usb *rtlusb = rtl_usbdev(usb_priv); |
84 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
85 | |
86 | if (bwificfg) { /* for WMM */ |
87 | rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, |
88 | "USB Chip-B & WMM Setting.....\n" ); |
89 | ep_map->ep_mapping[RTL_TXQ_BE] = rtlusb->out_eps[0]; |
90 | ep_map->ep_mapping[RTL_TXQ_BK] = rtlusb->out_eps[1]; |
91 | ep_map->ep_mapping[RTL_TXQ_VI] = rtlusb->out_eps[1]; |
92 | ep_map->ep_mapping[RTL_TXQ_VO] = rtlusb->out_eps[0]; |
93 | ep_map->ep_mapping[RTL_TXQ_MGT] = rtlusb->out_eps[0]; |
94 | ep_map->ep_mapping[RTL_TXQ_BCN] = rtlusb->out_eps[0]; |
95 | ep_map->ep_mapping[RTL_TXQ_HI] = rtlusb->out_eps[0]; |
96 | } else { /* typical setting */ |
97 | rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, |
98 | "USB typical Setting.....\n" ); |
99 | ep_map->ep_mapping[RTL_TXQ_BE] = rtlusb->out_eps[1]; |
100 | ep_map->ep_mapping[RTL_TXQ_BK] = rtlusb->out_eps[1]; |
101 | ep_map->ep_mapping[RTL_TXQ_VI] = rtlusb->out_eps[0]; |
102 | ep_map->ep_mapping[RTL_TXQ_VO] = rtlusb->out_eps[0]; |
103 | ep_map->ep_mapping[RTL_TXQ_MGT] = rtlusb->out_eps[0]; |
104 | ep_map->ep_mapping[RTL_TXQ_BCN] = rtlusb->out_eps[0]; |
105 | ep_map->ep_mapping[RTL_TXQ_HI] = rtlusb->out_eps[0]; |
106 | } |
107 | } |
108 | |
109 | static void threeoutepmapping(struct ieee80211_hw *hw, bool bwificfg, |
110 | struct rtl_ep_map *ep_map) |
111 | { |
112 | struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw); |
113 | struct rtl_usb *rtlusb = rtl_usbdev(usb_priv); |
114 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
115 | |
116 | if (bwificfg) { /* for WMM */ |
117 | rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, |
118 | "USB 3EP Setting for WMM.....\n" ); |
119 | ep_map->ep_mapping[RTL_TXQ_BE] = rtlusb->out_eps[2]; |
120 | ep_map->ep_mapping[RTL_TXQ_BK] = rtlusb->out_eps[1]; |
121 | ep_map->ep_mapping[RTL_TXQ_VI] = rtlusb->out_eps[1]; |
122 | ep_map->ep_mapping[RTL_TXQ_VO] = rtlusb->out_eps[0]; |
123 | ep_map->ep_mapping[RTL_TXQ_MGT] = rtlusb->out_eps[0]; |
124 | ep_map->ep_mapping[RTL_TXQ_BCN] = rtlusb->out_eps[0]; |
125 | ep_map->ep_mapping[RTL_TXQ_HI] = rtlusb->out_eps[0]; |
126 | } else { /* typical setting */ |
127 | rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, |
128 | "USB 3EP Setting for typical.....\n" ); |
129 | ep_map->ep_mapping[RTL_TXQ_BE] = rtlusb->out_eps[2]; |
130 | ep_map->ep_mapping[RTL_TXQ_BK] = rtlusb->out_eps[2]; |
131 | ep_map->ep_mapping[RTL_TXQ_VI] = rtlusb->out_eps[1]; |
132 | ep_map->ep_mapping[RTL_TXQ_VO] = rtlusb->out_eps[0]; |
133 | ep_map->ep_mapping[RTL_TXQ_MGT] = rtlusb->out_eps[0]; |
134 | ep_map->ep_mapping[RTL_TXQ_BCN] = rtlusb->out_eps[0]; |
135 | ep_map->ep_mapping[RTL_TXQ_HI] = rtlusb->out_eps[0]; |
136 | } |
137 | } |
138 | |
139 | static void oneoutepmapping(struct ieee80211_hw *hw, struct rtl_ep_map *ep_map) |
140 | { |
141 | struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw); |
142 | struct rtl_usb *rtlusb = rtl_usbdev(usb_priv); |
143 | |
144 | ep_map->ep_mapping[RTL_TXQ_BE] = rtlusb->out_eps[0]; |
145 | ep_map->ep_mapping[RTL_TXQ_BK] = rtlusb->out_eps[0]; |
146 | ep_map->ep_mapping[RTL_TXQ_VI] = rtlusb->out_eps[0]; |
147 | ep_map->ep_mapping[RTL_TXQ_VO] = rtlusb->out_eps[0]; |
148 | ep_map->ep_mapping[RTL_TXQ_MGT] = rtlusb->out_eps[0]; |
149 | ep_map->ep_mapping[RTL_TXQ_BCN] = rtlusb->out_eps[0]; |
150 | ep_map->ep_mapping[RTL_TXQ_HI] = rtlusb->out_eps[0]; |
151 | } |
152 | |
153 | static int _out_ep_mapping(struct ieee80211_hw *hw) |
154 | { |
155 | int err = 0; |
156 | bool ischipn, bwificfg = false; |
157 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
158 | struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw); |
159 | struct rtl_usb *rtlusb = rtl_usbdev(usb_priv); |
160 | struct rtl_ep_map *ep_map = &(rtlusb->ep_map); |
161 | |
162 | ischipn = IS_NORMAL_CHIP(rtlhal->version); |
163 | switch (rtlusb->out_ep_nums) { |
164 | case 2: |
165 | twooutepmapping(hw, is_chip8: ischipn, bwificfg, ep_map); |
166 | break; |
167 | case 3: |
168 | /* Test chip doesn't support three out EPs. */ |
169 | if (!ischipn) { |
170 | err = -EINVAL; |
171 | goto err_out; |
172 | } |
173 | threeoutepmapping(hw, bwificfg: ischipn, ep_map); |
174 | break; |
175 | case 1: |
176 | oneoutepmapping(hw, ep_map); |
177 | break; |
178 | default: |
179 | err = -EINVAL; |
180 | break; |
181 | } |
182 | err_out: |
183 | return err; |
184 | |
185 | } |
186 | |
187 | /* endpoint mapping */ |
188 | int rtl8192cu_endpoint_mapping(struct ieee80211_hw *hw) |
189 | { |
190 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
191 | int error = 0; |
192 | |
193 | if (likely(IS_NORMAL_CHIP(rtlhal->version))) |
194 | error = configvernoutep(hw); |
195 | else |
196 | error = configvertoutep(hw); |
197 | if (error) |
198 | goto err_out; |
199 | error = _out_ep_mapping(hw); |
200 | if (error) |
201 | goto err_out; |
202 | err_out: |
203 | return error; |
204 | } |
205 | |
206 | u16 rtl8192cu_mq_to_hwq(__le16 fc, u16 mac80211_queue_index) |
207 | { |
208 | u16 hw_queue_index; |
209 | |
210 | if (unlikely(ieee80211_is_beacon(fc))) { |
211 | hw_queue_index = RTL_TXQ_BCN; |
212 | goto out; |
213 | } |
214 | if (ieee80211_is_mgmt(fc)) { |
215 | hw_queue_index = RTL_TXQ_MGT; |
216 | goto out; |
217 | } |
218 | switch (mac80211_queue_index) { |
219 | case 0: |
220 | hw_queue_index = RTL_TXQ_VO; |
221 | break; |
222 | case 1: |
223 | hw_queue_index = RTL_TXQ_VI; |
224 | break; |
225 | case 2: |
226 | hw_queue_index = RTL_TXQ_BE; |
227 | break; |
228 | case 3: |
229 | hw_queue_index = RTL_TXQ_BK; |
230 | break; |
231 | default: |
232 | hw_queue_index = RTL_TXQ_BE; |
233 | WARN_ONCE(true, "rtl8192cu: QSLT_BE queue, skb_queue:%d\n" , |
234 | mac80211_queue_index); |
235 | break; |
236 | } |
237 | out: |
238 | return hw_queue_index; |
239 | } |
240 | |
241 | static enum rtl_desc_qsel _rtl8192cu_mq_to_descq(struct ieee80211_hw *hw, |
242 | __le16 fc, u16 mac80211_queue_index) |
243 | { |
244 | enum rtl_desc_qsel qsel; |
245 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
246 | |
247 | if (unlikely(ieee80211_is_beacon(fc))) { |
248 | qsel = QSLT_BEACON; |
249 | goto out; |
250 | } |
251 | if (ieee80211_is_mgmt(fc)) { |
252 | qsel = QSLT_MGNT; |
253 | goto out; |
254 | } |
255 | switch (mac80211_queue_index) { |
256 | case 0: /* VO */ |
257 | qsel = QSLT_VO; |
258 | rtl_dbg(rtlpriv, COMP_USB, DBG_DMESG, |
259 | "VO queue, set qsel = 0x%x\n" , QSLT_VO); |
260 | break; |
261 | case 1: /* VI */ |
262 | qsel = QSLT_VI; |
263 | rtl_dbg(rtlpriv, COMP_USB, DBG_DMESG, |
264 | "VI queue, set qsel = 0x%x\n" , QSLT_VI); |
265 | break; |
266 | case 3: /* BK */ |
267 | qsel = QSLT_BK; |
268 | rtl_dbg(rtlpriv, COMP_USB, DBG_DMESG, |
269 | "BK queue, set qsel = 0x%x\n" , QSLT_BK); |
270 | break; |
271 | case 2: /* BE */ |
272 | default: |
273 | qsel = QSLT_BE; |
274 | rtl_dbg(rtlpriv, COMP_USB, DBG_DMESG, |
275 | "BE queue, set qsel = 0x%x\n" , QSLT_BE); |
276 | break; |
277 | } |
278 | out: |
279 | return qsel; |
280 | } |
281 | |
282 | /* =============================================================== */ |
283 | |
284 | /*---------------------------------------------------------------------- |
285 | * |
286 | * Rx handler |
287 | * |
288 | *---------------------------------------------------------------------- */ |
289 | bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw, |
290 | struct rtl_stats *stats, |
291 | struct ieee80211_rx_status *rx_status, |
292 | u8 *pdesc8, struct sk_buff *skb) |
293 | { |
294 | struct rx_fwinfo_92c *p_drvinfo; |
295 | struct rx_desc_92c *p_desc = (struct rx_desc_92c *)pdesc8; |
296 | __le32 *pdesc = (__le32 *)pdesc8; |
297 | u32 phystatus = get_rx_desc_phy_status(rxdesc: pdesc); |
298 | |
299 | stats->length = (u16)get_rx_desc_pkt_len(rxdesc: pdesc); |
300 | stats->rx_drvinfo_size = (u8)get_rx_desc_drvinfo_size(rxdesc: pdesc) * |
301 | RX_DRV_INFO_SIZE_UNIT; |
302 | stats->rx_bufshift = (u8)(get_rx_desc_shift(rxdesc: pdesc) & 0x03); |
303 | stats->icv = (u16)get_rx_desc_icv(rxdesc: pdesc); |
304 | stats->crc = (u16)get_rx_desc_crc32(rxdesc: pdesc); |
305 | stats->hwerror = (stats->crc | stats->icv); |
306 | stats->decrypted = !get_rx_desc_swdec(rxdesc: pdesc); |
307 | stats->rate = (u8)get_rx_desc_rx_mcs(rxdesc: pdesc); |
308 | stats->shortpreamble = (u16)get_rx_desc_splcp(rxdesc: pdesc); |
309 | stats->isampdu = (bool)(get_rx_desc_paggr(rxdesc: pdesc) == 1); |
310 | stats->isfirst_ampdu = (bool)((get_rx_desc_paggr(rxdesc: pdesc) == 1) && |
311 | (get_rx_desc_faggr(rxdesc: pdesc) == 1)); |
312 | stats->timestamp_low = get_rx_desc_tsfl(rxdesc: pdesc); |
313 | stats->rx_is40mhzpacket = (bool)get_rx_desc_bw(rxdesc: pdesc); |
314 | stats->is_ht = (bool)get_rx_desc_rx_ht(rxdesc: pdesc); |
315 | rx_status->freq = hw->conf.chandef.chan->center_freq; |
316 | rx_status->band = hw->conf.chandef.chan->band; |
317 | if (get_rx_desc_crc32(rxdesc: pdesc)) |
318 | rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; |
319 | if (!get_rx_desc_swdec(rxdesc: pdesc)) |
320 | rx_status->flag |= RX_FLAG_DECRYPTED; |
321 | if (get_rx_desc_bw(rxdesc: pdesc)) |
322 | rx_status->bw = RATE_INFO_BW_40; |
323 | if (get_rx_desc_rx_ht(rxdesc: pdesc)) |
324 | rx_status->encoding = RX_ENC_HT; |
325 | rx_status->flag |= RX_FLAG_MACTIME_START; |
326 | if (stats->decrypted) |
327 | rx_status->flag |= RX_FLAG_DECRYPTED; |
328 | rx_status->rate_idx = rtlwifi_rate_mapping(hw, isht: stats->is_ht, |
329 | isvht: false, desc_rate: stats->rate); |
330 | rx_status->mactime = get_rx_desc_tsfl(rxdesc: pdesc); |
331 | if (phystatus) { |
332 | p_drvinfo = (struct rx_fwinfo_92c *)(skb->data + |
333 | stats->rx_bufshift); |
334 | rtl92c_translate_rx_signal_stuff(hw, skb, pstats: stats, pdesc: p_desc, |
335 | p_drvinfo); |
336 | } |
337 | /*rx_status->qual = stats->signal; */ |
338 | rx_status->signal = stats->recvsignalpower + 10; |
339 | return true; |
340 | } |
341 | |
342 | #define RTL_RX_DRV_INFO_UNIT 8 |
343 | |
344 | static void _rtl_rx_process(struct ieee80211_hw *hw, struct sk_buff *skb) |
345 | { |
346 | struct ieee80211_rx_status *rx_status = |
347 | (struct ieee80211_rx_status *)IEEE80211_SKB_RXCB(skb); |
348 | u32 skb_len, pkt_len, drvinfo_len; |
349 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
350 | __le32 *rxdesc; |
351 | struct rtl_stats stats = { |
352 | .signal = 0, |
353 | .rate = 0, |
354 | }; |
355 | struct rx_fwinfo_92c *p_drvinfo; |
356 | bool bv; |
357 | __le16 fc; |
358 | struct ieee80211_hdr *hdr; |
359 | |
360 | memset(rx_status, 0, sizeof(*rx_status)); |
361 | rxdesc = (__le32 *)skb->data; |
362 | skb_len = skb->len; |
363 | drvinfo_len = (get_rx_desc_drvinfo_size(rxdesc: rxdesc) * RTL_RX_DRV_INFO_UNIT); |
364 | pkt_len = get_rx_desc_pkt_len(rxdesc: rxdesc); |
365 | /* TODO: Error recovery. drop this skb or something. */ |
366 | WARN_ON(skb_len < (pkt_len + RTL_RX_DESC_SIZE + drvinfo_len)); |
367 | stats.length = (u16)get_rx_desc_pkt_len(rxdesc: rxdesc); |
368 | stats.rx_drvinfo_size = (u8)get_rx_desc_drvinfo_size(rxdesc: rxdesc) * |
369 | RX_DRV_INFO_SIZE_UNIT; |
370 | stats.rx_bufshift = (u8)(get_rx_desc_shift(rxdesc: rxdesc) & 0x03); |
371 | stats.icv = (u16)get_rx_desc_icv(rxdesc: rxdesc); |
372 | stats.crc = (u16)get_rx_desc_crc32(rxdesc: rxdesc); |
373 | stats.hwerror = (stats.crc | stats.icv); |
374 | stats.decrypted = !get_rx_desc_swdec(rxdesc: rxdesc); |
375 | stats.rate = (u8)get_rx_desc_rx_mcs(rxdesc: rxdesc); |
376 | stats.shortpreamble = (u16)get_rx_desc_splcp(rxdesc: rxdesc); |
377 | stats.isampdu = (bool)((get_rx_desc_paggr(rxdesc: rxdesc) == 1) && |
378 | (get_rx_desc_faggr(rxdesc: rxdesc) == 1)); |
379 | stats.timestamp_low = get_rx_desc_tsfl(rxdesc: rxdesc); |
380 | stats.rx_is40mhzpacket = (bool)get_rx_desc_bw(rxdesc: rxdesc); |
381 | stats.is_ht = (bool)get_rx_desc_rx_ht(rxdesc: rxdesc); |
382 | /* TODO: is center_freq changed when doing scan? */ |
383 | /* TODO: Shall we add protection or just skip those two step? */ |
384 | rx_status->freq = hw->conf.chandef.chan->center_freq; |
385 | rx_status->band = hw->conf.chandef.chan->band; |
386 | if (get_rx_desc_crc32(rxdesc: rxdesc)) |
387 | rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; |
388 | if (!get_rx_desc_swdec(rxdesc: rxdesc)) |
389 | rx_status->flag |= RX_FLAG_DECRYPTED; |
390 | if (get_rx_desc_bw(rxdesc: rxdesc)) |
391 | rx_status->bw = RATE_INFO_BW_40; |
392 | if (get_rx_desc_rx_ht(rxdesc: rxdesc)) |
393 | rx_status->encoding = RX_ENC_HT; |
394 | /* Data rate */ |
395 | rx_status->rate_idx = rtlwifi_rate_mapping(hw, isht: stats.is_ht, |
396 | isvht: false, desc_rate: stats.rate); |
397 | /* There is a phy status after this rx descriptor. */ |
398 | if (get_rx_desc_phy_status(rxdesc: rxdesc)) { |
399 | p_drvinfo = (struct rx_fwinfo_92c *)(rxdesc + RTL_RX_DESC_SIZE); |
400 | rtl92c_translate_rx_signal_stuff(hw, skb, pstats: &stats, |
401 | pdesc: (struct rx_desc_92c *)rxdesc, p_drvinfo); |
402 | } |
403 | skb_pull(skb, len: (drvinfo_len + RTL_RX_DESC_SIZE)); |
404 | hdr = rtl_get_hdr(skb); |
405 | fc = hdr->frame_control; |
406 | bv = ieee80211_is_probe_resp(fc); |
407 | if (bv) |
408 | rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, |
409 | "Got probe response frame\n" ); |
410 | if (ieee80211_is_beacon(fc)) |
411 | rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, "Got beacon frame\n" ); |
412 | if (ieee80211_is_data(fc)) |
413 | rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, "Got data frame\n" ); |
414 | rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, |
415 | "Fram: fc = 0x%X addr1 = 0x%02X:0x%02X:0x%02X:0x%02X:0x%02X:0x%02X\n" , |
416 | fc, |
417 | (u32)hdr->addr1[0], (u32)hdr->addr1[1], |
418 | (u32)hdr->addr1[2], (u32)hdr->addr1[3], |
419 | (u32)hdr->addr1[4], (u32)hdr->addr1[5]); |
420 | ieee80211_rx(hw, skb); |
421 | } |
422 | |
423 | void rtl8192cu_rx_hdl(struct ieee80211_hw *hw, struct sk_buff * skb) |
424 | { |
425 | _rtl_rx_process(hw, skb); |
426 | } |
427 | |
428 | /*---------------------------------------------------------------------- |
429 | * |
430 | * Tx handler |
431 | * |
432 | *---------------------------------------------------------------------- */ |
433 | void rtl8192c_tx_cleanup(struct ieee80211_hw *hw, struct sk_buff *skb) |
434 | { |
435 | } |
436 | |
437 | int rtl8192c_tx_post_hdl(struct ieee80211_hw *hw, struct urb *urb, |
438 | struct sk_buff *skb) |
439 | { |
440 | return 0; |
441 | } |
442 | |
443 | struct sk_buff *rtl8192c_tx_aggregate_hdl(struct ieee80211_hw *hw, |
444 | struct sk_buff_head *list) |
445 | { |
446 | return skb_dequeue(list); |
447 | } |
448 | |
449 | /*======================================== trx ===============================*/ |
450 | |
451 | static void _rtl_fill_usb_tx_desc(__le32 *txdesc) |
452 | { |
453 | set_tx_desc_own(txdesc: txdesc, value: 1); |
454 | set_tx_desc_last_seg(txdesc: txdesc, value: 1); |
455 | set_tx_desc_first_seg(txdesc: txdesc, value: 1); |
456 | } |
457 | |
458 | /* |
459 | * For HW recovery information |
460 | */ |
461 | static void _rtl_tx_desc_checksum(__le32 *txdesc) |
462 | { |
463 | __le16 *ptr = (__le16 *)txdesc; |
464 | u16 checksum = 0; |
465 | u32 index; |
466 | |
467 | /* Clear first */ |
468 | set_tx_desc_tx_desc_checksum(txdesc: txdesc, value: 0); |
469 | for (index = 0; index < 16; index++) |
470 | checksum = checksum ^ le16_to_cpu(*(ptr + index)); |
471 | set_tx_desc_tx_desc_checksum(txdesc: txdesc, value: checksum); |
472 | } |
473 | |
474 | void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, |
475 | struct ieee80211_hdr *hdr, u8 *pdesc_tx, |
476 | u8 *pbd_desc_tx, struct ieee80211_tx_info *info, |
477 | struct ieee80211_sta *sta, |
478 | struct sk_buff *skb, |
479 | u8 queue_index, |
480 | struct rtl_tcb_desc *tcb_desc) |
481 | { |
482 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
483 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
484 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); |
485 | struct rtl_sta_info *sta_entry; |
486 | u8 agg_state = RTL_AGG_STOP; |
487 | u8 ampdu_density = 0; |
488 | u16 seq_number; |
489 | __le16 fc = hdr->frame_control; |
490 | u8 rate_flag = info->control.rates[0].flags; |
491 | u16 pktlen = skb->len; |
492 | enum rtl_desc_qsel fw_qsel = _rtl8192cu_mq_to_descq(hw, fc, |
493 | mac80211_queue_index: skb_get_queue_mapping(skb)); |
494 | u8 *txdesc8; |
495 | __le32 *txdesc; |
496 | u8 tid; |
497 | |
498 | seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; |
499 | rtl_get_tcb_desc(hw, info, sta, skb, tcb_desc); |
500 | txdesc8 = skb_push(skb, RTL_TX_HEADER_SIZE); |
501 | txdesc = (__le32 *)txdesc8; |
502 | memset(txdesc, 0, RTL_TX_HEADER_SIZE); |
503 | set_tx_desc_pkt_size(txdesc: txdesc, value: pktlen); |
504 | set_tx_desc_linip(txdesc: txdesc, value: 0); |
505 | set_tx_desc_pkt_offset(txdesc: txdesc, RTL_DUMMY_OFFSET); |
506 | set_tx_desc_offset(txdesc: txdesc, RTL_TX_HEADER_SIZE); |
507 | set_tx_desc_tx_rate(pdesc: txdesc, val: tcb_desc->hw_rate); |
508 | if (tcb_desc->use_shortgi || tcb_desc->use_shortpreamble) |
509 | set_tx_desc_data_shortgi(pdesc: txdesc, val: 1); |
510 | |
511 | if (sta) { |
512 | sta_entry = (struct rtl_sta_info *)sta->drv_priv; |
513 | tid = ieee80211_get_tid(hdr); |
514 | agg_state = sta_entry->tids[tid].agg.agg_state; |
515 | ampdu_density = sta->deflink.ht_cap.ampdu_density; |
516 | } |
517 | |
518 | if (agg_state == RTL_AGG_OPERATIONAL && |
519 | info->flags & IEEE80211_TX_CTL_AMPDU) { |
520 | set_tx_desc_agg_enable(txdesc: txdesc, value: 1); |
521 | set_tx_desc_max_agg_num(txdesc: txdesc, value: 0x14); |
522 | set_tx_desc_ampdu_density(txdesc: txdesc, value: ampdu_density); |
523 | tcb_desc->rts_enable = 1; |
524 | tcb_desc->rts_rate = DESC_RATE24M; |
525 | } else { |
526 | set_tx_desc_agg_break(txdesc: txdesc, value: 1); |
527 | } |
528 | set_tx_desc_seq(txdesc: txdesc, value: seq_number); |
529 | set_tx_desc_rts_enable(txdesc: txdesc, |
530 | value: ((tcb_desc->rts_enable && |
531 | !tcb_desc->cts_enable) ? 1 : 0)); |
532 | set_tx_desc_hw_rts_enable(txdesc: txdesc, |
533 | value: ((tcb_desc->rts_enable || |
534 | tcb_desc->cts_enable) ? 1 : 0)); |
535 | set_tx_desc_cts2self(txdesc: txdesc, value: ((tcb_desc->cts_enable) ? 1 : 0)); |
536 | set_tx_desc_rts_stbc(txdesc: txdesc, value: ((tcb_desc->rts_stbc) ? 1 : 0)); |
537 | set_tx_desc_rts_rate(txdesc: txdesc, value: tcb_desc->rts_rate); |
538 | set_tx_desc_rts_bw(txdesc: txdesc, value: 0); |
539 | set_tx_desc_rts_sc(txdesc: txdesc, value: tcb_desc->rts_sc); |
540 | set_tx_desc_rts_short(txdesc: txdesc, |
541 | value: ((tcb_desc->rts_rate <= DESC_RATE54M) ? |
542 | (tcb_desc->rts_use_shortpreamble ? 1 : 0) |
543 | : (tcb_desc->rts_use_shortgi ? 1 : 0))); |
544 | if (mac->bw_40) { |
545 | if (rate_flag & IEEE80211_TX_RC_DUP_DATA) { |
546 | set_tx_desc_data_bw(txdesc: txdesc, value: 1); |
547 | set_tx_desc_data_sc(txdesc: txdesc, value: 3); |
548 | } else if(rate_flag & IEEE80211_TX_RC_40_MHZ_WIDTH){ |
549 | set_tx_desc_data_bw(txdesc: txdesc, value: 1); |
550 | set_tx_desc_data_sc(txdesc: txdesc, value: mac->cur_40_prime_sc); |
551 | } else { |
552 | set_tx_desc_data_bw(txdesc: txdesc, value: 0); |
553 | set_tx_desc_data_sc(txdesc: txdesc, value: 0); |
554 | } |
555 | } else { |
556 | set_tx_desc_data_bw(txdesc: txdesc, value: 0); |
557 | set_tx_desc_data_sc(txdesc: txdesc, value: 0); |
558 | } |
559 | if (info->control.hw_key) { |
560 | struct ieee80211_key_conf *keyconf = info->control.hw_key; |
561 | |
562 | switch (keyconf->cipher) { |
563 | case WLAN_CIPHER_SUITE_WEP40: |
564 | case WLAN_CIPHER_SUITE_WEP104: |
565 | case WLAN_CIPHER_SUITE_TKIP: |
566 | set_tx_desc_sec_type(txdesc: txdesc, value: 0x1); |
567 | break; |
568 | case WLAN_CIPHER_SUITE_CCMP: |
569 | set_tx_desc_sec_type(txdesc: txdesc, value: 0x3); |
570 | break; |
571 | default: |
572 | set_tx_desc_sec_type(txdesc: txdesc, value: 0x0); |
573 | break; |
574 | } |
575 | } |
576 | set_tx_desc_pkt_id(txdesc: txdesc, value: 0); |
577 | set_tx_desc_queue_sel(txdesc: txdesc, value: fw_qsel); |
578 | set_tx_desc_data_rate_fb_limit(txdesc: txdesc, value: 0x1F); |
579 | set_tx_desc_rts_rate_fb_limit(txdesc: txdesc, value: 0xF); |
580 | set_tx_desc_disable_fb(txdesc: txdesc, value: 0); |
581 | set_tx_desc_use_rate(txdesc: txdesc, value: tcb_desc->use_driver_rate ? 1 : 0); |
582 | if (ieee80211_is_data_qos(fc)) { |
583 | if (mac->rdg_en) { |
584 | rtl_dbg(rtlpriv, COMP_SEND, DBG_TRACE, |
585 | "Enable RDG function\n" ); |
586 | set_tx_desc_rdg_enable(txdesc: txdesc, value: 1); |
587 | set_tx_desc_htc(txdesc: txdesc, value: 1); |
588 | } |
589 | } |
590 | if (rtlpriv->dm.useramask) { |
591 | set_tx_desc_rate_id(txdesc: txdesc, value: tcb_desc->ratr_index); |
592 | set_tx_desc_macid(txdesc: txdesc, value: tcb_desc->mac_id); |
593 | } else { |
594 | set_tx_desc_rate_id(txdesc: txdesc, value: 0xC + tcb_desc->ratr_index); |
595 | set_tx_desc_macid(txdesc: txdesc, value: tcb_desc->ratr_index); |
596 | } |
597 | if ((!ieee80211_is_data_qos(fc)) && ppsc->leisure_ps && |
598 | ppsc->fwctrl_lps) { |
599 | set_tx_desc_hwseq_en(txdesc: txdesc, value: 1); |
600 | set_tx_desc_pkt_id(txdesc: txdesc, value: 8); |
601 | } |
602 | if (ieee80211_has_morefrags(fc)) |
603 | set_tx_desc_more_frag(txdesc: txdesc, value: 1); |
604 | if (is_multicast_ether_addr(addr: ieee80211_get_DA(hdr)) || |
605 | is_broadcast_ether_addr(addr: ieee80211_get_DA(hdr))) |
606 | set_tx_desc_bmc(txdesc: txdesc, value: 1); |
607 | _rtl_fill_usb_tx_desc(txdesc); |
608 | _rtl_tx_desc_checksum(txdesc); |
609 | rtl_dbg(rtlpriv, COMP_SEND, DBG_TRACE, "==>\n" ); |
610 | } |
611 | |
612 | void rtl92cu_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc8, |
613 | struct sk_buff *skb) |
614 | { |
615 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
616 | u8 fw_queue = QSLT_BEACON; |
617 | struct ieee80211_hdr *hdr = rtl_get_hdr(skb); |
618 | __le16 fc = hdr->frame_control; |
619 | __le32 *pdesc = (__le32 *)pdesc8; |
620 | |
621 | memset((void *)pdesc, 0, RTL_TX_HEADER_SIZE); |
622 | set_tx_desc_offset(txdesc: pdesc, RTL_TX_HEADER_SIZE); |
623 | set_tx_desc_tx_rate(pdesc: pdesc, val: DESC_RATE1M); |
624 | set_tx_desc_seq(txdesc: pdesc, value: 0); |
625 | set_tx_desc_linip(txdesc: pdesc, value: 0); |
626 | set_tx_desc_queue_sel(txdesc: pdesc, value: fw_queue); |
627 | set_tx_desc_first_seg(txdesc: pdesc, value: 1); |
628 | set_tx_desc_last_seg(txdesc: pdesc, value: 1); |
629 | set_tx_desc_rate_id(txdesc: pdesc, value: 7); |
630 | set_tx_desc_macid(txdesc: pdesc, value: 0); |
631 | set_tx_desc_own(txdesc: pdesc, value: 1); |
632 | set_tx_desc_pkt_size(txdesc: pdesc, value: (u16)skb->len); |
633 | set_tx_desc_first_seg(txdesc: pdesc, value: 1); |
634 | set_tx_desc_last_seg(txdesc: pdesc, value: 1); |
635 | set_tx_desc_offset(txdesc: pdesc, value: 0x20); |
636 | set_tx_desc_use_rate(txdesc: pdesc, value: 1); |
637 | if (!ieee80211_is_data_qos(fc)) { |
638 | set_tx_desc_hwseq_en(txdesc: pdesc, value: 1); |
639 | set_tx_desc_pkt_id(txdesc: pdesc, value: 8); |
640 | } |
641 | RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, "H2C Tx Cmd Content" , |
642 | pdesc, RTL_TX_DESC_SIZE); |
643 | } |
644 | |