mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-09 13:49:24 -04:00
usb: gadget: Add snapshot of USB QDSS function driver
This change adds USB QDSS function driver which allows communication
between USB BAM and QDSS BAM for QDSS debug functionality over USB.
This snapshot is taken as of msm-4.19 kernel commit <b318a6e04625>
("Merge "msm: ipa4: Fix to use common PM handle for coalescing and
default pipe"").
Change-Id: I07919f9453552bec5e420afad32a1bc65c761fd7
Signed-off-by: Mayank Rana <mrana@codeaurora.org>
This commit is contained in:
parent
cc4575e377
commit
9dff3d36df
6 changed files with 1549 additions and 0 deletions
|
|
@ -225,6 +225,9 @@ config USB_F_ACC
|
|||
config USB_F_AUDIO_SRC
|
||||
tristate
|
||||
|
||||
config USB_F_QDSS
|
||||
tristate
|
||||
|
||||
# this first set of drivers all depend on bulk-capable hardware.
|
||||
|
||||
config USB_CONFIGFS
|
||||
|
|
@ -527,6 +530,16 @@ config USB_CONFIGFS_F_DIAG
|
|||
over USB. Applications can also send commands to diagnostics client
|
||||
running on device.
|
||||
|
||||
config USB_CONFIGFS_F_QDSS
|
||||
tristate "USB QDSS function"
|
||||
select USB_F_QDSS
|
||||
depends on USB_CONFIGFS
|
||||
help
|
||||
USB QDSS function driver to get hwtracing related data over
|
||||
USB. USB QDSS function driver which allows communication
|
||||
between USB BAM and QDSS BAM for QDSS debug functionality
|
||||
over USB.
|
||||
|
||||
choice
|
||||
tristate "USB Gadget precomposed configurations"
|
||||
default USB_ETH
|
||||
|
|
|
|||
|
|
@ -56,3 +56,5 @@ usb_f_audio_source-y := f_audio_source.o
|
|||
obj-$(CONFIG_USB_F_AUDIO_SRC) += usb_f_audio_source.o
|
||||
usb_f_diag-y := f_diag.o
|
||||
obj-$(CONFIG_USB_F_DIAG) += usb_f_diag.o
|
||||
usb_f_qdss-y := f_qdss.o u_qdss.o
|
||||
obj-$(CONFIG_USB_F_QDSS) += usb_f_qdss.o
|
||||
|
|
|
|||
1216
drivers/usb/gadget/function/f_qdss.c
Normal file
1216
drivers/usb/gadget/function/f_qdss.c
Normal file
File diff suppressed because it is too large
Load diff
75
drivers/usb/gadget/function/f_qdss.h
Normal file
75
drivers/usb/gadget/function/f_qdss.h
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _F_QDSS_H
|
||||
#define _F_QDSS_H
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/usb/ch9.h>
|
||||
#include <linux/usb/gadget.h>
|
||||
#include <linux/usb/composite.h>
|
||||
#include <linux/usb/usb_qdss.h>
|
||||
|
||||
enum qti_port_type {
|
||||
QTI_PORT_RMNET,
|
||||
QTI_PORT_DPL,
|
||||
QTI_NUM_PORTS
|
||||
};
|
||||
|
||||
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;
|
||||
unsigned long qdss_bam_iova;
|
||||
phys_addr_t qdss_bam_phys;
|
||||
u32 qdss_bam_size;
|
||||
};
|
||||
|
||||
struct gqdss {
|
||||
struct usb_function function;
|
||||
struct usb_ep *ctrl_out;
|
||||
struct usb_ep *ctrl_in;
|
||||
struct usb_ep *data;
|
||||
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 */
|
||||
struct f_qdss {
|
||||
struct gqdss port;
|
||||
struct usb_qdss_bam_connect_info bam_info;
|
||||
struct usb_gadget *gadget;
|
||||
short int port_num;
|
||||
u8 ctrl_iface_id;
|
||||
u8 data_iface_id;
|
||||
int usb_connected;
|
||||
bool debug_inface_enabled;
|
||||
struct usb_request *endless_req;
|
||||
struct usb_qdss_ch ch;
|
||||
struct list_head ctrl_read_pool;
|
||||
struct list_head ctrl_write_pool;
|
||||
|
||||
/* for mdm channel SW path */
|
||||
struct list_head data_write_pool;
|
||||
|
||||
struct work_struct connect_w;
|
||||
struct work_struct disconnect_w;
|
||||
spinlock_t lock;
|
||||
unsigned int data_enabled:1;
|
||||
unsigned int ctrl_in_enabled:1;
|
||||
unsigned int ctrl_out_enabled:1;
|
||||
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 f_qdss *qdss, int enable);
|
||||
#endif
|
||||
149
drivers/usb/gadget/function/u_qdss.c
Normal file
149
drivers/usb/gadget/function/u_qdss.c
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/usb_bam.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
#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;
|
||||
u32 sps_params = 0;
|
||||
|
||||
pr_debug("send_sps_req\n");
|
||||
|
||||
req = usb_ep_alloc_request(data_ep, GFP_ATOMIC);
|
||||
if (!req) {
|
||||
pr_err("usb_ep_alloc_request failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init_data(struct usb_ep *ep);
|
||||
int set_qdss_data_connection(struct f_qdss *qdss, int enable)
|
||||
{
|
||||
enum usb_ctrl usb_bam_type;
|
||||
int res = 0;
|
||||
int idx;
|
||||
struct usb_qdss_bam_connect_info bam_info;
|
||||
struct usb_gadget *gadget;
|
||||
struct device *dev;
|
||||
int ret;
|
||||
|
||||
pr_debug("%s\n", __func__);
|
||||
|
||||
if (!qdss) {
|
||||
pr_err("%s: qdss ptr is NULL\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
gadget = qdss->gadget;
|
||||
usb_bam_type = usb_bam_get_bam_type(gadget->name);
|
||||
dev = gadget->dev.parent;
|
||||
|
||||
bam_info = qdss->bam_info;
|
||||
/* There is only one qdss pipe, so the pipe number can be set to 0 */
|
||||
idx = usb_bam_get_connection_idx(usb_bam_type, QDSS_P_BAM,
|
||||
PEER_PERIPHERAL_TO_USB, 0);
|
||||
if (idx < 0) {
|
||||
pr_err("%s: usb_bam_get_connection_idx failed\n", __func__);
|
||||
return idx;
|
||||
}
|
||||
|
||||
if (enable) {
|
||||
ret = get_qdss_bam_info(usb_bam_type, idx,
|
||||
&bam_info.qdss_bam_phys,
|
||||
&bam_info.qdss_bam_size);
|
||||
if (ret) {
|
||||
pr_err("%s(): failed to get qdss bam info err(%d)\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bam_info.qdss_bam_iova = dma_map_resource(dev->parent,
|
||||
bam_info.qdss_bam_phys, bam_info.qdss_bam_size,
|
||||
DMA_BIDIRECTIONAL, 0);
|
||||
if (!bam_info.qdss_bam_iova) {
|
||||
pr_err("dma_map_resource failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
usb_bam_alloc_fifos(usb_bam_type, idx);
|
||||
bam_info.data_fifo =
|
||||
kzalloc(sizeof(struct sps_mem_buffer), GFP_KERNEL);
|
||||
if (!bam_info.data_fifo) {
|
||||
usb_bam_free_fifos(usb_bam_type, idx);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pr_debug("%s(): qdss_bam: iova:%lx p_addr:%lx size:%x\n",
|
||||
__func__, bam_info.qdss_bam_iova,
|
||||
(unsigned long)bam_info.qdss_bam_phys,
|
||||
bam_info.qdss_bam_size);
|
||||
|
||||
get_bam2bam_connection_info(usb_bam_type, idx,
|
||||
&bam_info.usb_bam_pipe_idx,
|
||||
NULL, bam_info.data_fifo, NULL);
|
||||
|
||||
alloc_sps_req(qdss->port.data);
|
||||
msm_data_fifo_config(qdss->port.data,
|
||||
bam_info.data_fifo->iova,
|
||||
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),
|
||||
bam_info.qdss_bam_iova);
|
||||
} else {
|
||||
res = usb_bam_disconnect_pipe(usb_bam_type, idx);
|
||||
if (res)
|
||||
pr_err("usb_bam_disconnection error\n");
|
||||
dma_unmap_resource(dev->parent, bam_info.qdss_bam_iova,
|
||||
bam_info.qdss_bam_size, DMA_BIDIRECTIONAL, 0);
|
||||
usb_bam_free_fifos(usb_bam_type, idx);
|
||||
kfree(bam_info.data_fifo);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int init_data(struct usb_ep *ep)
|
||||
{
|
||||
struct f_qdss *qdss = ep->driver_data;
|
||||
int res = 0;
|
||||
|
||||
pr_debug("%s\n", __func__);
|
||||
|
||||
res = msm_ep_config(ep, qdss->endless_req);
|
||||
if (res)
|
||||
pr_err("msm_ep_config failed\n");
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int uninit_data(struct usb_ep *ep)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
pr_debug("%s\n", __func__);
|
||||
|
||||
res = msm_ep_unconfig(ep);
|
||||
if (res)
|
||||
pr_err("msm_ep_unconfig failed\n");
|
||||
|
||||
return res;
|
||||
}
|
||||
94
include/linux/usb/usb_qdss.h
Normal file
94
include/linux/usb/usb_qdss.h
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2012-2013, 2017-2019 The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_USB_QDSS_H
|
||||
#define __LINUX_USB_QDSS_H
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#define USB_QDSS_CH_MDM "qdss_mdm"
|
||||
#define USB_QDSS_CH_MSM "qdss"
|
||||
|
||||
struct qdss_request {
|
||||
char *buf;
|
||||
int length;
|
||||
int actual;
|
||||
int status;
|
||||
void *context;
|
||||
struct scatterlist *sg;
|
||||
unsigned int num_sgs;
|
||||
unsigned int num_mapped_sgs;
|
||||
};
|
||||
|
||||
struct usb_qdss_ch {
|
||||
const char *name;
|
||||
struct list_head list;
|
||||
void (*notify)(void *priv, unsigned int event,
|
||||
struct qdss_request *d_req, struct usb_qdss_ch *ch);
|
||||
void *priv;
|
||||
void *priv_usb;
|
||||
int app_conn;
|
||||
};
|
||||
|
||||
enum qdss_state {
|
||||
USB_QDSS_CONNECT,
|
||||
USB_QDSS_DISCONNECT,
|
||||
USB_QDSS_CTRL_READ_DONE,
|
||||
USB_QDSS_DATA_WRITE_DONE,
|
||||
USB_QDSS_CTRL_WRITE_DONE,
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_USB_F_QDSS)
|
||||
struct usb_qdss_ch *usb_qdss_open(const char *name, void *priv,
|
||||
void (*notify)(void *priv, unsigned int event,
|
||||
struct qdss_request *d_req, struct usb_qdss_ch *ch));
|
||||
void usb_qdss_close(struct usb_qdss_ch *ch);
|
||||
int usb_qdss_alloc_req(struct usb_qdss_ch *ch, int n_write, int n_read);
|
||||
void usb_qdss_free_req(struct usb_qdss_ch *ch);
|
||||
int usb_qdss_read(struct usb_qdss_ch *ch, struct qdss_request *d_req);
|
||||
int usb_qdss_write(struct usb_qdss_ch *ch, struct qdss_request *d_req);
|
||||
int usb_qdss_ctrl_write(struct usb_qdss_ch *ch, struct qdss_request *d_req);
|
||||
int usb_qdss_ctrl_read(struct usb_qdss_ch *ch, struct qdss_request *d_req);
|
||||
#else
|
||||
static inline struct usb_qdss_ch *usb_qdss_open(const char *name, void *priv,
|
||||
void (*n)(void *, unsigned int event,
|
||||
struct qdss_request *d, struct usb_qdss_ch *c))
|
||||
{
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
static inline int usb_qdss_read(struct usb_qdss_ch *c, struct qdss_request *d)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int usb_qdss_write(struct usb_qdss_ch *c, struct qdss_request *d)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int usb_qdss_ctrl_write(struct usb_qdss_ch *c,
|
||||
struct qdss_request *d)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int usb_qdss_ctrl_read(struct usb_qdss_ch *c,
|
||||
struct qdss_request *d)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
static inline int usb_qdss_alloc_req(struct usb_qdss_ch *c, int n_wr, int n_rd)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
||||
static inline void usb_qdss_close(struct usb_qdss_ch *ch) { }
|
||||
|
||||
static inline void usb_qdss_free_req(struct usb_qdss_ch *ch) { }
|
||||
#endif /* CONFIG_USB_F_QDSS */
|
||||
|
||||
#endif
|
||||
Loading…
Reference in a new issue