--- usbnet.c.orig	Sun Feb 18 16:10:47 2001
+++ usbnet.c	Mon Feb 19 01:05:42 2001
@@ -61,6 +61,8 @@
  * 08-feb-2001	stubbed in "linuxdev", maybe the SA-1100 folk can use it;
  *		AnchorChips 2720 support (from spec) for testing;
  *		fix bit-ordering problem with ethernet multicast addr
+ * 19-feb-2001  Support for clearing halt conditions. SA1100 UDC support
+ *		updates. Oleg Drokin (green@iXcelerator.com)
  *
  *-------------------------------------------------------------------------*/
 
@@ -85,7 +87,7 @@
 
 
 #define	CONFIG_USB_AN2720
-// #define	CONFIG_USB_LINUXDEV
+#define	CONFIG_USB_LINUXDEV
 #define	CONFIG_USB_NET1080
 #define	CONFIG_USB_PL2301
 
@@ -145,6 +147,7 @@
 	struct sk_buff_head	txq;
 	struct sk_buff_head	done;
 	struct tasklet_struct	bh;
+	struct tq_struct ctrl_task;
 };
 
 // device-specific info used by the driver
@@ -226,13 +229,13 @@
 	// all else is optional, and must start with:
 	// u16	vendorId;		// from usb-if
 	// u16	productId;
-};
+} __attribute__((__packed__));
 
 #define	PAD_BYTE	((unsigned char)0xAC)
 
 struct nc_trailer {
 	u16	packet_id;
-};
+} __attribute__((__packed__));
 
 // packets may use FLAG_FRAMING and optional pad
 #define FRAMED_SIZE(mtu) (sizeof (struct nc_header) \
@@ -294,7 +297,7 @@
 	description:	"Linux Device",
 	// no reset defined (yet?)
 	// no check_connect needed!
-
+	flags:		FLAG_FRAMING,
 	in: 2, out: 1,
 	epsize:	64,
 };
@@ -1049,6 +1052,17 @@
 }
 
 /*-------------------------------------------------------------------------*/
+/* usb_clear_halt cannot be called in interrupt context */
+
+static void
+tx_clear_halt(void *data)
+{
+	struct usbnet		*dev = data;
+
+	usb_clear_halt( dev->udev, usb_sndbulkpipe (dev->udev, dev->driver_info->out));
+}
+
+/*-------------------------------------------------------------------------*/
 
 static void tx_complete (struct urb *urb)
 {
@@ -1056,6 +1070,15 @@
 	struct skb_data		*entry = (struct skb_data *) skb->cb;
 	struct usbnet		*dev = entry->dev;
 
+	if (urb->status == USB_ST_STALL) {
+		if (dev->ctrl_task.sync == 0) {
+			dev->ctrl_task.routine = tx_clear_halt;
+			dev->ctrl_task.data = dev;
+			schedule_task(&dev->ctrl_task);
+		} else {
+			printk("Cannot clear TX stall\n");
+		}
+	}
 	urb->dev = 0;
 	entry->state = tx_done;
 	defer_bh (dev, skb);

