Skip to content

Commit

Permalink
net: enetc: initialize RFS/RSS memories for unused ports too
Browse files Browse the repository at this point in the history
commit 3222b5b upstream.

Michael reports that since linux-next-20210211, the AER messages for ECC
errors have started reappearing, and this time they can be reliably
reproduced with the first ping on one of his LS1028A boards.

$ ping 1[   33.258069] pcieport 0000:00:1f.0: AER: Multiple Corrected error received: 0000:00:00.0
72.16.0.1
PING [   33.267050] pcieport 0000:00:1f.0: AER: can't find device of ID0000
172.16.0.1 (172.16.0.1): 56 data bytes
64 bytes from 172.16.0.1: seq=0 ttl=64 time=17.124 ms
64 bytes from 172.16.0.1: seq=1 ttl=64 time=0.273 ms

$ devmem 0x1f8010e10 32
0xC0000006

It isn't clear why this is necessary, but it seems that for the errors
to go away, we must clear the entire RFS and RSS memory, not just for
the ports in use.

Sadly the code is structured in such a way that we can't have unified
logic for the used and unused ports. For the minimal initialization of
an unused port, we need just to enable and ioremap the PF memory space,
and a control buffer descriptor ring. Unused ports must then free the
CBDR because the driver will exit, but used ports can not pick up from
where that code path left, since the CBDR API does not reinitialize a
ring when setting it up, so its producer and consumer indices are out of
sync between the software and hardware state. So a separate
enetc_init_unused_port function was created, and it gets called right
after the PF memory space is enabled.

Fixes: 07bf34a ("net: enetc: initialize the RFS and RSS memories")
Reported-by: Michael Walle <michael@walle.cc>
Cc: Jesse Brandeburg <jesse.brandeburg@intel.com>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Tested-by: Michael Walle <michael@walle.cc>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
vladimiroltean authored and gregkh committed Mar 17, 2021
1 parent 6a1d94a commit 5fb230e
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 9 deletions.
8 changes: 4 additions & 4 deletions drivers/net/ethernet/freescale/enetc/enetc.c
Expand Up @@ -984,7 +984,7 @@ static void enetc_free_rxtx_rings(struct enetc_ndev_priv *priv)
enetc_free_tx_ring(priv->tx_ring[i]);
}

static int enetc_alloc_cbdr(struct device *dev, struct enetc_cbdr *cbdr)
int enetc_alloc_cbdr(struct device *dev, struct enetc_cbdr *cbdr)
{
int size = cbdr->bd_count * sizeof(struct enetc_cbd);

Expand All @@ -1005,15 +1005,15 @@ static int enetc_alloc_cbdr(struct device *dev, struct enetc_cbdr *cbdr)
return 0;
}

static void enetc_free_cbdr(struct device *dev, struct enetc_cbdr *cbdr)
void enetc_free_cbdr(struct device *dev, struct enetc_cbdr *cbdr)
{
int size = cbdr->bd_count * sizeof(struct enetc_cbd);

dma_free_coherent(dev, size, cbdr->bd_base, cbdr->bd_dma_base);
cbdr->bd_base = NULL;
}

static void enetc_setup_cbdr(struct enetc_hw *hw, struct enetc_cbdr *cbdr)
void enetc_setup_cbdr(struct enetc_hw *hw, struct enetc_cbdr *cbdr)
{
/* set CBDR cache attributes */
enetc_wr(hw, ENETC_SICAR2,
Expand All @@ -1033,7 +1033,7 @@ static void enetc_setup_cbdr(struct enetc_hw *hw, struct enetc_cbdr *cbdr)
cbdr->cir = hw->reg + ENETC_SICBDRCIR;
}

static void enetc_clear_cbdr(struct enetc_hw *hw)
void enetc_clear_cbdr(struct enetc_hw *hw)
{
enetc_wr(hw, ENETC_SICBDRMR, 0);
}
Expand Down
4 changes: 4 additions & 0 deletions drivers/net/ethernet/freescale/enetc/enetc.h
Expand Up @@ -310,6 +310,10 @@ int enetc_setup_tc(struct net_device *ndev, enum tc_setup_type type,
void enetc_set_ethtool_ops(struct net_device *ndev);

/* control buffer descriptor ring (CBDR) */
int enetc_alloc_cbdr(struct device *dev, struct enetc_cbdr *cbdr);
void enetc_free_cbdr(struct device *dev, struct enetc_cbdr *cbdr);
void enetc_setup_cbdr(struct enetc_hw *hw, struct enetc_cbdr *cbdr);
void enetc_clear_cbdr(struct enetc_hw *hw);
int enetc_set_mac_flt_entry(struct enetc_si *si, int index,
char *mac_addr, int si_map);
int enetc_clear_mac_flt_entry(struct enetc_si *si, int index);
Expand Down
33 changes: 28 additions & 5 deletions drivers/net/ethernet/freescale/enetc/enetc_pf.c
Expand Up @@ -1041,6 +1041,26 @@ static int enetc_init_port_rss_memory(struct enetc_si *si)
return err;
}

static void enetc_init_unused_port(struct enetc_si *si)
{
struct device *dev = &si->pdev->dev;
struct enetc_hw *hw = &si->hw;
int err;

si->cbd_ring.bd_count = ENETC_CBDR_DEFAULT_SIZE;
err = enetc_alloc_cbdr(dev, &si->cbd_ring);
if (err)
return;

enetc_setup_cbdr(hw, &si->cbd_ring);

enetc_init_port_rfs_memory(si);
enetc_init_port_rss_memory(si);

enetc_clear_cbdr(hw);
enetc_free_cbdr(dev, &si->cbd_ring);
}

static int enetc_pf_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
Expand All @@ -1051,11 +1071,6 @@ static int enetc_pf_probe(struct pci_dev *pdev,
struct enetc_pf *pf;
int err;

if (node && !of_device_is_available(node)) {
dev_info(&pdev->dev, "device is disabled, skipping\n");
return -ENODEV;
}

err = enetc_pci_probe(pdev, KBUILD_MODNAME, sizeof(*pf));
if (err) {
dev_err(&pdev->dev, "PCI probing failed\n");
Expand All @@ -1069,6 +1084,13 @@ static int enetc_pf_probe(struct pci_dev *pdev,
goto err_map_pf_space;
}

if (node && !of_device_is_available(node)) {
enetc_init_unused_port(si);
dev_info(&pdev->dev, "device is disabled, skipping\n");
err = -ENODEV;
goto err_device_disabled;
}

pf = enetc_si_priv(si);
pf->si = si;
pf->total_vfs = pci_sriov_get_totalvfs(pdev);
Expand Down Expand Up @@ -1151,6 +1173,7 @@ static int enetc_pf_probe(struct pci_dev *pdev,
si->ndev = NULL;
free_netdev(ndev);
err_alloc_netdev:
err_device_disabled:
err_map_pf_space:
enetc_pci_remove(pdev);

Expand Down

0 comments on commit 5fb230e

Please sign in to comment.