diff options
Diffstat (limited to 'drivers/net/usb/rtl8150.c')
| -rw-r--r-- | drivers/net/usb/rtl8150.c | 304 |
1 files changed, 121 insertions, 183 deletions
diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c index f14d225404d..6e87e571004 100644 --- a/drivers/net/usb/rtl8150.c +++ b/drivers/net/usb/rtl8150.c @@ -6,7 +6,6 @@ * version 2 as published by the Free Software Foundation. */ -#include <linux/init.h> #include <linux/signal.h> #include <linux/slab.h> #include <linux/module.h> @@ -85,32 +84,6 @@ #define INT_CRERR_CNT 0x06 #define INT_COL_CNT 0x07 -/* Transmit status register errors */ -#define TSR_ECOL (1<<5) -#define TSR_LCOL (1<<4) -#define TSR_LOSS_CRS (1<<3) -#define TSR_JBR (1<<2) -#define TSR_ERRORS (TSR_ECOL | TSR_LCOL | TSR_LOSS_CRS | TSR_JBR) -/* Receive status register errors */ -#define RSR_CRC (1<<2) -#define RSR_FAE (1<<1) -#define RSR_ERRORS (RSR_CRC | RSR_FAE) - -/* Media status register definitions */ -#define MSR_DUPLEX (1<<4) -#define MSR_SPEED (1<<3) -#define MSR_LINK (1<<2) - -/* Interrupt pipe data */ -#define INT_TSR 0x00 -#define INT_RSR 0x01 -#define INT_MSR 0x02 -#define INT_WAKSR 0x03 -#define INT_TXOK_CNT 0x04 -#define INT_RXLOST_CNT 0x05 -#define INT_CRERR_CNT 0x06 -#define INT_COL_CNT 0x07 - #define RTL8150_MTU 1540 #define RTL8150_TX_TIMEOUT (HZ) @@ -156,39 +129,25 @@ struct rtl8150 { struct usb_device *udev; struct tasklet_struct tl; struct net_device *netdev; - struct urb *rx_urb, *tx_urb, *intr_urb, *ctrl_urb; + struct urb *rx_urb, *tx_urb, *intr_urb; struct sk_buff *tx_skb, *rx_skb; struct sk_buff *rx_skb_pool[RX_SKB_POOL_SIZE]; spinlock_t rx_pool_lock; struct usb_ctrlrequest dr; int intr_interval; - __le16 rx_creg; u8 *intr_buff; u8 phy; }; typedef struct rtl8150 rtl8150_t; -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); +struct async_req { + struct usb_ctrlrequest dr; + u16 rx_creg; +}; static const char driver_name [] = "rtl8150"; -static struct usb_driver rtl8150_driver = { - .name = driver_name, - .probe = rtl8150_probe, - .disconnect = rtl8150_disconnect, - .id_table = rtl8150_table, - .suspend = rtl8150_suspend, - .resume = rtl8150_resume -}; - /* ** ** device related part of the code @@ -208,50 +167,47 @@ static int set_registers(rtl8150_t * dev, u16 indx, u16 size, void *data) indx, 0, data, size, 500); } -static void ctrl_callback(struct urb *urb) +static void async_set_reg_cb(struct urb *urb) { - rtl8150_t *dev; + struct async_req *req = (struct async_req *)urb->context; int status = urb->status; - switch (status) { - case 0: - break; - case -EINPROGRESS: - break; - case -ENOENT: - break; - default: - if (printk_ratelimit()) - dev_warn(&urb->dev->dev, "ctrl urb status %d\n", status); - } - dev = urb->context; - clear_bit(RX_REG_SET, &dev->flags); + if (status < 0) + dev_dbg(&urb->dev->dev, "%s failed with %d", __func__, status); + kfree(req); + usb_free_urb(urb); } -static int async_set_registers(rtl8150_t * dev, u16 indx, u16 size) +static int async_set_registers(rtl8150_t *dev, u16 indx, u16 size, u16 reg) { - int ret; + int res = -ENOMEM; + struct urb *async_urb; + struct async_req *req; - if (test_bit(RX_REG_SET, &dev->flags)) - return -EAGAIN; - - dev->dr.bRequestType = RTL8150_REQT_WRITE; - dev->dr.bRequest = RTL8150_REQ_SET_REGS; - dev->dr.wValue = cpu_to_le16(indx); - dev->dr.wIndex = 0; - dev->dr.wLength = cpu_to_le16(size); - dev->ctrl_urb->transfer_buffer_length = 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 == -ENODEV) + req = kmalloc(sizeof(struct async_req), GFP_ATOMIC); + if (req == NULL) + return res; + async_urb = usb_alloc_urb(0, GFP_ATOMIC); + if (async_urb == NULL) { + kfree(req); + return res; + } + req->rx_creg = cpu_to_le16(reg); + req->dr.bRequestType = RTL8150_REQT_WRITE; + req->dr.bRequest = RTL8150_REQ_SET_REGS; + req->dr.wIndex = 0; + req->dr.wValue = cpu_to_le16(indx); + req->dr.wLength = cpu_to_le16(size); + usb_fill_control_urb(async_urb, dev->udev, + usb_sndctrlpipe(dev->udev, 0), (void *)&req->dr, + &req->rx_creg, size, async_set_reg_cb, req); + res = usb_submit_urb(async_urb, GFP_ATOMIC); + if (res) { + if (res == -ENODEV) netif_device_detach(dev->netdev); - err("control request submission failed: %d", ret); - } else - set_bit(RX_REG_SET, &dev->flags); - - return ret; + dev_err(&dev->udev->dev, "%s failed with %d\n", __func__, res); + } + return res; } static int read_mii_word(rtl8150_t * dev, u8 phy, __u8 indx, u16 * reg) @@ -270,7 +226,7 @@ static int read_mii_word(rtl8150_t * dev, u8 phy, __u8 indx, u16 * reg) get_registers(dev, PHYCNT, 1, data); } while ((data[0] & PHY_GO) && (i++ < MII_TIMEOUT)); - if (i < MII_TIMEOUT) { + if (i <= MII_TIMEOUT) { get_registers(dev, PHYDAT, 2, data); *reg = data[0] | (data[1] << 8); return 0; @@ -295,7 +251,7 @@ static int write_mii_word(rtl8150_t * dev, u8 phy, __u8 indx, u16 reg) get_registers(dev, PHYCNT, 1, data); } while ((data[0] & PHY_GO) && (i++ < MII_TIMEOUT)); - if (i < MII_TIMEOUT) + if (i <= MII_TIMEOUT) return 0; else return 1; @@ -313,20 +269,17 @@ static int rtl8150_set_mac_address(struct net_device *netdev, void *p) { struct sockaddr *addr = p; rtl8150_t *dev = netdev_priv(netdev); - int i; if (netif_running(netdev)) return -EBUSY; memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - dbg("%s: Setting MAC address to ", netdev->name); - for (i = 0; i < 5; i++) - dbg("%02X:", netdev->dev_addr[i]); - dbg("%02X\n", netdev->dev_addr[i]); + netdev_dbg(netdev, "Setting MAC address to %pM\n", netdev->dev_addr); /* Set the IDR registers. */ set_registers(dev, IDR, netdev->addr_len, netdev->dev_addr); #ifdef EEPROM_WRITE { + int i; u8 cr; /* Get the CR contents. */ get_registers(dev, CR, 1, &cr); @@ -336,7 +289,7 @@ static int rtl8150_set_mac_address(struct net_device *netdev, void *p) /* Write the MAC address into eeprom. Eeprom writes must be word-sized, so we need to split them up. */ for (i = 0; i * 2 < netdev->addr_len; i++) { - set_registers(dev, IDR_EEPROM + (i * 2), 2, + set_registers(dev, IDR_EEPROM + (i * 2), 2, netdev->dev_addr + (i * 2)); } /* Clear the WEPROM bit (preventing accidental eeprom writes). */ @@ -376,13 +329,6 @@ static int alloc_all_urbs(rtl8150_t * dev) usb_free_urb(dev->tx_urb); return 0; } - dev->ctrl_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!dev->ctrl_urb) { - usb_free_urb(dev->rx_urb); - usb_free_urb(dev->tx_urb); - usb_free_urb(dev->intr_urb); - return 0; - } return 1; } @@ -392,7 +338,6 @@ static void free_all_urbs(rtl8150_t * dev) usb_free_urb(dev->rx_urb); usb_free_urb(dev->tx_urb); usb_free_urb(dev->intr_urb); - usb_free_urb(dev->ctrl_urb); } static void unlink_all_urbs(rtl8150_t * dev) @@ -400,7 +345,6 @@ static void unlink_all_urbs(rtl8150_t * dev) 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) @@ -493,44 +437,6 @@ resched: tasklet_schedule(&dev->tl); } -static void rx_fixup(unsigned long data) -{ - rtl8150_t *dev; - struct sk_buff *skb; - int status; - - dev = (rtl8150_t *)data; - - spin_lock_irq(&dev->rx_pool_lock); - fill_skb_pool(dev); - spin_unlock_irq(&dev->rx_pool_lock); - if (test_bit(RX_URB_FAIL, &dev->flags)) - if (dev->rx_skb) - goto try_again; - spin_lock_irq(&dev->rx_pool_lock); - skb = pull_skb(dev); - spin_unlock_irq(&dev->rx_pool_lock); - if (skb == NULL) - goto tlsched; - dev->rx_skb = skb; - 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: - 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 { - clear_bit(RX_URB_FAIL, &dev->flags); - } - - return; -tlsched: - tasklet_schedule(&dev->tl); -} - static void write_bulk_callback(struct urb *urb) { rtl8150_t *dev; @@ -587,12 +493,12 @@ static void intr_callback(struct urb *urb) if ((d[INT_MSR] & MSR_LINK) == 0) { if (netif_carrier_ok(dev->netdev)) { netif_carrier_off(dev->netdev); - dbg("%s: LINK LOST\n", __func__); + netdev_dbg(dev->netdev, "%s: LINK LOST\n", __func__); } } else { if (!netif_carrier_ok(dev->netdev)) { netif_carrier_on(dev->netdev); - dbg("%s: LINK CAME BACK\n", __func__); + netdev_dbg(dev->netdev, "%s: LINK CAME BACK\n", __func__); } } @@ -601,9 +507,9 @@ resubmit: if (res == -ENODEV) netif_device_detach(dev->netdev); else if (res) - err ("can't resubmit intr, %s-%s/input0, status %d", - dev->udev->bus->bus_name, - dev->udev->devpath, res); + dev_err(&dev->udev->dev, + "can't resubmit intr, %s-%s/input0, status %d\n", + dev->udev->bus->bus_name, dev->udev->devpath, res); } static int rtl8150_suspend(struct usb_interface *intf, pm_message_t message) @@ -668,6 +574,42 @@ static void free_skb_pool(rtl8150_t *dev) dev_kfree_skb(dev->rx_skb_pool[i]); } +static void rx_fixup(unsigned long data) +{ + struct rtl8150 *dev = (struct rtl8150 *)data; + struct sk_buff *skb; + int status; + + spin_lock_irq(&dev->rx_pool_lock); + fill_skb_pool(dev); + spin_unlock_irq(&dev->rx_pool_lock); + if (test_bit(RX_URB_FAIL, &dev->flags)) + if (dev->rx_skb) + goto try_again; + spin_lock_irq(&dev->rx_pool_lock); + skb = pull_skb(dev); + spin_unlock_irq(&dev->rx_pool_lock); + if (skb == NULL) + goto tlsched; + dev->rx_skb = skb; + 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: + 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 { + clear_bit(RX_URB_FAIL, &dev->flags); + } + + return; +tlsched: + tasklet_schedule(&dev->tl); +} + static int enable_net_traffic(rtl8150_t * dev) { u8 cr, tcr, rcr, msr; @@ -677,7 +619,6 @@ static int enable_net_traffic(rtl8150_t * dev) } /* RCR bit7=1 attach Rx info at the end; =0 HW CRC (which is broken) */ rcr = 0x9e; - dev->rx_creg = cpu_to_le16(rcr); tcr = 0xd8; cr = 0x0c; if (!(rcr & 0x80)) @@ -710,20 +651,22 @@ static void rtl8150_tx_timeout(struct net_device *netdev) static void rtl8150_set_multicast(struct net_device *netdev) { rtl8150_t *dev = netdev_priv(netdev); + u16 rx_creg = 0x9e; + netif_stop_queue(netdev); if (netdev->flags & IFF_PROMISC) { - dev->rx_creg |= cpu_to_le16(0x0001); + rx_creg |= 0x0001; dev_info(&netdev->dev, "%s: promiscuous mode\n", netdev->name); - } else if (netdev->mc_count || + } else if (!netdev_mc_empty(netdev) || (netdev->flags & IFF_ALLMULTI)) { - dev->rx_creg &= cpu_to_le16(0xfffe); - dev->rx_creg |= cpu_to_le16(0x0002); + rx_creg &= 0xfffe; + rx_creg |= 0x0002; dev_info(&netdev->dev, "%s: allmulti set\n", netdev->name); } else { /* ~RX_MULTICAST, ~RX_PROMISCUOUS */ - dev->rx_creg &= cpu_to_le16(0x00fc); + rx_creg &= 0x00fc; } - async_set_registers(dev, RCR, 2); + async_set_registers(dev, RCR, sizeof(rx_creg), rx_creg); netif_wake_queue(netdev); } @@ -781,7 +724,7 @@ static int rtl8150_open(struct net_device *netdev) return -ENOMEM; set_registers(dev, IDR, 6, netdev->dev_addr); - + 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))) { @@ -824,9 +767,9 @@ static void rtl8150_get_drvinfo(struct net_device *netdev, struct ethtool_drvinf { 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); + strlcpy(info->driver, driver_name, sizeof(info->driver)); + strlcpy(info->version, DRIVER_VERSION, sizeof(info->version)); + usb_make_path(dev->udev, info->bus_info, sizeof(info->bus_info)); } static int rtl8150_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) @@ -846,10 +789,11 @@ static int rtl8150_get_settings(struct net_device *netdev, struct ethtool_cmd *e get_registers(dev, BMCR, 2, &bmcr); get_registers(dev, ANLP, 2, &lpa); if (bmcr & BMCR_ANENABLE) { + u32 speed = ((lpa & (LPA_100HALF | LPA_100FULL)) ? + SPEED_100 : SPEED_10); + ethtool_cmd_speed_set(ecmd, speed); ecmd->autoneg = AUTONEG_ENABLE; - ecmd->speed = (lpa & (LPA_100HALF | LPA_100FULL)) ? - SPEED_100 : SPEED_10; - if (ecmd->speed == SPEED_100) + if (speed == SPEED_100) ecmd->duplex = (lpa & LPA_100FULL) ? DUPLEX_FULL : DUPLEX_HALF; else @@ -857,8 +801,8 @@ static int rtl8150_get_settings(struct net_device *netdev, struct ethtool_cmd *e DUPLEX_FULL : DUPLEX_HALF; } else { ecmd->autoneg = AUTONEG_DISABLE; - ecmd->speed = (bmcr & BMCR_SPEED100) ? - SPEED_100 : SPEED_10; + ethtool_cmd_speed_set(ecmd, ((bmcr & BMCR_SPEED100) ? + SPEED_100 : SPEED_10)); ecmd->duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF; } @@ -900,8 +844,8 @@ static const struct net_device_ops rtl8150_netdev_ops = { .ndo_stop = rtl8150_close, .ndo_do_ioctl = rtl8150_ioctl, .ndo_start_xmit = rtl8150_start_xmit, - .ndo_tx_timeout = rtl8150_tx_timeout, - .ndo_set_multicast_list = rtl8150_set_multicast, + .ndo_tx_timeout = rtl8150_tx_timeout, + .ndo_set_rx_mode = rtl8150_set_multicast, .ndo_set_mac_address = rtl8150_set_mac_address, .ndo_change_mtu = eth_change_mtu, @@ -916,10 +860,8 @@ static int rtl8150_probe(struct usb_interface *intf, struct net_device *netdev; netdev = alloc_etherdev(sizeof(rtl8150_t)); - if (!netdev) { - err("Out of memory"); + if (!netdev) return -ENOMEM; - } dev = netdev_priv(netdev); @@ -931,29 +873,29 @@ static int rtl8150_probe(struct usb_interface *intf, tasklet_init(&dev->tl, rx_fixup, (unsigned long)dev); spin_lock_init(&dev->rx_pool_lock); - + dev->udev = udev; dev->netdev = netdev; netdev->netdev_ops = &rtl8150_netdev_ops; netdev->watchdog_timeo = RTL8150_TX_TIMEOUT; - SET_ETHTOOL_OPS(netdev, &ops); + netdev->ethtool_ops = &ops; dev->intr_interval = 100; /* 100ms */ if (!alloc_all_urbs(dev)) { - err("out of memory"); + dev_err(&intf->dev, "out of memory\n"); goto out; } if (!rtl8150_reset(dev)) { - err("couldn't reset the device"); + dev_err(&intf->dev, "couldn't reset the device\n"); goto out1; } fill_skb_pool(dev); set_ethernet_addr(dev); - + usb_set_intfdata(intf, dev); SET_NETDEV_DEV(netdev, &intf->dev); if (register_netdev(netdev) != 0) { - err("couldn't register the device"); + dev_err(&intf->dev, "couldn't register the device\n"); goto out2; } @@ -979,7 +921,6 @@ 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); @@ -992,20 +933,17 @@ static void rtl8150_disconnect(struct usb_interface *intf) } } -static int __init usb_rtl8150_init(void) -{ - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return usb_register(&rtl8150_driver); -} - -static void __exit usb_rtl8150_exit(void) -{ - usb_deregister(&rtl8150_driver); -} +static struct usb_driver rtl8150_driver = { + .name = driver_name, + .probe = rtl8150_probe, + .disconnect = rtl8150_disconnect, + .id_table = rtl8150_table, + .suspend = rtl8150_suspend, + .resume = rtl8150_resume, + .disable_hub_initiated_lpm = 1, +}; -module_init(usb_rtl8150_init); -module_exit(usb_rtl8150_exit); +module_usb_driver(rtl8150_driver); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); |
