aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/usb/rtl8150.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/usb/rtl8150.c')
-rw-r--r--drivers/net/usb/rtl8150.c293
1 files changed, 117 insertions, 176 deletions
diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c
index e85c89c6706..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;
-
- if (test_bit(RX_REG_SET, &dev->flags))
- return -EAGAIN;
+ int res = -ENOMEM;
+ struct urb *async_urb;
+ struct async_req *req;
- 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)
@@ -318,7 +274,7 @@ static int rtl8150_set_mac_address(struct net_device *netdev, void *p)
return -EBUSY;
memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
- dbg("%s: Setting MAC address to %pM\n", netdev->name, netdev->dev_addr);
+ 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
@@ -333,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). */
@@ -373,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;
}
@@ -389,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)
@@ -397,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)
@@ -490,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;
@@ -584,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__);
}
}
@@ -598,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)
@@ -665,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;
@@ -674,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))
@@ -707,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_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);
}
@@ -778,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))) {
@@ -821,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)
@@ -843,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
@@ -854,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;
}
@@ -897,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,
@@ -913,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);
@@ -928,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;
}
@@ -976,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);
@@ -989,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);