vserver 1.9.5.x5
[linux-2.6.git] / drivers / usb / net / usbnet.c
index 557edde..9c8d8c2 100644 (file)
@@ -31,6 +31,7 @@
  *     - GeneSys GL620USB-A
  *     - NetChip 1080 (interoperates with NetChip Win32 drivers)
  *     - Prolific PL-2301/2302 (replaces "plusb" driver)
+ *     - KC Technology KC2190
  *
  *   + Smart USB devices can support such links directly, using Internet
  *     standard protocols instead of proprietary host-to-device links.
  *             disconnect; other cleanups. (db)  Flush net1080 fifos
  *             after several sequential framing errors. (Johannes Erdfelt)
  * 22-aug-2003 AX8817X support (Dave Hollis).
+ * 14-jun-2004  Trivial patch for AX8817X based Buffalo LUA-U2-KTX in Japan
+ *             (Neil Bortnak)
+ * 03-nov-2004 Trivial patch for KC2190 (KC-190) chip. (Jonathan McDowell)
  *
  *-------------------------------------------------------------------------*/
 
 #include <linux/mm.h>
 #include <linux/dma-mapping.h>
 
-#define DRIVER_VERSION         "25-Aug-2003"
+#define DRIVER_VERSION         "03-Nov-2004"
 
 
 /*-------------------------------------------------------------------------*/
 #define CONTROL_TIMEOUT_JIFFIES ((CONTROL_TIMEOUT_MS * HZ)/1000)
 
 // between wakeups
-#define UNLINK_TIMEOUT_JIFFIES ((3  /*ms*/ * HZ)/1000)
+#define UNLINK_TIMEOUT_MS      3
 
 /*-------------------------------------------------------------------------*/
 
@@ -266,7 +270,7 @@ static const char driver_name [] = "usbnet";
 
 /* use ethtool to change the level for any given device */
 static int msg_level = 1;
-MODULE_PARM (msg_level, "i");
+module_param (msg_level, int, 0);
 MODULE_PARM_DESC (msg_level, "Initial message level (default = 1)");
 
 
@@ -314,7 +318,7 @@ get_endpoints (struct usbnet *dev, struct usb_interface *intf)
        for (tmp = 0; tmp < intf->num_altsetting; tmp++) {
                unsigned        ep;
 
-               in = out = 0;
+               in = out = NULL;
                alt = intf->altsetting + tmp;
 
                /* take the first altsetting with in-bulk + out-bulk;
@@ -452,6 +456,15 @@ static const struct driver_info    an2720_info = {
 #define AX_MCAST_FILTER_SIZE           8
 #define AX_MAX_MCAST                   64
 
+#define AX_INTERRUPT_BUFSIZE           8
+
+/* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */
+struct ax8817x_data {
+       u8 multi_filter[AX_MCAST_FILTER_SIZE];
+       struct urb *int_urb;
+       u8 *int_buf;
+};
+
 static int ax8817x_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
                            u16 size, void *data)
 {
@@ -494,6 +507,30 @@ static void ax8817x_async_cmd_callback(struct urb *urb, struct pt_regs *regs)
        usb_free_urb(urb);
 }
 
+static void ax8817x_interrupt_complete(struct urb *urb, struct pt_regs *regs)
+{
+       struct usbnet *dev = (struct usbnet *)urb->context;
+       struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
+       int link;
+
+       if (urb->status < 0) {
+               printk(KERN_DEBUG "ax8817x_interrupt_complete() failed with %d",
+                       urb->status);
+       } else {
+               if (data->int_buf[5] == 0x90) {
+                       link = data->int_buf[2] & 0x01;
+                       if (netif_carrier_ok(dev->net) != link) {
+                               if (link)
+                                       netif_carrier_on(dev->net);
+                               else
+                                       netif_carrier_off(dev->net);
+                               devdbg(dev, "ax8817x - Link Status is: %d", link);
+                       }
+               }
+               usb_submit_urb(data->int_urb, GFP_ATOMIC);
+       }
+}
+
 static void ax8817x_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
                                    u16 size, void *data)
 {
@@ -532,7 +569,8 @@ static void ax8817x_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 i
 
 static void ax8817x_set_multicast(struct net_device *net)
 {
-       struct usbnet *dev = (struct usbnet *) net->priv;
+       struct usbnet *dev = netdev_priv(net);
+       struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
        u8 rx_ctl = 0x8c;
 
        if (net->flags & IFF_PROMISC) {
@@ -547,25 +585,24 @@ static void ax8817x_set_multicast(struct net_device *net)
                 * for our 8 byte filter buffer
                 * to avoid allocating memory that
                 * is tricky to free later */
-               u8 *multi_filter = (u8 *)&dev->data;
                struct dev_mc_list *mc_list = net->mc_list;
                u32 crc_bits;
                int i;
 
-               memset(multi_filter, 0, AX_MCAST_FILTER_SIZE);
+               memset(data->multi_filter, 0, AX_MCAST_FILTER_SIZE);
 
                /* Build the multicast hash filter. */
                for (i = 0; i < net->mc_count; i++) {
                        crc_bits =
                            ether_crc(ETH_ALEN,
                                      mc_list->dmi_addr) >> 26;
-                       multi_filter[crc_bits >> 3] |=
+                       data->multi_filter[crc_bits >> 3] |=
                            1 << (crc_bits & 7);
                        mc_list = mc_list->next;
                }
 
                ax8817x_write_cmd_async(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0,
-                                  AX_MCAST_FILTER_SIZE, multi_filter);
+                                  AX_MCAST_FILTER_SIZE, data->multi_filter);
 
                rx_ctl |= 0x10;
        }
@@ -575,7 +612,7 @@ static void ax8817x_set_multicast(struct net_device *net)
 
 static int ax8817x_mdio_read(struct net_device *netdev, int phy_id, int loc)
 {
-       struct usbnet *dev = netdev->priv;
+       struct usbnet *dev = netdev_priv(netdev);
        u16 res;
        u8 buf[1];
 
@@ -588,7 +625,7 @@ static int ax8817x_mdio_read(struct net_device *netdev, int phy_id, int loc)
 
 static void ax8817x_mdio_write(struct net_device *netdev, int phy_id, int loc, int val)
 {
-       struct usbnet *dev = netdev->priv;
+       struct usbnet *dev = netdev_priv(netdev);
        u16 res = val;
        u8 buf[1];
 
@@ -599,7 +636,7 @@ static void ax8817x_mdio_write(struct net_device *netdev, int phy_id, int loc, i
 
 static void ax8817x_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
 {
-       struct usbnet *dev = (struct usbnet *)net->priv;
+       struct usbnet *dev = netdev_priv(net);
        u8 opt;
 
        if (ax8817x_read_cmd(dev, AX_CMD_READ_MONITOR_MODE, 0, 0, 1, &opt) < 0) {
@@ -619,7 +656,7 @@ static void ax8817x_get_wol(struct net_device *net, struct ethtool_wolinfo *woli
 
 static int ax8817x_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
 {
-       struct usbnet *dev = (struct usbnet *)net->priv;
+       struct usbnet *dev = netdev_priv(net);
        u8 opt = 0;
        u8 buf[1];
 
@@ -640,7 +677,7 @@ static int ax8817x_set_wol(struct net_device *net, struct ethtool_wolinfo *wolin
 static int ax8817x_get_eeprom(struct net_device *net,
                              struct ethtool_eeprom *eeprom, u8 *data)
 {
-       struct usbnet *dev = (struct usbnet *)net->priv;
+       struct usbnet *dev = netdev_priv(net);
        u16 *ebuf = (u16 *)data;
        int i;
 
@@ -667,23 +704,16 @@ static void ax8817x_get_drvinfo (struct net_device *net,
        info->eedump_len = 0x3e;
 }
 
-static u32 ax8817x_get_link (struct net_device *net)
-{
-       struct usbnet *dev = (struct usbnet *)net->priv;
-
-       return (u32)mii_link_ok(&dev->mii);
-}
-
 static int ax8817x_get_settings(struct net_device *net, struct ethtool_cmd *cmd)
 {
-       struct usbnet *dev = (struct usbnet *)net->priv;
+       struct usbnet *dev = netdev_priv(net);
 
        return mii_ethtool_gset(&dev->mii,cmd);
 }
 
 static int ax8817x_set_settings(struct net_device *net, struct ethtool_cmd *cmd)
 {
-       struct usbnet *dev = (struct usbnet *)net->priv;
+       struct usbnet *dev = netdev_priv(net);
 
        return mii_ethtool_sset(&dev->mii,cmd);
 }
@@ -693,7 +723,7 @@ static int ax8817x_set_settings(struct net_device *net, struct ethtool_cmd *cmd)
    devices that may be connected at the same time. */
 static struct ethtool_ops ax8817x_ethtool_ops = {
        .get_drvinfo            = ax8817x_get_drvinfo,
-       .get_link               = ax8817x_get_link,
+       .get_link               = ethtool_op_get_link,
        .get_msglevel           = usbnet_get_msglevel,
        .set_msglevel           = usbnet_set_msglevel,
        .get_wol                = ax8817x_get_wol,
@@ -707,13 +737,34 @@ static int ax8817x_bind(struct usbnet *dev, struct usb_interface *intf)
 {
        int ret;
        u8 buf[6];
-       u16 *buf16 = (u16 *) buf;
        int i;
        unsigned long gpio_bits = dev->driver_info->data;
+       struct ax8817x_data *data = (struct ax8817x_data *)dev->data;
 
        dev->in = usb_rcvbulkpipe(dev->udev, 3);
        dev->out = usb_sndbulkpipe(dev->udev, 2);
 
+       // allocate irq urb
+       if ((data->int_urb = usb_alloc_urb (0, GFP_KERNEL)) == NULL) {
+               dbg ("%s: cannot allocate interrupt URB",
+                       dev->net->name);
+               return -ENOMEM;
+       }
+       
+       if ((data->int_buf = kmalloc(AX_INTERRUPT_BUFSIZE, GFP_KERNEL)) == NULL) {
+               dbg ("%s: cannot allocate memory for interrupt buffer",
+                       dev->net->name);
+               usb_free_urb(data->int_urb);
+               return -ENOMEM;
+       }
+       memset(data->int_buf, 0, AX_INTERRUPT_BUFSIZE);
+
+       usb_fill_int_urb (data->int_urb, dev->udev,
+               usb_rcvintpipe (dev->udev, 1),
+               data->int_buf, AX_INTERRUPT_BUFSIZE,
+               ax8817x_interrupt_complete, dev,
+               dev->udev->speed == USB_SPEED_HIGH ? 8 : 100);
+
        /* Toggle the GPIOs in a manufacturer/model specific way */
        for (i = 2; i >= 0; i--) {
                if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
@@ -754,49 +805,37 @@ static int ax8817x_bind(struct usbnet *dev, struct usb_interface *intf)
        dev->mii.reg_num_mask = 0x1f;
        dev->mii.phy_id = buf[1];
 
-       if ((ret = ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, &buf)) < 0) {
-               dbg("Failed to go to software MII mode: %02x", ret);
-               return ret;
-       }
-
-       *buf16 = cpu_to_le16(BMCR_RESET);
-       if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG,
-                                    dev->mii.phy_id, MII_BMCR, 2, buf16)) < 0) {
-               dbg("Failed to write MII reg - MII_BMCR: %02x", ret);
-               return ret;
-       }
+       dev->net->set_multicast_list = ax8817x_set_multicast;
+       dev->net->ethtool_ops = &ax8817x_ethtool_ops;
 
-       /* Advertise that we can do full-duplex pause */
-       *buf16 = cpu_to_le16(ADVERTISE_ALL | ADVERTISE_CSMA | 0x0400);
-       if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG,
-                                    dev->mii.phy_id, MII_ADVERTISE, 
-                                    2, buf16)) < 0) {
-               dbg("Failed to write MII_REG advertisement: %02x", ret);
-               return ret;
-       }
+       ax8817x_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR,
+                       cpu_to_le16(BMCR_RESET));
+       ax8817x_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
+                       cpu_to_le16(ADVERTISE_ALL | ADVERTISE_CSMA | 0x0400));
+       mii_nway_restart(&dev->mii);
 
-       *buf16 = cpu_to_le16(BMCR_ANENABLE | BMCR_ANRESTART);
-       if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG,
-                                    dev->mii.phy_id, MII_BMCR, 
-                                    2, buf16)) < 0) {
-               dbg("Failed to write MII reg autonegotiate: %02x", ret);
+       if((ret = usb_submit_urb(data->int_urb, GFP_KERNEL)) < 0) {
+               dbg("Failed to submit interrupt URB: %02x", ret);
+               usb_free_urb(data->int_urb);
                return ret;
        }
 
-       if ((ret = ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, &buf)) < 0) {
-               dbg("Failed to set hardware MII: %02x", ret);
-               return ret;
-       }
+       return 0;
+}
 
-       dev->net->set_multicast_list = ax8817x_set_multicast;
-       dev->net->ethtool_ops = &ax8817x_ethtool_ops;
+static void ax8817x_unbind(struct usbnet *dev, struct usb_interface *intf)
+{
+       struct ax8817x_data *data = (struct ax8817x_data *)dev->data;
 
-       return 0;
+       usb_kill_urb(data->int_urb);
+       usb_free_urb(data->int_urb);
+       kfree(data->int_buf);
 }
 
 static const struct driver_info ax8817x_info = {
        .description = "ASIX AX8817x USB 2.0 Ethernet",
        .bind = ax8817x_bind,
+       .unbind = ax8817x_unbind,
        .flags =  FLAG_ETHER,
        .data = 0x00130103,
 };
@@ -804,6 +843,7 @@ static const struct driver_info ax8817x_info = {
 static const struct driver_info dlink_dub_e100_info = {
        .description = "DLink DUB-E100 USB Ethernet",
        .bind = ax8817x_bind,
+       .unbind = ax8817x_unbind,
        .flags =  FLAG_ETHER,
        .data = 0x009f9d9f,
 };
@@ -811,6 +851,7 @@ static const struct driver_info dlink_dub_e100_info = {
 static const struct driver_info netgear_fa120_info = {
        .description = "Netgear FA-120 USB Ethernet",
        .bind = ax8817x_bind,
+       .unbind = ax8817x_unbind,
        .flags =  FLAG_ETHER,
        .data = 0x00130103,
 };
@@ -818,6 +859,7 @@ static const struct driver_info netgear_fa120_info = {
 static const struct driver_info hawking_uf200_info = {
        .description = "Hawking UF200 USB Ethernet",
        .bind = ax8817x_bind,
+       .unbind = ax8817x_unbind,
        .flags =  FLAG_ETHER,
        .data = 0x001f1d1f,
 };
@@ -897,8 +939,8 @@ struct ether_desc {
 
        u8      iMACAddress;
        u32     bmEthernetStatistics;
-       u16     wMaxSegmentSize;
-       u16     wNumberMCFilters;
+       __le16  wMaxSegmentSize;
+       __le16  wNumberMCFilters;
        u8      bNumberPowerFilters;
 } __attribute__ ((packed));
 
@@ -1034,7 +1076,7 @@ static int generic_cdc_bind (struct usbnet *dev, struct usb_interface *intf)
                                        info->u->bLength);
                                goto bad_desc;
                        }
-                       dev->net->mtu = cpu_to_le16p (
+                       dev->net->mtu = le16_to_cpup (
                                                &info->ether->wMaxSegmentSize)
                                        - ETH_HLEN;
                        /* because of Zaurus, we may be ignoring the host
@@ -1084,7 +1126,7 @@ static void cdc_unbind (struct usbnet *dev, struct usb_interface *intf)
                /* ensure immediate exit from usbnet_disconnect */
                usb_set_intfdata(info->data, NULL);
                usb_driver_release_interface (&usbnet_driver, info->data);
-               info->data = 0;
+               info->data = NULL;
        }
 
        /* and vice versa (just in case) */
@@ -1092,7 +1134,7 @@ static void cdc_unbind (struct usbnet *dev, struct usb_interface *intf)
                /* ensure immediate exit from usbnet_disconnect */
                usb_set_intfdata(info->control, NULL);
                usb_driver_release_interface (&usbnet_driver, info->control);
-               info->control = 0;
+               info->control = NULL;
        }
 }
 
@@ -1157,6 +1199,7 @@ static int cdc_bind (struct usbnet *dev, struct usb_interface *intf)
 
        status = get_ethernet_addr (dev, info->ether);
        if (status < 0) {
+               usb_set_intfdata(info->data, NULL);
                usb_driver_release_interface (&usbnet_driver, info->data);
                return status;
        }
@@ -1255,7 +1298,7 @@ struct gl_header {
        struct gl_packet        packets;
 };
 
-#ifdef GENLINK_ACK
+#ifdef GENELINK_ACK
 
 // FIXME:  this code is incomplete, not debugged; it doesn't
 // handle interrupts correctly.  interrupts should be generic
@@ -1396,7 +1439,7 @@ static int genelink_free (struct usbnet *dev)
 // handling needs to be generic)
 
        // cancel irq urb first
-       usb_unlink_urb (priv->irq_urb);
+       usb_kill_urb (priv->irq_urb);
 
        // free irq urb
        usb_free_urb (priv->irq_urb);
@@ -1638,7 +1681,7 @@ nc_vendor_write (struct usbnet *dev, u8 req, u8 regnum, u16 value)
                req,
                USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
                value, regnum,
-               0, 0,                   // data is in setup packet
+               NULL, 0,                        // data is in setup packet
                CONTROL_TIMEOUT_JIFFIES);
 }
 
@@ -2081,7 +2124,7 @@ pl_vendor_req (struct usbnet *dev, u8 req, u8 val, u8 index)
                req,
                USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
                val, index,
-               0, 0,
+               NULL, 0,
                CONTROL_TIMEOUT_JIFFIES);
 }
 
@@ -2118,6 +2161,13 @@ static const struct driver_info  prolific_info = {
 
 #endif /* CONFIG_USB_PL2301 */
 
+\f
+#ifdef CONFIG_USB_KC2190
+#define HAVE_HARDWARE
+static const struct driver_info kc2190_info = {
+       .description =  "KC Technology KC-190",
+};
+#endif /* CONFIG_USB_KC2190 */
 
 \f
 #ifdef CONFIG_USB_ARMLINUX
@@ -2215,14 +2265,34 @@ static const struct driver_info zaurus_sl5x00_info = {
        .unbind =       cdc_unbind,
        .tx_fixup =     zaurus_tx_fixup,
 };
+#define        ZAURUS_STRONGARM_INFO   ((unsigned long)&zaurus_sl5x00_info)
+
 static const struct driver_info        zaurus_pxa_info = {
        .description =  "Sharp Zaurus, PXA-2xx based",
        .flags =        FLAG_FRAMING_Z,
        .check_connect = always_connected,
+       .bind =         generic_cdc_bind,
+       .unbind =       cdc_unbind,
        .tx_fixup =     zaurus_tx_fixup,
+};
+#define        ZAURUS_PXA_INFO         ((unsigned long)&zaurus_pxa_info)
 
-       .in = 1, .out = 2,
+static const struct driver_info        olympus_mxl_info = {
+       .description =  "Olympus R1000",
+       .flags =        FLAG_FRAMING_Z,
+       .check_connect = always_connected,
+       .bind =         generic_cdc_bind,
+       .unbind =       cdc_unbind,
+       .tx_fixup =     zaurus_tx_fixup,
 };
+#define        OLYMPUS_MXL_INFO        ((unsigned long)&olympus_mxl_info)
+
+#else
+
+/* blacklist all those devices */
+#define        ZAURUS_STRONGARM_INFO   0
+#define        ZAURUS_PXA_INFO         0
+#define        OLYMPUS_MXL_INFO        0
 
 #endif
 
@@ -2235,7 +2305,7 @@ static const struct driver_info   zaurus_pxa_info = {
 
 static int usbnet_change_mtu (struct net_device *net, int new_mtu)
 {
-       struct usbnet   *dev = (struct usbnet *) net->priv;
+       struct usbnet   *dev = netdev_priv(net);
 
        if (new_mtu <= MIN_PACKET || new_mtu > MAX_PACKET)
                return -EINVAL;
@@ -2261,7 +2331,8 @@ static int usbnet_change_mtu (struct net_device *net, int new_mtu)
 
 static struct net_device_stats *usbnet_get_stats (struct net_device *net)
 {
-       return &((struct usbnet *) net->priv)->stats;
+       struct usbnet   *dev = netdev_priv(net);
+       return &dev->stats;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -2333,7 +2404,7 @@ static void rx_submit (struct usbnet *dev, struct urb *urb, int flags)
 #endif
                size = (sizeof (struct ethhdr) + dev->net->mtu);
 
-       if ((skb = alloc_skb (size, flags)) == 0) {
+       if ((skb = alloc_skb (size, flags)) == NULL) {
                devdbg (dev, "no rx skb");
                defer_kevent (dev, EVENT_RX_MEMORY);
                usb_free_urb (urb);
@@ -2415,7 +2486,7 @@ static void rx_complete (struct urb *urb, struct pt_regs *regs)
 
        skb_put (skb, urb->actual_length);
        entry->state = rx_done;
-       entry->urb = 0;
+       entry->urb = NULL;
 
        switch (urb_status) {
            // success
@@ -2459,7 +2530,7 @@ static void rx_complete (struct urb *urb, struct pt_regs *regs)
 block:
                entry->state = rx_cleanup;
                entry->urb = urb;
-               urb = 0;
+               urb = NULL;
                break;
 
            // data overrun ... flush fifo?
@@ -2528,7 +2599,7 @@ static int unlink_urbs (struct usbnet *dev, struct sk_buff_head *q)
 
 static int usbnet_stop (struct net_device *net)
 {
-       struct usbnet           *dev = (struct usbnet *) net->priv;
+       struct usbnet           *dev = netdev_priv(net);
        int                     temp;
        DECLARE_WAIT_QUEUE_HEAD (unlink_wakeup); 
        DECLARE_WAITQUEUE (wait, current);
@@ -2550,11 +2621,10 @@ static int usbnet_stop (struct net_device *net)
        while (skb_queue_len (&dev->rxq)
                        && skb_queue_len (&dev->txq)
                        && skb_queue_len (&dev->done)) {
-               set_current_state (TASK_UNINTERRUPTIBLE);
-               schedule_timeout (UNLINK_TIMEOUT_JIFFIES);
+               msleep(UNLINK_TIMEOUT_MS);
                devdbg (dev, "waited for %d urb completions", temp);
        }
-       dev->wait = 0;
+       dev->wait = NULL;
        remove_wait_queue (&unlink_wakeup, &wait); 
 
        /* deferred work (task, timer, softirq) must also stop.
@@ -2576,7 +2646,7 @@ static int usbnet_stop (struct net_device *net)
 
 static int usbnet_open (struct net_device *net)
 {
-       struct usbnet           *dev = (struct usbnet *) net->priv;
+       struct usbnet           *dev = netdev_priv(net);
        int                     retval = 0;
        struct driver_info      *info = dev->driver_info;
 
@@ -2626,7 +2696,7 @@ done:
 
 static void usbnet_get_drvinfo (struct net_device *net, struct ethtool_drvinfo *info)
 {
-       struct usbnet *dev = net->priv;
+       struct usbnet *dev = netdev_priv(net);
 
        strncpy (info->driver, driver_name, sizeof info->driver);
        strncpy (info->version, DRIVER_VERSION, sizeof info->version);
@@ -2637,7 +2707,7 @@ static void usbnet_get_drvinfo (struct net_device *net, struct ethtool_drvinfo *
 
 static u32 usbnet_get_link (struct net_device *net)
 {
-       struct usbnet *dev = net->priv;
+       struct usbnet *dev = netdev_priv(net);
 
        /* If a check_connect is defined, return it's results */
        if (dev->driver_info->check_connect)
@@ -2649,14 +2719,14 @@ static u32 usbnet_get_link (struct net_device *net)
 
 static u32 usbnet_get_msglevel (struct net_device *net)
 {
-       struct usbnet *dev = net->priv;
+       struct usbnet *dev = netdev_priv(net);
 
        return dev->msg_level;
 }
 
 static void usbnet_set_msglevel (struct net_device *net, u32 level)
 {
-       struct usbnet *dev = net->priv;
+       struct usbnet *dev = netdev_priv(net);
 
        dev->msg_level = level;
 }
@@ -2665,7 +2735,7 @@ static int usbnet_ioctl (struct net_device *net, struct ifreq *rq, int cmd)
 {
 #ifdef NEED_MII
        {
-       struct usbnet *dev = (struct usbnet *)net->priv;
+       struct usbnet *dev = netdev_priv(net);
 
        if (dev->mii.mdio_read != NULL && dev->mii.mdio_write != NULL)
                return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
@@ -2691,7 +2761,7 @@ kevent (void *data)
        if (test_bit (EVENT_TX_HALT, &dev->flags)) {
                unlink_urbs (dev, &dev->txq);
                status = usb_clear_halt (dev->udev, dev->out);
-               if (status < 0)
+               if (status < 0 && status != -EPIPE)
                        deverr (dev, "can't clear tx halt, status %d",
                                status);
                else {
@@ -2702,7 +2772,7 @@ kevent (void *data)
        if (test_bit (EVENT_RX_HALT, &dev->flags)) {
                unlink_urbs (dev, &dev->rxq);
                status = usb_clear_halt (dev->udev, dev->in);
-               if (status < 0)
+               if (status < 0 && status != -EPIPE)
                        deverr (dev, "can't clear rx halt, status %d",
                                status);
                else {
@@ -2713,13 +2783,13 @@ kevent (void *data)
 
        /* tasklet could resubmit itself forever if memory is tight */
        if (test_bit (EVENT_RX_MEMORY, &dev->flags)) {
-               struct urb      *urb = 0;
+               struct urb      *urb = NULL;
 
                if (netif_running (dev->net))
                        urb = usb_alloc_urb (0, GFP_KERNEL);
                else
                        clear_bit (EVENT_RX_MEMORY, &dev->flags);
-               if (urb != 0) {
+               if (urb != NULL) {
                        clear_bit (EVENT_RX_MEMORY, &dev->flags);
                        rx_submit (dev, urb, GFP_KERNEL);
                        tasklet_schedule (&dev->bh);
@@ -2768,7 +2838,7 @@ static void tx_complete (struct urb *urb, struct pt_regs *regs)
                }
        }
 
-       urb->dev = 0;
+       urb->dev = NULL;
        entry->state = tx_done;
        defer_bh (dev, skb);
 }
@@ -2777,7 +2847,7 @@ static void tx_complete (struct urb *urb, struct pt_regs *regs)
 
 static void usbnet_tx_timeout (struct net_device *net)
 {
-       struct usbnet           *dev = (struct usbnet *) net->priv;
+       struct usbnet           *dev = netdev_priv(net);
 
        unlink_urbs (dev, &dev->txq);
        tasklet_schedule (&dev->bh);
@@ -2789,16 +2859,16 @@ static void usbnet_tx_timeout (struct net_device *net)
 
 static int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net)
 {
-       struct usbnet           *dev = (struct usbnet *) net->priv;
+       struct usbnet           *dev = netdev_priv(net);
        int                     length;
        int                     retval = NET_XMIT_SUCCESS;
-       struct urb              *urb = 0;
+       struct urb              *urb = NULL;
        struct skb_data         *entry;
        struct driver_info      *info = dev->driver_info;
        unsigned long           flags;
 #ifdef CONFIG_USB_NET1080
-       struct nc_header        *header = 0;
-       struct nc_trailer       *trailer = 0;
+       struct nc_header        *header = NULL;
+       struct nc_trailer       *trailer = NULL;
 #endif /* CONFIG_USB_NET1080 */
 
        // some devices want funky USB-level framing, for
@@ -2946,7 +3016,8 @@ static void usbnet_bh (unsigned long param)
 
                        // don't refill the queue all at once
                        for (i = 0; i < 10 && dev->rxq.qlen < qlen; i++) {
-                               if ((urb = usb_alloc_urb (0, GFP_ATOMIC)) != 0)
+                               urb = usb_alloc_urb (0, GFP_ATOMIC);
+                               if (urb != NULL)
                                        rx_submit (dev, urb, GFP_ATOMIC);
                        }
                        if (temp != dev->rxq.qlen)
@@ -2974,6 +3045,7 @@ static void usbnet_disconnect (struct usb_interface *intf)
 {
        struct usbnet           *dev;
        struct usb_device       *xdev;
+       struct net_device       *net;
 
        dev = usb_get_intfdata(intf);
        usb_set_intfdata(intf, NULL);
@@ -2986,7 +3058,8 @@ static void usbnet_disconnect (struct usb_interface *intf)
                xdev->bus->bus_name, xdev->devpath,
                dev->driver_info->description);
        
-       unregister_netdev (dev->net);
+       net = dev->net;
+       unregister_netdev (net);
 
        /* we don't hold rtnl here ... */
        flush_scheduled_work ();
@@ -2994,8 +3067,7 @@ static void usbnet_disconnect (struct usb_interface *intf)
        if (dev->driver_info->unbind)
                dev->driver_info->unbind (dev, intf);
 
-       free_netdev(dev->net);
-       kfree (dev);
+       free_netdev(net);
        usb_put_dev (xdev);
 }
 
@@ -3029,12 +3101,13 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
        status = -ENOMEM;
 
        // set up our own records
-       if (!(dev = kmalloc (sizeof *dev, GFP_KERNEL))) {
+       net = alloc_etherdev(sizeof(*dev));
+       if (!net) {
                dbg ("can't kmalloc dev");
                goto out;
        }
-       memset (dev, 0, sizeof *dev);
 
+       dev = netdev_priv(net);
        dev->udev = xdev;
        dev->driver_info = info;
        dev->msg_level = msg_level;
@@ -3048,14 +3121,8 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
        dev->delay.data = (unsigned long) dev;
        init_timer (&dev->delay);
 
-       // set up network interface records
-       net = alloc_etherdev(0);
-       if (!net)
-               goto out1;
-
        SET_MODULE_OWNER (net);
        dev->net = net;
-       net->priv = dev;
        strcpy (net->name, "usb%d");
        memcpy (net->dev_addr, node_id, sizeof node_id);
 
@@ -3104,8 +3171,8 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
 
        dev->maxpacket = usb_maxpacket (dev->udev, dev->out, 1);
        
-       SET_NETDEV_DEV(dev->net, &udev->dev);
-       status = register_netdev (dev->net);
+       SET_NETDEV_DEV(net, &udev->dev);
+       status = register_netdev (net);
        if (status)
                goto out3;
        devinfo (dev, "register usbnet at usb-%s-%s, %s",
@@ -3116,16 +3183,15 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
        usb_set_intfdata (udev, dev);
 
        // start as if the link is up
-       netif_device_attach (dev->net);
+       netif_device_attach (net);
 
        return 0;
 
 out3:
        if (info->unbind)
                info->unbind (dev, udev);
-       free_netdev(net);
 out1:
-       kfree(dev);
+       free_netdev(net);
 out:
        usb_put_dev(xdev);
        return status;
@@ -3204,6 +3270,26 @@ static const struct usb_device_id        products [] = {
        // ATEN UC210T
        USB_DEVICE (0x0557, 0x2009),
        .driver_info =  (unsigned long) &ax8817x_info,
+}, {
+       // Buffalo LUA-U2-KTX
+       USB_DEVICE (0x0411, 0x003d),
+       .driver_info =  (unsigned long) &ax8817x_info,
+}, {
+       // Sitecom LN-029 "USB 2.0 10/100 Ethernet adapter"
+       USB_DEVICE (0x6189, 0x182d),
+       .driver_info =  (unsigned long) &ax8817x_info,
+}, {
+       // corega FEther USB2-TX
+       USB_DEVICE (0x07aa, 0x0017),
+       .driver_info =  (unsigned long) &ax8817x_info,
+}, {
+       // Surecom EP-1427X-2
+       USB_DEVICE (0x1189, 0x0893),
+       .driver_info = (unsigned long) &ax8817x_info,
+}, {
+       // goodway corp usb gwusb2e
+       USB_DEVICE (0x1631, 0x6200),
+       .driver_info = (unsigned long) &ax8817x_info,
 },
 #endif
 
@@ -3244,6 +3330,13 @@ static const struct usb_device_id        products [] = {
 },
 #endif
 
+#ifdef CONFIG_USB_KC2190
+{
+       USB_DEVICE (0x050f, 0x0190),    // KC-190
+       .driver_info =  (unsigned long) &kc2190_info,
+},
+#endif
+
 #ifdef CONFIG_USB_RNDIS
 {
        /* RNDIS is MSFT's un-official variant of CDC ACM */
@@ -3260,11 +3353,18 @@ static const struct usb_device_id       products [] = {
  *
  * PXA25x or PXA210 ...  these use a "usb-eth" driver much like
  * the sa1100 one, but hardware uses different endpoint numbers.
+ *
+ * Or the Linux "Ethernet" gadget on hardware that can't talk
+ * CDC Ethernet (e.g., no altsettings), in either of two modes:
+ *  - acting just like the old "usb-eth" firmware, though
+ *    the implementation is different 
+ *  - supporting RNDIS as the first/default configuration for
+ *    MS-Windows interop; Linux needs to use the other config
  */
 {
        // 1183 = 0x049F, both used as hex values?
        // Compaq "Itsy" vendor/product id
-       USB_DEVICE (0x049F, 0x505A),
+       USB_DEVICE (0x049F, 0x505A),    // usb-eth, or compatible
        .driver_info =  (unsigned long) &linuxdev_info,
 }, {
        USB_DEVICE (0x0E7E, 0x1001),    // G.Mate "Yopy"
@@ -3272,15 +3372,22 @@ static const struct usb_device_id       products [] = {
 }, {
        USB_DEVICE (0x8086, 0x07d3),    // "blob" bootloader
        .driver_info =  (unsigned long) &blob_info,
+}, {
+       // Linux Ethernet/RNDIS gadget on pxa210/25x/26x
+       USB_DEVICE_VER (0x0525, 0xa4a2, 0x0203, 0x0203),
+       .driver_info =  (unsigned long) &linuxdev_info,
 }, 
 #endif
 
-#ifdef CONFIG_USB_ZAURUS
+#if    defined(CONFIG_USB_ZAURUS) || defined(CONFIG_USB_CDCETHER)
 /*
  * SA-1100 based Sharp Zaurus ("collie"), or compatible.
  * Same idea as above, but different framing.
  *
  * PXA-2xx based models are also lying-about-cdc.
+ *
+ * NOTE:  These entries do double-duty, serving as blacklist entries
+ * whenever Zaurus support isn't enabled, but CDC Ethernet is.
  */
 {
        .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
@@ -3291,82 +3398,79 @@ static const struct usb_device_id       products [] = {
        .bInterfaceClass        = USB_CLASS_COMM,
        .bInterfaceSubClass     = 6 /* Ethernet model */,
        .bInterfaceProtocol     = 0,
-       .driver_info =  (unsigned long) &zaurus_sl5x00_info,
+       .driver_info = ZAURUS_STRONGARM_INFO,
 }, {
        .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
                          | USB_DEVICE_ID_MATCH_DEVICE, 
        .idVendor               = 0x04DD,
        .idProduct              = 0x8005,       /* A-300 */
-       .bInterfaceClass        = 0x02,
-       .bInterfaceSubClass     = 0x0a,
+       .bInterfaceClass        = USB_CLASS_COMM,
+       .bInterfaceSubClass     = 6 /* Ethernet model */,
        .bInterfaceProtocol     = 0x00,
-       .driver_info =  (unsigned long) &zaurus_pxa_info,
+       .driver_info = ZAURUS_PXA_INFO,
 }, {
        .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
                          | USB_DEVICE_ID_MATCH_DEVICE, 
        .idVendor               = 0x04DD,
        .idProduct              = 0x8006,       /* B-500/SL-5600 */
-       .bInterfaceClass        = 0x02,
-       .bInterfaceSubClass     = 0x0a,
+       .bInterfaceClass        = USB_CLASS_COMM,
+       .bInterfaceSubClass     = 6 /* Ethernet model */,
        .bInterfaceProtocol     = 0x00,
-       .driver_info =  (unsigned long) &zaurus_pxa_info,
+       .driver_info = ZAURUS_PXA_INFO,
 }, {
        .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
                  | USB_DEVICE_ID_MATCH_DEVICE,
        .idVendor               = 0x04DD,
        .idProduct              = 0x8007,       /* C-700 */
-       .bInterfaceClass    = 0x02,
-       .bInterfaceSubClass = 0x0a,
+       .bInterfaceClass        = USB_CLASS_COMM,
+       .bInterfaceSubClass     = 6 /* Ethernet model */,
        .bInterfaceProtocol = 0x00,
-       .driver_info =  (unsigned long) &zaurus_pxa_info,
+       .driver_info = ZAURUS_PXA_INFO,
 }, {
        .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
                 | USB_DEVICE_ID_MATCH_DEVICE,
        .idVendor               = 0x04DD,
        .idProduct              = 0x9031,       /* C-750 C-760 */
-       .bInterfaceClass        = 0x02,
-       .bInterfaceSubClass     = 0x0a,
+       .bInterfaceClass        = USB_CLASS_COMM,
+       .bInterfaceSubClass     = 6 /* Ethernet model */,
        .bInterfaceProtocol     = 0x00,
-       .driver_info =  (unsigned long) &zaurus_pxa_info,
+       .driver_info = ZAURUS_PXA_INFO,
 }, {
        .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
                 | USB_DEVICE_ID_MATCH_DEVICE,
        .idVendor               = 0x04DD,
        .idProduct              = 0x9032,       /* SL-6000 */
-       .bInterfaceClass        = 0x02,
-       .bInterfaceSubClass     = 0x0a,
+       .bInterfaceClass        = USB_CLASS_COMM,
+       .bInterfaceSubClass     = 6 /* Ethernet model */,
        .bInterfaceProtocol     = 0x00,
-       .driver_info =  (unsigned long) &zaurus_pxa_info,
+       .driver_info = ZAURUS_PXA_INFO,
 }, {
        .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
                 | USB_DEVICE_ID_MATCH_DEVICE,
        .idVendor               = 0x04DD,
        .idProduct              = 0x9050,       /* C-860 */
-       .bInterfaceClass        = 0x02,
-       .bInterfaceSubClass     = 0x0a,
+       .bInterfaceClass        = USB_CLASS_COMM,
+       .bInterfaceSubClass     = 6 /* Ethernet model */,
        .bInterfaceProtocol     = 0x00,
-       .driver_info =  (unsigned long) &zaurus_pxa_info,
+       .driver_info = ZAURUS_PXA_INFO,
 },
-#endif
 
-#ifdef CONFIG_USB_CDCETHER
-
-#ifndef        CONFIG_USB_ZAURUS
-       /* if we couldn't whitelist Zaurus, we must blacklist it */
+/* Olympus has some models with a Zaurus-compatible option.
+ * R-1000 uses a FreeScale i.MXL cpu (ARMv4T)
+ */
 {
-       .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
-                         | USB_DEVICE_ID_MATCH_DEVICE, 
-       .idVendor               = 0x04DD,
-       .idProduct              = 0x8004,
-       /* match the master interface */
+       .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
+                | USB_DEVICE_ID_MATCH_DEVICE,
+       .idVendor               = 0x07B4,
+       .idProduct              = 0x0F02,       /* R-1000 */
        .bInterfaceClass        = USB_CLASS_COMM,
        .bInterfaceSubClass     = 6 /* Ethernet model */,
-       .bInterfaceProtocol     = 0,
-       .driver_info            = 0, /* BLACKLIST */
+       .bInterfaceProtocol     = 0x00,
+       .driver_info = OLYMPUS_MXL_INFO,
 },
-       // FIXME blacklist the other Zaurus models too, sigh
 #endif
 
+#ifdef CONFIG_USB_CDCETHER
 {
        /* CDC Ether uses two interfaces, not necessarily consecutive.
         * We match the main interface, ignoring the optional device