summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorMichael Hsu <mhsu@nvidia.com>2011-10-18 17:40:17 -0700
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:49:54 -0800
commit0e26b85e30d84b65ea5893e74deecb2d76f19391 (patch)
tree1de9635813f72f43862499ec8c6454615cc9e7ac /drivers
parent151bc231e803570689dfcc7b51edfe01a64d432a (diff)
arm: tegra: comms: Fix race condition in probe function.
XMM modem baseband character driver, which is used to download modem software, had race condition. If USB host stack has not enumerated XMM modem boot rom yet, then driver aborts module load. With this change, I/O (such as downloading modem software) will be delayed until USB host stack has enumerated modem boot rom. BUG 828389 Reviewed-on: http://git-master/r/58870 (cherry picked from commit 22a5122689ab957fd0236cf2fcf1623dac82ab69) Change-Id: Ib858363b11ea41d40218ed9ed044012421209371 Reviewed-on: http://git-master/r/62734 Reviewed-by: Varun Colbert <vcolbert@nvidia.com> Tested-by: Varun Colbert <vcolbert@nvidia.com> Rebase-Id: Re7857218c723d3c43072f17ccf5ffc70a7faf163
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/serial/baseband_usb_chr.c511
1 files changed, 262 insertions, 249 deletions
diff --git a/drivers/usb/serial/baseband_usb_chr.c b/drivers/usb/serial/baseband_usb_chr.c
index c0f45dafd4c8..bb2649dc4c36 100644
--- a/drivers/usb/serial/baseband_usb_chr.c
+++ b/drivers/usb/serial/baseband_usb_chr.c
@@ -34,7 +34,7 @@
#include <linux/usb.h>
#include <linux/workqueue.h>
#include <asm/ioctls.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include "baseband_usb_chr.h"
MODULE_LICENSE("GPL");
@@ -52,6 +52,8 @@ MODULE_PARM_DESC(baseband_usb_chr_intf, "baseband (usb chr) - USB interface");
static struct baseband_usb *baseband_usb_chr;
+static atomic_t g_rx_count = ATOMIC_INIT(0);
+
/* baseband ipc functions */
static void baseband_ipc_dump(const char *prefix, unsigned long int offset,
@@ -59,8 +61,7 @@ static void baseband_ipc_dump(const char *prefix, unsigned long int offset,
{
size_t i;
- for (i = 0; i < bufsiz; i += 16)
- {
+ for (i = 0; i < bufsiz; i += 16) {
pr_debug("%s"
"[%lx+%x] %p "
"%02x %02x %02x %02x "
@@ -71,22 +72,38 @@ static void baseband_ipc_dump(const char *prefix, unsigned long int offset,
offset,
i,
((const unsigned char *) buf) + i,
- (i + 0 < bufsiz) ? ((const unsigned char *) buf)[i+0] : 0xff,
- (i + 1 < bufsiz) ? ((const unsigned char *) buf)[i+1] : 0xff,
- (i + 2 < bufsiz) ? ((const unsigned char *) buf)[i+2] : 0xff,
- (i + 3 < bufsiz) ? ((const unsigned char *) buf)[i+3] : 0xff,
- (i + 4 < bufsiz) ? ((const unsigned char *) buf)[i+4] : 0xff,
- (i + 5 < bufsiz) ? ((const unsigned char *) buf)[i+5] : 0xff,
- (i + 6 < bufsiz) ? ((const unsigned char *) buf)[i+6] : 0xff,
- (i + 7 < bufsiz) ? ((const unsigned char *) buf)[i+7] : 0xff,
- (i + 8 < bufsiz) ? ((const unsigned char *) buf)[i+8] : 0xff,
- (i + 9 < bufsiz) ? ((const unsigned char *) buf)[i+9] : 0xff,
- (i + 10 < bufsiz) ? ((const unsigned char *) buf)[i+10] : 0xff,
- (i + 11 < bufsiz) ? ((const unsigned char *) buf)[i+11] : 0xff,
- (i + 12 < bufsiz) ? ((const unsigned char *) buf)[i+12] : 0xff,
- (i + 13 < bufsiz) ? ((const unsigned char *) buf)[i+13] : 0xff,
- (i + 14 < bufsiz) ? ((const unsigned char *) buf)[i+14] : 0xff,
- (i + 15 < bufsiz) ? ((const unsigned char *) buf)[i+15] : 0xff);
+ (i + 0 < bufsiz) ? ((const unsigned char *) buf)[i+0]
+ : 0xff,
+ (i + 1 < bufsiz) ? ((const unsigned char *) buf)[i+1]
+ : 0xff,
+ (i + 2 < bufsiz) ? ((const unsigned char *) buf)[i+2]
+ : 0xff,
+ (i + 3 < bufsiz) ? ((const unsigned char *) buf)[i+3]
+ : 0xff,
+ (i + 4 < bufsiz) ? ((const unsigned char *) buf)[i+4]
+ : 0xff,
+ (i + 5 < bufsiz) ? ((const unsigned char *) buf)[i+5]
+ : 0xff,
+ (i + 6 < bufsiz) ? ((const unsigned char *) buf)[i+6]
+ : 0xff,
+ (i + 7 < bufsiz) ? ((const unsigned char *) buf)[i+7]
+ : 0xff,
+ (i + 8 < bufsiz) ? ((const unsigned char *) buf)[i+8]
+ : 0xff,
+ (i + 9 < bufsiz) ? ((const unsigned char *) buf)[i+9]
+ : 0xff,
+ (i + 10 < bufsiz) ? ((const unsigned char *) buf)[i+10]
+ : 0xff,
+ (i + 11 < bufsiz) ? ((const unsigned char *) buf)[i+11]
+ : 0xff,
+ (i + 12 < bufsiz) ? ((const unsigned char *) buf)[i+12]
+ : 0xff,
+ (i + 13 < bufsiz) ? ((const unsigned char *) buf)[i+13]
+ : 0xff,
+ (i + 14 < bufsiz) ? ((const unsigned char *) buf)[i+14]
+ : 0xff,
+ (i + 15 < bufsiz) ? ((const unsigned char *) buf)[i+15]
+ : 0xff);
}
}
@@ -119,11 +136,10 @@ static size_t peek_ipc_tx_bufsiz(struct baseband_ipc *ipc,
pr_debug("peek_ipc_tx_bufsiz - "
"ipc_buf %p ipc_buf->offset %x ipc_buf->count %x\n",
ipc_buf, ipc_buf->offset, ipc_buf->count);
- if (ipc_buf->count > bufsiz - tx_bufsiz) {
+ if (ipc_buf->count > bufsiz - tx_bufsiz)
break;
- } else {
+ else
tx_bufsiz += ipc_buf->count;
- }
}
/* release tx buffer semaphores */
@@ -145,9 +161,8 @@ static size_t get_ipc_tx_buf(struct baseband_ipc *ipc,
pr_err("!ipc || !buf\n");
return 0;
}
- if (!bufsiz) {
+ if (!bufsiz)
return 0;
- }
/* acquire tx buffer semaphores */
if (down_interruptible(&ipc->buf_sem)) {
@@ -213,9 +228,8 @@ static size_t put_ipc_rx_buf(struct baseband_ipc *ipc,
pr_err("!ipc || !buf\n");
return 0;
}
- if (!bufsiz) {
+ if (!bufsiz)
return 0;
- }
/* acquire rx buffer semaphores */
retry:
@@ -474,14 +488,10 @@ static void baseband_ipc_close(struct baseband_ipc *ipc)
memset(&ipc->rx.wait, 0, sizeof(ipc->rx.wait));
/* destroy data buffers */
- if (ipc->ipc_tx) {
- kfree(ipc->ipc_tx);
- ipc->ipc_tx = (unsigned char *) 0;
- }
- if (ipc->ipc_rx) {
- kfree(ipc->ipc_rx);
- ipc->ipc_rx = (unsigned char *) 0;
- }
+ 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)
{
kfree(ipc_buf);
@@ -514,16 +524,14 @@ static struct baseband_ipc *baseband_ipc_open(work_func_t work_func,
{
struct baseband_ipc *ipc;
struct baseband_ipc_buf *ipc_buf;
- int err;
int i;
pr_debug("baseband_ipc_open {\n");
/* allocate baseband ipc structure */
- ipc = (struct baseband_ipc *) kzalloc(sizeof(struct baseband_ipc),
- GFP_KERNEL);
+ ipc = kzalloc(sizeof(struct baseband_ipc), GFP_KERNEL);
if (!ipc)
- return ((struct baseband_ipc *) 0);
+ return (struct baseband_ipc *) 0;
/* create semaphores */
sema_init(&ipc->buf_sem, 1);
@@ -537,7 +545,8 @@ static struct baseband_ipc *baseband_ipc_open(work_func_t work_func,
ipc_buf = (struct baseband_ipc_buf *)
kzalloc(sizeof(struct baseband_ipc_buf), GFP_KERNEL);
if (!ipc_buf) {
- pr_err("cannot allocate baseband ipc rx buffer #%d\n", i);
+ pr_err("cannot allocate baseband ipc rx buffer #%d\n",
+ i);
goto error_exit;
}
pr_debug("baseband_ipc_open - "
@@ -549,7 +558,8 @@ static struct baseband_ipc *baseband_ipc_open(work_func_t work_func,
ipc_buf = (struct baseband_ipc_buf *)
kzalloc(sizeof(struct baseband_ipc_buf), GFP_KERNEL);
if (!ipc_buf) {
- pr_err("cannot allocate baseband ipc tx buffer #%d\n", i);
+ pr_err("cannot allocate baseband ipc tx buffer #%d\n",
+ i);
goto error_exit;
}
pr_debug("baseband_ipc_open - "
@@ -573,77 +583,121 @@ static struct baseband_ipc *baseband_ipc_open(work_func_t work_func,
pr_err("cannot create workqueue\n");
goto error_exit;
}
- if (work_func) {
+ if (work_func)
INIT_WORK(&ipc->work, work_func);
- }
- if (rx_work_func) {
+ if (rx_work_func)
INIT_WORK(&ipc->rx_work, rx_work_func);
- }
- if (tx_work_func) {
+ if (tx_work_func)
INIT_WORK(&ipc->tx_work, tx_work_func);
- }
pr_debug("baseband_ipc_open }\n");
return ipc;
error_exit:
baseband_ipc_close(ipc);
- return ((struct baseband_ipc *) 0);
+ return (struct baseband_ipc *) 0;
}
-/* usb functions */
+/* usb rx */
-static unsigned int g_usb_interface_index;
-static struct usb_interface *g_usb_interface;
+static void baseband_usb_chr_rx_urb_comp(struct urb *urb)
+{
+ struct baseband_usb *usb = (struct baseband_usb *) urb->context;
-static int baseband_usb_driver_probe(struct usb_interface *intf,
- const struct usb_device_id *id)
+ pr_debug("baseband_usb_chr_rx_urb_comp { urb %p\n", urb);
+
+ /* queue rx urb completion work */
+ queue_work(usb->ipc->workqueue, &usb->ipc->rx_work);
+
+ pr_debug("baseband_usb_chr_rx_urb_comp }\n");
+}
+
+static int baseband_usb_chr_rx_urb_submit(struct baseband_usb *usb)
{
- pr_debug("%s(%d) { intf %p id %p\n", __func__, __LINE__, intf, id);
+ struct urb *urb;
+ void *buf;
+ int err;
- pr_debug("intf->cur_altsetting->desc.bInterfaceNumber %02x\n",
- intf->cur_altsetting->desc.bInterfaceNumber);
- pr_debug("intf->cur_altsetting->desc.bAlternateSetting %02x\n",
- intf->cur_altsetting->desc.bAlternateSetting);
- pr_debug("intf->cur_altsetting->desc.bNumEndpoints %02x\n",
- intf->cur_altsetting->desc.bNumEndpoints);
- pr_debug("intf->cur_altsetting->desc.bInterfaceClass %02x\n",
- intf->cur_altsetting->desc.bInterfaceClass);
- pr_debug("intf->cur_altsetting->desc.bInterfaceSubClass %02x\n",
- intf->cur_altsetting->desc.bInterfaceSubClass);
- pr_debug("intf->cur_altsetting->desc.bInterfaceProtocol %02x\n",
- intf->cur_altsetting->desc.bInterfaceProtocol);
- pr_debug("intf->cur_altsetting->desc.iInterface %02x\n",
- intf->cur_altsetting->desc.iInterface);
+ pr_debug("baseband_usb_chr_rx_urb_submit { usb %p\n", usb);
- if (g_usb_interface_index !=
- intf->cur_altsetting->desc.bInterfaceNumber) {
- pr_debug("%s(%d) } -ENODEV\n", __func__, __LINE__);
- return -ENODEV;
- } else {
- g_usb_interface = intf;
+ /* check input */
+ if (usb->usb.rx_urb) {
+ pr_err("previous urb still active\n");
+ return -1;
}
- pr_debug("%s(%d) }\n", __func__, __LINE__);
- return 0;
+ /* allocate rx urb */
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!urb) {
+ pr_err("usb_alloc_urb() failed\n");
+ return -ENOMEM;
+ }
+ buf = kzalloc(USB_CHR_RX_BUFSIZ, GFP_ATOMIC);
+ if (!buf) {
+ pr_err("usb buffer kzalloc() failed\n");
+ usb_free_urb(urb);
+ return -ENOMEM;
+ }
+ usb_fill_bulk_urb(urb, usb->usb.device, usb->usb.pipe.bulk.in,
+ buf, USB_CHR_RX_BUFSIZ,
+ baseband_usb_chr_rx_urb_comp,
+ usb);
+ urb->transfer_flags = 0;
+
+ /* submit rx urb */
+ usb->usb.rx_urb = urb;
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err < 0) {
+ pr_err("usb_submit_urb() failed - err %d\n", err);
+ usb->usb.rx_urb = (struct urb *) 0;
+ kfree(urb->transfer_buffer);
+ usb_free_urb(urb);
+ return err;
+ }
+
+ pr_debug("baseband_usb_chr_rx_urb_submit }\n");
+ return err;
}
-static void baseband_usb_driver_disconnect(struct usb_interface *intf)
+static void baseband_usb_chr_rx_urb_comp_work(struct work_struct *work)
{
- pr_debug("%s(%d) { intf %p\n", __func__, __LINE__, intf);
- pr_debug("%s(%d) }\n", __func__, __LINE__);
-}
+ struct baseband_usb *usb = baseband_usb_chr;
+ struct urb *urb = usb->usb.rx_urb;
+ size_t len;
-static char baseband_usb_driver_name[32];
+ pr_debug("baseband_usb_chr_rx_urb_comp_work { work %p\n", work);
-static struct usb_device_id baseband_usb_driver_id_table[2];
+ /* put rx urb data in rx buffer */
+ if (urb->actual_length) {
+ pr_debug("baseband_usb_chr_rx_urb_comp_work - "
+ "urb->actual_length %d\n", urb->actual_length);
+ len = put_ipc_rx_buf(usb->ipc,
+ urb->transfer_buffer, urb->actual_length);
+ baseband_ipc_dump("baseband_usb_chr_rx_urb_comp_work"
+ " - rx buf ", 0,
+ urb->transfer_buffer, len > 16 ? 16 : len);
+ if (len != urb->actual_length) {
+ pr_err("baseband_usb_chr_rx_urb_comp_work - "
+ "put_ipx_rx_buf() only put %d/%d bytes\n",
+ len, urb->actual_length);
+ }
+ /* increment count of available rx bytes */
+ atomic_add(len, &g_rx_count);
+ }
-static struct usb_driver baseband_usb_driver = {
- .name = baseband_usb_driver_name,
- .probe = baseband_usb_driver_probe,
- .disconnect = baseband_usb_driver_disconnect,
- .id_table = baseband_usb_driver_id_table,
-};
+ /* free rx urb */
+ kfree(urb->transfer_buffer);
+ urb->transfer_buffer = (void *) 0;
+ usb_free_urb(urb);
+ usb->usb.rx_urb = (struct urb *) 0;
+
+ /* submit next rx urb */
+ baseband_usb_chr_rx_urb_submit(usb);
+
+ pr_debug("baseband_usb_chr_rx_urb_comp_work }\n");
+}
+
+/* usb functions */
static void find_usb_pipe(struct baseband_usb *usb)
{
@@ -684,6 +738,88 @@ static void find_usb_pipe(struct baseband_usb *usb)
}
}
+static int baseband_usb_driver_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ int err;
+
+ pr_debug("%s(%d) { intf %p id %p\n", __func__, __LINE__, intf, id);
+
+ pr_debug("intf->cur_altsetting->desc.bInterfaceNumber %02x\n",
+ intf->cur_altsetting->desc.bInterfaceNumber);
+ pr_debug("intf->cur_altsetting->desc.bAlternateSetting %02x\n",
+ intf->cur_altsetting->desc.bAlternateSetting);
+ pr_debug("intf->cur_altsetting->desc.bNumEndpoints %02x\n",
+ intf->cur_altsetting->desc.bNumEndpoints);
+ pr_debug("intf->cur_altsetting->desc.bInterfaceClass %02x\n",
+ intf->cur_altsetting->desc.bInterfaceClass);
+ pr_debug("intf->cur_altsetting->desc.bInterfaceSubClass %02x\n",
+ intf->cur_altsetting->desc.bInterfaceSubClass);
+ pr_debug("intf->cur_altsetting->desc.bInterfaceProtocol %02x\n",
+ intf->cur_altsetting->desc.bInterfaceProtocol);
+ pr_debug("intf->cur_altsetting->desc.iInterface %02x\n",
+ intf->cur_altsetting->desc.iInterface);
+
+ /* usb interface mismatch */
+ if (baseband_usb_chr_intf !=
+ intf->cur_altsetting->desc.bInterfaceNumber) {
+ pr_debug("%s(%d) } -ENODEV\n", __func__, __LINE__);
+ return -ENODEV;
+ }
+
+ /* usb interface match */
+ baseband_usb_chr->usb.device = interface_to_usbdev(intf);
+ baseband_usb_chr->usb.interface = intf;
+ find_usb_pipe(baseband_usb_chr);
+ baseband_usb_chr->usb.rx_urb = (struct urb *) 0;
+ baseband_usb_chr->usb.tx_urb = (struct urb *) 0;
+ pr_debug("baseband_usb_chr->usb.driver->name %s\n",
+ baseband_usb_chr->usb.driver->name);
+ pr_debug("baseband_usb_chr->usb.device %p\n",
+ baseband_usb_chr->usb.device);
+ pr_debug("baseband_usb_chr->usb.interface %p\n",
+ baseband_usb_chr->usb.interface);
+ pr_debug("baseband_usb_chr->usb.pipe.isoch.in %x\n",
+ baseband_usb_chr->usb.pipe.isoch.in);
+ pr_debug("baseband_usb_chr->usb.pipe.isoch.out %x\n",
+ baseband_usb_chr->usb.pipe.isoch.out);
+ pr_debug("baseband_usb_chr->usb.pipe.bulk.in %x\n",
+ baseband_usb_chr->usb.pipe.bulk.in);
+ pr_debug("baseband_usb_chr->usb.pipe.bulk.out %x\n",
+ baseband_usb_chr->usb.pipe.bulk.out);
+ pr_debug("baseband_usb_chr->usb.pipe.interrupt.in %x\n",
+ baseband_usb_chr->usb.pipe.interrupt.in);
+ pr_debug("baseband_usb_chr->usb.pipe.interrupt.out %x\n",
+ baseband_usb_chr->usb.pipe.interrupt.out);
+
+ /* start usb rx */
+ err = baseband_usb_chr_rx_urb_submit(baseband_usb_chr);
+ if (err < 0) {
+ pr_err("submit rx failed - err %d\n", err);
+ return -ENODEV;
+ }
+
+ pr_debug("%s(%d) }\n", __func__, __LINE__);
+ return 0;
+}
+
+static void baseband_usb_driver_disconnect(struct usb_interface *intf)
+{
+ pr_debug("%s(%d) { intf %p\n", __func__, __LINE__, intf);
+ pr_debug("%s(%d) }\n", __func__, __LINE__);
+}
+
+static char baseband_usb_driver_name[32];
+
+static struct usb_device_id baseband_usb_driver_id_table[2];
+
+static struct usb_driver baseband_usb_driver = {
+ .name = baseband_usb_driver_name,
+ .probe = baseband_usb_driver_probe,
+ .disconnect = baseband_usb_driver_disconnect,
+ .id_table = baseband_usb_driver_id_table,
+};
+
static void baseband_usb_chr_work(struct work_struct *work)
{
struct baseband_usb *usb = baseband_usb_chr;
@@ -702,10 +838,17 @@ static void baseband_usb_chr_work(struct work_struct *work)
"usb not open\n");
return;
}
+ if (!usb->usb.device) {
+ pr_err("baseband_usb_chr_work - "
+ "usb device not probed yet\n");
+ mdelay(10);
+ queue_work(usb->ipc->workqueue, &usb->ipc->work);
+ return;
+ }
/* allocate buffers on first transaction (will be freed on close) */
if (!usb->ipc->ipc_rx) {
- usb->ipc->ipc_rx = (unsigned char *) kzalloc(USB_CHR_RX_BUFSIZ, GFP_KERNEL);
+ usb->ipc->ipc_rx = kzalloc(USB_CHR_RX_BUFSIZ, GFP_KERNEL);
if (!usb->ipc->ipc_rx) {
pr_err("baseband_usb_chr_work - "
"cannot allocate usb->ipc->ipc_rx\n");
@@ -713,7 +856,7 @@ static void baseband_usb_chr_work(struct work_struct *work)
}
}
if (!usb->ipc->ipc_tx) {
- usb->ipc->ipc_tx = (unsigned char *) kzalloc(USB_CHR_TX_BUFSIZ, GFP_KERNEL);
+ usb->ipc->ipc_tx = kzalloc(USB_CHR_TX_BUFSIZ, GFP_KERNEL);
if (!usb->ipc->ipc_tx) {
pr_err("baseband_usb_chr_work - "
"cannot allocate usb->ipc->ipc_tx\n");
@@ -724,9 +867,8 @@ static void baseband_usb_chr_work(struct work_struct *work)
/* usb transaction loop */
rx.buf = usb->ipc->ipc_rx;
tx.buf = usb->ipc->ipc_tx;
- while ((tx.bufsiz_byte = peek_ipc_tx_bufsiz(usb->ipc, USB_CHR_TX_BUFSIZ))
- != 0)
- {
+ while ((tx.bufsiz_byte = peek_ipc_tx_bufsiz(usb->ipc,
+ USB_CHR_TX_BUFSIZ)) != 0) {
get_ipc_tx_buf(usb->ipc, tx.buf, tx.bufsiz_byte);
err = usb_bulk_msg(usb->usb.device, usb->usb.pipe.bulk.out,
tx.buf, tx.bufsiz_byte, &ipc_tx_byte, USB_CHR_TIMEOUT);
@@ -736,7 +878,8 @@ static void baseband_usb_chr_work(struct work_struct *work)
continue;
}
if (tx.bufsiz_byte != ipc_tx_byte) {
- pr_err("tx.bufsiz_byte %d != ipc_tx_byte %d\n", tx.bufsiz_byte, ipc_tx_byte);
+ pr_err("tx.bufsiz_byte %d != ipc_tx_byte %d\n",
+ tx.bufsiz_byte, ipc_tx_byte);
continue;
}
}
@@ -746,8 +889,6 @@ static void baseband_usb_chr_work(struct work_struct *work)
/* usb character file operations */
-static atomic_t g_rx_count = ATOMIC_INIT(0);
-
static int baseband_usb_chr_open(struct inode *inode, struct file *file)
{
pr_debug("baseband_usb_chr_open\n");
@@ -760,29 +901,35 @@ static int baseband_usb_chr_release(struct inode *inode, struct file *file)
return 0;
}
-static ssize_t baseband_usb_chr_read(struct file *file, char *buf, size_t count, loff_t *pos)
+static ssize_t baseband_usb_chr_read(struct file *file, char *buf,
+ size_t count, loff_t *pos)
{
ssize_t ret;
pr_debug("baseband_usb_chr_read\n");
- ret = baseband_ipc_file_read(baseband_usb_chr->ipc, file, buf, count, pos);
+ ret = baseband_ipc_file_read(baseband_usb_chr->ipc,
+ file, buf, count, pos);
if (ret > 0) {
/* decrement count of available rx bytes */
int val = atomic_read(&g_rx_count);
- pr_debug("baseband_usb_chr_read - read %d unread %d\n", ret, val - ret);
+ pr_debug("baseband_usb_chr_read - read %d unread %d\n",
+ ret, val - ret);
atomic_sub(ret, &g_rx_count);
}
return ret;
}
-static ssize_t baseband_usb_chr_write(struct file *file, const char *buf, size_t count, loff_t *pos)
+static ssize_t baseband_usb_chr_write(struct file *file, const char *buf,
+ size_t count, loff_t *pos)
{
pr_debug("baseband_usb_chr_write\n");
- return baseband_ipc_file_write(baseband_usb_chr->ipc, file, buf, count, pos);
+ return baseband_ipc_file_write(baseband_usb_chr->ipc,
+ file, buf, count, pos);
}
-static long baseband_usb_chr_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+static long baseband_usb_chr_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
{
pr_debug("baseband_usb_chr_ioctl\n");
switch (cmd) {
@@ -807,12 +954,12 @@ static long baseband_usb_chr_ioctl(struct file *file, unsigned int cmd, unsigned
return -ENODEV;
}
-static struct file_operations baseband_usb_chr_fops = {
- open: baseband_usb_chr_open,
- release: baseband_usb_chr_release,
- read: baseband_usb_chr_read,
- write: baseband_usb_chr_write,
- unlocked_ioctl: baseband_usb_chr_ioctl,
+static const struct file_operations baseband_usb_chr_fops = {
+ .open = baseband_usb_chr_open,
+ .release = baseband_usb_chr_release,
+ .read = baseband_usb_chr_read,
+ .write = baseband_usb_chr_write,
+ .unlocked_ioctl = baseband_usb_chr_ioctl,
};
/* usb device driver functions */
@@ -858,10 +1005,10 @@ static struct baseband_usb *baseband_usb_open(unsigned int vid,
pr_debug("baseband_usb_open {\n");
/* allocate baseband usb structure */
- usb = (struct baseband_usb *) kzalloc(sizeof(struct baseband_usb),
- GFP_KERNEL);
+ usb = kzalloc(sizeof(struct baseband_usb), GFP_KERNEL);
if (!usb)
- return ((struct baseband_usb *) 0);
+ return (struct baseband_usb *) 0;
+ baseband_usb_chr = usb;
/* open baseband ipc */
usb->ipc = baseband_ipc_open(work_func,
@@ -876,149 +1023,24 @@ static struct baseband_usb *baseband_usb_open(unsigned int vid,
sprintf(baseband_usb_driver_name,
"baseband_usb_%x_%x_%x",
vid, pid, intf);
- baseband_usb_driver_id_table[0].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
+ baseband_usb_driver_id_table[0].match_flags
+ = USB_DEVICE_ID_MATCH_DEVICE;
baseband_usb_driver_id_table[0].idVendor = vid;
baseband_usb_driver_id_table[0].idProduct = pid;
- g_usb_interface_index = intf;
- g_usb_interface = (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;
}
- usb->usb.driver = &baseband_usb_driver;
- if (!g_usb_interface) {
- pr_err("cannot open usb driver - !g_usb_interface\n");
- goto error_exit;
- }
- usb->usb.device = interface_to_usbdev(g_usb_interface);
- usb->usb.interface = g_usb_interface;
- find_usb_pipe(usb);
- usb->usb.rx_urb = (struct urb *) 0;
- usb->usb.tx_urb = (struct urb *) 0;
- g_usb_interface_index = ~0U;
- g_usb_interface = (struct usb_interface *) 0;
- pr_debug("usb->usb.driver->name %s\n", usb->usb.driver->name);
- pr_debug("usb->usb.device %p\n", usb->usb.device);
- pr_debug("usb->usb.interface %p\n", usb->usb.interface);
- pr_debug("usb->usb.pipe.isoch.in %x\n", usb->usb.pipe.isoch.in);
- pr_debug("usb->usb.pipe.isoch.out %x\n", usb->usb.pipe.isoch.out);
- pr_debug("usb->usb.pipe.bulk.in %x\n", usb->usb.pipe.bulk.in);
- pr_debug("usb->usb.pipe.bulk.out %x\n", usb->usb.pipe.bulk.out);
- pr_debug("usb->usb.pipe.interrupt.in %x\n", usb->usb.pipe.interrupt.in);
- pr_debug("usb->usb.pipe.interrupt.out %x\n", usb->usb.pipe.interrupt.out);
pr_debug("baseband_usb_open }\n");
return usb;
error_exit:
baseband_usb_close(usb);
- return ((struct baseband_usb *) 0);
-}
-
-/* usb rx */
-
-static int baseband_usb_chr_rx_urb_submit(struct baseband_usb *usb);
-static void baseband_usb_chr_rx_urb_comp(struct urb *urb);
-static void baseband_usb_chr_rx_urb_comp_work(struct work_struct *work);
-
-static int baseband_usb_chr_rx_urb_submit(struct baseband_usb *usb)
-{
- struct urb *urb;
- void *buf;
- int err;
-
- pr_debug("baseband_usb_chr_rx_urb_submit { usb %p\n", usb);
-
- /* check input */
- if (usb->usb.rx_urb) {
- pr_err("previous urb still active\n");
- return -1;
- }
-
- /* allocate rx urb */
- urb = usb_alloc_urb(0, GFP_ATOMIC);
- if (!urb) {
- pr_err("usb_alloc_urb() failed\n");
- return -ENOMEM;
- }
- buf = kzalloc(USB_CHR_RX_BUFSIZ, GFP_ATOMIC);
- if (!buf) {
- pr_err("usb buffer kzalloc() failed\n");
- usb_free_urb(urb);
- return -ENOMEM;
- }
- usb_fill_bulk_urb(urb, usb->usb.device, usb->usb.pipe.bulk.in,
- buf, USB_CHR_RX_BUFSIZ,
- baseband_usb_chr_rx_urb_comp,
- usb);
- urb->transfer_flags = 0;
-
- /* submit rx urb */
- usb->usb.rx_urb = urb;
- err = usb_submit_urb(urb, GFP_ATOMIC);
- if (err < 0) {
- pr_err("usb_submit_urb() failed - err %d\n", err);
- usb->usb.rx_urb = (struct urb *) 0;
- kfree(urb->transfer_buffer);
- usb_free_urb(urb);
- return err;
- }
-
- pr_debug("baseband_usb_chr_rx_urb_submit }\n");
- return err;
-}
-
-static void baseband_usb_chr_rx_urb_comp(struct urb *urb)
-{
- struct baseband_usb *usb = (struct baseband_usb *) urb->context;
-
- pr_debug("baseband_usb_chr_rx_urb_comp { urb %p\n", urb);
-
- /* queue rx urb completion work */
- queue_work(usb->ipc->workqueue, &usb->ipc->rx_work);
-
- pr_debug("baseband_usb_chr_rx_urb_comp }\n");
-}
-
-static void baseband_usb_chr_rx_urb_comp_work(struct work_struct *work)
-{
- struct baseband_usb *usb = baseband_usb_chr;
- struct urb *urb = usb->usb.rx_urb;
- size_t len;
-
- pr_debug("baseband_usb_chr_rx_urb_comp_work { work %p\n", work);
-
- /* put rx urb data in rx buffer */
- if (urb->actual_length) {
- pr_debug("baseband_usb_chr_rx_urb_comp_work - "
- "urb->actual_length %d\n", urb->actual_length);
- len = put_ipc_rx_buf(usb->ipc,
- urb->transfer_buffer, urb->actual_length);
- baseband_ipc_dump("baseband_usb_chr_rx_urb_comp_work"
- " - rx buf ", 0,
- urb->transfer_buffer, len > 16 ? 16 : len);
- if (len != urb->actual_length) {
- pr_err("baseband_usb_chr_rx_urb_comp_work - "
- "put_ipx_rx_buf() only put %d/%d bytes\n",
- len, urb->actual_length);
- }
- /* increment count of available rx bytes */
- atomic_add(len, &g_rx_count);
- }
-
- /* free rx urb */
- if (urb->transfer_buffer) {
- kfree(urb->transfer_buffer);
- urb->transfer_buffer = (void *) 0;
- }
- usb_free_urb(urb);
- usb->usb.rx_urb = (struct urb *) 0;
-
- /* submit next rx urb */
- baseband_usb_chr_rx_urb_submit(usb);
-
- pr_debug("baseband_usb_chr_rx_urb_comp_work }\n");
+ baseband_usb_chr = (struct baseband_usb *) 0;
+ return (struct baseband_usb *) 0;
}
/* module init / exit functions */
@@ -1054,17 +1076,8 @@ static int baseband_usb_chr_init(void)
pr_debug("registered baseband usb character device - major %d\n",
BASEBAND_USB_CHR_DEV_MAJOR);
- /* start usb rx */
- err = baseband_usb_chr_rx_urb_submit(baseband_usb_chr);
- if (err < 0) {
- pr_err("submit rx failed - err %d\n", err);
- goto err3;
- }
-
pr_debug("baseband_usb_chr_init }\n");
return 0;
-err3: unregister_chrdev(BASEBAND_USB_CHR_DEV_MAJOR,
- BASEBAND_USB_CHR_DEV_NAME);
err2: baseband_usb_close(baseband_usb_chr);
baseband_usb_chr = (struct baseband_usb *) 0;
err1: return err;