linux/drivers/net/usb/dm9601.c
<<
>>
Prefs
   1/*
   2 * Davicom DM96xx USB 10/100Mbps ethernet devices
   3 *
   4 * Peter Korsgaard <jacmet@sunsite.dk>
   5 *
   6 * This file is licensed under the terms of the GNU General Public License
   7 * version 2.  This program is licensed "as is" without any warranty of any
   8 * kind, whether express or implied.
   9 */
  10
  11//#define DEBUG
  12
  13#include <linux/module.h>
  14#include <linux/sched.h>
  15#include <linux/stddef.h>
  16#include <linux/netdevice.h>
  17#include <linux/etherdevice.h>
  18#include <linux/ethtool.h>
  19#include <linux/mii.h>
  20#include <linux/usb.h>
  21#include <linux/crc32.h>
  22#include <linux/usb/usbnet.h>
  23#include <linux/slab.h>
  24
  25/* datasheet:
  26 http://ptm2.cc.utu.fi/ftp/network/cards/DM9601/From_NET/DM9601-DS-P01-930914.pdf
  27*/
  28
  29/* control requests */
  30#define DM_READ_REGS    0x00
  31#define DM_WRITE_REGS   0x01
  32#define DM_READ_MEMS    0x02
  33#define DM_WRITE_REG    0x03
  34#define DM_WRITE_MEMS   0x05
  35#define DM_WRITE_MEM    0x07
  36
  37/* registers */
  38#define DM_NET_CTRL     0x00
  39#define DM_RX_CTRL      0x05
  40#define DM_SHARED_CTRL  0x0b
  41#define DM_SHARED_ADDR  0x0c
  42#define DM_SHARED_DATA  0x0d    /* low + high */
  43#define DM_PHY_ADDR     0x10    /* 6 bytes */
  44#define DM_MCAST_ADDR   0x16    /* 8 bytes */
  45#define DM_GPR_CTRL     0x1e
  46#define DM_GPR_DATA     0x1f
  47#define DM_CHIP_ID      0x2c
  48#define DM_MODE_CTRL    0x91    /* only on dm9620 */
  49
  50/* chip id values */
  51#define ID_DM9601       0
  52#define ID_DM9620       1
  53
  54#define DM_MAX_MCAST    64
  55#define DM_MCAST_SIZE   8
  56#define DM_EEPROM_LEN   256
  57#define DM_TX_OVERHEAD  2       /* 2 byte header */
  58#define DM_RX_OVERHEAD  7       /* 3 byte header + 4 byte crc tail */
  59#define DM_TIMEOUT      1000
  60
  61static int dm_read(struct usbnet *dev, u8 reg, u16 length, void *data)
  62{
  63        int err;
  64        err = usbnet_read_cmd(dev, DM_READ_REGS,
  65                               USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  66                               0, reg, data, length);
  67        if(err != length && err >= 0)
  68                err = -EINVAL;
  69        return err;
  70}
  71
  72static int dm_read_reg(struct usbnet *dev, u8 reg, u8 *value)
  73{
  74        return dm_read(dev, reg, 1, value);
  75}
  76
  77static int dm_write(struct usbnet *dev, u8 reg, u16 length, void *data)
  78{
  79        int err;
  80        err = usbnet_write_cmd(dev, DM_WRITE_REGS,
  81                                USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  82                                0, reg, data, length);
  83
  84        if (err >= 0 && err < length)
  85                err = -EINVAL;
  86        return err;
  87}
  88
  89static int dm_write_reg(struct usbnet *dev, u8 reg, u8 value)
  90{
  91        return usbnet_write_cmd(dev, DM_WRITE_REG,
  92                                USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  93                                value, reg, NULL, 0);
  94}
  95
  96static void dm_write_async(struct usbnet *dev, u8 reg, u16 length, void *data)
  97{
  98        usbnet_write_cmd_async(dev, DM_WRITE_REGS,
  99                               USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 100                               0, reg, data, length);
 101}
 102
 103static void dm_write_reg_async(struct usbnet *dev, u8 reg, u8 value)
 104{
 105        usbnet_write_cmd_async(dev, DM_WRITE_REG,
 106                               USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 107                               value, reg, NULL, 0);
 108}
 109
 110static int dm_read_shared_word(struct usbnet *dev, int phy, u8 reg, __le16 *value)
 111{
 112        int ret, i;
 113
 114        mutex_lock(&dev->phy_mutex);
 115
 116        dm_write_reg(dev, DM_SHARED_ADDR, phy ? (reg | 0x40) : reg);
 117        dm_write_reg(dev, DM_SHARED_CTRL, phy ? 0xc : 0x4);
 118
 119        for (i = 0; i < DM_TIMEOUT; i++) {
 120                u8 tmp = 0;
 121
 122                udelay(1);
 123                ret = dm_read_reg(dev, DM_SHARED_CTRL, &tmp);
 124                if (ret < 0)
 125                        goto out;
 126
 127                /* ready */
 128                if ((tmp & 1) == 0)
 129                        break;
 130        }
 131
 132        if (i == DM_TIMEOUT) {
 133                netdev_err(dev->net, "%s read timed out!\n", phy ? "phy" : "eeprom");
 134                ret = -EIO;
 135                goto out;
 136        }
 137
 138        dm_write_reg(dev, DM_SHARED_CTRL, 0x0);
 139        ret = dm_read(dev, DM_SHARED_DATA, 2, value);
 140
 141        netdev_dbg(dev->net, "read shared %d 0x%02x returned 0x%04x, %d\n",
 142                   phy, reg, *value, ret);
 143
 144 out:
 145        mutex_unlock(&dev->phy_mutex);
 146        return ret;
 147}
 148
 149static int dm_write_shared_word(struct usbnet *dev, int phy, u8 reg, __le16 value)
 150{
 151        int ret, i;
 152
 153        mutex_lock(&dev->phy_mutex);
 154
 155        ret = dm_write(dev, DM_SHARED_DATA, 2, &value);
 156        if (ret < 0)
 157                goto out;
 158
 159        dm_write_reg(dev, DM_SHARED_ADDR, phy ? (reg | 0x40) : reg);
 160        dm_write_reg(dev, DM_SHARED_CTRL, phy ? 0x1a : 0x12);
 161
 162        for (i = 0; i < DM_TIMEOUT; i++) {
 163                u8 tmp = 0;
 164
 165                udelay(1);
 166                ret = dm_read_reg(dev, DM_SHARED_CTRL, &tmp);
 167                if (ret < 0)
 168                        goto out;
 169
 170                /* ready */
 171                if ((tmp & 1) == 0)
 172                        break;
 173        }
 174
 175        if (i == DM_TIMEOUT) {
 176                netdev_err(dev->net, "%s write timed out!\n", phy ? "phy" : "eeprom");
 177                ret = -EIO;
 178                goto out;
 179        }
 180
 181        dm_write_reg(dev, DM_SHARED_CTRL, 0x0);
 182
 183out:
 184        mutex_unlock(&dev->phy_mutex);
 185        return ret;
 186}
 187
 188static int dm_read_eeprom_word(struct usbnet *dev, u8 offset, void *value)
 189{
 190        return dm_read_shared_word(dev, 0, offset, value);
 191}
 192
 193
 194
 195static int dm9601_get_eeprom_len(struct net_device *dev)
 196{
 197        return DM_EEPROM_LEN;
 198}
 199
 200static int dm9601_get_eeprom(struct net_device *net,
 201                             struct ethtool_eeprom *eeprom, u8 * data)
 202{
 203        struct usbnet *dev = netdev_priv(net);
 204        __le16 *ebuf = (__le16 *) data;
 205        int i;
 206
 207        /* access is 16bit */
 208        if ((eeprom->offset % 2) || (eeprom->len % 2))
 209                return -EINVAL;
 210
 211        for (i = 0; i < eeprom->len / 2; i++) {
 212                if (dm_read_eeprom_word(dev, eeprom->offset / 2 + i,
 213                                        &ebuf[i]) < 0)
 214                        return -EINVAL;
 215        }
 216        return 0;
 217}
 218
 219static int dm9601_mdio_read(struct net_device *netdev, int phy_id, int loc)
 220{
 221        struct usbnet *dev = netdev_priv(netdev);
 222
 223        __le16 res;
 224
 225        if (phy_id) {
 226                netdev_dbg(dev->net, "Only internal phy supported\n");
 227                return 0;
 228        }
 229
 230        dm_read_shared_word(dev, 1, loc, &res);
 231
 232        netdev_dbg(dev->net,
 233                   "dm9601_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x\n",
 234                   phy_id, loc, le16_to_cpu(res));
 235
 236        return le16_to_cpu(res);
 237}
 238
 239static void dm9601_mdio_write(struct net_device *netdev, int phy_id, int loc,
 240                              int val)
 241{
 242        struct usbnet *dev = netdev_priv(netdev);
 243        __le16 res = cpu_to_le16(val);
 244
 245        if (phy_id) {
 246                netdev_dbg(dev->net, "Only internal phy supported\n");
 247                return;
 248        }
 249
 250        netdev_dbg(dev->net, "dm9601_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x\n",
 251                   phy_id, loc, val);
 252
 253        dm_write_shared_word(dev, 1, loc, res);
 254}
 255
 256static void dm9601_get_drvinfo(struct net_device *net,
 257                               struct ethtool_drvinfo *info)
 258{
 259        /* Inherit standard device info */
 260        usbnet_get_drvinfo(net, info);
 261}
 262
 263static u32 dm9601_get_link(struct net_device *net)
 264{
 265        struct usbnet *dev = netdev_priv(net);
 266
 267        return mii_link_ok(&dev->mii);
 268}
 269
 270static int dm9601_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
 271{
 272        struct usbnet *dev = netdev_priv(net);
 273
 274        return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
 275}
 276
 277static const struct ethtool_ops dm9601_ethtool_ops = {
 278        .get_drvinfo    = dm9601_get_drvinfo,
 279        .get_link       = dm9601_get_link,
 280        .get_msglevel   = usbnet_get_msglevel,
 281        .set_msglevel   = usbnet_set_msglevel,
 282        .get_eeprom_len = dm9601_get_eeprom_len,
 283        .get_eeprom     = dm9601_get_eeprom,
 284        .get_settings   = usbnet_get_settings,
 285        .set_settings   = usbnet_set_settings,
 286        .nway_reset     = usbnet_nway_reset,
 287};
 288
 289static void dm9601_set_multicast(struct net_device *net)
 290{
 291        struct usbnet *dev = netdev_priv(net);
 292        /* We use the 20 byte dev->data for our 8 byte filter buffer
 293         * to avoid allocating memory that is tricky to free later */
 294        u8 *hashes = (u8 *) & dev->data;
 295        u8 rx_ctl = 0x31;
 296
 297        memset(hashes, 0x00, DM_MCAST_SIZE);
 298        hashes[DM_MCAST_SIZE - 1] |= 0x80;      /* broadcast address */
 299
 300        if (net->flags & IFF_PROMISC) {
 301                rx_ctl |= 0x02;
 302        } else if (net->flags & IFF_ALLMULTI ||
 303                   netdev_mc_count(net) > DM_MAX_MCAST) {
 304                rx_ctl |= 0x08;
 305        } else if (!netdev_mc_empty(net)) {
 306                struct netdev_hw_addr *ha;
 307
 308                netdev_for_each_mc_addr(ha, net) {
 309                        u32 crc = ether_crc(ETH_ALEN, ha->addr) >> 26;
 310                        hashes[crc >> 3] |= 1 << (crc & 0x7);
 311                }
 312        }
 313
 314        dm_write_async(dev, DM_MCAST_ADDR, DM_MCAST_SIZE, hashes);
 315        dm_write_reg_async(dev, DM_RX_CTRL, rx_ctl);
 316}
 317
 318static void __dm9601_set_mac_address(struct usbnet *dev)
 319{
 320        dm_write_async(dev, DM_PHY_ADDR, ETH_ALEN, dev->net->dev_addr);
 321}
 322
 323static int dm9601_set_mac_address(struct net_device *net, void *p)
 324{
 325        struct sockaddr *addr = p;
 326        struct usbnet *dev = netdev_priv(net);
 327
 328        if (!is_valid_ether_addr(addr->sa_data)) {
 329                dev_err(&net->dev, "not setting invalid mac address %pM\n",
 330                                                                addr->sa_data);
 331                return -EINVAL;
 332        }
 333
 334        memcpy(net->dev_addr, addr->sa_data, net->addr_len);
 335        __dm9601_set_mac_address(dev);
 336
 337        return 0;
 338}
 339
 340static const struct net_device_ops dm9601_netdev_ops = {
 341        .ndo_open               = usbnet_open,
 342        .ndo_stop               = usbnet_stop,
 343        .ndo_start_xmit         = usbnet_start_xmit,
 344        .ndo_tx_timeout         = usbnet_tx_timeout,
 345        .ndo_change_mtu         = usbnet_change_mtu,
 346        .ndo_validate_addr      = eth_validate_addr,
 347        .ndo_do_ioctl           = dm9601_ioctl,
 348        .ndo_set_rx_mode        = dm9601_set_multicast,
 349        .ndo_set_mac_address    = dm9601_set_mac_address,
 350};
 351
 352static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf)
 353{
 354        int ret;
 355        u8 mac[ETH_ALEN], id;
 356
 357        ret = usbnet_get_endpoints(dev, intf);
 358        if (ret)
 359                goto out;
 360
 361        dev->net->netdev_ops = &dm9601_netdev_ops;
 362        dev->net->ethtool_ops = &dm9601_ethtool_ops;
 363        dev->net->hard_header_len += DM_TX_OVERHEAD;
 364        dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
 365
 366        /* dm9620/21a require room for 4 byte padding, even in dm9601
 367         * mode, so we need +1 to be able to receive full size
 368         * ethernet frames.
 369         */
 370        dev->rx_urb_size = dev->net->mtu + ETH_HLEN + DM_RX_OVERHEAD + 1;
 371
 372        dev->mii.dev = dev->net;
 373        dev->mii.mdio_read = dm9601_mdio_read;
 374        dev->mii.mdio_write = dm9601_mdio_write;
 375        dev->mii.phy_id_mask = 0x1f;
 376        dev->mii.reg_num_mask = 0x1f;
 377
 378        /* reset */
 379        dm_write_reg(dev, DM_NET_CTRL, 1);
 380        udelay(20);
 381
 382        /* read MAC */
 383        if (dm_read(dev, DM_PHY_ADDR, ETH_ALEN, mac) < 0) {
 384                printk(KERN_ERR "Error reading MAC address\n");
 385                ret = -ENODEV;
 386                goto out;
 387        }
 388
 389        /*
 390         * Overwrite the auto-generated address only with good ones.
 391         */
 392        if (is_valid_ether_addr(mac))
 393                memcpy(dev->net->dev_addr, mac, ETH_ALEN);
 394        else {
 395                printk(KERN_WARNING
 396                        "dm9601: No valid MAC address in EEPROM, using %pM\n",
 397                        dev->net->dev_addr);
 398                __dm9601_set_mac_address(dev);
 399        }
 400
 401        if (dm_read_reg(dev, DM_CHIP_ID, &id) < 0) {
 402                netdev_err(dev->net, "Error reading chip ID\n");
 403                ret = -ENODEV;
 404                goto out;
 405        }
 406
 407        /* put dm9620 devices in dm9601 mode */
 408        if (id == ID_DM9620) {
 409                u8 mode;
 410
 411                if (dm_read_reg(dev, DM_MODE_CTRL, &mode) < 0) {
 412                        netdev_err(dev->net, "Error reading MODE_CTRL\n");
 413                        ret = -ENODEV;
 414                        goto out;
 415                }
 416                dm_write_reg(dev, DM_MODE_CTRL, mode & 0x7f);
 417        }
 418
 419        /* power up phy */
 420        dm_write_reg(dev, DM_GPR_CTRL, 1);
 421        dm_write_reg(dev, DM_GPR_DATA, 0);
 422
 423        /* receive broadcast packets */
 424        dm9601_set_multicast(dev->net);
 425
 426        dm9601_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
 427        dm9601_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
 428                          ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
 429        mii_nway_restart(&dev->mii);
 430
 431out:
 432        return ret;
 433}
 434
 435static int dm9601_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 436{
 437        u8 status;
 438        int len;
 439
 440        /* format:
 441           b1: rx status
 442           b2: packet length (incl crc) low
 443           b3: packet length (incl crc) high
 444           b4..n-4: packet data
 445           bn-3..bn: ethernet crc
 446         */
 447
 448        if (unlikely(skb->len < DM_RX_OVERHEAD)) {
 449                dev_err(&dev->udev->dev, "unexpected tiny rx frame\n");
 450                return 0;
 451        }
 452
 453        status = skb->data[0];
 454        len = (skb->data[1] | (skb->data[2] << 8)) - 4;
 455
 456        if (unlikely(status & 0xbf)) {
 457                if (status & 0x01) dev->net->stats.rx_fifo_errors++;
 458                if (status & 0x02) dev->net->stats.rx_crc_errors++;
 459                if (status & 0x04) dev->net->stats.rx_frame_errors++;
 460                if (status & 0x20) dev->net->stats.rx_missed_errors++;
 461                if (status & 0x90) dev->net->stats.rx_length_errors++;
 462                return 0;
 463        }
 464
 465        skb_pull(skb, 3);
 466        skb_trim(skb, len);
 467
 468        return 1;
 469}
 470
 471static struct sk_buff *dm9601_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
 472                                       gfp_t flags)
 473{
 474        int len, pad;
 475
 476        /* format:
 477           b1: packet length low
 478           b2: packet length high
 479           b3..n: packet data
 480        */
 481
 482        len = skb->len + DM_TX_OVERHEAD;
 483
 484        /* workaround for dm962x errata with tx fifo getting out of
 485         * sync if a USB bulk transfer retry happens right after a
 486         * packet with odd / maxpacket length by adding up to 3 bytes
 487         * padding.
 488         */
 489        while ((len & 1) || !(len % dev->maxpacket))
 490                len++;
 491
 492        len -= DM_TX_OVERHEAD; /* hw header doesn't count as part of length */
 493        pad = len - skb->len;
 494
 495        if (skb_headroom(skb) < DM_TX_OVERHEAD || skb_tailroom(skb) < pad) {
 496                struct sk_buff *skb2;
 497
 498                skb2 = skb_copy_expand(skb, DM_TX_OVERHEAD, pad, flags);
 499                dev_kfree_skb_any(skb);
 500                skb = skb2;
 501                if (!skb)
 502                        return NULL;
 503        }
 504
 505        __skb_push(skb, DM_TX_OVERHEAD);
 506
 507        if (pad) {
 508                memset(skb->data + skb->len, 0, pad);
 509                __skb_put(skb, pad);
 510        }
 511
 512        skb->data[0] = len;
 513        skb->data[1] = len >> 8;
 514
 515        return skb;
 516}
 517
 518static void dm9601_status(struct usbnet *dev, struct urb *urb)
 519{
 520        int link;
 521        u8 *buf;
 522
 523        /* format:
 524           b0: net status
 525           b1: tx status 1
 526           b2: tx status 2
 527           b3: rx status
 528           b4: rx overflow
 529           b5: rx count
 530           b6: tx count
 531           b7: gpr
 532        */
 533
 534        if (urb->actual_length < 8)
 535                return;
 536
 537        buf = urb->transfer_buffer;
 538
 539        link = !!(buf[0] & 0x40);
 540        if (netif_carrier_ok(dev->net) != link) {
 541                usbnet_link_change(dev, link, 1);
 542                netdev_dbg(dev->net, "Link Status is: %d\n", link);
 543        }
 544}
 545
 546static int dm9601_link_reset(struct usbnet *dev)
 547{
 548        struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET };
 549
 550        mii_check_media(&dev->mii, 1, 1);
 551        mii_ethtool_gset(&dev->mii, &ecmd);
 552
 553        netdev_dbg(dev->net, "link_reset() speed: %u duplex: %d\n",
 554                   ethtool_cmd_speed(&ecmd), ecmd.duplex);
 555
 556        return 0;
 557}
 558
 559static const struct driver_info dm9601_info = {
 560        .description    = "Davicom DM96xx USB 10/100 Ethernet",
 561        .flags          = FLAG_ETHER | FLAG_LINK_INTR,
 562        .bind           = dm9601_bind,
 563        .rx_fixup       = dm9601_rx_fixup,
 564        .tx_fixup       = dm9601_tx_fixup,
 565        .status         = dm9601_status,
 566        .link_reset     = dm9601_link_reset,
 567        .reset          = dm9601_link_reset,
 568};
 569
 570static const struct usb_device_id products[] = {
 571        {
 572         USB_DEVICE(0x07aa, 0x9601),    /* Corega FEther USB-TXC */
 573         .driver_info = (unsigned long)&dm9601_info,
 574         },
 575        {
 576         USB_DEVICE(0x0a46, 0x9601),    /* Davicom USB-100 */
 577         .driver_info = (unsigned long)&dm9601_info,
 578         },
 579        {
 580         USB_DEVICE(0x0a46, 0x6688),    /* ZT6688 USB NIC */
 581         .driver_info = (unsigned long)&dm9601_info,
 582         },
 583        {
 584         USB_DEVICE(0x0a46, 0x0268),    /* ShanTou ST268 USB NIC */
 585         .driver_info = (unsigned long)&dm9601_info,
 586         },
 587        {
 588         USB_DEVICE(0x0a46, 0x8515),    /* ADMtek ADM8515 USB NIC */
 589         .driver_info = (unsigned long)&dm9601_info,
 590         },
 591        {
 592        USB_DEVICE(0x0a47, 0x9601),     /* Hirose USB-100 */
 593        .driver_info = (unsigned long)&dm9601_info,
 594         },
 595        {
 596        USB_DEVICE(0x0fe6, 0x8101),     /* DM9601 USB to Fast Ethernet Adapter */
 597        .driver_info = (unsigned long)&dm9601_info,
 598         },
 599        {
 600         USB_DEVICE(0x0fe6, 0x9700),    /* DM9601 USB to Fast Ethernet Adapter */
 601         .driver_info = (unsigned long)&dm9601_info,
 602         },
 603        {
 604         USB_DEVICE(0x0a46, 0x9000),    /* DM9000E */
 605         .driver_info = (unsigned long)&dm9601_info,
 606         },
 607        {
 608         USB_DEVICE(0x0a46, 0x9620),    /* DM9620 USB to Fast Ethernet Adapter */
 609         .driver_info = (unsigned long)&dm9601_info,
 610         },
 611        {
 612         USB_DEVICE(0x0a46, 0x9621),    /* DM9621A USB to Fast Ethernet Adapter */
 613         .driver_info = (unsigned long)&dm9601_info,
 614        },
 615        {
 616         USB_DEVICE(0x0a46, 0x9622),    /* DM9622 USB to Fast Ethernet Adapter */
 617         .driver_info = (unsigned long)&dm9601_info,
 618        },
 619        {
 620         USB_DEVICE(0x0a46, 0x0269),    /* DM962OA USB to Fast Ethernet Adapter */
 621         .driver_info = (unsigned long)&dm9601_info,
 622        },
 623        {
 624         USB_DEVICE(0x0a46, 0x1269),    /* DM9621A USB to Fast Ethernet Adapter */
 625         .driver_info = (unsigned long)&dm9601_info,
 626        },
 627        {},                     // END
 628};
 629
 630MODULE_DEVICE_TABLE(usb, products);
 631
 632static struct usb_driver dm9601_driver = {
 633        .name = "dm9601",
 634        .id_table = products,
 635        .probe = usbnet_probe,
 636        .disconnect = usbnet_disconnect,
 637        .suspend = usbnet_suspend,
 638        .resume = usbnet_resume,
 639        .disable_hub_initiated_lpm = 1,
 640};
 641
 642module_usb_driver(dm9601_driver);
 643
 644MODULE_AUTHOR("Peter Korsgaard <jacmet@sunsite.dk>");
 645MODULE_DESCRIPTION("Davicom DM96xx USB 10/100 ethernet devices");
 646MODULE_LICENSE("GPL");
 647