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