diff options
| author | Mayank Rana <mrana@codeaurora.org> | 2016-03-04 19:22:09 -0800 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 21:23:33 -0700 |
| commit | 7d9fa0899e06a4d1b910621529de95d59b9eaf65 (patch) | |
| tree | 69d6f266b04b9ca173991866b65a5b1f69d0b388 /drivers/usb/gadget/function | |
| parent | 395af0817263a899345940a88de86ed59c9682ca (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/Makefile | 2 | ||||
| -rw-r--r-- | drivers/usb/gadget/function/f_qdss.c | 666 | ||||
| -rw-r--r-- | drivers/usb/gadget/function/f_qdss.h | 23 | ||||
| -rw-r--r-- | drivers/usb/gadget/function/u_qdss.c | 62 |
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; } |
