ChangeSet 1.1243.50.7, 2003/06/06 15:08:08-07:00, [EMAIL PROTECTED]
[PATCH] USB: pegasus patch
better error handling and ethtool ioctl() cleanup. HOME_PNA
now should work (at least for the pegasus II based devices).
one more vendor and device IDs.
drivers/usb/net/pegasus.c | 106 +++++++++++++++++++++++++++++++++-------------
drivers/usb/net/pegasus.h | 5 +-
2 files changed, 82 insertions(+), 29 deletions(-)
diff -Nru a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c
--- a/drivers/usb/net/pegasus.c Tue Jun 10 17:11:47 2003
+++ b/drivers/usb/net/pegasus.c Tue Jun 10 17:11:47 2003
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999-2002 Petko Manolov ([EMAIL PROTECTED])
+ * Copyright (c) 1999-2003 Petko Manolov ([EMAIL PROTECTED])
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -45,7 +45,7 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v0.5.10 (2003/04/01)"
+#define DRIVER_VERSION "v0.5.12 (2003/06/06)"
#define DRIVER_AUTHOR "Petko Manolov <[EMAIL PROTECTED]>"
#define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver"
@@ -564,7 +564,14 @@
dbg("%s: reset MAC", net->name);
pegasus->flags &= ~PEGASUS_RX_BUSY;
break;
+ case -EPIPE: /* stall, or disconnect from TT */
+ /* FIXME schedule work to clear the halt */
+ warn("%s: no rx stall recovery", net->name);
+ return;
case -ENOENT:
+ case -ECONNRESET:
+ case -ESHUTDOWN:
+ dbg("%s: rx unlink, %d", net->name, urb->status);
return;
default:
dbg("%s: RX status %d", net->name, urb->status);
@@ -604,6 +611,9 @@
pegasus->stats.rx_packets++;
pegasus->stats.rx_bytes += pkt_len;
+ if (pegasus->flags & PEGASUS_UNPLUG)
+ return;
+
spin_lock(&pegasus->rx_pool_lock);
pegasus->rx_skb = pull_skb(pegasus);
spin_unlock(&pegasus->rx_pool_lock);
@@ -631,24 +641,24 @@
static void rx_fixup(unsigned long data)
{
pegasus_t *pegasus;
+ unsigned long flags;
pegasus = (pegasus_t *) data;
+ if (pegasus->flags & PEGASUS_UNPLUG)
+ return;
- spin_lock_irq(&pegasus->rx_pool_lock);
+ spin_lock_irqsave(&pegasus->rx_pool_lock, flags);
fill_skb_pool(pegasus);
- spin_unlock_irq(&pegasus->rx_pool_lock);
if (pegasus->flags & PEGASUS_RX_URB_FAIL)
if (pegasus->rx_skb)
goto try_again;
if (pegasus->rx_skb == NULL) {
- spin_lock_irq(&pegasus->rx_pool_lock);
pegasus->rx_skb = pull_skb(pegasus);
- spin_unlock_irq(&pegasus->rx_pool_lock);
}
if (pegasus->rx_skb == NULL) {
warn("wow, low on memory");
tasklet_schedule(&pegasus->rx_tl);
- return;
+ goto done;
}
usb_fill_bulk_urb(pegasus->rx_urb, pegasus->usb,
usb_rcvbulkpipe(pegasus->usb, 1),
@@ -661,23 +671,41 @@
} else {
pegasus->flags &= ~PEGASUS_RX_URB_FAIL;
}
+done:
+ spin_unlock_irqrestore(&pegasus->rx_pool_lock, flags);
}
static void write_bulk_callback(struct urb *urb, struct pt_regs *regs)
{
pegasus_t *pegasus = urb->context;
+ struct net_device *net = pegasus->net;
if (!pegasus || !(pegasus->flags & PEGASUS_RUNNING))
return;
- if (!netif_device_present(pegasus->net))
+ if (!netif_device_present(net))
return;
- if (urb->status)
- info("%s: TX status %d", pegasus->net->name, urb->status);
+ switch (urb->status) {
+ case -EPIPE:
+ /* FIXME schedule_work() to clear the tx halt */
+ netif_stop_queue(net);
+ warn("%s: no tx stall recovery", net->name);
+ return;
+ case -ENOENT:
+ case -ECONNRESET:
+ case -ESHUTDOWN:
+ dbg("%s: tx unlink, %d", net->name, urb->status);
+ return;
+ default:
+ info("%s: TX status %d", net->name, urb->status);
+ /* FALL THROUGH */
+ case 0:
+ break;
+ }
- pegasus->net->trans_start = jiffies;
- netif_wake_queue(pegasus->net);
+ net->trans_start = jiffies;
+ netif_wake_queue(net);
}
static void intr_callback(struct urb *urb, struct pt_regs *regs)
@@ -754,8 +782,16 @@
write_bulk_callback, pegasus);
if ((res = usb_submit_urb(pegasus->tx_urb, GFP_ATOMIC))) {
warn("failed tx_urb %d", res);
- pegasus->stats.tx_errors++;
- netif_start_queue(net);
+ switch (res) {
+ case -EPIPE: /* stall, or disconnect from TT */
+ /* cleanup should already have been scheduled */
+ break;
+ case -ENODEV: /* disconnect() upcoming */
+ break;
+ default:
+ pegasus->stats.tx_errors++;
+ netif_start_queue(net);
+ }
} else {
pegasus->stats.tx_packets++;
pegasus->stats.tx_bytes += skb->len;
@@ -908,6 +944,7 @@
netif_stop_queue(net);
if (!(pegasus->flags & PEGASUS_UNPLUG))
disable_net_traffic(pegasus);
+ tasklet_kill(&pegasus->rx_tl);
unlink_all_urbs(pegasus);
up(&pegasus->sem);
@@ -926,11 +963,15 @@
switch (ethcmd) {
/* get driver-specific version/etc. info */
case ETHTOOL_GDRVINFO:{
- struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
- strlcpy(info.driver, driver_name,
- sizeof (info.driver));
- strlcpy(info.version, DRIVER_VERSION,
- sizeof (info.version));
+ struct ethtool_drvinfo info;
+ memset (&info, 0, sizeof (info));
+ info.cmd = ETHTOOL_GDRVINFO;
+ strncpy(info.driver, driver_name,
+ sizeof (info.driver) - 1);
+ strncpy(info.version, DRIVER_VERSION,
+ sizeof (info.version) - 1);
+ usb_make_path(pegasus->usb, info.bus_info,
+ sizeof (info.bus_info));
if (copy_to_user(useraddr, &info, sizeof (info)))
return -EFAULT;
return 0;
@@ -999,12 +1040,15 @@
return -EFAULT;
switch (cmd) {
case ETHTOOL_GDRVINFO:{
- struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
- strncpy(info.driver, driver_name, sizeof info.driver);
+ struct ethtool_drvinfo info;
+ memset (&info, 0, sizeof (info));
+ info.cmd = ETHTOOL_GDRVINFO;
+ strncpy(info.driver, driver_name,
+ sizeof (info.driver) - 1);
strncpy(info.version, DRIVER_VERSION,
- ETHTOOL_BUSINFO_LEN);
+ sizeof (info.version) - 1);
usb_make_path(pegasus->usb, info.bus_info,
- sizeof info.bus_info);
+ sizeof (info.bus_info));
if (copy_to_user(uaddr, &info, sizeof (info)))
return -EFAULT;
return 0;
@@ -1012,15 +1056,20 @@
case ETHTOOL_GSET:{
struct ethtool_cmd ecmd;
short lpa, bmcr;
+ u8 port;
- memset(&ecmd, 0, sizeof ecmd);
+ memset(&ecmd, 0, sizeof (ecmd));
ecmd.supported = (SUPPORTED_10baseT_Half |
SUPPORTED_10baseT_Full |
SUPPORTED_100baseT_Half |
SUPPORTED_100baseT_Full |
SUPPORTED_Autoneg |
SUPPORTED_TP | SUPPORTED_MII);
- ecmd.port = PORT_TP;
+ get_registers(pegasus, Reg7b, 1, &port);
+ if (port == 0)
+ ecmd.port = PORT_MII;
+ else
+ ecmd.port = PORT_TP;
ecmd.transceiver = XCVR_INTERNAL;
ecmd.phy_address = pegasus->phy;
read_mii_word(pegasus, pegasus->phy, MII_BMCR, &bmcr);
@@ -1142,7 +1191,10 @@
set_register(pegasus, Reg1d, 0);
set_register(pegasus, Reg7b, 1);
mdelay(100);
- set_register(pegasus, Reg7b, 2);
+ if ((pegasus->features & HAS_HOME_PNA) && mii_mode)
+ set_register(pegasus, Reg7b, 0);
+ else
+ set_register(pegasus, Reg7b, 2);
set_register(pegasus, 0x83, data);
get_registers(pegasus, 0x83, 1, &data);
@@ -1262,7 +1314,6 @@
pegasus->flags |= PEGASUS_UNPLUG;
unregister_netdev(pegasus->net);
usb_put_dev(interface_to_usbdev(intf));
- unlink_all_urbs(pegasus);
free_all_urbs(pegasus);
free_skb_pool(pegasus);
if (pegasus->rx_skb)
@@ -1273,7 +1324,6 @@
}
static struct usb_driver pegasus_driver = {
- .owner = THIS_MODULE,
.name = driver_name,
.probe = pegasus_probe,
.disconnect = pegasus_disconnect,
diff -Nru a/drivers/usb/net/pegasus.h b/drivers/usb/net/pegasus.h
--- a/drivers/usb/net/pegasus.h Tue Jun 10 17:11:47 2003
+++ b/drivers/usb/net/pegasus.h Tue Jun 10 17:11:47 2003
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999-2002 Petko Manolov - Petkan ([EMAIL PROTECTED])
+ * Copyright (c) 1999-2003 Petko Manolov - Petkan ([EMAIL PROTECTED])
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as published
@@ -130,6 +130,7 @@
#define VENDOR_ELCON 0x0db7
#define VENDOR_ELSA 0x05cc
#define VENDOR_HAWKING 0x0e66
+#define VENDOR_HP 0x03f0
#define VENDOR_IODATA 0x04bb
#define VENDOR_KINGSTON 0x0951
#define VENDOR_LANEED 0x056e
@@ -224,6 +225,8 @@
DEFAULT_GPIO_RESET )
PEGASUS_DEV( "Hawking UF100 10/100 Ethernet", VENDOR_HAWKING, 0x400c,
DEFAULT_GPIO_RESET | PEGASUS_II )
+PEGASUS_DEV( "HP hn210c Ethernet USB", VENDOR_HP, 0x811c,
+ DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "IO DATA USB ET/TX", VENDOR_IODATA, 0x0904,
DEFAULT_GPIO_RESET )
PEGASUS_DEV( "IO DATA USB ET/TX-S", VENDOR_IODATA, 0x0913,
-------------------------------------------------------
This SF.net email is sponsored by: Etnus, makers of TotalView, The best
thread debugger on the planet. Designed with thread debugging features
you've never dreamed of, try TotalView 6 free at www.etnus.com.
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel