1 | /* |
2 | * Copyright (c) 2014 Redpine Signals Inc. |
3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above |
6 | * copyright notice and this permission notice appear in all copies. |
7 | * |
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | * |
16 | */ |
17 | |
18 | #include <linux/module.h> |
19 | #include <linux/types.h> |
20 | #include <net/rsi_91x.h> |
21 | #include "rsi_usb.h" |
22 | #include "rsi_hal.h" |
23 | #include "rsi_coex.h" |
24 | |
25 | /* Default operating mode is wlan STA + BT */ |
26 | static u16 dev_oper_mode = DEV_OPMODE_STA_BT_DUAL; |
27 | module_param(dev_oper_mode, ushort, 0444); |
28 | MODULE_PARM_DESC(dev_oper_mode, DEV_OPMODE_PARAM_DESC); |
29 | |
30 | static int rsi_rx_urb_submit(struct rsi_hw *adapter, u8 ep_num, gfp_t flags); |
31 | |
32 | /** |
33 | * rsi_usb_card_write() - This function writes to the USB Card. |
34 | * @adapter: Pointer to the adapter structure. |
35 | * @buf: Pointer to the buffer from where the data has to be taken. |
36 | * @len: Length to be written. |
37 | * @endpoint: Type of endpoint. |
38 | * |
39 | * Return: status: 0 on success, a negative error code on failure. |
40 | */ |
41 | static int rsi_usb_card_write(struct rsi_hw *adapter, |
42 | u8 *buf, |
43 | u16 len, |
44 | u8 endpoint) |
45 | { |
46 | struct rsi_91x_usbdev *dev = adapter->rsi_dev; |
47 | int status; |
48 | u8 *seg = dev->tx_buffer; |
49 | int transfer; |
50 | int ep = dev->bulkout_endpoint_addr[endpoint - 1]; |
51 | |
52 | memset(seg, 0, len + RSI_USB_TX_HEAD_ROOM); |
53 | memcpy(seg + RSI_USB_TX_HEAD_ROOM, buf, len); |
54 | len += RSI_USB_TX_HEAD_ROOM; |
55 | transfer = len; |
56 | status = usb_bulk_msg(usb_dev: dev->usbdev, |
57 | usb_sndbulkpipe(dev->usbdev, ep), |
58 | data: (void *)seg, |
59 | len: (int)len, |
60 | actual_length: &transfer, |
61 | USB_CTRL_SET_TIMEOUT); |
62 | |
63 | if (status < 0) { |
64 | rsi_dbg(ERR_ZONE, |
65 | fmt: "Card write failed with error code :%10d\n" , status); |
66 | dev->write_fail = 1; |
67 | } |
68 | return status; |
69 | } |
70 | |
71 | /** |
72 | * rsi_write_multiple() - This function writes multiple bytes of information |
73 | * to the USB card. |
74 | * @adapter: Pointer to the adapter structure. |
75 | * @endpoint: Type of endpoint. |
76 | * @data: Pointer to the data that has to be written. |
77 | * @count: Number of multiple bytes to be written. |
78 | * |
79 | * Return: 0 on success, a negative error code on failure. |
80 | */ |
81 | static int rsi_write_multiple(struct rsi_hw *adapter, |
82 | u8 endpoint, |
83 | u8 *data, |
84 | u32 count) |
85 | { |
86 | struct rsi_91x_usbdev *dev; |
87 | |
88 | if (!adapter) |
89 | return -ENODEV; |
90 | |
91 | if (endpoint == 0) |
92 | return -EINVAL; |
93 | |
94 | dev = adapter->rsi_dev; |
95 | if (dev->write_fail) |
96 | return -ENETDOWN; |
97 | |
98 | return rsi_usb_card_write(adapter, buf: data, len: count, endpoint); |
99 | } |
100 | |
101 | /** |
102 | * rsi_find_bulk_in_and_out_endpoints() - This function initializes the bulk |
103 | * endpoints to the device. |
104 | * @interface: Pointer to the USB interface structure. |
105 | * @adapter: Pointer to the adapter structure. |
106 | * |
107 | * Return: ret_val: 0 on success, -ENOMEM on failure. |
108 | */ |
109 | static int rsi_find_bulk_in_and_out_endpoints(struct usb_interface *interface, |
110 | struct rsi_hw *adapter) |
111 | { |
112 | struct rsi_91x_usbdev *dev = adapter->rsi_dev; |
113 | struct usb_host_interface *iface_desc; |
114 | struct usb_endpoint_descriptor *endpoint; |
115 | __le16 buffer_size; |
116 | int ii, bin_found = 0, bout_found = 0; |
117 | |
118 | iface_desc = interface->cur_altsetting; |
119 | |
120 | for (ii = 0; ii < iface_desc->desc.bNumEndpoints; ++ii) { |
121 | endpoint = &(iface_desc->endpoint[ii].desc); |
122 | |
123 | if (!dev->bulkin_endpoint_addr[bin_found] && |
124 | (endpoint->bEndpointAddress & USB_DIR_IN) && |
125 | ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == |
126 | USB_ENDPOINT_XFER_BULK)) { |
127 | buffer_size = endpoint->wMaxPacketSize; |
128 | dev->bulkin_size[bin_found] = buffer_size; |
129 | dev->bulkin_endpoint_addr[bin_found] = |
130 | endpoint->bEndpointAddress; |
131 | bin_found++; |
132 | } |
133 | |
134 | if (!dev->bulkout_endpoint_addr[bout_found] && |
135 | !(endpoint->bEndpointAddress & USB_DIR_IN) && |
136 | ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == |
137 | USB_ENDPOINT_XFER_BULK)) { |
138 | buffer_size = endpoint->wMaxPacketSize; |
139 | dev->bulkout_endpoint_addr[bout_found] = |
140 | endpoint->bEndpointAddress; |
141 | dev->bulkout_size[bout_found] = buffer_size; |
142 | bout_found++; |
143 | } |
144 | |
145 | if (bin_found >= MAX_BULK_EP || bout_found >= MAX_BULK_EP) |
146 | break; |
147 | } |
148 | |
149 | if (!(dev->bulkin_endpoint_addr[0] && dev->bulkout_endpoint_addr[0])) { |
150 | dev_err(&interface->dev, "missing wlan bulk endpoints\n" ); |
151 | return -EINVAL; |
152 | } |
153 | |
154 | if (adapter->priv->coex_mode > 1) { |
155 | if (!dev->bulkin_endpoint_addr[1]) { |
156 | dev_err(&interface->dev, "missing bt bulk-in endpoint\n" ); |
157 | return -EINVAL; |
158 | } |
159 | } |
160 | |
161 | return 0; |
162 | } |
163 | |
164 | #define RSI_USB_REQ_OUT (USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE) |
165 | #define RSI_USB_REQ_IN (USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE) |
166 | |
167 | /* rsi_usb_reg_read() - This function reads data from given register address. |
168 | * @usbdev: Pointer to the usb_device structure. |
169 | * @reg: Address of the register to be read. |
170 | * @value: Value to be read. |
171 | * @len: length of data to be read. |
172 | * |
173 | * Return: status: 0 on success, a negative error code on failure. |
174 | */ |
175 | static int rsi_usb_reg_read(struct usb_device *usbdev, |
176 | u32 reg, |
177 | u16 *value, |
178 | u16 len) |
179 | { |
180 | u8 *buf; |
181 | int status = -ENOMEM; |
182 | |
183 | if (len > RSI_USB_CTRL_BUF_SIZE) |
184 | return -EINVAL; |
185 | |
186 | buf = kmalloc(RSI_USB_CTRL_BUF_SIZE, GFP_KERNEL); |
187 | if (!buf) |
188 | return status; |
189 | |
190 | status = usb_control_msg(dev: usbdev, |
191 | usb_rcvctrlpipe(usbdev, 0), |
192 | USB_VENDOR_REGISTER_READ, |
193 | RSI_USB_REQ_IN, |
194 | value: ((reg & 0xffff0000) >> 16), index: (reg & 0xffff), |
195 | data: (void *)buf, |
196 | size: len, |
197 | USB_CTRL_GET_TIMEOUT); |
198 | |
199 | *value = (buf[0] | (buf[1] << 8)); |
200 | if (status < 0) { |
201 | rsi_dbg(ERR_ZONE, |
202 | fmt: "%s: Reg read failed with error code :%d\n" , |
203 | __func__, status); |
204 | } |
205 | kfree(objp: buf); |
206 | |
207 | return status; |
208 | } |
209 | |
210 | /** |
211 | * rsi_usb_reg_write() - This function writes the given data into the given |
212 | * register address. |
213 | * @usbdev: Pointer to the usb_device structure. |
214 | * @reg: Address of the register. |
215 | * @value: Value to write. |
216 | * @len: Length of data to be written. |
217 | * |
218 | * Return: status: 0 on success, a negative error code on failure. |
219 | */ |
220 | static int rsi_usb_reg_write(struct usb_device *usbdev, |
221 | u32 reg, |
222 | u32 value, |
223 | u16 len) |
224 | { |
225 | u8 *usb_reg_buf; |
226 | int status = -ENOMEM; |
227 | |
228 | if (len > RSI_USB_CTRL_BUF_SIZE) |
229 | return -EINVAL; |
230 | |
231 | usb_reg_buf = kmalloc(RSI_USB_CTRL_BUF_SIZE, GFP_KERNEL); |
232 | if (!usb_reg_buf) |
233 | return status; |
234 | |
235 | usb_reg_buf[0] = (cpu_to_le32(value) & 0x00ff); |
236 | usb_reg_buf[1] = (cpu_to_le32(value) & 0xff00) >> 8; |
237 | usb_reg_buf[2] = (cpu_to_le32(value) & 0x00ff0000) >> 16; |
238 | usb_reg_buf[3] = (cpu_to_le32(value) & 0xff000000) >> 24; |
239 | |
240 | status = usb_control_msg(dev: usbdev, |
241 | usb_sndctrlpipe(usbdev, 0), |
242 | USB_VENDOR_REGISTER_WRITE, |
243 | RSI_USB_REQ_OUT, |
244 | value: ((cpu_to_le32(reg) & 0xffff0000) >> 16), |
245 | index: (cpu_to_le32(reg) & 0xffff), |
246 | data: (void *)usb_reg_buf, |
247 | size: len, |
248 | USB_CTRL_SET_TIMEOUT); |
249 | if (status < 0) { |
250 | rsi_dbg(ERR_ZONE, |
251 | fmt: "%s: Reg write failed with error code :%d\n" , |
252 | __func__, status); |
253 | } |
254 | kfree(objp: usb_reg_buf); |
255 | |
256 | return status; |
257 | } |
258 | |
259 | /** |
260 | * rsi_rx_done_handler() - This function is called when a packet is received |
261 | * from USB stack. This is callback to receive done. |
262 | * @urb: Received URB. |
263 | * |
264 | * Return: None. |
265 | */ |
266 | static void rsi_rx_done_handler(struct urb *urb) |
267 | { |
268 | struct rx_usb_ctrl_block *rx_cb = urb->context; |
269 | struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)rx_cb->data; |
270 | int status = -EINVAL; |
271 | |
272 | if (!rx_cb->rx_skb) |
273 | return; |
274 | |
275 | if (urb->status) { |
276 | dev_kfree_skb(rx_cb->rx_skb); |
277 | rx_cb->rx_skb = NULL; |
278 | return; |
279 | } |
280 | |
281 | if (urb->actual_length <= 0 || |
282 | urb->actual_length > rx_cb->rx_skb->len) { |
283 | rsi_dbg(INFO_ZONE, fmt: "%s: Invalid packet length = %d\n" , |
284 | __func__, urb->actual_length); |
285 | goto out; |
286 | } |
287 | if (skb_queue_len(list_: &dev->rx_q) >= RSI_MAX_RX_PKTS) { |
288 | rsi_dbg(INFO_ZONE, fmt: "Max RX packets reached\n" ); |
289 | goto out; |
290 | } |
291 | skb_trim(skb: rx_cb->rx_skb, len: urb->actual_length); |
292 | skb_queue_tail(list: &dev->rx_q, newsk: rx_cb->rx_skb); |
293 | |
294 | rsi_set_event(event: &dev->rx_thread.event); |
295 | status = 0; |
296 | |
297 | out: |
298 | if (rsi_rx_urb_submit(adapter: dev->priv, ep_num: rx_cb->ep_num, GFP_ATOMIC)) |
299 | rsi_dbg(ERR_ZONE, fmt: "%s: Failed in urb submission" , __func__); |
300 | |
301 | if (status) { |
302 | dev_kfree_skb(rx_cb->rx_skb); |
303 | rx_cb->rx_skb = NULL; |
304 | } |
305 | } |
306 | |
307 | static void rsi_rx_urb_kill(struct rsi_hw *adapter, u8 ep_num) |
308 | { |
309 | struct rsi_91x_usbdev *dev = adapter->rsi_dev; |
310 | struct rx_usb_ctrl_block *rx_cb = &dev->rx_cb[ep_num - 1]; |
311 | struct urb *urb = rx_cb->rx_urb; |
312 | |
313 | usb_kill_urb(urb); |
314 | } |
315 | |
316 | /** |
317 | * rsi_rx_urb_submit() - This function submits the given URB to the USB stack. |
318 | * @adapter: Pointer to the adapter structure. |
319 | * @ep_num: Endpoint number. |
320 | * @mem_flags: The type of memory to allocate. |
321 | * |
322 | * Return: 0 on success, a negative error code on failure. |
323 | */ |
324 | static int rsi_rx_urb_submit(struct rsi_hw *adapter, u8 ep_num, gfp_t mem_flags) |
325 | { |
326 | struct rsi_91x_usbdev *dev = adapter->rsi_dev; |
327 | struct rx_usb_ctrl_block *rx_cb = &dev->rx_cb[ep_num - 1]; |
328 | struct urb *urb = rx_cb->rx_urb; |
329 | int status; |
330 | struct sk_buff *skb; |
331 | u8 dword_align_bytes = 0; |
332 | |
333 | skb = dev_alloc_skb(RSI_MAX_RX_USB_PKT_SIZE); |
334 | if (!skb) |
335 | return -ENOMEM; |
336 | skb_reserve(skb, MAX_DWORD_ALIGN_BYTES); |
337 | skb_put(skb, RSI_MAX_RX_USB_PKT_SIZE - MAX_DWORD_ALIGN_BYTES); |
338 | dword_align_bytes = (unsigned long)skb->data & 0x3f; |
339 | if (dword_align_bytes > 0) |
340 | skb_push(skb, len: dword_align_bytes); |
341 | urb->transfer_buffer = skb->data; |
342 | rx_cb->rx_skb = skb; |
343 | |
344 | usb_fill_bulk_urb(urb, |
345 | dev: dev->usbdev, |
346 | usb_rcvbulkpipe(dev->usbdev, |
347 | dev->bulkin_endpoint_addr[ep_num - 1]), |
348 | transfer_buffer: urb->transfer_buffer, |
349 | buffer_length: skb->len, |
350 | complete_fn: rsi_rx_done_handler, |
351 | context: rx_cb); |
352 | |
353 | status = usb_submit_urb(urb, mem_flags); |
354 | if (status) { |
355 | rsi_dbg(ERR_ZONE, fmt: "%s: Failed in urb submission\n" , __func__); |
356 | dev_kfree_skb(skb); |
357 | } |
358 | |
359 | return status; |
360 | } |
361 | |
362 | static int rsi_usb_read_register_multiple(struct rsi_hw *adapter, u32 addr, |
363 | u8 *data, u16 count) |
364 | { |
365 | struct rsi_91x_usbdev *dev = adapter->rsi_dev; |
366 | u8 *buf; |
367 | u16 transfer; |
368 | int status; |
369 | |
370 | if (!addr) |
371 | return -EINVAL; |
372 | |
373 | buf = kzalloc(RSI_USB_BUF_SIZE, GFP_KERNEL); |
374 | if (!buf) |
375 | return -ENOMEM; |
376 | |
377 | while (count) { |
378 | transfer = min_t(u16, count, RSI_USB_BUF_SIZE); |
379 | status = usb_control_msg(dev: dev->usbdev, |
380 | usb_rcvctrlpipe(dev->usbdev, 0), |
381 | USB_VENDOR_REGISTER_READ, |
382 | RSI_USB_REQ_IN, |
383 | value: ((addr & 0xffff0000) >> 16), |
384 | index: (addr & 0xffff), data: (void *)buf, |
385 | size: transfer, USB_CTRL_GET_TIMEOUT); |
386 | if (status < 0) { |
387 | rsi_dbg(ERR_ZONE, |
388 | fmt: "Reg read failed with error code :%d\n" , |
389 | status); |
390 | kfree(objp: buf); |
391 | return status; |
392 | } |
393 | memcpy(data, buf, transfer); |
394 | count -= transfer; |
395 | data += transfer; |
396 | addr += transfer; |
397 | } |
398 | kfree(objp: buf); |
399 | return 0; |
400 | } |
401 | |
402 | /** |
403 | * rsi_usb_write_register_multiple() - This function writes multiple bytes of |
404 | * information to multiple registers. |
405 | * @adapter: Pointer to the adapter structure. |
406 | * @addr: Address of the register. |
407 | * @data: Pointer to the data that has to be written. |
408 | * @count: Number of multiple bytes to be written on to the registers. |
409 | * |
410 | * Return: status: 0 on success, a negative error code on failure. |
411 | */ |
412 | static int rsi_usb_write_register_multiple(struct rsi_hw *adapter, u32 addr, |
413 | u8 *data, u16 count) |
414 | { |
415 | struct rsi_91x_usbdev *dev = adapter->rsi_dev; |
416 | u8 *buf; |
417 | u16 transfer; |
418 | int status = 0; |
419 | |
420 | buf = kzalloc(RSI_USB_BUF_SIZE, GFP_KERNEL); |
421 | if (!buf) |
422 | return -ENOMEM; |
423 | |
424 | while (count) { |
425 | transfer = min_t(u16, count, RSI_USB_BUF_SIZE); |
426 | memcpy(buf, data, transfer); |
427 | status = usb_control_msg(dev: dev->usbdev, |
428 | usb_sndctrlpipe(dev->usbdev, 0), |
429 | USB_VENDOR_REGISTER_WRITE, |
430 | RSI_USB_REQ_OUT, |
431 | value: ((addr & 0xffff0000) >> 16), |
432 | index: (addr & 0xffff), |
433 | data: (void *)buf, |
434 | size: transfer, |
435 | USB_CTRL_SET_TIMEOUT); |
436 | if (status < 0) { |
437 | rsi_dbg(ERR_ZONE, |
438 | fmt: "Reg write failed with error code :%d\n" , |
439 | status); |
440 | kfree(objp: buf); |
441 | return status; |
442 | } |
443 | count -= transfer; |
444 | data += transfer; |
445 | addr += transfer; |
446 | } |
447 | |
448 | kfree(objp: buf); |
449 | return 0; |
450 | } |
451 | |
452 | /** |
453 | *rsi_usb_host_intf_write_pkt() - This function writes the packet to the |
454 | * USB card. |
455 | * @adapter: Pointer to the adapter structure. |
456 | * @pkt: Pointer to the data to be written on to the card. |
457 | * @len: Length of the data to be written on to the card. |
458 | * |
459 | * Return: 0 on success, a negative error code on failure. |
460 | */ |
461 | static int rsi_usb_host_intf_write_pkt(struct rsi_hw *adapter, |
462 | u8 *pkt, |
463 | u32 len) |
464 | { |
465 | u32 queueno = ((pkt[1] >> 4) & 0x7); |
466 | u8 endpoint; |
467 | |
468 | endpoint = ((queueno == RSI_WIFI_MGMT_Q || queueno == RSI_WIFI_DATA_Q || |
469 | queueno == RSI_COEX_Q) ? WLAN_EP : BT_EP); |
470 | |
471 | return rsi_write_multiple(adapter, |
472 | endpoint, |
473 | data: (u8 *)pkt, |
474 | count: len); |
475 | } |
476 | |
477 | static int rsi_usb_master_reg_read(struct rsi_hw *adapter, u32 reg, |
478 | u32 *value, u16 len) |
479 | { |
480 | struct usb_device *usbdev = |
481 | ((struct rsi_91x_usbdev *)adapter->rsi_dev)->usbdev; |
482 | u16 temp; |
483 | int ret; |
484 | |
485 | ret = rsi_usb_reg_read(usbdev, reg, value: &temp, len); |
486 | if (ret < 0) |
487 | return ret; |
488 | *value = temp; |
489 | |
490 | return 0; |
491 | } |
492 | |
493 | static int rsi_usb_master_reg_write(struct rsi_hw *adapter, |
494 | unsigned long reg, |
495 | unsigned long value, u16 len) |
496 | { |
497 | struct usb_device *usbdev = |
498 | ((struct rsi_91x_usbdev *)adapter->rsi_dev)->usbdev; |
499 | |
500 | return rsi_usb_reg_write(usbdev, reg, value, len); |
501 | } |
502 | |
503 | static int rsi_usb_load_data_master_write(struct rsi_hw *adapter, |
504 | u32 base_address, |
505 | u32 instructions_sz, u16 block_size, |
506 | u8 *ta_firmware) |
507 | { |
508 | u16 num_blocks; |
509 | u32 cur_indx, i; |
510 | u8 temp_buf[256]; |
511 | int status; |
512 | |
513 | num_blocks = instructions_sz / block_size; |
514 | rsi_dbg(INFO_ZONE, fmt: "num_blocks: %d\n" , num_blocks); |
515 | |
516 | for (cur_indx = 0, i = 0; i < num_blocks; i++, cur_indx += block_size) { |
517 | memcpy(temp_buf, ta_firmware + cur_indx, block_size); |
518 | status = rsi_usb_write_register_multiple(adapter, addr: base_address, |
519 | data: (u8 *)(temp_buf), |
520 | count: block_size); |
521 | if (status < 0) |
522 | return status; |
523 | |
524 | rsi_dbg(INFO_ZONE, fmt: "%s: loading block: %d\n" , __func__, i); |
525 | base_address += block_size; |
526 | } |
527 | |
528 | if (instructions_sz % block_size) { |
529 | memset(temp_buf, 0, block_size); |
530 | memcpy(temp_buf, ta_firmware + cur_indx, |
531 | instructions_sz % block_size); |
532 | status = rsi_usb_write_register_multiple |
533 | (adapter, addr: base_address, |
534 | data: (u8 *)temp_buf, |
535 | count: instructions_sz % block_size); |
536 | if (status < 0) |
537 | return status; |
538 | rsi_dbg(INFO_ZONE, |
539 | fmt: "Written Last Block in Address 0x%x Successfully\n" , |
540 | cur_indx); |
541 | } |
542 | return 0; |
543 | } |
544 | |
545 | static struct rsi_host_intf_ops usb_host_intf_ops = { |
546 | .write_pkt = rsi_usb_host_intf_write_pkt, |
547 | .read_reg_multiple = rsi_usb_read_register_multiple, |
548 | .write_reg_multiple = rsi_usb_write_register_multiple, |
549 | .master_reg_read = rsi_usb_master_reg_read, |
550 | .master_reg_write = rsi_usb_master_reg_write, |
551 | .load_data_master_write = rsi_usb_load_data_master_write, |
552 | }; |
553 | |
554 | /** |
555 | * rsi_deinit_usb_interface() - This function deinitializes the usb interface. |
556 | * @adapter: Pointer to the adapter structure. |
557 | * |
558 | * Return: None. |
559 | */ |
560 | static void rsi_deinit_usb_interface(struct rsi_hw *adapter) |
561 | { |
562 | struct rsi_91x_usbdev *dev = adapter->rsi_dev; |
563 | |
564 | rsi_kill_thread(handle: &dev->rx_thread); |
565 | |
566 | usb_free_urb(urb: dev->rx_cb[0].rx_urb); |
567 | if (adapter->priv->coex_mode > 1) |
568 | usb_free_urb(urb: dev->rx_cb[1].rx_urb); |
569 | |
570 | kfree(objp: dev->tx_buffer); |
571 | } |
572 | |
573 | static int rsi_usb_init_rx(struct rsi_hw *adapter) |
574 | { |
575 | struct rsi_91x_usbdev *dev = adapter->rsi_dev; |
576 | struct rx_usb_ctrl_block *rx_cb; |
577 | u8 idx, num_rx_cb; |
578 | |
579 | num_rx_cb = (adapter->priv->coex_mode > 1 ? 2 : 1); |
580 | |
581 | for (idx = 0; idx < num_rx_cb; idx++) { |
582 | rx_cb = &dev->rx_cb[idx]; |
583 | |
584 | rx_cb->rx_urb = usb_alloc_urb(iso_packets: 0, GFP_KERNEL); |
585 | if (!rx_cb->rx_urb) { |
586 | rsi_dbg(ERR_ZONE, fmt: "Failed alloc rx urb[%d]\n" , idx); |
587 | goto err; |
588 | } |
589 | rx_cb->ep_num = idx + 1; |
590 | rx_cb->data = (void *)dev; |
591 | } |
592 | skb_queue_head_init(list: &dev->rx_q); |
593 | rsi_init_event(pevent: &dev->rx_thread.event); |
594 | if (rsi_create_kthread(common: adapter->priv, thread: &dev->rx_thread, |
595 | func_ptr: rsi_usb_rx_thread, name: "RX-Thread" )) { |
596 | rsi_dbg(ERR_ZONE, fmt: "%s: Unable to init rx thrd\n" , __func__); |
597 | goto err; |
598 | } |
599 | |
600 | return 0; |
601 | |
602 | err: |
603 | usb_free_urb(urb: dev->rx_cb[0].rx_urb); |
604 | if (adapter->priv->coex_mode > 1) |
605 | usb_free_urb(urb: dev->rx_cb[1].rx_urb); |
606 | |
607 | return -1; |
608 | } |
609 | |
610 | /** |
611 | * rsi_init_usb_interface() - This function initializes the usb interface. |
612 | * @adapter: Pointer to the adapter structure. |
613 | * @pfunction: Pointer to USB interface structure. |
614 | * |
615 | * Return: 0 on success, a negative error code on failure. |
616 | */ |
617 | static int rsi_init_usb_interface(struct rsi_hw *adapter, |
618 | struct usb_interface *pfunction) |
619 | { |
620 | struct rsi_91x_usbdev *rsi_dev; |
621 | int status; |
622 | |
623 | rsi_dev = kzalloc(size: sizeof(*rsi_dev), GFP_KERNEL); |
624 | if (!rsi_dev) |
625 | return -ENOMEM; |
626 | |
627 | adapter->rsi_dev = rsi_dev; |
628 | rsi_dev->usbdev = interface_to_usbdev(pfunction); |
629 | rsi_dev->priv = (void *)adapter; |
630 | |
631 | if (rsi_find_bulk_in_and_out_endpoints(interface: pfunction, adapter)) { |
632 | status = -EINVAL; |
633 | goto fail_eps; |
634 | } |
635 | |
636 | adapter->device = &pfunction->dev; |
637 | usb_set_intfdata(intf: pfunction, data: adapter); |
638 | |
639 | rsi_dev->tx_buffer = kmalloc(size: 2048, GFP_KERNEL); |
640 | if (!rsi_dev->tx_buffer) { |
641 | status = -ENOMEM; |
642 | goto fail_eps; |
643 | } |
644 | |
645 | if (rsi_usb_init_rx(adapter)) { |
646 | rsi_dbg(ERR_ZONE, fmt: "Failed to init RX handle\n" ); |
647 | status = -ENOMEM; |
648 | goto fail_rx; |
649 | } |
650 | |
651 | rsi_dev->tx_blk_size = 252; |
652 | adapter->block_size = rsi_dev->tx_blk_size; |
653 | |
654 | /* Initializing function callbacks */ |
655 | adapter->check_hw_queue_status = rsi_usb_check_queue_status; |
656 | adapter->determine_event_timeout = rsi_usb_event_timeout; |
657 | adapter->rsi_host_intf = RSI_HOST_INTF_USB; |
658 | adapter->host_intf_ops = &usb_host_intf_ops; |
659 | |
660 | #ifdef CONFIG_RSI_DEBUGFS |
661 | /* In USB, one less than the MAX_DEBUGFS_ENTRIES entries is required */ |
662 | adapter->num_debugfs_entries = (MAX_DEBUGFS_ENTRIES - 1); |
663 | #endif |
664 | |
665 | rsi_dbg(INIT_ZONE, fmt: "%s: Enabled the interface\n" , __func__); |
666 | return 0; |
667 | |
668 | fail_rx: |
669 | kfree(objp: rsi_dev->tx_buffer); |
670 | |
671 | fail_eps: |
672 | |
673 | return status; |
674 | } |
675 | |
676 | static int usb_ulp_read_write(struct rsi_hw *adapter, u16 addr, u32 data, |
677 | u16 len_in_bits) |
678 | { |
679 | int ret; |
680 | |
681 | ret = rsi_usb_master_reg_write |
682 | (adapter, RSI_GSPI_DATA_REG1, |
683 | value: ((addr << 6) | ((data >> 16) & 0xffff)), len: 2); |
684 | if (ret < 0) |
685 | return ret; |
686 | |
687 | ret = rsi_usb_master_reg_write(adapter, RSI_GSPI_DATA_REG0, |
688 | value: (data & 0xffff), len: 2); |
689 | if (ret < 0) |
690 | return ret; |
691 | |
692 | /* Initializing GSPI for ULP read/writes */ |
693 | rsi_usb_master_reg_write(adapter, RSI_GSPI_CTRL_REG0, |
694 | RSI_GSPI_CTRL_REG0_VALUE, len: 2); |
695 | |
696 | ret = rsi_usb_master_reg_write(adapter, RSI_GSPI_CTRL_REG1, |
697 | value: ((len_in_bits - 1) | RSI_GSPI_TRIG), len: 2); |
698 | if (ret < 0) |
699 | return ret; |
700 | |
701 | msleep(msecs: 20); |
702 | |
703 | return 0; |
704 | } |
705 | |
706 | static int rsi_reset_card(struct rsi_hw *adapter) |
707 | { |
708 | int ret; |
709 | |
710 | rsi_dbg(INFO_ZONE, fmt: "Resetting Card...\n" ); |
711 | rsi_usb_master_reg_write(adapter, RSI_TA_HOLD_REG, value: 0xE, len: 4); |
712 | |
713 | /* This msleep will ensure Thread-Arch processor to go to hold |
714 | * and any pending dma transfers to rf in device to finish. |
715 | */ |
716 | msleep(msecs: 100); |
717 | |
718 | ret = rsi_usb_master_reg_write(adapter, SWBL_REGOUT, |
719 | RSI_FW_WDT_DISABLE_REQ, |
720 | RSI_COMMON_REG_SIZE); |
721 | if (ret < 0) { |
722 | rsi_dbg(ERR_ZONE, fmt: "Disabling firmware watchdog timer failed\n" ); |
723 | goto fail; |
724 | } |
725 | |
726 | if (adapter->device_model != RSI_DEV_9116) { |
727 | ret = usb_ulp_read_write(adapter, RSI_WATCH_DOG_TIMER_1, |
728 | RSI_ULP_WRITE_2, len_in_bits: 32); |
729 | if (ret < 0) |
730 | goto fail; |
731 | ret = usb_ulp_read_write(adapter, RSI_WATCH_DOG_TIMER_2, |
732 | RSI_ULP_WRITE_0, len_in_bits: 32); |
733 | if (ret < 0) |
734 | goto fail; |
735 | ret = usb_ulp_read_write(adapter, RSI_WATCH_DOG_DELAY_TIMER_1, |
736 | RSI_ULP_WRITE_50, len_in_bits: 32); |
737 | if (ret < 0) |
738 | goto fail; |
739 | ret = usb_ulp_read_write(adapter, RSI_WATCH_DOG_DELAY_TIMER_2, |
740 | RSI_ULP_WRITE_0, len_in_bits: 32); |
741 | if (ret < 0) |
742 | goto fail; |
743 | ret = usb_ulp_read_write(adapter, RSI_WATCH_DOG_TIMER_ENABLE, |
744 | RSI_ULP_TIMER_ENABLE, len_in_bits: 32); |
745 | if (ret < 0) |
746 | goto fail; |
747 | } else { |
748 | ret = rsi_usb_master_reg_write(adapter, |
749 | NWP_WWD_INTERRUPT_TIMER, |
750 | NWP_WWD_INT_TIMER_CLKS, |
751 | RSI_9116_REG_SIZE); |
752 | if (ret < 0) |
753 | goto fail; |
754 | ret = rsi_usb_master_reg_write(adapter, |
755 | NWP_WWD_SYSTEM_RESET_TIMER, |
756 | NWP_WWD_SYS_RESET_TIMER_CLKS, |
757 | RSI_9116_REG_SIZE); |
758 | if (ret < 0) |
759 | goto fail; |
760 | ret = rsi_usb_master_reg_write(adapter, |
761 | NWP_WWD_MODE_AND_RSTART, |
762 | NWP_WWD_TIMER_DISABLE, |
763 | RSI_9116_REG_SIZE); |
764 | if (ret < 0) |
765 | goto fail; |
766 | } |
767 | |
768 | rsi_dbg(INFO_ZONE, fmt: "Reset card done\n" ); |
769 | return ret; |
770 | |
771 | fail: |
772 | rsi_dbg(ERR_ZONE, fmt: "Reset card failed\n" ); |
773 | return ret; |
774 | } |
775 | |
776 | /** |
777 | * rsi_probe() - This function is called by kernel when the driver provided |
778 | * Vendor and device IDs are matched. All the initialization |
779 | * work is done here. |
780 | * @pfunction: Pointer to the USB interface structure. |
781 | * @id: Pointer to the usb_device_id structure. |
782 | * |
783 | * Return: 0 on success, a negative error code on failure. |
784 | */ |
785 | static int rsi_probe(struct usb_interface *pfunction, |
786 | const struct usb_device_id *id) |
787 | { |
788 | struct rsi_hw *adapter; |
789 | struct rsi_91x_usbdev *dev; |
790 | u16 fw_status; |
791 | int status; |
792 | |
793 | rsi_dbg(INIT_ZONE, fmt: "%s: Init function called\n" , __func__); |
794 | |
795 | adapter = rsi_91x_init(oper_mode: dev_oper_mode); |
796 | if (!adapter) { |
797 | rsi_dbg(ERR_ZONE, fmt: "%s: Failed to init os intf ops\n" , |
798 | __func__); |
799 | return -ENOMEM; |
800 | } |
801 | adapter->rsi_host_intf = RSI_HOST_INTF_USB; |
802 | |
803 | status = rsi_init_usb_interface(adapter, pfunction); |
804 | if (status) { |
805 | rsi_dbg(ERR_ZONE, fmt: "%s: Failed to init usb interface\n" , |
806 | __func__); |
807 | goto err; |
808 | } |
809 | |
810 | rsi_dbg(ERR_ZONE, fmt: "%s: Initialized os intf ops\n" , __func__); |
811 | |
812 | if (id->idProduct == RSI_USB_PID_9113) { |
813 | rsi_dbg(INIT_ZONE, fmt: "%s: 9113 module detected\n" , __func__); |
814 | adapter->device_model = RSI_DEV_9113; |
815 | } else if (id->idProduct == RSI_USB_PID_9116) { |
816 | rsi_dbg(INIT_ZONE, fmt: "%s: 9116 module detected\n" , __func__); |
817 | adapter->device_model = RSI_DEV_9116; |
818 | } else { |
819 | rsi_dbg(ERR_ZONE, fmt: "%s: Unsupported RSI device id 0x%x\n" , |
820 | __func__, id->idProduct); |
821 | status = -ENODEV; |
822 | goto err1; |
823 | } |
824 | |
825 | dev = adapter->rsi_dev; |
826 | |
827 | status = rsi_usb_reg_read(usbdev: dev->usbdev, FW_STATUS_REG, value: &fw_status, len: 2); |
828 | if (status < 0) |
829 | goto err1; |
830 | else |
831 | fw_status &= 1; |
832 | |
833 | if (!fw_status) { |
834 | rsi_dbg(INIT_ZONE, fmt: "Loading firmware...\n" ); |
835 | status = rsi_hal_device_init(adapter); |
836 | if (status) { |
837 | rsi_dbg(ERR_ZONE, fmt: "%s: Failed in device init\n" , |
838 | __func__); |
839 | goto err1; |
840 | } |
841 | rsi_dbg(INIT_ZONE, fmt: "%s: Device Init Done\n" , __func__); |
842 | } |
843 | |
844 | status = rsi_rx_urb_submit(adapter, WLAN_EP, GFP_KERNEL); |
845 | if (status) |
846 | goto err1; |
847 | |
848 | if (adapter->priv->coex_mode > 1) { |
849 | status = rsi_rx_urb_submit(adapter, BT_EP, GFP_KERNEL); |
850 | if (status) |
851 | goto err_kill_wlan_urb; |
852 | } |
853 | |
854 | return 0; |
855 | |
856 | err_kill_wlan_urb: |
857 | rsi_rx_urb_kill(adapter, WLAN_EP); |
858 | err1: |
859 | rsi_deinit_usb_interface(adapter); |
860 | err: |
861 | rsi_91x_deinit(adapter); |
862 | rsi_dbg(ERR_ZONE, fmt: "%s: Failed in probe...Exiting\n" , __func__); |
863 | return status; |
864 | } |
865 | |
866 | /** |
867 | * rsi_disconnect() - This function performs the reverse of the probe function, |
868 | * it deinitialize the driver structure. |
869 | * @pfunction: Pointer to the USB interface structure. |
870 | * |
871 | * Return: None. |
872 | */ |
873 | static void rsi_disconnect(struct usb_interface *pfunction) |
874 | { |
875 | struct rsi_hw *adapter = usb_get_intfdata(intf: pfunction); |
876 | |
877 | if (!adapter) |
878 | return; |
879 | |
880 | rsi_mac80211_detach(hw: adapter); |
881 | |
882 | if (IS_ENABLED(CONFIG_RSI_COEX) && adapter->priv->coex_mode > 1 && |
883 | adapter->priv->bt_adapter) { |
884 | rsi_bt_ops.detach(adapter->priv->bt_adapter); |
885 | adapter->priv->bt_adapter = NULL; |
886 | } |
887 | |
888 | if (adapter->priv->coex_mode > 1) |
889 | rsi_rx_urb_kill(adapter, BT_EP); |
890 | rsi_rx_urb_kill(adapter, WLAN_EP); |
891 | |
892 | rsi_reset_card(adapter); |
893 | rsi_deinit_usb_interface(adapter); |
894 | rsi_91x_deinit(adapter); |
895 | |
896 | rsi_dbg(INFO_ZONE, fmt: "%s: Deinitialization completed\n" , __func__); |
897 | } |
898 | |
899 | #ifdef CONFIG_PM |
900 | static int rsi_suspend(struct usb_interface *intf, pm_message_t message) |
901 | { |
902 | /* Not yet implemented */ |
903 | return -ENOSYS; |
904 | } |
905 | |
906 | static int rsi_resume(struct usb_interface *intf) |
907 | { |
908 | /* Not yet implemented */ |
909 | return -ENOSYS; |
910 | } |
911 | #endif |
912 | |
913 | static const struct usb_device_id rsi_dev_table[] = { |
914 | { USB_DEVICE(RSI_USB_VENDOR_ID, RSI_USB_PID_9113) }, |
915 | { USB_DEVICE(RSI_USB_VENDOR_ID, RSI_USB_PID_9116) }, |
916 | { /* Blank */}, |
917 | }; |
918 | |
919 | static struct usb_driver rsi_driver = { |
920 | .name = "RSI-USB WLAN" , |
921 | .probe = rsi_probe, |
922 | .disconnect = rsi_disconnect, |
923 | .id_table = rsi_dev_table, |
924 | #ifdef CONFIG_PM |
925 | .suspend = rsi_suspend, |
926 | .resume = rsi_resume, |
927 | #endif |
928 | }; |
929 | |
930 | module_usb_driver(rsi_driver); |
931 | |
932 | MODULE_AUTHOR("Redpine Signals Inc" ); |
933 | MODULE_DESCRIPTION("Common USB layer for RSI drivers" ); |
934 | MODULE_DEVICE_TABLE(usb, rsi_dev_table); |
935 | MODULE_FIRMWARE(FIRMWARE_RSI9113); |
936 | MODULE_VERSION("0.1" ); |
937 | MODULE_LICENSE("Dual BSD/GPL" ); |
938 | |