ChangeSet 1.1673.8.4, 2004/03/25 11:31:25-08:00, petkan@nucleusys.com [PATCH] USB: rtl8150 update adds two more vid/did and better packet error statistics. Link detection also has been added. drivers/usb/net/rtl8150.c | 115 +++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 108 insertions(+), 7 deletions(-) diff -Nru a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c --- a/drivers/usb/net/rtl8150.c Wed Apr 14 14:40:10 2004 +++ b/drivers/usb/net/rtl8150.c Wed Apr 14 14:40:10 2004 @@ -20,7 +20,7 @@ #include /* Version Information */ -#define DRIVER_VERSION "v0.5.7 (2002/12/31)" +#define DRIVER_VERSION "v0.6.1 (2004/03/13)" #define DRIVER_AUTHOR "Petko Manolov " #define DRIVER_DESC "rtl8150 based usb-ethernet driver" @@ -43,6 +43,8 @@ #define ANAR 0x0144 #define ANLP 0x0146 #define AER 0x0148 +#define CSCR 0x014C /* This one has the link status */ +#define CSCR_LINK_STATUS (1 << 3) #define IDR_EEPROM 0x1202 @@ -58,6 +60,60 @@ #define RTL8150_REQ_GET_REGS 0x05 #define RTL8150_REQ_SET_REGS 0x05 + +/* 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 + +/* 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) #define RX_SKB_POOL_SIZE 4 @@ -71,9 +127,13 @@ /* Define these values to match your device */ #define VENDOR_ID_REALTEK 0x0bda #define VENDOR_ID_MELCO 0x0411 +#define VENDOR_ID_MICRONET 0x3980 +#define VENDOR_ID_LONGSHINE 0x07b8 #define PRODUCT_ID_RTL8150 0x8150 #define PRODUCT_ID_LUAKTX 0x0012 +#define PRODUCT_ID_LCS8138TX 0x401a +#define PRODUCT_ID_SP128AR 0x0003 #undef EEPROM_WRITE @@ -81,6 +141,8 @@ static struct usb_device_id rtl8150_table[] = { {USB_DEVICE(VENDOR_ID_REALTEK, PRODUCT_ID_RTL8150)}, {USB_DEVICE(VENDOR_ID_MELCO, PRODUCT_ID_LUAKTX)}, + {USB_DEVICE(VENDOR_ID_MICRONET, PRODUCT_ID_SP128AR)}, + {USB_DEVICE(VENDOR_ID_LONGSHINE, PRODUCT_ID_LCS8138TX)}, {} }; @@ -368,6 +430,9 @@ if (!dev->rx_skb) goto resched; + /* protect against short packets (tell me why we got some?!?) */ + if (urb->actual_length < 4) + goto goon; res = urb->actual_length; rx_stat = le16_to_cpu(*(short *)(urb->transfer_buffer + res - 4)); @@ -454,6 +519,7 @@ void intr_callback(struct urb *urb, struct pt_regs *regs) { rtl8150_t *dev; + __u8 *d; int status; dev = urb->context; @@ -472,7 +538,28 @@ goto resubmit; } - /* FIXME if this doesn't do anything, don't submit the urb! */ + d = urb->transfer_buffer; + if (d[0] & TSR_ERRORS) { + dev->stats.tx_errors++; + if (d[INT_TSR] & (TSR_ECOL | TSR_JBR)) + dev->stats.tx_aborted_errors++; + if (d[INT_TSR] & TSR_LCOL) + dev->stats.tx_window_errors++; + if (d[INT_TSR] & TSR_LOSS_CRS) + dev->stats.tx_carrier_errors++; + } + /* Report link status changes to the network stack */ + if ((d[INT_MSR] & MSR_LINK) == 0) { + if (netif_carrier_ok(dev->netdev)) { + netif_carrier_off(dev->netdev); + dbg("%s: LINK LOST\n", __func__); + } + } else { + if (!netif_carrier_ok(dev->netdev)) { + netif_carrier_on(dev->netdev); + dbg("%s: LINK CAME BACK\n", __func__); + } + } resubmit: status = usb_submit_urb (urb, SLAB_ATOMIC); @@ -482,6 +569,7 @@ dev->udev->devpath, status); } + /* ** ** network related part of the code @@ -538,7 +626,7 @@ warn("%s - device reset failed", __FUNCTION__); } /* RCR bit7=1 attach Rx info at the end; =0 HW CRC (which is broken) */ - rcr = 0x9e; /* bit7=1 attach Rx info at the end */ + rcr = 0x9e; dev->rx_creg = cpu_to_le16(rcr); tcr = 0xd8; cr = 0x0c; @@ -626,6 +714,19 @@ return 0; } + +static void set_carrier(struct net_device *netdev) +{ + rtl8150_t *dev = netdev->priv; + short tmp; + + get_registers(dev, CSCR, 2, &tmp); + if (tmp & CSCR_LINK_STATUS) + netif_carrier_on(netdev); + else + netif_carrier_off(netdev); +} + static int rtl8150_open(struct net_device *netdev) { rtl8150_t *dev; @@ -653,6 +754,7 @@ warn("%s: intr_urb submit failed: %d", __FUNCTION__, res); netif_start_queue(netdev); enable_net_traffic(dev); + set_carrier(netdev); return res; } @@ -674,7 +776,7 @@ return res; } -static int rtl8150_ethtool_ioctl(struct net_device *netdev, void __user *uaddr) +static int rtl8150_ethtool_ioctl(struct net_device *netdev, void *uaddr) { rtl8150_t *dev; int cmd; @@ -759,7 +861,7 @@ switch (cmd) { case SIOCETHTOOL: - res = rtl8150_ethtool_ioctl(netdev, (void __user *)rq->ifr_data); + res = rtl8150_ethtool_ioctl(netdev, rq->ifr_data); break; case SIOCDEVPRIVATE: data[0] = dev->phy; @@ -774,6 +876,7 @@ default: res = -EOPNOTSUPP; } + return res; } @@ -796,7 +899,6 @@ kfree(dev); return -ENOMEM; } - netdev = alloc_etherdev(0); if (!netdev) { kfree(dev->intr_buff); @@ -837,7 +939,6 @@ info("%s: rtl8150 is detected", netdev->name); usb_set_intfdata(intf, dev); - SET_NETDEV_DEV(netdev, &intf->dev); if (register_netdev(netdev) != 0) { err("couldn't register the device");