18 #include <linux/module.h>
25 #define TX_URB_COUNT 32
26 #define RX_URB_COUNT 32
27 #define ATH6KL_USB_RX_BUFFER_SIZE 1700
42 #define ATH6KL_USB_PIPE_INVALID ATH6KL_USB_PIPE_MAX
61 #define ATH6KL_USB_PIPE_FLAG_TX (1 << 0)
85 #define ATH6KL_USB_EP_ADDR_APP_CTRL_IN 0x81
86 #define ATH6KL_USB_EP_ADDR_APP_DATA_IN 0x82
87 #define ATH6KL_USB_EP_ADDR_APP_DATA2_IN 0x83
88 #define ATH6KL_USB_EP_ADDR_APP_INT_IN 0x84
90 #define ATH6KL_USB_EP_ADDR_APP_CTRL_OUT 0x01
91 #define ATH6KL_USB_EP_ADDR_APP_DATA_LP_OUT 0x02
92 #define ATH6KL_USB_EP_ADDR_APP_DATA_MP_OUT 0x03
93 #define ATH6KL_USB_EP_ADDR_APP_DATA_HP_OUT 0x04
96 #define ATH6KL_USB_CONTROL_REQ_SEND_BMI_CMD 1
97 #define ATH6KL_USB_CONTROL_REQ_RECV_BMI_RESP 2
98 #define ATH6KL_USB_CONTROL_REQ_DIAG_CMD 3
99 #define ATH6KL_USB_CONTROL_REQ_DIAG_RESP 4
101 #define ATH6KL_USB_CTRL_DIAG_CC_READ 0
102 #define ATH6KL_USB_CTRL_DIAG_CC_WRITE 1
121 static void ath6kl_usb_recv_complete(
struct urb *
urb);
123 #define ATH6KL_USB_IS_BULK_EP(attr) (((attr) & 3) == 0x02)
124 #define ATH6KL_USB_IS_INT_EP(attr) (((attr) & 3) == 0x03)
125 #define ATH6KL_USB_IS_ISOC_EP(attr) (((attr) & 3) == 0x01)
126 #define ATH6KL_USB_IS_DIR_IN(addr) ((addr) & 0x80)
143 spin_unlock_irqrestore(&pipe->
ar_usb->cs_lock, flags);
157 spin_unlock_irqrestore(&pipe->
ar_usb->cs_lock, flags);
162 if (urb_context->
skb !=
NULL) {
163 dev_kfree_skb(urb_context->
skb);
167 ath6kl_usb_free_urb_to_pipe(urb_context->
pipe, urb_context);
185 for (
i = 0;
i < urb_cnt;
i++) {
188 if (urb_context ==
NULL)
199 ath6kl_usb_free_urb_to_pipe(pipe, urb_context);
203 "ath6kl usb: alloc resources lpipe:%d hpipe:0x%X urbs:%d\n",
210 static void ath6kl_usb_free_pipe_resources(
struct ath6kl_usb_pipe *pipe)
220 "ath6kl usb: free resources lpipe:%d"
221 "hpipe:0x%X urbs:%d avail:%d\n",
227 "ath6kl usb: urb leak! lpipe:%d"
228 "hpipe:0x%X urbs:%d avail:%d\n",
234 urb_context = ath6kl_usb_alloc_urb_from_pipe(pipe);
235 if (urb_context ==
NULL)
242 static void ath6kl_usb_cleanup_pipe_resources(
struct ath6kl_usb *ar_usb)
247 ath6kl_usb_free_pipe_resources(&ar_usb->
pipes[i]);
251 static u8 ath6kl_usb_get_logical_pipe_num(
struct ath6kl_usb *ar_usb,
252 u8 ep_address,
int *urb_count)
256 switch (ep_address) {
297 static int ath6kl_usb_setup_pipe_resources(
struct ath6kl_usb *ar_usb)
300 struct usb_host_interface *iface_desc =
interface->cur_altsetting;
303 int i, urbcount, status = 0;
306 ath6kl_dbg(
ATH6KL_DBG_USB,
"setting up USB Pipes using interface\n");
309 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++
i) {
310 endpoint = &iface_desc->endpoint[
i].desc;
314 "%s Bulk Ep:0x%2.2X maxpktsz:%d\n",
321 "%s Int Ep:0x%2.2X maxpktsz:%d interval:%d\n",
330 "%s ISOC Ep:0x%2.2X maxpktsz:%d interval:%d\n",
340 ath6kl_usb_get_logical_pipe_num(ar_usb,
346 pipe = &ar_usb->
pipes[pipe_num];
360 usb_rcvbulkpipe(ar_usb->
udev,
364 usb_sndbulkpipe(ar_usb->
udev,
370 usb_rcvintpipe(ar_usb->
udev,
374 usb_sndintpipe(ar_usb->
udev,
381 usb_rcvisocpipe(ar_usb->
udev,
385 usb_sndisocpipe(ar_usb->
udev,
395 status = ath6kl_usb_alloc_pipe_resources(pipe, urbcount);
404 static void ath6kl_usb_post_recv_transfers(
struct ath6kl_usb_pipe *recv_pipe,
412 urb_context = ath6kl_usb_alloc_urb_from_pipe(recv_pipe);
413 if (urb_context ==
NULL)
416 urb_context->
skb = dev_alloc_skb(buffer_length);
418 goto err_cleanup_urb;
422 goto err_cleanup_urb;
424 usb_fill_bulk_urb(urb,
427 urb_context->
skb->data,
429 ath6kl_usb_recv_complete, urb_context);
432 "ath6kl usb: bulk recv submit:%d, 0x%X (ep:0x%2.2X), %d bytes buf:0x%p\n",
435 buffer_length, urb_context->
skb);
442 "ath6kl usb : usb bulk recv failed %d\n",
446 goto err_cleanup_urb;
453 ath6kl_usb_cleanup_recv_urb(urb_context);
457 static void ath6kl_usb_flush_all(
struct ath6kl_usb *ar_usb)
473 static void ath6kl_usb_start_recv_pipes(
struct ath6kl_usb *ar_usb)
491 static void ath6kl_usb_recv_complete(
struct urb *urb)
499 "%s: recv pipe: %d, stat:%d, len:%d urb:0x%p\n", __func__,
503 if (urb->status != 0) {
505 switch (urb->status) {
517 "%s recv pipe: %d (ep:0x%2.2X), failed:%d\n",
522 goto cleanup_recv_urb;
525 if (urb->actual_length == 0)
526 goto cleanup_recv_urb;
528 skb = urb_context->
skb;
532 skb_put(skb, urb->actual_length);
539 ath6kl_usb_cleanup_recv_urb(urb_context);
548 static void ath6kl_usb_usb_transmit_complete(
struct urb *urb)
555 "%s: pipe: %d, stat:%d, len:%d\n",
559 if (urb->status != 0) {
561 "%s: pipe: %d, failed:%d\n",
565 skb = urb_context->
skb;
567 ath6kl_usb_free_urb_to_pipe(urb_context->
pipe, urb_context);
587 "ath6kl usb xmit callback buf:0x%p\n", skb);
591 "ath6kl usb recv callback buf:0x%p\n", skb);
598 #define ATH6KL_USB_MAX_DIAG_CMD (sizeof(struct ath6kl_usb_ctrl_diag_cmd_write))
599 #define ATH6KL_USB_MAX_DIAG_RESP (sizeof(struct ath6kl_usb_ctrl_diag_resp_read))
601 static void ath6kl_usb_destroy(
struct ath6kl_usb *ar_usb)
603 ath6kl_usb_flush_all(ar_usb);
605 ath6kl_usb_cleanup_pipe_resources(ar_usb);
617 struct usb_device *
dev = interface_to_usbdev(interface);
625 goto fail_ath6kl_usb_create;
627 usb_set_intfdata(interface, ar_usb);
635 ath6kl_usb_io_comp_work);
642 goto fail_ath6kl_usb_create;
649 goto fail_ath6kl_usb_create;
652 status = ath6kl_usb_setup_pipe_resources(ar_usb);
654 fail_ath6kl_usb_create:
656 ath6kl_usb_destroy(ar_usb);
662 static void ath6kl_usb_device_detached(
struct usb_interface *interface)
666 ar_usb = usb_get_intfdata(interface);
675 ath6kl_usb_destroy(ar_usb);
679 static void hif_start(
struct ath6kl *
ar)
684 ath6kl_usb_start_recv_pipes(device);
689 device->
pipes[
i].urb_cnt_thresh =
690 device->
pipes[
i].urb_alloc / 2;
694 static int ath6kl_usb_send(
struct ath6kl *ar,
u8 PipeID,
697 struct ath6kl_usb *device = ath6kl_usb_priv(ar);
700 int usb_status, status = 0;
706 __func__, PipeID, skb);
708 urb_context = ath6kl_usb_alloc_urb_from_pipe(pipe);
710 if (urb_context ==
NULL) {
716 "%s pipe:%d no urbs left. URB Cnt : %d\n",
717 __func__, PipeID, pipe->
urb_cnt);
730 ath6kl_usb_free_urb_to_pipe(urb_context->
pipe,
735 usb_fill_bulk_urb(urb,
740 ath6kl_usb_usb_transmit_complete, urb_context);
744 urb->transfer_flags |= URB_ZERO_PACKET;
748 "athusb bulk send submit:%d, 0x%X (ep:0x%2.2X), %d bytes\n",
757 "ath6kl usb : usb bulk transmit failed %d\n",
760 ath6kl_usb_free_urb_to_pipe(urb_context->
pipe,
770 static void hif_stop(
struct ath6kl *ar)
772 struct ath6kl_usb *device = ath6kl_usb_priv(ar);
774 ath6kl_usb_flush_all(device);
777 static void ath6kl_usb_get_default_pipe(
struct ath6kl *ar,
778 u8 *ul_pipe,
u8 *dl_pipe)
784 static int ath6kl_usb_map_service_pipe(
struct ath6kl *ar,
u16 svc_id,
785 u8 *ul_pipe,
u8 *dl_pipe)
829 static u16 ath6kl_usb_get_free_queue_number(
struct ath6kl *ar,
u8 pipe_id)
831 struct ath6kl_usb *device = ath6kl_usb_priv(ar);
833 return device->
pipes[pipe_id].urb_cnt;
836 static void hif_detach_htc(
struct ath6kl *ar)
838 struct ath6kl_usb *device = ath6kl_usb_priv(ar);
840 ath6kl_usb_flush_all(device);
843 static int ath6kl_usb_submit_ctrl_out(
struct ath6kl_usb *ar_usb,
860 usb_sndctrlpipe(ar_usb->
udev, 0),
876 static int ath6kl_usb_submit_ctrl_in(
struct ath6kl_usb *ar_usb,
877 u8 req,
u16 value,
u16 index,
void *data,
891 usb_rcvctrlpipe(ar_usb->
udev, 0),
909 static int ath6kl_usb_ctrl_msg_exchange(
struct ath6kl_usb *ar_usb,
916 ret = ath6kl_usb_submit_ctrl_out(ar_usb, req_val, 0, 0,
922 if (resp_buf ==
NULL) {
928 ret = ath6kl_usb_submit_ctrl_in(ar_usb, resp_val, 0, 0,
929 resp_buf, *resp_len);
944 memset(cmd, 0,
sizeof(*cmd));
947 resp_len =
sizeof(*resp);
949 ret = ath6kl_usb_ctrl_msg_exchange(ar_usb,
967 static int ath6kl_usb_diag_write32(
struct ath6kl *ar,
u32 address,
__le32 data)
979 return ath6kl_usb_ctrl_msg_exchange(ar_usb,
987 static int ath6kl_usb_bmi_read(
struct ath6kl *ar,
u8 *buf,
u32 len)
993 ret = ath6kl_usb_submit_ctrl_in(ar_usb,
997 ath6kl_err(
"Unable to read the bmi data from the device: %d\n",
1005 static int ath6kl_usb_bmi_write(
struct ath6kl *ar,
u8 *buf,
u32 len)
1011 ret = ath6kl_usb_submit_ctrl_out(ar_usb,
1015 ath6kl_err(
"unable to send the bmi data to the device: %d\n",
1023 static int ath6kl_usb_power_on(
struct ath6kl *ar)
1029 static int ath6kl_usb_power_off(
struct ath6kl *ar)
1035 static void ath6kl_usb_stop(
struct ath6kl *ar)
1040 static void ath6kl_usb_cleanup_scatter(
struct ath6kl *ar)
1049 .diag_read32 = ath6kl_usb_diag_read32,
1050 .diag_write32 = ath6kl_usb_diag_write32,
1051 .bmi_read = ath6kl_usb_bmi_read,
1052 .bmi_write = ath6kl_usb_bmi_write,
1053 .power_on = ath6kl_usb_power_on,
1054 .power_off = ath6kl_usb_power_off,
1055 .stop = ath6kl_usb_stop,
1056 .pipe_send = ath6kl_usb_send,
1057 .pipe_get_default = ath6kl_usb_get_default_pipe,
1058 .pipe_map_service = ath6kl_usb_map_service_pipe,
1059 .pipe_get_free_queue_number = ath6kl_usb_get_free_queue_number,
1060 .cleanup_scatter = ath6kl_usb_cleanup_scatter,
1064 static int ath6kl_usb_probe(
struct usb_interface *interface,
1067 struct usb_device *dev = interface_to_usbdev(interface);
1075 vendor_id =
le16_to_cpu(dev->descriptor.idVendor);
1076 product_id =
le16_to_cpu(dev->descriptor.idProduct);
1081 if (interface->cur_altsetting)
1083 interface->cur_altsetting->desc.bInterfaceNumber);
1091 ar_usb = ath6kl_usb_create(interface);
1093 if (ar_usb ==
NULL) {
1102 goto err_usb_destroy;
1107 ar->
hif_ops = &ath6kl_usb_ops;
1109 ar->
bmi.max_data_size = 252;
1115 ath6kl_err(
"Failed to init ath6kl core: %d\n", ret);
1124 ath6kl_usb_destroy(ar_usb);
1131 static void ath6kl_usb_remove(
struct usb_interface *interface)
1134 ath6kl_usb_device_detached(interface);
1143 device = usb_get_intfdata(interface);
1145 ath6kl_usb_flush_all(device);
1152 device = usb_get_intfdata(interface);
1164 if (usb_get_intfdata(intf))
1165 ath6kl_usb_remove(intf);
1171 #define ath6kl_usb_suspend NULL
1172 #define ath6kl_usb_resume NULL
1173 #define ath6kl_usb_reset_resume NULL
1179 {USB_DEVICE(0x0cf3, 0x9374)},
1185 static struct usb_driver ath6kl_usb_driver = {
1186 .name =
"ath6kl_usb",
1187 .probe = ath6kl_usb_probe,
1191 .disconnect = ath6kl_usb_remove,
1192 .id_table = ath6kl_usb_ids,
1193 .supports_autosuspend =
true,
1194 .disable_hub_initiated_lpm = 1,
1197 static int ath6kl_usb_init(
void)
1199 usb_register(&ath6kl_usb_driver);
1203 static void ath6kl_usb_exit(
void)