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

Commit 35d3ad1b authored by Mayank Rana's avatar Mayank Rana
Browse files

f_qc_rndis: Fix issue with bus resume while using Linux Host



Remote Wakeup disable with Window Host, USB bus suspend/resume case:
Windows host sends non-zero value RNDIS_PACKET_FILTER before initiating
bus suspend which initiates USB IPA disconnect functionality. For bus
resume case, after initiating bus resume windows host sends
RNIDS_INIT_MSG Or zero value RNDIS_PACKET_FILTER which initiates USB
Tx/Rx transfers and connection with IPA BAM.

In case of using Linux Host:
Linux host doesn't send any RNDIS message for both bus suspend and
resume case. Due to which after resuming device, there is no Tx/Rx
transfer being initiated which results in no IP Address assignment
with RNDIS USB network interface. Fix this issue by initiating
required operations as performed with windows host case and update
RNDIS state machine accordingly.

CRs-Fixed: 730343
Change-Id: Ifebbc0a9527096b5502a18f3062fd156bbd37bf1
Signed-off-by: default avatarMayank Rana <mrana@codeaurora.org>
parent f8fa637b
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -827,6 +827,14 @@ static void rndis_qc_suspend(struct usb_function *f)
	if (remote_wakeup_allowed) {
		bam_data_suspend(RNDIS_QC_ACTIVE_PORT);
	} else {
		/* This is required as Linux host side RNDIS driver doesn't
		 * send RNDIS_MESSAGE_PACKET_FILTER before suspending USB bus.
		 * Hence we perform same operations explicitly here for Linux
		 * host case. In case of windows, this RNDIS state machine is
		 * already updated due to receiving of PACKET_FILTER.
		 */
		rndis_flow_control(rndis->config, true);

		/*
		 * When remote wakeup is disabled, IPA BAM is disconnected
		 * because it cannot send new data until the USB bus is resumed.
@@ -874,6 +882,14 @@ static void rndis_qc_resume(struct usb_function *f)
		rndis->bam_port.in->desc  = rndis->in_ep_desc_backup;
		rndis->bam_port.out->desc = rndis->out_ep_desc_backup;
		rndis_qc_bam_connect(rndis);
		/*
		 * Linux Host doesn't sends RNDIS_MSG_INIT or non-zero value
		 * set with RNDIS_MESSAGE_PACKET_FILTER after performing bus
		 * resume. Hence trigger USB IPA transfer functionality
		 * explicitly here. For Windows host case is also being
		 * handle with RNDIS state machine.
		 */
		rndis_flow_control(rndis->config, false);
	}

	pr_debug("%s: RNDIS resume completed\n", __func__);
+39 −17
Original line number Diff line number Diff line
@@ -544,24 +544,11 @@ static int gen_ndis_set_resp(u8 configNr, u32 OID, u8 *buf, u32 buf_len,
		 */
		retval = 0;
		if (*params->filter) {
			if (!is_rndis_ipa_supported()) {
				netif_carrier_on(params->dev);
				if (netif_running(params->dev))
					netif_wake_queue(params->dev);
			pr_debug("%s(): disable flow control\n", __func__);
			rndis_flow_control(configNr, false);
		} else {
				if (params->state != RNDIS_DATA_INITIALIZED)
					u_bam_data_start_rndis_ipa();
			}
			params->state = RNDIS_DATA_INITIALIZED;
		} else {
			if (!is_rndis_ipa_supported()) {
				netif_carrier_off(params->dev);
				netif_stop_queue(params->dev);
			} else {
				if (params->state == RNDIS_DATA_INITIALIZED)
					u_bam_data_stop_rndis_ipa();
			}
			params->state = RNDIS_INITIALIZED;
			pr_debug("%s(): enable flow control\n", __func__);
			rndis_flow_control(configNr, true);
		}
		break;

@@ -1013,6 +1000,41 @@ void rndis_set_pkt_alignment_factor(u8 configNr, u8 pkt_alignment_factor)
	rndis_per_dev_params[configNr].pkt_alignment_factor =
					pkt_alignment_factor;
}
/**
 * rndis_flow_control: enable/disable flow control with USB RNDIS interface
 * confignr - RNDIS network interface number
 * enable_flow_control - true: perform flow control, false: disable flow control
 *
 * In BAM2BAM IPA mode, this function triggers functionality to start/stop
 * endless transfers, otherwise it enables/disables RNDIS network interface.
 */
void rndis_flow_control(u8 confignr, bool enable_flow_control)
{
	struct rndis_params *params;

	params = &rndis_per_dev_params[confignr];
	pr_debug("%s(): params->state:%x\n", __func__, params->state);
	if (enable_flow_control) {
		if (is_rndis_ipa_supported() &&
			params->state == RNDIS_DATA_INITIALIZED) {
			u_bam_data_stop_rndis_ipa();
		} else {
			netif_carrier_off(params->dev);
			netif_stop_queue(params->dev);
		}
		params->state = RNDIS_INITIALIZED;
	} else {
		if (is_rndis_ipa_supported() &&
			params->state != RNDIS_DATA_INITIALIZED) {
			u_bam_data_start_rndis_ipa();
		} else {
			netif_carrier_on(params->dev);
			if (netif_running(params->dev))
				netif_wake_queue(params->dev);
		}
		params->state = RNDIS_DATA_INITIALIZED;
	}
}

void rndis_add_hdr(struct sk_buff *skb)
{
+1 −1
Original line number Diff line number Diff line
@@ -228,5 +228,5 @@ extern void rndis_set_host_mac (int configNr, const u8 *addr);
extern bool is_rndis_ipa_supported(void);
int rndis_init(void);
void rndis_exit (void);

void rndis_flow_control(u8 confignr, bool enable_flow_control);
#endif  /* _LINUX_RNDIS_H */