ChangeSet 1.1250, 2003/06/18 16:55:03-07:00, petkan@users.sourceforge.net [PATCH] USB: pegasus patch better EPIPE handling, ethtool improvements, and another attempt to fix HOME_PNA support was made. HP added as a vendor and device ID. drivers/usb/pegasus.c | 75 ++++++++++++++++++++++++++++++++++++++------------ drivers/usb/pegasus.h | 3 ++ 2 files changed, 60 insertions(+), 18 deletions(-) diff -Nru a/drivers/usb/pegasus.c b/drivers/usb/pegasus.c --- a/drivers/usb/pegasus.c Wed Jun 18 17:35:06 2003 +++ b/drivers/usb/pegasus.c Wed Jun 18 17:35:06 2003 @@ -42,7 +42,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v0.4.30 (2003/04/01)" +#define DRIVER_VERSION "v0.4.32 (2003/06/06)" #define DRIVER_AUTHOR "Petko Manolov " #define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver" @@ -582,18 +582,34 @@ static void write_bulk_callback(struct urb *urb) { 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); } #ifdef PEGASUS_USE_INTR @@ -665,9 +681,16 @@ write_bulk_callback, pegasus); pegasus->tx_urb->transfer_buffer_length = count; if ((res = usb_submit_urb(pegasus->tx_urb))) { - 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; @@ -793,11 +816,16 @@ switch (ethcmd) { /* get driver-specific version/etc. info */ case ETHTOOL_GDRVINFO:{ - struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; + 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; @@ -860,20 +888,23 @@ { pegasus_t *pegasus; int cmd; - char tmp[128]; pegasus = net->priv; if (get_user(cmd, (int *) uaddr)) return -EFAULT; switch (cmd) { case ETHTOOL_GDRVINFO:{ - struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; + struct ethtool_drvinfo info; + + memset (&info, 0, sizeof info); + info.cmd = ETHTOOL_GDRVINFO; + strncpy(info.driver, driver_name, + sizeof (info.driver) - 1); strncpy(info.driver, DRIVER_DESC, ETHTOOL_BUSINFO_LEN); strncpy(info.version, DRIVER_VERSION, - ETHTOOL_BUSINFO_LEN); - sprintf(tmp, "usb%d:%d", pegasus->usb->bus->busnum, - pegasus->usb->devnum); - strncpy(info.bus_info, tmp, ETHTOOL_BUSINFO_LEN); + sizeof (info.version) - 1); + usb_make_path(pegasus->usb, info.bus_info, + sizeof (info.bus_info) -1); if (copy_to_user(uaddr, &info, sizeof(info))) return -EFAULT; return 0; @@ -881,6 +912,7 @@ case ETHTOOL_GSET:{ struct ethtool_cmd ecmd; short lpa, bmcr; + u8 port; if (copy_from_user(&ecmd, uaddr, sizeof(ecmd))) return -EFAULT; @@ -890,7 +922,11 @@ 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); @@ -1013,7 +1049,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); diff -Nru a/drivers/usb/pegasus.h b/drivers/usb/pegasus.h --- a/drivers/usb/pegasus.h Wed Jun 18 17:35:06 2003 +++ b/drivers/usb/pegasus.h Wed Jun 18 17:35:06 2003 @@ -127,6 +127,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 @@ -219,6 +220,8 @@ PEGASUS_DEV( "Elsa Micolink USB2Ethernet", VENDOR_ELSA, 0x3000, 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 )