Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 20c7884f authored by Mayank Rana's avatar Mayank Rana
Browse files

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.4 commit 6f4dec2b0c31 ("qcom:
qpnp-smb2: Reset switcher_power_ok irq count when USBIN_UV fires").

This change also fixes different coding style related warnings.

Change-Id: I4439e87955bd4907086db49e1c80295169fbeb46
Signed-off-by: default avatarMayank Rana <mrana@codeaurora.org>
parent e713c9df
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -233,6 +233,9 @@ config USB_F_CCID
config USB_F_GSI
	tristate

config USB_F_QDSS
	tristate

# this first set of drivers all depend on bulk-capable hardware.

config USB_CONFIGFS
@@ -549,6 +552,13 @@ config USB_CONFIGFS_F_GSI
	help
	  Generic function driver to support h/w acceleration to IPA over GSI.

config USB_CONFIGFS_F_QDSS
        bool "USB QDSS function"
	select USB_F_QDSS
	depends on USB_CONFIGFS
	help
          USB QDSS function driver to get hwtracing related data over USB.

choice
	tristate "USB Gadget Drivers"
	default USB_ETH
+2 −0
Original line number Diff line number Diff line
@@ -62,3 +62,5 @@ usb_f_ccid-y := f_ccid.o
obj-$(CONFIG_USB_F_CCID)   	+= usb_f_ccid.o
usb_f_gsi-y			:= f_gsi.o rndis.o
obj-$(CONFIG_USB_F_GSI)         += usb_f_gsi.o
usb_f_qdss-y			:= f_qdss.o u_qdss.o
obj-$(CONFIG_USB_F_QDSS)        += usb_f_qdss.o
+1072 −0

File added.

Preview size limit exceeded, changes collapsed.

+74 −0
Original line number Diff line number Diff line
/*
 * Copyright (c) 2012-2017, 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
 * only version 2 as published by the Free Software Foundation.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details
 */

#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/msm_hsusb.h>
#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;
	unsigned long usb_bam_handle;
	struct sps_mem_buffer *data_fifo;
};

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;
	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 usb_gadget *gadget,
	struct usb_ep *data_ep, u8 data_addr, int enable);
#endif
+121 −0
Original line number Diff line number Diff line
/*
 * Copyright (c) 2012-2017, 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
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details
 */

#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/usb/msm_hsusb.h>
#include <linux/usb_bam.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 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");

	usb_bam_type = usb_bam_get_bam_type(gadget->name);

	/* 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, USB_BAM_DEVICE, 0);
	if (idx < 0) {
		pr_err("%s: usb_bam_get_connection_idx failed\n", __func__);
		return idx;
	}

	if (enable) {
		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) {
			pr_err("qdss_data_connection: memory alloc failed\n");
			return -ENOMEM;
		}
		get_bam2bam_connection_info(usb_bam_type, idx,
				&bam_info.usb_bam_pipe_idx,
				NULL, bam_info.data_fifo, NULL);

		alloc_sps_req(data_ep);
		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));
	} else {
		kfree(bam_info.data_fifo);
		res = usb_bam_disconnect_pipe(usb_bam_type, idx);
		if (res)
			pr_err("usb_bam_disconnection error\n");
		usb_bam_free_fifos(usb_bam_type, idx);
	}

	return res;
}

static int init_data(struct usb_ep *ep)
{
	struct f_qdss *qdss = ep->driver_data;
	int res = 0;

	pr_debug("init_data\n");

	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_err("uninit_data\n");

	res = msm_ep_unconfig(ep);
	if (res)
		pr_err("msm_ep_unconfig failed\n");

	return res;
}
Loading