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