X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fusb%2Fnet%2Frtl8150.c;h=670262a38a0f25e8471ad9073ac970901f1c981f;hb=refs%2Fheads%2Fvserver;hp=640aa5b6809568539784de728783a468b17889c4;hpb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;p=linux-2.6.git diff --git a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c index 640aa5b68..670262a38 100644 --- a/drivers/usb/net/rtl8150.c +++ b/drivers/usb/net/rtl8150.c @@ -6,7 +6,6 @@ * version 2 as published by the Free Software Foundation. */ -#include #include #include #include @@ -20,7 +19,7 @@ #include /* Version Information */ -#define DRIVER_VERSION "v0.6.1 (2004/03/13)" +#define DRIVER_VERSION "v0.6.2 (2004/08/27)" #define DRIVER_AUTHOR "Petko Manolov " #define DRIVER_DESC "rtl8150 based usb-ethernet driver" @@ -125,15 +124,18 @@ #define RX_URB_FAIL 3 /* Define these values to match your device */ -#define VENDOR_ID_REALTEK 0x0bda +#define VENDOR_ID_REALTEK 0x0bda #define VENDOR_ID_MELCO 0x0411 -#define VENDOR_ID_MICRONET 0x3980 +#define VENDOR_ID_MICRONET 0x3980 #define VENDOR_ID_LONGSHINE 0x07b8 +#define VENDOR_ID_OQO 0x1557 +#define VENDOR_ID_ZYXEL 0x0586 #define PRODUCT_ID_RTL8150 0x8150 #define PRODUCT_ID_LUAKTX 0x0012 #define PRODUCT_ID_LCS8138TX 0x401a #define PRODUCT_ID_SP128AR 0x0003 +#define PRODUCT_ID_PRESTIGE 0x401a #undef EEPROM_WRITE @@ -143,6 +145,8 @@ static struct usb_device_id rtl8150_table[] = { {USB_DEVICE(VENDOR_ID_MELCO, PRODUCT_ID_LUAKTX)}, {USB_DEVICE(VENDOR_ID_MICRONET, PRODUCT_ID_SP128AR)}, {USB_DEVICE(VENDOR_ID_LONGSHINE, PRODUCT_ID_LCS8138TX)}, + {USB_DEVICE(VENDOR_ID_OQO, PRODUCT_ID_RTL8150)}, + {USB_DEVICE(VENDOR_ID_ZYXEL, PRODUCT_ID_PRESTIGE)}, {} }; @@ -167,23 +171,24 @@ struct rtl8150 { typedef struct rtl8150 rtl8150_t; -static unsigned long multicast_filter_limit = 32; - static void fill_skb_pool(rtl8150_t *); static void free_skb_pool(rtl8150_t *); static inline struct sk_buff *pull_skb(rtl8150_t *); static void rtl8150_disconnect(struct usb_interface *intf); static int rtl8150_probe(struct usb_interface *intf, const struct usb_device_id *id); +static int rtl8150_suspend(struct usb_interface *intf, pm_message_t message); +static int rtl8150_resume(struct usb_interface *intf); static const char driver_name [] = "rtl8150"; static struct usb_driver rtl8150_driver = { - .owner = THIS_MODULE, .name = driver_name, .probe = rtl8150_probe, .disconnect = rtl8150_disconnect, .id_table = rtl8150_table, + .suspend = rtl8150_suspend, + .resume = rtl8150_resume }; /* @@ -195,17 +200,17 @@ static int get_registers(rtl8150_t * dev, u16 indx, u16 size, void *data) { return usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), RTL8150_REQ_GET_REGS, RTL8150_REQT_READ, - indx, 0, data, size, HZ / 2); + indx, 0, data, size, 500); } static int set_registers(rtl8150_t * dev, u16 indx, u16 size, void *data) { return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), RTL8150_REQ_SET_REGS, RTL8150_REQT_WRITE, - indx, 0, data, size, HZ / 2); + indx, 0, data, size, 500); } -static void ctrl_callback(struct urb *urb, struct pt_regs *regs) +static void ctrl_callback(struct urb *urb) { rtl8150_t *dev; @@ -239,9 +244,11 @@ static int async_set_registers(rtl8150_t * dev, u16 indx, u16 size) usb_fill_control_urb(dev->ctrl_urb, dev->udev, usb_sndctrlpipe(dev->udev, 0), (char *) &dev->dr, &dev->rx_creg, size, ctrl_callback, dev); - if ((ret = usb_submit_urb(dev->ctrl_urb, GFP_ATOMIC))) + if ((ret = usb_submit_urb(dev->ctrl_urb, GFP_ATOMIC))) { + if (ret == -ENODEV) + netif_device_detach(dev->netdev); err("control request submission failed: %d", ret); - else + } else set_bit(RX_REG_SET, &dev->flags); return ret; @@ -277,7 +284,8 @@ static int write_mii_word(rtl8150_t * dev, u8 phy, __u8 indx, u16 reg) u8 data[3], tmp; data[0] = phy; - *(data + 1) = cpu_to_le16p(®); + data[1] = reg & 0xff; + data[2] = (reg >> 8) & 0xff; tmp = indx | PHY_WRITE | PHY_GO; i = 0; @@ -304,15 +312,12 @@ static inline void set_ethernet_addr(rtl8150_t * dev) static int rtl8150_set_mac_address(struct net_device *netdev, void *p) { struct sockaddr *addr = p; - rtl8150_t *dev; + rtl8150_t *dev = netdev_priv(netdev); int i; if (netif_running(netdev)) return -EBUSY; - dev = netdev->priv; - if (dev == NULL) { - return -ENODEV; - } + memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); dbg("%s: Setting MAC address to ", netdev->name); for (i = 0; i < 5; i++) @@ -392,10 +397,10 @@ static void free_all_urbs(rtl8150_t * dev) static void unlink_all_urbs(rtl8150_t * dev) { - usb_unlink_urb(dev->rx_urb); - usb_unlink_urb(dev->tx_urb); - usb_unlink_urb(dev->intr_urb); - usb_unlink_urb(dev->ctrl_urb); + usb_kill_urb(dev->rx_urb); + usb_kill_urb(dev->tx_urb); + usb_kill_urb(dev->intr_urb); + usb_kill_urb(dev->ctrl_urb); } static inline struct sk_buff *pull_skb(rtl8150_t *dev) @@ -413,13 +418,14 @@ static inline struct sk_buff *pull_skb(rtl8150_t *dev) return NULL; } -static void read_bulk_callback(struct urb *urb, struct pt_regs *regs) +static void read_bulk_callback(struct urb *urb) { rtl8150_t *dev; unsigned pkt_len, res; struct sk_buff *skb; struct net_device *netdev; u16 rx_stat; + int status; dev = urb->context; if (!dev) @@ -435,7 +441,7 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs) break; case -ENOENT: return; /* the urb is in unlink state */ - case -ETIMEDOUT: + case -ETIME: warn("may be reset is needed?.."); goto goon; default: @@ -469,7 +475,10 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs) goon: usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1), dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev); - if (usb_submit_urb(dev->rx_urb, GFP_ATOMIC)) { + status = usb_submit_urb(dev->rx_urb, GFP_ATOMIC); + if (status == -ENODEV) + netif_device_detach(dev->netdev); + else if (status) { set_bit(RX_URB_FAIL, &dev->flags); goto resched; } else { @@ -485,6 +494,7 @@ static void rx_fixup(unsigned long data) { rtl8150_t *dev; struct sk_buff *skb; + int status; dev = (rtl8150_t *)data; @@ -503,10 +513,13 @@ static void rx_fixup(unsigned long data) usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1), dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev); try_again: - if (usb_submit_urb(dev->rx_urb, GFP_ATOMIC)) { + status = usb_submit_urb(dev->rx_urb, GFP_ATOMIC); + if (status == -ENODEV) { + netif_device_detach(dev->netdev); + } else if (status) { set_bit(RX_URB_FAIL, &dev->flags); goto tlsched; - } else { + } else { clear_bit(RX_URB_FAIL, &dev->flags); } @@ -515,7 +528,7 @@ tlsched: tasklet_schedule(&dev->tl); } -static void write_bulk_callback(struct urb *urb, struct pt_regs *regs) +static void write_bulk_callback(struct urb *urb) { rtl8150_t *dev; @@ -531,7 +544,7 @@ static void write_bulk_callback(struct urb *urb, struct pt_regs *regs) netif_wake_queue(dev->netdev); } -static void intr_callback(struct urb *urb, struct pt_regs *regs) +static void intr_callback(struct urb *urb) { rtl8150_t *dev; __u8 *d; @@ -577,13 +590,44 @@ static void intr_callback(struct urb *urb, struct pt_regs *regs) } resubmit: - status = usb_submit_urb (urb, SLAB_ATOMIC); - if (status) + status = usb_submit_urb (urb, GFP_ATOMIC); + if (status == -ENODEV) + netif_device_detach(dev->netdev); + else if (status) err ("can't resubmit intr, %s-%s/input0, status %d", dev->udev->bus->bus_name, dev->udev->devpath, status); } +static int rtl8150_suspend(struct usb_interface *intf, pm_message_t message) +{ + rtl8150_t *dev = usb_get_intfdata(intf); + + netif_device_detach(dev->netdev); + + if (netif_running(dev->netdev)) { + usb_kill_urb(dev->rx_urb); + usb_kill_urb(dev->intr_urb); + } + return 0; +} + +static int rtl8150_resume(struct usb_interface *intf) +{ + rtl8150_t *dev = usb_get_intfdata(intf); + + netif_device_attach(dev->netdev); + if (netif_running(dev->netdev)) { + dev->rx_urb->status = 0; + dev->rx_urb->actual_length = 0; + read_bulk_callback(dev->rx_urb); + + dev->intr_urb->status = 0; + dev->intr_urb->actual_length = 0; + intr_callback(dev->intr_urb); + } + return 0; +} /* ** @@ -651,32 +695,25 @@ static void disable_net_traffic(rtl8150_t * dev) static struct net_device_stats *rtl8150_netdev_stats(struct net_device *dev) { - return &((rtl8150_t *) dev->priv)->stats; + return &((rtl8150_t *)netdev_priv(dev))->stats; } static void rtl8150_tx_timeout(struct net_device *netdev) { - rtl8150_t *dev; - - dev = netdev->priv; - if (!dev) - return; + rtl8150_t *dev = netdev_priv(netdev); warn("%s: Tx timeout.", netdev->name); - dev->tx_urb->transfer_flags |= URB_ASYNC_UNLINK; usb_unlink_urb(dev->tx_urb); dev->stats.tx_errors++; } static void rtl8150_set_multicast(struct net_device *netdev) { - rtl8150_t *dev; - - dev = netdev->priv; + rtl8150_t *dev = netdev_priv(netdev); netif_stop_queue(netdev); if (netdev->flags & IFF_PROMISC) { dev->rx_creg |= cpu_to_le16(0x0001); info("%s: promiscuous mode", netdev->name); - } else if ((netdev->mc_count > multicast_filter_limit) || + } else if (netdev->mc_count || (netdev->flags & IFF_ALLMULTI)) { dev->rx_creg &= cpu_to_le16(0xfffe); dev->rx_creg |= cpu_to_le16(0x0002); @@ -691,20 +728,24 @@ static void rtl8150_set_multicast(struct net_device *netdev) static int rtl8150_start_xmit(struct sk_buff *skb, struct net_device *netdev) { - rtl8150_t *dev; + rtl8150_t *dev = netdev_priv(netdev); int count, res; netif_stop_queue(netdev); - dev = netdev->priv; count = (skb->len < 60) ? 60 : skb->len; count = (count & 0x3f) ? count : count + 1; dev->tx_skb = skb; usb_fill_bulk_urb(dev->tx_urb, dev->udev, usb_sndbulkpipe(dev->udev, 2), skb->data, count, write_bulk_callback, dev); if ((res = usb_submit_urb(dev->tx_urb, GFP_ATOMIC))) { - warn("failed tx_urb %d\n", res); - dev->stats.tx_errors++; - netif_start_queue(netdev); + /* Can we get/handle EPIPE here? */ + if (res == -ENODEV) + netif_device_detach(dev->netdev); + else { + warn("failed tx_urb %d\n", res); + dev->stats.tx_errors++; + netif_start_queue(netdev); + } } else { dev->stats.tx_packets++; dev->stats.tx_bytes += skb->len; @@ -717,7 +758,7 @@ static int rtl8150_start_xmit(struct sk_buff *skb, struct net_device *netdev) static void set_carrier(struct net_device *netdev) { - rtl8150_t *dev = netdev->priv; + rtl8150_t *dev = netdev_priv(netdev); short tmp; get_registers(dev, CSCR, 2, &tmp); @@ -729,13 +770,9 @@ static void set_carrier(struct net_device *netdev) static int rtl8150_open(struct net_device *netdev) { - rtl8150_t *dev; + rtl8150_t *dev = netdev_priv(netdev); int res; - dev = netdev->priv; - if (dev == NULL) { - return -ENODEV; - } if (dev->rx_skb == NULL) dev->rx_skb = pull_skb(dev); if (!dev->rx_skb) @@ -745,29 +782,34 @@ static int rtl8150_open(struct net_device *netdev) usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1), dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev); - if ((res = usb_submit_urb(dev->rx_urb, GFP_KERNEL))) + if ((res = usb_submit_urb(dev->rx_urb, GFP_KERNEL))) { + if (res == -ENODEV) + netif_device_detach(dev->netdev); warn("%s: rx_urb submit failed: %d", __FUNCTION__, res); + return res; + } usb_fill_int_urb(dev->intr_urb, dev->udev, usb_rcvintpipe(dev->udev, 3), dev->intr_buff, INTBUFSIZE, intr_callback, dev, dev->intr_interval); - if ((res = usb_submit_urb(dev->intr_urb, GFP_KERNEL))) + if ((res = usb_submit_urb(dev->intr_urb, GFP_KERNEL))) { + if (res == -ENODEV) + netif_device_detach(dev->netdev); warn("%s: intr_urb submit failed: %d", __FUNCTION__, res); - netif_start_queue(netdev); + usb_kill_urb(dev->rx_urb); + return res; + } enable_net_traffic(dev); set_carrier(netdev); + netif_start_queue(netdev); return res; } static int rtl8150_close(struct net_device *netdev) { - rtl8150_t *dev; + rtl8150_t *dev = netdev_priv(netdev); int res = 0; - dev = netdev->priv; - if (!dev) - return -ENODEV; - netif_stop_queue(netdev); if (!test_bit(RTL8150_UNPLUG, &dev->flags)) disable_net_traffic(dev); @@ -776,93 +818,64 @@ static int rtl8150_close(struct net_device *netdev) return res; } -static int rtl8150_ethtool_ioctl(struct net_device *netdev, void __user *uaddr) +static void rtl8150_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *info) { - rtl8150_t *dev; - int cmd; + rtl8150_t *dev = netdev_priv(netdev); + + strncpy(info->driver, driver_name, ETHTOOL_BUSINFO_LEN); + strncpy(info->version, DRIVER_VERSION, ETHTOOL_BUSINFO_LEN); + usb_make_path(dev->udev, info->bus_info, sizeof info->bus_info); +} - dev = netdev->priv; - if (get_user(cmd, (int __user *) uaddr)) - return -EFAULT; +static int rtl8150_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) +{ + rtl8150_t *dev = netdev_priv(netdev); + short lpa, bmcr; - switch (cmd) { - case ETHTOOL_GDRVINFO:{ - struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; - - strncpy(info.driver, driver_name, ETHTOOL_BUSINFO_LEN); - strncpy(info.version, DRIVER_VERSION, ETHTOOL_BUSINFO_LEN); - usb_make_path(dev->udev, info.bus_info, sizeof info.bus_info); - if (copy_to_user(uaddr, &info, sizeof(info))) - return -EFAULT; - return 0; - } - case ETHTOOL_GSET:{ - struct ethtool_cmd ecmd; - short lpa, bmcr; - - if (copy_from_user(&ecmd, uaddr, sizeof(ecmd))) - return -EFAULT; - ecmd.supported = (SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | - SUPPORTED_100baseT_Full | - SUPPORTED_Autoneg | - SUPPORTED_TP | SUPPORTED_MII); - ecmd.port = PORT_TP; - ecmd.transceiver = XCVR_INTERNAL; - ecmd.phy_address = dev->phy; - get_registers(dev, BMCR, 2, &bmcr); - get_registers(dev, ANLP, 2, &lpa); - if (bmcr & BMCR_ANENABLE) { - ecmd.autoneg = AUTONEG_ENABLE; - ecmd.speed = (lpa & (LPA_100HALF | LPA_100FULL)) ? - SPEED_100 : SPEED_10; - if (ecmd.speed == SPEED_100) - ecmd.duplex = (lpa & LPA_100FULL) ? - DUPLEX_FULL : DUPLEX_HALF; - else - ecmd.duplex = (lpa & LPA_10FULL) ? - DUPLEX_FULL : DUPLEX_HALF; - } else { - ecmd.autoneg = AUTONEG_DISABLE; - ecmd.speed = (bmcr & BMCR_SPEED100) ? - SPEED_100 : SPEED_10; - ecmd.duplex = (bmcr & BMCR_FULLDPLX) ? + ecmd->supported = (SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full | + SUPPORTED_Autoneg | + SUPPORTED_TP | SUPPORTED_MII); + ecmd->port = PORT_TP; + ecmd->transceiver = XCVR_INTERNAL; + ecmd->phy_address = dev->phy; + get_registers(dev, BMCR, 2, &bmcr); + get_registers(dev, ANLP, 2, &lpa); + if (bmcr & BMCR_ANENABLE) { + ecmd->autoneg = AUTONEG_ENABLE; + ecmd->speed = (lpa & (LPA_100HALF | LPA_100FULL)) ? + SPEED_100 : SPEED_10; + if (ecmd->speed == SPEED_100) + ecmd->duplex = (lpa & LPA_100FULL) ? DUPLEX_FULL : DUPLEX_HALF; - } - if (copy_to_user(uaddr, &ecmd, sizeof(ecmd))) - return -EFAULT; - return 0; - } - case ETHTOOL_SSET: - return -ENOTSUPP; - case ETHTOOL_GLINK:{ - struct ethtool_value edata = { ETHTOOL_GLINK }; - - edata.data = netif_carrier_ok(netdev); - if (copy_to_user(uaddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - default: - return -EOPNOTSUPP; + else + ecmd->duplex = (lpa & LPA_10FULL) ? + DUPLEX_FULL : DUPLEX_HALF; + } else { + ecmd->autoneg = AUTONEG_DISABLE; + ecmd->speed = (bmcr & BMCR_SPEED100) ? + SPEED_100 : SPEED_10; + ecmd->duplex = (bmcr & BMCR_FULLDPLX) ? + DUPLEX_FULL : DUPLEX_HALF; } + return 0; } +static struct ethtool_ops ops = { + .get_drvinfo = rtl8150_get_drvinfo, + .get_settings = rtl8150_get_settings, + .get_link = ethtool_op_get_link +}; + static int rtl8150_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) { - rtl8150_t *dev; - u16 *data; - int res; - - dev = netdev->priv; - data = (u16 *) & rq->ifr_ifru; - res = 0; + rtl8150_t *dev = netdev_priv(netdev); + u16 *data = (u16 *) & rq->ifr_ifru; + int res = 0; switch (cmd) { - case SIOCETHTOOL: - res = rtl8150_ethtool_ioctl(netdev, rq->ifr_data); - break; case SIOCDEVPRIVATE: data[0] = dev->phy; case SIOCDEVPRIVATE + 1: @@ -887,23 +900,18 @@ static int rtl8150_probe(struct usb_interface *intf, rtl8150_t *dev; struct net_device *netdev; - dev = kmalloc(sizeof(rtl8150_t), GFP_KERNEL); - if (!dev) { + netdev = alloc_etherdev(sizeof(rtl8150_t)); + if (!netdev) { err("Out of memory"); return -ENOMEM; - } else - memset(dev, 0, sizeof(rtl8150_t)); + } + + dev = netdev_priv(netdev); + memset(dev, 0, sizeof(rtl8150_t)); dev->intr_buff = kmalloc(INTBUFSIZE, GFP_KERNEL); if (!dev->intr_buff) { - kfree(dev); - return -ENOMEM; - } - netdev = alloc_etherdev(0); - if (!netdev) { - kfree(dev->intr_buff); - kfree(dev); - err("Oh boy, out of memory again?!?"); + free_netdev(netdev); return -ENOMEM; } @@ -913,7 +921,6 @@ static int rtl8150_probe(struct usb_interface *intf, dev->udev = udev; dev->netdev = netdev; SET_MODULE_OWNER(netdev); - netdev->priv = dev; netdev->open = rtl8150_open; netdev->stop = rtl8150_close; netdev->do_ioctl = rtl8150_ioctl; @@ -924,6 +931,7 @@ static int rtl8150_probe(struct usb_interface *intf, netdev->set_mac_address = rtl8150_set_mac_address; netdev->get_stats = rtl8150_netdev_stats; netdev->mtu = RTL8150_MTU; + SET_ETHTOOL_OPS(netdev, &ops); dev->intr_interval = 100; /* 100ms */ if (!alloc_all_urbs(dev)) { @@ -936,7 +944,6 @@ static int rtl8150_probe(struct usb_interface *intf, } fill_skb_pool(dev); set_ethernet_addr(dev); - info("%s: rtl8150 is detected", netdev->name); usb_set_intfdata(intf, dev); SET_NETDEV_DEV(netdev, &intf->dev); @@ -944,6 +951,9 @@ static int rtl8150_probe(struct usb_interface *intf, err("couldn't register the device"); goto out2; } + + info("%s: rtl8150 is detected", netdev->name); + return 0; out2: @@ -954,7 +964,6 @@ out1: out: kfree(dev->intr_buff); free_netdev(netdev); - kfree(dev); return -EIO; } @@ -965,15 +974,16 @@ static void rtl8150_disconnect(struct usb_interface *intf) usb_set_intfdata(intf, NULL); if (dev) { set_bit(RTL8150_UNPLUG, &dev->flags); + tasklet_disable(&dev->tl); + tasklet_kill(&dev->tl); unregister_netdev(dev->netdev); unlink_all_urbs(dev); free_all_urbs(dev); free_skb_pool(dev); if (dev->rx_skb) dev_kfree_skb(dev->rx_skb); - free_netdev(dev->netdev); kfree(dev->intr_buff); - kfree(dev); + free_netdev(dev->netdev); } }