diff options
author | Kevin Vigor <kevin@realmsys.com> | 2005-09-22 03:49:24 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-09-22 10:58:26 -0400 |
commit | a85a46f2c38def5150251816890393803fdae7d0 (patch) | |
tree | 98cfbc561911ee869d29a30b40847fae15bd65f1 /drivers/usb/net | |
parent | 4b2e790a4d73d729d936cc42f3b08af34f8ea5c6 (diff) |
[PATCH] USB: fix pegasus driver
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>
Diffstat (limited to 'drivers/usb/net')
-rw-r--r-- | drivers/usb/net/pegasus.c | 29 |
1 files changed, 20 insertions, 9 deletions
diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c index 7484d34780fc..6a4ffe6c3977 100644 --- a/drivers/usb/net/pegasus.c +++ b/drivers/usb/net/pegasus.c | |||
@@ -648,6 +648,13 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs) | |||
648 | } | 648 | } |
649 | 649 | ||
650 | /* | 650 | /* |
651 | * If the packet is unreasonably long, quietly drop it rather than | ||
652 | * kernel panicing by calling skb_put. | ||
653 | */ | ||
654 | if (pkt_len > PEGASUS_MTU) | ||
655 | goto goon; | ||
656 | |||
657 | /* | ||
651 | * at this point we are sure pegasus->rx_skb != NULL | 658 | * at this point we are sure pegasus->rx_skb != NULL |
652 | * so we go ahead and pass up the packet. | 659 | * so we go ahead and pass up the packet. |
653 | */ | 660 | */ |
@@ -886,15 +893,17 @@ static inline void get_interrupt_interval(pegasus_t * pegasus) | |||
886 | __u8 data[2]; | 893 | __u8 data[2]; |
887 | 894 | ||
888 | read_eprom_word(pegasus, 4, (__u16 *) data); | 895 | read_eprom_word(pegasus, 4, (__u16 *) data); |
889 | if (data[1] < 0x80) { | 896 | if (pegasus->usb->speed != USB_SPEED_HIGH) { |
890 | if (netif_msg_timer(pegasus)) | 897 | if (data[1] < 0x80) { |
891 | dev_info(&pegasus->intf->dev, | 898 | if (netif_msg_timer(pegasus)) |
892 | "intr interval changed from %ums to %ums\n", | 899 | dev_info(&pegasus->intf->dev, "intr interval " |
893 | data[1], 0x80); | 900 | "changed from %ums to %ums\n", |
894 | data[1] = 0x80; | 901 | data[1], 0x80); |
895 | #ifdef PEGASUS_WRITE_EEPROM | 902 | data[1] = 0x80; |
896 | write_eprom_word(pegasus, 4, *(__u16 *) data); | 903 | #ifdef PEGASUS_WRITE_EEPROM |
904 | write_eprom_word(pegasus, 4, *(__u16 *) data); | ||
897 | #endif | 905 | #endif |
906 | } | ||
898 | } | 907 | } |
899 | pegasus->intr_interval = data[1]; | 908 | pegasus->intr_interval = data[1]; |
900 | } | 909 | } |
@@ -904,8 +913,9 @@ static void set_carrier(struct net_device *net) | |||
904 | pegasus_t *pegasus = netdev_priv(net); | 913 | pegasus_t *pegasus = netdev_priv(net); |
905 | u16 tmp; | 914 | u16 tmp; |
906 | 915 | ||
907 | if (read_mii_word(pegasus, pegasus->phy, MII_BMSR, &tmp)) | 916 | if (!read_mii_word(pegasus, pegasus->phy, MII_BMSR, &tmp)) |
908 | return; | 917 | return; |
918 | |||
909 | if (tmp & BMSR_LSTATUS) | 919 | if (tmp & BMSR_LSTATUS) |
910 | netif_carrier_on(net); | 920 | netif_carrier_on(net); |
911 | else | 921 | else |
@@ -1355,6 +1365,7 @@ static void pegasus_disconnect(struct usb_interface *intf) | |||
1355 | cancel_delayed_work(&pegasus->carrier_check); | 1365 | cancel_delayed_work(&pegasus->carrier_check); |
1356 | unregister_netdev(pegasus->net); | 1366 | unregister_netdev(pegasus->net); |
1357 | usb_put_dev(interface_to_usbdev(intf)); | 1367 | usb_put_dev(interface_to_usbdev(intf)); |
1368 | unlink_all_urbs(pegasus); | ||
1358 | free_all_urbs(pegasus); | 1369 | free_all_urbs(pegasus); |
1359 | free_skb_pool(pegasus); | 1370 | free_skb_pool(pegasus); |
1360 | if (pegasus->rx_skb) | 1371 | if (pegasus->rx_skb) |