Skip to content

Commit 39dfaf2

Browse files
committed
WIP: net: bcmgenet: experimental 9000 byte MTU without status blocks
RBUF_PKT_RDY_THLD is where the status block gets written, not a limit on the frame. With the status blocks off jumbo frames come through and the threshold splits nothing. Costs both checksum offloads and all but one transmit queue. Signed-off-by: Nicolai Buchwitz <nb@tipi-net.de>
1 parent 9b39d78 commit 39dfaf2

1 file changed

Lines changed: 74 additions & 22 deletions

File tree

drivers/net/ethernet/broadcom/genet/bcmgenet.c

Lines changed: 74 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <linux/acpi.h>
1111
#include <linux/kernel.h>
1212
#include <linux/module.h>
13+
#include <linux/of.h>
1314
#include <linux/sched.h>
1415
#include <linux/types.h>
1516
#include <linux/fcntl.h>
@@ -51,6 +52,12 @@
5152

5253
#define SKB_ALIGNMENT 32
5354

55+
/* Test only, see the commit message */
56+
static bool experimental_jumbo;
57+
module_param(experimental_jumbo, bool, 0444);
58+
MODULE_PARM_DESC(experimental_jumbo,
59+
"9000 byte MTU, costs the status blocks and checksum offload");
60+
5461
/* Tx/Rx DMA register offset, skip 256 descriptors */
5562
#define WORDS_PER_BD(p) (p->hw_params->words_per_bd)
5663
#define DMA_DESC_SIZE (WORDS_PER_BD(priv) * sizeof(u32))
@@ -2150,11 +2157,13 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev)
21502157
*/
21512158
GENET_CB(skb)->bytes_sent = skb->len;
21522159

2153-
/* add the Transmit Status Block */
2154-
skb = bcmgenet_add_tsb(dev, skb, ring);
2155-
if (!skb) {
2156-
ret = NETDEV_TX_OK;
2157-
goto out;
2160+
/* No TSB, probe cleared the checksum offloads */
2161+
if (!experimental_jumbo) {
2162+
skb = bcmgenet_add_tsb(dev, skb, ring);
2163+
if (!skb) {
2164+
ret = NETDEV_TX_OK;
2165+
goto out;
2166+
}
21582167
}
21592168

21602169
for (i = 0; i <= nr_frags; i++) {
@@ -2209,7 +2218,8 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev)
22092218

22102219
GENET_CB(skb)->last_cb = tx_cb_ptr;
22112220

2212-
bcmgenet_hide_tsb(skb);
2221+
if (!experimental_jumbo)
2222+
bcmgenet_hide_tsb(skb);
22132223
skb_tx_timestamp(skb);
22142224

22152225
/* Decrement total BD count and advance our write pointer */
@@ -2339,20 +2349,25 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,
23392349
__be16 rx_csum;
23402350

23412351
cb = &priv->rx_cbs[ring->read_ptr];
2352+
if (experimental_jumbo)
2353+
dma_length_status = bcmgenet_readl(cb->bd_addr +
2354+
DMA_DESC_LENGTH_STATUS);
23422355
skb = bcmgenet_rx_refill(priv, cb);
23432356

23442357
if (unlikely(!skb)) {
23452358
BCMGENET_STATS64_INC(stats, dropped);
23462359
goto next;
23472360
}
23482361

2349-
status = (struct status_64 *)skb->data;
2350-
dma_length_status = status->length_status;
2351-
if (dev->features & NETIF_F_RXCSUM) {
2352-
rx_csum = (__force __be16)(status->rx_csum & 0xffff);
2353-
if (rx_csum) {
2354-
skb->csum = (__force __wsum)ntohs(rx_csum);
2355-
skb->ip_summed = CHECKSUM_COMPLETE;
2362+
if (!experimental_jumbo) {
2363+
status = (struct status_64 *)skb->data;
2364+
dma_length_status = status->length_status;
2365+
if (dev->features & NETIF_F_RXCSUM) {
2366+
rx_csum = (__force __be16)(status->rx_csum & 0xffff);
2367+
if (rx_csum) {
2368+
skb->csum = (__force __wsum)ntohs(rx_csum);
2369+
skb->ip_summed = CHECKSUM_COMPLETE;
2370+
}
23562371
}
23572372
}
23582373

@@ -2367,7 +2382,10 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,
23672382
__func__, p_index, ring->c_index,
23682383
ring->read_ptr, dma_length_status);
23692384

2370-
if (unlikely(len > priv->rx_buf_len)) {
2385+
if (unlikely(len > priv->rx_buf_len ||
2386+
len < (experimental_jumbo ? ENET_RBUF_ALIGN :
2387+
ENET_RX_OFFSET) + ETH_HLEN +
2388+
(priv->crc_fwd_en ? ETH_FCS_LEN : 0))) {
23712389
netif_err(priv, rx_status, dev, "oversized packet\n");
23722390
BCMGENET_STATS64_INC(stats, length_errors);
23732391
dev_kfree_skb_any(skb);
@@ -2412,9 +2430,14 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,
24122430

24132431
skb_put(skb, len);
24142432

2415-
/* remove RSB and hardware 2bytes added for IP alignment */
2416-
skb_pull(skb, ENET_RX_OFFSET);
2417-
len -= ENET_RX_OFFSET;
2433+
/* Remove the alignment bytes, and the RSB if there is one */
2434+
if (experimental_jumbo) {
2435+
skb_pull(skb, ENET_RBUF_ALIGN);
2436+
len -= ENET_RBUF_ALIGN;
2437+
} else {
2438+
skb_pull(skb, ENET_RX_OFFSET);
2439+
len -= ENET_RX_OFFSET;
2440+
}
24182441

24192442
if (priv->crc_fwd_en) {
24202443
skb_trim(skb, len - ETH_FCS_LEN);
@@ -2612,6 +2635,11 @@ static unsigned int bcmgenet_pkt_rdy_thld(unsigned int mtu)
26122635
/* A buffer has to hold everything the threshold lets the hardware deliver */
26132636
static unsigned int bcmgenet_rx_buf_len(unsigned int mtu)
26142637
{
2638+
if (experimental_jumbo)
2639+
return max_t(unsigned int, ENET_THLD_DEFAULT * ENET_THLD_UNIT,
2640+
round_up(ENET_MAX_FRAME_LEN(mtu) + ENET_RBUF_ALIGN,
2641+
ENET_THLD_BURST));
2642+
26152643
return ENET_RSB_LEN + bcmgenet_pkt_rdy_thld(mtu) * ENET_THLD_UNIT;
26162644
}
26172645

@@ -2652,17 +2680,28 @@ static void init_umac(struct bcmgenet_priv *priv)
26522680

26532681
/* init tx registers, enable TSB */
26542682
reg = bcmgenet_tbuf_ctrl_get(priv);
2655-
reg |= TBUF_64B_EN;
2683+
if (experimental_jumbo)
2684+
reg &= ~TBUF_64B_EN;
2685+
else
2686+
reg |= TBUF_64B_EN;
26562687
bcmgenet_tbuf_ctrl_set(priv, reg);
26572688

26582689
/* init rx registers, enable ip header optimization and RSB */
26592690
reg = bcmgenet_rbuf_readl(priv, RBUF_CTRL);
2660-
reg |= RBUF_ALIGN_2B | RBUF_64B_EN;
2691+
reg |= RBUF_ALIGN_2B;
2692+
if (experimental_jumbo)
2693+
reg &= ~RBUF_64B_EN;
2694+
else
2695+
reg |= RBUF_64B_EN;
26612696
bcmgenet_rbuf_writel(priv, reg, RBUF_CTRL);
26622697

26632698
/* enable rx checksumming */
26642699
reg = bcmgenet_rbuf_readl(priv, RBUF_CHK_CTRL);
2665-
reg |= RBUF_RXCHK_EN | RBUF_L3_PARSE_DIS;
2700+
reg |= RBUF_L3_PARSE_DIS;
2701+
if (experimental_jumbo)
2702+
reg &= ~RBUF_RXCHK_EN;
2703+
else
2704+
reg |= RBUF_RXCHK_EN;
26662705
/* If UniMAC forwards CRC, we need to skip over it to get
26672706
* a valid CHK bit to be set in the per-packet status word
26682707
*/
@@ -4132,6 +4171,18 @@ static int bcmgenet_probe(struct platform_device *pdev)
41324171

41334172
bcmgenet_set_hw_params(priv);
41344173

4174+
if (experimental_jumbo) {
4175+
if (!of_device_is_compatible(pdev->dev.of_node,
4176+
"brcm,bcm2711-genet-v5")) {
4177+
err = -EOPNOTSUPP;
4178+
goto err_clk_disable;
4179+
}
4180+
dev->features &= ~(NETIF_F_CSUM_MASK | NETIF_F_RXCSUM);
4181+
dev->hw_features &= ~(NETIF_F_CSUM_MASK | NETIF_F_RXCSUM);
4182+
dev->vlan_features &= ~(NETIF_F_CSUM_MASK | NETIF_F_RXCSUM);
4183+
dev_warn(&pdev->dev, "experimental jumbo mode enabled\n");
4184+
}
4185+
41354186
err = -EIO;
41364187
if (bcmgenet_has_40bits(priv))
41374188
err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(40));
@@ -4147,7 +4198,7 @@ static int bcmgenet_probe(struct platform_device *pdev)
41474198
/* v1 cannot program the thresholds, so it stays at the default MTU */
41484199
priv->rx_buf_len = bcmgenet_rx_buf_len(dev->mtu);
41494200
if (!GENET_IS_V1(priv))
4150-
dev->max_mtu = ENET_MAX_MTU;
4201+
dev->max_mtu = experimental_jumbo ? 9000 : ENET_MAX_MTU;
41514202
INIT_WORK(&priv->bcmgenet_irq_work, bcmgenet_irq_task);
41524203

41534204
priv->clk_wol = devm_clk_get_optional(&priv->pdev->dev, "enet-wol");
@@ -4193,7 +4244,8 @@ static int bcmgenet_probe(struct platform_device *pdev)
41934244
goto err_clk_disable;
41944245

41954246
/* setup number of real queues + 1 */
4196-
netif_set_real_num_tx_queues(priv->dev, priv->hw_params->tx_queues + 1);
4247+
netif_set_real_num_tx_queues(priv->dev, experimental_jumbo ? 1 :
4248+
priv->hw_params->tx_queues + 1);
41974249
netif_set_real_num_rx_queues(priv->dev, priv->hw_params->rx_queues + 1);
41984250

41994251
/* Set default coalescing parameters */

0 commit comments

Comments
 (0)