Commit | Line | Data |
---|---|---|
29d00a3e G |
1 | /****************************************************************************** |
2 | * | |
3 | * Copyright(c) 2009-2010 Realtek Corporation. All rights reserved. | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify it | |
6 | * under the terms of version 2 of the GNU General Public License as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | |
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
12 | * more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along with | |
15 | * this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | |
17 | * | |
18 | * The full GNU General Public License is included in this distribution in the | |
19 | * file called LICENSE. | |
20 | * | |
21 | * Contact Information: | |
22 | * wlanfae <wlanfae@realtek.com> | |
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | |
24 | * Hsinchu 300, Taiwan. | |
25 | * | |
26 | * Larry Finger <Larry.Finger@lwfinger.net> | |
27 | * | |
28 | *****************************************************************************/ | |
29 | ||
30 | #include "../wifi.h" | |
31 | #include "../usb.h" | |
32 | #include "../ps.h" | |
33 | #include "../base.h" | |
34 | #include "reg.h" | |
35 | #include "def.h" | |
36 | #include "phy.h" | |
37 | #include "rf.h" | |
38 | #include "dm.h" | |
39 | #include "mac.h" | |
40 | #include "trx.h" | |
41 | ||
42 | static int _ConfigVerTOutEP(struct ieee80211_hw *hw) | |
43 | { | |
44 | u8 ep_cfg, txqsele; | |
45 | u8 ep_nums = 0; | |
46 | ||
47 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
48 | struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw); | |
49 | struct rtl_usb *rtlusb = rtl_usbdev(usb_priv); | |
50 | ||
51 | rtlusb->out_queue_sel = 0; | |
52 | ep_cfg = rtl_read_byte(rtlpriv, REG_TEST_SIE_OPTIONAL); | |
53 | ep_cfg = (ep_cfg & USB_TEST_EP_MASK) >> USB_TEST_EP_SHIFT; | |
54 | switch (ep_cfg) { | |
55 | case 0: /* 2 bulk OUT, 1 bulk IN */ | |
56 | case 3: | |
57 | rtlusb->out_queue_sel = TX_SELE_HQ | TX_SELE_LQ; | |
58 | ep_nums = 2; | |
59 | break; | |
60 | case 1: /* 1 bulk IN/OUT => map all endpoint to Low queue */ | |
61 | case 2: /* 1 bulk IN, 1 bulk OUT => map all endpoint to High queue */ | |
62 | txqsele = rtl_read_byte(rtlpriv, REG_TEST_USB_TXQS); | |
63 | if (txqsele & 0x0F) /* /map all endpoint to High queue */ | |
64 | rtlusb->out_queue_sel = TX_SELE_HQ; | |
65 | else if (txqsele&0xF0) /* map all endpoint to Low queue */ | |
66 | rtlusb->out_queue_sel = TX_SELE_LQ; | |
67 | ep_nums = 1; | |
68 | break; | |
69 | default: | |
70 | break; | |
71 | } | |
72 | return (rtlusb->out_ep_nums == ep_nums) ? 0 : -EINVAL; | |
73 | } | |
74 | ||
75 | static int _ConfigVerNOutEP(struct ieee80211_hw *hw) | |
76 | { | |
77 | u8 ep_cfg; | |
78 | u8 ep_nums = 0; | |
79 | ||
80 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
81 | struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw); | |
82 | struct rtl_usb *rtlusb = rtl_usbdev(usb_priv); | |
83 | ||
84 | rtlusb->out_queue_sel = 0; | |
85 | /* Normal and High queue */ | |
86 | ep_cfg = rtl_read_byte(rtlpriv, (REG_NORMAL_SIE_EP + 1)); | |
87 | if (ep_cfg & USB_NORMAL_SIE_EP_MASK) { | |
88 | rtlusb->out_queue_sel |= TX_SELE_HQ; | |
89 | ep_nums++; | |
90 | } | |
91 | if ((ep_cfg >> USB_NORMAL_SIE_EP_SHIFT) & USB_NORMAL_SIE_EP_MASK) { | |
92 | rtlusb->out_queue_sel |= TX_SELE_NQ; | |
93 | ep_nums++; | |
94 | } | |
95 | /* Low queue */ | |
96 | ep_cfg = rtl_read_byte(rtlpriv, (REG_NORMAL_SIE_EP + 2)); | |
97 | if (ep_cfg & USB_NORMAL_SIE_EP_MASK) { | |
98 | rtlusb->out_queue_sel |= TX_SELE_LQ; | |
99 | ep_nums++; | |
100 | } | |
101 | return (rtlusb->out_ep_nums == ep_nums) ? 0 : -EINVAL; | |
102 | } | |
103 | ||
104 | static void _TwoOutEpMapping(struct ieee80211_hw *hw, bool bIsChipB, | |
105 | bool bwificfg, struct rtl_ep_map *ep_map) | |
106 | { | |
107 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
108 | ||
109 | if (bwificfg) { /* for WMM */ | |
110 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, | |
111 | ("USB Chip-B & WMM Setting.....\n")); | |
112 | ep_map->ep_mapping[RTL_TXQ_BE] = 2; | |
113 | ep_map->ep_mapping[RTL_TXQ_BK] = 3; | |
114 | ep_map->ep_mapping[RTL_TXQ_VI] = 3; | |
115 | ep_map->ep_mapping[RTL_TXQ_VO] = 2; | |
116 | ep_map->ep_mapping[RTL_TXQ_MGT] = 2; | |
117 | ep_map->ep_mapping[RTL_TXQ_BCN] = 2; | |
118 | ep_map->ep_mapping[RTL_TXQ_HI] = 2; | |
119 | } else { /* typical setting */ | |
120 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, | |
121 | ("USB typical Setting.....\n")); | |
122 | ep_map->ep_mapping[RTL_TXQ_BE] = 3; | |
123 | ep_map->ep_mapping[RTL_TXQ_BK] = 3; | |
124 | ep_map->ep_mapping[RTL_TXQ_VI] = 2; | |
125 | ep_map->ep_mapping[RTL_TXQ_VO] = 2; | |
126 | ep_map->ep_mapping[RTL_TXQ_MGT] = 2; | |
127 | ep_map->ep_mapping[RTL_TXQ_BCN] = 2; | |
128 | ep_map->ep_mapping[RTL_TXQ_HI] = 2; | |
129 | } | |
130 | } | |
131 | ||
132 | static void _ThreeOutEpMapping(struct ieee80211_hw *hw, bool bwificfg, | |
133 | struct rtl_ep_map *ep_map) | |
134 | { | |
135 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
136 | if (bwificfg) { /* for WMM */ | |
137 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, | |
138 | ("USB 3EP Setting for WMM.....\n")); | |
139 | ep_map->ep_mapping[RTL_TXQ_BE] = 5; | |
140 | ep_map->ep_mapping[RTL_TXQ_BK] = 3; | |
141 | ep_map->ep_mapping[RTL_TXQ_VI] = 3; | |
142 | ep_map->ep_mapping[RTL_TXQ_VO] = 2; | |
143 | ep_map->ep_mapping[RTL_TXQ_MGT] = 2; | |
144 | ep_map->ep_mapping[RTL_TXQ_BCN] = 2; | |
145 | ep_map->ep_mapping[RTL_TXQ_HI] = 2; | |
146 | } else { /* typical setting */ | |
147 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, | |
148 | ("USB 3EP Setting for typical.....\n")); | |
149 | ep_map->ep_mapping[RTL_TXQ_BE] = 5; | |
150 | ep_map->ep_mapping[RTL_TXQ_BK] = 5; | |
151 | ep_map->ep_mapping[RTL_TXQ_VI] = 3; | |
152 | ep_map->ep_mapping[RTL_TXQ_VO] = 2; | |
153 | ep_map->ep_mapping[RTL_TXQ_MGT] = 2; | |
154 | ep_map->ep_mapping[RTL_TXQ_BCN] = 2; | |
155 | ep_map->ep_mapping[RTL_TXQ_HI] = 2; | |
156 | } | |
157 | } | |
158 | ||
159 | static void _OneOutEpMapping(struct ieee80211_hw *hw, struct rtl_ep_map *ep_map) | |
160 | { | |
161 | ep_map->ep_mapping[RTL_TXQ_BE] = 2; | |
162 | ep_map->ep_mapping[RTL_TXQ_BK] = 2; | |
163 | ep_map->ep_mapping[RTL_TXQ_VI] = 2; | |
164 | ep_map->ep_mapping[RTL_TXQ_VO] = 2; | |
165 | ep_map->ep_mapping[RTL_TXQ_MGT] = 2; | |
166 | ep_map->ep_mapping[RTL_TXQ_BCN] = 2; | |
167 | ep_map->ep_mapping[RTL_TXQ_HI] = 2; | |
168 | } | |
169 | static int _out_ep_mapping(struct ieee80211_hw *hw) | |
170 | { | |
171 | int err = 0; | |
172 | bool bIsChipN, bwificfg = false; | |
173 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | |
174 | struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw); | |
175 | struct rtl_usb *rtlusb = rtl_usbdev(usb_priv); | |
176 | struct rtl_ep_map *ep_map = &(rtlusb->ep_map); | |
177 | ||
178 | bIsChipN = IS_NORMAL_CHIP(rtlhal->version); | |
179 | switch (rtlusb->out_ep_nums) { | |
180 | case 2: | |
181 | _TwoOutEpMapping(hw, bIsChipN, bwificfg, ep_map); | |
182 | break; | |
183 | case 3: | |
184 | /* Test chip doesn't support three out EPs. */ | |
185 | if (!bIsChipN) { | |
186 | err = -EINVAL; | |
187 | goto err_out; | |
188 | } | |
189 | _ThreeOutEpMapping(hw, bIsChipN, ep_map); | |
190 | break; | |
191 | case 1: | |
192 | _OneOutEpMapping(hw, ep_map); | |
193 | break; | |
194 | default: | |
195 | err = -EINVAL; | |
196 | break; | |
197 | } | |
198 | err_out: | |
199 | return err; | |
200 | ||
201 | } | |
202 | /* endpoint mapping */ | |
203 | int rtl8192cu_endpoint_mapping(struct ieee80211_hw *hw) | |
204 | { | |
205 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | |
206 | int error = 0; | |
207 | if (likely(IS_NORMAL_CHIP(rtlhal->version))) | |
208 | error = _ConfigVerNOutEP(hw); | |
209 | else | |
210 | error = _ConfigVerTOutEP(hw); | |
211 | if (error) | |
212 | goto err_out; | |
213 | error = _out_ep_mapping(hw); | |
214 | if (error) | |
215 | goto err_out; | |
216 | err_out: | |
217 | return error; | |
218 | } | |
219 | ||
220 | u16 rtl8192cu_mq_to_hwq(__le16 fc, u16 mac80211_queue_index) | |
221 | { | |
222 | u16 hw_queue_index; | |
223 | ||
224 | if (unlikely(ieee80211_is_beacon(fc))) { | |
225 | hw_queue_index = RTL_TXQ_BCN; | |
226 | goto out; | |
227 | } | |
228 | if (ieee80211_is_mgmt(fc)) { | |
229 | hw_queue_index = RTL_TXQ_MGT; | |
230 | goto out; | |
231 | } | |
232 | switch (mac80211_queue_index) { | |
233 | case 0: | |
234 | hw_queue_index = RTL_TXQ_VO; | |
235 | break; | |
236 | case 1: | |
237 | hw_queue_index = RTL_TXQ_VI; | |
238 | break; | |
239 | case 2: | |
240 | hw_queue_index = RTL_TXQ_BE; | |
241 | break; | |
242 | case 3: | |
243 | hw_queue_index = RTL_TXQ_BK; | |
244 | break; | |
245 | default: | |
246 | hw_queue_index = RTL_TXQ_BE; | |
247 | RT_ASSERT(false, ("QSLT_BE queue, skb_queue:%d\n", | |
248 | mac80211_queue_index)); | |
249 | break; | |
250 | } | |
251 | out: | |
252 | return hw_queue_index; | |
253 | } | |
254 | ||
255 | static enum rtl_desc_qsel _rtl8192cu_mq_to_descq(struct ieee80211_hw *hw, | |
256 | __le16 fc, u16 mac80211_queue_index) | |
257 | { | |
258 | enum rtl_desc_qsel qsel; | |
259 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
260 | ||
261 | if (unlikely(ieee80211_is_beacon(fc))) { | |
262 | qsel = QSLT_BEACON; | |
263 | goto out; | |
264 | } | |
265 | if (ieee80211_is_mgmt(fc)) { | |
266 | qsel = QSLT_MGNT; | |
267 | goto out; | |
268 | } | |
269 | switch (mac80211_queue_index) { | |
270 | case 0: /* VO */ | |
271 | qsel = QSLT_VO; | |
272 | RT_TRACE(rtlpriv, COMP_USB, DBG_DMESG, | |
273 | ("VO queue, set qsel = 0x%x\n", QSLT_VO)); | |
274 | break; | |
275 | case 1: /* VI */ | |
276 | qsel = QSLT_VI; | |
277 | RT_TRACE(rtlpriv, COMP_USB, DBG_DMESG, | |
278 | ("VI queue, set qsel = 0x%x\n", QSLT_VI)); | |
279 | break; | |
280 | case 3: /* BK */ | |
281 | qsel = QSLT_BK; | |
282 | RT_TRACE(rtlpriv, COMP_USB, DBG_DMESG, | |
283 | ("BK queue, set qsel = 0x%x\n", QSLT_BK)); | |
284 | break; | |
285 | case 2: /* BE */ | |
286 | default: | |
287 | qsel = QSLT_BE; | |
288 | RT_TRACE(rtlpriv, COMP_USB, DBG_DMESG, | |
289 | ("BE queue, set qsel = 0x%x\n", QSLT_BE)); | |
290 | break; | |
291 | } | |
292 | out: | |
293 | return qsel; | |
294 | } | |
295 | ||
296 | /* =============================================================== */ | |
297 | ||
298 | /*---------------------------------------------------------------------- | |
299 | * | |
300 | * Rx handler | |
301 | * | |
302 | *---------------------------------------------------------------------- */ | |
303 | bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw, | |
304 | struct rtl_stats *stats, | |
305 | struct ieee80211_rx_status *rx_status, | |
306 | u8 *p_desc, struct sk_buff *skb) | |
307 | { | |
308 | struct rx_fwinfo_92c *p_drvinfo; | |
309 | struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc; | |
310 | u32 phystatus = GET_RX_DESC_PHY_STATUS(pdesc); | |
311 | ||
312 | stats->length = (u16) GET_RX_DESC_PKT_LEN(pdesc); | |
313 | stats->rx_drvinfo_size = (u8)GET_RX_DESC_DRVINFO_SIZE(pdesc) * | |
314 | RX_DRV_INFO_SIZE_UNIT; | |
315 | stats->rx_bufshift = (u8) (GET_RX_DESC_SHIFT(pdesc) & 0x03); | |
316 | stats->icv = (u16) GET_RX_DESC_ICV(pdesc); | |
317 | stats->crc = (u16) GET_RX_DESC_CRC32(pdesc); | |
318 | stats->hwerror = (stats->crc | stats->icv); | |
319 | stats->decrypted = !GET_RX_DESC_SWDEC(pdesc); | |
320 | stats->rate = (u8) GET_RX_DESC_RX_MCS(pdesc); | |
321 | stats->shortpreamble = (u16) GET_RX_DESC_SPLCP(pdesc); | |
322 | stats->isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1); | |
323 | stats->isampdu = (bool) ((GET_RX_DESC_PAGGR(pdesc) == 1) | |
324 | && (GET_RX_DESC_FAGGR(pdesc) == 1)); | |
325 | stats->timestamp_low = GET_RX_DESC_TSFL(pdesc); | |
326 | stats->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc); | |
327 | rx_status->freq = hw->conf.channel->center_freq; | |
328 | rx_status->band = hw->conf.channel->band; | |
329 | if (GET_RX_DESC_CRC32(pdesc)) | |
330 | rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; | |
331 | if (!GET_RX_DESC_SWDEC(pdesc)) | |
332 | rx_status->flag |= RX_FLAG_DECRYPTED; | |
333 | if (GET_RX_DESC_BW(pdesc)) | |
334 | rx_status->flag |= RX_FLAG_40MHZ; | |
335 | if (GET_RX_DESC_RX_HT(pdesc)) | |
336 | rx_status->flag |= RX_FLAG_HT; | |
337 | rx_status->flag |= RX_FLAG_TSFT; | |
338 | if (stats->decrypted) | |
339 | rx_status->flag |= RX_FLAG_DECRYPTED; | |
340 | rx_status->rate_idx = _rtl92c_rate_mapping(hw, | |
341 | (bool)GET_RX_DESC_RX_HT(pdesc), | |
342 | (u8)GET_RX_DESC_RX_MCS(pdesc), | |
343 | (bool)GET_RX_DESC_PAGGR(pdesc)); | |
344 | rx_status->mactime = GET_RX_DESC_TSFL(pdesc); | |
345 | if (phystatus == true) { | |
346 | p_drvinfo = (struct rx_fwinfo_92c *)(pdesc + RTL_RX_DESC_SIZE); | |
347 | rtl92c_translate_rx_signal_stuff(hw, skb, stats, pdesc, | |
348 | p_drvinfo); | |
349 | } | |
350 | /*rx_status->qual = stats->signal; */ | |
351 | rx_status->signal = stats->rssi + 10; | |
352 | /*rx_status->noise = -stats->noise; */ | |
353 | return true; | |
354 | } | |
355 | ||
356 | #define RTL_RX_DRV_INFO_UNIT 8 | |
357 | ||
358 | static void _rtl_rx_process(struct ieee80211_hw *hw, struct sk_buff *skb) | |
359 | { | |
360 | struct ieee80211_rx_status *rx_status = | |
361 | (struct ieee80211_rx_status *)IEEE80211_SKB_RXCB(skb); | |
362 | u32 skb_len, pkt_len, drvinfo_len; | |
363 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
364 | u8 *rxdesc; | |
365 | struct rtl_stats stats = { | |
366 | .signal = 0, | |
367 | .noise = -98, | |
368 | .rate = 0, | |
369 | }; | |
370 | struct rx_fwinfo_92c *p_drvinfo; | |
371 | bool bv; | |
372 | __le16 fc; | |
373 | struct ieee80211_hdr *hdr; | |
374 | ||
375 | memset(rx_status, 0, sizeof(rx_status)); | |
376 | rxdesc = skb->data; | |
377 | skb_len = skb->len; | |
378 | drvinfo_len = (GET_RX_DESC_DRVINFO_SIZE(rxdesc) * RTL_RX_DRV_INFO_UNIT); | |
379 | pkt_len = GET_RX_DESC_PKT_LEN(rxdesc); | |
380 | /* TODO: Error recovery. drop this skb or something. */ | |
381 | WARN_ON(skb_len < (pkt_len + RTL_RX_DESC_SIZE + drvinfo_len)); | |
382 | stats.length = (u16) GET_RX_DESC_PKT_LEN(rxdesc); | |
383 | stats.rx_drvinfo_size = (u8)GET_RX_DESC_DRVINFO_SIZE(rxdesc) * | |
384 | RX_DRV_INFO_SIZE_UNIT; | |
385 | stats.rx_bufshift = (u8) (GET_RX_DESC_SHIFT(rxdesc) & 0x03); | |
386 | stats.icv = (u16) GET_RX_DESC_ICV(rxdesc); | |
387 | stats.crc = (u16) GET_RX_DESC_CRC32(rxdesc); | |
388 | stats.hwerror = (stats.crc | stats.icv); | |
389 | stats.decrypted = !GET_RX_DESC_SWDEC(rxdesc); | |
390 | stats.rate = (u8) GET_RX_DESC_RX_MCS(rxdesc); | |
391 | stats.shortpreamble = (u16) GET_RX_DESC_SPLCP(rxdesc); | |
392 | stats.isampdu = (bool) ((GET_RX_DESC_PAGGR(rxdesc) == 1) | |
393 | && (GET_RX_DESC_FAGGR(rxdesc) == 1)); | |
394 | stats.timestamp_low = GET_RX_DESC_TSFL(rxdesc); | |
395 | stats.rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(rxdesc); | |
396 | /* TODO: is center_freq changed when doing scan? */ | |
397 | /* TODO: Shall we add protection or just skip those two step? */ | |
398 | rx_status->freq = hw->conf.channel->center_freq; | |
399 | rx_status->band = hw->conf.channel->band; | |
400 | if (GET_RX_DESC_CRC32(rxdesc)) | |
401 | rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; | |
402 | if (!GET_RX_DESC_SWDEC(rxdesc)) | |
403 | rx_status->flag |= RX_FLAG_DECRYPTED; | |
404 | if (GET_RX_DESC_BW(rxdesc)) | |
405 | rx_status->flag |= RX_FLAG_40MHZ; | |
406 | if (GET_RX_DESC_RX_HT(rxdesc)) | |
407 | rx_status->flag |= RX_FLAG_HT; | |
408 | /* Data rate */ | |
409 | rx_status->rate_idx = _rtl92c_rate_mapping(hw, | |
410 | (bool)GET_RX_DESC_RX_HT(rxdesc), | |
411 | (u8)GET_RX_DESC_RX_MCS(rxdesc), | |
412 | (bool)GET_RX_DESC_PAGGR(rxdesc) | |
413 | ); | |
414 | /* There is a phy status after this rx descriptor. */ | |
415 | if (GET_RX_DESC_PHY_STATUS(rxdesc)) { | |
416 | p_drvinfo = (struct rx_fwinfo_92c *)(rxdesc + RTL_RX_DESC_SIZE); | |
417 | rtl92c_translate_rx_signal_stuff(hw, skb, &stats, | |
418 | (struct rx_desc_92c *)rxdesc, p_drvinfo); | |
419 | } | |
420 | skb_pull(skb, (drvinfo_len + RTL_RX_DESC_SIZE)); | |
421 | hdr = (struct ieee80211_hdr *)(skb->data); | |
422 | fc = hdr->frame_control; | |
423 | bv = ieee80211_is_probe_resp(fc); | |
424 | if (bv) | |
425 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, | |
426 | ("Got probe response frame.\n")); | |
427 | if (ieee80211_is_beacon(fc)) | |
428 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, | |
429 | ("Got beacon frame.\n")); | |
430 | if (ieee80211_is_data(fc)) | |
431 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("Got data frame.\n")); | |
432 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, | |
433 | ("Fram: fc = 0x%X addr1 = 0x%02X:0x%02X:0x%02X:0x%02X:0x%02X:" | |
434 | "0x%02X\n", fc, (u32)hdr->addr1[0], (u32)hdr->addr1[1], | |
435 | (u32)hdr->addr1[2], (u32)hdr->addr1[3], (u32)hdr->addr1[4], | |
436 | (u32)hdr->addr1[5])); | |
437 | memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); | |
438 | ieee80211_rx_irqsafe(hw, skb); | |
439 | } | |
440 | ||
441 | void rtl8192cu_rx_hdl(struct ieee80211_hw *hw, struct sk_buff * skb) | |
442 | { | |
443 | _rtl_rx_process(hw, skb); | |
444 | } | |
445 | ||
446 | void rtl8192c_rx_segregate_hdl( | |
447 | struct ieee80211_hw *hw, | |
448 | struct sk_buff *skb, | |
449 | struct sk_buff_head *skb_list) | |
450 | { | |
451 | } | |
452 | ||
453 | /*---------------------------------------------------------------------- | |
454 | * | |
455 | * Tx handler | |
456 | * | |
457 | *---------------------------------------------------------------------- */ | |
458 | void rtl8192c_tx_cleanup(struct ieee80211_hw *hw, struct sk_buff *skb) | |
459 | { | |
460 | } | |
461 | ||
462 | int rtl8192c_tx_post_hdl(struct ieee80211_hw *hw, struct urb *urb, | |
463 | struct sk_buff *skb) | |
464 | { | |
465 | return 0; | |
466 | } | |
467 | ||
468 | struct sk_buff *rtl8192c_tx_aggregate_hdl(struct ieee80211_hw *hw, | |
469 | struct sk_buff_head *list) | |
470 | { | |
471 | return skb_dequeue(list); | |
472 | } | |
473 | ||
474 | /*======================================== trx ===============================*/ | |
475 | ||
476 | static void _rtl_fill_usb_tx_desc(u8 *txdesc) | |
477 | { | |
478 | SET_TX_DESC_OWN(txdesc, 1); | |
479 | SET_TX_DESC_LAST_SEG(txdesc, 1); | |
480 | SET_TX_DESC_FIRST_SEG(txdesc, 1); | |
481 | } | |
482 | /** | |
483 | * For HW recovery information | |
484 | */ | |
485 | static void _rtl_tx_desc_checksum(u8 *txdesc) | |
486 | { | |
487 | u16 *ptr = (u16 *)txdesc; | |
488 | u16 checksum = 0; | |
489 | u32 index; | |
490 | ||
491 | /* Clear first */ | |
492 | SET_TX_DESC_TX_DESC_CHECKSUM(txdesc, 0); | |
493 | for (index = 0; index < 16; index++) | |
494 | checksum = checksum ^ (*(ptr + index)); | |
495 | SET_TX_DESC_TX_DESC_CHECKSUM(txdesc, checksum); | |
496 | } | |
497 | ||
498 | void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, | |
499 | struct ieee80211_hdr *hdr, u8 *pdesc_tx, | |
500 | struct ieee80211_tx_info *info, struct sk_buff *skb, | |
501 | unsigned int queue_index) | |
502 | { | |
503 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
504 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | |
505 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | |
506 | bool defaultadapter = true; | |
507 | struct ieee80211_sta *sta = ieee80211_find_sta(mac->vif, mac->bssid); | |
508 | struct rtl_tcb_desc tcb_desc; | |
509 | u8 *qc = ieee80211_get_qos_ctl(hdr); | |
510 | u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; | |
511 | u16 seq_number; | |
512 | __le16 fc = hdr->frame_control; | |
513 | u8 rate_flag = info->control.rates[0].flags; | |
514 | u16 pktlen = skb->len; | |
515 | enum rtl_desc_qsel fw_qsel = _rtl8192cu_mq_to_descq(hw, fc, | |
516 | skb_get_queue_mapping(skb)); | |
517 | u8 *txdesc; | |
518 | ||
519 | seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; | |
520 | rtl_get_tcb_desc(hw, info, skb, &tcb_desc); | |
521 | txdesc = (u8 *)skb_push(skb, RTL_TX_HEADER_SIZE); | |
522 | memset(txdesc, 0, RTL_TX_HEADER_SIZE); | |
523 | SET_TX_DESC_PKT_SIZE(txdesc, pktlen); | |
524 | SET_TX_DESC_LINIP(txdesc, 0); | |
525 | SET_TX_DESC_PKT_OFFSET(txdesc, RTL_DUMMY_OFFSET); | |
526 | SET_TX_DESC_OFFSET(txdesc, RTL_TX_HEADER_SIZE); | |
527 | SET_TX_DESC_TX_RATE(txdesc, tcb_desc.hw_rate); | |
528 | if (tcb_desc.use_shortgi || tcb_desc.use_shortpreamble) | |
529 | SET_TX_DESC_DATA_SHORTGI(txdesc, 1); | |
530 | if (mac->tids[tid].agg.agg_state == RTL_AGG_ON && | |
531 | info->flags & IEEE80211_TX_CTL_AMPDU) { | |
532 | SET_TX_DESC_AGG_ENABLE(txdesc, 1); | |
533 | SET_TX_DESC_MAX_AGG_NUM(txdesc, 0x14); | |
534 | } else { | |
535 | SET_TX_DESC_AGG_BREAK(txdesc, 1); | |
536 | } | |
537 | SET_TX_DESC_SEQ(txdesc, seq_number); | |
538 | SET_TX_DESC_RTS_ENABLE(txdesc, ((tcb_desc.rts_enable && | |
539 | !tcb_desc.cts_enable) ? 1 : 0)); | |
540 | SET_TX_DESC_HW_RTS_ENABLE(txdesc, ((tcb_desc.rts_enable || | |
541 | tcb_desc.cts_enable) ? 1 : 0)); | |
542 | SET_TX_DESC_CTS2SELF(txdesc, ((tcb_desc.cts_enable) ? 1 : 0)); | |
543 | SET_TX_DESC_RTS_STBC(txdesc, ((tcb_desc.rts_stbc) ? 1 : 0)); | |
544 | SET_TX_DESC_RTS_RATE(txdesc, tcb_desc.rts_rate); | |
545 | SET_TX_DESC_RTS_BW(txdesc, 0); | |
546 | SET_TX_DESC_RTS_SC(txdesc, tcb_desc.rts_sc); | |
547 | SET_TX_DESC_RTS_SHORT(txdesc, | |
548 | ((tcb_desc.rts_rate <= DESC92C_RATE54M) ? | |
549 | (tcb_desc.rts_use_shortpreamble ? 1 : 0) | |
550 | : (tcb_desc.rts_use_shortgi ? 1 : 0))); | |
551 | if (mac->bw_40) { | |
552 | if (tcb_desc.packet_bw) { | |
553 | SET_TX_DESC_DATA_BW(txdesc, 1); | |
554 | SET_TX_DESC_DATA_SC(txdesc, 3); | |
555 | } else { | |
556 | SET_TX_DESC_DATA_BW(txdesc, 0); | |
557 | if (rate_flag & IEEE80211_TX_RC_DUP_DATA) | |
558 | SET_TX_DESC_DATA_SC(txdesc, | |
559 | mac->cur_40_prime_sc); | |
560 | } | |
561 | } else { | |
562 | SET_TX_DESC_DATA_BW(txdesc, 0); | |
563 | SET_TX_DESC_DATA_SC(txdesc, 0); | |
564 | } | |
565 | if (sta) { | |
566 | u8 ampdu_density = sta->ht_cap.ampdu_density; | |
567 | SET_TX_DESC_AMPDU_DENSITY(txdesc, ampdu_density); | |
568 | } | |
569 | if (info->control.hw_key) { | |
570 | struct ieee80211_key_conf *keyconf = info->control.hw_key; | |
571 | switch (keyconf->cipher) { | |
572 | case WLAN_CIPHER_SUITE_WEP40: | |
573 | case WLAN_CIPHER_SUITE_WEP104: | |
574 | case WLAN_CIPHER_SUITE_TKIP: | |
575 | SET_TX_DESC_SEC_TYPE(txdesc, 0x1); | |
576 | break; | |
577 | case WLAN_CIPHER_SUITE_CCMP: | |
578 | SET_TX_DESC_SEC_TYPE(txdesc, 0x3); | |
579 | break; | |
580 | default: | |
581 | SET_TX_DESC_SEC_TYPE(txdesc, 0x0); | |
582 | break; | |
583 | } | |
584 | } | |
585 | SET_TX_DESC_PKT_ID(txdesc, 0); | |
586 | SET_TX_DESC_QUEUE_SEL(txdesc, fw_qsel); | |
587 | SET_TX_DESC_DATA_RATE_FB_LIMIT(txdesc, 0x1F); | |
588 | SET_TX_DESC_RTS_RATE_FB_LIMIT(txdesc, 0xF); | |
589 | SET_TX_DESC_DISABLE_FB(txdesc, 0); | |
590 | SET_TX_DESC_USE_RATE(txdesc, tcb_desc.use_driver_rate ? 1 : 0); | |
591 | if (ieee80211_is_data_qos(fc)) { | |
592 | if (mac->rdg_en) { | |
593 | RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, | |
594 | ("Enable RDG function.\n")); | |
595 | SET_TX_DESC_RDG_ENABLE(txdesc, 1); | |
596 | SET_TX_DESC_HTC(txdesc, 1); | |
597 | } | |
598 | } | |
599 | if (rtlpriv->dm.useramask) { | |
600 | SET_TX_DESC_RATE_ID(txdesc, tcb_desc.ratr_index); | |
601 | SET_TX_DESC_MACID(txdesc, tcb_desc.mac_id); | |
602 | } else { | |
603 | SET_TX_DESC_RATE_ID(txdesc, 0xC + tcb_desc.ratr_index); | |
604 | SET_TX_DESC_MACID(txdesc, tcb_desc.ratr_index); | |
605 | } | |
606 | if ((!ieee80211_is_data_qos(fc)) && ppsc->leisure_ps && | |
607 | ppsc->fwctrl_lps) { | |
608 | SET_TX_DESC_HWSEQ_EN(txdesc, 1); | |
609 | SET_TX_DESC_PKT_ID(txdesc, 8); | |
610 | if (!defaultadapter) | |
611 | SET_TX_DESC_QOS(txdesc, 1); | |
612 | } | |
613 | if (ieee80211_has_morefrags(fc)) | |
614 | SET_TX_DESC_MORE_FRAG(txdesc, 1); | |
615 | if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) || | |
616 | is_broadcast_ether_addr(ieee80211_get_DA(hdr))) | |
617 | SET_TX_DESC_BMC(txdesc, 1); | |
618 | _rtl_fill_usb_tx_desc(txdesc); | |
619 | _rtl_tx_desc_checksum(txdesc); | |
620 | RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, (" %s ==>\n", __func__)); | |
621 | } | |
622 | ||
623 | void rtl92cu_fill_fake_txdesc(struct ieee80211_hw *hw, u8 * pDesc, | |
624 | u32 buffer_len, bool bIsPsPoll) | |
625 | { | |
626 | /* Clear all status */ | |
627 | memset(pDesc, 0, RTL_TX_HEADER_SIZE); | |
628 | SET_TX_DESC_FIRST_SEG(pDesc, 1); /* bFirstSeg; */ | |
629 | SET_TX_DESC_LAST_SEG(pDesc, 1); /* bLastSeg; */ | |
630 | SET_TX_DESC_OFFSET(pDesc, RTL_TX_HEADER_SIZE); /* Offset = 32 */ | |
631 | SET_TX_DESC_PKT_SIZE(pDesc, buffer_len); /* Buffer size + command hdr */ | |
632 | SET_TX_DESC_QUEUE_SEL(pDesc, QSLT_MGNT); /* Fixed queue of Mgnt queue */ | |
633 | /* Set NAVUSEHDR to prevent Ps-poll AId filed to be changed to error | |
634 | * vlaue by Hw. */ | |
635 | if (bIsPsPoll) { | |
636 | SET_TX_DESC_NAV_USE_HDR(pDesc, 1); | |
637 | } else { | |
638 | SET_TX_DESC_HWSEQ_EN(pDesc, 1); /* Hw set sequence number */ | |
639 | SET_TX_DESC_PKT_ID(pDesc, 0x100); /* set bit3 to 1. */ | |
640 | } | |
641 | SET_TX_DESC_USE_RATE(pDesc, 1); /* use data rate which is set by Sw */ | |
642 | SET_TX_DESC_OWN(pDesc, 1); | |
643 | SET_TX_DESC_TX_RATE(pDesc, DESC92C_RATE1M); | |
644 | _rtl_tx_desc_checksum(pDesc); | |
645 | } | |
646 | ||
647 | void rtl92cu_tx_fill_cmddesc(struct ieee80211_hw *hw, | |
648 | u8 *pdesc, bool firstseg, | |
649 | bool lastseg, struct sk_buff *skb) | |
650 | { | |
651 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
652 | u8 fw_queue = QSLT_BEACON; | |
653 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); | |
654 | __le16 fc = hdr->frame_control; | |
655 | ||
656 | memset((void *)pdesc, 0, RTL_TX_HEADER_SIZE); | |
657 | if (firstseg) | |
658 | SET_TX_DESC_OFFSET(pdesc, RTL_TX_HEADER_SIZE); | |
659 | SET_TX_DESC_TX_RATE(pdesc, DESC92C_RATE1M); | |
660 | SET_TX_DESC_SEQ(pdesc, 0); | |
661 | SET_TX_DESC_LINIP(pdesc, 0); | |
662 | SET_TX_DESC_QUEUE_SEL(pdesc, fw_queue); | |
663 | SET_TX_DESC_FIRST_SEG(pdesc, 1); | |
664 | SET_TX_DESC_LAST_SEG(pdesc, 1); | |
665 | SET_TX_DESC_RATE_ID(pdesc, 7); | |
666 | SET_TX_DESC_MACID(pdesc, 0); | |
667 | SET_TX_DESC_OWN(pdesc, 1); | |
668 | SET_TX_DESC_PKT_SIZE((u8 *) pdesc, (u16) (skb->len)); | |
669 | SET_TX_DESC_FIRST_SEG(pdesc, 1); | |
670 | SET_TX_DESC_LAST_SEG(pdesc, 1); | |
671 | SET_TX_DESC_OFFSET(pdesc, 0x20); | |
672 | SET_TX_DESC_USE_RATE(pdesc, 1); | |
673 | if (!ieee80211_is_data_qos(fc)) { | |
674 | SET_TX_DESC_HWSEQ_EN(pdesc, 1); | |
675 | SET_TX_DESC_PKT_ID(pdesc, 8); | |
676 | } | |
677 | RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, "H2C Tx Cmd Content\n", | |
678 | pdesc, RTL_TX_DESC_SIZE); | |
679 | } | |
680 | ||
681 | bool rtl92cu_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb) | |
682 | { | |
683 | return true; | |
684 | } |