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

Commit a730d81c authored by Mayank Rana's avatar Mayank Rana
Browse files

qc_rndis: Add max_pkt_per_xfer and pkt_alignment_factor support



For RNDIS UL aggregation, max_pkt_per_xfer and pkt_alignment_factor
is key information which host expects from device to send aggregated
RNDIS packets. Currently max_pkt_per_xfer and pkt_alignment_factor
are hardcoded with value as 15 and 2 respectively. This change adds
supports which allows setting of these parameters. This changes creates
new sysfs entry for pkt_alignment_factor and uses already available
syfs entry for max_pkt_per_xfer.
e.g.
1.
To enable aggregation of 2 RNDIS Packets with alignment factor 3.
echo 2 >
/sys/devices/virtual/android_usb/android0/f_rndis_qc/max_pkt_per_xfer
echo 3 >
/sys/devices/virtual/android_usb/android0/f_rndis_qc/pkt_alignment_factor
2. If both parameters are not set, it uses default value as 15 and 2 as
default aggregation configuration.
3. For disabling RNDIS UL aggregation,
echo 1 >
/sys/devices/virtual/android_usb/android0/f_rndis_qc/max_pkt_per_xfer

Change-Id: I18d0b720c48c6ed5bf8c08a108736cb4506e2257
Signed-off-by: default avatarMayank Rana <mrana@codeaurora.org>
parent d4650c13
Loading
Loading
Loading
Loading
+32 −2
Original line number Diff line number Diff line
@@ -1667,6 +1667,7 @@ struct rndis_function_config {
	u8      ethaddr[ETH_ALEN];
	u32     vendorID;
	u8      max_pkt_per_xfer;
	u8	pkt_alignment_factor;
	char	manufacturer[256];
	/* "Wireless" RNDIS; auto-detected by Windows */
	bool	wceis;
@@ -1791,8 +1792,8 @@ static int rndis_qc_function_bind_config(struct android_usb_function *f,
	}

	return rndis_qc_bind_config_vendor(c, rndis->ethaddr, rndis->vendorID,
				    rndis->manufacturer,
					rndis->max_pkt_per_xfer, trans);
			rndis->manufacturer, rndis->max_pkt_per_xfer,
			rndis->pkt_alignment_factor, trans);
}

static void rndis_function_unbind_config(struct android_usb_function *f,
@@ -1973,6 +1974,34 @@ static ssize_t rndis_rx_trigger_store(struct device *dev,
static DEVICE_ATTR(rx_trigger, S_IWUSR, NULL,
					     rndis_rx_trigger_store);

static ssize_t rndis_pkt_alignment_factor_show(struct device *dev,
		struct device_attribute *attr, char *buf)
{
	struct android_usb_function *f = dev_get_drvdata(dev);
	struct rndis_function_config *config = f->config;

	return snprintf(buf, PAGE_SIZE, "%d\n", config->pkt_alignment_factor);
}

static ssize_t rndis_pkt_alignment_factor_store(struct device *dev,
		struct device_attribute *attr, const char *buf, size_t size)
{
	struct android_usb_function *f = dev_get_drvdata(dev);
	struct rndis_function_config *config = f->config;
	int value;

	if (sscanf(buf, "%d", &value) == 1) {
		config->pkt_alignment_factor = value;
		return size;
	}

	return -EINVAL;
}

static DEVICE_ATTR(pkt_alignment_factor, S_IRUGO | S_IWUSR,
					rndis_pkt_alignment_factor_show,
					rndis_pkt_alignment_factor_store);

static struct device_attribute *rndis_function_attributes[] = {
	&dev_attr_manufacturer,
	&dev_attr_wceis,
@@ -1981,6 +2010,7 @@ static struct device_attribute *rndis_function_attributes[] = {
	&dev_attr_max_pkt_per_xfer,
	&dev_attr_rndis_transports,
	&dev_attr_rx_trigger,
	&dev_attr_pkt_alignment_factor,
	NULL
};

+33 −5
Original line number Diff line number Diff line
@@ -86,6 +86,7 @@ struct f_rndis_qc {
	u8				ethaddr[ETH_ALEN];
	u32				vendorID;
	u8				max_pkt_per_xfer;
	u8				pkt_alignment_factor;
	u32				max_pkt_size;
	const char			*manufacturer;
	int				config;
@@ -133,6 +134,8 @@ static unsigned int rndis_qc_bitrate(struct usb_gadget *g)
/* default max packets per tarnsfer value */
#define DEFAULT_MAX_PKT_PER_XFER			15

/* default pkt alignment factor */
#define DEFAULT_PKT_ALIGNMENT_FACTOR			2

#define RNDIS_QC_IOCTL_MAGIC		'i'
#define RNDIS_QC_GET_MAX_PKT_PER_XFER   _IOR(RNDIS_QC_IOCTL_MAGIC, 1, u8)
@@ -969,12 +972,17 @@ rndis_qc_bind(struct usb_configuration *c, struct usb_function *f)
			rndis->manufacturer))
		goto fail;

	pr_debug("%s(): max_pkt_per_xfer:%d\n", __func__,
				rndis->max_pkt_per_xfer);
	rndis_set_max_pkt_xfer(rndis->config, rndis->max_pkt_per_xfer);

	/* In case of aggregated packets QC device will request
	 * aliment to 4 (2^2).
	 */
	rndis_set_pkt_alignment_factor(rndis->config, 2);
	pr_debug("%s(): pkt_alignment_factor:%d\n", __func__,
				rndis->pkt_alignment_factor);
	rndis_set_pkt_alignment_factor(rndis->config,
				rndis->pkt_alignment_factor);

	/* NOTE:  all that is done without knowing or caring about
	 * the network link ... which is unavailable to this code
@@ -1066,13 +1074,15 @@ static inline bool can_support_rndis_qc(struct usb_configuration *c)
int
rndis_qc_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
{
	return rndis_qc_bind_config_vendor(c, ethaddr, 0, NULL, 1, NULL);
	return rndis_qc_bind_config_vendor(c, ethaddr, 0, NULL, 1, 0, NULL);
}

int
rndis_qc_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
					u32 vendorID, const char *manufacturer,
					 u8 max_pkt_per_xfer, char *xport_name)
					u8 max_pkt_per_xfer,
					u8 pkt_alignment_factor,
					char *xport_name)
{
	struct f_rndis_qc	*rndis;
	int		status;
@@ -1147,9 +1157,27 @@ rndis_qc_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],

	/* if max_pkt_per_xfer was not configured set to default value */
	rndis->max_pkt_per_xfer =
		max_pkt_per_xfer ? max_pkt_per_xfer : DEFAULT_MAX_PKT_PER_XFER;
			max_pkt_per_xfer ? max_pkt_per_xfer :
			DEFAULT_MAX_PKT_PER_XFER;
	u_bam_data_set_max_pkt_num(rndis->max_pkt_per_xfer);

	/*
	 * Check no RNDIS aggregation, and alignment if not mentioned,
	 * use alignment factor as zero. If aggregated RNDIS data transfer,
	 * max packet per transfer would be default if it is not set
	 * explicitly, and same way use alignment factor as 2 by default.
	 * This would eliminate need of writing to sysfs if default RNDIS
	 * aggregation setting required. Writing to both sysfs entries,
	 * those values will always override default values.
	 */
	if ((rndis->pkt_alignment_factor == 0) &&
			(rndis->max_pkt_per_xfer == 1))
		rndis->pkt_alignment_factor = 0;
	else
		rndis->pkt_alignment_factor = pkt_alignment_factor ?
				pkt_alignment_factor :
				DEFAULT_PKT_ALIGNMENT_FACTOR;

	/* RNDIS activates when the host changes this filter */
	rndis->port.cdc_filter = 0;

+5 −2
Original line number Diff line number Diff line
@@ -1143,7 +1143,8 @@ static int rndis_proc_show(struct seq_file *m, void *v)
			 "vendor ID : 0x%08X\n"
			 "vendor    : %s\n"
			 "ul-max-xfer-size:%d max-xfer-size-rcvd: %d\n"
			 "ul-max-pkts-per-xfer:%d max-pkts-per-xfer-rcvd:%d\n",
			 "ul-max-pkts-per-xfer:%d max-pkts-per-xfer-rcvd:%d\n"
			"pkt_alignment_factor:%d\n",
			 param->confignr, (param->used) ? "y" : "n",
			 ({ char *s = "?";
			 switch (param->state) {
@@ -1163,7 +1164,8 @@ static int rndis_proc_show(struct seq_file *m, void *v)
				  sizeof(struct rndis_packet_msg_type) + 22),
			 rndis_ul_max_xfer_size_rcvd,
			 param->max_pkt_per_xfer,
			 rndis_ul_max_pkt_per_xfer_rcvd);
			 rndis_ul_max_pkt_per_xfer_rcvd,
			param->pkt_alignment_factor);
	return 0;
}

@@ -1262,6 +1264,7 @@ int rndis_init(void)
		rndis_per_dev_params[i].confignr = i;
		rndis_per_dev_params[i].used = 0;
		rndis_per_dev_params[i].state = RNDIS_UNINITIALIZED;
		rndis_per_dev_params[i].pkt_alignment_factor = 0;
		rndis_per_dev_params[i].media_state
				= RNDIS_MEDIA_STATE_DISCONNECTED;
		INIT_LIST_HEAD(&(rndis_per_dev_params[i].resp_queue));
+4 −3
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@
 * Copyright (C) 2003-2005,2008 David Brownell
 * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger
 * Copyright (C) 2008 Nokia Corporation
 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
 * Copyright (c) 2012-2014, 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
@@ -93,7 +93,8 @@ int ecm_qc_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
int
rndis_qc_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
				u32 vendorID, const char *manufacturer,
					 u8 maxPktPerXfer, char *xport_name);
				u8 maxPktPerXfer, u8 pkt_alignment_factor,
				char *xport_name);

void gether_qc_get_macs(u8 dev_mac[ETH_ALEN], u8 host_mac[ETH_ALEN]);