Commit a85a46f2 authored by Kevin Vigor's avatar Kevin Vigor Committed by Linus Torvalds

[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: default avatarKevin Vigor <kevin@realmsys.com>
Cc: Petko Manolov <petkan@users.sourceforge.net>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 4b2e790a
...@@ -647,6 +647,13 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs) ...@@ -647,6 +647,13 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs)
pkt_len -= 8; 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 * at this point we are sure pegasus->rx_skb != NULL
* so we go ahead and pass up the packet. * so we go ahead and pass up the packet.
...@@ -886,16 +893,18 @@ static inline void get_interrupt_interval(pegasus_t * pegasus) ...@@ -886,16 +893,18 @@ static inline void get_interrupt_interval(pegasus_t * pegasus)
__u8 data[2]; __u8 data[2];
read_eprom_word(pegasus, 4, (__u16 *) data); read_eprom_word(pegasus, 4, (__u16 *) data);
if (pegasus->usb->speed != USB_SPEED_HIGH) {
if (data[1] < 0x80) { if (data[1] < 0x80) {
if (netif_msg_timer(pegasus)) if (netif_msg_timer(pegasus))
dev_info(&pegasus->intf->dev, dev_info(&pegasus->intf->dev, "intr interval "
"intr interval changed from %ums to %ums\n", "changed from %ums to %ums\n",
data[1], 0x80); data[1], 0x80);
data[1] = 0x80; data[1] = 0x80;
#ifdef PEGASUS_WRITE_EEPROM #ifdef PEGASUS_WRITE_EEPROM
write_eprom_word(pegasus, 4, *(__u16 *) data); write_eprom_word(pegasus, 4, *(__u16 *) data);
#endif #endif
} }
}
pegasus->intr_interval = data[1]; pegasus->intr_interval = data[1];
} }
...@@ -904,8 +913,9 @@ static void set_carrier(struct net_device *net) ...@@ -904,8 +913,9 @@ static void set_carrier(struct net_device *net)
pegasus_t *pegasus = netdev_priv(net); pegasus_t *pegasus = netdev_priv(net);
u16 tmp; u16 tmp;
if (read_mii_word(pegasus, pegasus->phy, MII_BMSR, &tmp)) if (!read_mii_word(pegasus, pegasus->phy, MII_BMSR, &tmp))
return; return;
if (tmp & BMSR_LSTATUS) if (tmp & BMSR_LSTATUS)
netif_carrier_on(net); netif_carrier_on(net);
else else
...@@ -1355,6 +1365,7 @@ static void pegasus_disconnect(struct usb_interface *intf) ...@@ -1355,6 +1365,7 @@ static void pegasus_disconnect(struct usb_interface *intf)
cancel_delayed_work(&pegasus->carrier_check); cancel_delayed_work(&pegasus->carrier_check);
unregister_netdev(pegasus->net); unregister_netdev(pegasus->net);
usb_put_dev(interface_to_usbdev(intf)); usb_put_dev(interface_to_usbdev(intf));
unlink_all_urbs(pegasus);
free_all_urbs(pegasus); free_all_urbs(pegasus);
free_skb_pool(pegasus); free_skb_pool(pegasus);
if (pegasus->rx_skb) if (pegasus->rx_skb)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment