]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/usb/net/pegasus.c
USB: Pegasus driver failing for ADMtek 8515 network device
[linux-2.6-omap-h63xx.git] / drivers / usb / net / pegasus.c
index 7683926a1b6f19c5fae68caa07a6727691acfc17..918cf5a77c08208f99e89aeede993397413d2129 100644 (file)
@@ -45,7 +45,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v0.6.13 (2005/11/13)"
+#define DRIVER_VERSION "v0.6.14 (2006/09/27)"
 #define DRIVER_AUTHOR "Petko Manolov <petkan@users.sourceforge.net>"
 #define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver"
 
@@ -163,6 +163,8 @@ static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
 
        /* using ATOMIC, we'd never wake up if we slept */
        if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) {
+               if (ret == -ENODEV)
+                       netif_device_detach(pegasus->net);
                if (netif_msg_drv(pegasus))
                        dev_err(&pegasus->intf->dev, "%s, status %d\n",
                                        __FUNCTION__, ret);
@@ -217,6 +219,8 @@ static int set_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
        set_current_state(TASK_UNINTERRUPTIBLE);
 
        if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) {
+               if (ret == -ENODEV)
+                       netif_device_detach(pegasus->net);
                if (netif_msg_drv(pegasus))
                        dev_err(&pegasus->intf->dev, "%s, status %d\n",
                                        __FUNCTION__, ret);
@@ -268,6 +272,8 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data)
        set_current_state(TASK_UNINTERRUPTIBLE);
 
        if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) {
+               if (ret == -ENODEV)
+                       netif_device_detach(pegasus->net);
                if (netif_msg_drv(pegasus))
                        dev_err(&pegasus->intf->dev, "%s, status %d\n",
                                        __FUNCTION__, ret);
@@ -298,10 +304,13 @@ static int update_eth_regs_async(pegasus_t * pegasus)
                             (char *) &pegasus->dr,
                             pegasus->eth_regs, 3, ctrl_callback, pegasus);
 
-       if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC)))
+       if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) {
+               if (ret == -ENODEV)
+                       netif_device_detach(pegasus->net);
                if (netif_msg_drv(pegasus))
                        dev_err(&pegasus->intf->dev, "%s, status %d\n",
                                        __FUNCTION__, ret);
+       }
 
        return ret;
 }
@@ -330,7 +339,7 @@ static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd)
        }
 fail:
        if (netif_msg_drv(pegasus))
-               dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
+               dev_warn(&pegasus->intf->dev, "%s failed\n", __FUNCTION__);
 
        return ret;
 }
@@ -367,7 +376,7 @@ static int write_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 regd)
 
 fail:
        if (netif_msg_drv(pegasus))
-               dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
+               dev_warn(&pegasus->intf->dev, "%s failed\n", __FUNCTION__);
        return -ETIMEDOUT;
 }
 
@@ -404,7 +413,7 @@ static int read_eprom_word(pegasus_t * pegasus, __u8 index, __u16 * retdata)
 
 fail:
        if (netif_msg_drv(pegasus))
-               dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
+               dev_warn(&pegasus->intf->dev, "%s failed\n", __FUNCTION__);
        return -ETIMEDOUT;
 }
 
@@ -452,7 +461,7 @@ static int write_eprom_word(pegasus_t * pegasus, __u8 index, __u16 data)
                return ret;
 fail:
        if (netif_msg_drv(pegasus))
-               dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
+               dev_warn(&pegasus->intf->dev, "%s failed\n", __FUNCTION__);
        return -ETIMEDOUT;
 }
 #endif                         /* PEGASUS_WRITE_EEPROM */
@@ -472,8 +481,12 @@ static void set_ethernet_addr(pegasus_t * pegasus)
 {
        __u8 node_id[6];
 
-       get_node_id(pegasus, node_id);
-       set_registers(pegasus, EthID, sizeof (node_id), node_id);
+       if (pegasus->features & PEGASUS_II) {
+               get_registers(pegasus, 0x10, sizeof(node_id), node_id);
+       } else {
+               get_node_id(pegasus, node_id);
+               set_registers(pegasus, EthID, sizeof (node_id), node_id);
+       }
        memcpy(pegasus->net->dev_addr, node_id, sizeof (node_id));
 }
 
@@ -610,7 +623,7 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs)
        switch (urb->status) {
        case 0:
                break;
-       case -ETIMEDOUT:
+       case -ETIME:
                if (netif_msg_rx_err(pegasus))
                        pr_debug("%s: reset MAC\n", net->name);
                pegasus->flags &= ~PEGASUS_RX_BUSY;
@@ -692,7 +705,10 @@ goon:
                          usb_rcvbulkpipe(pegasus->usb, 1),
                          pegasus->rx_skb->data, PEGASUS_MTU + 8,
                          read_bulk_callback, pegasus);
-       if (usb_submit_urb(pegasus->rx_urb, GFP_ATOMIC)) {
+       rx_status = usb_submit_urb(pegasus->rx_urb, GFP_ATOMIC);
+       if (rx_status == -ENODEV)
+               netif_device_detach(pegasus->net);
+       else if (rx_status) {
                pegasus->flags |= PEGASUS_RX_URB_FAIL;
                goto tl_sched;
        } else {
@@ -709,6 +725,7 @@ static void rx_fixup(unsigned long data)
 {
        pegasus_t *pegasus;
        unsigned long flags;
+       int status;
 
        pegasus = (pegasus_t *) data;
        if (pegasus->flags & PEGASUS_UNPLUG)
@@ -734,7 +751,10 @@ static void rx_fixup(unsigned long data)
                          pegasus->rx_skb->data, PEGASUS_MTU + 8,
                          read_bulk_callback, pegasus);
 try_again:
-       if (usb_submit_urb(pegasus->rx_urb, GFP_ATOMIC)) {
+       status = usb_submit_urb(pegasus->rx_urb, GFP_ATOMIC);
+       if (status == -ENODEV)
+               netif_device_detach(pegasus->net);
+       else if (status) {
                pegasus->flags |= PEGASUS_RX_URB_FAIL;
                tasklet_schedule(&pegasus->rx_tl);
        } else {
@@ -836,6 +856,8 @@ static void intr_callback(struct urb *urb, struct pt_regs *regs)
        }
 
        status = usb_submit_urb(urb, SLAB_ATOMIC);
+       if (status == -ENODEV)
+               netif_device_detach(pegasus->net);
        if (status && netif_msg_timer(pegasus))
                printk(KERN_ERR "%s: can't resubmit interrupt urb, %d\n",
                                net->name, status);
@@ -874,6 +896,7 @@ static int pegasus_start_xmit(struct sk_buff *skb, struct net_device *net)
                        /* cleanup should already have been scheduled */
                        break;
                case -ENODEV:           /* disconnect() upcoming */
+                       netif_device_detach(pegasus->net);
                        break;
                default:
                        pegasus->stats.tx_errors++;
@@ -999,6 +1022,8 @@ static int pegasus_open(struct net_device *net)
                          pegasus->rx_skb->data, PEGASUS_MTU + 8,
                          read_bulk_callback, pegasus);
        if ((res = usb_submit_urb(pegasus->rx_urb, GFP_KERNEL))) {
+               if (res == -ENODEV)
+                       netif_device_detach(pegasus->net);
                if (netif_msg_ifup(pegasus))
                        pr_debug("%s: failed rx_urb, %d", net->name, res);
                goto exit;
@@ -1009,6 +1034,8 @@ static int pegasus_open(struct net_device *net)
                         pegasus->intr_buff, sizeof (pegasus->intr_buff),
                         intr_callback, pegasus, pegasus->intr_interval);
        if ((res = usb_submit_urb(pegasus->intr_urb, GFP_KERNEL))) {
+               if (res == -ENODEV)
+                       netif_device_detach(pegasus->net);
                if (netif_msg_ifup(pegasus))
                        pr_debug("%s: failed intr_urb, %d\n", net->name, res);
                usb_kill_urb(pegasus->rx_urb);