Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+20 −9
Original line number Diff line number Diff line
@@ -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,16 +893,18 @@ static inline void get_interrupt_interval(pegasus_t * pegasus)
	__u8 data[2];

	read_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",
				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)