summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorKevin Vigor <kevin@realmsys.com>2005-09-22 11:49:24 +0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-09-22 18:58:26 +0400
commita85a46f2c38def5150251816890393803fdae7d0 (patch)
tree98cfbc561911ee869d29a30b40847fae15bd65f1 /drivers
parent4b2e790a4d73d729d936cc42f3b08af34f8ea5c6 (diff)
downloadlinux-a85a46f2c38def5150251816890393803fdae7d0.tar.xz
[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')
-rw-r--r--drivers/usb/net/pegasus.c29
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)
}
/*
+ * 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)