| From 4354ed54862b8af5a74b0aaffced0324f61fd6b0 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Sun, 26 Dec 2021 23:12:08 +0100 |
| Subject: net: usb: pegasus: Do not drop long Ethernet frames |
| |
| From: Matthias-Christian Ott <ott@mirix.org> |
| |
| [ Upstream commit ca506fca461b260ab32952b610c3d4aadc6c11fd ] |
| |
| The D-Link DSB-650TX (2001:4002) is unable to receive Ethernet frames |
| that are longer than 1518 octets, for example, Ethernet frames that |
| contain 802.1Q VLAN tags. |
| |
| The frames are sent to the pegasus driver via USB but the driver |
| discards them because they have the Long_pkt field set to 1 in the |
| received status report. The function read_bulk_callback of the pegasus |
| driver treats such received "packets" (in the terminology of the |
| hardware) as errors but the field simply does just indicate that the |
| Ethernet frame (MAC destination to FCS) is longer than 1518 octets. |
| |
| It seems that in the 1990s there was a distinction between |
| "giant" (> 1518) and "runt" (< 64) frames and the hardware includes |
| flags to indicate this distinction. It seems that the purpose of the |
| distinction "giant" frames was to not allow infinitely long frames due |
| to transmission errors and to allow hardware to have an upper limit of |
| the frame size. However, the hardware already has such limit with its |
| 2048 octet receive buffer and, therefore, Long_pkt is merely a |
| convention and should not be treated as a receive error. |
| |
| Actually, the hardware is even able to receive Ethernet frames with 2048 |
| octets which exceeds the claimed limit frame size limit of the driver of |
| 1536 octets (PEGASUS_MTU). |
| |
| Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") |
| Signed-off-by: Matthias-Christian Ott <ott@mirix.org> |
| Reviewed-by: Andrew Lunn <andrew@lunn.ch> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/net/usb/pegasus.c | 4 ++-- |
| 1 file changed, 2 insertions(+), 2 deletions(-) |
| |
| diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c |
| index 9f1777e56d7db..881468ff02bfa 100644 |
| --- a/drivers/net/usb/pegasus.c |
| +++ b/drivers/net/usb/pegasus.c |
| @@ -498,11 +498,11 @@ static void read_bulk_callback(struct urb *urb) |
| goto goon; |
| |
| rx_status = buf[count - 2]; |
| - if (rx_status & 0x1e) { |
| + if (rx_status & 0x1c) { |
| netif_dbg(pegasus, rx_err, net, |
| "RX packet error %x\n", rx_status); |
| net->stats.rx_errors++; |
| - if (rx_status & 0x06) /* long or runt */ |
| + if (rx_status & 0x04) /* runt */ |
| net->stats.rx_length_errors++; |
| if (rx_status & 0x08) |
| net->stats.rx_crc_errors++; |
| -- |
| 2.34.1 |
| |