Skip to content

Commit c406700

Browse files
jarodwilsondavem330
authored andcommitted
ethernet/atheros/alx: sanitize buffer sizing and padding
This is based on the work done by Przemek Rudy in bug 70761 at bugzilla.kernel.org, but with some work done to disentagle and clarify things a bit. Similar to Przemek's work and other drivers, we're adding a padding of 16 here, but we're also disentangling mtu size calculations from max buffer size calculations a bit, and adding ETH_HLEN to the value written into ALX_MTU. Hopefully, with a bit more consistency and clarity, things behave better here. Sadly, I can only test in my alx-driven E2200, which worked just fine before this patch. In comment #58 of bug 70761, Eugene A. Shatokhin reports that this patch does help considerably for a ROSA Linux user of his with an AR8162 network adapter when patched into a 4.1.x-based kernel, with several days of normal operation where wired network previously wasn't usable without setting MTU to 9000 as a work-around. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=70761 CC: "Eugene A. Shatokhin" <[email protected]> CC: Przemek Rudy <[email protected]> CC: Jay Cliburn <[email protected]> CC: Chris Snook <[email protected]> CC: [email protected] Signed-off-by: Jarod Wilson <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent f637941 commit c406700

File tree

3 files changed

+14
-12
lines changed

3 files changed

+14
-12
lines changed

drivers/net/ethernet/atheros/alx/hw.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -958,13 +958,13 @@ void alx_configure_basic(struct alx_hw *hw)
958958
alx_write_mem32(hw, ALX_TINT_TPD_THRSHLD, hw->ith_tpd);
959959
alx_write_mem32(hw, ALX_TINT_TIMER, hw->imt);
960960

961-
raw_mtu = hw->mtu + ETH_HLEN;
962-
alx_write_mem32(hw, ALX_MTU, raw_mtu + 8);
963-
if (raw_mtu > ALX_MTU_JUMBO_TH)
961+
raw_mtu = ALX_RAW_MTU(hw->mtu);
962+
alx_write_mem32(hw, ALX_MTU, raw_mtu);
963+
if (raw_mtu > (ALX_MTU_JUMBO_TH + ETH_FCS_LEN + VLAN_HLEN))
964964
hw->rx_ctrl &= ~ALX_MAC_CTRL_FAST_PAUSE;
965965

966-
if ((raw_mtu + 8) < ALX_TXQ1_JUMBO_TSO_TH)
967-
val = (raw_mtu + 8 + 7) >> 3;
966+
if (raw_mtu < ALX_TXQ1_JUMBO_TSO_TH)
967+
val = (raw_mtu + 7) >> 3;
968968
else
969969
val = ALX_TXQ1_JUMBO_TSO_TH >> 3;
970970
alx_write_mem32(hw, ALX_TXQ1, val | ALX_TXQ1_ERRLGPKT_DROP_EN);

drivers/net/ethernet/atheros/alx/hw.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include <linux/types.h>
3838
#include <linux/mdio.h>
3939
#include <linux/pci.h>
40+
#include <linux/if_vlan.h>
4041
#include "reg.h"
4142

4243
/* Transmit Packet Descriptor, contains 4 32-bit words.
@@ -343,12 +344,14 @@ struct alx_rrd {
343344
ALX_RSS_HASH_TYPE_IPV4_TCP | \
344345
ALX_RSS_HASH_TYPE_IPV6 | \
345346
ALX_RSS_HASH_TYPE_IPV6_TCP)
346-
#define ALX_DEF_RXBUF_SIZE 1536
347+
#define ALX_FRAME_PAD 16
348+
#define ALX_RAW_MTU(_mtu) (_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN)
349+
#define ALX_MAX_FRAME_LEN(_mtu) (ALIGN((ALX_RAW_MTU(_mtu) + ALX_FRAME_PAD), 8))
350+
#define ALX_DEF_RXBUF_SIZE ALX_MAX_FRAME_LEN(1500)
347351
#define ALX_MAX_JUMBO_PKT_SIZE (9*1024)
348352
#define ALX_MAX_TSO_PKT_SIZE (7*1024)
349353
#define ALX_MAX_FRAME_SIZE ALX_MAX_JUMBO_PKT_SIZE
350-
#define ALX_MIN_FRAME_SIZE 68
351-
#define ALX_RAW_MTU(_mtu) (_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN)
354+
#define ALX_MIN_FRAME_SIZE (ETH_ZLEN + ETH_FCS_LEN + VLAN_HLEN)
352355

353356
#define ALX_MAX_RX_QUEUES 8
354357
#define ALX_MAX_TX_QUEUES 4

drivers/net/ethernet/atheros/alx/main.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -704,7 +704,7 @@ static int alx_init_sw(struct alx_priv *alx)
704704

705705
hw->smb_timer = 400;
706706
hw->mtu = alx->dev->mtu;
707-
alx->rxbuf_size = ALIGN(ALX_RAW_MTU(hw->mtu), 8);
707+
alx->rxbuf_size = ALX_MAX_FRAME_LEN(hw->mtu);
708708
alx->tx_ringsz = 256;
709709
alx->rx_ringsz = 512;
710710
hw->imt = 200;
@@ -805,7 +805,7 @@ static void alx_reinit(struct alx_priv *alx)
805805
static int alx_change_mtu(struct net_device *netdev, int mtu)
806806
{
807807
struct alx_priv *alx = netdev_priv(netdev);
808-
int max_frame = mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
808+
int max_frame = ALX_MAX_FRAME_LEN(mtu);
809809

810810
if ((max_frame < ALX_MIN_FRAME_SIZE) ||
811811
(max_frame > ALX_MAX_FRAME_SIZE))
@@ -816,8 +816,7 @@ static int alx_change_mtu(struct net_device *netdev, int mtu)
816816

817817
netdev->mtu = mtu;
818818
alx->hw.mtu = mtu;
819-
alx->rxbuf_size = mtu > ALX_DEF_RXBUF_SIZE ?
820-
ALIGN(max_frame, 8) : ALX_DEF_RXBUF_SIZE;
819+
alx->rxbuf_size = max(max_frame, ALX_DEF_RXBUF_SIZE);
821820
netdev_update_features(netdev);
822821
if (netif_running(netdev))
823822
alx_reinit(alx);

0 commit comments

Comments
 (0)