Patchwork [U-Boot,5/5] USB-RNDIS: Send RNDIS state on disconnecting

login
register
mail settings
Submitter Vitaly Kuzmichev
Date Feb. 11, 2011, 3:18 p.m.
Message ID <1297437515-4069-6-git-send-email-vkuzmichev@mvista.com>
Download mbox | patch
Permalink /patch/82772/
State Accepted
Commit e4ae66608bbf8b7be9162e5933a98905dcf52d6b
Delegated to: Remy Bohmer
Headers show

Comments

Vitaly Kuzmichev - Feb. 11, 2011, 3:18 p.m.
Add waiting for receiving Ethernet gadget state on the Windows host
side before dropping pullup, but keep it for debug.

Signed-off-by: Vitaly Kuzmichev <vkuzmichev@mvista.com>
---
 drivers/usb/gadget/ether.c |   23 +++++++++++++++++++++++
 drivers/usb/gadget/rndis.c |    5 +++++
 drivers/usb/gadget/rndis.h |    8 ++++++++
 3 files changed, 36 insertions(+), 0 deletions(-)
Remy Bohmer - Feb. 19, 2011, 7:50 p.m.
Hi,

2011/2/11 Vitaly Kuzmichev <vkuzmichev@mvista.com>:
> Add waiting for receiving Ethernet gadget state on the Windows host
> side before dropping pullup, but keep it for debug.
>
> Signed-off-by: Vitaly Kuzmichev <vkuzmichev@mvista.com>
> ---
>  drivers/usb/gadget/ether.c |   23 +++++++++++++++++++++++
>  drivers/usb/gadget/rndis.c |    5 +++++
>  drivers/usb/gadget/rndis.h |    8 ++++++++
>  3 files changed, 36 insertions(+), 0 deletions(-)

Applied to u-boot-usb.

Thanks.

Remy

Patch

diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index f909267..9fb0e80 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -1921,10 +1921,22 @@  static void eth_start(struct eth_dev *dev, gfp_t gfp_flags)
 
 static int eth_stop(struct eth_dev *dev)
 {
+#ifdef RNDIS_COMPLETE_SIGNAL_DISCONNECT
+	unsigned long ts;
+	unsigned long timeout = CONFIG_SYS_HZ; /* 1 sec to stop RNDIS */
+#endif
+
 	if (rndis_active(dev)) {
 		rndis_set_param_medium(dev->rndis_config, NDIS_MEDIUM_802_3, 0);
 		rndis_signal_disconnect(dev->rndis_config);
 
+#ifdef RNDIS_COMPLETE_SIGNAL_DISCONNECT
+		/* Wait until host receives OID_GEN_MEDIA_CONNECT_STATUS */
+		ts = get_timer(0);
+		while (get_timer(ts) < timeout)
+			usb_gadget_handle_interrupts();
+#endif
+
 		rndis_uninit(dev->rndis_config);
 		dev->rndis = 0;
 	}
@@ -2486,6 +2498,17 @@  void usb_eth_halt(struct eth_device *netdev)
 	if (!dev->gadget)
 		return;
 
+	/*
+	 * Some USB controllers may need additional deinitialization here
+	 * before dropping pull-up (also due to hardware issues).
+	 * For example: unhandled interrupt with status stage started may
+	 * bring the controller to fully broken state (until board reset).
+	 * There are some variants to debug and fix such cases:
+	 * 1) In the case of RNDIS connection eth_stop can perform additional
+	 * interrupt handling. See RNDIS_COMPLETE_SIGNAL_DISCONNECT definition.
+	 * 2) 'pullup' callback in your UDC driver can be improved to perform
+	 * this deinitialization.
+	 */
 	eth_stop(dev);
 
 	usb_gadget_disconnect(dev->gadget);
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c
index 3e3f740..886c093 100644
--- a/drivers/usb/gadget/rndis.c
+++ b/drivers/usb/gadget/rndis.c
@@ -995,7 +995,12 @@  int rndis_signal_disconnect(int configNr)
 	rndis_per_dev_params[configNr].media_state
 			= NDIS_MEDIA_STATE_DISCONNECTED;
 
+#ifdef RNDIS_COMPLETE_SIGNAL_DISCONNECT
+	return rndis_indicate_status_msg(configNr,
+					  RNDIS_STATUS_MEDIA_DISCONNECT);
+#else
 	return 0;
+#endif
 }
 
 void rndis_uninit(int configNr)
diff --git a/drivers/usb/gadget/rndis.h b/drivers/usb/gadget/rndis.h
index 73a1204..d9e3a75 100644
--- a/drivers/usb/gadget/rndis.h
+++ b/drivers/usb/gadget/rndis.h
@@ -17,6 +17,14 @@ 
 
 #include "ndis.h"
 
+/*
+ * By default rndis_signal_disconnect does not send status message about
+ * RNDIS disconnection to USB host (indicated as cable disconnected).
+ * Define RNDIS_COMPLETE_SIGNAL_DISCONNECT to send it.
+ * However, this will cause 1 sec delay on Ethernet device halt.
+ * Usually you do not need to define it. Mostly usable for debugging.
+ */
+
 #define RNDIS_MAXIMUM_FRAME_SIZE	1518
 #define RNDIS_MAX_TOTAL_SIZE		1558