Commit 47ff5805 authored by David S. Miller's avatar David S. Miller

Merge branch 'pegasus-sizes'

Petko Manolov says:

====================
pegasus: correct buffer & packet sizes

As noticed by Lincoln Ramsay <a1291762@gmail.com> some old (usb 1.1) Pegasus
based devices may actually return more bytes than the specified in the datasheet
amount.  That would not be a problem if the allocated space for the SKB was
equal to the parameter passed to usb_fill_bulk_urb().  Some poor bugger (i
really hope it was not me, but 'git blame' is useless in this case, so anyway)
decided to add '+ 8' to the buffer length parameter.  Sometimes the usb transfer
overflows and corrupts the socket structure, leading to kernel panic.

The above doesn't seem to happen for newer (Pegasus2 based) devices which did
help this bug to hide for so long.

The new default is to not include the CRC at the end of each received package.
So far CRC has been ignored which makes no sense to do it in a first place.

The patch is against v4.6-rc5 and was tested on ADM8515 device by transferring
multiple gigabytes of data over a couple of days without any complaints from the
kernel.  Please apply it to whatever net tree you deem fit.

Changes since v1:

 - split the patch in two parts;
 - corrected the subject lines;

Changes since v2:

 - do not append CRC by default (based on a discussion with Johannes Berg);
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 6c76f3d2 1a8deec0
...@@ -411,7 +411,7 @@ static int enable_net_traffic(struct net_device *dev, struct usb_device *usb) ...@@ -411,7 +411,7 @@ static int enable_net_traffic(struct net_device *dev, struct usb_device *usb)
int ret; int ret;
read_mii_word(pegasus, pegasus->phy, MII_LPA, &linkpart); read_mii_word(pegasus, pegasus->phy, MII_LPA, &linkpart);
data[0] = 0xc9; data[0] = 0xc8; /* TX & RX enable, append status, no CRC */
data[1] = 0; data[1] = 0;
if (linkpart & (ADVERTISE_100FULL | ADVERTISE_10FULL)) if (linkpart & (ADVERTISE_100FULL | ADVERTISE_10FULL))
data[1] |= 0x20; /* set full duplex */ data[1] |= 0x20; /* set full duplex */
...@@ -497,7 +497,7 @@ static void read_bulk_callback(struct urb *urb) ...@@ -497,7 +497,7 @@ static void read_bulk_callback(struct urb *urb)
pkt_len = buf[count - 3] << 8; pkt_len = buf[count - 3] << 8;
pkt_len += buf[count - 4]; pkt_len += buf[count - 4];
pkt_len &= 0xfff; pkt_len &= 0xfff;
pkt_len -= 8; pkt_len -= 4;
} }
/* /*
...@@ -528,7 +528,7 @@ static void read_bulk_callback(struct urb *urb) ...@@ -528,7 +528,7 @@ static void read_bulk_callback(struct urb *urb)
goon: goon:
usb_fill_bulk_urb(pegasus->rx_urb, pegasus->usb, usb_fill_bulk_urb(pegasus->rx_urb, pegasus->usb,
usb_rcvbulkpipe(pegasus->usb, 1), usb_rcvbulkpipe(pegasus->usb, 1),
pegasus->rx_skb->data, PEGASUS_MTU + 8, pegasus->rx_skb->data, PEGASUS_MTU,
read_bulk_callback, pegasus); read_bulk_callback, pegasus);
rx_status = usb_submit_urb(pegasus->rx_urb, GFP_ATOMIC); rx_status = usb_submit_urb(pegasus->rx_urb, GFP_ATOMIC);
if (rx_status == -ENODEV) if (rx_status == -ENODEV)
...@@ -569,7 +569,7 @@ static void rx_fixup(unsigned long data) ...@@ -569,7 +569,7 @@ static void rx_fixup(unsigned long data)
} }
usb_fill_bulk_urb(pegasus->rx_urb, pegasus->usb, usb_fill_bulk_urb(pegasus->rx_urb, pegasus->usb,
usb_rcvbulkpipe(pegasus->usb, 1), usb_rcvbulkpipe(pegasus->usb, 1),
pegasus->rx_skb->data, PEGASUS_MTU + 8, pegasus->rx_skb->data, PEGASUS_MTU,
read_bulk_callback, pegasus); read_bulk_callback, pegasus);
try_again: try_again:
status = usb_submit_urb(pegasus->rx_urb, GFP_ATOMIC); status = usb_submit_urb(pegasus->rx_urb, GFP_ATOMIC);
...@@ -823,7 +823,7 @@ static int pegasus_open(struct net_device *net) ...@@ -823,7 +823,7 @@ static int pegasus_open(struct net_device *net)
usb_fill_bulk_urb(pegasus->rx_urb, pegasus->usb, usb_fill_bulk_urb(pegasus->rx_urb, pegasus->usb,
usb_rcvbulkpipe(pegasus->usb, 1), usb_rcvbulkpipe(pegasus->usb, 1),
pegasus->rx_skb->data, PEGASUS_MTU + 8, pegasus->rx_skb->data, PEGASUS_MTU,
read_bulk_callback, pegasus); read_bulk_callback, pegasus);
if ((res = usb_submit_urb(pegasus->rx_urb, GFP_KERNEL))) { if ((res = usb_submit_urb(pegasus->rx_urb, GFP_KERNEL))) {
if (res == -ENODEV) if (res == -ENODEV)
......
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