usb: usb_bam: Add support for multi USB BAMs
This change add the support for activating more than
one usb core in the system in bam to bam mode.
Potentially, we can have up to three usb cores in
the system: HSUSB, HSIC and DWC3.
This change simplify the USB BAM driver design, such that
we can easily define bam to bam paths for more than one usb
core concurrently with flexible peer BAMs configuration.
Change-Id: Ie5acb68f29e30cb6c14d2afd957ac8e21cc7beba
Signed-off-by: Shimrit Malichi <smalichi@codeaurora.org>
diff --git a/drivers/usb/gadget/f_mbim.c b/drivers/usb/gadget/f_mbim.c
index a32dd15..893f315 100644
--- a/drivers/usb/gadget/f_mbim.c
+++ b/drivers/usb/gadget/f_mbim.c
@@ -662,19 +662,30 @@
static int mbim_bam_connect(struct f_mbim *dev)
{
int ret;
+ u8 src_connection_idx, dst_connection_idx;
+ struct usb_gadget *gadget = dev->cdev->gadget;
pr_info("dev:%p portno:%d\n", dev, dev->port_num);
+ src_connection_idx = usb_bam_get_connection_idx(gadget->name, A2_P_BAM,
+ USB_TO_PEER_PERIPHERAL, dev->port_num);
+ dst_connection_idx = usb_bam_get_connection_idx(gadget->name, A2_P_BAM,
+ PEER_PERIPHERAL_TO_USB, dev->port_num);
+ if (src_connection_idx < 0 || dst_connection_idx < 0) {
+ pr_err("%s: usb_bam_get_connection_idx failed\n", __func__);
+ return ret;
+ }
+
ret = bam_data_connect(&dev->bam_port, dev->port_num,
- USB_GADGET_XPORT_BAM2BAM, dev->port_num, USB_FUNC_MBIM);
+ USB_GADGET_XPORT_BAM2BAM, src_connection_idx,
+ dst_connection_idx, USB_FUNC_MBIM);
if (ret) {
pr_err("bam_data_setup failed: err:%d\n",
ret);
return ret;
- } else {
- pr_info("mbim bam connected\n");
}
+ pr_info("mbim bam connected\n");
return 0;
}
diff --git a/drivers/usb/gadget/f_qc_ecm.c b/drivers/usb/gadget/f_qc_ecm.c
index 559fd04..51f0e50 100644
--- a/drivers/usb/gadget/f_qc_ecm.c
+++ b/drivers/usb/gadget/f_qc_ecm.c
@@ -390,14 +390,27 @@
static int ecm_qc_bam_connect(struct f_ecm_qc *dev)
{
int ret;
+ u8 src_connection_idx, dst_connection_idx;
+ struct usb_composite_dev *cdev = dev->port.func.config->cdev;
+ struct usb_gadget *gadget = cdev->gadget;
+ enum peer_bam peer_bam = (dev->xport == USB_GADGET_XPORT_BAM2BAM_IPA) ?
+ IPA_P_BAM : A2_P_BAM;
- ecm_qc_bam_port.cdev = dev->port.func.config->cdev;
+ ecm_qc_bam_port.cdev = cdev;
ecm_qc_bam_port.in = dev->port.in_ep;
ecm_qc_bam_port.out = dev->port.out_ep;
/* currently we use the first connection */
+ src_connection_idx = usb_bam_get_connection_idx(gadget->name, peer_bam,
+ USB_TO_PEER_PERIPHERAL, 0);
+ dst_connection_idx = usb_bam_get_connection_idx(gadget->name, peer_bam,
+ PEER_PERIPHERAL_TO_USB, 0);
+ if (src_connection_idx < 0 || dst_connection_idx < 0) {
+ pr_err("%s: usb_bam_get_connection_idx failed\n", __func__);
+ return ret;
+ }
ret = bam_data_connect(&ecm_qc_bam_port, 0, dev->xport,
- 0, USB_FUNC_ECM);
+ src_connection_idx, dst_connection_idx, USB_FUNC_ECM);
if (ret) {
pr_err("bam_data_connect failed: err:%d\n", ret);
return ret;
diff --git a/drivers/usb/gadget/f_qc_rndis.c b/drivers/usb/gadget/f_qc_rndis.c
index 51d7bc1..8b01176 100644
--- a/drivers/usb/gadget/f_qc_rndis.c
+++ b/drivers/usb/gadget/f_qc_rndis.c
@@ -421,22 +421,33 @@
static int rndis_qc_bam_connect(struct f_rndis_qc *dev)
{
int ret;
+ u8 src_connection_idx, dst_connection_idx;
+ struct usb_composite_dev *cdev = dev->port.func.config->cdev;
+ struct usb_gadget *gadget = cdev->gadget;
- dev->bam_port.cdev = dev->port.func.config->cdev;
+ dev->bam_port.cdev = cdev;
dev->bam_port.in = dev->port.in_ep;
dev->bam_port.out = dev->port.out_ep;
/* currently we use the first connection */
+ src_connection_idx = usb_bam_get_connection_idx(gadget->name, A2_P_BAM,
+ USB_TO_PEER_PERIPHERAL, 0);
+ dst_connection_idx = usb_bam_get_connection_idx(gadget->name, A2_P_BAM,
+ PEER_PERIPHERAL_TO_USB, 0);
+ if (src_connection_idx < 0 || dst_connection_idx < 0) {
+ pr_err("%s: usb_bam_get_connection_idx failed\n", __func__);
+ return ret;
+ }
ret = bam_data_connect(&dev->bam_port, 0, USB_GADGET_XPORT_BAM2BAM,
- 0, USB_FUNC_RNDIS);
+ src_connection_idx, dst_connection_idx, USB_FUNC_RNDIS);
if (ret) {
pr_err("bam_data_connect failed: err:%d\n",
ret);
return ret;
- } else {
- pr_info("rndis bam connected\n");
}
+ pr_info("rndis bam connected\n");
+
return 0;
}
diff --git a/drivers/usb/gadget/f_qdss.c b/drivers/usb/gadget/f_qdss.c
index 3069bcb..6518095 100644
--- a/drivers/usb/gadget/f_qdss.c
+++ b/drivers/usb/gadget/f_qdss.c
@@ -1,7 +1,7 @@
/*
* f_qdss.c -- QDSS function Driver
*
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-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
@@ -447,8 +447,8 @@
qdss->ch.notify(qdss->ch.priv, USB_QDSS_DISCONNECT, NULL,
NULL);
/* If the app was never started, we can skip USB BAM reset */
- status = set_qdss_data_connection(qdss->data,
- qdss->data->address, 0);
+ status = set_qdss_data_connection(qdss->cdev->gadget,
+ qdss->data, qdss->data->address, 0);
if (status)
pr_err("qdss_disconnect error");
}
@@ -490,7 +490,7 @@
return;
}
- status = set_qdss_data_connection(qdss->data,
+ status = set_qdss_data_connection(qdss->cdev->gadget, qdss->data,
qdss->data->address, 1);
if (status) {
pr_err("set_qdss_data_connection error");
diff --git a/drivers/usb/gadget/f_rmnet.c b/drivers/usb/gadget/f_rmnet.c
index af68827..4b9dfbf 100644
--- a/drivers/usb/gadget/f_rmnet.c
+++ b/drivers/usb/gadget/f_rmnet.c
@@ -387,6 +387,8 @@
unsigned port_num;
enum transport_type cxport = rmnet_ports[dev->port_num].ctrl_xport;
enum transport_type dxport = rmnet_ports[dev->port_num].data_xport;
+ u8 src_connection_idx, dst_connection_idx;
+ struct usb_gadget *gadget = dev->cdev->gadget;
pr_debug("%s: ctrl xport: %s data xport: %s dev: %p portno: %d\n",
__func__, xport_to_str(cxport), xport_to_str(dxport),
@@ -435,12 +437,42 @@
}
port_num = rmnet_ports[dev->port_num].data_xport_num;
+
switch (dxport) {
case USB_GADGET_XPORT_BAM:
case USB_GADGET_XPORT_BAM2BAM:
- case USB_GADGET_XPORT_BAM2BAM_IPA:
+ src_connection_idx = usb_bam_get_connection_idx(gadget->name,
+ A2_P_BAM, USB_TO_PEER_PERIPHERAL, port_num);
+ dst_connection_idx = usb_bam_get_connection_idx(gadget->name,
+ A2_P_BAM, PEER_PERIPHERAL_TO_USB, port_num);
+ if (dst_connection_idx < 0 || src_connection_idx < 0) {
+ pr_err("%s: usb_bam_get_connection_idx failed\n",
+ __func__);
+ gsmd_ctrl_disconnect(&dev->port, port_num);
+ return ret;
+ }
ret = gbam_connect(&dev->port, port_num,
- dxport, port_num);
+ dxport, src_connection_idx, dst_connection_idx);
+ if (ret) {
+ pr_err("%s: gbam_connect failed: err:%d\n",
+ __func__, ret);
+ gsmd_ctrl_disconnect(&dev->port, port_num);
+ return ret;
+ }
+ break;
+ case USB_GADGET_XPORT_BAM2BAM_IPA:
+ src_connection_idx = usb_bam_get_connection_idx(gadget->name,
+ IPA_P_BAM, USB_TO_PEER_PERIPHERAL, port_num);
+ dst_connection_idx = usb_bam_get_connection_idx(gadget->name,
+ IPA_P_BAM, PEER_PERIPHERAL_TO_USB, port_num);
+ if (dst_connection_idx < 0 || src_connection_idx < 0) {
+ pr_err("%s: usb_bam_get_connection_idx failed\n",
+ __func__);
+ gsmd_ctrl_disconnect(&dev->port, port_num);
+ return ret;
+ }
+ ret = gbam_connect(&dev->port, port_num,
+ dxport, src_connection_idx, dst_connection_idx);
if (ret) {
pr_err("%s: gbam_connect failed: err:%d\n",
__func__, ret);
diff --git a/drivers/usb/gadget/u_bam.c b/drivers/usb/gadget/u_bam.c
index 5a6faf2..3c3fbca 100644
--- a/drivers/usb/gadget/u_bam.c
+++ b/drivers/usb/gadget/u_bam.c
@@ -100,7 +100,8 @@
u32 src_pipe_idx;
u32 dst_pipe_idx;
- u8 connection_idx;
+ u8 src_connection_idx;
+ u8 dst_connection_idx;
enum transport_type trans;
struct usb_bam_connect_ipa_params ipa_params;
@@ -663,7 +664,7 @@
int ret;
if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
- ret = usb_bam_disconnect_ipa(d->connection_idx, &d->ipa_params);
+ ret = usb_bam_disconnect_ipa(&d->ipa_params);
if (ret)
pr_err("%s: usb_bam_disconnect_ipa failed: err:%d\n",
__func__, ret);
@@ -715,10 +716,15 @@
int ret;
if (d->trans == USB_GADGET_XPORT_BAM2BAM) {
- ret = usb_bam_connect(d->connection_idx, &d->src_pipe_idx,
- &d->dst_pipe_idx);
+ ret = usb_bam_connect(d->src_connection_idx, &d->src_pipe_idx);
if (ret) {
- pr_err("%s: usb_bam_connect failed: err:%d\n",
+ pr_err("%s: usb_bam_connect (src) failed: err:%d\n",
+ __func__, ret);
+ return;
+ }
+ ret = usb_bam_connect(d->dst_connection_idx, &d->dst_pipe_idx);
+ if (ret) {
+ pr_err("%s: usb_bam_connect (dst) failed: err:%d\n",
__func__, ret);
return;
}
@@ -787,8 +793,7 @@
if (d->trans == USB_GADGET_XPORT_BAM2BAM && port->port_num == 0) {
/* Register for peer reset callback */
- usb_bam_register_peer_reset_cb(d->connection_idx,
- gbam_peer_reset_cb, port);
+ usb_bam_register_peer_reset_cb(gbam_peer_reset_cb, port);
ret = usb_bam_client_ready(true);
if (ret) {
@@ -832,7 +837,7 @@
msm_hw_bam_disable(1);
/* Reset BAM */
- ret = usb_bam_reset();
+ ret = usb_bam_a2_reset();
if (ret) {
pr_err("%s: BAM reset failed %d\n", __func__, ret);
goto reenable_eps;
@@ -867,7 +872,7 @@
/* Unregister the peer reset callback */
if (d->trans == USB_GADGET_XPORT_BAM2BAM && port->port_num == 0)
- usb_bam_register_peer_reset_cb(d->connection_idx, NULL, NULL);
+ usb_bam_register_peer_reset_cb(NULL, NULL);
return 0;
}
@@ -1216,7 +1221,8 @@
}
int gbam_connect(struct grmnet *gr, u8 port_num,
- enum transport_type trans, u8 connection_idx)
+ enum transport_type trans, u8 src_connection_idx,
+ u8 dst_connection_idx)
{
struct gbam_port *port;
struct bam_ch_info *d;
@@ -1283,12 +1289,14 @@
if (trans == USB_GADGET_XPORT_BAM2BAM) {
port->gr = gr;
- d->connection_idx = connection_idx;
+ d->src_connection_idx = src_connection_idx;
+ d->dst_connection_idx = dst_connection_idx;
} else if (trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
port->gr = gr;
d->ipa_params.src_pipe = &(d->src_pipe_idx);
d->ipa_params.dst_pipe = &(d->dst_pipe_idx);
- d->ipa_params.idx = connection_idx;
+ d->ipa_params.src_idx = src_connection_idx;
+ d->ipa_params.dst_idx = dst_connection_idx;
}
d->trans = trans;
@@ -1379,7 +1387,7 @@
pr_debug("%s: suspended port %d\n", __func__, port_num);
- usb_bam_register_wake_cb(d->connection_idx, gbam_wake_cb, port);
+ usb_bam_register_wake_cb(d->dst_connection_idx, gbam_wake_cb, port);
}
void gbam_resume(struct grmnet *gr, u8 port_num, enum transport_type trans)
@@ -1396,5 +1404,5 @@
pr_debug("%s: resumed port %d\n", __func__, port_num);
- usb_bam_register_wake_cb(d->connection_idx, NULL, NULL);
+ usb_bam_register_wake_cb(d->dst_connection_idx, NULL, NULL);
}
diff --git a/drivers/usb/gadget/u_bam_data.c b/drivers/usb/gadget/u_bam_data.c
index 700d07f..83f885a 100644
--- a/drivers/usb/gadget/u_bam_data.c
+++ b/drivers/usb/gadget/u_bam_data.c
@@ -47,7 +47,8 @@
u32 src_pipe_idx;
u32 dst_pipe_idx;
- u8 connection_idx;
+ u8 src_connection_idx;
+ u8 dst_connection_idx;
enum function_type func_type;
enum transport_type trans;
@@ -135,7 +136,7 @@
msm_hw_bam_disable(1);
/* Reset BAM */
- ret = usb_bam_reset();
+ ret = usb_bam_a2_reset();
if (ret) {
pr_err("%s: BAM reset failed %d\n", __func__, ret);
goto reenable_eps;
@@ -169,7 +170,7 @@
}
/* Unregister the peer reset callback */
- usb_bam_register_peer_reset_cb(d->connection_idx, NULL, NULL);
+ usb_bam_register_peer_reset_cb(NULL, NULL);
return 0;
}
@@ -184,7 +185,7 @@
if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
if (d->func_type == USB_FUNC_ECM)
ecm_ipa_disconnect(d->ipa_params.priv);
- ret = usb_bam_disconnect_ipa(d->connection_idx, &d->ipa_params);
+ ret = usb_bam_disconnect_ipa(&d->ipa_params);
if (ret)
pr_err("usb_bam_disconnect_ipa failed: err:%d\n", ret);
}
@@ -237,13 +238,17 @@
}
}
} else { /* transport type is USB_GADGET_XPORT_BAM2BAM */
- ret = usb_bam_connect(d->connection_idx, &d->src_pipe_idx,
- &d->dst_pipe_idx);
- if (ret) {
- pr_err("usb_bam_connect failed: err:%d\n", ret);
- return;
- }
+ ret = usb_bam_connect(d->src_connection_idx, &d->src_pipe_idx);
+ if (ret) {
+ pr_err("usb_bam_connect (src) failed: err:%d\n", ret);
+ return;
}
+ ret = usb_bam_connect(d->dst_connection_idx, &d->dst_pipe_idx);
+ if (ret) {
+ pr_err("usb_bam_connect (dst) failed: err:%d\n", ret);
+ return;
+ }
+}
if (!port->port_usb) {
pr_err("port_usb is NULL");
@@ -282,8 +287,7 @@
/* Register for peer reset callback if USB_GADGET_XPORT_BAM2BAM */
if (d->trans != USB_GADGET_XPORT_BAM2BAM_IPA) {
- usb_bam_register_peer_reset_cb(d->connection_idx,
- bam_data_peer_reset_cb, port);
+ usb_bam_register_peer_reset_cb(bam_data_peer_reset_cb, port);
ret = usb_bam_client_ready(true);
if (ret) {
@@ -369,7 +373,8 @@
}
int bam_data_connect(struct data_port *gr, u8 port_num,
- enum transport_type trans, u8 connection_idx, enum function_type func)
+ enum transport_type trans, u8 src_connection_idx,
+ u8 dst_connection_idx, enum function_type func)
{
struct bam_data_port *port;
struct bam_data_ch_info *d;
@@ -408,14 +413,16 @@
port->port_usb = gr;
- d->connection_idx = connection_idx;
+ d->src_connection_idx = src_connection_idx;
+ d->dst_connection_idx = dst_connection_idx;
d->trans = trans;
if (trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
d->ipa_params.src_pipe = &(d->src_pipe_idx);
d->ipa_params.dst_pipe = &(d->dst_pipe_idx);
- d->ipa_params.idx = connection_idx;
+ d->ipa_params.src_idx = src_connection_idx;
+ d->ipa_params.dst_idx = dst_connection_idx;
}
d->func_type = func;
@@ -499,7 +506,7 @@
d = &port->data_ch;
pr_debug("%s: suspended port %d\n", __func__, port_num);
- usb_bam_register_wake_cb(d->connection_idx, bam_data_wake_cb, port);
+ usb_bam_register_wake_cb(d->dst_connection_idx, bam_data_wake_cb, port);
}
void bam_data_resume(u8 port_num)
@@ -512,6 +519,6 @@
d = &port->data_ch;
pr_debug("%s: resumed port %d\n", __func__, port_num);
- usb_bam_register_wake_cb(d->connection_idx, NULL, NULL);
+ usb_bam_register_wake_cb(d->dst_connection_idx, NULL, NULL);
}
diff --git a/drivers/usb/gadget/u_bam_data.h b/drivers/usb/gadget/u_bam_data.h
index 71a01b9..486191b5 100644
--- a/drivers/usb/gadget/u_bam_data.h
+++ b/drivers/usb/gadget/u_bam_data.h
@@ -30,7 +30,8 @@
void bam_data_disconnect(struct data_port *gr, u8 port_num);
int bam_data_connect(struct data_port *gr, u8 port_num,
- enum transport_type trans, u8 connection_idx, enum function_type func);
+ enum transport_type trans, u8 src_connection_idx,
+ u8 dst_connection_idx, enum function_type func);
int bam_data_setup(unsigned int no_bam2bam_port);
diff --git a/drivers/usb/gadget/u_qdss.c b/drivers/usb/gadget/u_qdss.c
index 028d5e6..e241e29 100644
--- a/drivers/usb/gadget/u_qdss.c
+++ b/drivers/usb/gadget/u_qdss.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-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
@@ -15,8 +15,6 @@
#include <linux/usb/msm_hsusb.h>
#include <mach/usb_bam.h>
-#define BAM_CONNC_IDX 0 /* USB bam connection index */
-
struct usb_qdss_bam_connect_info {
u32 usb_bam_pipe_idx;
u32 peer_pipe_idx;
@@ -60,28 +58,33 @@
return 0;
}
-int set_qdss_data_connection(struct usb_ep *data_ep, u8 data_addr, int enable)
+static int set_qdss_data_connection(struct usb_gadget *gadget,
+ struct usb_ep *data_ep, u8 data_addr, int enable)
{
int res = 0;
+ u8 idx;
pr_debug("set_qdss_data_connection\n");
- if (enable) {
- res = usb_bam_connect(BAM_CONNC_IDX, NULL,
- &(bam_info.usb_bam_pipe_idx));
- if (res) {
- pr_err("usb_bam_connection error\n");
- return res;
- }
+ /* There is only one qdss pipe, so the pipe number can be set to 0 */
+ idx = usb_bam_get_connection_idx(gadget->name, QDSS_P_BAM,
+ PEER_PERIPHERAL_TO_USB, 0);
+ if (idx < 0) {
+ pr_err("%s: usb_bam_get_connection_idx failed\n", __func__);
+ return idx;
+ }
+ if (enable) {
+ res = usb_bam_connect(idx, &(bam_info.usb_bam_pipe_idx));
bam_info.data_fifo =
kzalloc(sizeof(struct sps_mem_buffer *), GFP_KERNEL);
if (!bam_info.data_fifo) {
pr_err("qdss_data_connection: memory alloc failed\n");
return -ENOMEM;
}
- get_bam2bam_connection_info(BAM_CONNC_IDX,
- PEER_PERIPHERAL_TO_USB, &bam_info.usb_bam_handle,
+ usb_bam_set_qdss_core(gadget->name);
+ get_bam2bam_connection_info(idx,
+ &bam_info.usb_bam_handle,
&bam_info.usb_bam_pipe_idx, &bam_info.peer_pipe_idx,
NULL, bam_info.data_fifo);
@@ -89,13 +92,13 @@
bam_info.data_fifo->size, bam_info.usb_bam_pipe_idx);
} else {
kfree(bam_info.data_fifo);
- res = usb_bam_disconnect_pipe(BAM_CONNC_IDX);
+ res = usb_bam_disconnect_pipe(idx);
if (res) {
pr_err("usb_bam_disconnection error\n");
return res;
}
-
}
+
return res;
}
diff --git a/drivers/usb/gadget/u_rmnet.h b/drivers/usb/gadget/u_rmnet.h
index cea9369..a9cca50 100644
--- a/drivers/usb/gadget/u_rmnet.h
+++ b/drivers/usb/gadget/u_rmnet.h
@@ -48,8 +48,10 @@
int gbam_setup(unsigned int no_bam_port, unsigned int no_bam2bam_port);
int gbam_connect(struct grmnet *gr, u8 port_num,
- enum transport_type trans, u8 connection_idx);
-void gbam_disconnect(struct grmnet *gr, u8 port_num, enum transport_type trans);
+ enum transport_type trans, u8 src_connection_idx,
+ u8 dst_connection_idx);
+void gbam_disconnect(struct grmnet *gr, u8 port_num,
+ enum transport_type trans);
void gbam_suspend(struct grmnet *gr, u8 port_num, enum transport_type trans);
void gbam_resume(struct grmnet *gr, u8 port_num, enum transport_type trans);
int gsmd_ctrl_connect(struct grmnet *gr, int port_num);