summaryrefslogtreecommitdiff
path: root/drivers/usb/gadget/function
diff options
context:
space:
mode:
authorMayank Rana <mrana@codeaurora.org>2016-03-04 19:22:09 -0800
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 21:23:33 -0700
commit7d9fa0899e06a4d1b910621529de95d59b9eaf65 (patch)
tree69d6f266b04b9ca173991866b65a5b1f69d0b388 /drivers/usb/gadget/function
parent395af0817263a899345940a88de86ed59c9682ca (diff)
usb: gadget: qdss: Modify to support configfs usage
- This change adds configfs usage with USB QDSS driver. - It removes all different supported control and data transports and assume BAM2BAM as default mode. - It also removes supported DPL functionality from this driver. Change-Id: I9678c9e9a397445f36272616e517bbb83a59e88a Signed-off-by: Mayank Rana <mrana@codeaurora.org>
Diffstat (limited to 'drivers/usb/gadget/function')
-rw-r--r--drivers/usb/gadget/function/Makefile2
-rw-r--r--drivers/usb/gadget/function/f_qdss.c666
-rw-r--r--drivers/usb/gadget/function/f_qdss.h23
-rw-r--r--drivers/usb/gadget/function/u_qdss.c62
4 files changed, 224 insertions, 529 deletions
diff --git a/drivers/usb/gadget/function/Makefile b/drivers/usb/gadget/function/Makefile
index 11a6a052cf35..2d5581d4065a 100644
--- a/drivers/usb/gadget/function/Makefile
+++ b/drivers/usb/gadget/function/Makefile
@@ -58,3 +58,5 @@ usb_f_gsi-y := f_gsi.o rndis.o
obj-$(CONFIG_USB_F_GSI) += usb_f_gsi.o
usb_f_cdev-y := f_cdev.o
obj-$(CONFIG_USB_F_CDEV) += usb_f_cdev.o
+usb_f_qdss-y := f_qdss.o
+obj-$(CONFIG_USB_F_QDSS) += usb_f_qdss.o u_qdss.o
diff --git a/drivers/usb/gadget/function/f_qdss.c b/drivers/usb/gadget/function/f_qdss.c
index 6ce347871d11..0a071e76da63 100644
--- a/drivers/usb/gadget/function/f_qdss.c
+++ b/drivers/usb/gadget/function/f_qdss.c
@@ -13,36 +13,15 @@
* GNU General Public License for more details
*/
+#include <linux/init.h>
+#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/usb/usb_qdss.h>
#include <linux/usb/msm_hsusb.h>
#include <linux/usb/cdc.h>
-#include "gadget_chips.h"
#include "f_qdss.h"
-#include "u_qdss.c"
-#include "usb_gadget_xport.h"
-#include "u_data_ipa.h"
-#include "u_rmnet.h"
-
-static unsigned int nr_qdss_ports;
-static unsigned int no_data_bam_ports;
-static unsigned int data_hsic_ports_no;
-static unsigned int no_ipa_ports;
-static unsigned int no_bam_dmux_ports;
-
-static struct qdss_ports {
- enum transport_type data_xport;
- unsigned char data_xport_num;
- enum transport_type ctrl_xport;
- unsigned char ctrl_xport_num;
- unsigned char port_num;
- struct f_qdss *port;
- struct gadget_ipa_port ipa_port;
- struct grmnet bam_dmux_port;
-} qdss_ports[NR_QDSS_PORTS];
-
static DEFINE_SPINLOCK(qdss_lock);
static LIST_HEAD(usb_qdss_ch_list);
@@ -198,6 +177,10 @@ static inline struct f_qdss *func_to_qdss(struct usb_function *f)
return container_of(f, struct f_qdss, port.function);
}
+static struct usb_qdss_opts *to_fi_usb_qdss_opts(struct usb_function_instance *fi)
+{
+ return container_of(fi, struct usb_qdss_opts, func_inst);
+}
/*----------------------------------------------------------------------*/
static void qdss_ctrl_write_complete(struct usb_ep *ep,
@@ -491,69 +474,32 @@ static void usb_qdss_disconnect_work(struct work_struct *work)
{
struct f_qdss *qdss;
int status;
- unsigned char portno;
- enum transport_type dxport;
- enum transport_type ctrl_xport;
- struct gadget_ipa_port *gp;
qdss = container_of(work, struct f_qdss, disconnect_w);
- dxport = qdss_ports[qdss->port_num].data_xport;
- ctrl_xport = qdss_ports[qdss->port_num].ctrl_xport;
- portno = qdss_ports[qdss->port_num].data_xport_num;
-
- if (qdss->port_num >= nr_qdss_ports) {
- pr_err("%s: supporting ports#%u port_id:%u", __func__,
- nr_qdss_ports, portno);
- return;
- }
pr_debug("usb_qdss_disconnect_work\n");
- if (ctrl_xport == USB_GADGET_XPORT_QTI)
- gqti_ctrl_disconnect(&qdss->port, DPL_QTI_CTRL_PORT_NO);
-
- switch (dxport) {
- case USB_GADGET_XPORT_BAM2BAM:
- /*
- * Uninitialized init data i.e. ep specific operation.
- * Notify qdss to cancel all active transfers.
- */
- if (qdss->ch.app_conn) {
- status = uninit_data(qdss->port.data);
- if (status)
- pr_err("%s: uninit_data error\n", __func__);
-
- if (qdss->ch.notify)
- qdss->ch.notify(qdss->ch.priv,
- USB_QDSS_DISCONNECT,
- NULL,
- NULL);
-
- status = set_qdss_data_connection(
- qdss->cdev->gadget,
- qdss->port.data,
- qdss->port.data->address,
- 0);
- if (status)
- pr_err("qdss_disconnect error");
- }
- break;
- case USB_GADGET_XPORT_BAM2BAM_IPA:
- gp = &qdss_ports[qdss->port_num].ipa_port;
- ipa_data_disconnect(gp, qdss->port_num);
- break;
- case USB_GADGET_XPORT_BAM_DMUX:
- gbam_disconnect(&qdss_ports[qdss->port_num].bam_dmux_port,
- portno, USB_GADGET_XPORT_BAM_DMUX);
- break;
- case USB_GADGET_XPORT_HSIC:
- pr_debug("usb_qdss_disconnect_work: HSIC transport\n");
- ghsic_data_disconnect(&qdss->port, portno);
- break;
- case USB_GADGET_XPORT_NONE:
- break;
- default:
- pr_err("%s: Un-supported transport: %s\n", __func__,
- xport_to_str(dxport));
+ /*
+ * Uninitialized init data i.e. ep specific operation.
+ * Notify qdss to cancel all active transfers.
+ */
+ if (qdss->ch.app_conn) {
+ status = uninit_data(qdss->port.data);
+ if (status)
+ pr_err("%s: uninit_data error\n", __func__);
+
+ if (qdss->ch.notify)
+ qdss->ch.notify(qdss->ch.priv,
+ USB_QDSS_DISCONNECT,
+ NULL,
+ NULL);
+
+ status = set_qdss_data_connection(
+ qdss->cdev->gadget,
+ qdss->port.data,
+ qdss->port.data->address,
+ 0);
+ if (status)
+ pr_err("qdss_disconnect error");
}
/*
@@ -567,15 +513,7 @@ static void qdss_disable(struct usb_function *f)
{
struct f_qdss *qdss = func_to_qdss(f);
unsigned long flags;
- unsigned char portno;
- enum transport_type dxport;
- portno = qdss->port_num;
- if (portno >= nr_qdss_ports) {
- pr_err("%s: supporting ports#%u port_id:%u", __func__,
- nr_qdss_ports, portno);
- return;
- }
pr_debug("qdss_disable\n");
spin_lock_irqsave(&qdss->lock, flags);
if (!qdss->usb_connected) {
@@ -583,97 +521,20 @@ static void qdss_disable(struct usb_function *f)
return;
}
- dxport = qdss_ports[qdss->port_num].data_xport;
qdss->usb_connected = 0;
- switch (dxport) {
- case USB_GADGET_XPORT_BAM2BAM_IPA:
- case USB_GADGET_XPORT_BAM_DMUX:
- spin_unlock_irqrestore(&qdss->lock, flags);
- /* Disable usb irq for CI gadget. It will be enabled in
- * usb_bam_disconnect_pipe() after disconnecting all pipes
- * and USB BAM reset is done.
- */
- if (!gadget_is_dwc3(qdss->cdev->gadget))
- msm_usb_irq_disable(true);
- usb_qdss_disconnect_work(&qdss->disconnect_w);
- return;
- default:
- pr_debug("%s: Un-supported transport: %s\n", __func__,
- xport_to_str(dxport));
- }
-
spin_unlock_irqrestore(&qdss->lock, flags);
/*cancell all active xfers*/
qdss_eps_disable(f);
- if (!gadget_is_dwc3(qdss->cdev->gadget))
- msm_usb_irq_disable(true);
queue_work(qdss->wq, &qdss->disconnect_w);
}
-static int qdss_dpl_ipa_connect(int port_num)
-{
- int ret;
- u8 dst_connection_idx;
- struct f_qdss *qdss;
- struct gqdss *g_qdss;
- struct gadget_ipa_port *gp;
- struct usb_gadget *gadget;
- enum usb_ctrl usb_bam_type;
- unsigned long flags;
-
- ipa_data_port_select(port_num, USB_GADGET_DPL);
- qdss = qdss_ports[port_num].port;
-
- spin_lock_irqsave(&qdss->lock, flags);
- g_qdss = &qdss->port;
- gp = &qdss_ports[port_num].ipa_port;
- gp->cdev = qdss->cdev;
- gp->in = g_qdss->data;
- /* For DPL, there is no BULK OUT data transfer. */
- gp->out = NULL;
- gp->func = &g_qdss->function;
- gadget = qdss->cdev->gadget;
-
- spin_unlock_irqrestore(&qdss->lock, flags);
-
- usb_bam_type = usb_bam_get_bam_type(gadget->name);
- dst_connection_idx = usb_bam_get_connection_idx(usb_bam_type, IPA_P_BAM,
- PEER_PERIPHERAL_TO_USB, USB_BAM_DEVICE, 1);
- if (dst_connection_idx < 0) {
- pr_err("usb_bam_get_connection_idx failed\n");
- return ret;
- }
-
- ret = ipa_data_connect(gp, port_num, 0, dst_connection_idx);
- if (ret) {
- pr_err("ipa_data_connect failed: err:%d\n", ret);
- return ret;
- }
-
- pr_info("dpl_ipa connected\n");
- return 0;
-}
-
static void usb_qdss_connect_work(struct work_struct *work)
{
struct f_qdss *qdss;
int status;
- unsigned char port_num;
- enum transport_type dxport;
- enum transport_type ctrl_xport;
qdss = container_of(work, struct f_qdss, connect_w);
- dxport = qdss_ports[qdss->port_num].data_xport;
- ctrl_xport = qdss_ports[qdss->port_num].ctrl_xport;
- port_num = qdss_ports[qdss->port_num].data_xport_num;
- pr_debug("%s: data xport: %s dev: %p portno: %d\n",
- __func__, xport_to_str(dxport),
- qdss, qdss->port_num);
- if (qdss->port_num >= nr_qdss_ports) {
- pr_err("%s: supporting ports#%u port_id:%u", __func__,
- nr_qdss_ports, qdss->port_num);
- return;
- }
+
/* If cable is already removed, discard connect_work */
if (qdss->usb_connected == 0) {
pr_debug("%s: discard connect_work\n", __func__);
@@ -682,75 +543,23 @@ static void usb_qdss_connect_work(struct work_struct *work)
}
pr_debug("usb_qdss_connect_work\n");
-
- if (ctrl_xport == USB_GADGET_XPORT_QTI) {
- status = gqti_ctrl_connect(&qdss->port, DPL_QTI_CTRL_PORT_NO,
- qdss->data_iface_id, dxport,
- USB_GADGET_DPL);
- if (status) {
- pr_err("%s: gqti_ctrl_connect failed: err:%d\n",
- __func__, status);
- return;
- }
- qdss->port.send_encap_cmd(DPL_QTI_CTRL_PORT_NO, NULL, 0);
+ status = set_qdss_data_connection(
+ qdss->cdev->gadget,
+ qdss->port.data,
+ qdss->port.data->address,
+ 1);
+ if (status) {
+ pr_err("set_qdss_data_connection error(%d)", status);
+ return;
}
- switch (dxport) {
- case USB_GADGET_XPORT_BAM2BAM:
- status = set_qdss_data_connection(
- qdss->cdev->gadget,
- qdss->port.data,
- qdss->port.data->address,
- 1);
- if (status) {
- pr_err("set_qdss_data_connection error");
- break;
- }
- if (qdss->ch.notify)
- qdss->ch.notify(qdss->ch.priv,
- USB_QDSS_CONNECT,
- NULL,
- &qdss->ch);
+ if (qdss->ch.notify)
+ qdss->ch.notify(qdss->ch.priv, USB_QDSS_CONNECT,
+ NULL, &qdss->ch);
- if (usb_ep_queue(qdss->port.data, qdss->endless_req,
- GFP_ATOMIC)) {
- pr_err("%s: usb_ep_queue error\n", __func__);
- break;
- }
- break;
- case USB_GADGET_XPORT_BAM2BAM_IPA:
- status = qdss_dpl_ipa_connect(qdss->port_num);
- if (status) {
- pr_err("DPL IPA connect failed with %d\n", status);
- return;
- }
- qdss->data_enabled = 1;
- break;
- case USB_GADGET_XPORT_BAM_DMUX:
- qdss_ports[qdss->port_num].bam_dmux_port.gadget =
- qdss->cdev->gadget;
- qdss_ports[qdss->port_num].bam_dmux_port.in =
- qdss->port.data;
- status = gbam_connect(&qdss_ports[qdss->port_num].bam_dmux_port,
- port_num, USB_GADGET_XPORT_BAM_DMUX, 0, 0);
- if (status)
- pr_err("BAM_DMUX connect failed with %d\n", status);
- break;
- case USB_GADGET_XPORT_HSIC:
- pr_debug("usb_qdss_connect_work: HSIC transport\n");
- status = ghsic_data_connect(&qdss->port, port_num);
- if (status) {
- pr_err("%s: ghsic_data_connect failed: err:%d\n",
- __func__, status);
- return;
- }
- break;
- case USB_GADGET_XPORT_NONE:
- break;
- default:
- pr_err("%s: Un-supported transport: %s\n", __func__,
- xport_to_str(dxport));
- }
+ status = usb_ep_queue(qdss->port.data, qdss->endless_req, GFP_ATOMIC);
+ if (status)
+ pr_err("%s: usb_ep_queue error (%d)\n", __func__, status);
}
static int qdss_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
@@ -759,12 +568,8 @@ static int qdss_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
struct usb_gadget *gadget = f->config->cdev->gadget;
struct usb_qdss_ch *ch = &qdss->ch;
int ret = 0;
- enum transport_type dxport;
-
- dxport = qdss_ports[qdss->port_num].data_xport;
pr_debug("qdss_set_alt qdss pointer = %p\n", qdss);
-
qdss->gadget = gadget;
if (alt != 0)
@@ -786,13 +591,6 @@ static int qdss_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
goto fail;
}
- if (dxport == USB_GADGET_XPORT_BAM2BAM_IPA ||
- dxport == USB_GADGET_XPORT_BAM_DMUX) {
- qdss->usb_connected = 1;
- usb_qdss_connect_work(&qdss->connect_w);
- return 0;
- }
-
ret = usb_ep_enable(qdss->port.data);
if (ret)
goto fail;
@@ -842,10 +640,10 @@ static int qdss_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
pr_debug("qdss_set_alt usb_connected INTF disabled\n");
}
}
- if (qdss->usb_connected && (ch->app_conn ||
- (dxport == USB_GADGET_XPORT_HSIC))) {
+
+ if (qdss->usb_connected && ch->app_conn)
queue_work(qdss->wq, &qdss->connect_w);
- }
+
return 0;
fail:
/* Decrement usage count in case of failure */
@@ -856,102 +654,54 @@ fail1:
return ret;
}
-static int qdss_bind_config(struct usb_configuration *c, unsigned char portno)
+static struct f_qdss *alloc_usb_qdss(char *channel_name)
{
struct f_qdss *qdss;
- int status, found = 0;
+ int found = 0;
struct usb_qdss_ch *ch;
unsigned long flags;
- char *name;
-
- pr_debug("qdss_bind_config\n");
- if (portno >= nr_qdss_ports) {
- pr_err("%s: supporting ports#%u port_id:%u", __func__,
- nr_qdss_ports, portno);
- return -ENODEV;
- }
- qdss = qdss_ports[portno].port;
-
- if (qdss_string_defs[QDSS_DATA_IDX].id == 0) {
- status = usb_string_id(c->cdev);
- if (status < 0)
- return status;
- qdss_string_defs[QDSS_DATA_IDX].id = status;
- qdss_data_intf_desc.iInterface = status;
- if (qdss->debug_inface_enabled) {
- status = usb_string_id(c->cdev);
- if (status < 0)
- return status;
- qdss_string_defs[QDSS_CTRL_IDX].id = status;
- qdss_ctrl_intf_desc.iInterface = status;
- }
- }
-
- if (qdss_ports[portno].data_xport == USB_GADGET_XPORT_BAM2BAM)
- name = kasprintf(GFP_ATOMIC, "qdss");
- else
- name = kasprintf(GFP_ATOMIC, "qdss%d", portno);
-
- if (!name)
- return -ENOMEM;
spin_lock_irqsave(&qdss_lock, flags);
-
list_for_each_entry(ch, &usb_qdss_ch_list, list) {
- if (!strcmp(name, ch->name)) {
+ if (!strcmp(channel_name, ch->name)) {
found = 1;
break;
}
}
- if (!found) {
- if (!qdss) {
- spin_unlock_irqrestore(&qdss_lock, flags);
- return -ENOMEM;
- }
+
+ if (found) {
spin_unlock_irqrestore(&qdss_lock, flags);
- qdss->wq = create_singlethread_workqueue(name);
- if (!qdss->wq) {
- kfree(qdss);
- return -ENOMEM;
- }
- spin_lock_irqsave(&qdss_lock, flags);
- ch = &qdss->ch;
- ch->name = name;
- list_add_tail(&ch->list, &usb_qdss_ch_list);
- } else {
- qdss = container_of(ch, struct f_qdss, ch);
- ch->priv_usb = qdss;
- qdss->debug_inface_enabled =
- qdss_ports[portno].port->debug_inface_enabled;
- if (qdss != qdss_ports[portno].port) {
- kfree(qdss_ports[portno].port);
- qdss_ports[portno].port = qdss;
- }
+ pr_err("%s: (%s) is already available.\n",
+ __func__, channel_name);
+ return ERR_PTR(-EEXIST);
+ }
+
+ spin_unlock_irqrestore(&qdss_lock, flags);
+ qdss = kzalloc(sizeof(struct f_qdss), GFP_KERNEL);
+ if (!qdss) {
+ pr_err("%s: Unable to allocate qdss device\n", __func__);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ qdss->wq = create_singlethread_workqueue(channel_name);
+ if (!qdss->wq) {
+ kfree(qdss);
+ return ERR_PTR(-ENOMEM);
}
+
+ spin_lock_irqsave(&qdss_lock, flags);
+ ch = &qdss->ch;
+ ch->name = channel_name;
+ list_add_tail(&ch->list, &usb_qdss_ch_list);
spin_unlock_irqrestore(&qdss_lock, flags);
- qdss->cdev = c->cdev;
- qdss->port_num = portno;
- qdss->port.function.name = name;
- qdss->port.function.fs_descriptors = qdss_hs_desc;
- qdss->port.function.hs_descriptors = qdss_hs_desc;
- qdss->port.function.strings = qdss_strings;
- qdss->port.function.bind = qdss_bind;
- qdss->port.function.unbind = qdss_unbind;
- qdss->port.function.set_alt = qdss_set_alt;
- qdss->port.function.disable = qdss_disable;
+
spin_lock_init(&qdss->lock);
INIT_LIST_HEAD(&qdss->ctrl_read_pool);
INIT_LIST_HEAD(&qdss->ctrl_write_pool);
INIT_WORK(&qdss->connect_w, usb_qdss_connect_work);
INIT_WORK(&qdss->disconnect_w, usb_qdss_disconnect_work);
- status = usb_add_function(c, &qdss->port.function);
- if (status) {
- pr_err("qdss usb_add_function failed\n");
- ch->priv_usb = NULL;
- kfree(qdss);
- }
- return status;
+ return qdss;
}
int usb_qdss_ctrl_read(struct usb_qdss_ch *ch, struct qdss_request *d_req)
@@ -1069,28 +819,15 @@ struct usb_qdss_ch *usb_qdss_open(const char *name, void *priv,
}
if (!found) {
- pr_debug("usb_qdss_open: allocation qdss ctx\n");
- qdss = kzalloc(sizeof(*qdss), GFP_ATOMIC);
- if (!qdss) {
- spin_unlock_irqrestore(&qdss_lock, flags);
- return ERR_PTR(-ENOMEM);
- }
spin_unlock_irqrestore(&qdss_lock, flags);
- qdss->wq = create_singlethread_workqueue(name);
- if (!qdss->wq) {
- kfree(qdss);
- return ERR_PTR(-ENOMEM);
- }
- spin_lock_irqsave(&qdss_lock, flags);
- ch = &qdss->ch;
- list_add_tail(&ch->list, &usb_qdss_ch_list);
+ pr_debug("usb_qdss_open failed as %s not found\n", name);
+ return NULL;
} else {
pr_debug("usb_qdss_open: qdss ctx found\n");
qdss = container_of(ch, struct f_qdss, ch);
ch->priv_usb = qdss;
}
- ch->name = name;
ch->priv = priv;
ch->notify = notify;
ch->app_conn = 1;
@@ -1159,168 +896,135 @@ static void qdss_cleanup(void)
}
}
-static int qdss_setup(void)
+static void qdss_free_func(struct usb_function *f)
{
- return 0;
+ /* Do nothing as usb_qdss_alloc() doesn't alloc anything. */
}
-static int qdss_init_port(const char *ctrl_name, const char *data_name,
- const char *port_name, bool debug_enable)
+static inline struct usb_qdss_opts *to_f_qdss_opts(struct config_item *item)
{
- struct f_qdss *dev;
- struct qdss_ports *qdss_port;
- int ret;
- int i;
-
- if (nr_qdss_ports >= NR_QDSS_PORTS) {
- pr_err("%s: Max-%d instances supported\n",
- __func__, NR_QDSS_PORTS);
- return -EINVAL;
- }
+ return container_of(to_config_group(item), struct usb_qdss_opts,
+ func_inst.group);
+}
- pr_debug("ctrl name = %s data_name %s port_name %s\n",
- ctrl_name, data_name, port_name);
+static void qdss_attr_release(struct config_item *item)
+{
+ struct usb_qdss_opts *opts = to_f_qdss_opts(item);
- pr_debug("%s: port#:%d, data port: %s\n",
- __func__, nr_qdss_ports, data_name);
+ usb_put_function_instance(&opts->func_inst);
+}
- dev = kzalloc(sizeof(struct f_qdss), GFP_KERNEL);
- if (!dev) {
- pr_err("%s: Unable to allocate qdss device\n", __func__);
- return -ENOMEM;
- }
+static struct configfs_item_operations qdss_item_ops = {
+ .release = qdss_attr_release,
+};
- dev->port_num = nr_qdss_ports;
- spin_lock_init(&dev->lock);
-
- qdss_port = &qdss_ports[nr_qdss_ports];
- qdss_port->port = dev;
- qdss_port->port_num = nr_qdss_ports;
- qdss_port->data_xport = str_to_xport(data_name);
- qdss_port->port->debug_inface_enabled = debug_enable;
-
- if (ctrl_name) {
- qdss_port->ctrl_xport = str_to_xport(ctrl_name);
- pr_debug("%s(): ctrl_name:%s ctrl_xport:%d\n", __func__,
- ctrl_name, qdss_port->ctrl_xport);
- switch (qdss_port->ctrl_xport) {
- case USB_GADGET_XPORT_QTI:
- pr_debug("USB_GADGET_XPORT_QTI is used.\n");
- break;
- default:
- pr_debug("%s(): No ctrl transport.\n", __func__);
- }
- }
+static struct configfs_attribute *qdss_attrs[] = {
+ NULL,
+};
- switch (qdss_port->data_xport) {
- case USB_GADGET_XPORT_BAM2BAM:
- qdss_port->data_xport_num = no_data_bam_ports;
- no_data_bam_ports++;
- pr_debug("USB_GADGET_XPORT_BAM2BAM %d\n", no_data_bam_ports);
- break;
- case USB_GADGET_XPORT_BAM2BAM_IPA:
- qdss_port->data_xport_num = no_ipa_ports;
- no_ipa_ports++;
- pr_debug("USB_GADGET_XPORT_BAM2BAM_IPA %d\n", no_ipa_ports);
- break;
- case USB_GADGET_XPORT_HSIC:
- pr_debug("%s USB_GADGET_XPORT_HSIC\n", __func__);
- ghsic_data_set_port_name(port_name, data_name);
- qdss_port->data_xport_num = data_hsic_ports_no;
- data_hsic_ports_no++;
- break;
- case USB_GADGET_XPORT_BAM_DMUX:
- qdss_port->data_xport_num = no_bam_dmux_ports;
- no_bam_dmux_ports++;
- pr_debug("USB_GADGET_XPORT_BAM_DMUX %u\n", no_bam_dmux_ports);
- break;
- case USB_GADGET_XPORT_NONE:
- break;
- default:
- pr_err("%s: Un-supported transport: %u\n", __func__,
- qdss_port->data_xport);
- ret = -ENODEV;
- goto fail_probe;
- }
- nr_qdss_ports++;
- return 0;
+static struct config_item_type qdss_func_type = {
+ .ct_item_ops = &qdss_item_ops,
+ .ct_attrs = qdss_attrs,
+ .ct_owner = THIS_MODULE,
+};
-fail_probe:
- for (i = 0; i < nr_qdss_ports; i++)
- kfree(qdss_ports[i].port);
+static void usb_qdss_free_inst(struct usb_function_instance *fi)
+{
+ struct usb_qdss_opts *opts;
- nr_qdss_ports = 0;
- no_data_bam_ports = 0;
- data_hsic_ports_no = 0;
- no_ipa_ports = 0;
- no_bam_dmux_ports = 0;
- return ret;
+ opts = container_of(fi, struct usb_qdss_opts, func_inst);
+ kfree(opts->usb_qdss);
+ kfree(opts);
}
-static int qdss_gport_setup(void)
+static int usb_qdss_set_inst_name(struct usb_function_instance *f, const char *name)
{
- int port_idx;
- int i;
-
- pr_debug("%s: bam ports: %u data hsic ports: %u ipa_ports:%u bam_dmux_port:%u nr_qdss_ports:%u\n",
- __func__, no_data_bam_ports, data_hsic_ports_no,
- no_ipa_ports, no_bam_dmux_ports, nr_qdss_ports);
-
- if (data_hsic_ports_no) {
- pr_debug("%s: go to setup hsic data\n", __func__);
- port_idx = ghsic_data_setup(data_hsic_ports_no,
- USB_GADGET_QDSS);
- if (port_idx < 0)
- return port_idx;
- for (i = 0; i < nr_qdss_ports; i++) {
- if (qdss_ports[i].data_xport ==
- USB_GADGET_XPORT_HSIC) {
- qdss_ports[i].data_xport_num = port_idx;
- pr_debug("%s: qdss data_xport_num = %d\n",
- __func__, qdss_ports[i].data_xport_num);
- port_idx++;
- }
- }
+ struct usb_qdss_opts *opts =
+ container_of(f, struct usb_qdss_opts, func_inst);
+ char *ptr;
+ size_t name_len;
+ struct f_qdss *usb_qdss;
+
+ /* get channel_name as expected input qdss.<channel_name> */
+ name_len = strlen(name) + 1;
+ if (name_len > 15)
+ return -ENAMETOOLONG;
+
+ /* get channel name */
+ ptr = kstrndup(name, name_len, GFP_KERNEL);
+ if (!ptr) {
+ pr_err("error:%ld\n", PTR_ERR(ptr));
+ return -ENOMEM;
}
- if (no_ipa_ports) {
- pr_debug("Inside initializaing ipa data port\n");
- port_idx = ipa_data_setup(no_ipa_ports);
- if (port_idx < 0) {
- pr_err("%s(): error with initializing IPA data setup\n",
- __func__);
- return port_idx;
- }
+ opts->channel_name = ptr;
+ pr_debug("qdss: channel_name:%s\n", opts->channel_name);
- for (i = 0; i < no_ipa_ports; i++) {
- if (qdss_ports[i].data_xport ==
- USB_GADGET_XPORT_BAM2BAM_IPA) {
- qdss_ports[i].data_xport_num = port_idx;
- pr_debug("%s: DPL data_xport_num = %d\n",
- __func__, qdss_ports[i].data_xport_num);
- port_idx++;
- }
- }
+ usb_qdss = alloc_usb_qdss(opts->channel_name);
+ if (IS_ERR(usb_qdss)) {
+ pr_err("Failed to create usb_qdss port(%s)\n", opts->channel_name);
+ return -ENOMEM;
}
- if (no_bam_dmux_ports) {
- port_idx = gbam_setup(no_bam_dmux_ports);
- if (port_idx < 0) {
- pr_err("%s(): gbam_setup failed with %d\n",
- __func__, port_idx);
- return port_idx;
- }
+ opts->usb_qdss = usb_qdss;
+ return 0;
+}
- for (i = 0; i < no_bam_dmux_ports; i++) {
- if (qdss_ports[i].data_xport ==
- USB_GADGET_XPORT_BAM_DMUX) {
- qdss_ports[i].data_xport_num = port_idx;
- pr_debug("%s: BAM-DMUX data_xport_num = %d\n",
- __func__, qdss_ports[i].data_xport_num);
- port_idx++;
- }
- }
+static struct usb_function_instance *qdss_alloc_inst(void)
+{
+ struct usb_qdss_opts *opts;
+
+ opts = kzalloc(sizeof(*opts), GFP_KERNEL);
+ if (!opts)
+ return ERR_PTR(-ENOMEM);
+
+ opts->func_inst.free_func_inst = usb_qdss_free_inst;
+ opts->func_inst.set_inst_name = usb_qdss_set_inst_name;
+
+ config_group_init_type_name(&opts->func_inst.group, "",
+ &qdss_func_type);
+ return &opts->func_inst;
+}
+
+static struct usb_function *qdss_alloc(struct usb_function_instance *fi)
+{
+ struct usb_qdss_opts *opts = to_fi_usb_qdss_opts(fi);
+ struct f_qdss *usb_qdss = opts->usb_qdss;
+
+ usb_qdss->port.function.name = "usb_qdss";
+ usb_qdss->port.function.fs_descriptors = qdss_hs_desc;
+ usb_qdss->port.function.hs_descriptors = qdss_hs_desc;
+ usb_qdss->port.function.strings = qdss_strings;
+ usb_qdss->port.function.bind = qdss_bind;
+ usb_qdss->port.function.unbind = qdss_unbind;
+ usb_qdss->port.function.set_alt = qdss_set_alt;
+ usb_qdss->port.function.disable = qdss_disable;
+ usb_qdss->port.function.setup = NULL;
+ usb_qdss->port.function.free_func = qdss_free_func;
+
+ return &usb_qdss->port.function;
+}
+
+DECLARE_USB_FUNCTION_INIT(qdss, qdss_alloc_inst, qdss_alloc);
+static int __init usb_qdss_init(void)
+{
+ int ret;
+
+ INIT_LIST_HEAD(&usb_qdss_ch_list);
+ ret = usb_function_register(&qdssusb_func);
+ if (ret) {
+ pr_err("%s: failed to register diag %d\n", __func__, ret);
+ return ret;
}
+ return ret;
+}
- return 0;
+static void __exit usb_qdss_exit(void)
+{
+ usb_function_unregister(&qdssusb_func);
+ qdss_cleanup();
}
+
+module_init(usb_qdss_init);
+module_exit(usb_qdss_exit);
+MODULE_DESCRIPTION("USB QDSS Function Driver");
diff --git a/drivers/usb/gadget/function/f_qdss.h b/drivers/usb/gadget/function/f_qdss.h
index 828f03e09ccd..a6e988e2cf0a 100644
--- a/drivers/usb/gadget/function/f_qdss.h
+++ b/drivers/usb/gadget/function/f_qdss.h
@@ -17,8 +17,17 @@
#include <linux/kernel.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
+#include <linux/usb/msm_hsusb.h>
+#include <linux/usb/composite.h>
+#include <linux/usb_bam.h>
+#include <linux/usb/usb_qdss.h>
-#define NR_QDSS_PORTS 4
+struct usb_qdss_bam_connect_info {
+ u32 usb_bam_pipe_idx;
+ u32 peer_pipe_idx;
+ unsigned long usb_bam_handle;
+ struct sps_mem_buffer *data_fifo;
+};
struct gqdss {
struct usb_function function;
@@ -32,9 +41,10 @@ struct gqdss {
/* struct f_qdss - USB qdss function driver private structure */
struct f_qdss {
struct gqdss port;
+ struct usb_qdss_bam_connect_info bam_info;
struct usb_composite_dev *cdev;
struct usb_gadget *gadget;
- u8 port_num;
+ short int port_num;
u8 ctrl_iface_id;
u8 data_iface_id;
int usb_connected;
@@ -52,4 +62,13 @@ struct f_qdss {
struct workqueue_struct *wq;
};
+struct usb_qdss_opts {
+ struct usb_function_instance func_inst;
+ struct f_qdss *usb_qdss;
+ char *channel_name;
+};
+
+int uninit_data(struct usb_ep *ep);
+int set_qdss_data_connection(struct usb_gadget *gadget,
+ struct usb_ep *data_ep, u8 data_addr, int enable);
#endif
diff --git a/drivers/usb/gadget/function/u_qdss.c b/drivers/usb/gadget/function/u_qdss.c
index 298d8cf3e399..8f5fcc16eb15 100644
--- a/drivers/usb/gadget/function/u_qdss.c
+++ b/drivers/usb/gadget/function/u_qdss.c
@@ -15,22 +15,11 @@
#include <linux/usb/msm_hsusb.h>
#include <linux/usb_bam.h>
-#include "gadget_chips.h"
-
-struct usb_qdss_bam_connect_info {
- u32 usb_bam_pipe_idx;
- u32 peer_pipe_idx;
- unsigned long usb_bam_handle;
- struct sps_mem_buffer *data_fifo;
-};
-
-static struct usb_qdss_bam_connect_info bam_info;
-
-int alloc_sps_req(struct usb_ep *data_ep)
+#include "f_qdss.h"
+static int alloc_sps_req(struct usb_ep *data_ep)
{
struct usb_request *req = NULL;
struct f_qdss *qdss = data_ep->driver_data;
- struct usb_gadget *gadget = qdss->cdev->gadget;
u32 sps_params = 0;
pr_debug("send_sps_req\n");
@@ -41,16 +30,9 @@ int alloc_sps_req(struct usb_ep *data_ep)
return -ENOMEM;
}
- if (gadget_is_dwc3(gadget)) {
- req->length = 32*1024;
- sps_params = MSM_SPS_MODE | MSM_DISABLE_WB |
- bam_info.usb_bam_pipe_idx;
- } else {
- /* non DWC3 BAM requires req->length to be 0 */
- req->length = 0;
- sps_params = (MSM_SPS_MODE | bam_info.usb_bam_pipe_idx |
- MSM_VENDOR_ID) & ~MSM_IS_FINITE_TRANSFER;
- }
+ req->length = 32*1024;
+ sps_params = MSM_SPS_MODE | MSM_DISABLE_WB |
+ qdss->bam_info.usb_bam_pipe_idx;
req->udc_priv = sps_params;
qdss->endless_req = req;
@@ -58,13 +40,14 @@ int alloc_sps_req(struct usb_ep *data_ep)
}
static int init_data(struct usb_ep *ep);
-static int set_qdss_data_connection(struct usb_gadget *gadget,
+int set_qdss_data_connection(struct usb_gadget *gadget,
struct usb_ep *data_ep, u8 data_addr, int enable)
{
enum usb_ctrl usb_bam_type;
int res = 0;
int idx;
struct f_qdss *qdss = data_ep->driver_data;
+ struct usb_qdss_bam_connect_info bam_info = qdss->bam_info;
pr_debug("set_qdss_data_connection\n");
@@ -91,16 +74,13 @@ static int set_qdss_data_connection(struct usb_gadget *gadget,
NULL, bam_info.data_fifo, NULL);
alloc_sps_req(data_ep);
- if (gadget_is_dwc3(gadget))
- msm_data_fifo_config(data_ep,
- bam_info.data_fifo->phys_base,
- bam_info.data_fifo->size,
- bam_info.usb_bam_pipe_idx);
+ msm_data_fifo_config(data_ep, bam_info.data_fifo->phys_base,
+ bam_info.data_fifo->size,
+ bam_info.usb_bam_pipe_idx);
init_data(qdss->port.data);
res = usb_bam_connect(usb_bam_type, idx,
&(bam_info.usb_bam_pipe_idx));
- gadget->bam2bam_func_enabled = true;
} else {
kfree(bam_info.data_fifo);
res = usb_bam_disconnect_pipe(usb_bam_type, idx);
@@ -114,36 +94,26 @@ static int set_qdss_data_connection(struct usb_gadget *gadget,
static int init_data(struct usb_ep *ep)
{
- struct f_qdss *qdss = ep->driver_data;
- struct usb_gadget *gadget = qdss->cdev->gadget;
int res = 0;
pr_debug("init_data\n");
- if (gadget_is_dwc3(gadget)) {
- res = msm_ep_config(ep, qdss->endless_req, GFP_ATOMIC);
- if (res)
- pr_err("msm_ep_config failed\n");
- } else {
- pr_debug("QDSS is used with non DWC3 core\n");
- }
+ res = msm_ep_config(ep);
+ if (res)
+ pr_err("msm_ep_config failed\n");
return res;
}
int uninit_data(struct usb_ep *ep)
{
- struct f_qdss *qdss = ep->driver_data;
- struct usb_gadget *gadget = qdss->cdev->gadget;
int res = 0;
pr_err("uninit_data\n");
- if (gadget_is_dwc3(gadget)) {
- res = msm_ep_unconfig(ep);
- if (res)
- pr_err("msm_ep_unconfig failed\n");
- }
+ res = msm_ep_unconfig(ep);
+ if (res)
+ pr_err("msm_ep_unconfig failed\n");
return res;
}