patch-2.4.15 linux/drivers/usb/usbnet.c
Next file: linux/drivers/video/Config.in
Previous file: linux/drivers/usb/usb.c
Back to the patch index
Back to the overall index
- Lines: 953
- Date:
Wed Nov 21 09:51:08 2001
- Orig file:
v2.4.14/linux/drivers/usb/usbnet.c
- Orig date:
Mon Nov 5 15:55:32 2001
diff -u --recursive --new-file v2.4.14/linux/drivers/usb/usbnet.c linux/drivers/usb/usbnet.c
@@ -16,6 +16,7 @@
*
* - AnchorChip 2720
* - Belkin, eTEK (interops with Win32 drivers)
+ * - GeneSys GL620USB-A
* - "Linux Devices" (like iPaq and similar SA-1100 based PDAs)
* - NetChip 1080 (interoperates with NetChip Win32 drivers)
* - Prolific PL-2301/2302 (replaces "plusb" driver)
@@ -76,6 +77,11 @@
* 17-oct-2001 Handle "Advance USBNET" product, like Belkin/eTEK devices,
* from Ioannis Mavroukakis <i.mavroukakis@btinternet.com>;
* rx unlinks somehow weren't async; minor cleanup.
+ * 03-nov-2001 Merged GeneSys driver; original code from Jiun-Jie Huang
+ * <huangjj@genesyslogic.com.tw>, updated by Stanislav Brabec
+ * <utx@penguin.cz>. Made framing options (NetChip/GeneSys)
+ * tie mostly to (sub)driver info. Workaround some PL-2302
+ * chips that seem to reject SET_INTERFACE requests.
*
*-------------------------------------------------------------------------*/
@@ -101,6 +107,7 @@
#define CONFIG_USB_AN2720
#define CONFIG_USB_BELKIN
+#define CONFIG_USB_GENESYS
#define CONFIG_USB_LINUXDEV
#define CONFIG_USB_NET1080
#define CONFIG_USB_PL2301
@@ -157,7 +164,10 @@
// protocol/interface state
struct net_device net;
struct net_device_stats stats;
+
+#ifdef CONFIG_USB_NET1080
u16 packet_id;
+#endif
// various kinds of pending driver work
struct sk_buff_head rxq;
@@ -173,6 +183,7 @@
int flags;
#define FLAG_FRAMING_NC 0x0001 /* guard against device dropouts */
+#define FLAG_FRAMING_GL 0x0002 /* genelink batches packets */
#define FLAG_NO_SETINT 0x0010 /* device can't set_interface() */
/* reset device ... can sleep */
@@ -181,7 +192,15 @@
/* see if peer is connected ... can sleep */
int (*check_connect)(struct usbnet *);
+ /* fixup rx packet (strip framing) */
+ int (*rx_fixup)(struct usbnet *dev, struct sk_buff *skb);
+
+ /* fixup tx packet (add framing) */
+ struct sk_buff *(*tx_fixup)(struct usbnet *dev,
+ struct sk_buff *skb, int flags);
+
// FIXME -- also an interrupt mechanism
+ // useful for at least PL2301/2302 and GL620USB-A
/* framework currently "knows" bulk EPs talk packets */
int in; /* rx endpoint */
@@ -224,47 +243,6 @@
#define devinfo(usbnet, fmt, arg...) \
printk(KERN_INFO "%s: " fmt "\n" , (usbnet)->net.name, ## arg)
-/*-------------------------------------------------------------------------
- *
- * NetChip framing of ethernet packets, supporting additional error
- * checks for links that may drop bulk packets from inside messages.
- * Odd USB length == always short read for last usb packet.
- * - nc_header
- * - Ethernet header (14 bytes)
- * - payload
- * - (optional padding byte, if needed so length becomes odd)
- * - nc_trailer
- *
- * This framing is to be avoided for non-NetChip devices.
- */
-
-struct nc_header { // packed:
- u16 hdr_len; // sizeof nc_header (LE, all)
- u16 packet_len; // payload size (including ethhdr)
- u16 packet_id; // detects dropped packets
-#define MIN_HEADER 6
-
- // 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_NC and optional pad
-#define FRAMED_SIZE(mtu) (sizeof (struct nc_header) \
- + sizeof (struct ethhdr) \
- + (mtu) \
- + 1 \
- + sizeof (struct nc_trailer))
-
-#define MIN_FRAMED FRAMED_SIZE(0)
-
-
#ifdef CONFIG_USB_AN2720
@@ -313,6 +291,330 @@
+#ifdef CONFIG_USB_GENESYS
+
+/*-------------------------------------------------------------------------
+ *
+ * GeneSys GL620USB-A (www.genesyslogic.com.tw)
+ *
+ * ... should partially interop with the Win32 driver for this hardware
+ * The GeneSys docs imply there's some NDIS issue motivating this framing.
+ *
+ *-------------------------------------------------------------------------*/
+
+// control msg write command
+#define GENELINK_CONNECT_WRITE 0xF0
+// interrupt pipe index
+#define GENELINK_INTERRUPT_PIPE 0x03
+// interrupt read buffer size
+#define INTERRUPT_BUFSIZE 0x08
+// interrupt pipe interval value
+#define GENELINK_INTERRUPT_INTERVAL 0x10
+// max transmit packet number per transmit
+#define GL_MAX_TRANSMIT_PACKETS 32
+// max packet length
+#define GL_MAX_PACKET_LEN 1514
+// max receive buffer size
+#define GL_RCV_BUF_SIZE \
+ (((GL_MAX_PACKET_LEN + 4) * GL_MAX_TRANSMIT_PACKETS) + 4)
+
+struct gl_packet {
+ u32 packet_length;
+ char packet_data [1];
+};
+
+struct gl_header {
+ u32 packet_count;
+ struct gl_packet packets;
+};
+
+#ifdef GENLINK_ACK
+
+// FIXME: this code is incomplete, not debugged; it doesn't
+// handle interrupts correctly. interrupts should be generic
+// code like all other device I/O, anyway.
+
+struct gl_priv {
+ struct urb *irq_urb;
+ char irq_buf [INTERRUPT_BUFSIZE];
+};
+
+static inline int gl_control_write (struct usbnet *dev, u8 request, u16 value)
+{
+ int retval;
+
+ retval = usb_control_msg (dev->udev,
+ usb_sndctrlpipe (dev->udev, 0),
+ request,
+ USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ value,
+ 0, // index
+ 0, // data buffer
+ 0, // size
+ CONTROL_TIMEOUT_JIFFIES);
+ return retval;
+}
+
+static void gl_interrupt_complete (struct urb *urb)
+{
+ int status = urb->status;
+
+ if (status)
+ dbg ("gl_interrupt_complete fail - %X", status);
+ else
+ dbg ("gl_interrupt_complete success...");
+}
+
+static int gl_interrupt_read (struct usbnet *dev)
+{
+ struct gl_priv *priv = dev->priv_data;
+ int retval;
+
+ // issue usb interrupt read
+ if (priv && priv->irq_urb) {
+ // submit urb
+ if ((retval = usb_submit_urb (priv->irq_urb)) != 0)
+ dbg ("gl_interrupt_read: submit fail - %X...", retval);
+ else
+ dbg ("gl_interrupt_read: submit success...");
+ }
+
+ return 0;
+}
+
+// check whether another side is connected
+static int genelink_check_connect (struct usbnet *dev)
+{
+ int retval;
+
+ dbg ("genelink_check_connect...");
+
+ // detect whether another side is connected
+ if ((retval = gl_control_write (dev, GENELINK_CONNECT_WRITE, 0)) != 0) {
+ dbg ("%s: genelink_check_connect write fail - %X",
+ dev->net.name, retval);
+ return retval;
+ }
+
+ // usb interrupt read to ack another side
+ if ((retval = gl_interrupt_read (dev)) != 0) {
+ dbg ("%s: genelink_check_connect read fail - %X",
+ dev->net.name, retval);
+ return retval;
+ }
+
+ dbg ("%s: genelink_check_connect read success", dev->net.name);
+ return 0;
+}
+
+// allocate and initialize the private data for genelink
+static int genelink_init (struct usbnet *dev)
+{
+ struct gl_priv *priv;
+
+ // allocate the private data structure
+ if ((priv = kmalloc (sizeof *priv, GFP_KERNEL)) == 0) {
+ dbg ("%s: cannot allocate private data per device",
+ dev->net.name);
+ return -ENOMEM;
+ }
+
+ // allocate irq urb
+ if ((priv->irq_urb = usb_alloc_urb (0)) == 0) {
+ dbg ("%s: cannot allocate private irq urb per device",
+ dev->net.name);
+ kfree (priv);
+ return -ENOMEM;
+ }
+
+ // fill irq urb
+ FILL_INT_URB (priv->irq_urb, dev->udev,
+ usb_rcvintpipe (dev->udev, GENELINK_INTERRUPT_PIPE),
+ priv->irq_buf, INTERRUPT_BUFSIZE,
+ gl_interrupt_complete, 0,
+ GENELINK_INTERRUPT_INTERVAL);
+
+ // set private data pointer
+ dev->priv_data = priv;
+
+ return 0;
+}
+
+// release the private data
+static int genelink_free (struct usbnet *dev)
+{
+ struct gl_priv *priv = dev->priv_data;
+
+ if (!priv)
+ return 0;
+
+// FIXME: can't cancel here; it's synchronous, and
+// should have happened earlier in any case (interrupt
+// handling needs to be generic)
+
+ // cancel irq urb first
+ usb_unlink_urb (priv->irq_urb);
+
+ // free irq urb
+ usb_free_urb (priv->irq_urb);
+
+ // free the private data structure
+ kfree (priv);
+
+ return 0;
+}
+
+#else
+
+static int genelink_check_connect (struct usbnet *dev)
+{
+ dbg ("%s: assuming peer is connected", dev->net.name);
+ return 0;
+}
+
+#endif
+
+// reset the device status
+static int genelink_reset (struct usbnet *dev)
+{
+ // we don't need to reset, just return 0
+ return 0;
+}
+
+static int genelink_rx_fixup (struct usbnet *dev, struct sk_buff *skb)
+{
+ struct gl_header *header;
+ struct gl_packet *packet;
+ struct sk_buff *gl_skb;
+ int status;
+ u32 size;
+
+ header = (struct gl_header *) skb->data;
+
+ // get the packet count of the received skb
+ le32_to_cpus (&header->packet_count);
+ if ((header->packet_count > GL_MAX_TRANSMIT_PACKETS)
+ || (header->packet_count < 0)) {
+ dbg ("genelink: illegal received packet count %d",
+ header->packet_count);
+ return 0;
+ }
+
+ // set the current packet pointer to the first packet
+ packet = &header->packets;
+
+ // decrement the length for the packet count size 4 bytes
+ skb_pull (skb, 4);
+
+ while (header->packet_count > 1) {
+ // get the packet length
+ size = packet->packet_length;
+
+ // this may be a broken packet
+ if (size > GL_MAX_PACKET_LEN) {
+ dbg ("genelink: illegal rx length %d", size);
+ return 0;
+ }
+
+ // allocate the skb for the individual packet
+ gl_skb = alloc_skb (size, GFP_ATOMIC);
+ if (gl_skb == 0)
+ return 0;
+
+ // copy the packet data to the new skb
+ memcpy (gl_skb->data, packet->packet_data, size);
+
+ // set skb data size
+ gl_skb->len = size;
+ gl_skb->dev = &dev->net;
+
+ // determine the packet's protocol ID
+ gl_skb->protocol = eth_type_trans (gl_skb, &dev->net);
+
+ // update the status
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += size;
+
+ // notify os of the received packet
+ status = netif_rx (gl_skb);
+
+ // advance to the next packet
+ packet = (struct gl_packet *)
+ &packet->packet_data [size];
+ header->packet_count--;
+
+ // shift the data pointer to the next gl_packet
+ skb_pull (skb, size + 4);
+ }
+
+ // skip the packet length field 4 bytes
+ skb_pull (skb, 4);
+
+ if (skb->len > GL_MAX_PACKET_LEN) {
+ dbg ("genelink: illegal rx length %d", skb->len);
+ return 0;
+ }
+ return 1;
+}
+
+static struct sk_buff *
+genelink_tx_fixup (struct usbnet *dev, struct sk_buff *skb, int flags)
+{
+ int padlen;
+ int length = skb->len;
+ int headroom = skb_headroom (skb);
+ int tailroom = skb_tailroom (skb);
+ u32 *packet_count;
+ u32 *packet_len;
+
+ // FIXME: magic numbers, bleech
+ padlen = ((skb->len + (4 + 4*1)) % 64) ? 0 : 1;
+
+ if ((!skb_cloned (skb))
+ && ((headroom + tailroom) >= (padlen + (4 + 4*1)))) {
+ if ((headroom < (4 + 4*1)) || (tailroom < padlen)) {
+ skb->data = memmove (skb->head + (4 + 4*1),
+ skb->data, skb->len);
+ skb->tail = skb->data + skb->len;
+ }
+ } else {
+ struct sk_buff *skb2;
+ skb2 = skb_copy_expand (skb, (4 + 4*1) , padlen, flags);
+ dev_kfree_skb_any (skb);
+ skb = skb2;
+ }
+
+ // attach the packet count to the header
+ packet_count = (u32 *) skb_push (skb, (4 + 4*1));
+ packet_len = packet_count + 1;
+
+ // FIXME little endian?
+ *packet_count = 1;
+ *packet_len = length;
+
+ // add padding byte
+ if ((skb->len % EP_SIZE (dev)) == 0)
+ skb_put (skb, 1);
+
+ return skb;
+}
+
+static const struct driver_info genelink_info = {
+ description: "Genesys GeneLink",
+ flags: FLAG_FRAMING_GL | FLAG_NO_SETINT,
+ reset: genelink_reset,
+ check_connect: genelink_check_connect,
+ rx_fixup: genelink_rx_fixup,
+ tx_fixup: genelink_tx_fixup,
+
+ in: 1, out: 2,
+ epsize: 64,
+};
+
+#endif /* CONFIG_USB_GENESYS */
+
+
+
#ifdef CONFIG_USB_LINUXDEV
/*-------------------------------------------------------------------------
@@ -348,10 +650,51 @@
/*-------------------------------------------------------------------------
*
* Netchip 1080 driver ... http://www.netchip.com
+ * Used in LapLink cables
*
*-------------------------------------------------------------------------*/
/*
+ * NetChip framing of ethernet packets, supporting additional error
+ * checks for links that may drop bulk packets from inside messages.
+ * Odd USB length == always short read for last usb packet.
+ * - nc_header
+ * - Ethernet header (14 bytes)
+ * - payload
+ * - (optional padding byte, if needed so length becomes odd)
+ * - nc_trailer
+ *
+ * This framing is to be avoided for non-NetChip devices.
+ */
+
+struct nc_header { // packed:
+ u16 hdr_len; // sizeof nc_header (LE, all)
+ u16 packet_len; // payload size (including ethhdr)
+ u16 packet_id; // detects dropped packets
+#define MIN_HEADER 6
+
+ // 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_NC and optional pad
+#define FRAMED_SIZE(mtu) (sizeof (struct nc_header) \
+ + sizeof (struct ethhdr) \
+ + (mtu) \
+ + 1 \
+ + sizeof (struct nc_trailer))
+
+#define MIN_FRAMED FRAMED_SIZE(0)
+
+
+/*
* Zero means no timeout; else, how long a 64 byte bulk packet may be queued
* before the hardware drops it. If that's done, the driver will need to
* frame network packets to guard against the dropped USB packets. The win32
@@ -636,11 +979,113 @@
return 0;
}
+static int net1080_rx_fixup (struct usbnet *dev, struct sk_buff *skb)
+{
+ struct nc_header *header;
+ struct nc_trailer *trailer;
+
+ if (!(skb->len & 0x01)
+ || MIN_FRAMED > skb->len
+ || skb->len > FRAMED_SIZE (dev->net.mtu)) {
+ dev->stats.rx_frame_errors++;
+ dbg ("rx framesize %d range %d..%d mtu %d", skb->len,
+ MIN_FRAMED, FRAMED_SIZE (dev->net.mtu),
+ dev->net.mtu
+ );
+ return 0;
+ }
+
+ header = (struct nc_header *) skb->data;
+ le16_to_cpus (&header->hdr_len);
+ le16_to_cpus (&header->packet_len);
+ if (FRAMED_SIZE (header->packet_len) > MAX_PACKET) {
+ dev->stats.rx_frame_errors++;
+ dbg ("packet too big, %d", header->packet_len);
+ return 0;
+ } else if (header->hdr_len < MIN_HEADER) {
+ dev->stats.rx_frame_errors++;
+ dbg ("header too short, %d", header->hdr_len);
+ return 0;
+ } else if (header->hdr_len > MIN_HEADER) {
+ // out of band data for us?
+ dbg ("header OOB, %d bytes",
+ header->hdr_len - MIN_HEADER);
+ // switch (vendor/product ids) { ... }
+ }
+ skb_pull (skb, header->hdr_len);
+
+ trailer = (struct nc_trailer *)
+ (skb->data + skb->len - sizeof *trailer);
+ skb_trim (skb, skb->len - sizeof *trailer);
+
+ if ((header->packet_len & 0x01) == 0) {
+ if (skb->data [header->packet_len] != PAD_BYTE) {
+ dev->stats.rx_frame_errors++;
+ dbg ("bad pad");
+ return 0;
+ }
+ skb_trim (skb, skb->len - 1);
+ }
+ if (skb->len != header->packet_len) {
+ dev->stats.rx_frame_errors++;
+ dbg ("bad packet len %d (expected %d)",
+ skb->len, header->packet_len);
+ return 0;
+ }
+ if (header->packet_id != get_unaligned (&trailer->packet_id)) {
+ dev->stats.rx_fifo_errors++;
+ dbg ("(2+ dropped) rx packet_id mismatch 0x%x 0x%x",
+ header->packet_id, trailer->packet_id);
+ return 0;
+ }
+#if 0
+ devdbg (dev, "frame <rx h %d p %d id %d", header->hdr_len,
+ header->packet_len, header->packet_id);
+#endif
+ return 1;
+}
+
+static struct sk_buff *
+net1080_tx_fixup (struct usbnet *dev, struct sk_buff *skb, int flags)
+{
+ int padlen;
+ struct sk_buff *skb2;
+
+ padlen = ((skb->len + sizeof (struct nc_header)
+ + sizeof (struct nc_trailer)) & 0x01) ? 0 : 1;
+ if (!skb_cloned (skb)) {
+ int headroom = skb_headroom (skb);
+ int tailroom = skb_tailroom (skb);
+
+ if ((padlen + sizeof (struct nc_trailer)) <= tailroom
+ && sizeof (struct nc_header) <= headroom)
+ return skb;
+
+ if ((sizeof (struct nc_header) + padlen
+ + sizeof (struct nc_trailer)) <
+ (headroom + tailroom)) {
+ skb->data = memmove (skb->head
+ + sizeof (struct nc_header),
+ skb->data, skb->len);
+ skb->tail = skb->data + skb->len;
+ return skb;
+ }
+ }
+ skb2 = skb_copy_expand (skb,
+ sizeof (struct nc_header),
+ sizeof (struct nc_trailer) + padlen,
+ flags);
+ dev_kfree_skb_any (skb);
+ return skb2;
+}
+
static const struct driver_info net1080_info = {
description: "NetChip TurboCONNECT",
flags: FLAG_FRAMING_NC,
reset: net1080_reset,
check_connect: net1080_check_connect,
+ rx_fixup: net1080_rx_fixup,
+ tx_fixup: net1080_tx_fixup,
in: 1, out: 1, // direction distinguishes these
epsize: 64,
@@ -714,6 +1159,8 @@
static const struct driver_info prolific_info = {
description: "Prolific PL-2301/PL-2302",
+ flags: FLAG_NO_SETINT,
+ /* some PL-2302 versions seem to fail usb_set_interface() */
reset: pl_reset,
check_connect: pl_check_connect,
@@ -737,11 +1184,19 @@
if (new_mtu <= MIN_PACKET || new_mtu > MAX_PACKET)
return -EINVAL;
+#ifdef CONFIG_USB_NET1080
if (((dev->driver_info->flags) & FLAG_FRAMING_NC)) {
if (FRAMED_SIZE (new_mtu) > MAX_PACKET)
return -EINVAL;
+ }
+#endif
+#ifdef CONFIG_USB_GENESYS
+ if (((dev->driver_info->flags) & FLAG_FRAMING_GL)
+ && new_mtu > GL_MAX_PACKET_LEN)
+ return -EINVAL;
+#endif
// no second zero-length packet read wanted after mtu-sized packets
- } else if (((new_mtu + sizeof (struct ethhdr)) % EP_SIZE (dev)) == 0)
+ if (((new_mtu + sizeof (struct ethhdr)) % EP_SIZE (dev)) == 0)
return -EDOM;
net->mtu = new_mtu;
return 0;
@@ -785,9 +1240,16 @@
unsigned long lockflags;
size_t size;
+#ifdef CONFIG_USB_NET1080
if (dev->driver_info->flags & FLAG_FRAMING_NC)
size = FRAMED_SIZE (dev->net.mtu);
else
+#endif
+#ifdef CONFIG_USB_GENESYS
+ if (dev->driver_info->flags & FLAG_FRAMING_GL)
+ size = GL_RCV_BUF_SIZE;
+ else
+#endif
size = (sizeof (struct ethhdr) + dev->net.mtu);
if ((skb = alloc_skb (size, flags)) == 0) {
@@ -841,72 +1303,10 @@
static inline void rx_process (struct usbnet *dev, struct sk_buff *skb)
{
- if (dev->driver_info->flags & FLAG_FRAMING_NC) {
- struct nc_header *header;
- struct nc_trailer *trailer;
-
- if (!(skb->len & 0x01)
- || MIN_FRAMED > skb->len
- || skb->len > FRAMED_SIZE (dev->net.mtu)) {
- dev->stats.rx_frame_errors++;
- dbg ("rx framesize %d range %d..%d mtu %d", skb->len,
- MIN_FRAMED, FRAMED_SIZE (dev->net.mtu),
- dev->net.mtu
- );
- goto error;
- }
-
- header = (struct nc_header *) skb->data;
- le16_to_cpus (&header->hdr_len);
- le16_to_cpus (&header->packet_len);
- if (FRAMED_SIZE (header->packet_len) > MAX_PACKET) {
- dev->stats.rx_frame_errors++;
- dbg ("packet too big, %d", header->packet_len);
- goto error;
- } else if (header->hdr_len < MIN_HEADER) {
- dev->stats.rx_frame_errors++;
- dbg ("header too short, %d", header->hdr_len);
- goto error;
- } else if (header->hdr_len > MIN_HEADER) {
- // out of band data for us?
- dbg ("header OOB, %d bytes",
- header->hdr_len - MIN_HEADER);
- // switch (vendor/product ids) { ... }
- }
- skb_pull (skb, header->hdr_len);
-
- trailer = (struct nc_trailer *)
- (skb->data + skb->len - sizeof *trailer);
- skb_trim (skb, skb->len - sizeof *trailer);
-
- if ((header->packet_len & 0x01) == 0) {
- if (skb->data [header->packet_len] != PAD_BYTE) {
- dev->stats.rx_frame_errors++;
- dbg ("bad pad");
- goto error;
- }
- skb_trim (skb, skb->len - 1);
- }
- if (skb->len != header->packet_len) {
- dev->stats.rx_frame_errors++;
- dbg ("bad packet len %d (expected %d)",
- skb->len, header->packet_len);
- goto error;
- }
- if (header->packet_id != get_unaligned (&trailer->packet_id)) {
- dev->stats.rx_fifo_errors++;
- dbg ("(2+ dropped) rx packet_id mismatch 0x%x 0x%x",
- header->packet_id, trailer->packet_id);
- goto error;
- }
-#if 0
- devdbg (dev, "frame <rx h %d p %d id %d", header->hdr_len,
- header->packet_len, header->packet_id);
-#endif
- } else {
- // we trust the network stack to remove
- // the extra byte we may have appended
- }
+ if (dev->driver_info->rx_fixup
+ && !dev->driver_info->rx_fixup (dev, skb))
+ goto error;
+ // else network stack removes extra byte if we forced a short packet
if (skb->len) {
int status;
@@ -922,7 +1322,7 @@
devdbg (dev, "< rx, len %d, type 0x%x",
skb->len + sizeof (struct ethhdr), skb->protocol);
#endif
- memset (skb->cb,0,sizeof(struct skb_data));
+ memset (skb->cb, 0, sizeof (struct skb_data));
status = netif_rx (skb);
if (status != NET_RX_SUCCESS)
devdbg (dev, "netif_rx status %d", status);
@@ -1040,7 +1440,7 @@
DECLARE_WAITQUEUE (wait, current);
mutex_lock (&dev->mutex);
- netif_stop_queue(net);
+ netif_stop_queue (net);
devdbg (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld",
dev->stats.rx_packets, dev->stats.tx_packets,
@@ -1056,7 +1456,7 @@
while (skb_queue_len (&dev->rxq)
&& skb_queue_len (&dev->txq)
&& skb_queue_len (&dev->done)) {
- set_current_state(TASK_UNINTERRUPTIBLE);
+ set_current_state (TASK_UNINTERRUPTIBLE);
schedule_timeout (UNLINK_TIMEOUT_JIFFIES);
dbg ("waited for %d urb completions", temp);
}
@@ -1099,8 +1499,10 @@
netif_start_queue (net);
devdbg (dev, "open: enable queueing (rx %d, tx %d) mtu %d %s framing",
RX_QLEN, TX_QLEN, dev->net.mtu,
- (info->flags & FLAG_FRAMING_NC)
- ? "NetChip"
+ (info->flags & (FLAG_FRAMING_NC | FLAG_FRAMING_GL))
+ ? ((info->flags & FLAG_FRAMING_NC)
+ ? "NetChip"
+ : "GeneSys")
: "raw"
);
@@ -1116,7 +1518,7 @@
/* usb_clear_halt cannot be called in interrupt context */
static void
-tx_clear_halt(void *data)
+tx_clear_halt (void *data)
{
struct usbnet *dev = data;
@@ -1137,7 +1539,7 @@
if (dev->ctrl_task.sync == 0) {
dev->ctrl_task.routine = tx_clear_halt;
dev->ctrl_task.data = dev;
- schedule_task(&dev->ctrl_task);
+ schedule_task (&dev->ctrl_task);
} else {
dbg ("Cannot clear TX stall");
}
@@ -1161,41 +1563,6 @@
/*-------------------------------------------------------------------------*/
-static inline struct sk_buff *fixup_skb (struct sk_buff *skb, int flags)
-{
- int padlen;
- struct sk_buff *skb2;
-
- padlen = ((skb->len + sizeof (struct nc_header)
- + sizeof (struct nc_trailer)) & 0x01) ? 0 : 1;
- if (!skb_cloned (skb)) {
- int headroom = skb_headroom (skb);
- int tailroom = skb_tailroom (skb);
-
- if ((padlen + sizeof (struct nc_trailer)) <= tailroom
- && sizeof (struct nc_header) <= headroom)
- return skb;
-
- if ((sizeof (struct nc_header) + padlen
- + sizeof (struct nc_trailer)) <
- (headroom + tailroom)) {
- skb->data = memmove (skb->head
- + sizeof (struct nc_header),
- skb->data, skb->len);
- skb->tail = skb->data + skb->len;
- return skb;
- }
- }
- skb2 = skb_copy_expand (skb,
- sizeof (struct nc_header),
- sizeof (struct nc_trailer) + padlen,
- flags);
- dev_kfree_skb_any (skb);
- return skb2;
-}
-
-/*-------------------------------------------------------------------------*/
-
static int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net)
{
struct usbnet *dev = (struct usbnet *) net->priv;
@@ -1203,21 +1570,23 @@
int retval = NET_XMIT_SUCCESS;
struct urb *urb = 0;
struct skb_data *entry;
- struct nc_header *header = 0;
- struct nc_trailer *trailer = 0;
struct driver_info *info = dev->driver_info;
int flags;
+#ifdef CONFIG_USB_NET1080
+ struct nc_header *header = 0;
+ struct nc_trailer *trailer = 0;
+#endif /* CONFIG_USB_NET1080 */
flags = in_interrupt () ? GFP_ATOMIC : GFP_KERNEL;
- if (info->flags & FLAG_FRAMING_NC) {
- struct sk_buff *skb2;
- skb2 = fixup_skb (skb, flags);
- if (!skb2) {
- dbg ("can't fixup skb");
+ // some devices want funky USB-level framing, for
+ // win32 driver (usually) and/or hardware quirks
+ if (info->tx_fixup) {
+ skb = info->tx_fixup (dev, skb, flags);
+ if (!skb) {
+ dbg ("can't tx_fixup skb");
goto drop;
}
- skb = skb2;
}
if (!(urb = usb_alloc_urb (0))) {
@@ -1231,6 +1600,10 @@
entry->state = tx_start;
entry->length = length;
+ // FIXME: reorganize a bit, so that fixup() fills out NetChip
+ // framing too. (Packet ID update needs the spinlock...)
+
+#ifdef CONFIG_USB_NET1080
if (info->flags & FLAG_FRAMING_NC) {
header = (struct nc_header *) skb_push (skb, sizeof *header);
header->hdr_len = cpu_to_le16 (sizeof (*header));
@@ -1238,20 +1611,12 @@
if (!((skb->len + sizeof *trailer) & 0x01))
*skb_put (skb, 1) = PAD_BYTE;
trailer = (struct nc_trailer *) skb_put (skb, sizeof *trailer);
- } else if ((length % EP_SIZE (dev)) == 0) {
- // not all hardware behaves with USB_ZERO_PACKET,
- // so we add an extra one-byte packet
- if (skb_shared (skb)) {
- struct sk_buff *skb2;
- skb2 = skb_unshare (skb, flags);
- if (!skb2) {
- dbg ("can't unshare skb");
- goto drop;
- }
- skb = skb2;
- }
+ } else
+#endif /* CONFIG_USB_NET1080 */
+
+ /* don't assume the hardware handles USB_ZERO_PACKET */
+ if ((length % EP_SIZE (dev)) == 0)
skb->len++;
- }
FILL_BULK_URB (urb, dev->udev,
usb_sndbulkpipe (dev->udev, info->out),
@@ -1263,6 +1628,8 @@
// FIXME urb->timeout = ... jiffies ... ;
spin_lock_irqsave (&dev->txq.lock, flags);
+
+#ifdef CONFIG_USB_NET1080
if (info->flags & FLAG_FRAMING_NC) {
header->packet_id = cpu_to_le16 (dev->packet_id++);
put_unaligned (header->packet_id, &trailer->packet_id);
@@ -1272,6 +1639,7 @@
header->packet_id);
#endif
}
+#endif /* CONFIG_USB_NET1080 */
netif_stop_queue (net);
if ((retval = usb_submit_urb (urb)) != 0) {
@@ -1290,7 +1658,8 @@
drop:
retval = NET_XMIT_DROP;
dev->stats.tx_dropped++;
- dev_kfree_skb_any (skb);
+ if (skb)
+ dev_kfree_skb_any (skb);
usb_free_urb (urb);
#ifdef VERBOSE
} else {
@@ -1516,9 +1885,12 @@
},
#endif
-// GeneSys GL620USB (www.genesyslogic.com.tw)
-// (patch exists against an older driver version)
-
+#ifdef CONFIG_USB_GENESYS
+{
+ USB_DEVICE (0x05e3, 0x0502), // GL620USB-A
+ driver_info: (unsigned long) &genelink_info,
+},
+#endif
#ifdef CONFIG_USB_LINUXDEV
/*
@@ -1552,6 +1924,8 @@
driver_info: (unsigned long) &prolific_info,
},
#endif
+
+/* KC2190 from www.sepoong.co.kr "InstaNET" */
{ }, // END
};
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)