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

Commit 0bf783f5 authored by Mayank Rana's avatar Mayank Rana
Browse files

USB: gadget: Add support to enable streaming mode with required function



Supported different usb functions' has different throughput requirement.
USB controller supports streaming mode feature which enables double
buffering scheme on both IN and OUT endpoint, and reduces number of
NAKs for IN transfer. Hence noticeble throughput is increased with it.
Currently streaming mode is disable with USB controller. As supported
usb functions'like mtp, rndis are required to have higher throughput.
Add support which allows to enable streaming mode with usb controller
in device mode when particular function based composition is being enabled.

CRs-Fixed: 550553
Change-Id: Ibf6f3dc3f3b821647ba9beb15ed735a85c8ed586
Signed-off-by: default avatarMayank Rana <mrana@codeaurora.org>
parent 9f5a3d56
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -186,11 +186,18 @@ Optional properties :
  update USB PID and serial numbers used by bootloader in DLOAD mode.
- qcom,android-usb-swfi-latency : value to be used by device to vote
  for DMA latency in microsecs.
- qcom,streaming-func : add list of usb function name. If mention usb function
  is being enable as part of USB composition, streaming mode is enable with
  usb device controller to get better throughput. NOTE: Inverted CRC and
  turnaround timeout is observed on enabling streaming. Hence it is required
  to see these errors and number of erros on enabling this at USB level to make
  final decision to enable this feature or not.
Example Android USB device node :
	android_usb@fc42b0c8 {
		compatible = "qcom,android-usb";
		reg = <0xfc42b0c8 0xc8>;
		qcom,android-usb-swfi-latency = <1>;
		qcom,streaming-func = "rndis","mtp";
	};


+57 −1
Original line number Diff line number Diff line
@@ -2541,7 +2541,20 @@ android_unbind_enabled_functions(struct android_dev *dev,
			f_holder->f->unbind_config(f_holder->f, c);
	}
}
static inline void check_streaming_func(struct usb_gadget *gadget,
		struct android_usb_platform_data *pdata,
		char *name)
{
	int i;

	for (i = 0; i < pdata->streaming_func_count; i++) {
		if (!strcmp(name, pdata->streaming_func[i])) {
			pr_debug("set streaming_enabled to true\n");
			gadget->streaming_enabled = true;
			break;
		}
	}
}
static int android_enable_function(struct android_dev *dev,
				   struct android_configuration *conf,
				   char *name)
@@ -2549,6 +2562,9 @@ static int android_enable_function(struct android_dev *dev,
	struct android_usb_function **functions = dev->functions;
	struct android_usb_function *f;
	struct android_usb_function_holder *f_holder;
	struct android_usb_platform_data *pdata = dev->pdata;
	struct usb_gadget *gadget = dev->cdev->gadget;

	while ((f = *functions++)) {
		if (!strcmp(name, f->name)) {
			if (f->android_dev && f->android_dev != dev)
@@ -2566,6 +2582,13 @@ static int android_enable_function(struct android_dev *dev,
				f_holder->f = f;
				list_add_tail(&f_holder->enabled_list,
					      &conf->enabled_functions);
				pr_debug("func:%s is enabled.\n", f->name);
				/*
				 * compare enable function with streaming func
				 * list and based on the same request streaming.
				 */
				check_streaming_func(gadget, pdata, f->name);

				return 0;
			}
		}
@@ -2962,6 +2985,10 @@ static void android_unbind_config(struct usb_configuration *c)
{
	struct android_dev *dev = cdev_to_android_dev(c->cdev);

	if (c->cdev->gadget->streaming_enabled) {
		c->cdev->gadget->streaming_enabled = false;
		pr_debug("setting streaming_enabled to false.\n");
	}
	android_unbind_enabled_functions(dev, c);
}

@@ -3271,7 +3298,7 @@ static int android_probe(struct platform_device *pdev)
	struct android_usb_platform_data *pdata;
	struct android_dev *android_dev;
	struct resource *res;
	int ret = 0;
	int ret = 0, i, len = 0;

	if (pdev->dev.of_node) {
		dev_dbg(&pdev->dev, "device tree enabled\n");
@@ -3284,6 +3311,35 @@ static int android_probe(struct platform_device *pdev)
		of_property_read_u32(pdev->dev.of_node,
				"qcom,android-usb-swfi-latency",
				&pdata->swfi_latency);

		len = of_property_count_strings(pdev->dev.of_node,
				"qcom,streaming-func");
		if (len > MAX_STREAMING_FUNCS) {
			pr_err("Invalid number of functions used.\n");
			return -EINVAL;
		}

		for (i = 0; i < len; i++) {
			const char *name = NULL;

			of_property_read_string_index(pdev->dev.of_node,
				"qcom,streaming-func", i, &name);

			if (!name)
				continue;

			if (sizeof(name) > FUNC_NAME_LEN) {
				pr_err("Function name is bigger than allowed.\n");
				continue;
			}

			strlcpy(pdata->streaming_func[i], name,
				sizeof(pdata->streaming_func[i]));
			pr_debug("name of streaming function:%s\n",
				pdata->streaming_func[i]);
		}

		pdata->streaming_func_count = len;
	} else {
		pdata = pdev->dev.platform_data;
	}
+9 −7
Original line number Diff line number Diff line
@@ -70,10 +70,6 @@
#include <mach/usb_trace.h>
#include "ci13xxx_udc.h"

/* Turns on streaming. overrides CI13XXX_DISABLE_STREAMING */
static unsigned int streaming;
module_param(streaming, uint, S_IRUGO | S_IWUSR);

/******************************************************************************
 * DEFINE
 *****************************************************************************/
@@ -392,14 +388,20 @@ static int hw_device_reset(struct ci13xxx *udc)
static int hw_device_state(u32 dma)
{
	struct ci13xxx *udc = _udc;
	struct usb_gadget *gadget = &udc->gadget;

	if (dma) {
		if (streaming || !(udc->udc_driver->flags &
				CI13XXX_DISABLE_STREAMING))
		if (gadget->streaming_enabled || !(udc->udc_driver->flags &
				CI13XXX_DISABLE_STREAMING)) {
			hw_cwrite(CAP_USBMODE, USBMODE_SDIS, 0);
		else
			pr_debug("%s(): streaming mode is enabled. USBMODE:%x\n",
				 __func__, hw_cread(CAP_USBMODE, ~0));
		} else {
			hw_cwrite(CAP_USBMODE, USBMODE_SDIS, USBMODE_SDIS);
			pr_debug("%s(): streaming mode is disabled. USBMODE:%x\n",
				__func__, hw_cread(CAP_USBMODE, ~0));

		}
		hw_cwrite(CAP_ENDPTLISTADDR, ~0, dma);

		if (udc->udc_driver->notify_event)
+4 −0
Original line number Diff line number Diff line
@@ -19,10 +19,14 @@

#include <linux/usb/composite.h>

#define MAX_STREAMING_FUNCS 3
#define FUNC_NAME_LEN 10
struct android_usb_platform_data {
	int (*update_pid_and_serial_num)(uint32_t, const char *);
	u32 swfi_latency;
	u8 usb_core_id;
	char streaming_func[MAX_STREAMING_FUNCS][FUNC_NAME_LEN];
	int  streaming_func_count;
};

#ifndef CONFIG_TARGET_CORE
+2 −0
Original line number Diff line number Diff line
@@ -508,6 +508,7 @@ struct usb_gadget_ops {
 * @in_epnum: last used in ep number
 * @usb_core_id: Identifies the usb core controlled by this usb_gadget.
 *		 Used in case of more then one core operates concurrently.
 * @streaming_enabled: Enable streaming mode with usb core.
 *
 * Gadgets have a mostly-portable "gadget driver" implementing device
 * functions, handling all usb configurations and interfaces.  Gadget
@@ -550,6 +551,7 @@ struct usb_gadget {
	unsigned			in_epnum;
	bool				l1_supported;
	u8				usb_core_id;
	bool				streaming_enabled;
};
#define work_to_gadget(w)	(container_of((w), struct usb_gadget, work))