[PATCH] USB: fix pegasus driver
authorKevin Vigor <kevin@realmsys.com>
Thu, 22 Sep 2005 07:49:24 +0000 (00:49 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Thu, 22 Sep 2005 14:58:26 +0000 (07:58 -0700)
Addresses some small bugs in the pegasus ethernet-over-USB driver.
Specifically, malformed long packets from the adapter could cause a kernel
panic; the interrupt interval calculation was inappropriate for high-speed
devices; the return code from read_mii_word was tested incorrectly; and
failure to unlink outstanding URBs before freeing them could lead to kernel
panics when unloading the driver.

Signed-off-by: Kevin Vigor <kevin@realmsys.com>
Cc: Petko Manolov <petkan@users.sourceforge.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
drivers/usb/net/pegasus.c

index 7484d34780fcb7e0dced0bdcb24556b776d6e2fa..6a4ffe6c39771c13f883c78401cca24e529ef87a 100644 (file)
@@ -647,6 +647,13 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs)
                pkt_len -= 8;
        }
 
+       /*
+        * If the packet is unreasonably long, quietly drop it rather than
+        * kernel panicing by calling skb_put.
+        */
+       if (pkt_len > PEGASUS_MTU)
+               goto goon;
+
        /*
         * at this point we are sure pegasus->rx_skb != NULL
         * so we go ahead and pass up the packet.
@@ -886,15 +893,17 @@ static inline void get_interrupt_interval(pegasus_t * pegasus)
        __u8 data[2];
 
        read_eprom_word(pegasus, 4, (__u16 *) data);
-       if (data[1] < 0x80) {
-               if (netif_msg_timer(pegasus))
-                       dev_info(&pegasus->intf->dev,
-                               "intr interval changed from %ums to %ums\n",
-                               data[1], 0x80);
-               data[1] = 0x80;
-#ifdef PEGASUS_WRITE_EEPROM
-               write_eprom_word(pegasus, 4, *(__u16 *) data);
+       if (pegasus->usb->speed != USB_SPEED_HIGH) {
+               if (data[1] < 0x80) {
+                       if (netif_msg_timer(pegasus))
+                               dev_info(&pegasus->intf->dev, "intr interval "
+                                       "changed from %ums to %ums\n",
+                                       data[1], 0x80);
+                       data[1] = 0x80;
+#ifdef PEGASUS_WRITE_EEPROM
+                       write_eprom_word(pegasus, 4, *(__u16 *) data);
 #endif
+               }
        }
        pegasus->intr_interval = data[1];
 }
@@ -904,8 +913,9 @@ static void set_carrier(struct net_device *net)
        pegasus_t *pegasus = netdev_priv(net);
        u16 tmp;
 
-       if (read_mii_word(pegasus, pegasus->phy, MII_BMSR, &tmp))
+       if (!read_mii_word(pegasus, pegasus->phy, MII_BMSR, &tmp))
                return;
+
        if (tmp & BMSR_LSTATUS)
                netif_carrier_on(net);
        else
@@ -1355,6 +1365,7 @@ static void pegasus_disconnect(struct usb_interface *intf)
        cancel_delayed_work(&pegasus->carrier_check);
        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)