usb: gadget: Add RMNET support using IPA over BAM2BAM
This change adds RMNET support using IPA over BAM2BAM. Removes all different supported control and data transports and assumes BAM2BAM_IPA as default mode. Cleans up QTI Control driver to support only RMNET and DPL. Change-Id: I5b763acfb28c2f1832874af786704835314fa9c7 Signed-off-by: Ajay Agarwal <ajaya@codeaurora.org>
This commit is contained in:
parent
24d0c1f91e
commit
52b9f4271f
6 changed files with 214 additions and 671 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2012-2016, 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
|
||||
|
@ -21,6 +21,8 @@
|
|||
#include <linux/usb/composite.h>
|
||||
#include <linux/usb/usb_qdss.h>
|
||||
|
||||
#include "u_rmnet.h"
|
||||
|
||||
struct usb_qdss_bam_connect_info {
|
||||
u32 usb_bam_pipe_idx;
|
||||
u32 peer_pipe_idx;
|
||||
|
@ -33,8 +35,8 @@ struct gqdss {
|
|||
struct usb_ep *ctrl_out;
|
||||
struct usb_ep *ctrl_in;
|
||||
struct usb_ep *data;
|
||||
int (*send_encap_cmd)(u8 port_num, void *buf, size_t len);
|
||||
void (*notify_modem)(void *g, u8 port_num, int cbits);
|
||||
int (*send_encap_cmd)(enum qti_port_type qport, void *buf, size_t len);
|
||||
void (*notify_modem)(void *g, enum qti_port_type qport, int cbits);
|
||||
};
|
||||
|
||||
/* struct f_qdss - USB qdss function driver private structure */
|
||||
|
|
|
@ -18,15 +18,8 @@
|
|||
#include <linux/spinlock.h>
|
||||
#include <linux/usb_bam.h>
|
||||
|
||||
#include "usb_gadget_xport.h"
|
||||
#include "u_ether.h"
|
||||
#include "u_rmnet.h"
|
||||
#include "gadget_chips.h"
|
||||
|
||||
static unsigned int rmnet_dl_max_pkt_per_xfer = 7;
|
||||
module_param(rmnet_dl_max_pkt_per_xfer, uint, S_IRUGO | S_IWUSR);
|
||||
MODULE_PARM_DESC(rmnet_dl_max_pkt_per_xfer,
|
||||
"Maximum packets per transfer for DL aggregation");
|
||||
#include "u_data_ipa.h"
|
||||
|
||||
#define RMNET_NOTIFY_INTERVAL 5
|
||||
#define RMNET_MAX_NOTIFY_SIZE sizeof(struct usb_cdc_notification)
|
||||
|
@ -38,10 +31,9 @@ MODULE_PARM_DESC(rmnet_dl_max_pkt_per_xfer,
|
|||
* control paths
|
||||
*/
|
||||
struct f_rmnet {
|
||||
struct gether gether_port;
|
||||
struct usb_function func;
|
||||
struct grmnet port;
|
||||
int ifc_id;
|
||||
u8 port_num;
|
||||
atomic_t online;
|
||||
atomic_t ctrl_online;
|
||||
struct usb_composite_dev *cdev;
|
||||
|
@ -53,30 +45,11 @@ struct f_rmnet {
|
|||
struct usb_request *notify_req;
|
||||
|
||||
/* control info */
|
||||
struct gadget_ipa_port ipa_port;
|
||||
struct list_head cpkt_resp_q;
|
||||
unsigned long notify_count;
|
||||
unsigned long cpkts_len;
|
||||
const struct usb_endpoint_descriptor *in_ep_desc_backup;
|
||||
const struct usb_endpoint_descriptor *out_ep_desc_backup;
|
||||
};
|
||||
|
||||
static unsigned int nr_rmnet_ports;
|
||||
static unsigned int no_ctrl_smd_ports;
|
||||
static unsigned int no_ctrl_qti_ports;
|
||||
static unsigned int no_ctrl_hsic_ports;
|
||||
static unsigned int no_ctrl_hsuart_ports;
|
||||
static unsigned int no_data_bam_ports;
|
||||
static unsigned int no_data_bam2bam_ports;
|
||||
static unsigned int no_data_hsic_ports;
|
||||
static unsigned int no_data_hsuart_ports;
|
||||
static struct rmnet_ports {
|
||||
enum transport_type data_xport;
|
||||
enum transport_type ctrl_xport;
|
||||
unsigned data_xport_num;
|
||||
unsigned ctrl_xport_num;
|
||||
unsigned port_num;
|
||||
struct f_rmnet *port;
|
||||
} rmnet_ports[NR_RMNET_PORTS];
|
||||
} rmnet_port;
|
||||
|
||||
static struct usb_interface_descriptor rmnet_interface_desc = {
|
||||
.bLength = USB_DT_INTERFACE_SIZE,
|
||||
|
@ -244,7 +217,7 @@ static void frmnet_ctrl_response_available(struct f_rmnet *dev);
|
|||
|
||||
static inline struct f_rmnet *func_to_rmnet(struct usb_function *f)
|
||||
{
|
||||
return container_of(f, struct f_rmnet, gether_port.func);
|
||||
return container_of(f, struct f_rmnet, func);
|
||||
}
|
||||
|
||||
static inline struct f_rmnet *port_to_rmnet(struct grmnet *r)
|
||||
|
@ -253,8 +226,7 @@ static inline struct f_rmnet *port_to_rmnet(struct grmnet *r)
|
|||
}
|
||||
|
||||
static struct usb_request *
|
||||
frmnet_alloc_req(struct usb_ep *ep, unsigned len, size_t extra_buf_alloc,
|
||||
gfp_t flags)
|
||||
frmnet_alloc_req(struct usb_ep *ep, unsigned len, gfp_t flags)
|
||||
{
|
||||
struct usb_request *req;
|
||||
|
||||
|
@ -262,7 +234,7 @@ frmnet_alloc_req(struct usb_ep *ep, unsigned len, size_t extra_buf_alloc,
|
|||
if (!req)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
req->buf = kmalloc(len + extra_buf_alloc, flags);
|
||||
req->buf = kmalloc(len, flags);
|
||||
if (!req->buf) {
|
||||
usb_ep_free_request(ep, req);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
@ -308,195 +280,48 @@ static void rmnet_free_ctrl_pkt(struct rmnet_ctrl_pkt *pkt)
|
|||
static int rmnet_gport_setup(void)
|
||||
{
|
||||
int ret;
|
||||
int port_idx;
|
||||
int i;
|
||||
u8 base;
|
||||
|
||||
pr_debug("%s: bam ports:%u bam2bam ports:%u data hsic ports:%u\n",
|
||||
__func__, no_data_bam_ports, no_data_bam2bam_ports,
|
||||
no_data_hsic_ports);
|
||||
|
||||
pr_debug("%s: data hsuart ports:%u smd ports:%u ctrl hsic ports:%u\n",
|
||||
__func__, no_data_hsuart_ports, no_ctrl_smd_ports,
|
||||
no_ctrl_hsic_ports);
|
||||
|
||||
pr_debug("%s: ctrl hsuart ports:%u nr_rmnet_ports:%u\n",
|
||||
__func__, no_ctrl_hsuart_ports, nr_rmnet_ports);
|
||||
|
||||
if (no_data_bam_ports) {
|
||||
ret = gbam_setup(no_data_bam_ports);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (no_data_bam2bam_ports) {
|
||||
ret = gbam2bam_setup(no_data_bam2bam_ports);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (no_ctrl_smd_ports) {
|
||||
ret = gsmd_ctrl_setup(FRMNET_CTRL_CLIENT,
|
||||
no_ctrl_smd_ports, &base);
|
||||
if (ret)
|
||||
return ret;
|
||||
for (i = 0; i < nr_rmnet_ports; i++)
|
||||
if (rmnet_ports[i].port)
|
||||
rmnet_ports[i].port->port_num += base;
|
||||
}
|
||||
|
||||
if (no_data_hsic_ports) {
|
||||
port_idx = ghsic_data_setup(no_data_hsic_ports,
|
||||
USB_GADGET_RMNET);
|
||||
if (port_idx < 0)
|
||||
return port_idx;
|
||||
for (i = 0; i < nr_rmnet_ports; i++) {
|
||||
if (rmnet_ports[i].data_xport ==
|
||||
USB_GADGET_XPORT_HSIC) {
|
||||
rmnet_ports[i].data_xport_num = port_idx;
|
||||
port_idx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (no_ctrl_hsic_ports) {
|
||||
port_idx = ghsic_ctrl_setup(no_ctrl_hsic_ports,
|
||||
USB_GADGET_RMNET);
|
||||
if (port_idx < 0)
|
||||
return port_idx;
|
||||
for (i = 0; i < nr_rmnet_ports; i++) {
|
||||
if (rmnet_ports[i].ctrl_xport ==
|
||||
USB_GADGET_XPORT_HSIC) {
|
||||
rmnet_ports[i].ctrl_xport_num = port_idx;
|
||||
port_idx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = ipa_data_setup(USB_IPA_FUNC_RMNET);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gport_rmnet_connect(struct f_rmnet *dev, unsigned intf)
|
||||
{
|
||||
int ret;
|
||||
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;
|
||||
int src_connection_idx = 0, dst_connection_idx = 0;
|
||||
struct usb_gadget *gadget = dev->cdev->gadget;
|
||||
enum usb_ctrl usb_bam_type;
|
||||
void *net;
|
||||
|
||||
pr_debug("%s: ctrl xport: %s data xport: %s dev: %p portno: %d\n",
|
||||
__func__, xport_to_str(cxport), xport_to_str(dxport),
|
||||
dev, dev->port_num);
|
||||
|
||||
port_num = rmnet_ports[dev->port_num].ctrl_xport_num;
|
||||
switch (cxport) {
|
||||
case USB_GADGET_XPORT_SMD:
|
||||
ret = gsmd_ctrl_connect(&dev->port, port_num);
|
||||
if (ret) {
|
||||
pr_err("%s: gsmd_ctrl_connect failed: err:%d\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
case USB_GADGET_XPORT_QTI:
|
||||
ret = gqti_ctrl_connect(&dev->port, port_num, dev->ifc_id,
|
||||
dxport, USB_GADGET_RMNET);
|
||||
if (ret) {
|
||||
pr_err("%s: gqti_ctrl_connect failed: err:%d\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
case USB_GADGET_XPORT_HSIC:
|
||||
ret = ghsic_ctrl_connect(&dev->port, port_num);
|
||||
if (ret) {
|
||||
pr_err("%s: ghsic_ctrl_connect failed: err:%d\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
case USB_GADGET_XPORT_NONE:
|
||||
break;
|
||||
default:
|
||||
pr_err("%s: Un-supported transport: %s\n", __func__,
|
||||
xport_to_str(cxport));
|
||||
return -ENODEV;
|
||||
ret = gqti_ctrl_connect(&dev->port, QTI_PORT_RMNET, dev->ifc_id);
|
||||
if (ret) {
|
||||
pr_err("%s: gqti_ctrl_connect failed: err:%d\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
port_num = rmnet_ports[dev->port_num].data_xport_num;
|
||||
|
||||
switch (dxport) {
|
||||
case USB_GADGET_XPORT_BAM_DMUX:
|
||||
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);
|
||||
gsmd_ctrl_disconnect(&dev->port, port_num);
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
case USB_GADGET_XPORT_BAM2BAM_IPA:
|
||||
usb_bam_type = usb_bam_get_bam_type(gadget->name);
|
||||
src_connection_idx = usb_bam_get_connection_idx(usb_bam_type,
|
||||
IPA_P_BAM, USB_TO_PEER_PERIPHERAL, USB_BAM_DEVICE,
|
||||
port_num);
|
||||
dst_connection_idx = usb_bam_get_connection_idx(usb_bam_type,
|
||||
IPA_P_BAM, PEER_PERIPHERAL_TO_USB, USB_BAM_DEVICE,
|
||||
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 -EINVAL;
|
||||
}
|
||||
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);
|
||||
if (cxport == USB_GADGET_XPORT_QTI)
|
||||
gqti_ctrl_disconnect(&dev->port, port_num);
|
||||
else
|
||||
gsmd_ctrl_disconnect(&dev->port, port_num);
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
case USB_GADGET_XPORT_HSIC:
|
||||
ret = ghsic_data_connect(&dev->port, port_num);
|
||||
if (ret) {
|
||||
pr_err("%s: ghsic_data_connect failed: err:%d\n",
|
||||
__func__, ret);
|
||||
ghsic_ctrl_disconnect(&dev->port, port_num);
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
case USB_GADGET_XPORT_ETHER:
|
||||
gether_enable_sg(&dev->gether_port, true);
|
||||
net = gether_connect(&dev->gether_port);
|
||||
if (IS_ERR(net)) {
|
||||
pr_err("%s: gether_connect failed: err:%ld\n",
|
||||
__func__, PTR_ERR(net));
|
||||
if (cxport == USB_GADGET_XPORT_QTI)
|
||||
gqti_ctrl_disconnect(&dev->port, port_num);
|
||||
else
|
||||
gsmd_ctrl_disconnect(&dev->port, port_num);
|
||||
|
||||
return PTR_ERR(net);
|
||||
}
|
||||
gether_update_dl_max_pkts_per_xfer(&dev->gether_port,
|
||||
rmnet_dl_max_pkt_per_xfer);
|
||||
gether_update_dl_max_xfer_size(&dev->gether_port, 16384);
|
||||
break;
|
||||
case USB_GADGET_XPORT_NONE:
|
||||
break;
|
||||
default:
|
||||
pr_err("%s: Un-supported transport: %s\n", __func__,
|
||||
xport_to_str(dxport));
|
||||
return -ENODEV;
|
||||
dev->ipa_port.cdev = dev->cdev;
|
||||
ipa_data_port_select(USB_IPA_FUNC_RMNET);
|
||||
usb_bam_type = usb_bam_get_bam_type(gadget->name);
|
||||
src_connection_idx = usb_bam_get_connection_idx(usb_bam_type,
|
||||
IPA_P_BAM, USB_TO_PEER_PERIPHERAL, USB_BAM_DEVICE,
|
||||
QTI_PORT_RMNET);
|
||||
dst_connection_idx = usb_bam_get_connection_idx(usb_bam_type,
|
||||
IPA_P_BAM, PEER_PERIPHERAL_TO_USB, USB_BAM_DEVICE,
|
||||
QTI_PORT_RMNET);
|
||||
if (dst_connection_idx < 0 || src_connection_idx < 0) {
|
||||
pr_err("%s: usb_bam_get_connection_idx failed\n",
|
||||
__func__);
|
||||
gqti_ctrl_disconnect(&dev->port, QTI_PORT_RMNET);
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = ipa_data_connect(&dev->ipa_port, USB_IPA_FUNC_RMNET,
|
||||
src_connection_idx, dst_connection_idx);
|
||||
if (ret) {
|
||||
pr_err("%s: ipa_data_connect failed: err:%d\n",
|
||||
__func__, ret);
|
||||
gqti_ctrl_disconnect(&dev->port, QTI_PORT_RMNET);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -504,53 +329,8 @@ static int gport_rmnet_connect(struct f_rmnet *dev, unsigned intf)
|
|||
|
||||
static int gport_rmnet_disconnect(struct f_rmnet *dev)
|
||||
{
|
||||
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;
|
||||
|
||||
pr_debug("%s: ctrl xport: %s data xport: %s dev: %p portno: %d\n",
|
||||
__func__, xport_to_str(cxport), xport_to_str(dxport),
|
||||
dev, dev->port_num);
|
||||
|
||||
port_num = rmnet_ports[dev->port_num].ctrl_xport_num;
|
||||
switch (cxport) {
|
||||
case USB_GADGET_XPORT_SMD:
|
||||
gsmd_ctrl_disconnect(&dev->port, port_num);
|
||||
break;
|
||||
case USB_GADGET_XPORT_QTI:
|
||||
gqti_ctrl_disconnect(&dev->port, port_num);
|
||||
break;
|
||||
case USB_GADGET_XPORT_HSIC:
|
||||
ghsic_ctrl_disconnect(&dev->port, port_num);
|
||||
break;
|
||||
case USB_GADGET_XPORT_NONE:
|
||||
break;
|
||||
default:
|
||||
pr_err("%s: Un-supported transport: %s\n", __func__,
|
||||
xport_to_str(cxport));
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
port_num = rmnet_ports[dev->port_num].data_xport_num;
|
||||
switch (dxport) {
|
||||
case USB_GADGET_XPORT_BAM_DMUX:
|
||||
case USB_GADGET_XPORT_BAM2BAM_IPA:
|
||||
gbam_disconnect(&dev->port, port_num, dxport);
|
||||
break;
|
||||
case USB_GADGET_XPORT_HSIC:
|
||||
ghsic_data_disconnect(&dev->port, port_num);
|
||||
break;
|
||||
case USB_GADGET_XPORT_ETHER:
|
||||
gether_disconnect(&dev->gether_port);
|
||||
break;
|
||||
case USB_GADGET_XPORT_NONE:
|
||||
break;
|
||||
default:
|
||||
pr_err("%s: Un-supported transport: %s\n", __func__,
|
||||
xport_to_str(dxport));
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
gqti_ctrl_disconnect(&dev->port, QTI_PORT_RMNET);
|
||||
ipa_data_disconnect(&dev->ipa_port, USB_IPA_FUNC_RMNET);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -558,7 +338,7 @@ static void frmnet_unbind(struct usb_configuration *c, struct usb_function *f)
|
|||
{
|
||||
struct f_rmnet *dev = func_to_rmnet(f);
|
||||
|
||||
pr_debug("%s: portno:%d\n", __func__, dev->port_num);
|
||||
pr_debug("%s: start unbinding\n", __func__);
|
||||
if (gadget_is_superspeed(c->cdev->gadget))
|
||||
usb_free_descriptors(f->ss_descriptors);
|
||||
if (gadget_is_dualspeed(c->cdev->gadget))
|
||||
|
@ -575,8 +355,7 @@ static void frmnet_purge_responses(struct f_rmnet *dev)
|
|||
unsigned long flags;
|
||||
struct rmnet_ctrl_pkt *cpkt;
|
||||
|
||||
pr_debug("%s: port#%d\n", __func__, dev->port_num);
|
||||
|
||||
pr_debug("%s: Purging responses\n", __func__);
|
||||
spin_lock_irqsave(&dev->lock, flags);
|
||||
while (!list_empty(&dev->cpkt_resp_q)) {
|
||||
cpkt = list_first_entry(&dev->cpkt_resp_q,
|
||||
|
@ -591,117 +370,46 @@ static void frmnet_purge_responses(struct f_rmnet *dev)
|
|||
|
||||
static void frmnet_suspend(struct usb_function *f)
|
||||
{
|
||||
struct f_rmnet *dev = func_to_rmnet(f);
|
||||
unsigned port_num;
|
||||
enum transport_type dxport = rmnet_ports[dev->port_num].data_xport;
|
||||
bool remote_wakeup_allowed;
|
||||
struct f_rmnet *dev = func_to_rmnet(f);
|
||||
bool remote_wakeup_allowed;
|
||||
|
||||
if (f->config->cdev->gadget->speed == USB_SPEED_SUPER)
|
||||
remote_wakeup_allowed = f->func_wakeup_allowed;
|
||||
else
|
||||
remote_wakeup_allowed = f->config->cdev->gadget->remote_wakeup;
|
||||
|
||||
pr_debug("%s: data xport: %s dev: %p portno: %d remote_wakeup: %d\n",
|
||||
__func__, xport_to_str(dxport),
|
||||
dev, dev->port_num, remote_wakeup_allowed);
|
||||
pr_debug("%s: dev: %p remote_wakeup: %d\n",
|
||||
__func__, dev, remote_wakeup_allowed);
|
||||
|
||||
usb_ep_fifo_flush(dev->notify);
|
||||
frmnet_purge_responses(dev);
|
||||
|
||||
port_num = rmnet_ports[dev->port_num].data_xport_num;
|
||||
switch (dxport) {
|
||||
case USB_GADGET_XPORT_BAM_DMUX:
|
||||
break;
|
||||
case USB_GADGET_XPORT_BAM2BAM_IPA:
|
||||
if (remote_wakeup_allowed) {
|
||||
gbam_suspend(&dev->port, port_num, dxport);
|
||||
} else {
|
||||
/*
|
||||
* When remote wakeup is disabled, IPA is disconnected
|
||||
* because it cannot send new data until the USB bus is
|
||||
* resumed. Endpoint descriptors info is saved before it
|
||||
* gets reset by the BAM disconnect API. This lets us
|
||||
* restore this info when the USB bus is resumed.
|
||||
*/
|
||||
dev->in_ep_desc_backup = dev->port.in->desc;
|
||||
dev->out_ep_desc_backup = dev->port.out->desc;
|
||||
pr_debug("in_ep_desc_bkup = %p, out_ep_desc_bkup = %p",
|
||||
dev->in_ep_desc_backup, dev->out_ep_desc_backup);
|
||||
pr_debug("%s(): Disconnecting\n", __func__);
|
||||
gport_rmnet_disconnect(dev);
|
||||
}
|
||||
break;
|
||||
case USB_GADGET_XPORT_HSIC:
|
||||
break;
|
||||
case USB_GADGET_XPORT_HSUART:
|
||||
break;
|
||||
case USB_GADGET_XPORT_ETHER:
|
||||
break;
|
||||
case USB_GADGET_XPORT_NONE:
|
||||
break;
|
||||
default:
|
||||
pr_err("%s: Un-supported transport: %s\n", __func__,
|
||||
xport_to_str(dxport));
|
||||
}
|
||||
ipa_data_suspend(&dev->ipa_port, USB_IPA_FUNC_RMNET,
|
||||
remote_wakeup_allowed);
|
||||
}
|
||||
|
||||
static void frmnet_resume(struct usb_function *f)
|
||||
{
|
||||
struct f_rmnet *dev = func_to_rmnet(f);
|
||||
unsigned port_num;
|
||||
enum transport_type dxport = rmnet_ports[dev->port_num].data_xport;
|
||||
int ret;
|
||||
bool remote_wakeup_allowed;
|
||||
struct f_rmnet *dev = func_to_rmnet(f);
|
||||
bool remote_wakeup_allowed;
|
||||
|
||||
if (f->config->cdev->gadget->speed == USB_SPEED_SUPER)
|
||||
remote_wakeup_allowed = f->func_wakeup_allowed;
|
||||
else
|
||||
remote_wakeup_allowed = f->config->cdev->gadget->remote_wakeup;
|
||||
|
||||
pr_debug("%s: data xport: %s dev: %p portno: %d remote_wakeup: %d\n",
|
||||
__func__, xport_to_str(dxport),
|
||||
dev, dev->port_num, remote_wakeup_allowed);
|
||||
pr_debug("%s: dev: %p remote_wakeup: %d\n",
|
||||
__func__, dev, remote_wakeup_allowed);
|
||||
|
||||
port_num = rmnet_ports[dev->port_num].data_xport_num;
|
||||
switch (dxport) {
|
||||
case USB_GADGET_XPORT_BAM_DMUX:
|
||||
break;
|
||||
case USB_GADGET_XPORT_BAM2BAM_IPA:
|
||||
if (remote_wakeup_allowed) {
|
||||
gbam_resume(&dev->port, port_num, dxport);
|
||||
} else {
|
||||
dev->port.in->desc = dev->in_ep_desc_backup;
|
||||
dev->port.out->desc = dev->out_ep_desc_backup;
|
||||
pr_debug("%s(): Connecting\n", __func__);
|
||||
ret = gport_rmnet_connect(dev, dev->ifc_id);
|
||||
if (ret) {
|
||||
pr_err("%s: gport_rmnet_connect failed: err:%d\n",
|
||||
__func__, ret);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case USB_GADGET_XPORT_HSIC:
|
||||
break;
|
||||
case USB_GADGET_XPORT_HSUART:
|
||||
break;
|
||||
case USB_GADGET_XPORT_ETHER:
|
||||
break;
|
||||
case USB_GADGET_XPORT_NONE:
|
||||
break;
|
||||
default:
|
||||
pr_err("%s: Un-supported transport: %s\n", __func__,
|
||||
xport_to_str(dxport));
|
||||
}
|
||||
ipa_data_resume(&dev->ipa_port, USB_IPA_FUNC_RMNET,
|
||||
remote_wakeup_allowed);
|
||||
}
|
||||
|
||||
static void frmnet_disable(struct usb_function *f)
|
||||
{
|
||||
struct f_rmnet *dev = func_to_rmnet(f);
|
||||
enum transport_type dxport = rmnet_ports[dev->port_num].data_xport;
|
||||
struct usb_composite_dev *cdev = dev->cdev;
|
||||
|
||||
pr_debug("%s: port#%d\n", __func__, dev->port_num);
|
||||
struct f_rmnet *dev = func_to_rmnet(f);
|
||||
|
||||
pr_debug("%s: Disabling\n", __func__);
|
||||
usb_ep_disable(dev->notify);
|
||||
dev->notify->driver_data = NULL;
|
||||
|
||||
|
@ -709,11 +417,8 @@ static void frmnet_disable(struct usb_function *f)
|
|||
|
||||
frmnet_purge_responses(dev);
|
||||
|
||||
if (dxport == USB_GADGET_XPORT_BAM2BAM_IPA &&
|
||||
gadget_is_dwc3(cdev->gadget)) {
|
||||
msm_ep_unconfig(dev->port.out);
|
||||
msm_ep_unconfig(dev->port.in);
|
||||
}
|
||||
msm_ep_unconfig(dev->ipa_port.out);
|
||||
msm_ep_unconfig(dev->ipa_port.in);
|
||||
gport_rmnet_disconnect(dev);
|
||||
}
|
||||
|
||||
|
@ -723,12 +428,11 @@ frmnet_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
|
|||
struct f_rmnet *dev = func_to_rmnet(f);
|
||||
struct usb_composite_dev *cdev = dev->cdev;
|
||||
int ret;
|
||||
struct list_head *cpkt;
|
||||
|
||||
pr_debug("%s:dev:%p port#%d\n", __func__, dev, dev->port_num);
|
||||
struct list_head *cpkt;
|
||||
|
||||
pr_debug("%s: dev: %p\n", __func__, dev);
|
||||
if (dev->notify->driver_data) {
|
||||
pr_debug("%s: reset port:%d\n", __func__, dev->port_num);
|
||||
pr_debug("%s: reset port\n", __func__);
|
||||
usb_ep_disable(dev->notify);
|
||||
}
|
||||
|
||||
|
@ -749,14 +453,14 @@ frmnet_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
|
|||
}
|
||||
dev->notify->driver_data = dev;
|
||||
|
||||
if (!dev->port.in->desc || !dev->port.out->desc) {
|
||||
if (config_ep_by_speed(cdev->gadget, f, dev->port.in) ||
|
||||
config_ep_by_speed(cdev->gadget, f, dev->port.out)) {
|
||||
if (!dev->ipa_port.in->desc || !dev->ipa_port.out->desc) {
|
||||
if (config_ep_by_speed(cdev->gadget, f, dev->ipa_port.in) ||
|
||||
config_ep_by_speed(cdev->gadget, f, dev->ipa_port.out)) {
|
||||
pr_err("%s(): config_ep_by_speed failed.\n", __func__);
|
||||
ret = -EINVAL;
|
||||
goto err_disable_ep;
|
||||
}
|
||||
dev->port.gadget = dev->cdev->gadget;
|
||||
dev->ipa_port.cdev = dev->cdev;
|
||||
}
|
||||
|
||||
ret = gport_rmnet_connect(dev, intf);
|
||||
|
@ -777,8 +481,8 @@ frmnet_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
|
|||
|
||||
return ret;
|
||||
err_disable_ep:
|
||||
dev->port.in->desc = NULL;
|
||||
dev->port.out->desc = NULL;
|
||||
dev->ipa_port.in->desc = NULL;
|
||||
dev->ipa_port.out->desc = NULL;
|
||||
usb_ep_disable(dev->notify);
|
||||
|
||||
return ret;
|
||||
|
@ -790,10 +494,9 @@ static void frmnet_ctrl_response_available(struct f_rmnet *dev)
|
|||
struct usb_cdc_notification *event;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
struct rmnet_ctrl_pkt *cpkt;
|
||||
|
||||
pr_debug("%s:dev:%p portno#%d\n", __func__, dev, dev->port_num);
|
||||
struct rmnet_ctrl_pkt *cpkt;
|
||||
|
||||
pr_debug("%s: dev: %p\n", __func__, dev);
|
||||
spin_lock_irqsave(&dev->lock, flags);
|
||||
if (!atomic_read(&dev->online) || !req || !req->buf) {
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
|
@ -913,8 +616,7 @@ frmnet_send_cpkt_response(void *gr, void *buf, size_t len)
|
|||
|
||||
dev = port_to_rmnet(gr);
|
||||
|
||||
pr_debug("%s: dev:%p port#%d\n", __func__, dev, dev->port_num);
|
||||
|
||||
pr_debug("%s: dev: %p\n", __func__, dev);
|
||||
if (!atomic_read(&dev->online) || !atomic_read(&dev->ctrl_online)) {
|
||||
rmnet_free_ctrl_pkt(cpkt);
|
||||
return 0;
|
||||
|
@ -934,32 +636,27 @@ frmnet_cmd_complete(struct usb_ep *ep, struct usb_request *req)
|
|||
{
|
||||
struct f_rmnet *dev = req->context;
|
||||
struct usb_composite_dev *cdev;
|
||||
unsigned port_num;
|
||||
|
||||
if (!dev) {
|
||||
pr_err("%s: rmnet dev is null\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
pr_debug("%s: dev:%p port#%d\n", __func__, dev, dev->port_num);
|
||||
|
||||
pr_debug("%s: dev: %p\n", __func__, dev);
|
||||
cdev = dev->cdev;
|
||||
|
||||
if (dev->port.send_encap_cmd) {
|
||||
port_num = rmnet_ports[dev->port_num].ctrl_xport_num;
|
||||
dev->port.send_encap_cmd(port_num, req->buf, req->actual);
|
||||
dev->port.send_encap_cmd(QTI_PORT_RMNET, req->buf, req->actual);
|
||||
}
|
||||
}
|
||||
|
||||
static void frmnet_notify_complete(struct usb_ep *ep, struct usb_request *req)
|
||||
{
|
||||
struct f_rmnet *dev = req->context;
|
||||
int status = req->status;
|
||||
struct f_rmnet *dev = req->context;
|
||||
int status = req->status;
|
||||
unsigned long flags;
|
||||
struct rmnet_ctrl_pkt *cpkt;
|
||||
|
||||
pr_debug("%s: dev:%p port#%d\n", __func__, dev, dev->port_num);
|
||||
|
||||
pr_debug("%s: dev: %p\n", __func__, dev);
|
||||
switch (status) {
|
||||
case -ECONNRESET:
|
||||
case -ESHUTDOWN:
|
||||
|
@ -1021,14 +718,12 @@ frmnet_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
|
|||
struct f_rmnet *dev = func_to_rmnet(f);
|
||||
struct usb_composite_dev *cdev = dev->cdev;
|
||||
struct usb_request *req = cdev->req;
|
||||
unsigned port_num;
|
||||
u16 w_index = le16_to_cpu(ctrl->wIndex);
|
||||
u16 w_value = le16_to_cpu(ctrl->wValue);
|
||||
u16 w_length = le16_to_cpu(ctrl->wLength);
|
||||
int ret = -EOPNOTSUPP;
|
||||
|
||||
pr_debug("%s:dev:%p port#%d\n", __func__, dev, dev->port_num);
|
||||
|
||||
pr_debug("%s: dev: %p\n", __func__, dev);
|
||||
if (!atomic_read(&dev->online)) {
|
||||
pr_warn("%s: usb cable is not connected\n", __func__);
|
||||
return -ENOTCONN;
|
||||
|
@ -1085,8 +780,8 @@ frmnet_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
|
|||
pr_debug("%s: USB_CDC_REQ_SET_CONTROL_LINE_STATE: DTR:%d\n",
|
||||
__func__, w_value & ACM_CTRL_DTR ? 1 : 0);
|
||||
if (dev->port.notify_modem) {
|
||||
port_num = rmnet_ports[dev->port_num].ctrl_xport_num;
|
||||
dev->port.notify_modem(&dev->port, port_num, w_value);
|
||||
dev->port.notify_modem(&dev->port,
|
||||
QTI_PORT_RMNET, w_value);
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
|
@ -1135,9 +830,7 @@ static int frmnet_bind(struct usb_configuration *c, struct usb_function *f)
|
|||
pr_err("%s: usb epin autoconfig failed\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
dev->port.in = ep;
|
||||
/* Update same for u_ether which uses gether port struct */
|
||||
dev->gether_port.in_ep = ep;
|
||||
dev->ipa_port.in = ep;
|
||||
ep->driver_data = cdev;
|
||||
|
||||
ep = usb_ep_autoconfig(cdev->gadget, &rmnet_fs_out_desc);
|
||||
|
@ -1146,9 +839,7 @@ static int frmnet_bind(struct usb_configuration *c, struct usb_function *f)
|
|||
ret = -ENODEV;
|
||||
goto ep_auto_out_fail;
|
||||
}
|
||||
dev->port.out = ep;
|
||||
/* Update same for u_ether which uses gether port struct */
|
||||
dev->gether_port.out_ep = ep;
|
||||
dev->ipa_port.out = ep;
|
||||
ep->driver_data = cdev;
|
||||
|
||||
ep = usb_ep_autoconfig(cdev->gadget, &rmnet_fs_notify_desc);
|
||||
|
@ -1162,7 +853,6 @@ static int frmnet_bind(struct usb_configuration *c, struct usb_function *f)
|
|||
|
||||
dev->notify_req = frmnet_alloc_req(ep,
|
||||
sizeof(struct usb_cdc_notification),
|
||||
cdev->gadget->extra_buf_alloc,
|
||||
GFP_KERNEL);
|
||||
if (IS_ERR(dev->notify_req)) {
|
||||
pr_err("%s: unable to allocate memory for notify req\n",
|
||||
|
@ -1218,10 +908,9 @@ static int frmnet_bind(struct usb_configuration *c, struct usb_function *f)
|
|||
}
|
||||
}
|
||||
|
||||
pr_debug("%s: RmNet(%d) %s Speed, IN:%s OUT:%s\n",
|
||||
__func__, dev->port_num,
|
||||
gadget_is_dualspeed(cdev->gadget) ? "dual" : "full",
|
||||
dev->port.in->name, dev->port.out->name);
|
||||
pr_debug("%s: RmNet %s Speed, IN:%s OUT:%s\n",
|
||||
__func__, gadget_is_dualspeed(cdev->gadget) ? "dual" : "full",
|
||||
dev->ipa_port.in->name, dev->ipa_port.out->name);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -1238,16 +927,16 @@ ep_notify_alloc_fail:
|
|||
dev->notify->driver_data = NULL;
|
||||
dev->notify = NULL;
|
||||
ep_auto_notify_fail:
|
||||
dev->port.out->driver_data = NULL;
|
||||
dev->port.out = NULL;
|
||||
dev->ipa_port.out->driver_data = NULL;
|
||||
dev->ipa_port.out = NULL;
|
||||
ep_auto_out_fail:
|
||||
dev->port.in->driver_data = NULL;
|
||||
dev->port.in = NULL;
|
||||
dev->ipa_port.in->driver_data = NULL;
|
||||
dev->ipa_port.in = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int frmnet_bind_config(struct usb_configuration *c, unsigned portno)
|
||||
static int frmnet_bind_config(struct usb_configuration *c)
|
||||
{
|
||||
int status;
|
||||
struct f_rmnet *dev;
|
||||
|
@ -1255,32 +944,7 @@ static int frmnet_bind_config(struct usb_configuration *c, unsigned portno)
|
|||
unsigned long flags;
|
||||
|
||||
pr_debug("%s: usb config:%p\n", __func__, c);
|
||||
|
||||
if (portno >= nr_rmnet_ports) {
|
||||
pr_err("%s: supporting ports#%u port_id:%u\n", __func__,
|
||||
nr_rmnet_ports, portno);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
dev = rmnet_ports[portno].port;
|
||||
|
||||
if (rmnet_ports[portno].data_xport == USB_GADGET_XPORT_ETHER) {
|
||||
struct net_device *net = gether_setup_name_default("usb_rmnet");
|
||||
|
||||
if (IS_ERR(net)) {
|
||||
pr_err("%s: gether_setup failed\n", __func__);
|
||||
return PTR_ERR(net);
|
||||
}
|
||||
dev->gether_port.ioport = netdev_priv(net);
|
||||
gether_set_gadget(net, c->cdev->gadget);
|
||||
status = gether_register_netdev(net);
|
||||
if (status < 0) {
|
||||
pr_err("%s: gether_register_netdev failed\n", __func__);
|
||||
free_netdev(net);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
dev = &rmnet_port;
|
||||
if (rmnet_string_defs[0].id == 0) {
|
||||
status = usb_string_id(c->cdev);
|
||||
if (status < 0) {
|
||||
|
@ -1293,8 +957,8 @@ static int frmnet_bind_config(struct usb_configuration *c, unsigned portno)
|
|||
|
||||
spin_lock_irqsave(&dev->lock, flags);
|
||||
dev->cdev = c->cdev;
|
||||
f = &dev->gether_port.func;
|
||||
f->name = kasprintf(GFP_ATOMIC, "rmnet%d", portno);
|
||||
f = &dev->func;
|
||||
f->name = kasprintf(GFP_ATOMIC, "rmnet%d", 0);
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
if (!f->name) {
|
||||
pr_err("%s: cannot allocate memory for name\n", __func__);
|
||||
|
@ -1312,7 +976,6 @@ static int frmnet_bind_config(struct usb_configuration *c, unsigned portno)
|
|||
dev->port.send_cpkt_response = frmnet_send_cpkt_response;
|
||||
dev->port.disconnect = frmnet_disconnect;
|
||||
dev->port.connect = frmnet_connect;
|
||||
dev->gether_port.cdc_filter = 0;
|
||||
|
||||
status = usb_add_function(c, f);
|
||||
if (status) {
|
||||
|
@ -1327,17 +990,6 @@ static int frmnet_bind_config(struct usb_configuration *c, unsigned portno)
|
|||
return status;
|
||||
}
|
||||
|
||||
static void frmnet_unbind_config(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nr_rmnet_ports; i++)
|
||||
if (rmnet_ports[i].data_xport == USB_GADGET_XPORT_ETHER) {
|
||||
gether_cleanup(rmnet_ports[i].port->gether_port.ioport);
|
||||
rmnet_ports[i].port->gether_port.ioport = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int rmnet_init(void)
|
||||
{
|
||||
return gqti_ctrl_init();
|
||||
|
@ -1345,130 +997,25 @@ static int rmnet_init(void)
|
|||
|
||||
static void frmnet_cleanup(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
gqti_ctrl_cleanup();
|
||||
|
||||
for (i = 0; i < nr_rmnet_ports; i++)
|
||||
kfree(rmnet_ports[i].port);
|
||||
|
||||
gbam_cleanup();
|
||||
nr_rmnet_ports = 0;
|
||||
no_ctrl_smd_ports = 0;
|
||||
no_ctrl_qti_ports = 0;
|
||||
no_data_bam_ports = 0;
|
||||
no_data_bam2bam_ports = 0;
|
||||
no_ctrl_hsic_ports = 0;
|
||||
no_data_hsic_ports = 0;
|
||||
no_ctrl_hsuart_ports = 0;
|
||||
no_data_hsuart_ports = 0;
|
||||
kfree(&rmnet_port);
|
||||
}
|
||||
|
||||
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;
|
||||
int ret;
|
||||
int i;
|
||||
struct f_rmnet *dev;
|
||||
|
||||
if (nr_rmnet_ports >= NR_RMNET_PORTS) {
|
||||
pr_err("%s: Max-%d instances supported\n",
|
||||
__func__, NR_RMNET_PORTS);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pr_debug("%s: port#:%d, ctrl port: %s data port: %s\n",
|
||||
__func__, nr_rmnet_ports, ctrl_name, data_name);
|
||||
pr_debug("%s: ctrl port: %s data port: %s\n",
|
||||
__func__, ctrl_name, data_name);
|
||||
|
||||
dev = kzalloc(sizeof(struct f_rmnet), GFP_KERNEL);
|
||||
if (!dev)
|
||||
return -ENOMEM;
|
||||
|
||||
dev->port_num = nr_rmnet_ports;
|
||||
spin_lock_init(&dev->lock);
|
||||
INIT_LIST_HEAD(&dev->cpkt_resp_q);
|
||||
|
||||
rmnet_port = &rmnet_ports[nr_rmnet_ports];
|
||||
rmnet_port->port = dev;
|
||||
rmnet_port->port_num = nr_rmnet_ports;
|
||||
rmnet_port->ctrl_xport = str_to_xport(ctrl_name);
|
||||
rmnet_port->data_xport = str_to_xport(data_name);
|
||||
|
||||
switch (rmnet_port->ctrl_xport) {
|
||||
case USB_GADGET_XPORT_SMD:
|
||||
rmnet_port->ctrl_xport_num = no_ctrl_smd_ports;
|
||||
no_ctrl_smd_ports++;
|
||||
break;
|
||||
case USB_GADGET_XPORT_QTI:
|
||||
rmnet_port->ctrl_xport_num = no_ctrl_qti_ports;
|
||||
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;
|
||||
case USB_GADGET_XPORT_HSUART:
|
||||
rmnet_port->ctrl_xport_num = no_ctrl_hsuart_ports;
|
||||
no_ctrl_hsuart_ports++;
|
||||
break;
|
||||
case USB_GADGET_XPORT_NONE:
|
||||
break;
|
||||
default:
|
||||
pr_err("%s: Un-supported transport: %u\n", __func__,
|
||||
rmnet_port->ctrl_xport);
|
||||
ret = -ENODEV;
|
||||
goto fail_probe;
|
||||
}
|
||||
|
||||
switch (rmnet_port->data_xport) {
|
||||
case USB_GADGET_XPORT_BAM2BAM:
|
||||
/* Override BAM2BAM to BAM_DMUX for old ABI compatibility */
|
||||
rmnet_port->data_xport = USB_GADGET_XPORT_BAM_DMUX;
|
||||
/* fall-through */
|
||||
case USB_GADGET_XPORT_BAM_DMUX:
|
||||
rmnet_port->data_xport_num = no_data_bam_ports;
|
||||
no_data_bam_ports++;
|
||||
break;
|
||||
case USB_GADGET_XPORT_BAM2BAM_IPA:
|
||||
rmnet_port->data_xport_num = no_data_bam2bam_ports;
|
||||
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;
|
||||
case USB_GADGET_XPORT_HSUART:
|
||||
rmnet_port->data_xport_num = no_data_hsuart_ports;
|
||||
no_data_hsuart_ports++;
|
||||
break;
|
||||
case USB_GADGET_XPORT_ETHER:
|
||||
case USB_GADGET_XPORT_NONE:
|
||||
break;
|
||||
default:
|
||||
pr_err("%s: Un-supported transport: %u\n", __func__,
|
||||
rmnet_port->data_xport);
|
||||
ret = -ENODEV;
|
||||
goto fail_probe;
|
||||
}
|
||||
nr_rmnet_ports++;
|
||||
rmnet_port = *dev;
|
||||
|
||||
return 0;
|
||||
|
||||
fail_probe:
|
||||
for (i = 0; i < nr_rmnet_ports; i++)
|
||||
kfree(rmnet_ports[i].port);
|
||||
|
||||
nr_rmnet_ports = 0;
|
||||
no_ctrl_smd_ports = 0;
|
||||
no_ctrl_qti_ports = 0;
|
||||
no_data_bam_ports = 0;
|
||||
no_ctrl_hsic_ports = 0;
|
||||
no_data_hsic_ports = 0;
|
||||
no_ctrl_hsuart_ports = 0;
|
||||
no_data_hsuart_ports = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -14,11 +14,11 @@
|
|||
#include <linux/wait.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/usb/usb_ctrl_qti.h>
|
||||
|
||||
#include <soc/qcom/bam_dmux.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/debugfs.h>
|
||||
|
||||
#include "u_rmnet.h"
|
||||
#include "usb_gadget_xport.h"
|
||||
#include "f_qdss.h"
|
||||
|
||||
#define RMNET_CTRL_QTI_NAME "rmnet_ctrl"
|
||||
#define DPL_CTRL_QTI_NAME "dpl_ctrl"
|
||||
|
@ -54,18 +54,18 @@ struct qti_ctrl_port {
|
|||
struct list_head cpkt_req_q;
|
||||
|
||||
spinlock_t lock;
|
||||
enum gadget_type gtype;
|
||||
enum qti_port_type port_type;
|
||||
unsigned host_to_modem;
|
||||
unsigned copied_to_modem;
|
||||
unsigned copied_from_modem;
|
||||
unsigned modem_to_host;
|
||||
unsigned drp_cpkt_cnt;
|
||||
};
|
||||
static struct qti_ctrl_port *ctrl_port[NR_QTI_PORTS];
|
||||
static struct qti_ctrl_port *ctrl_port[QTI_NUM_PORTS];
|
||||
|
||||
static inline int qti_ctrl_lock(atomic_t *excl)
|
||||
{
|
||||
if (atomic_inc_return(excl) == 1) {
|
||||
if (atomic_inc_return(excl) == 1)
|
||||
return 0;
|
||||
atomic_dec(excl);
|
||||
return -EBUSY;
|
||||
|
@ -76,6 +76,32 @@ static inline void qti_ctrl_unlock(atomic_t *excl)
|
|||
atomic_dec(excl);
|
||||
}
|
||||
|
||||
static struct rmnet_ctrl_pkt *alloc_rmnet_ctrl_pkt(unsigned len, gfp_t flags)
|
||||
{
|
||||
struct rmnet_ctrl_pkt *pkt;
|
||||
|
||||
pkt = kzalloc(sizeof(struct rmnet_ctrl_pkt), flags);
|
||||
if (!pkt)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
pkt->buf = kmalloc(len, flags);
|
||||
if (!pkt->buf) {
|
||||
kfree(pkt);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
pkt->len = len;
|
||||
|
||||
return pkt;
|
||||
}
|
||||
|
||||
static void free_rmnet_ctrl_pkt(struct rmnet_ctrl_pkt *pkt)
|
||||
{
|
||||
kfree(pkt->buf);
|
||||
kfree(pkt);
|
||||
}
|
||||
|
||||
|
||||
static void qti_ctrl_queue_notify(struct qti_ctrl_port *port)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
@ -106,7 +132,8 @@ static void qti_ctrl_queue_notify(struct qti_ctrl_port *port)
|
|||
wake_up(&port->read_wq);
|
||||
}
|
||||
|
||||
static int gqti_ctrl_send_cpkt_tomodem(u8 portno, void *buf, size_t len)
|
||||
static int gqti_ctrl_send_cpkt_tomodem(enum qti_port_type qport,
|
||||
void *buf, size_t len)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct qti_ctrl_port *port;
|
||||
|
@ -118,12 +145,11 @@ static int gqti_ctrl_send_cpkt_tomodem(u8 portno, void *buf, size_t len)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (portno >= NR_QTI_PORTS) {
|
||||
pr_err("%s: Invalid QTI port %d\n", __func__, portno);
|
||||
if (qport >= QTI_NUM_PORTS) {
|
||||
pr_err("%s: Invalid QTI port %d\n", __func__, qport);
|
||||
return -ENODEV;
|
||||
}
|
||||
port = ctrl_port[portno];
|
||||
|
||||
port = ctrl_port[qport];
|
||||
cpkt = alloc_rmnet_ctrl_pkt(len, GFP_ATOMIC);
|
||||
if (IS_ERR(cpkt)) {
|
||||
pr_err("%s: Unable to allocate ctrl pkt\n", __func__);
|
||||
|
@ -133,8 +159,8 @@ static int gqti_ctrl_send_cpkt_tomodem(u8 portno, void *buf, size_t len)
|
|||
memcpy(cpkt->buf, buf, len);
|
||||
cpkt->len = len;
|
||||
|
||||
pr_debug("%s: gtype:%d: Add to cpkt_req_q packet with len = %zu\n",
|
||||
__func__, port->gtype, len);
|
||||
pr_debug("%s: port type:%d: Add to cpkt_req_q packet with len = %zu\n",
|
||||
__func__, port->port_type, len);
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
|
||||
/* drop cpkt if port is not open */
|
||||
|
@ -159,71 +185,51 @@ static int gqti_ctrl_send_cpkt_tomodem(u8 portno, void *buf, size_t len)
|
|||
}
|
||||
|
||||
static void
|
||||
gqti_ctrl_notify_modem(void *gptr, u8 portno, int val)
|
||||
gqti_ctrl_notify_modem(void *gptr, enum qti_port_type qport, int val)
|
||||
{
|
||||
struct qti_ctrl_port *port;
|
||||
|
||||
if (portno >= NR_QTI_PORTS) {
|
||||
pr_err("%s: Invalid QTI port %d\n", __func__, portno);
|
||||
if (qport >= QTI_NUM_PORTS) {
|
||||
pr_err("%s: Invalid QTI port %d\n", __func__, qport);
|
||||
return;
|
||||
}
|
||||
port = ctrl_port[portno];
|
||||
|
||||
port = ctrl_port[qport];
|
||||
atomic_set(&port->line_state, val);
|
||||
|
||||
/* send 0 len pkt to qti to notify state change */
|
||||
qti_ctrl_queue_notify(port);
|
||||
}
|
||||
|
||||
int gqti_ctrl_connect(void *gr, u8 port_num, unsigned intf,
|
||||
enum transport_type dxport, enum gadget_type gtype)
|
||||
int gqti_ctrl_connect(void *gr, enum qti_port_type qport, unsigned intf)
|
||||
{
|
||||
struct qti_ctrl_port *port;
|
||||
struct grmnet *g_rmnet = NULL;
|
||||
struct gqdss *g_dpl = NULL;
|
||||
unsigned long flags;
|
||||
|
||||
pr_debug("%s: gtype:%d gadget:%p\n", __func__, gtype, gr);
|
||||
if (port_num >= NR_QTI_PORTS) {
|
||||
pr_err("%s: Invalid QTI port %d\n", __func__, port_num);
|
||||
pr_debug("%s: port type:%d gadget:%p\n", __func__, qport, gr);
|
||||
if (qport >= QTI_NUM_PORTS) {
|
||||
pr_err("%s: Invalid QTI port %d\n", __func__, qport);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
port = ctrl_port[port_num];
|
||||
port = ctrl_port[qport];
|
||||
if (!port) {
|
||||
pr_err("%s: gadget port is null\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
port->gtype = gtype;
|
||||
if (dxport == USB_GADGET_XPORT_BAM_DMUX) {
|
||||
/*
|
||||
* BAM-DMUX data transport is used for RMNET and DPL
|
||||
* on some targets where IPA is not available.
|
||||
* Set endpoint type as BAM-DMUX and interface
|
||||
* id as channel number. This information is
|
||||
* sent to user space via EP_LOOKUP ioctl.
|
||||
*
|
||||
*/
|
||||
port->port_type = qport;
|
||||
port->ep_type = DATA_EP_TYPE_HSUSB;
|
||||
port->intf = intf;
|
||||
|
||||
port->ep_type = DATA_EP_TYPE_BAM_DMUX;
|
||||
port->intf = (gtype == USB_GADGET_RMNET) ?
|
||||
BAM_DMUX_USB_RMNET_0 :
|
||||
BAM_DMUX_USB_DPL;
|
||||
port->ipa_prod_idx = 0;
|
||||
port->ipa_cons_idx = 0;
|
||||
} else {
|
||||
port->ep_type = DATA_EP_TYPE_HSUSB;
|
||||
port->intf = intf;
|
||||
}
|
||||
|
||||
if (gr && port->gtype == USB_GADGET_RMNET) {
|
||||
if (gr && port->port_type == QTI_PORT_RMNET) {
|
||||
port->port_usb = gr;
|
||||
g_rmnet = (struct grmnet *)gr;
|
||||
g_rmnet->send_encap_cmd = gqti_ctrl_send_cpkt_tomodem;
|
||||
g_rmnet->notify_modem = gqti_ctrl_notify_modem;
|
||||
} else if (gr && port->gtype == USB_GADGET_DPL) {
|
||||
} else if (gr && port->port_type == QTI_PORT_DPL) {
|
||||
port->port_usb = gr;
|
||||
g_dpl = (struct gqdss *)gr;
|
||||
g_dpl->send_encap_cmd = gqti_ctrl_send_cpkt_tomodem;
|
||||
|
@ -231,7 +237,7 @@ int gqti_ctrl_connect(void *gr, u8 port_num, unsigned intf,
|
|||
atomic_set(&port->line_state, 1);
|
||||
} else {
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
pr_err("%s(): Port is used without gtype.\n", __func__);
|
||||
pr_err("%s(): Port is used without port type.\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -251,7 +257,7 @@ int gqti_ctrl_connect(void *gr, u8 port_num, unsigned intf,
|
|||
return 0;
|
||||
}
|
||||
|
||||
void gqti_ctrl_disconnect(void *gr, u8 port_num)
|
||||
void gqti_ctrl_disconnect(void *gr, enum qti_port_type qport)
|
||||
{
|
||||
struct qti_ctrl_port *port;
|
||||
unsigned long flags;
|
||||
|
@ -261,13 +267,12 @@ void gqti_ctrl_disconnect(void *gr, u8 port_num)
|
|||
|
||||
pr_debug("%s: gadget:%p\n", __func__, gr);
|
||||
|
||||
if (port_num >= NR_QTI_PORTS) {
|
||||
pr_err("%s: Invalid QTI port %d\n", __func__, port_num);
|
||||
if (qport >= QTI_NUM_PORTS) {
|
||||
pr_err("%s: Invalid QTI port %d\n", __func__, qport);
|
||||
return;
|
||||
}
|
||||
|
||||
port = ctrl_port[port_num];
|
||||
|
||||
port = ctrl_port[qport];
|
||||
if (!port) {
|
||||
pr_err("%s: gadget port is null\n", __func__);
|
||||
return;
|
||||
|
@ -282,17 +287,17 @@ void gqti_ctrl_disconnect(void *gr, u8 port_num)
|
|||
port->ipa_cons_idx = -1;
|
||||
port->port_usb = NULL;
|
||||
|
||||
if (gr && port->gtype == USB_GADGET_RMNET) {
|
||||
if (gr && port->port_type == QTI_PORT_RMNET) {
|
||||
g_rmnet = (struct grmnet *)gr;
|
||||
g_rmnet->send_encap_cmd = NULL;
|
||||
g_rmnet->notify_modem = NULL;
|
||||
} else if (gr && port->gtype == USB_GADGET_DPL) {
|
||||
} else if (gr && port->port_type == QTI_PORT_DPL) {
|
||||
g_dpl = (struct gqdss *)gr;
|
||||
g_dpl->send_encap_cmd = NULL;
|
||||
g_dpl->notify_modem = NULL;
|
||||
} else {
|
||||
pr_err("%s(): unrecognized gadget type(%d).\n",
|
||||
__func__, port->gtype);
|
||||
__func__, port->port_type);
|
||||
}
|
||||
|
||||
while (!list_empty(&port->cpkt_req_q)) {
|
||||
|
@ -309,18 +314,17 @@ void gqti_ctrl_disconnect(void *gr, u8 port_num)
|
|||
qti_ctrl_queue_notify(port);
|
||||
}
|
||||
|
||||
void gqti_ctrl_update_ipa_pipes(void *gr, u8 port_num, u32 ipa_prod,
|
||||
u32 ipa_cons)
|
||||
void gqti_ctrl_update_ipa_pipes(void *gr, enum qti_port_type qport,
|
||||
u32 ipa_prod, u32 ipa_cons)
|
||||
{
|
||||
struct qti_ctrl_port *port;
|
||||
|
||||
if (port_num >= NR_QTI_PORTS) {
|
||||
pr_err("%s: Invalid QTI port %d\n", __func__, port_num);
|
||||
if (qport >= QTI_NUM_PORTS) {
|
||||
pr_err("%s: Invalid QTI port %d\n", __func__, qport);
|
||||
return;
|
||||
}
|
||||
|
||||
port = ctrl_port[port_num];
|
||||
|
||||
port = ctrl_port[qport];
|
||||
port->ipa_prod_idx = ipa_prod;
|
||||
port->ipa_cons_idx = ipa_cons;
|
||||
|
||||
|
@ -492,12 +496,12 @@ qti_ctrl_write(struct file *fp, const char __user *buf, size_t count,
|
|||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
if (port && port->port_usb) {
|
||||
if (port->gtype == USB_GADGET_RMNET) {
|
||||
if (port->port_type == QTI_PORT_RMNET) {
|
||||
g_rmnet = (struct grmnet *)port->port_usb;
|
||||
} else {
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
pr_err("%s(): unrecognized gadget type(%d).\n",
|
||||
__func__, port->gtype);
|
||||
__func__, port->port_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -530,15 +534,15 @@ static long qti_ctrl_ioctl(struct file *fp, unsigned cmd, unsigned long arg)
|
|||
struct ep_info info;
|
||||
int val, ret = 0;
|
||||
|
||||
pr_debug("%s: Received command %d for gtype:%d\n",
|
||||
__func__, cmd, port->gtype);
|
||||
pr_debug("%s: Received command %d for port type:%d\n",
|
||||
__func__, cmd, port->port_type);
|
||||
|
||||
if (qti_ctrl_lock(&port->ioctl_excl))
|
||||
return -EBUSY;
|
||||
|
||||
switch (cmd) {
|
||||
case QTI_CTRL_MODEM_OFFLINE:
|
||||
if (port && (port->gtype == USB_GADGET_DPL)) {
|
||||
if (port && (port->port_type == QTI_PORT_DPL)) {
|
||||
pr_err("%s(): Modem Offline not handled\n", __func__);
|
||||
goto exit_ioctl;
|
||||
}
|
||||
|
@ -550,7 +554,7 @@ static long qti_ctrl_ioctl(struct file *fp, unsigned cmd, unsigned long arg)
|
|||
gr->disconnect(gr);
|
||||
break;
|
||||
case QTI_CTRL_MODEM_ONLINE:
|
||||
if (port && (port->gtype == USB_GADGET_DPL)) {
|
||||
if (port && (port->port_type == QTI_PORT_DPL)) {
|
||||
pr_err("%s(): Modem Online not handled\n", __func__);
|
||||
goto exit_ioctl;
|
||||
}
|
||||
|
@ -568,13 +572,13 @@ static long qti_ctrl_ioctl(struct file *fp, unsigned cmd, unsigned long arg)
|
|||
pr_err("copying to user space failed");
|
||||
ret = -EFAULT;
|
||||
}
|
||||
pr_debug("%s: Sent line_state: %d for gtype:%d\n", __func__,
|
||||
atomic_read(&port->line_state), port->gtype);
|
||||
pr_debug("%s: Sent line_state: %d for port type:%d\n", __func__,
|
||||
atomic_read(&port->line_state), port->port_type);
|
||||
break;
|
||||
case QTI_CTRL_EP_LOOKUP:
|
||||
|
||||
pr_debug("%s(): EP_LOOKUP for gtype:%d\n", __func__,
|
||||
port->gtype);
|
||||
pr_debug("%s(): EP_LOOKUP for port type:%d\n", __func__,
|
||||
port->port_type);
|
||||
val = atomic_read(&port->connected);
|
||||
if (!val) {
|
||||
pr_err_ratelimited("EP_LOOKUP failed: not connected\n");
|
||||
|
@ -593,9 +597,9 @@ static long qti_ctrl_ioctl(struct file *fp, unsigned cmd, unsigned long arg)
|
|||
info.ipa_ep_pair.cons_pipe_num = port->ipa_cons_idx;
|
||||
info.ipa_ep_pair.prod_pipe_num = port->ipa_prod_idx;
|
||||
|
||||
pr_debug("%s(): gtype:%d ep_type:%d intf:%d\n",
|
||||
__func__, port->gtype, info.ph_ep_info.ep_type,
|
||||
info.ph_ep_info.peripheral_iface_id);
|
||||
pr_debug("%s(): port type:%d ep_type:%d intf:%d\n",
|
||||
__func__, port->port_type, info.ph_ep_info.ep_type,
|
||||
info.ph_ep_info.peripheral_iface_id);
|
||||
|
||||
pr_debug("%s(): ipa_cons_idx:%d ipa_prod_idx:%d\n",
|
||||
__func__, info.ipa_ep_pair.cons_pipe_num,
|
||||
|
@ -650,7 +654,7 @@ static int qti_ctrl_read_stats(struct seq_file *s, void *unused)
|
|||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NR_QTI_PORTS; i++) {
|
||||
for (i = 0; i < QTI_NUM_PORTS; i++) {
|
||||
port = ctrl_port[i];
|
||||
if (!port)
|
||||
continue;
|
||||
|
@ -687,7 +691,7 @@ static ssize_t qti_ctrl_reset_stats(struct file *file,
|
|||
int i;
|
||||
unsigned long flags;
|
||||
|
||||
for (i = 0; i < NR_QTI_PORTS; i++) {
|
||||
for (i = 0; i < QTI_NUM_PORTS; i++) {
|
||||
port = ctrl_port[i];
|
||||
if (!port)
|
||||
continue;
|
||||
|
@ -762,10 +766,9 @@ int gqti_ctrl_init(void)
|
|||
int ret, i, sz = QTI_CTRL_NAME_LEN;
|
||||
struct qti_ctrl_port *port = NULL;
|
||||
|
||||
for (i = 0; i < NR_QTI_PORTS; i++) {
|
||||
for (i = 0; i < QTI_NUM_PORTS; i++) {
|
||||
port = kzalloc(sizeof(struct qti_ctrl_port), GFP_KERNEL);
|
||||
if (!port) {
|
||||
pr_err("Failed to allocate rmnet control device\n");
|
||||
ret = -ENOMEM;
|
||||
goto fail_init;
|
||||
}
|
||||
|
@ -787,16 +790,16 @@ int gqti_ctrl_init(void)
|
|||
port->ipa_prod_idx = -1;
|
||||
port->ipa_cons_idx = -1;
|
||||
|
||||
if (i == 0)
|
||||
if (i == QTI_PORT_RMNET)
|
||||
strlcat(port->name, RMNET_CTRL_QTI_NAME, sz);
|
||||
else if (i == DPL_QTI_CTRL_PORT_NO)
|
||||
else if (i == QTI_PORT_DPL)
|
||||
strlcat(port->name, DPL_CTRL_QTI_NAME, sz);
|
||||
else
|
||||
snprintf(port->name, sz, "%s%d",
|
||||
RMNET_CTRL_QTI_NAME, i);
|
||||
RMNET_CTRL_QTI_NAME, i);
|
||||
|
||||
port->ctrl_device.name = port->name;
|
||||
if (i == DPL_QTI_CTRL_PORT_NO)
|
||||
if (i == QTI_PORT_DPL)
|
||||
port->ctrl_device.fops = &dpl_qti_ctrl_fops;
|
||||
else
|
||||
port->ctrl_device.fops = &qti_ctrl_fops;
|
||||
|
@ -809,7 +812,6 @@ int gqti_ctrl_init(void)
|
|||
}
|
||||
}
|
||||
qti_ctrl_debugfs_init();
|
||||
|
||||
return ret;
|
||||
|
||||
fail_init:
|
||||
|
@ -825,7 +827,7 @@ void gqti_ctrl_cleanup(void)
|
|||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NR_QTI_PORTS; i++) {
|
||||
for (i = 0; i < QTI_NUM_PORTS; i++) {
|
||||
misc_deregister(&ctrl_port[i]->ctrl_device);
|
||||
kfree(ctrl_port[i]);
|
||||
ctrl_port[i] = NULL;
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <linux/usb_bam.h>
|
||||
|
||||
#include "u_data_ipa.h"
|
||||
#include "u_rmnet.h"
|
||||
|
||||
struct ipa_data_ch_info {
|
||||
struct usb_request *rx_req;
|
||||
|
@ -564,6 +565,11 @@ static void ipa_data_connect_work(struct work_struct *w)
|
|||
atomic_set(&port->pipe_connect_notified, 1);
|
||||
}
|
||||
|
||||
if (port->func_type == USB_IPA_FUNC_RMNET) {
|
||||
gqti_ctrl_update_ipa_pipes(port->port_usb, QTI_PORT_RMNET,
|
||||
gport->ipa_producer_ep, gport->ipa_consumer_ep);
|
||||
}
|
||||
|
||||
pr_debug("ipa_producer_ep:%d ipa_consumer_ep:%d\n",
|
||||
gport->ipa_producer_ep,
|
||||
gport->ipa_consumer_ep);
|
||||
|
@ -1135,7 +1141,7 @@ int ipa_data_setup(enum ipa_func_type func)
|
|||
}
|
||||
if (ipa_data_wq) {
|
||||
pr_debug("ipa_data_wq is already setup.");
|
||||
goto free_rndis_data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ipa_data_wq = alloc_workqueue("k_usb_ipa_data",
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
#include <linux/ipa_usb.h>
|
||||
#include <linux/usb_bam.h>
|
||||
|
||||
#include "u_rmnet.h"
|
||||
|
||||
enum ipa_func_type {
|
||||
USB_IPA_FUNC_ECM,
|
||||
USB_IPA_FUNC_MBIM,
|
||||
|
@ -87,4 +89,6 @@ void *rndis_qc_get_ipa_rx_cb(void);
|
|||
bool rndis_qc_get_skip_ep_config(void);
|
||||
void *rndis_qc_get_ipa_tx_cb(void);
|
||||
void rndis_ipa_reset_trigger(void);
|
||||
void gqti_ctrl_update_ipa_pipes(void *gr, enum qti_port_type qport,
|
||||
u32 ipa_prod, u32 ipa_cons);
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2011-2016, 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
|
||||
|
@ -19,18 +19,19 @@
|
|||
#include <linux/workqueue.h>
|
||||
|
||||
struct rmnet_ctrl_pkt {
|
||||
void *buf;
|
||||
int len;
|
||||
void *buf;
|
||||
int len;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
enum qti_port_type {
|
||||
QTI_PORT_RMNET,
|
||||
QTI_PORT_DPL,
|
||||
QTI_NUM_PORTS
|
||||
};
|
||||
|
||||
|
||||
struct grmnet {
|
||||
struct usb_function func;
|
||||
|
||||
struct usb_gadget *gadget;
|
||||
struct usb_ep *in;
|
||||
struct usb_ep *out;
|
||||
|
||||
/* to usb host, aka laptop, windows pc etc. Will
|
||||
* be filled by usb driver of rmnet functionality
|
||||
*/
|
||||
|
@ -39,18 +40,13 @@ struct grmnet {
|
|||
/* to modem, and to be filled by driver implementing
|
||||
* control function
|
||||
*/
|
||||
int (*send_encap_cmd)(u8 port_num, void *buf, size_t len);
|
||||
|
||||
void (*notify_modem)(void *g, u8 port_num, int cbits);
|
||||
int (*send_encap_cmd)(enum qti_port_type qport, void *buf, size_t len);
|
||||
void (*notify_modem)(void *g, enum qti_port_type qport, int cbits);
|
||||
|
||||
void (*disconnect)(struct grmnet *g);
|
||||
void (*connect)(struct grmnet *g);
|
||||
};
|
||||
|
||||
#define NR_QTI_PORTS (NR_RMNET_PORTS + NR_DPL_PORTS)
|
||||
#define NR_RMNET_PORTS 4
|
||||
#define NR_DPL_PORTS 1
|
||||
|
||||
enum ctrl_client {
|
||||
FRMNET_CTRL_CLIENT,
|
||||
GPS_CTRL_CLIENT,
|
||||
|
@ -58,22 +54,8 @@ enum ctrl_client {
|
|||
NR_CTRL_CLIENTS
|
||||
};
|
||||
|
||||
int gbam_setup(unsigned int no_bam_port);
|
||||
int gbam2bam_setup(unsigned int no_bam2bam_port);
|
||||
void gbam_cleanup(void);
|
||||
int gbam_connect(struct grmnet *gr, u8 port_num,
|
||||
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 gbam_mbim_setup(void);
|
||||
int gbam_mbim_connect(struct usb_gadget *g, struct usb_ep *in,
|
||||
struct usb_ep *out);
|
||||
void gbam_mbim_disconnect(void);
|
||||
int gsmd_ctrl_connect(struct grmnet *gr, int port_num);
|
||||
void gsmd_ctrl_disconnect(struct grmnet *gr, u8 port_num);
|
||||
int gsmd_ctrl_setup(enum ctrl_client client_num, unsigned int count,
|
||||
u8 *first_port_idx);
|
||||
int gqti_ctrl_connect(void *gr, enum qti_port_type qport, unsigned intf);
|
||||
void gqti_ctrl_disconnect(void *gr, enum qti_port_type qport);
|
||||
int gqti_ctrl_init(void);
|
||||
void gqti_ctrl_cleanup(void);
|
||||
#endif /* __U_RMNET_H*/
|
||||
|
|
Loading…
Add table
Reference in a new issue