usb: gadget: Add support to RmNet over USB-IPA
Add support for the RmNet over USB-IPA BAM2BAM.
Change-Id: I47db19c32efe4bf35fc45210dbce7a9a738c493b
Signed-off-by: Ofir Cohen <ofirc@codeaurora.org>
diff --git a/drivers/usb/gadget/u_bam.c b/drivers/usb/gadget/u_bam.c
index f092329..7f3713f 100644
--- a/drivers/usb/gadget/u_bam.c
+++ b/drivers/usb/gadget/u_bam.c
@@ -101,6 +101,8 @@
u32 src_pipe_idx;
u32 dst_pipe_idx;
u8 connection_idx;
+ enum transport_type trans;
+ struct usb_bam_connect_ipa_params *ipa_params;
/* stats */
unsigned int pending_with_bam;
@@ -640,6 +642,21 @@
clear_bit(BAM_CH_OPENED, &d->flags);
}
+static void gbam2bam_disconnect_work(struct work_struct *w)
+{
+ struct gbam_port *port = container_of(w, struct gbam_port, connect_w);
+ struct bam_ch_info *d = &port->data_ch;
+ int ret;
+
+ if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
+ ret = usb_bam_disconnect_ipa(d->connection_idx, d->ipa_params);
+ if (ret)
+ pr_err("%s: usb_bam_disconnect_ipa failed: err:%d\n",
+ __func__, ret);
+ rmnet_bridge_disconnect();
+ }
+}
+
static void gbam_connect_work(struct work_struct *w)
{
struct gbam_port *port = container_of(w, struct gbam_port, connect_w);
@@ -680,12 +697,38 @@
u32 sps_params;
int ret;
- ret = usb_bam_connect(d->connection_idx, &d->src_pipe_idx,
- &d->dst_pipe_idx);
- if (ret) {
- pr_err("%s: usb_bam_connect failed: err:%d\n",
- __func__, ret);
- return;
+ if (d->trans == USB_GADGET_XPORT_BAM2BAM) {
+ ret = usb_bam_connect(d->connection_idx, &d->src_pipe_idx,
+ &d->dst_pipe_idx);
+ if (ret) {
+ pr_err("%s: usb_bam_connect failed: err:%d\n",
+ __func__, ret);
+ return;
+ }
+ } else if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
+ d->ipa_params->client = IPA_CLIENT_USB_CONS;
+ d->ipa_params->dir = PEER_PERIPHERAL_TO_USB;
+ ret = usb_bam_connect_ipa(d->ipa_params);
+ if (ret) {
+ pr_err("%s: usb_bam_connect_ipa failed: err:%d\n",
+ __func__, ret);
+ return;
+ }
+
+ d->ipa_params->client = IPA_CLIENT_USB_PROD;
+ d->ipa_params->dir = USB_TO_PEER_PERIPHERAL;
+ /* Currently only DMA mode is supported */
+ d->ipa_params->ipa_ep_cfg.mode.mode = IPA_DMA;
+ d->ipa_params->ipa_ep_cfg.mode.dst =
+ IPA_CLIENT_A2_TETHERED_CONS;
+ ret = usb_bam_connect_ipa(d->ipa_params);
+ if (ret) {
+ pr_err("%s: usb_bam_connect_ipa failed: err:%d\n",
+ __func__, ret);
+ return;
+ }
+ rmnet_bridge_connect(d->ipa_params->prod_clnt_hdl,
+ d->ipa_params->cons_clnt_hdl, 0);
}
d->rx_req = usb_ep_alloc_request(port->port_usb->out, GFP_KERNEL);
@@ -873,6 +916,7 @@
spin_lock_init(&port->port_lock_dl);
INIT_WORK(&port->connect_w, gbam2bam_connect_work);
+ INIT_WORK(&port->disconnect_w, gbam2bam_disconnect_work);
/* data ch */
d = &port->data_ch;
@@ -993,7 +1037,8 @@
static void gam_debugfs_init(void) { }
#endif
-void gbam_disconnect(struct grmnet *gr, u8 port_num, enum transport_type trans)
+void gbam_disconnect(struct grmnet *gr, u8 port_num, enum transport_type trans,
+ struct usb_bam_connect_ipa_params *ipa_params)
{
struct gbam_port *port;
unsigned long flags;
@@ -1008,7 +1053,8 @@
return;
}
- if (trans == USB_GADGET_XPORT_BAM2BAM &&
+ if ((trans == USB_GADGET_XPORT_BAM2BAM ||
+ trans == USB_GADGET_XPORT_BAM2BAM_IPA) &&
port_num >= n_bam2bam_ports) {
pr_err("%s: invalid bam2bam portno#%d\n",
__func__, port_num);
@@ -1044,12 +1090,14 @@
gr->in->driver_data = NULL;
gr->out->driver_data = NULL;
- if (trans == USB_GADGET_XPORT_BAM)
+ if (trans == USB_GADGET_XPORT_BAM ||
+ trans == USB_GADGET_XPORT_BAM2BAM_IPA)
queue_work(gbam_wq, &port->disconnect_w);
}
int gbam_connect(struct grmnet *gr, u8 port_num,
- enum transport_type trans, u8 connection_idx)
+ enum transport_type trans, u8 connection_idx,
+ struct usb_bam_connect_ipa_params *ipa_params)
{
struct gbam_port *port;
struct bam_ch_info *d;
@@ -1063,7 +1111,9 @@
return -ENODEV;
}
- if (trans == USB_GADGET_XPORT_BAM2BAM && port_num >= n_bam2bam_ports) {
+ if ((trans == USB_GADGET_XPORT_BAM2BAM ||
+ trans == USB_GADGET_XPORT_BAM2BAM_IPA)
+ && port_num >= n_bam2bam_ports) {
pr_err("%s: invalid portno#%d\n", __func__, port_num);
return -ENODEV;
}
@@ -1115,8 +1165,15 @@
if (trans == USB_GADGET_XPORT_BAM2BAM) {
port->gr = gr;
d->connection_idx = connection_idx;
+ } else if (trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
+ d->ipa_params = ipa_params;
+ 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->trans = trans;
queue_work(gbam_wq, &port->connect_w);
return 0;
@@ -1195,7 +1252,8 @@
struct gbam_port *port;
struct bam_ch_info *d;
- if (trans != USB_GADGET_XPORT_BAM2BAM)
+ if (trans != USB_GADGET_XPORT_BAM2BAM &&
+ trans != USB_GADGET_XPORT_BAM2BAM_IPA)
return;
port = bam2bam_ports[port_num];
@@ -1211,7 +1269,8 @@
struct gbam_port *port;
struct bam_ch_info *d;
- if (trans != USB_GADGET_XPORT_BAM2BAM)
+ if (trans != USB_GADGET_XPORT_BAM2BAM &&
+ trans != USB_GADGET_XPORT_BAM2BAM_IPA)
return;
port = bam2bam_ports[port_num];