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

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

USB: IPA: RNDIS: Add both device and host side parameters



RNDIS IPA driver requires both host and device side different
parameters like max transfer size, number of packets and aggregation
status. This change provides these information to IPA driver by using
RNDIS initialization protocol.

CRs-Fixed: 679074
Change-Id: Ic755d61db79c093d5540a28276b9b428c5ffad92
Signed-off-by: default avatarRavi Gummadidala <rgummadi@codeaurora.org>
Signed-off-by: default avatarMayank Rana <mrana@codeaurora.org>
parent b91baddb
Loading
Loading
Loading
Loading
+27 −19
Original line number Diff line number Diff line
@@ -302,8 +302,8 @@ static void rndis_ipa_dump_skb(struct sk_buff *skb);
static int rndis_ipa_debugfs_init(struct rndis_ipa_dev *rndis_ipa_ctx);
static void rndis_ipa_debugfs_destroy(struct rndis_ipa_dev *rndis_ipa_ctx);
static int rndis_ipa_ep_registers_cfg(u32 usb_to_ipa_hdl,
		u32 ipa_to_usb_hdl, u32 max_transfer_size,
		u32 max_packet_number, u32 mtu,
		u32 ipa_to_usb_hdl, u32 max_xfer_size_bytes_to_dev,
		u32 max_xfer_size_bytes_to_host, u32 mtu,
		bool deaggr_enable);
static int rndis_ipa_set_device_ethernet_addr(u8 *dev_ethaddr,
		u8 device_ethaddr[]);
@@ -698,8 +698,9 @@ EXPORT_SYMBOL(rndis_ipa_init);
 */
int rndis_ipa_pipe_connect_notify(u32 usb_to_ipa_hdl,
			u32 ipa_to_usb_hdl,
			u32 max_transfer_byte_size,
			u32 max_packet_number,
			u32 max_xfer_size_bytes_to_dev,
			u32 max_packet_number_to_dev,
			u32 max_xfer_size_bytes_to_host,
			void *private)
{
	struct rndis_ipa_dev *rndis_ipa_ctx = private;
@@ -712,8 +713,11 @@ int rndis_ipa_pipe_connect_notify(u32 usb_to_ipa_hdl,

	RNDIS_IPA_DEBUG("usb_to_ipa_hdl=%d, ipa_to_usb_hdl=%d, private=0x%p\n",
				usb_to_ipa_hdl, ipa_to_usb_hdl, private);
	RNDIS_IPA_DEBUG("max_xfer_sz=%d, max_pkt_num=%d\n",
			max_transfer_byte_size, max_packet_number);
	RNDIS_IPA_DEBUG("max_xfer_sz_to_dev=%d, max_pkt_num_to_dev=%d\n",
			max_xfer_size_bytes_to_dev,
			max_packet_number_to_dev);
	RNDIS_IPA_DEBUG("max_xfer_sz_to_host=%d\n",
			max_xfer_size_bytes_to_host);

	next_state = rndis_ipa_next_state(rndis_ipa_ctx->state,
		RNDIS_IPA_CONNECT);
@@ -734,10 +738,14 @@ int rndis_ipa_pipe_connect_notify(u32 usb_to_ipa_hdl,
	}
	rndis_ipa_ctx->ipa_to_usb_hdl = ipa_to_usb_hdl;
	rndis_ipa_ctx->usb_to_ipa_hdl = usb_to_ipa_hdl;
	if (max_packet_number_to_dev > 1)
		rndis_ipa_ctx->deaggregation_enable = true;
	else
		rndis_ipa_ctx->deaggregation_enable = false;
	result = rndis_ipa_ep_registers_cfg(usb_to_ipa_hdl,
			ipa_to_usb_hdl,
			max_transfer_byte_size,
			max_packet_number,
			max_xfer_size_bytes_to_dev,
			max_xfer_size_bytes_to_host,
			rndis_ipa_ctx->net->mtu,
			rndis_ipa_ctx->deaggregation_enable);
	if (result) {
@@ -1876,12 +1884,10 @@ static bool rm_enabled(struct rndis_ipa_dev *rndis_ipa_ctx)
 *  the USB to IPA end-point
 * @ipa_to_usb_hdl: handle received from ipa_connect which represents
 *  the IPA to USB end-point
 * @max_transfer_byte_size: the maximum size, in bytes, that the device
 * @max_xfer_size_bytes_to_dev: the maximum size, in bytes, that the device
 *  expects to receive from the host. supplied on REMOTE_NDIS_INITIALIZE_CMPLT.
 * @max_packet_number: The maximum number of
 * concatenated REMOTE_NDIS_PACKET_MSG messages that the device can handle
 * in a single bus transfer to it.
 * This value MUST be at least 1.
 * @max_xfer_size_bytes_to_host: the maximum size, in bytes, that the host
 *  expects to receive from the device. supplied on REMOTE_NDIS_INITIALIZE_MSG.
 * @mtu: the netdev MTU size, in bytes
 *
 * USB to IPA pipe:
@@ -1897,8 +1903,8 @@ static bool rm_enabled(struct rndis_ipa_dev *rndis_ipa_ctx)
 */
static int rndis_ipa_ep_registers_cfg(u32 usb_to_ipa_hdl,
		u32 ipa_to_usb_hdl,
		u32 max_transfer_byte_size,
		u32 max_packet_number,
		u32 max_xfer_size_bytes_to_dev,
		u32 max_xfer_size_bytes_to_host,
		u32 mtu,
		bool deaggr_enable)
{
@@ -1913,7 +1919,7 @@ static int rndis_ipa_ep_registers_cfg(u32 usb_to_ipa_hdl,
		RNDIS_IPA_DEBUG("deaggregation disabled\n");
	}

	usb_to_ipa_ep_cfg->deaggr.max_packet_len = max_transfer_byte_size;
	usb_to_ipa_ep_cfg->deaggr.max_packet_len = max_xfer_size_bytes_to_dev;
	result = ipa_cfg_ep(usb_to_ipa_hdl, usb_to_ipa_ep_cfg);
	if (result) {
		pr_err("failed to configure USB to IPA point\n");
@@ -1921,9 +1927,9 @@ static int rndis_ipa_ep_registers_cfg(u32 usb_to_ipa_hdl,
	}
	RNDIS_IPA_DEBUG("IPA<-USB end-point configured\n");

	ipa_to_usb_ep_cfg.aggr.aggr_pkt_limit = max_packet_number;
	ipa_to_usb_ep_cfg.aggr.aggr_pkt_limit = 0;
	ipa_to_usb_ep_cfg.aggr.aggr_byte_limit =
		(max_transfer_byte_size - mtu)/1024;
		(max_xfer_size_bytes_to_host - mtu)/1024;
	result = ipa_cfg_ep(ipa_to_usb_hdl, &ipa_to_usb_ep_cfg);
	if (result) {
		pr_err("failed to configure IPA to USB end-point\n");
@@ -2676,8 +2682,10 @@ static int rndis_ipa_setup_loopback(bool enable,
	retval = rndis_ipa_pipe_connect_notify(
			rndis_ipa_ctx->usb_to_ipa_loopback_pipe.ipa_drv_ep_hdl,
			rndis_ipa_ctx->ipa_to_usb_loopback_pipe.ipa_drv_ep_hdl,
			BAM_DMA_DATA_FIFO_SIZE,
			15,
			BAM_DMA_DATA_FIFO_SIZE - rndis_ipa_ctx->net->mtu,
			15, rndis_ipa_ctx);
			rndis_ipa_ctx);
	if (retval) {
		RNDIS_IPA_ERROR("connect notify fail");
		return -ENODEV;
+15 −13
Original line number Diff line number Diff line
@@ -85,7 +85,7 @@ struct f_rndis_qc {
	u8				ctrl_id, data_id;
	u8				ethaddr[ETH_ALEN];
	u32				vendorID;
	u8				max_pkt_per_xfer;
	u8				ul_max_pkt_per_xfer;
	u8				pkt_alignment_factor;
	u32				max_pkt_size;
	const char			*manufacturer;
@@ -587,6 +587,7 @@ static void rndis_qc_command_complete(struct usb_ep *ep,
	struct f_rndis_qc		*rndis = req->context;
	int				status;
	rndis_init_msg_type		*buf;
	u32		ul_max_xfer_size, dl_max_xfer_size;

	/* received RNDIS command from USB_CDC_SEND_ENCAPSULATED_COMMAND */
	status = rndis_msg_parser(rndis->config, (u8 *) req->buf);
@@ -597,9 +598,10 @@ static void rndis_qc_command_complete(struct usb_ep *ep,
	buf = (rndis_init_msg_type *)req->buf;

	if (buf->MessageType == RNDIS_MSG_INIT) {
		rndis->max_pkt_size = buf->MaxTransferSize;
		pr_debug("MaxTransferSize: %d\n", buf->MaxTransferSize);
		u_bam_data_set_max_xfer_size(rndis->max_pkt_size);
		ul_max_xfer_size = rndis_get_ul_max_xfer_size(rndis->config);
		u_bam_data_set_ul_max_xfer_size(ul_max_xfer_size);
		dl_max_xfer_size = rndis_get_dl_max_xfer_size(rndis->config);
		u_bam_data_set_dl_max_xfer_size(dl_max_xfer_size);
	}
}

@@ -968,8 +970,8 @@ rndis_qc_bind(struct usb_configuration *c, struct usb_function *f)
		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);
				rndis->ul_max_pkt_per_xfer);
	rndis_set_max_pkt_xfer(rndis->config, rndis->ul_max_pkt_per_xfer);

	/* In case of aggregated packets QC device will request
	 * aliment to 4 (2^2).
@@ -1178,10 +1180,10 @@ rndis_qc_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
	rndis->manufacturer = manufacturer;

	/* if max_pkt_per_xfer was not configured set to default value */
	rndis->max_pkt_per_xfer =
	rndis->ul_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);
	u_bam_data_set_ul_max_pkt_num(rndis->ul_max_pkt_per_xfer);

	/*
	 * Check no RNDIS aggregation, and alignment if not mentioned,
@@ -1193,7 +1195,7 @@ rndis_qc_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
	 * those values will always override default values.
	 */
	if ((rndis->pkt_alignment_factor == 0) &&
			(rndis->max_pkt_per_xfer == 1))
			(rndis->ul_max_pkt_per_xfer == 1))
		rndis->pkt_alignment_factor = 0;
	else
		rndis->pkt_alignment_factor = pkt_alignment_factor ?
@@ -1288,14 +1290,14 @@ static long rndis_qc_ioctl(struct file *fp, unsigned cmd, unsigned long arg)
	switch (cmd) {
	case RNDIS_QC_GET_MAX_PKT_PER_XFER:
		ret = copy_to_user((void __user *)arg,
					&rndis->max_pkt_per_xfer,
					sizeof(rndis->max_pkt_per_xfer));
					&rndis->ul_max_pkt_per_xfer,
					sizeof(rndis->ul_max_pkt_per_xfer));
		if (ret) {
			pr_err("copying to user space failed\n");
			ret = -EFAULT;
		}
		pr_info("Sent max packets per xfer %d\n",
				rndis->max_pkt_per_xfer);
		pr_info("Sent UL max packets per xfer %d\n",
				rndis->ul_max_pkt_per_xfer);
		break;
	case RNDIS_QC_GET_MAX_PKT_SIZE:
		ret = copy_to_user((void __user *)arg,
+26 −1
Original line number Diff line number Diff line
@@ -615,6 +615,7 @@ static int rndis_init_response(int configNr, rndis_init_msg_type *buf)
	resp->AFListOffset = cpu_to_le32(0);
	resp->AFListSize = cpu_to_le32(0);

	params->ul_max_xfer_size = le32_to_cpu(resp->MaxTransferSize);
	params->resp_avail(params->v);
	return 0;
}
@@ -820,7 +821,7 @@ void rndis_set_host_mac(int configNr, const u8 *addr)
 */
int rndis_msg_parser(u8 configNr, u8 *buf)
{
	u32 MsgType, MsgLength;
	u32 MsgType, MsgLength, major, minor, max_transfer_size;
	__le32 *tmp;
	struct rndis_params *params;

@@ -845,6 +846,19 @@ int rndis_msg_parser(u8 configNr, u8 *buf)
	case RNDIS_MSG_INIT:
		pr_debug("%s: RNDIS_MSG_INIT\n",
			__func__);
		tmp++; /* to get RequestID */
		major = get_unaligned_le32(tmp++);
		minor = get_unaligned_le32(tmp++);
		max_transfer_size = get_unaligned_le32(tmp++);

		params->host_rndis_major_ver = major;
		params->host_rndis_minor_ver = minor;
		params->dl_max_xfer_size = max_transfer_size;

		pr_debug("%s(): RNDIS Host Major:%d Minor:%d version\n",
					__func__, major, minor);
		pr_debug("%s(): UL Max Transfer size:%x\n", __func__,
					max_transfer_size);
		params->state = RNDIS_INITIALIZED;
		return rndis_init_response(configNr,
					(rndis_init_msg_type *)buf);
@@ -967,6 +981,17 @@ int rndis_set_param_medium(u8 configNr, u32 medium, u32 speed)

	return 0;
}
u32 rndis_get_dl_max_xfer_size(u8 configNr)
{
	pr_debug("%s:\n", __func__);
	return rndis_per_dev_params[configNr].dl_max_xfer_size;
}

u32 rndis_get_ul_max_xfer_size(u8 configNr)
{
	pr_debug("%s:\n", __func__);
	return rndis_per_dev_params[configNr].ul_max_xfer_size;
}

void rndis_set_max_pkt_xfer(u8 configNr, u8 max_pkt_per_xfer)
{
+6 −0
Original line number Diff line number Diff line
@@ -196,6 +196,10 @@ typedef struct rndis_params
	void			*v;
	struct list_head	resp_queue;
	spinlock_t		lock;
	u32			host_rndis_major_ver;
	u32			host_rndis_minor_ver;
	u32			ul_max_xfer_size;
	u32			dl_max_xfer_size;
} rndis_params;

/* RNDIS Message parser and other useless functions */
@@ -208,6 +212,8 @@ int rndis_set_param_vendor (u8 configNr, u32 vendorID,
			    const char *vendorDescr);
int  rndis_set_param_medium (u8 configNr, u32 medium, u32 speed);
void rndis_set_max_pkt_xfer(u8 configNr, u8 max_pkt_per_xfer);
u32  rndis_get_ul_max_xfer_size(u8 configNr);
u32  rndis_get_dl_max_xfer_size(u8 configNr);
void rndis_add_hdr (struct sk_buff *skb);
int rndis_rm_hdr(struct gether *port, struct sk_buff *skb,
			struct sk_buff_head *list);
+42 −9
Original line number Diff line number Diff line
@@ -58,8 +58,12 @@ module_param(bam_data_mux_rx_req_size, uint, S_IRUGO | S_IWUSR);
#define MSM_VENDOR_ID			BIT(16)

struct rndis_data_ch_info {
	u32 max_transfer_size;
	u32 max_packets_number;
	/* this provides downlink (device->host i.e host) side configuration*/
	u32 dl_max_transfer_size;
	/* this provides uplink (host->device i.e device) side configuration */
	u32 ul_max_transfer_size;
	u32 ul_max_packets_number;
	bool ul_aggregation_enable;
	u32 prod_clnt_hdl;
	u32 cons_clnt_hdl;
	void *priv;
@@ -992,11 +996,19 @@ static void bam2bam_data_connect_work(struct work_struct *w)
				d->ipa_params.cons_clnt_hdl;
			rndis_data.priv = d->ipa_params.priv;

			pr_debug("ul_max_transfer_size:%d\n",
					rndis_data.ul_max_transfer_size);
			pr_debug("ul_max_packets_number:%d\n",
					rndis_data.ul_max_packets_number);
			pr_debug("dl_max_transfer_size:%d\n",
					rndis_data.dl_max_transfer_size);

			ret = rndis_ipa_pipe_connect_notify(
				rndis_data.cons_clnt_hdl,
				rndis_data.prod_clnt_hdl,
				rndis_data.max_transfer_size,
				rndis_data.max_packets_number,
				rndis_data.ul_max_transfer_size,
				rndis_data.ul_max_packets_number,
				rndis_data.dl_max_transfer_size,
				rndis_data.priv);
			if (ret) {
				pr_err("%s: failed to connect IPA: err:%d\n",
@@ -1650,17 +1662,18 @@ static void bam2bam_data_resume_work(struct work_struct *w)
	}
}

void u_bam_data_set_max_xfer_size(u32 max_transfer_size)
void u_bam_data_set_dl_max_xfer_size(u32 max_transfer_size)
{

	if (!max_transfer_size) {
		pr_err("%s: invalid parameters\n", __func__);
		return;
	}

	rndis_data.max_transfer_size = max_transfer_size;
	rndis_data.dl_max_transfer_size = max_transfer_size;
	pr_debug("%s(): dl_max_xfer_size:%d\n", __func__, max_transfer_size);
}

void u_bam_data_set_max_pkt_num(u32 max_packets_number)
void u_bam_data_set_ul_max_pkt_num(u8 max_packets_number)

{
	if (!max_packets_number) {
@@ -1668,5 +1681,25 @@ void u_bam_data_set_max_pkt_num(u32 max_packets_number)
		return;
	}

	rndis_data.max_packets_number = max_packets_number;
	rndis_data.ul_max_packets_number = max_packets_number;

	if (max_packets_number > 1)
		rndis_data.ul_aggregation_enable = true;
	else
		rndis_data.ul_aggregation_enable = false;

	pr_debug("%s(): ul_aggregation enable:%d\n", __func__,
				rndis_data.ul_aggregation_enable);
	pr_debug("%s(): ul_max_packets_number:%d\n", __func__,
				max_packets_number);
}

void u_bam_data_set_ul_max_xfer_size(u32 max_transfer_size)
{
	if (!max_transfer_size) {
		pr_err("%s: invalid parameters\n", __func__);
		return;
	}
	rndis_data.ul_max_transfer_size = max_transfer_size;
	pr_debug("%s(): ul_max_xfer_size:%d\n", __func__, max_transfer_size);
}
Loading