477754dc4470540adce1d34ddcada9d98c276e14
[oweals/openwrt.git] /
1 From 3ba615169e1f9866f70c2967a664f0fac36c5699 Mon Sep 17 00:00:00 2001
2 From: P33M <p33m@github.com>
3 Date: Wed, 1 May 2019 17:04:32 +0100
4 Subject: [PATCH 479/773] smsc95xx: dynamically fix up TX buffer alignment with
5  padding bytes
6
7 dwc_otg requires a 32-bit aligned buffer start address, otherwise
8 expensive bounce buffers are used. The LAN951x hardware can skip up to
9 3 bytes between the TX header and the start of frame data, which can
10 be used to force alignment of the URB passed to dwc_otg.
11
12 As found in https://github.com/raspberrypi/linux/issues/2924
13 ---
14  drivers/net/usb/smsc95xx.c | 12 +++++++-----
15  drivers/net/usb/smsc95xx.h |  2 +-
16  2 files changed, 8 insertions(+), 6 deletions(-)
17
18 --- a/drivers/net/usb/smsc95xx.c
19 +++ b/drivers/net/usb/smsc95xx.c
20 @@ -2082,7 +2082,9 @@ static struct sk_buff *smsc95xx_tx_fixup
21                                          struct sk_buff *skb, gfp_t flags)
22  {
23         bool csum = skb->ip_summed == CHECKSUM_PARTIAL;
24 -       int overhead = csum ? SMSC95XX_TX_OVERHEAD_CSUM : SMSC95XX_TX_OVERHEAD;
25 +       unsigned int align_bytes = -((uintptr_t)skb->data) & 0x3;
26 +       int overhead = csum ? SMSC95XX_TX_OVERHEAD_CSUM + align_bytes
27 +                               : SMSC95XX_TX_OVERHEAD + align_bytes;
28         u32 tx_cmd_a, tx_cmd_b;
29  
30         /* We do not advertise SG, so skbs should be already linearized */
31 @@ -2116,16 +2118,16 @@ static struct sk_buff *smsc95xx_tx_fixup
32                 }
33         }
34  
35 -       skb_push(skb, 4);
36 -       tx_cmd_b = (u32)(skb->len - 4);
37 +       skb_push(skb, 4 + align_bytes);
38 +       tx_cmd_b = (u32)(skb->len - 4 - align_bytes);
39         if (csum)
40                 tx_cmd_b |= TX_CMD_B_CSUM_ENABLE;
41         cpu_to_le32s(&tx_cmd_b);
42         memcpy(skb->data, &tx_cmd_b, 4);
43  
44         skb_push(skb, 4);
45 -       tx_cmd_a = (u32)(skb->len - 8) | TX_CMD_A_FIRST_SEG_ |
46 -               TX_CMD_A_LAST_SEG_;
47 +       tx_cmd_a = (u32)(skb->len - 8 - align_bytes) | TX_CMD_A_FIRST_SEG_ |
48 +               (align_bytes << 16) | TX_CMD_A_LAST_SEG_;
49         cpu_to_le32s(&tx_cmd_a);
50         memcpy(skb->data, &tx_cmd_a, 4);
51  
52 --- a/drivers/net/usb/smsc95xx.h
53 +++ b/drivers/net/usb/smsc95xx.h
54 @@ -21,7 +21,7 @@
55  #define _SMSC95XX_H
56  
57  /* Tx command words */
58 -#define TX_CMD_A_DATA_OFFSET_  (0x001F0000)    /* Data Start Offset */
59 +#define TX_CMD_A_DATA_OFFSET_  (0x00030000)    /* Data Start Offset */
60  #define TX_CMD_A_FIRST_SEG_    (0x00002000)    /* First Segment */
61  #define TX_CMD_A_LAST_SEG_     (0x00001000)    /* Last Segment */
62  #define TX_CMD_A_BUF_SIZE_     (0x000007FF)    /* Buffer Size */