#include <asm/uaccess.h>
/* 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 <petkan@users.sourceforge.net>"
#define DRIVER_DESC "rtl8150 based usb-ethernet driver"
spinlock_t rx_pool_lock;
struct usb_ctrlrequest dr;
int intr_interval;
- u16 rx_creg;
+ __le16 rx_creg;
u8 *intr_buff;
u8 phy;
};
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 const char driver_name [] = "rtl8150";
static struct usb_driver rtl8150_driver = {
- .owner = THIS_MODULE,
.name = driver_name,
.probe = rtl8150_probe,
.disconnect = rtl8150_disconnect,
{
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)
if (i < MII_TIMEOUT) {
get_registers(dev, PHYDAT, 2, data);
- *reg = le16_to_cpup(data);
+ *reg = data[0] | (data[1] << 8);
return 0;
} else
return 1;
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++)
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)
goto goon;
res = urb->actual_length;
- rx_stat = le16_to_cpu(*(short *)(urb->transfer_buffer + res - 4));
+ rx_stat = le16_to_cpu(*(__le16 *)(urb->transfer_buffer + res - 4));
pkt_len = res - 4;
skb_put(dev->rx_skb, pkt_len);
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);
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;
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);
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)
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);
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);
- dev = netdev->priv;
- if (get_user(cmd, (int __user *) uaddr))
- return -EFAULT;
+ 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);
+}
- 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) ?
+static int rtl8150_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
+{
+ rtl8150_t *dev = netdev_priv(netdev);
+ short lpa, bmcr;
+
+ 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:
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;
}
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;
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)) {
}
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);
err("couldn't register the device");
goto out2;
}
+
+ info("%s: rtl8150 is detected", netdev->name);
+
return 0;
out2:
out:
kfree(dev->intr_buff);
free_netdev(netdev);
- kfree(dev);
return -EIO;
}
usb_set_intfdata(intf, NULL);
if (dev) {
set_bit(RTL8150_UNPLUG, &dev->flags);
+ tasklet_disable(&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);
}
}