diff options
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/serial/baseband_usb_chr.c | 98 |
1 files changed, 65 insertions, 33 deletions
diff --git a/drivers/usb/serial/baseband_usb_chr.c b/drivers/usb/serial/baseband_usb_chr.c index 96db92715207..c4eda3fe1ab7 100644 --- a/drivers/usb/serial/baseband_usb_chr.c +++ b/drivers/usb/serial/baseband_usb_chr.c @@ -74,6 +74,13 @@ static struct workqueue_struct *chr_ipc_wq; static atomic_t g_rx_count = ATOMIC_INIT(0); +struct usb_chr_resource { + unsigned char *ipc_rx; + unsigned char *ipc_tx; + unsigned char *rx_buf; +}; +static struct usb_chr_resource usb_chr_res; + /* baseband ipc functions */ static void baseband_ipc_dump(const char *prefix, unsigned long int offset, @@ -521,9 +528,7 @@ static void baseband_ipc_close(struct baseband_ipc *ipc) memset(&ipc->rx.wait, 0, sizeof(ipc->rx.wait)); /* destroy data buffers */ - kfree(ipc->ipc_tx); ipc->ipc_tx = (unsigned char *) 0; - kfree(ipc->ipc_rx); ipc->ipc_rx = (unsigned char *) 0; list_for_each_entry_safe(ipc_buf, ipc_buf_next, &ipc->tx_free.buf, list) { @@ -601,16 +606,14 @@ static struct baseband_ipc *baseband_ipc_open(work_func_t work_func, ipc_buf); list_add_tail(&ipc_buf->list, &ipc->tx_free.buf); } - ipc->ipc_rx = kmalloc(USB_CHR_RX_BUFSIZ, GFP_KERNEL); + ipc->ipc_rx = usb_chr_res.ipc_rx; if (!ipc->ipc_rx) { - pr_err("baseband_ipc_open - " - "cannot allocate ipc->ipc_rx\n"); + pr_err("%s: cannot find ipc->ipc_rx\n", __func__); goto error_exit; } - ipc->ipc_tx = kmalloc(USB_CHR_TX_BUFSIZ, GFP_KERNEL); + ipc->ipc_tx = usb_chr_res.ipc_tx; if (!ipc->ipc_tx) { - pr_err("baseband_ipc_open - " - "cannot allocate ipc->ipc_tx\n"); + pr_err("%s: cannot find ipc->ipc_tx\n", __func__); goto error_exit; } @@ -867,6 +870,7 @@ static void baseband_usb_driver_disconnect(struct usb_interface *intf) && baseband_usb_chr->ipc->workqueue) flush_workqueue(baseband_usb_chr->ipc->workqueue); usb_device_connection = false; + probe_usb_intf = NULL; } pr_debug("%s(%d) }\n", __func__, __LINE__); } @@ -956,7 +960,6 @@ static void baseband_usb_close(struct baseband_usb *usb) usb_kill_urb(usb->usb.rx_urb); if (usb->usb.rx_urb->transfer_buffer) { pr_debug("%s: free rx urb transfer buffer\n", __func__); - kfree(usb->usb.rx_urb->transfer_buffer); usb->usb.rx_urb->transfer_buffer = (void *) 0; } } @@ -966,13 +969,6 @@ static void baseband_usb_close(struct baseband_usb *usb) flush_work_sync(&usb->ipc->rx_work); } - /* close usb driver */ - if (usb->usb.driver) { - pr_debug("close usb driver {\n"); - usb_deregister(usb->usb.driver); - usb->usb.driver = (struct usb_driver *) 0; - pr_debug("close usb driver }\n"); - } /* close baseband ipc */ if (usb->ipc) { @@ -1014,24 +1010,17 @@ static struct baseband_usb *baseband_usb_open(work_func_t work_func, goto error_exit; } - /* open usb driver */ - probe_usb_intf = (struct usb_interface *) 0; usb->usb.driver = &baseband_usb_driver; - err = usb_register(&baseband_usb_driver); - if (err < 0) { - pr_err("cannot open usb driver - err %d\n", err); - goto error_exit; - } - /* wait for probe */ - pr_info("%s: waiting for usb probe...\n", __func__); - for (i = 0; i < 5 * 10; i++) { + for (i = 0; i < 5 * 50; i++) { if (probe_usb_intf && usb_device_connection) break; - msleep(100); + /* wait for probe */ + pr_debug("%s: waiting for usb probe...\n", __func__); + msleep(20); } if (!probe_usb_intf || !usb_device_connection) { - pr_info("%s: probe timed out!\n", __func__); + pr_err("%s: probe timed out!\n", __func__); goto error_exit; } @@ -1066,9 +1055,9 @@ static struct baseband_usb *baseband_usb_open(work_func_t work_func, pr_err("usb_alloc_urb() failed\n"); goto error_exit; } - buf = kmalloc(USB_CHR_RX_BUFSIZ, GFP_KERNEL); + buf = usb_chr_res.rx_buf; if (!buf) { - pr_err("%s: usb buffer kmalloc() failed\n", __func__); + pr_err("%s: usb rx buffer not found\n", __func__); usb_free_urb(urb); goto error_exit; } @@ -1222,17 +1211,33 @@ static const struct file_operations baseband_usb_chr_fops = { static int baseband_usb_chr_init(void) { - int err; + int err = -ENOMEM; pr_debug("baseband_usb_chr_init {\n"); + usb_chr_res.ipc_rx = kmalloc(USB_CHR_RX_BUFSIZ, GFP_KERNEL); + if (!usb_chr_res.ipc_rx) { + pr_err("cannot allocate ipc_rx\n"); + goto error; + } + usb_chr_res.ipc_tx = kmalloc(USB_CHR_TX_BUFSIZ, GFP_KERNEL); + if (!usb_chr_res.ipc_tx) { + pr_err("cannot allocate ipc_tx\n"); + goto error; + } + usb_chr_res.rx_buf = kmalloc(USB_CHR_RX_BUFSIZ, GFP_KERNEL); + if (!usb_chr_res.rx_buf) { + pr_err("%s: usb buffer kmalloc() failed\n", __func__); + goto error; + } + /* register character device */ err = register_chrdev(BASEBAND_USB_CHR_DEV_MAJOR, BASEBAND_USB_CHR_DEV_NAME, &baseband_usb_chr_fops); if (err < 0) { pr_err("cannot register character device - %d\n", err); - return err; + goto error; } pr_debug("registered baseband usb character device - major %d\n", BASEBAND_USB_CHR_DEV_MAJOR); @@ -1243,11 +1248,30 @@ static int baseband_usb_chr_init(void) pr_err("cannot create workqueue\n"); unregister_chrdev(BASEBAND_USB_CHR_DEV_MAJOR, BASEBAND_USB_CHR_DEV_NAME); - return -ENODEV; + err = -ENODEV; + goto error; + } + + /* register usb driver */ + err = usb_register(&baseband_usb_driver); + if (err < 0) { + pr_err("%s: cannot register usb driver %d\n", __func__, err); + goto error2; } pr_debug("baseband_usb_chr_init }\n"); return 0; + +error2: + unregister_chrdev(BASEBAND_USB_CHR_DEV_MAJOR, + BASEBAND_USB_CHR_DEV_NAME); + destroy_workqueue(chr_ipc_wq); + chr_ipc_wq = NULL; +error: + kfree(usb_chr_res.ipc_rx); + kfree(usb_chr_res.ipc_tx); + kfree(usb_chr_res.rx_buf); + return err; } static void baseband_usb_chr_exit(void) @@ -1262,6 +1286,14 @@ static void baseband_usb_chr_exit(void) destroy_workqueue(chr_ipc_wq); chr_ipc_wq = NULL; } + + /* close usb driver */ + usb_deregister(&baseband_usb_driver); + + kfree(usb_chr_res.ipc_rx); + kfree(usb_chr_res.ipc_tx); + kfree(usb_chr_res.rx_buf); + pr_debug("baseband_usb_chr_exit }\n"); } |