1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* Copyright(c) 2009-2012 Realtek Corporation.*/ |
3 | |
4 | #include "wifi.h" |
5 | #include "core.h" |
6 | #include "usb.h" |
7 | #include "base.h" |
8 | #include "ps.h" |
9 | #include "rtl8192c/fw_common.h" |
10 | #include <linux/export.h> |
11 | #include <linux/module.h> |
12 | |
13 | MODULE_AUTHOR("lizhaoming <chaoming_li@realsil.com.cn>" ); |
14 | MODULE_AUTHOR("Realtek WlanFAE <wlanfae@realtek.com>" ); |
15 | MODULE_AUTHOR("Larry Finger <Larry.FInger@lwfinger.net>" ); |
16 | MODULE_LICENSE("GPL" ); |
17 | MODULE_DESCRIPTION("USB basic driver for rtlwifi" ); |
18 | |
19 | #define REALTEK_USB_VENQT_READ 0xC0 |
20 | #define REALTEK_USB_VENQT_WRITE 0x40 |
21 | #define REALTEK_USB_VENQT_CMD_REQ 0x05 |
22 | #define REALTEK_USB_VENQT_CMD_IDX 0x00 |
23 | |
24 | #define MAX_USBCTRL_VENDORREQ_TIMES 10 |
25 | |
26 | static void _usbctrl_vendorreq_sync(struct usb_device *udev, u8 reqtype, |
27 | u16 value, void *pdata, u16 len) |
28 | { |
29 | unsigned int pipe; |
30 | int status; |
31 | int vendorreq_times = 0; |
32 | static int count; |
33 | |
34 | if (reqtype == REALTEK_USB_VENQT_READ) |
35 | pipe = usb_rcvctrlpipe(udev, 0); /* read_in */ |
36 | else |
37 | pipe = usb_sndctrlpipe(udev, 0); /* write_out */ |
38 | |
39 | do { |
40 | status = usb_control_msg(dev: udev, pipe, REALTEK_USB_VENQT_CMD_REQ, |
41 | requesttype: reqtype, value, REALTEK_USB_VENQT_CMD_IDX, |
42 | data: pdata, size: len, timeout: 1000); |
43 | if (status < 0) { |
44 | /* firmware download is checksumed, don't retry */ |
45 | if ((value >= FW_8192C_START_ADDRESS && |
46 | value <= FW_8192C_END_ADDRESS)) |
47 | break; |
48 | } else { |
49 | break; |
50 | } |
51 | } while (++vendorreq_times < MAX_USBCTRL_VENDORREQ_TIMES); |
52 | |
53 | if (status < 0 && count++ < 4) |
54 | dev_err(&udev->dev, "reg 0x%x, usbctrl_vendorreq TimeOut! status:0x%x value=0x%x reqtype=0x%x\n" , |
55 | value, status, *(u32 *)pdata, reqtype); |
56 | } |
57 | |
58 | static u32 _usb_read_sync(struct rtl_priv *rtlpriv, u32 addr, u16 len) |
59 | { |
60 | struct device *dev = rtlpriv->io.dev; |
61 | struct usb_device *udev = to_usb_device(dev); |
62 | u16 wvalue; |
63 | __le32 *data; |
64 | unsigned long flags; |
65 | |
66 | spin_lock_irqsave(&rtlpriv->locks.usb_lock, flags); |
67 | if (++rtlpriv->usb_data_index >= RTL_USB_MAX_RX_COUNT) |
68 | rtlpriv->usb_data_index = 0; |
69 | data = &rtlpriv->usb_data[rtlpriv->usb_data_index]; |
70 | spin_unlock_irqrestore(lock: &rtlpriv->locks.usb_lock, flags); |
71 | |
72 | wvalue = (u16)addr; |
73 | _usbctrl_vendorreq_sync(udev, REALTEK_USB_VENQT_READ, value: wvalue, pdata: data, len); |
74 | return le32_to_cpu(*data); |
75 | } |
76 | |
77 | |
78 | static void _usb_write_sync(struct rtl_priv *rtlpriv, u32 addr, u32 val, u16 len) |
79 | { |
80 | struct device *dev = rtlpriv->io.dev; |
81 | struct usb_device *udev = to_usb_device(dev); |
82 | unsigned long flags; |
83 | __le32 *data; |
84 | u16 wvalue; |
85 | |
86 | spin_lock_irqsave(&rtlpriv->locks.usb_lock, flags); |
87 | if (++rtlpriv->usb_data_index >= RTL_USB_MAX_RX_COUNT) |
88 | rtlpriv->usb_data_index = 0; |
89 | data = &rtlpriv->usb_data[rtlpriv->usb_data_index]; |
90 | spin_unlock_irqrestore(lock: &rtlpriv->locks.usb_lock, flags); |
91 | |
92 | wvalue = (u16)(addr & 0x0000ffff); |
93 | *data = cpu_to_le32(val); |
94 | |
95 | _usbctrl_vendorreq_sync(udev, REALTEK_USB_VENQT_WRITE, value: wvalue, pdata: data, len); |
96 | } |
97 | |
98 | static u8 _usb_read8_sync(struct rtl_priv *rtlpriv, u32 addr) |
99 | { |
100 | return (u8)_usb_read_sync(rtlpriv, addr, len: 1); |
101 | } |
102 | |
103 | static u16 _usb_read16_sync(struct rtl_priv *rtlpriv, u32 addr) |
104 | { |
105 | return (u16)_usb_read_sync(rtlpriv, addr, len: 2); |
106 | } |
107 | |
108 | static u32 _usb_read32_sync(struct rtl_priv *rtlpriv, u32 addr) |
109 | { |
110 | return _usb_read_sync(rtlpriv, addr, len: 4); |
111 | } |
112 | |
113 | static void _usb_write8_sync(struct rtl_priv *rtlpriv, u32 addr, u8 val) |
114 | { |
115 | _usb_write_sync(rtlpriv, addr, val, len: 1); |
116 | } |
117 | |
118 | static void _usb_write16_sync(struct rtl_priv *rtlpriv, u32 addr, u16 val) |
119 | { |
120 | _usb_write_sync(rtlpriv, addr, val, len: 2); |
121 | } |
122 | |
123 | static void _usb_write32_sync(struct rtl_priv *rtlpriv, u32 addr, u32 val) |
124 | { |
125 | _usb_write_sync(rtlpriv, addr, val, len: 4); |
126 | } |
127 | |
128 | static void _usb_write_chunk_sync(struct rtl_priv *rtlpriv, u32 addr, |
129 | u32 length, u8 *data) |
130 | { |
131 | struct usb_device *udev = to_usb_device(rtlpriv->io.dev); |
132 | |
133 | _usbctrl_vendorreq_sync(udev, REALTEK_USB_VENQT_WRITE, value: addr, pdata: data, len: length); |
134 | } |
135 | |
136 | static void _rtl_usb_io_handler_init(struct device *dev, |
137 | struct ieee80211_hw *hw) |
138 | { |
139 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
140 | |
141 | rtlpriv->io.dev = dev; |
142 | mutex_init(&rtlpriv->io.bb_mutex); |
143 | rtlpriv->io.write8 = _usb_write8_sync; |
144 | rtlpriv->io.write16 = _usb_write16_sync; |
145 | rtlpriv->io.write32 = _usb_write32_sync; |
146 | rtlpriv->io.write_chunk = _usb_write_chunk_sync; |
147 | rtlpriv->io.read8 = _usb_read8_sync; |
148 | rtlpriv->io.read16 = _usb_read16_sync; |
149 | rtlpriv->io.read32 = _usb_read32_sync; |
150 | } |
151 | |
152 | static void _rtl_usb_io_handler_release(struct ieee80211_hw *hw) |
153 | { |
154 | struct rtl_priv __maybe_unused *rtlpriv = rtl_priv(hw); |
155 | |
156 | mutex_destroy(lock: &rtlpriv->io.bb_mutex); |
157 | } |
158 | |
159 | /* Default aggregation handler. Do nothing and just return the oldest skb. */ |
160 | static struct sk_buff *_none_usb_tx_aggregate_hdl(struct ieee80211_hw *hw, |
161 | struct sk_buff_head *list) |
162 | { |
163 | return skb_dequeue(list); |
164 | } |
165 | |
166 | #define IS_HIGH_SPEED_USB(udev) \ |
167 | ((USB_SPEED_HIGH == (udev)->speed) ? true : false) |
168 | |
169 | static int _rtl_usb_init_tx(struct ieee80211_hw *hw) |
170 | { |
171 | u32 i; |
172 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
173 | struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); |
174 | |
175 | rtlusb->max_bulk_out_size = IS_HIGH_SPEED_USB(rtlusb->udev) |
176 | ? USB_HIGH_SPEED_BULK_SIZE |
177 | : USB_FULL_SPEED_BULK_SIZE; |
178 | |
179 | rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, "USB Max Bulk-out Size=%d\n" , |
180 | rtlusb->max_bulk_out_size); |
181 | |
182 | for (i = 0; i < __RTL_TXQ_NUM; i++) { |
183 | u32 ep_num = rtlusb->ep_map.ep_mapping[i]; |
184 | |
185 | if (!ep_num) { |
186 | rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, |
187 | "Invalid endpoint map setting!\n" ); |
188 | return -EINVAL; |
189 | } |
190 | } |
191 | |
192 | rtlusb->usb_tx_post_hdl = |
193 | rtlpriv->cfg->usb_interface_cfg->usb_tx_post_hdl; |
194 | rtlusb->usb_tx_cleanup = |
195 | rtlpriv->cfg->usb_interface_cfg->usb_tx_cleanup; |
196 | rtlusb->usb_tx_aggregate_hdl = |
197 | (rtlpriv->cfg->usb_interface_cfg->usb_tx_aggregate_hdl) |
198 | ? rtlpriv->cfg->usb_interface_cfg->usb_tx_aggregate_hdl |
199 | : &_none_usb_tx_aggregate_hdl; |
200 | |
201 | init_usb_anchor(anchor: &rtlusb->tx_submitted); |
202 | for (i = 0; i < RTL_USB_MAX_EP_NUM; i++) { |
203 | skb_queue_head_init(list: &rtlusb->tx_skb_queue[i]); |
204 | init_usb_anchor(anchor: &rtlusb->tx_pending[i]); |
205 | } |
206 | return 0; |
207 | } |
208 | |
209 | static void _rtl_rx_work(struct tasklet_struct *t); |
210 | |
211 | static int _rtl_usb_init_rx(struct ieee80211_hw *hw) |
212 | { |
213 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
214 | struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw); |
215 | struct rtl_usb *rtlusb = rtl_usbdev(usb_priv); |
216 | |
217 | rtlusb->rx_max_size = rtlpriv->cfg->usb_interface_cfg->rx_max_size; |
218 | rtlusb->rx_urb_num = rtlpriv->cfg->usb_interface_cfg->rx_urb_num; |
219 | rtlusb->usb_rx_hdl = rtlpriv->cfg->usb_interface_cfg->usb_rx_hdl; |
220 | rtlusb->usb_rx_segregate_hdl = |
221 | rtlpriv->cfg->usb_interface_cfg->usb_rx_segregate_hdl; |
222 | |
223 | pr_info("rx_max_size %d, rx_urb_num %d, in_ep %d\n" , |
224 | rtlusb->rx_max_size, rtlusb->rx_urb_num, rtlusb->in_ep); |
225 | init_usb_anchor(anchor: &rtlusb->rx_submitted); |
226 | init_usb_anchor(anchor: &rtlusb->rx_cleanup_urbs); |
227 | |
228 | skb_queue_head_init(list: &rtlusb->rx_queue); |
229 | tasklet_setup(t: &rtlusb->rx_work_tasklet, callback: _rtl_rx_work); |
230 | |
231 | return 0; |
232 | } |
233 | |
234 | static int _rtl_usb_init(struct ieee80211_hw *hw) |
235 | { |
236 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
237 | struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw); |
238 | struct rtl_usb *rtlusb = rtl_usbdev(usb_priv); |
239 | int err; |
240 | u8 epidx; |
241 | struct usb_interface *usb_intf = rtlusb->intf; |
242 | u8 epnums = usb_intf->cur_altsetting->desc.bNumEndpoints; |
243 | |
244 | rtlusb->out_ep_nums = rtlusb->in_ep_nums = 0; |
245 | for (epidx = 0; epidx < epnums; epidx++) { |
246 | struct usb_endpoint_descriptor *pep_desc; |
247 | |
248 | pep_desc = &usb_intf->cur_altsetting->endpoint[epidx].desc; |
249 | |
250 | if (usb_endpoint_dir_in(epd: pep_desc)) { |
251 | if (usb_endpoint_xfer_bulk(epd: pep_desc)) { |
252 | /* The vendor drivers assume there is only one |
253 | * bulk in ep and that it's the first in ep. |
254 | */ |
255 | if (rtlusb->in_ep_nums == 0) |
256 | rtlusb->in_ep = usb_endpoint_num(epd: pep_desc); |
257 | else |
258 | pr_warn("%s: bulk in endpoint is not the first in endpoint\n" , |
259 | __func__); |
260 | } |
261 | |
262 | rtlusb->in_ep_nums++; |
263 | } else if (usb_endpoint_dir_out(epd: pep_desc)) { |
264 | if (rtlusb->out_ep_nums < RTL_USB_MAX_BULKOUT_NUM) { |
265 | if (usb_endpoint_xfer_bulk(epd: pep_desc)) |
266 | rtlusb->out_eps[rtlusb->out_ep_nums] = |
267 | usb_endpoint_num(epd: pep_desc); |
268 | } else { |
269 | pr_warn("%s: found more bulk out endpoints than the expected %d\n" , |
270 | __func__, RTL_USB_MAX_BULKOUT_NUM); |
271 | } |
272 | |
273 | rtlusb->out_ep_nums++; |
274 | } |
275 | |
276 | rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, |
277 | "USB EP(0x%02x), MaxPacketSize=%d, Interval=%d\n" , |
278 | pep_desc->bEndpointAddress, pep_desc->wMaxPacketSize, |
279 | pep_desc->bInterval); |
280 | } |
281 | |
282 | if (rtlusb->out_ep_nums == 0) { |
283 | pr_err("No output end points found\n" ); |
284 | return -EINVAL; |
285 | } |
286 | /* usb endpoint mapping */ |
287 | err = rtlpriv->cfg->usb_interface_cfg->usb_endpoint_mapping(hw); |
288 | rtlusb->usb_mq_to_hwq = rtlpriv->cfg->usb_interface_cfg->usb_mq_to_hwq; |
289 | _rtl_usb_init_tx(hw); |
290 | _rtl_usb_init_rx(hw); |
291 | return err; |
292 | } |
293 | |
294 | static void rtl_usb_init_sw(struct ieee80211_hw *hw) |
295 | { |
296 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
297 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
298 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); |
299 | struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); |
300 | |
301 | rtlhal->hw = hw; |
302 | ppsc->inactiveps = false; |
303 | ppsc->leisure_ps = false; |
304 | ppsc->fwctrl_lps = false; |
305 | ppsc->reg_fwctrl_lps = 3; |
306 | ppsc->reg_max_lps_awakeintvl = 5; |
307 | ppsc->fwctrl_psmode = FW_PS_DTIM_MODE; |
308 | |
309 | /* IBSS */ |
310 | mac->beacon_interval = 100; |
311 | |
312 | /* AMPDU */ |
313 | mac->min_space_cfg = 0; |
314 | mac->max_mss_density = 0; |
315 | |
316 | /* set sane AMPDU defaults */ |
317 | mac->current_ampdu_density = 7; |
318 | mac->current_ampdu_factor = 3; |
319 | |
320 | /* QOS */ |
321 | rtlusb->acm_method = EACMWAY2_SW; |
322 | |
323 | /* IRQ */ |
324 | /* HIMR - turn all on */ |
325 | rtlusb->irq_mask[0] = 0xFFFFFFFF; |
326 | /* HIMR_EX - turn all on */ |
327 | rtlusb->irq_mask[1] = 0xFFFFFFFF; |
328 | rtlusb->disablehwsm = true; |
329 | } |
330 | |
331 | static void _rtl_rx_completed(struct urb *urb); |
332 | |
333 | static int _rtl_prep_rx_urb(struct ieee80211_hw *hw, struct rtl_usb *rtlusb, |
334 | struct urb *urb, gfp_t gfp_mask) |
335 | { |
336 | void *buf; |
337 | |
338 | buf = usb_alloc_coherent(dev: rtlusb->udev, size: rtlusb->rx_max_size, mem_flags: gfp_mask, |
339 | dma: &urb->transfer_dma); |
340 | if (!buf) { |
341 | pr_err("Failed to usb_alloc_coherent!!\n" ); |
342 | return -ENOMEM; |
343 | } |
344 | |
345 | usb_fill_bulk_urb(urb, dev: rtlusb->udev, |
346 | usb_rcvbulkpipe(rtlusb->udev, rtlusb->in_ep), |
347 | transfer_buffer: buf, buffer_length: rtlusb->rx_max_size, complete_fn: _rtl_rx_completed, context: rtlusb); |
348 | urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
349 | |
350 | return 0; |
351 | } |
352 | |
353 | static void _rtl_usb_rx_process_agg(struct ieee80211_hw *hw, |
354 | struct sk_buff *skb) |
355 | { |
356 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
357 | u8 *rxdesc = skb->data; |
358 | struct ieee80211_hdr *hdr; |
359 | bool unicast = false; |
360 | __le16 fc; |
361 | struct ieee80211_rx_status rx_status = {0}; |
362 | struct rtl_stats stats = { |
363 | .signal = 0, |
364 | .rate = 0, |
365 | }; |
366 | |
367 | skb_pull(skb, RTL_RX_DESC_SIZE); |
368 | rtlpriv->cfg->ops->query_rx_desc(hw, &stats, &rx_status, rxdesc, skb); |
369 | skb_pull(skb, len: (stats.rx_drvinfo_size + stats.rx_bufshift)); |
370 | hdr = rtl_get_hdr(skb); |
371 | fc = hdr->frame_control; |
372 | if (!stats.crc) { |
373 | memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); |
374 | |
375 | if (is_broadcast_ether_addr(addr: hdr->addr1)) { |
376 | /*TODO*/; |
377 | } else if (is_multicast_ether_addr(addr: hdr->addr1)) { |
378 | /*TODO*/ |
379 | } else { |
380 | unicast = true; |
381 | rtlpriv->stats.rxbytesunicast += skb->len; |
382 | } |
383 | |
384 | if (ieee80211_is_data(fc)) { |
385 | rtlpriv->cfg->ops->led_control(hw, LED_CTL_RX); |
386 | |
387 | if (unicast) |
388 | rtlpriv->link_info.num_rx_inperiod++; |
389 | } |
390 | /* static bcn for roaming */ |
391 | rtl_beacon_statistic(hw, skb); |
392 | } |
393 | } |
394 | |
395 | static void _rtl_usb_rx_process_noagg(struct ieee80211_hw *hw, |
396 | struct sk_buff *skb) |
397 | { |
398 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
399 | u8 *rxdesc = skb->data; |
400 | struct ieee80211_hdr *hdr; |
401 | bool unicast = false; |
402 | __le16 fc; |
403 | struct ieee80211_rx_status rx_status = {0}; |
404 | struct rtl_stats stats = { |
405 | .signal = 0, |
406 | .rate = 0, |
407 | }; |
408 | |
409 | skb_pull(skb, RTL_RX_DESC_SIZE); |
410 | rtlpriv->cfg->ops->query_rx_desc(hw, &stats, &rx_status, rxdesc, skb); |
411 | skb_pull(skb, len: (stats.rx_drvinfo_size + stats.rx_bufshift)); |
412 | hdr = rtl_get_hdr(skb); |
413 | fc = hdr->frame_control; |
414 | if (!stats.crc) { |
415 | memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); |
416 | |
417 | if (is_broadcast_ether_addr(addr: hdr->addr1)) { |
418 | /*TODO*/; |
419 | } else if (is_multicast_ether_addr(addr: hdr->addr1)) { |
420 | /*TODO*/ |
421 | } else { |
422 | unicast = true; |
423 | rtlpriv->stats.rxbytesunicast += skb->len; |
424 | } |
425 | |
426 | if (ieee80211_is_data(fc)) { |
427 | rtlpriv->cfg->ops->led_control(hw, LED_CTL_RX); |
428 | |
429 | if (unicast) |
430 | rtlpriv->link_info.num_rx_inperiod++; |
431 | } |
432 | |
433 | /* static bcn for roaming */ |
434 | rtl_beacon_statistic(hw, skb); |
435 | |
436 | if (likely(rtl_action_proc(hw, skb, false))) |
437 | ieee80211_rx(hw, skb); |
438 | else |
439 | dev_kfree_skb_any(skb); |
440 | } else { |
441 | dev_kfree_skb_any(skb); |
442 | } |
443 | } |
444 | |
445 | static void _rtl_rx_pre_process(struct ieee80211_hw *hw, struct sk_buff *skb) |
446 | { |
447 | struct sk_buff *_skb; |
448 | struct sk_buff_head rx_queue; |
449 | struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); |
450 | |
451 | skb_queue_head_init(list: &rx_queue); |
452 | if (rtlusb->usb_rx_segregate_hdl) |
453 | rtlusb->usb_rx_segregate_hdl(hw, skb, &rx_queue); |
454 | WARN_ON(skb_queue_empty(&rx_queue)); |
455 | while (!skb_queue_empty(list: &rx_queue)) { |
456 | _skb = skb_dequeue(list: &rx_queue); |
457 | _rtl_usb_rx_process_agg(hw, skb: _skb); |
458 | ieee80211_rx(hw, skb: _skb); |
459 | } |
460 | } |
461 | |
462 | #define __RX_SKB_MAX_QUEUED 64 |
463 | |
464 | static void _rtl_rx_work(struct tasklet_struct *t) |
465 | { |
466 | struct rtl_usb *rtlusb = from_tasklet(rtlusb, t, rx_work_tasklet); |
467 | struct ieee80211_hw *hw = usb_get_intfdata(intf: rtlusb->intf); |
468 | struct sk_buff *skb; |
469 | |
470 | while ((skb = skb_dequeue(list: &rtlusb->rx_queue))) { |
471 | if (unlikely(IS_USB_STOP(rtlusb))) { |
472 | dev_kfree_skb_any(skb); |
473 | continue; |
474 | } |
475 | |
476 | if (likely(!rtlusb->usb_rx_segregate_hdl)) { |
477 | _rtl_usb_rx_process_noagg(hw, skb); |
478 | } else { |
479 | /* TO DO */ |
480 | _rtl_rx_pre_process(hw, skb); |
481 | pr_err("rx agg not supported\n" ); |
482 | } |
483 | } |
484 | } |
485 | |
486 | static unsigned int _rtl_rx_get_padding(struct ieee80211_hdr *hdr, |
487 | unsigned int len) |
488 | { |
489 | #if NET_IP_ALIGN != 0 |
490 | unsigned int padding = 0; |
491 | #endif |
492 | |
493 | /* make function no-op when possible */ |
494 | if (NET_IP_ALIGN == 0 || len < sizeof(*hdr)) |
495 | return 0; |
496 | |
497 | #if NET_IP_ALIGN != 0 |
498 | /* alignment calculation as in lbtf_rx() / carl9170_rx_copy_data() */ |
499 | /* TODO: deduplicate common code, define helper function instead? */ |
500 | |
501 | if (ieee80211_is_data_qos(hdr->frame_control)) { |
502 | u8 *qc = ieee80211_get_qos_ctl(hdr); |
503 | |
504 | padding ^= NET_IP_ALIGN; |
505 | |
506 | /* Input might be invalid, avoid accessing memory outside |
507 | * the buffer. |
508 | */ |
509 | if ((unsigned long)qc - (unsigned long)hdr < len && |
510 | *qc & IEEE80211_QOS_CTL_A_MSDU_PRESENT) |
511 | padding ^= NET_IP_ALIGN; |
512 | } |
513 | |
514 | if (ieee80211_has_a4(hdr->frame_control)) |
515 | padding ^= NET_IP_ALIGN; |
516 | |
517 | return padding; |
518 | #endif |
519 | } |
520 | |
521 | #define __RADIO_TAP_SIZE_RSV 32 |
522 | |
523 | static void _rtl_rx_completed(struct urb *_urb) |
524 | { |
525 | struct rtl_usb *rtlusb = (struct rtl_usb *)_urb->context; |
526 | int err = 0; |
527 | |
528 | if (unlikely(IS_USB_STOP(rtlusb))) |
529 | goto free; |
530 | |
531 | if (likely(0 == _urb->status)) { |
532 | unsigned int padding; |
533 | struct sk_buff *skb; |
534 | unsigned int qlen; |
535 | unsigned int size = _urb->actual_length; |
536 | struct ieee80211_hdr *hdr; |
537 | |
538 | if (size < RTL_RX_DESC_SIZE + sizeof(struct ieee80211_hdr)) { |
539 | pr_err("Too short packet from bulk IN! (len: %d)\n" , |
540 | size); |
541 | goto resubmit; |
542 | } |
543 | |
544 | qlen = skb_queue_len(list_: &rtlusb->rx_queue); |
545 | if (qlen >= __RX_SKB_MAX_QUEUED) { |
546 | pr_err("Pending RX skbuff queue full! (qlen: %d)\n" , |
547 | qlen); |
548 | goto resubmit; |
549 | } |
550 | |
551 | hdr = (void *)(_urb->transfer_buffer + RTL_RX_DESC_SIZE); |
552 | padding = _rtl_rx_get_padding(hdr, len: size - RTL_RX_DESC_SIZE); |
553 | |
554 | skb = dev_alloc_skb(length: size + __RADIO_TAP_SIZE_RSV + padding); |
555 | if (!skb) { |
556 | pr_err("Can't allocate skb for bulk IN!\n" ); |
557 | goto resubmit; |
558 | } |
559 | |
560 | _rtl_install_trx_info(rtlusb, skb, ep_num: rtlusb->in_ep); |
561 | |
562 | /* Make sure the payload data is 4 byte aligned. */ |
563 | skb_reserve(skb, len: padding); |
564 | |
565 | /* reserve some space for mac80211's radiotap */ |
566 | skb_reserve(skb, __RADIO_TAP_SIZE_RSV); |
567 | |
568 | skb_put_data(skb, data: _urb->transfer_buffer, len: size); |
569 | |
570 | skb_queue_tail(list: &rtlusb->rx_queue, newsk: skb); |
571 | tasklet_schedule(t: &rtlusb->rx_work_tasklet); |
572 | |
573 | goto resubmit; |
574 | } |
575 | |
576 | switch (_urb->status) { |
577 | /* disconnect */ |
578 | case -ENOENT: |
579 | case -ECONNRESET: |
580 | case -ENODEV: |
581 | case -ESHUTDOWN: |
582 | goto free; |
583 | default: |
584 | break; |
585 | } |
586 | |
587 | resubmit: |
588 | usb_anchor_urb(urb: _urb, anchor: &rtlusb->rx_submitted); |
589 | err = usb_submit_urb(urb: _urb, GFP_ATOMIC); |
590 | if (unlikely(err)) { |
591 | usb_unanchor_urb(urb: _urb); |
592 | goto free; |
593 | } |
594 | return; |
595 | |
596 | free: |
597 | /* On some architectures, usb_free_coherent must not be called from |
598 | * hardirq context. Queue urb to cleanup list. |
599 | */ |
600 | usb_anchor_urb(urb: _urb, anchor: &rtlusb->rx_cleanup_urbs); |
601 | } |
602 | |
603 | #undef __RADIO_TAP_SIZE_RSV |
604 | |
605 | static void _rtl_usb_cleanup_rx(struct ieee80211_hw *hw) |
606 | { |
607 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
608 | struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); |
609 | struct urb *urb; |
610 | |
611 | usb_kill_anchored_urbs(anchor: &rtlusb->rx_submitted); |
612 | |
613 | tasklet_kill(t: &rtlusb->rx_work_tasklet); |
614 | cancel_work_sync(work: &rtlpriv->works.lps_change_work); |
615 | |
616 | if (rtlpriv->works.rtl_wq) { |
617 | destroy_workqueue(wq: rtlpriv->works.rtl_wq); |
618 | rtlpriv->works.rtl_wq = NULL; |
619 | } |
620 | |
621 | skb_queue_purge(list: &rtlusb->rx_queue); |
622 | |
623 | while ((urb = usb_get_from_anchor(anchor: &rtlusb->rx_cleanup_urbs))) { |
624 | usb_free_coherent(dev: urb->dev, size: urb->transfer_buffer_length, |
625 | addr: urb->transfer_buffer, dma: urb->transfer_dma); |
626 | usb_free_urb(urb); |
627 | } |
628 | } |
629 | |
630 | static int _rtl_usb_receive(struct ieee80211_hw *hw) |
631 | { |
632 | struct urb *urb; |
633 | int err; |
634 | int i; |
635 | struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); |
636 | |
637 | WARN_ON(0 == rtlusb->rx_urb_num); |
638 | /* 1600 == 1514 + max WLAN header + rtk info */ |
639 | WARN_ON(rtlusb->rx_max_size < 1600); |
640 | |
641 | for (i = 0; i < rtlusb->rx_urb_num; i++) { |
642 | err = -ENOMEM; |
643 | urb = usb_alloc_urb(iso_packets: 0, GFP_KERNEL); |
644 | if (!urb) |
645 | goto err_out; |
646 | |
647 | err = _rtl_prep_rx_urb(hw, rtlusb, urb, GFP_KERNEL); |
648 | if (err < 0) { |
649 | pr_err("Failed to prep_rx_urb!!\n" ); |
650 | usb_free_urb(urb); |
651 | goto err_out; |
652 | } |
653 | |
654 | usb_anchor_urb(urb, anchor: &rtlusb->rx_submitted); |
655 | err = usb_submit_urb(urb, GFP_KERNEL); |
656 | if (err) { |
657 | usb_unanchor_urb(urb); |
658 | usb_free_urb(urb); |
659 | goto err_out; |
660 | } |
661 | usb_free_urb(urb); |
662 | } |
663 | return 0; |
664 | |
665 | err_out: |
666 | usb_kill_anchored_urbs(anchor: &rtlusb->rx_submitted); |
667 | return err; |
668 | } |
669 | |
670 | static int rtl_usb_start(struct ieee80211_hw *hw) |
671 | { |
672 | int err; |
673 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
674 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
675 | struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); |
676 | |
677 | err = rtlpriv->cfg->ops->hw_init(hw); |
678 | if (!err) { |
679 | rtl_init_rx_config(hw); |
680 | |
681 | /* Enable software */ |
682 | SET_USB_START(rtlusb); |
683 | /* should after adapter start and interrupt enable. */ |
684 | set_hal_start(rtlhal); |
685 | |
686 | /* Start bulk IN */ |
687 | err = _rtl_usb_receive(hw); |
688 | } |
689 | |
690 | return err; |
691 | } |
692 | |
693 | /*======================= tx =========================================*/ |
694 | static void rtl_usb_cleanup(struct ieee80211_hw *hw) |
695 | { |
696 | u32 i; |
697 | struct sk_buff *_skb; |
698 | struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); |
699 | struct ieee80211_tx_info *txinfo; |
700 | |
701 | /* clean up rx stuff. */ |
702 | _rtl_usb_cleanup_rx(hw); |
703 | |
704 | /* clean up tx stuff */ |
705 | for (i = 0; i < RTL_USB_MAX_EP_NUM; i++) { |
706 | while ((_skb = skb_dequeue(list: &rtlusb->tx_skb_queue[i]))) { |
707 | rtlusb->usb_tx_cleanup(hw, _skb); |
708 | txinfo = IEEE80211_SKB_CB(skb: _skb); |
709 | ieee80211_tx_info_clear_status(info: txinfo); |
710 | txinfo->flags |= IEEE80211_TX_STAT_ACK; |
711 | ieee80211_tx_status_irqsafe(hw, skb: _skb); |
712 | } |
713 | usb_kill_anchored_urbs(anchor: &rtlusb->tx_pending[i]); |
714 | } |
715 | usb_kill_anchored_urbs(anchor: &rtlusb->tx_submitted); |
716 | } |
717 | |
718 | /* We may add some struct into struct rtl_usb later. Do deinit here. */ |
719 | static void rtl_usb_deinit(struct ieee80211_hw *hw) |
720 | { |
721 | rtl_usb_cleanup(hw); |
722 | } |
723 | |
724 | static void rtl_usb_stop(struct ieee80211_hw *hw) |
725 | { |
726 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
727 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
728 | struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); |
729 | struct urb *urb; |
730 | |
731 | /* should after adapter start and interrupt enable. */ |
732 | set_hal_stop(rtlhal); |
733 | cancel_work_sync(work: &rtlpriv->works.fill_h2c_cmd); |
734 | /* Enable software */ |
735 | SET_USB_STOP(rtlusb); |
736 | |
737 | /* free pre-allocated URBs from rtl_usb_start() */ |
738 | usb_kill_anchored_urbs(anchor: &rtlusb->rx_submitted); |
739 | |
740 | tasklet_kill(t: &rtlusb->rx_work_tasklet); |
741 | cancel_work_sync(work: &rtlpriv->works.lps_change_work); |
742 | cancel_work_sync(work: &rtlpriv->works.update_beacon_work); |
743 | |
744 | flush_workqueue(rtlpriv->works.rtl_wq); |
745 | |
746 | skb_queue_purge(list: &rtlusb->rx_queue); |
747 | |
748 | while ((urb = usb_get_from_anchor(anchor: &rtlusb->rx_cleanup_urbs))) { |
749 | usb_free_coherent(dev: urb->dev, size: urb->transfer_buffer_length, |
750 | addr: urb->transfer_buffer, dma: urb->transfer_dma); |
751 | usb_free_urb(urb); |
752 | } |
753 | |
754 | rtlpriv->cfg->ops->hw_disable(hw); |
755 | } |
756 | |
757 | static void _rtl_submit_tx_urb(struct ieee80211_hw *hw, struct urb *_urb) |
758 | { |
759 | int err; |
760 | struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); |
761 | |
762 | usb_anchor_urb(urb: _urb, anchor: &rtlusb->tx_submitted); |
763 | err = usb_submit_urb(urb: _urb, GFP_ATOMIC); |
764 | if (err < 0) { |
765 | struct sk_buff *skb; |
766 | |
767 | pr_err("Failed to submit urb\n" ); |
768 | usb_unanchor_urb(urb: _urb); |
769 | skb = (struct sk_buff *)_urb->context; |
770 | kfree_skb(skb); |
771 | } |
772 | usb_free_urb(urb: _urb); |
773 | } |
774 | |
775 | static int _usb_tx_post(struct ieee80211_hw *hw, struct urb *urb, |
776 | struct sk_buff *skb) |
777 | { |
778 | struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); |
779 | struct ieee80211_tx_info *txinfo; |
780 | |
781 | rtlusb->usb_tx_post_hdl(hw, urb, skb); |
782 | skb_pull(skb, RTL_TX_HEADER_SIZE); |
783 | txinfo = IEEE80211_SKB_CB(skb); |
784 | ieee80211_tx_info_clear_status(info: txinfo); |
785 | txinfo->flags |= IEEE80211_TX_STAT_ACK; |
786 | |
787 | if (urb->status) { |
788 | pr_err("Urb has error status 0x%X\n" , urb->status); |
789 | goto out; |
790 | } |
791 | /* TODO: statistics */ |
792 | out: |
793 | ieee80211_tx_status_irqsafe(hw, skb); |
794 | return urb->status; |
795 | } |
796 | |
797 | static void _rtl_tx_complete(struct urb *urb) |
798 | { |
799 | struct sk_buff *skb = (struct sk_buff *)urb->context; |
800 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
801 | struct rtl_usb *rtlusb = (struct rtl_usb *)info->rate_driver_data[0]; |
802 | struct ieee80211_hw *hw = usb_get_intfdata(intf: rtlusb->intf); |
803 | int err; |
804 | |
805 | if (unlikely(IS_USB_STOP(rtlusb))) |
806 | return; |
807 | err = _usb_tx_post(hw, urb, skb); |
808 | if (err) { |
809 | /* Ignore error and keep issuiing other urbs */ |
810 | return; |
811 | } |
812 | } |
813 | |
814 | static struct urb *_rtl_usb_tx_urb_setup(struct ieee80211_hw *hw, |
815 | struct sk_buff *skb, u32 ep_num) |
816 | { |
817 | struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); |
818 | struct urb *_urb; |
819 | |
820 | WARN_ON(NULL == skb); |
821 | _urb = usb_alloc_urb(iso_packets: 0, GFP_ATOMIC); |
822 | if (!_urb) |
823 | return NULL; |
824 | _rtl_install_trx_info(rtlusb, skb, ep_num); |
825 | usb_fill_bulk_urb(urb: _urb, dev: rtlusb->udev, usb_sndbulkpipe(rtlusb->udev, |
826 | ep_num), transfer_buffer: skb->data, buffer_length: skb->len, complete_fn: _rtl_tx_complete, context: skb); |
827 | _urb->transfer_flags |= URB_ZERO_PACKET; |
828 | return _urb; |
829 | } |
830 | |
831 | static void _rtl_usb_transmit(struct ieee80211_hw *hw, struct sk_buff *skb, |
832 | enum rtl_txq qnum) |
833 | { |
834 | struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); |
835 | u32 ep_num; |
836 | struct urb *_urb = NULL; |
837 | |
838 | WARN_ON(NULL == rtlusb->usb_tx_aggregate_hdl); |
839 | if (unlikely(IS_USB_STOP(rtlusb))) { |
840 | pr_err("USB device is stopping...\n" ); |
841 | kfree_skb(skb); |
842 | return; |
843 | } |
844 | ep_num = rtlusb->ep_map.ep_mapping[qnum]; |
845 | _urb = _rtl_usb_tx_urb_setup(hw, skb, ep_num); |
846 | if (unlikely(!_urb)) { |
847 | pr_err("Can't allocate urb. Drop skb!\n" ); |
848 | kfree_skb(skb); |
849 | return; |
850 | } |
851 | _rtl_submit_tx_urb(hw, _urb); |
852 | } |
853 | |
854 | static void _rtl_usb_tx_preprocess(struct ieee80211_hw *hw, |
855 | struct ieee80211_sta *sta, |
856 | struct sk_buff *skb, |
857 | u16 hw_queue) |
858 | { |
859 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
860 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
861 | struct rtl_tx_desc *pdesc = NULL; |
862 | struct rtl_tcb_desc tcb_desc; |
863 | struct ieee80211_hdr *hdr = rtl_get_hdr(skb); |
864 | __le16 fc = hdr->frame_control; |
865 | u8 *pda_addr = hdr->addr1; |
866 | |
867 | memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); |
868 | if (ieee80211_is_auth(fc)) { |
869 | rtl_dbg(rtlpriv, COMP_SEND, DBG_DMESG, "MAC80211_LINKING\n" ); |
870 | } |
871 | |
872 | if (rtlpriv->psc.sw_ps_enabled) { |
873 | if (ieee80211_is_data(fc) && !ieee80211_is_nullfunc(fc) && |
874 | !ieee80211_has_pm(fc)) |
875 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); |
876 | } |
877 | |
878 | rtl_action_proc(hw, skb, is_tx: true); |
879 | if (is_multicast_ether_addr(addr: pda_addr)) |
880 | rtlpriv->stats.txbytesmulticast += skb->len; |
881 | else if (is_broadcast_ether_addr(addr: pda_addr)) |
882 | rtlpriv->stats.txbytesbroadcast += skb->len; |
883 | else |
884 | rtlpriv->stats.txbytesunicast += skb->len; |
885 | rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *)pdesc, NULL, info, sta, skb, |
886 | hw_queue, &tcb_desc); |
887 | if (ieee80211_is_data(fc)) |
888 | rtlpriv->cfg->ops->led_control(hw, LED_CTL_TX); |
889 | } |
890 | |
891 | static int rtl_usb_tx(struct ieee80211_hw *hw, |
892 | struct ieee80211_sta *sta, |
893 | struct sk_buff *skb, |
894 | struct rtl_tcb_desc *dummy) |
895 | { |
896 | struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); |
897 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
898 | struct ieee80211_hdr *hdr = rtl_get_hdr(skb); |
899 | __le16 fc = hdr->frame_control; |
900 | u16 hw_queue; |
901 | |
902 | if (unlikely(is_hal_stop(rtlhal))) |
903 | goto err_free; |
904 | hw_queue = rtlusb->usb_mq_to_hwq(fc, skb_get_queue_mapping(skb)); |
905 | _rtl_usb_tx_preprocess(hw, sta, skb, hw_queue); |
906 | _rtl_usb_transmit(hw, skb, qnum: hw_queue); |
907 | return NETDEV_TX_OK; |
908 | |
909 | err_free: |
910 | dev_kfree_skb_any(skb); |
911 | return NETDEV_TX_OK; |
912 | } |
913 | |
914 | static bool rtl_usb_tx_chk_waitq_insert(struct ieee80211_hw *hw, |
915 | struct ieee80211_sta *sta, |
916 | struct sk_buff *skb) |
917 | { |
918 | return false; |
919 | } |
920 | |
921 | static void rtl_fill_h2c_cmd_work_callback(struct work_struct *work) |
922 | { |
923 | struct rtl_works *rtlworks = |
924 | container_of(work, struct rtl_works, fill_h2c_cmd); |
925 | struct ieee80211_hw *hw = rtlworks->hw; |
926 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
927 | |
928 | rtlpriv->cfg->ops->fill_h2c_cmd(hw, H2C_RA_MASK, 5, rtlpriv->rate_mask); |
929 | } |
930 | |
931 | static const struct rtl_intf_ops rtl_usb_ops = { |
932 | .adapter_start = rtl_usb_start, |
933 | .adapter_stop = rtl_usb_stop, |
934 | .adapter_tx = rtl_usb_tx, |
935 | .waitq_insert = rtl_usb_tx_chk_waitq_insert, |
936 | }; |
937 | |
938 | int rtl_usb_probe(struct usb_interface *intf, |
939 | const struct usb_device_id *id, |
940 | struct rtl_hal_cfg *rtl_hal_cfg) |
941 | { |
942 | int err; |
943 | struct ieee80211_hw *hw = NULL; |
944 | struct rtl_priv *rtlpriv = NULL; |
945 | struct usb_device *udev; |
946 | struct rtl_usb_priv *usb_priv; |
947 | |
948 | hw = ieee80211_alloc_hw(priv_data_len: sizeof(struct rtl_priv) + |
949 | sizeof(struct rtl_usb_priv), ops: &rtl_ops); |
950 | if (!hw) { |
951 | pr_warn("rtl_usb: ieee80211 alloc failed\n" ); |
952 | return -ENOMEM; |
953 | } |
954 | rtlpriv = hw->priv; |
955 | rtlpriv->hw = hw; |
956 | rtlpriv->usb_data = kcalloc(RTL_USB_MAX_RX_COUNT, size: sizeof(u32), |
957 | GFP_KERNEL); |
958 | if (!rtlpriv->usb_data) { |
959 | ieee80211_free_hw(hw); |
960 | return -ENOMEM; |
961 | } |
962 | |
963 | /* this spin lock must be initialized early */ |
964 | spin_lock_init(&rtlpriv->locks.usb_lock); |
965 | INIT_WORK(&rtlpriv->works.fill_h2c_cmd, |
966 | rtl_fill_h2c_cmd_work_callback); |
967 | INIT_WORK(&rtlpriv->works.lps_change_work, |
968 | rtl_lps_change_work_callback); |
969 | INIT_WORK(&rtlpriv->works.update_beacon_work, |
970 | rtl_update_beacon_work_callback); |
971 | |
972 | rtlpriv->usb_data_index = 0; |
973 | init_completion(x: &rtlpriv->firmware_loading_complete); |
974 | SET_IEEE80211_DEV(hw, dev: &intf->dev); |
975 | udev = interface_to_usbdev(intf); |
976 | usb_get_dev(dev: udev); |
977 | usb_priv = rtl_usbpriv(hw); |
978 | memset(usb_priv, 0, sizeof(*usb_priv)); |
979 | usb_priv->dev.intf = intf; |
980 | usb_priv->dev.udev = udev; |
981 | usb_set_intfdata(intf, data: hw); |
982 | /* init cfg & intf_ops */ |
983 | rtlpriv->rtlhal.interface = INTF_USB; |
984 | rtlpriv->cfg = rtl_hal_cfg; |
985 | rtlpriv->intf_ops = &rtl_usb_ops; |
986 | /* Init IO handler */ |
987 | _rtl_usb_io_handler_init(dev: &udev->dev, hw); |
988 | rtlpriv->cfg->ops->read_chip_version(hw); |
989 | /*like read eeprom and so on */ |
990 | rtlpriv->cfg->ops->read_eeprom_info(hw); |
991 | err = _rtl_usb_init(hw); |
992 | if (err) |
993 | goto error_out2; |
994 | rtl_usb_init_sw(hw); |
995 | /* Init mac80211 sw */ |
996 | err = rtl_init_core(hw); |
997 | if (err) { |
998 | pr_err("Can't allocate sw for mac80211\n" ); |
999 | goto error_out2; |
1000 | } |
1001 | if (rtlpriv->cfg->ops->init_sw_vars(hw)) { |
1002 | pr_err("Can't init_sw_vars\n" ); |
1003 | goto error_out; |
1004 | } |
1005 | rtl_init_sw_leds(hw); |
1006 | |
1007 | err = ieee80211_register_hw(hw); |
1008 | if (err) { |
1009 | pr_err("Can't register mac80211 hw.\n" ); |
1010 | goto error_out; |
1011 | } |
1012 | rtlpriv->mac80211.mac80211_registered = 1; |
1013 | |
1014 | set_bit(nr: RTL_STATUS_INTERFACE_START, addr: &rtlpriv->status); |
1015 | return 0; |
1016 | |
1017 | error_out: |
1018 | rtl_deinit_core(hw); |
1019 | error_out2: |
1020 | _rtl_usb_io_handler_release(hw); |
1021 | usb_put_dev(dev: udev); |
1022 | complete(&rtlpriv->firmware_loading_complete); |
1023 | kfree(objp: rtlpriv->usb_data); |
1024 | ieee80211_free_hw(hw); |
1025 | return -ENODEV; |
1026 | } |
1027 | EXPORT_SYMBOL(rtl_usb_probe); |
1028 | |
1029 | void rtl_usb_disconnect(struct usb_interface *intf) |
1030 | { |
1031 | struct ieee80211_hw *hw = usb_get_intfdata(intf); |
1032 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1033 | struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw)); |
1034 | struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); |
1035 | |
1036 | if (unlikely(!rtlpriv)) |
1037 | return; |
1038 | /* just in case driver is removed before firmware callback */ |
1039 | wait_for_completion(&rtlpriv->firmware_loading_complete); |
1040 | clear_bit(nr: RTL_STATUS_INTERFACE_START, addr: &rtlpriv->status); |
1041 | /*ieee80211_unregister_hw will call ops_stop */ |
1042 | if (rtlmac->mac80211_registered == 1) { |
1043 | ieee80211_unregister_hw(hw); |
1044 | rtlmac->mac80211_registered = 0; |
1045 | } else { |
1046 | rtl_deinit_deferred_work(hw, ips_wq: false); |
1047 | rtlpriv->intf_ops->adapter_stop(hw); |
1048 | } |
1049 | /*deinit rfkill */ |
1050 | /* rtl_deinit_rfkill(hw); */ |
1051 | rtl_usb_deinit(hw); |
1052 | rtl_deinit_core(hw); |
1053 | kfree(objp: rtlpriv->usb_data); |
1054 | rtlpriv->cfg->ops->deinit_sw_vars(hw); |
1055 | _rtl_usb_io_handler_release(hw); |
1056 | usb_put_dev(dev: rtlusb->udev); |
1057 | usb_set_intfdata(intf, NULL); |
1058 | ieee80211_free_hw(hw); |
1059 | } |
1060 | EXPORT_SYMBOL(rtl_usb_disconnect); |
1061 | |
1062 | int rtl_usb_suspend(struct usb_interface *pusb_intf, pm_message_t message) |
1063 | { |
1064 | return 0; |
1065 | } |
1066 | EXPORT_SYMBOL(rtl_usb_suspend); |
1067 | |
1068 | int rtl_usb_resume(struct usb_interface *pusb_intf) |
1069 | { |
1070 | return 0; |
1071 | } |
1072 | EXPORT_SYMBOL(rtl_usb_resume); |
1073 | |