// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2025 Broadcom.
#include <asm /byteorder.h>
#include <linux/dma-mapping.h>
#include <linux/dmapool.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/pci.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/if .h>
#include <net/ip.h>
#include <linux/skbuff.h>
#include "bnge.h"
#include "bnge_hwrm_lib.h"
#include "bnge_ethtool.h"
static netdev_tx_t bnge_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
dev_kfree_skb_any(skb);
return NETDEV_TX_OK;
}
static int bnge_open(struct net_device *dev)
{
return 0;
}
static int bnge_close(struct net_device *dev)
{
return 0;
}
static const struct net_device_ops bnge_netdev_ops = {
.ndo_open = bnge_open,
.ndo_stop = bnge_close,
.ndo_start_xmit = bnge_start_xmit,
};
static void bnge_init_mac_addr(struct bnge_dev *bd)
{
eth_hw_addr_set(bd->netdev, bd->pf.mac_addr);
}
static void bnge_set_tpa_flags(struct bnge_dev *bd)
{
struct bnge_net *bn = netdev_priv(bd->netdev);
bn->priv_flags &= ~BNGE_NET_EN_TPA;
if (bd->netdev->features & NETIF_F_LRO)
bn->priv_flags |= BNGE_NET_EN_LRO;
else if (bd->netdev->features & NETIF_F_GRO_HW)
bn->priv_flags |= BNGE_NET_EN_GRO;
}
static void bnge_init_l2_fltr_tbl(struct bnge_net *bn)
{
int i;
for (i = 0; i < BNGE_L2_FLTR_HASH_SIZE; i++)
INIT_HLIST_HEAD(&bn->l2_fltr_hash_tbl[i]);
get_random_bytes(&bn->hash_seed, sizeof (bn->hash_seed));
}
void bnge_set_ring_params(struct bnge_dev *bd)
{
struct bnge_net *bn = netdev_priv(bd->netdev);
u32 ring_size, rx_size, rx_space, max_rx_cmpl;
u32 agg_factor = 0, agg_ring_size = 0;
/* 8 for CRC and VLAN */
rx_size = SKB_DATA_ALIGN(bn->netdev->mtu + ETH_HLEN + NET_IP_ALIGN + 8);
rx_space = rx_size + ALIGN(NET_SKB_PAD, 8) +
SKB_DATA_ALIGN(sizeof (struct skb_shared_info));
bn->rx_copy_thresh = BNGE_RX_COPY_THRESH;
ring_size = bn->rx_ring_size;
bn->rx_agg_ring_size = 0;
bn->rx_agg_nr_pages = 0;
if (bn->priv_flags & BNGE_NET_EN_TPA)
agg_factor = min_t(u32, 4, 65536 / BNGE_RX_PAGE_SIZE);
bn->priv_flags &= ~BNGE_NET_EN_JUMBO;
if (rx_space > PAGE_SIZE) {
u32 jumbo_factor;
bn->priv_flags |= BNGE_NET_EN_JUMBO;
jumbo_factor = PAGE_ALIGN(bn->netdev->mtu - 40) >> PAGE_SHIFT;
if (jumbo_factor > agg_factor)
agg_factor = jumbo_factor;
}
if (agg_factor) {
if (ring_size > BNGE_MAX_RX_DESC_CNT_JUM_ENA) {
ring_size = BNGE_MAX_RX_DESC_CNT_JUM_ENA;
netdev_warn(bn->netdev, "RX ring size reduced from %d to %d due to jumbo ring\n" ,
bn->rx_ring_size, ring_size);
bn->rx_ring_size = ring_size;
}
agg_ring_size = ring_size * agg_factor;
bn->rx_agg_nr_pages = bnge_adjust_pow_two(agg_ring_size,
RX_DESC_CNT);
if (bn->rx_agg_nr_pages > MAX_RX_AGG_PAGES) {
u32 tmp = agg_ring_size;
bn->rx_agg_nr_pages = MAX_RX_AGG_PAGES;
agg_ring_size = MAX_RX_AGG_PAGES * RX_DESC_CNT - 1;
netdev_warn(bn->netdev, "RX agg ring size %d reduced to %d.\n" ,
tmp, agg_ring_size);
}
bn->rx_agg_ring_size = agg_ring_size;
bn->rx_agg_ring_mask = (bn->rx_agg_nr_pages * RX_DESC_CNT) - 1;
rx_size = SKB_DATA_ALIGN(BNGE_RX_COPY_THRESH + NET_IP_ALIGN);
rx_space = rx_size + NET_SKB_PAD +
SKB_DATA_ALIGN(sizeof (struct skb_shared_info));
}
bn->rx_buf_use_size = rx_size;
bn->rx_buf_size = rx_space;
bn->rx_nr_pages = bnge_adjust_pow_two(ring_size, RX_DESC_CNT);
bn->rx_ring_mask = (bn->rx_nr_pages * RX_DESC_CNT) - 1;
ring_size = bn->tx_ring_size;
bn->tx_nr_pages = bnge_adjust_pow_two(ring_size, TX_DESC_CNT);
bn->tx_ring_mask = (bn->tx_nr_pages * TX_DESC_CNT) - 1;
max_rx_cmpl = bn->rx_ring_size;
if (bn->priv_flags & BNGE_NET_EN_TPA)
max_rx_cmpl += bd->max_tpa_v2;
ring_size = max_rx_cmpl * 2 + agg_ring_size + bn->tx_ring_size;
bn->cp_ring_size = ring_size;
bn->cp_nr_pages = bnge_adjust_pow_two(ring_size, CP_DESC_CNT);
if (bn->cp_nr_pages > MAX_CP_PAGES) {
bn->cp_nr_pages = MAX_CP_PAGES;
bn->cp_ring_size = MAX_CP_PAGES * CP_DESC_CNT - 1;
netdev_warn(bn->netdev, "completion ring size %d reduced to %d.\n" ,
ring_size, bn->cp_ring_size);
}
bn->cp_bit = bn->cp_nr_pages * CP_DESC_CNT;
bn->cp_ring_mask = bn->cp_bit - 1;
}
int bnge_netdev_alloc(struct bnge_dev *bd, int max_irqs)
{
struct net_device *netdev;
struct bnge_net *bn;
int rc;
netdev = alloc_etherdev_mqs(sizeof (*bn), max_irqs * BNGE_MAX_QUEUE,
max_irqs);
if (!netdev)
return -ENOMEM;
SET_NETDEV_DEV(netdev, bd->dev);
bd->netdev = netdev;
netdev->netdev_ops = &bnge_netdev_ops;
bnge_set_ethtool_ops(netdev);
bn = netdev_priv(netdev);
bn->netdev = netdev;
bn->bd = bd;
netdev->min_mtu = ETH_ZLEN;
netdev->max_mtu = bd->max_mtu;
netdev->hw_features = NETIF_F_IP_CSUM |
NETIF_F_IPV6_CSUM |
NETIF_F_SG |
NETIF_F_TSO |
NETIF_F_TSO6 |
NETIF_F_GSO_UDP_TUNNEL |
NETIF_F_GSO_GRE |
NETIF_F_GSO_IPXIP4 |
NETIF_F_GSO_UDP_TUNNEL_CSUM |
NETIF_F_GSO_GRE_CSUM |
NETIF_F_GSO_PARTIAL |
NETIF_F_RXHASH |
NETIF_F_RXCSUM |
NETIF_F_GRO;
if (bd->flags & BNGE_EN_UDP_GSO_SUPP)
netdev->hw_features |= NETIF_F_GSO_UDP_L4;
if (BNGE_SUPPORTS_TPA(bd))
netdev->hw_features |= NETIF_F_LRO;
netdev->hw_enc_features = NETIF_F_IP_CSUM |
NETIF_F_IPV6_CSUM |
NETIF_F_SG |
NETIF_F_TSO |
NETIF_F_TSO6 |
NETIF_F_GSO_UDP_TUNNEL |
NETIF_F_GSO_GRE |
NETIF_F_GSO_UDP_TUNNEL_CSUM |
NETIF_F_GSO_GRE_CSUM |
NETIF_F_GSO_IPXIP4 |
NETIF_F_GSO_PARTIAL;
if (bd->flags & BNGE_EN_UDP_GSO_SUPP)
netdev->hw_enc_features |= NETIF_F_GSO_UDP_L4;
netdev->gso_partial_features = NETIF_F_GSO_UDP_TUNNEL_CSUM |
NETIF_F_GSO_GRE_CSUM;
netdev->vlan_features = netdev->hw_features | NETIF_F_HIGHDMA;
if (bd->fw_cap & BNGE_FW_CAP_VLAN_RX_STRIP)
netdev->hw_features |= BNGE_HW_FEATURE_VLAN_ALL_RX;
if (bd->fw_cap & BNGE_FW_CAP_VLAN_TX_INSERT)
netdev->hw_features |= BNGE_HW_FEATURE_VLAN_ALL_TX;
if (BNGE_SUPPORTS_TPA(bd))
netdev->hw_features |= NETIF_F_GRO_HW;
netdev->features |= netdev->hw_features | NETIF_F_HIGHDMA;
if (netdev->features & NETIF_F_GRO_HW)
netdev->features &= ~NETIF_F_LRO;
netdev->priv_flags |= IFF_UNICAST_FLT;
netif_set_tso_max_size(netdev, GSO_MAX_SIZE);
if (bd->tso_max_segs)
netif_set_tso_max_segs(netdev, bd->tso_max_segs);
bn->rx_ring_size = BNGE_DEFAULT_RX_RING_SIZE;
bn->tx_ring_size = BNGE_DEFAULT_TX_RING_SIZE;
bnge_set_tpa_flags(bd);
bnge_set_ring_params(bd);
bnge_init_l2_fltr_tbl(bn);
bnge_init_mac_addr(bd);
rc = register_netdev(netdev);
if (rc) {
dev_err(bd->dev, "Register netdev failed rc: %d\n" , rc);
goto err_netdev;
}
return 0;
err_netdev:
free_netdev(netdev);
return rc;
}
void bnge_netdev_free(struct bnge_dev *bd)
{
struct net_device *netdev = bd->netdev;
unregister_netdev(netdev);
free_netdev(netdev);
bd->netdev = NULL;
}
Messung V0.5 C=99 H=93 G=95
¤ Dauer der Verarbeitung: 0.9 Sekunden
(vorverarbeitet)
¤
*© Formatika GbR, Deutschland