usb: gadget: Support multiple HSIC transport instances for dun and rmnet
Instead of using integer-based IDs to couple bridge instances to the
corresponding gadget ports, assign transport name strings (passed by
userspace) describing the port instance, and match strings to identify
the correct instance when bridge_open() called. This allows multiple
dun and rmnet ports to be assigned without having dependecy of
one-to-one mapping between gadget port instance and bridge driver
instance.
Change-Id: Ia87bd6e9c72d5e98f47dbc2a1cf0b71b48daa1a8
Signed-off-by: Hemant Kumar <hemantk@codeaurora.org>
Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org>
diff --git a/arch/arm/mach-msm/include/mach/usb_bridge.h b/arch/arm/mach-msm/include/mach/usb_bridge.h
index adc9321..1c125b7 100644
--- a/arch/arm/mach-msm/include/mach/usb_bridge.h
+++ b/arch/arm/mach-msm/include/mach/usb_bridge.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -17,10 +17,8 @@
#include <linux/netdevice.h>
#include <linux/usb.h>
-/* bridge device 0: DUN
- * bridge device 1 : Tethered RMNET
- */
#define MAX_BRIDGE_DEVICES 2
+#define BRIDGE_NAME_MAX_LEN 20
struct bridge_ops {
int (*send_pkt)(void *, void *, size_t actual);
@@ -37,11 +35,12 @@
/* context of the gadget port using bridge driver */
void *ctx;
- /* bridge device array index mapped to the gadget port array index.
- * data bridge[ch_id] <-- bridge --> gadget port[ch_id]
- */
+ /*to maps bridge driver instance*/
unsigned int ch_id;
+ /*to match against bridge xport name to get bridge driver instance*/
+ char *name;
+
/* flow control bits */
unsigned long flags;
@@ -103,7 +102,8 @@
/* defined in control bridge */
int ctrl_bridge_init(void);
void ctrl_bridge_exit(void);
-int ctrl_bridge_probe(struct usb_interface *, struct usb_host_endpoint *, int);
+int ctrl_bridge_probe(struct usb_interface *, struct usb_host_endpoint *,
+ char *, int);
void ctrl_bridge_disconnect(unsigned int);
int ctrl_bridge_resume(unsigned int);
int ctrl_bridge_suspend(unsigned int);
diff --git a/arch/arm/mach-msm/include/mach/usb_gadget_xport.h b/arch/arm/mach-msm/include/mach/usb_gadget_xport.h
index a183f0e..634a4dc 100644
--- a/arch/arm/mach-msm/include/mach/usb_gadget_xport.h
+++ b/arch/arm/mach-msm/include/mach/usb_gadget_xport.h
@@ -89,8 +89,8 @@
USB_GADGET_RMNET,
};
-#define NUM_RMNET_HSIC_PORTS 1
-#define NUM_DUN_HSIC_PORTS 1
+#define NUM_RMNET_HSIC_PORTS 2
+#define NUM_DUN_HSIC_PORTS 2
#define NUM_PORTS (NUM_RMNET_HSIC_PORTS \
+ NUM_DUN_HSIC_PORTS)
@@ -102,9 +102,11 @@
int ghsic_ctrl_connect(void *, int);
void ghsic_ctrl_disconnect(void *, int);
int ghsic_ctrl_setup(unsigned int, enum gadget_type);
+void ghsic_ctrl_set_port_name(const char *, const char *);
int ghsic_data_connect(void *, int);
void ghsic_data_disconnect(void *, int);
int ghsic_data_setup(unsigned int, enum gadget_type);
+void ghsic_data_set_port_name(const char *, const char *);
int ghsuart_ctrl_connect(void *, int);
void ghsuart_ctrl_disconnect(void *, int);
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index 36a43c3..38b1967 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -671,6 +671,9 @@
#define MAX_XPORT_STR_LEN 50
static char rmnet_transports[MAX_XPORT_STR_LEN];
+/*rmnet transport name string - "rmnet_hsic[,rmnet_hsusb]" */
+static char rmnet_xport_names[MAX_XPORT_STR_LEN];
+
static void rmnet_function_cleanup(struct android_usb_function *f)
{
frmnet_cleanup();
@@ -683,18 +686,28 @@
int err = 0;
char *ctrl_name;
char *data_name;
+ char *tname = NULL;
char buf[MAX_XPORT_STR_LEN], *b;
+ char xport_name_buf[MAX_XPORT_STR_LEN], *tb;
static int rmnet_initialized, ports;
if (!rmnet_initialized) {
rmnet_initialized = 1;
strlcpy(buf, rmnet_transports, sizeof(buf));
b = strim(buf);
+
+ strlcpy(xport_name_buf, rmnet_xport_names,
+ sizeof(xport_name_buf));
+ tb = strim(xport_name_buf);
+
while (b) {
ctrl_name = strsep(&b, ",");
data_name = strsep(&b, ",");
if (ctrl_name && data_name) {
- err = frmnet_init_port(ctrl_name, data_name);
+ if (tb)
+ tname = strsep(&tb, ",");
+ err = frmnet_init_port(ctrl_name, data_name,
+ tname);
if (err) {
pr_err("rmnet: Cannot open ctrl port:"
"'%s' data port:'%s'\n",
@@ -738,12 +751,34 @@
return size;
}
+static ssize_t rmnet_xport_names_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n", rmnet_xport_names);
+}
+
+static ssize_t rmnet_xport_names_store(
+ struct device *device, struct device_attribute *attr,
+ const char *buff, size_t size)
+{
+ strlcpy(rmnet_xport_names, buff, sizeof(rmnet_xport_names));
+
+ return size;
+}
+
static struct device_attribute dev_attr_rmnet_transports =
__ATTR(transports, S_IRUGO | S_IWUSR,
rmnet_transports_show,
rmnet_transports_store);
+
+static struct device_attribute dev_attr_rmnet_xport_names =
+ __ATTR(transport_names, S_IRUGO | S_IWUSR,
+ rmnet_xport_names_show,
+ rmnet_xport_names_store);
+
static struct device_attribute *rmnet_function_attributes[] = {
&dev_attr_rmnet_transports,
+ &dev_attr_rmnet_xport_names,
NULL };
static struct android_usb_function rmnet_function = {
@@ -1199,9 +1234,33 @@
return size;
}
+/*enabled FSERIAL transport names - "serial_hsic[,serial_hsusb]"*/
+static char serial_xport_names[32];
+static ssize_t serial_xport_names_store(
+ struct device *device, struct device_attribute *attr,
+ const char *buff, size_t size)
+{
+ strlcpy(serial_xport_names, buff, sizeof(serial_xport_names));
+
+ return size;
+}
+
+static ssize_t serial_xport_names_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n", serial_xport_names);
+}
+
static DEVICE_ATTR(transports, S_IWUSR, NULL, serial_transports_store);
-static struct device_attribute *serial_function_attributes[] =
- { &dev_attr_transports, NULL };
+static struct device_attribute dev_attr_serial_xport_names =
+ __ATTR(transport_names, S_IRUGO | S_IWUSR,
+ serial_xport_names_show,
+ serial_xport_names_store);
+
+static struct device_attribute *serial_function_attributes[] = {
+ &dev_attr_transports,
+ &dev_attr_serial_xport_names,
+ NULL };
static void serial_function_cleanup(struct android_usb_function *f)
{
@@ -1211,8 +1270,8 @@
static int serial_function_bind_config(struct android_usb_function *f,
struct usb_configuration *c)
{
- char *name;
- char buf[32], *b;
+ char *name, *xport_name = NULL;
+ char buf[32], *b, xport_name_buf[32], *tb;
int err = -1, i;
static int serial_initialized = 0, ports = 0;
@@ -1223,11 +1282,16 @@
strlcpy(buf, serial_transports, sizeof(buf));
b = strim(buf);
+ strlcpy(xport_name_buf, serial_xport_names, sizeof(xport_name_buf));
+ tb = strim(xport_name_buf);
+
while (b) {
name = strsep(&b, ",");
if (name) {
- err = gserial_init_port(ports, name);
+ if (tb)
+ xport_name = strsep(&tb, ",");
+ err = gserial_init_port(ports, name, xport_name);
if (err) {
pr_err("serial: Cannot open port '%s'", name);
goto out;
diff --git a/drivers/usb/gadget/f_rmnet.c b/drivers/usb/gadget/f_rmnet.c
index f095efb..26b739d 100644
--- a/drivers/usb/gadget/f_rmnet.c
+++ b/drivers/usb/gadget/f_rmnet.c
@@ -1230,7 +1230,8 @@
no_data_hsuart_ports = 0;
}
-static int frmnet_init_port(const char *ctrl_name, const char *data_name)
+static int frmnet_init_port(const char *ctrl_name, const char *data_name,
+ const char *port_name)
{
struct f_rmnet *dev;
struct rmnet_ports *rmnet_port;
@@ -1272,6 +1273,7 @@
no_ctrl_qti_ports++;
break;
case USB_GADGET_XPORT_HSIC:
+ ghsic_ctrl_set_port_name(port_name, ctrl_name);
rmnet_port->ctrl_xport_num = no_ctrl_hsic_ports;
no_ctrl_hsic_ports++;
break;
@@ -1299,6 +1301,7 @@
no_data_bam2bam_ports++;
break;
case USB_GADGET_XPORT_HSIC:
+ ghsic_data_set_port_name(port_name, data_name);
rmnet_port->data_xport_num = no_data_hsic_ports;
no_data_hsic_ports++;
break;
diff --git a/drivers/usb/gadget/f_serial.c b/drivers/usb/gadget/f_serial.c
index 74dba07..57cbc03 100644
--- a/drivers/usb/gadget/f_serial.c
+++ b/drivers/usb/gadget/f_serial.c
@@ -985,9 +985,11 @@
/**
* gserial_init_port - bind a gserial_port to its transport
*/
-static int gserial_init_port(int port_num, const char *name)
+static int gserial_init_port(int port_num, const char *name,
+ const char *port_name)
{
enum transport_type transport;
+ int ret = 0;
if (port_num >= GSERIAL_NO_PORTS)
return -ENODEV;
@@ -1013,6 +1015,9 @@
no_smd_ports++;
break;
case USB_GADGET_XPORT_HSIC:
+ ghsic_ctrl_set_port_name(port_name, name);
+ ghsic_data_set_port_name(port_name, name);
+
/*client port number will be updated in gport_setup*/
no_hsic_sports++;
break;
@@ -1028,5 +1033,5 @@
nr_ports++;
- return 0;
+ return ret;
}
diff --git a/drivers/usb/gadget/u_ctrl_hsic.c b/drivers/usb/gadget/u_ctrl_hsic.c
index 0f93ad4..6143d1b 100644
--- a/drivers/usb/gadget/u_ctrl_hsic.c
+++ b/drivers/usb/gadget/u_ctrl_hsic.c
@@ -36,12 +36,6 @@
static unsigned int no_ctrl_ports;
-static const char *ctrl_bridge_names[] = {
- "dun_ctrl_hsic0",
- "rmnet_ctrl_hsic0"
-};
-
-#define CTRL_BRIDGE_NAME_MAX_LEN 20
#define READ_BUF_LEN 1024
#define CH_OPENED 0
@@ -83,6 +77,7 @@
static struct {
struct gctrl_port *port;
struct platform_driver pdrv;
+ char port_name[BRIDGE_NAME_MAX_LEN];
} gctrl_ports[NUM_PORTS];
static int ghsic_ctrl_receive(void *dev, void *buf, size_t actual)
@@ -336,19 +331,35 @@
gser->send_modem_ctrl_bits(gser, ctrl_bits);
}
+static int ghsic_ctrl_get_port_id(const char *pdev_name)
+{
+ struct gctrl_port *port;
+ int i;
+
+ for (i = 0; i < no_ctrl_ports; i++) {
+ port = gctrl_ports[i].port;
+ if (!strncmp(port->brdg.name, pdev_name, BRIDGE_NAME_MAX_LEN))
+ return i;
+ }
+
+ return -EINVAL;
+}
+
static int ghsic_ctrl_probe(struct platform_device *pdev)
{
struct gctrl_port *port;
unsigned long flags;
+ int id;
pr_debug("%s: name:%s\n", __func__, pdev->name);
- if (pdev->id >= no_ctrl_ports) {
- pr_err("%s: invalid port: %d\n", __func__, pdev->id);
+ id = ghsic_ctrl_get_port_id(pdev->name);
+ if (id < 0 || id >= no_ctrl_ports) {
+ pr_err("%s: invalid port: %d\n", __func__, id);
return -EINVAL;
}
- port = gctrl_ports[pdev->id].port;
+ port = gctrl_ports[id].port;
set_bit(CH_READY, &port->bridge_sts);
/* if usb is online, start read */
@@ -366,15 +377,17 @@
struct gserial *gser = NULL;
struct grmnet *gr = NULL;
unsigned long flags;
+ int id;
pr_debug("%s: name:%s\n", __func__, pdev->name);
- if (pdev->id >= no_ctrl_ports) {
- pr_err("%s: invalid port: %d\n", __func__, pdev->id);
+ id = ghsic_ctrl_get_port_id(pdev->name);
+ if (id < 0 || id >= no_ctrl_ports) {
+ pr_err("%s: invalid port: %d\n", __func__, id);
return -EINVAL;
}
- port = gctrl_ports[pdev->id].port;
+ port = gctrl_ports[id].port;
spin_lock_irqsave(&port->port_lock, flags);
if (!port->port_usb) {
@@ -421,15 +434,17 @@
{
struct gctrl_port *port;
struct platform_driver *pdrv;
+ char *name;
port = kzalloc(sizeof(struct gctrl_port), GFP_KERNEL);
if (!port)
return -ENOMEM;
- port->wq = create_singlethread_workqueue(ctrl_bridge_names[portno]);
+ name = gctrl_ports[portno].port_name;
+
+ port->wq = create_singlethread_workqueue(name);
if (!port->wq) {
- pr_err("%s: Unable to create workqueue:%s\n",
- __func__, ctrl_bridge_names[portno]);
+ pr_err("%s: Unable to create workqueue:%s\n", __func__, name);
return -ENOMEM;
}
@@ -441,7 +456,7 @@
INIT_WORK(&port->connect_w, ghsic_ctrl_connect_w);
INIT_WORK(&port->disconnect_w, gctrl_disconnect_w);
- port->brdg.ch_id = portno;
+ port->brdg.name = name;
port->brdg.ctx = port;
port->brdg.ops.send_pkt = ghsic_ctrl_receive;
if (port->gtype == USB_GADGET_SERIAL)
@@ -451,7 +466,7 @@
pdrv = &gctrl_ports[portno].pdrv;
pdrv->probe = ghsic_ctrl_probe;
pdrv->remove = ghsic_ctrl_remove;
- pdrv->driver.name = ctrl_bridge_names[portno];
+ pdrv->driver.name = name;
pdrv->driver.owner = THIS_MODULE;
platform_driver_register(pdrv);
@@ -461,6 +476,31 @@
return 0;
}
+/*portname will be used to find the bridge channel index*/
+void ghsic_ctrl_set_port_name(const char *name, const char *xport_type)
+{
+ static unsigned int port_num;
+
+ if (port_num >= NUM_PORTS) {
+ pr_err("%s: setting xport name for invalid port num %d\n",
+ __func__, port_num);
+ return;
+ }
+
+ /*if no xport name is passed set it to xport type e.g. hsic*/
+ if (!name)
+ strlcpy(gctrl_ports[port_num].port_name, xport_type,
+ BRIDGE_NAME_MAX_LEN);
+ else
+ strlcpy(gctrl_ports[port_num].port_name, name,
+ BRIDGE_NAME_MAX_LEN);
+
+ /*append _ctrl to get ctrl bridge name e.g. serial_hsic_ctrl*/
+ strlcat(gctrl_ports[port_num].port_name, "_ctrl", BRIDGE_NAME_MAX_LEN);
+
+ port_num++;
+}
+
int ghsic_ctrl_setup(unsigned int num_ports, enum gadget_type gtype)
{
int first_port_id = no_ctrl_ports;
diff --git a/drivers/usb/gadget/u_data_hsic.c b/drivers/usb/gadget/u_data_hsic.c
index 3932bbc..458eefe 100644
--- a/drivers/usb/gadget/u_data_hsic.c
+++ b/drivers/usb/gadget/u_data_hsic.c
@@ -25,13 +25,6 @@
static unsigned int no_data_ports;
-static const char *data_bridge_names[] = {
- "dun_data_hsic0",
- "rmnet_data_hsic0"
-};
-
-#define DATA_BRIDGE_NAME_MAX_LEN 20
-
#define GHSIC_DATA_RMNET_RX_Q_SIZE 50
#define GHSIC_DATA_RMNET_TX_Q_SIZE 300
#define GHSIC_DATA_SERIAL_RX_Q_SIZE 10
@@ -130,6 +123,7 @@
static struct {
struct gdata_port *port;
struct platform_driver pdrv;
+ char port_name[BRIDGE_NAME_MAX_LEN];
} gdata_ports[NUM_PORTS];
static unsigned int get_timestamp(void);
@@ -586,19 +580,35 @@
spin_unlock_irqrestore(&port->rx_lock, flags);
}
+static int ghsic_data_get_port_id(const char *pdev_name)
+{
+ struct gdata_port *port;
+ int i;
+
+ for (i = 0; i < no_data_ports; i++) {
+ port = gdata_ports[i].port;
+ if (!strncmp(port->brdg.name, pdev_name, BRIDGE_NAME_MAX_LEN))
+ return i;
+ }
+
+ return -EINVAL;
+}
+
static int ghsic_data_probe(struct platform_device *pdev)
{
struct gdata_port *port;
+ int id;
- pr_debug("%s: name:%s no_data_ports= %d\n",
- __func__, pdev->name, no_data_ports);
+ pr_debug("%s: name:%s no_data_ports= %d\n", __func__, pdev->name,
+ no_data_ports);
- if (pdev->id >= no_data_ports) {
- pr_err("%s: invalid port: %d\n", __func__, pdev->id);
+ id = ghsic_data_get_port_id(pdev->name);
+ if (id < 0 || id >= no_data_ports) {
+ pr_err("%s: invalid port: %d\n", __func__, id);
return -EINVAL;
}
- port = gdata_ports[pdev->id].port;
+ port = gdata_ports[id].port;
set_bit(CH_READY, &port->bridge_sts);
/* if usb is online, try opening bridge */
@@ -614,15 +624,17 @@
struct gdata_port *port;
struct usb_ep *ep_in;
struct usb_ep *ep_out;
+ int id;
pr_debug("%s: name:%s\n", __func__, pdev->name);
- if (pdev->id >= no_data_ports) {
- pr_err("%s: invalid port: %d\n", __func__, pdev->id);
+ id = ghsic_data_get_port_id(pdev->name);
+ if (id < 0 || id >= no_data_ports) {
+ pr_err("%s: invalid port: %d\n", __func__, id);
return -EINVAL;
}
- port = gdata_ports[pdev->id].port;
+ port = gdata_ports[id].port;
ep_in = port->in;
if (ep_in)
@@ -658,15 +670,17 @@
{
struct gdata_port *port;
struct platform_driver *pdrv;
+ char *name;
port = kzalloc(sizeof(struct gdata_port), GFP_KERNEL);
if (!port)
return -ENOMEM;
- port->wq = create_singlethread_workqueue(data_bridge_names[port_num]);
+ name = gdata_ports[port_num].port_name;
+
+ port->wq = create_singlethread_workqueue(name);
if (!port->wq) {
- pr_err("%s: Unable to create workqueue:%s\n",
- __func__, data_bridge_names[port_num]);
+ pr_err("%s: Unable to create workqueue:%s\n", __func__, name);
kfree(port);
return -ENOMEM;
}
@@ -688,7 +702,7 @@
skb_queue_head_init(&port->rx_skb_q);
port->gtype = gtype;
- port->brdg.ch_id = port_num;
+ port->brdg.name = name;
port->brdg.ctx = port;
port->brdg.ops.send_pkt = ghsic_data_receive;
port->brdg.ops.unthrottle_tx = ghsic_data_unthrottle_tx;
@@ -697,7 +711,7 @@
pdrv = &gdata_ports[port_num].pdrv;
pdrv->probe = ghsic_data_probe;
pdrv->remove = ghsic_data_remove;
- pdrv->driver.name = data_bridge_names[port_num];
+ pdrv->driver.name = name;
pdrv->driver.owner = THIS_MODULE;
platform_driver_register(pdrv);
@@ -846,7 +860,7 @@
}
#if defined(CONFIG_DEBUG_FS)
-#define DEBUG_BUF_SIZE 1024
+#define DEBUG_DATA_BUF_SIZE 4096
static unsigned int record_timestamp;
module_param(record_timestamp, uint, S_IRUGO | S_IWUSR);
@@ -917,7 +931,7 @@
if (!record_timestamp)
return 0;
- buf = kzalloc(sizeof(char) * 4 * DEBUG_BUF_SIZE, GFP_KERNEL);
+ buf = kzalloc(sizeof(char) * DEBUG_DATA_BUF_SIZE, GFP_KERNEL);
if (!buf)
return -ENOMEM;
@@ -927,7 +941,7 @@
for (dbg_inc(&i); i != dbg_data.idx; dbg_inc(&i)) {
if (!strnlen(dbg_data.buf[i], DBG_DATA_MSG))
continue;
- j += scnprintf(buf + j, (4 * DEBUG_BUF_SIZE) - j,
+ j += scnprintf(buf + j, DEBUG_DATA_BUF_SIZE - j,
"%s\n", dbg_data.buf[i]);
}
@@ -955,7 +969,7 @@
int i;
int temp = 0;
- buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
+ buf = kzalloc(sizeof(char) * DEBUG_DATA_BUF_SIZE, GFP_KERNEL);
if (!buf)
return -ENOMEM;
@@ -966,7 +980,7 @@
pdrv = &gdata_ports[i].pdrv;
spin_lock_irqsave(&port->rx_lock, flags);
- temp += scnprintf(buf + temp, DEBUG_BUF_SIZE - temp,
+ temp += scnprintf(buf + temp, DEBUG_DATA_BUF_SIZE - temp,
"\nName: %s\n"
"#PORT:%d port#: %p\n"
"data_ch_open: %d\n"
@@ -991,7 +1005,7 @@
spin_unlock_irqrestore(&port->rx_lock, flags);
spin_lock_irqsave(&port->tx_lock, flags);
- temp += scnprintf(buf + temp, DEBUG_BUF_SIZE - temp,
+ temp += scnprintf(buf + temp, DEBUG_DATA_BUF_SIZE - temp,
"\n******DL INFO******\n\n"
"dpkts_to_usbhost: %lu\n"
"tx_buf_len: %u\n"
@@ -1094,6 +1108,31 @@
#endif
+/*portname will be used to find the bridge channel index*/
+void ghsic_data_set_port_name(const char *name, const char *xport_type)
+{
+ static unsigned int port_num;
+
+ if (port_num >= NUM_PORTS) {
+ pr_err("%s: setting xport name for invalid port num %d\n",
+ __func__, port_num);
+ return;
+ }
+
+ /*if no xport name is passed set it to xport type e.g. hsic*/
+ if (!name)
+ strlcpy(gdata_ports[port_num].port_name, xport_type,
+ BRIDGE_NAME_MAX_LEN);
+ else
+ strlcpy(gdata_ports[port_num].port_name, name,
+ BRIDGE_NAME_MAX_LEN);
+
+ /*append _data to get data bridge name: e.g. serial_hsic_data*/
+ strlcat(gdata_ports[port_num].port_name, "_data", BRIDGE_NAME_MAX_LEN);
+
+ port_num++;
+}
+
int ghsic_data_setup(unsigned num_ports, enum gadget_type gtype)
{
int first_port_id = no_data_ports;
diff --git a/drivers/usb/misc/mdm_ctrl_bridge.c b/drivers/usb/misc/mdm_ctrl_bridge.c
index 2b56ee0..9ab06a1 100644
--- a/drivers/usb/misc/mdm_ctrl_bridge.c
+++ b/drivers/usb/misc/mdm_ctrl_bridge.c
@@ -26,11 +26,6 @@
#include <asm/unaligned.h>
#include <mach/usb_bridge.h>
-static const char *ctrl_bridge_names[] = {
- "dun_ctrl_hsic0",
- "rmnet_ctrl_hsic0"
-};
-
/* polling interval for Interrupt ep */
#define HS_INTERVAL 7
#define FS_LS_INTERVAL 3
@@ -44,6 +39,8 @@
struct usb_device *udev;
struct usb_interface *intf;
+ char *name;
+
unsigned int int_pipe;
struct urb *inturb;
void *intbuf;
@@ -79,6 +76,20 @@
/* counter used for indexing ctrl bridge devices */
static int ch_id;
+static int get_ctrl_bridge_chid(char *xport_name)
+{
+ struct ctrl_bridge *dev;
+ int i;
+
+ for (i = 0; i < MAX_BRIDGE_DEVICES; i++) {
+ dev = __dev[i];
+ if (!strncmp(dev->name, xport_name, BRIDGE_NAME_MAX_LEN))
+ return i;
+ }
+
+ return -ENODEV;
+}
+
unsigned int ctrl_bridge_get_cbits_tohost(unsigned int id)
{
struct ctrl_bridge *dev;
@@ -272,21 +283,22 @@
int ctrl_bridge_open(struct bridge *brdg)
{
struct ctrl_bridge *dev;
+ int ch_id;
if (!brdg) {
err("bridge is null\n");
return -EINVAL;
}
- if (brdg->ch_id >= MAX_BRIDGE_DEVICES)
- return -EINVAL;
-
- dev = __dev[brdg->ch_id];
- if (!dev) {
- err("dev is null\n");
- return -ENODEV;
+ ch_id = get_ctrl_bridge_chid(brdg->name);
+ if (ch_id < 0 || ch_id >= MAX_BRIDGE_DEVICES) {
+ err("%s: %s dev not found\n", __func__, brdg->name);
+ return ch_id;
}
+ brdg->ch_id = ch_id;
+
+ dev = __dev[ch_id];
dev->brdg = brdg;
dev->snd_encap_cmd = 0;
dev->get_encap_res = 0;
@@ -596,7 +608,7 @@
int
ctrl_bridge_probe(struct usb_interface *ifc, struct usb_host_endpoint *int_in,
- int id)
+ char *name, int id)
{
struct ctrl_bridge *dev;
struct usb_device *udev;
@@ -613,7 +625,9 @@
return -ENODEV;
}
- dev->pdev = platform_device_alloc(ctrl_bridge_names[id], id);
+ dev->name = name;
+
+ dev->pdev = platform_device_alloc(name, -1);
if (!dev->pdev) {
dev_err(&ifc->dev, "%s: unable to allocate platform device\n",
__func__);
@@ -743,6 +757,9 @@
goto error;
}
+ /*transport name will be set during probe*/
+ dev->name = "";
+
init_usb_anchor(&dev->tx_submitted);
init_usb_anchor(&dev->tx_deferred);
diff --git a/drivers/usb/misc/mdm_data_bridge.c b/drivers/usb/misc/mdm_data_bridge.c
index f783f09..82a7e35 100644
--- a/drivers/usb/misc/mdm_data_bridge.c
+++ b/drivers/usb/misc/mdm_data_bridge.c
@@ -29,9 +29,18 @@
#define FLOW_CTRL_DISABLE 300
#define FLOW_CTRL_SUPPORT 1
-static const char *data_bridge_names[] = {
- "dun_data_hsic0",
- "rmnet_data_hsic0"
+#define BRIDGE_DATA_IDX 0
+#define BRIDGE_CTRL_IDX 1
+
+/*for xport : HSIC*/
+static const char * const serial_hsic_bridge_names[] = {
+ "serial_hsic_data",
+ "serial_hsic_ctrl",
+};
+
+static const char * const rmnet_hsic_bridge_names[] = {
+ "rmnet_hsic_data",
+ "rmnet_hsic_ctrl",
};
static struct workqueue_struct *bridge_wq;
@@ -62,6 +71,7 @@
struct usb_interface *intf;
struct usb_device *udev;
int id;
+ char *name;
unsigned int bulk_in;
unsigned int bulk_out;
@@ -110,6 +120,20 @@
static int submit_rx_urb(struct data_bridge *dev, struct urb *urb,
gfp_t flags);
+static int get_data_bridge_chid(char *xport_name)
+{
+ struct data_bridge *dev;
+ int i;
+
+ for (i = 0; i < MAX_BRIDGE_DEVICES; i++) {
+ dev = __dev[i];
+ if (!strncmp(dev->name, xport_name, BRIDGE_NAME_MAX_LEN))
+ return i;
+ }
+
+ return -ENODEV;
+}
+
static inline bool rx_halted(struct data_bridge *dev)
{
return test_bit(RX_HALT, &dev->flags);
@@ -322,21 +346,23 @@
int data_bridge_open(struct bridge *brdg)
{
struct data_bridge *dev;
+ int ch_id;
if (!brdg) {
err("bridge is null\n");
return -EINVAL;
}
- if (brdg->ch_id >= MAX_BRIDGE_DEVICES)
- return -EINVAL;
-
- dev = __dev[brdg->ch_id];
- if (!dev) {
- err("dev is null\n");
- return -ENODEV;
+ ch_id = get_data_bridge_chid(brdg->name);
+ if (ch_id < 0 || ch_id >= MAX_BRIDGE_DEVICES) {
+ err("%s: %s dev not found\n", __func__, brdg->name);
+ return ch_id;
}
+ brdg->ch_id = ch_id;
+
+ dev = __dev[ch_id];
+
dev_dbg(&dev->intf->dev, "%s: dev:%p\n", __func__, dev);
dev->brdg = brdg;
@@ -657,7 +683,7 @@
static int data_bridge_probe(struct usb_interface *iface,
struct usb_host_endpoint *bulk_in,
- struct usb_host_endpoint *bulk_out, int id)
+ struct usb_host_endpoint *bulk_out, char *name, int id)
{
struct data_bridge *dev;
int retval;
@@ -668,7 +694,7 @@
return -ENODEV;
}
- dev->pdev = platform_device_alloc(data_bridge_names[id], id);
+ dev->pdev = platform_device_alloc(name, -1);
if (!dev->pdev) {
err("%s: unable to allocate platform device\n", __func__);
kfree(dev);
@@ -677,6 +703,7 @@
dev->flags = 0;
dev->id = id;
+ dev->name = name;
dev->udev = interface_to_usbdev(iface);
dev->intf = iface;
@@ -939,9 +966,7 @@
int i;
int status = 0;
int numends;
- unsigned int iface_num;
-
- iface_num = iface->cur_altsetting->desc.bInterfaceNumber;
+ char **bname = (char **)id->driver_info;
if (iface->num_altsetting != 1) {
err("%s invalid num_altsetting %u\n",
@@ -949,9 +974,6 @@
return -EINVAL;
}
- if (!test_bit(iface_num, &id->driver_info))
- return -ENODEV;
-
udev = interface_to_usbdev(iface);
usb_get_dev(udev);
@@ -979,13 +1001,15 @@
goto out;
}
- status = data_bridge_probe(iface, bulk_in, bulk_out, ch_id);
+ status = data_bridge_probe(iface, bulk_in, bulk_out,
+ bname[BRIDGE_DATA_IDX], ch_id);
if (status < 0) {
dev_err(&iface->dev, "data_bridge_probe failed %d\n", status);
goto out;
}
- status = ctrl_bridge_probe(iface, int_in, ch_id);
+ status = ctrl_bridge_probe(iface, int_in, bname[BRIDGE_CTRL_IDX],
+ ch_id);
if (status < 0) {
dev_err(&iface->dev, "ctrl_bridge_probe failed %d\n", status);
goto error;
@@ -1024,28 +1048,37 @@
usb_put_dev(dev->udev);
}
-/*bit position represents interface number*/
-#define PID9001_IFACE_MASK 0xC
-#define PID9034_IFACE_MASK 0xC
-#define PID9048_IFACE_MASK 0x18
-#define PID904C_IFACE_MASK 0x28
-#define PID9075_IFACE_MASK 0x28
-
+/*driver info stores data/ctrl bridge name used to match bridge xport name*/
static const struct usb_device_id bridge_ids[] = {
- { USB_DEVICE(0x5c6, 0x9001),
- .driver_info = PID9001_IFACE_MASK,
+ { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9001, 2),
+ .driver_info = (unsigned long)serial_hsic_bridge_names,
},
- { USB_DEVICE(0x5c6, 0x9034),
- .driver_info = PID9034_IFACE_MASK,
+ { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9001, 3),
+ .driver_info = (unsigned long)rmnet_hsic_bridge_names,
},
- { USB_DEVICE(0x5c6, 0x9048),
- .driver_info = PID9048_IFACE_MASK,
+ { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9034, 2),
+ .driver_info = (unsigned long)serial_hsic_bridge_names,
},
- { USB_DEVICE(0x5c6, 0x904c),
- .driver_info = PID904C_IFACE_MASK,
+ { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9034, 3),
+ .driver_info = (unsigned long)rmnet_hsic_bridge_names,
},
- { USB_DEVICE(0x5c6, 0x9075),
- .driver_info = PID9075_IFACE_MASK,
+ { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9048, 3),
+ .driver_info = (unsigned long)serial_hsic_bridge_names,
+ },
+ { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9048, 4),
+ .driver_info = (unsigned long)rmnet_hsic_bridge_names,
+ },
+ { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x904c, 3),
+ .driver_info = (unsigned long)serial_hsic_bridge_names,
+ },
+ { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x904c, 5),
+ .driver_info = (unsigned long)rmnet_hsic_bridge_names,
+ },
+ { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9075, 3),
+ .driver_info = (unsigned long)serial_hsic_bridge_names,
+ },
+ { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9075, 5),
+ .driver_info = (unsigned long)rmnet_hsic_bridge_names,
},
{ } /* Terminating entry */
@@ -1090,6 +1123,9 @@
dev->wq = bridge_wq;
+ /*transport name will be set during probe*/
+ dev->name = "";
+
init_usb_anchor(&dev->tx_active);
init_usb_anchor(&dev->rx_active);
init_usb_anchor(&dev->delayed);