GNU Linux-libre 4.9.333-gnu1
[releases.git] / drivers / net / usb / mcs7830.c
1 /*
2  * MOSCHIP MCS7830 based (7730/7830/7832) USB 2.0 Ethernet Devices
3  *
4  * based on usbnet.c, asix.c and the vendor provided mcs7830 driver
5  *
6  * Copyright (C) 2010 Andreas Mohr <andi@lisas.de>
7  * Copyright (C) 2006 Arnd Bergmann <arnd@arndb.de>
8  * Copyright (C) 2003-2005 David Hollis <dhollis@davehollis.com>
9  * Copyright (C) 2005 Phil Chang <pchang23@sbcglobal.net>
10  * Copyright (c) 2002-2003 TiVo Inc.
11  *
12  * Definitions gathered from MOSCHIP, Data Sheet_7830DA.pdf (thanks!).
13  *
14  * 2010-12-19: add 7832 USB PID ("functionality same as MCS7830"),
15  *             per active notification by manufacturer
16  *
17  * TODO:
18  * - support HIF_REG_CONFIG_SLEEPMODE/HIF_REG_CONFIG_TXENABLE (via autopm?)
19  * - implement ethtool_ops get_pauseparam/set_pauseparam
20  *   via HIF_REG_PAUSE_THRESHOLD (>= revision C only!)
21  * - implement get_eeprom/[set_eeprom]
22  * - switch PHY on/off on ifup/ifdown (perhaps in usbnet.c, via MII)
23  * - mcs7830_get_regs() handling is weird: for rev 2 we return 32 regs,
24  *   can access only ~ 24, remaining user buffer is uninitialized garbage
25  * - anything else?
26  *
27  *
28  * This program is free software; you can redistribute it and/or modify
29  * it under the terms of the GNU General Public License as published by
30  * the Free Software Foundation; either version 2 of the License, or
31  * (at your option) any later version.
32  *
33  * This program is distributed in the hope that it will be useful,
34  * but WITHOUT ANY WARRANTY; without even the implied warranty of
35  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
36  * GNU General Public License for more details.
37  *
38  * You should have received a copy of the GNU General Public License
39  * along with this program; if not, see <http://www.gnu.org/licenses/>.
40  */
41
42 #include <linux/crc32.h>
43 #include <linux/etherdevice.h>
44 #include <linux/ethtool.h>
45 #include <linux/mii.h>
46 #include <linux/module.h>
47 #include <linux/netdevice.h>
48 #include <linux/slab.h>
49 #include <linux/usb.h>
50 #include <linux/usb/usbnet.h>
51
52 /* requests */
53 #define MCS7830_RD_BMREQ        (USB_DIR_IN  | USB_TYPE_VENDOR | \
54                                  USB_RECIP_DEVICE)
55 #define MCS7830_WR_BMREQ        (USB_DIR_OUT | USB_TYPE_VENDOR | \
56                                  USB_RECIP_DEVICE)
57 #define MCS7830_RD_BREQ         0x0E
58 #define MCS7830_WR_BREQ         0x0D
59
60 #define MCS7830_CTRL_TIMEOUT    1000
61 #define MCS7830_MAX_MCAST       64
62
63 #define MCS7830_VENDOR_ID       0x9710
64 #define MCS7832_PRODUCT_ID      0x7832
65 #define MCS7830_PRODUCT_ID      0x7830
66 #define MCS7730_PRODUCT_ID      0x7730
67
68 #define SITECOM_VENDOR_ID       0x0DF6
69 #define LN_030_PRODUCT_ID       0x0021
70
71 #define MCS7830_MII_ADVERTISE   (ADVERTISE_PAUSE_CAP | ADVERTISE_100FULL | \
72                                  ADVERTISE_100HALF | ADVERTISE_10FULL | \
73                                  ADVERTISE_10HALF | ADVERTISE_CSMA)
74
75 /* HIF_REG_XX corresponding index value */
76 enum {
77         HIF_REG_MULTICAST_HASH                  = 0x00,
78         HIF_REG_PACKET_GAP1                     = 0x08,
79         HIF_REG_PACKET_GAP2                     = 0x09,
80         HIF_REG_PHY_DATA                        = 0x0a,
81         HIF_REG_PHY_CMD1                        = 0x0c,
82            HIF_REG_PHY_CMD1_READ                = 0x40,
83            HIF_REG_PHY_CMD1_WRITE               = 0x20,
84            HIF_REG_PHY_CMD1_PHYADDR             = 0x01,
85         HIF_REG_PHY_CMD2                        = 0x0d,
86            HIF_REG_PHY_CMD2_PEND_FLAG_BIT       = 0x80,
87            HIF_REG_PHY_CMD2_READY_FLAG_BIT      = 0x40,
88         HIF_REG_CONFIG                          = 0x0e,
89         /* hmm, spec sez: "R/W", "Except bit 3" (likely TXENABLE). */
90            HIF_REG_CONFIG_CFG                   = 0x80,
91            HIF_REG_CONFIG_SPEED100              = 0x40,
92            HIF_REG_CONFIG_FULLDUPLEX_ENABLE     = 0x20,
93            HIF_REG_CONFIG_RXENABLE              = 0x10,
94            HIF_REG_CONFIG_TXENABLE              = 0x08,
95            HIF_REG_CONFIG_SLEEPMODE             = 0x04,
96            HIF_REG_CONFIG_ALLMULTICAST          = 0x02,
97            HIF_REG_CONFIG_PROMISCUOUS           = 0x01,
98         HIF_REG_ETHERNET_ADDR                   = 0x0f,
99         HIF_REG_FRAME_DROP_COUNTER              = 0x15, /* 0..ff; reset: 0 */
100         HIF_REG_PAUSE_THRESHOLD                 = 0x16,
101            HIF_REG_PAUSE_THRESHOLD_DEFAULT      = 0,
102 };
103
104 /* Trailing status byte in Ethernet Rx frame */
105 enum {
106         MCS7830_RX_SHORT_FRAME          = 0x01, /* < 64 bytes */
107         MCS7830_RX_LENGTH_ERROR         = 0x02, /* framelen != Ethernet length field */
108         MCS7830_RX_ALIGNMENT_ERROR      = 0x04, /* non-even number of nibbles */
109         MCS7830_RX_CRC_ERROR            = 0x08,
110         MCS7830_RX_LARGE_FRAME          = 0x10, /* > 1518 bytes */
111         MCS7830_RX_FRAME_CORRECT        = 0x20, /* frame is correct */
112         /* [7:6] reserved */
113 };
114
115 struct mcs7830_data {
116         u8 multi_filter[8];
117         u8 config;
118 };
119
120 static const char driver_name[] = "MOSCHIP usb-ethernet driver";
121
122 static int mcs7830_get_reg(struct usbnet *dev, u16 index, u16 size, void *data)
123 {
124         int ret;
125
126         ret = usbnet_read_cmd(dev, MCS7830_RD_BREQ, MCS7830_RD_BMREQ,
127                               0x0000, index, data, size);
128         if (ret < 0)
129                 return ret;
130         else if (ret < size)
131                 return -ENODATA;
132
133         return ret;
134 }
135
136 static int mcs7830_set_reg(struct usbnet *dev, u16 index, u16 size, const void *data)
137 {
138         return usbnet_write_cmd(dev, MCS7830_WR_BREQ, MCS7830_WR_BMREQ,
139                                 0x0000, index, data, size);
140 }
141
142 static void mcs7830_set_reg_async(struct usbnet *dev, u16 index, u16 size, void *data)
143 {
144         usbnet_write_cmd_async(dev, MCS7830_WR_BREQ, MCS7830_WR_BMREQ,
145                                 0x0000, index, data, size);
146 }
147
148 static int mcs7830_hif_get_mac_address(struct usbnet *dev, unsigned char *addr)
149 {
150         int ret = mcs7830_get_reg(dev, HIF_REG_ETHERNET_ADDR, ETH_ALEN, addr);
151         if (ret < 0)
152                 return ret;
153         return 0;
154 }
155
156 static int mcs7830_hif_set_mac_address(struct usbnet *dev, unsigned char *addr)
157 {
158         int ret = mcs7830_set_reg(dev, HIF_REG_ETHERNET_ADDR, ETH_ALEN, addr);
159
160         if (ret < 0)
161                 return ret;
162         return 0;
163 }
164
165 static int mcs7830_set_mac_address(struct net_device *netdev, void *p)
166 {
167         int ret;
168         struct usbnet *dev = netdev_priv(netdev);
169         struct sockaddr *addr = p;
170
171         if (netif_running(netdev))
172                 return -EBUSY;
173
174         if (!is_valid_ether_addr(addr->sa_data))
175                 return -EADDRNOTAVAIL;
176
177         ret = mcs7830_hif_set_mac_address(dev, addr->sa_data);
178
179         if (ret < 0)
180                 return ret;
181
182         /* it worked --> adopt it on netdev side */
183         memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
184
185         return 0;
186 }
187
188 static int mcs7830_read_phy(struct usbnet *dev, u8 index)
189 {
190         int ret;
191         int i;
192         __le16 val;
193
194         u8 cmd[2] = {
195                 HIF_REG_PHY_CMD1_READ | HIF_REG_PHY_CMD1_PHYADDR,
196                 HIF_REG_PHY_CMD2_PEND_FLAG_BIT | index,
197         };
198
199         mutex_lock(&dev->phy_mutex);
200         /* write the MII command */
201         ret = mcs7830_set_reg(dev, HIF_REG_PHY_CMD1, 2, cmd);
202         if (ret < 0)
203                 goto out;
204
205         /* wait for the data to become valid, should be within < 1ms */
206         for (i = 0; i < 10; i++) {
207                 ret = mcs7830_get_reg(dev, HIF_REG_PHY_CMD1, 2, cmd);
208                 if ((ret < 0) || (cmd[1] & HIF_REG_PHY_CMD2_READY_FLAG_BIT))
209                         break;
210                 ret = -EIO;
211                 msleep(1);
212         }
213         if (ret < 0)
214                 goto out;
215
216         /* read actual register contents */
217         ret = mcs7830_get_reg(dev, HIF_REG_PHY_DATA, 2, &val);
218         if (ret < 0)
219                 goto out;
220         ret = le16_to_cpu(val);
221         dev_dbg(&dev->udev->dev, "read PHY reg %02x: %04x (%d tries)\n",
222                 index, val, i);
223 out:
224         mutex_unlock(&dev->phy_mutex);
225         return ret;
226 }
227
228 static int mcs7830_write_phy(struct usbnet *dev, u8 index, u16 val)
229 {
230         int ret;
231         int i;
232         __le16 le_val;
233
234         u8 cmd[2] = {
235                 HIF_REG_PHY_CMD1_WRITE | HIF_REG_PHY_CMD1_PHYADDR,
236                 HIF_REG_PHY_CMD2_PEND_FLAG_BIT | (index & 0x1F),
237         };
238
239         mutex_lock(&dev->phy_mutex);
240
241         /* write the new register contents */
242         le_val = cpu_to_le16(val);
243         ret = mcs7830_set_reg(dev, HIF_REG_PHY_DATA, 2, &le_val);
244         if (ret < 0)
245                 goto out;
246
247         /* write the MII command */
248         ret = mcs7830_set_reg(dev, HIF_REG_PHY_CMD1, 2, cmd);
249         if (ret < 0)
250                 goto out;
251
252         /* wait for the command to be accepted by the PHY */
253         for (i = 0; i < 10; i++) {
254                 ret = mcs7830_get_reg(dev, HIF_REG_PHY_CMD1, 2, cmd);
255                 if ((ret < 0) || (cmd[1] & HIF_REG_PHY_CMD2_READY_FLAG_BIT))
256                         break;
257                 ret = -EIO;
258                 msleep(1);
259         }
260         if (ret < 0)
261                 goto out;
262
263         ret = 0;
264         dev_dbg(&dev->udev->dev, "write PHY reg %02x: %04x (%d tries)\n",
265                 index, val, i);
266 out:
267         mutex_unlock(&dev->phy_mutex);
268         return ret;
269 }
270
271 /*
272  * This algorithm comes from the original mcs7830 version 1.4 driver,
273  * not sure if it is needed.
274  */
275 static int mcs7830_set_autoneg(struct usbnet *dev, int ptrUserPhyMode)
276 {
277         int ret;
278         /* Enable all media types */
279         ret = mcs7830_write_phy(dev, MII_ADVERTISE, MCS7830_MII_ADVERTISE);
280
281         /* First reset BMCR */
282         if (!ret)
283                 ret = mcs7830_write_phy(dev, MII_BMCR, 0x0000);
284         /* Enable Auto Neg */
285         if (!ret)
286                 ret = mcs7830_write_phy(dev, MII_BMCR, BMCR_ANENABLE);
287         /* Restart Auto Neg (Keep the Enable Auto Neg Bit Set) */
288         if (!ret)
289                 ret = mcs7830_write_phy(dev, MII_BMCR,
290                                 BMCR_ANENABLE | BMCR_ANRESTART  );
291         return ret;
292 }
293
294
295 /*
296  * if we can read register 22, the chip revision is C or higher
297  */
298 static int mcs7830_get_rev(struct usbnet *dev)
299 {
300         u8 dummy[2];
301         int ret;
302         ret = mcs7830_get_reg(dev, HIF_REG_FRAME_DROP_COUNTER, 2, dummy);
303         if (ret > 0)
304                 return 2; /* Rev C or later */
305         return 1; /* earlier revision */
306 }
307
308 /*
309  * On rev. C we need to set the pause threshold
310  */
311 static void mcs7830_rev_C_fixup(struct usbnet *dev)
312 {
313         u8 pause_threshold = HIF_REG_PAUSE_THRESHOLD_DEFAULT;
314         int retry;
315
316         for (retry = 0; retry < 2; retry++) {
317                 if (mcs7830_get_rev(dev) == 2) {
318                         dev_info(&dev->udev->dev, "applying rev.C fixup\n");
319                         mcs7830_set_reg(dev, HIF_REG_PAUSE_THRESHOLD,
320                                         1, &pause_threshold);
321                 }
322                 msleep(1);
323         }
324 }
325
326 static int mcs7830_mdio_read(struct net_device *netdev, int phy_id,
327                              int location)
328 {
329         struct usbnet *dev = netdev_priv(netdev);
330         return mcs7830_read_phy(dev, location);
331 }
332
333 static void mcs7830_mdio_write(struct net_device *netdev, int phy_id,
334                                 int location, int val)
335 {
336         struct usbnet *dev = netdev_priv(netdev);
337         mcs7830_write_phy(dev, location, val);
338 }
339
340 static int mcs7830_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
341 {
342         struct usbnet *dev = netdev_priv(net);
343         return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
344 }
345
346 static inline struct mcs7830_data *mcs7830_get_data(struct usbnet *dev)
347 {
348         return (struct mcs7830_data *)&dev->data;
349 }
350
351 static void mcs7830_hif_update_multicast_hash(struct usbnet *dev)
352 {
353         struct mcs7830_data *data = mcs7830_get_data(dev);
354         mcs7830_set_reg_async(dev, HIF_REG_MULTICAST_HASH,
355                                 sizeof data->multi_filter,
356                                 data->multi_filter);
357 }
358
359 static void mcs7830_hif_update_config(struct usbnet *dev)
360 {
361         /* implementation specific to data->config
362            (argument needs to be heap-based anyway - USB DMA!) */
363         struct mcs7830_data *data = mcs7830_get_data(dev);
364         mcs7830_set_reg_async(dev, HIF_REG_CONFIG, 1, &data->config);
365 }
366
367 static void mcs7830_data_set_multicast(struct net_device *net)
368 {
369         struct usbnet *dev = netdev_priv(net);
370         struct mcs7830_data *data = mcs7830_get_data(dev);
371
372         memset(data->multi_filter, 0, sizeof data->multi_filter);
373
374         data->config = HIF_REG_CONFIG_TXENABLE;
375
376         /* this should not be needed, but it doesn't work otherwise */
377         data->config |= HIF_REG_CONFIG_ALLMULTICAST;
378
379         if (net->flags & IFF_PROMISC) {
380                 data->config |= HIF_REG_CONFIG_PROMISCUOUS;
381         } else if (net->flags & IFF_ALLMULTI ||
382                    netdev_mc_count(net) > MCS7830_MAX_MCAST) {
383                 data->config |= HIF_REG_CONFIG_ALLMULTICAST;
384         } else if (netdev_mc_empty(net)) {
385                 /* just broadcast and directed */
386         } else {
387                 /* We use the 20 byte dev->data
388                  * for our 8 byte filter buffer
389                  * to avoid allocating memory that
390                  * is tricky to free later */
391                 struct netdev_hw_addr *ha;
392                 u32 crc_bits;
393
394                 /* Build the multicast hash filter. */
395                 netdev_for_each_mc_addr(ha, net) {
396                         crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26;
397                         data->multi_filter[crc_bits >> 3] |= 1 << (crc_bits & 7);
398                 }
399         }
400 }
401
402 static int mcs7830_apply_base_config(struct usbnet *dev)
403 {
404         int ret;
405
406         /* re-configure known MAC (suspend case etc.) */
407         ret = mcs7830_hif_set_mac_address(dev, dev->net->dev_addr);
408         if (ret) {
409                 dev_info(&dev->udev->dev, "Cannot set MAC address\n");
410                 goto out;
411         }
412
413         /* Set up PHY */
414         ret = mcs7830_set_autoneg(dev, 0);
415         if (ret) {
416                 dev_info(&dev->udev->dev, "Cannot set autoneg\n");
417                 goto out;
418         }
419
420         mcs7830_hif_update_multicast_hash(dev);
421         mcs7830_hif_update_config(dev);
422
423         mcs7830_rev_C_fixup(dev);
424         ret = 0;
425 out:
426         return ret;
427 }
428
429 /* credits go to asix_set_multicast */
430 static void mcs7830_set_multicast(struct net_device *net)
431 {
432         struct usbnet *dev = netdev_priv(net);
433
434         mcs7830_data_set_multicast(net);
435
436         mcs7830_hif_update_multicast_hash(dev);
437         mcs7830_hif_update_config(dev);
438 }
439
440 static int mcs7830_get_regs_len(struct net_device *net)
441 {
442         struct usbnet *dev = netdev_priv(net);
443
444         switch (mcs7830_get_rev(dev)) {
445         case 1:
446                 return 21;
447         case 2:
448                 return 32;
449         }
450         return 0;
451 }
452
453 static void mcs7830_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *drvinfo)
454 {
455         usbnet_get_drvinfo(net, drvinfo);
456 }
457
458 static void mcs7830_get_regs(struct net_device *net, struct ethtool_regs *regs, void *data)
459 {
460         struct usbnet *dev = netdev_priv(net);
461
462         regs->version = mcs7830_get_rev(dev);
463         mcs7830_get_reg(dev, 0, regs->len, data);
464 }
465
466 static const struct ethtool_ops mcs7830_ethtool_ops = {
467         .get_drvinfo            = mcs7830_get_drvinfo,
468         .get_regs_len           = mcs7830_get_regs_len,
469         .get_regs               = mcs7830_get_regs,
470
471         /* common usbnet calls */
472         .get_link               = usbnet_get_link,
473         .get_msglevel           = usbnet_get_msglevel,
474         .set_msglevel           = usbnet_set_msglevel,
475         .get_settings           = usbnet_get_settings,
476         .set_settings           = usbnet_set_settings,
477         .nway_reset             = usbnet_nway_reset,
478 };
479
480 static const struct net_device_ops mcs7830_netdev_ops = {
481         .ndo_open               = usbnet_open,
482         .ndo_stop               = usbnet_stop,
483         .ndo_start_xmit         = usbnet_start_xmit,
484         .ndo_tx_timeout         = usbnet_tx_timeout,
485         .ndo_change_mtu         = usbnet_change_mtu,
486         .ndo_validate_addr      = eth_validate_addr,
487         .ndo_do_ioctl           = mcs7830_ioctl,
488         .ndo_set_rx_mode        = mcs7830_set_multicast,
489         .ndo_set_mac_address    = mcs7830_set_mac_address,
490 };
491
492 static int mcs7830_bind(struct usbnet *dev, struct usb_interface *udev)
493 {
494         struct net_device *net = dev->net;
495         int ret;
496         int retry;
497
498         /* Initial startup: Gather MAC address setting from EEPROM */
499         ret = -EINVAL;
500         for (retry = 0; retry < 5 && ret; retry++)
501                 ret = mcs7830_hif_get_mac_address(dev, net->dev_addr);
502         if (ret) {
503                 dev_warn(&dev->udev->dev, "Cannot read MAC address\n");
504                 goto out;
505         }
506
507         mcs7830_data_set_multicast(net);
508
509         ret = mcs7830_apply_base_config(dev);
510         if (ret)
511                 goto out;
512
513         net->ethtool_ops = &mcs7830_ethtool_ops;
514         net->netdev_ops = &mcs7830_netdev_ops;
515
516         /* reserve space for the status byte on rx */
517         dev->rx_urb_size = ETH_FRAME_LEN + 1;
518
519         dev->mii.mdio_read = mcs7830_mdio_read;
520         dev->mii.mdio_write = mcs7830_mdio_write;
521         dev->mii.dev = net;
522         dev->mii.phy_id_mask = 0x3f;
523         dev->mii.reg_num_mask = 0x1f;
524         dev->mii.phy_id = *((u8 *) net->dev_addr + 1);
525
526         ret = usbnet_get_endpoints(dev, udev);
527 out:
528         return ret;
529 }
530
531 /* The chip always appends a status byte that we need to strip */
532 static int mcs7830_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
533 {
534         u8 status;
535
536         /* This check is no longer done by usbnet */
537         if (skb->len < dev->net->hard_header_len) {
538                 dev_err(&dev->udev->dev, "unexpected tiny rx frame\n");
539                 return 0;
540         }
541
542         skb_trim(skb, skb->len - 1);
543         status = skb->data[skb->len];
544
545         if (status != MCS7830_RX_FRAME_CORRECT) {
546                 dev_dbg(&dev->udev->dev, "rx fixup status %x\n", status);
547
548                 /* hmm, perhaps usbnet.c already sees a globally visible
549                    frame error and increments rx_errors on its own already? */
550                 dev->net->stats.rx_errors++;
551
552                 if (status &    (MCS7830_RX_SHORT_FRAME
553                                 |MCS7830_RX_LENGTH_ERROR
554                                 |MCS7830_RX_LARGE_FRAME))
555                         dev->net->stats.rx_length_errors++;
556                 if (status & MCS7830_RX_ALIGNMENT_ERROR)
557                         dev->net->stats.rx_frame_errors++;
558                 if (status & MCS7830_RX_CRC_ERROR)
559                         dev->net->stats.rx_crc_errors++;
560         }
561
562         return skb->len > 0;
563 }
564
565 static void mcs7830_status(struct usbnet *dev, struct urb *urb)
566 {
567         u8 *buf = urb->transfer_buffer;
568         bool link, link_changed;
569
570         if (urb->actual_length < 16)
571                 return;
572
573         link = !(buf[1] == 0x20);
574         link_changed = netif_carrier_ok(dev->net) != link;
575         if (link_changed) {
576                 usbnet_link_change(dev, link, 0);
577                 netdev_dbg(dev->net, "Link Status is: %d\n", link);
578         }
579 }
580
581 static const struct driver_info moschip_info = {
582         .description    = "MOSCHIP 7830/7832/7730 usb-NET adapter",
583         .bind           = mcs7830_bind,
584         .rx_fixup       = mcs7830_rx_fixup,
585         .flags          = FLAG_ETHER | FLAG_LINK_INTR,
586         .status         = mcs7830_status,
587         .in             = 1,
588         .out            = 2,
589 };
590
591 static const struct driver_info sitecom_info = {
592         .description    = "Sitecom LN-30 usb-NET adapter",
593         .bind           = mcs7830_bind,
594         .rx_fixup       = mcs7830_rx_fixup,
595         .flags          = FLAG_ETHER | FLAG_LINK_INTR,
596         .status         = mcs7830_status,
597         .in             = 1,
598         .out            = 2,
599 };
600
601 static const struct usb_device_id products[] = {
602         {
603                 USB_DEVICE(MCS7830_VENDOR_ID, MCS7832_PRODUCT_ID),
604                 .driver_info = (unsigned long) &moschip_info,
605         },
606         {
607                 USB_DEVICE(MCS7830_VENDOR_ID, MCS7830_PRODUCT_ID),
608                 .driver_info = (unsigned long) &moschip_info,
609         },
610         {
611                 USB_DEVICE(MCS7830_VENDOR_ID, MCS7730_PRODUCT_ID),
612                 .driver_info = (unsigned long) &moschip_info,
613         },
614         {
615                 USB_DEVICE(SITECOM_VENDOR_ID, LN_030_PRODUCT_ID),
616                 .driver_info = (unsigned long) &sitecom_info,
617         },
618         {},
619 };
620 MODULE_DEVICE_TABLE(usb, products);
621
622 static int mcs7830_reset_resume (struct usb_interface *intf)
623 {
624         /* YES, this function is successful enough that ethtool -d
625            does show same output pre-/post-suspend */
626
627         struct usbnet           *dev = usb_get_intfdata(intf);
628
629         mcs7830_apply_base_config(dev);
630
631         usbnet_resume(intf);
632
633         return 0;
634 }
635
636 static struct usb_driver mcs7830_driver = {
637         .name = driver_name,
638         .id_table = products,
639         .probe = usbnet_probe,
640         .disconnect = usbnet_disconnect,
641         .suspend = usbnet_suspend,
642         .resume = usbnet_resume,
643         .reset_resume = mcs7830_reset_resume,
644         .disable_hub_initiated_lpm = 1,
645 };
646
647 module_usb_driver(mcs7830_driver);
648
649 MODULE_DESCRIPTION("USB to network adapter MCS7830)");
650 MODULE_LICENSE("GPL");