2020-10-01 10:54:40

by Grygorii Strashko

[permalink] [raw]
Subject: [PATCH net-next 0/8] net: ethernet: ti: am65-cpsw: add multi port support in mac-only mode

Hi

This series adds multi-port support in mac-only mode (multi MAC mode) to TI
AM65x CPSW driver in preparation for enabling support for multi-port devices,
like Main CPSW0 on K3 J721E SoC or future CPSW3g on K3 AM64x SoC.

The multi MAC mode is implemented by configuring every enabled port in "mac-only"
mode (all ingress packets are sent only to the Host port and egress packets
directed to target Ext. Port) and creating separate net_device for
every enabled Ext. port.

Patches 1-3: Preparation patches to improve K3 CPSW configuration depending on DT
Patches 4-5: Fix VLAN offload for multi MAC mode
Patch 6: Fixes CPTS context lose issue during PM runtime transition
Patches 7-8: add multi-port support to TI AM65x CPSW

Grygorii Strashko (8):
net: ethernet: ti: am65-cpsw: move ale selection in pdata
net: ethernet: ti: am65-cpsw: move free desc queue mode selection in pdata
net: ethernet: ti: am65-cpsw: use cppi5_desc_is_tdcm()
net: ethernet: ti: cpsw_ale: add cpsw_ale_vlan_del_modify()
net: ethernet: ti: am65-cpsw: fix vlan offload for multi mac mode
net: ethernet: ti: am65-cpsw: keep active if cpts enabled
net: ethernet: ti: am65-cpsw: prepare xmit/rx path for multi-port
devices in mac-only mode
net: ethernet: ti: am65-cpsw: add multi port support in mac-only mode

drivers/net/ethernet/ti/am65-cpsw-nuss.c | 179 ++++++++++++++---------
drivers/net/ethernet/ti/am65-cpsw-nuss.h | 4 +
drivers/net/ethernet/ti/cpsw_ale.c | 41 +++++-
drivers/net/ethernet/ti/cpsw_ale.h | 1 +
drivers/net/ethernet/ti/cpsw_switchdev.c | 2 +-
5 files changed, 153 insertions(+), 74 deletions(-)

--
2.17.1


2020-10-01 10:54:58

by Grygorii Strashko

[permalink] [raw]
Subject: [PATCH net-next 1/8] net: ethernet: ti: am65-cpsw: move ale selection in pdata

In preparation of adding more multi-port K3 CPSW versions move ALE
selection in am65_cpsw_pdata, so it can be selected basing on DT
compatibility property.

Signed-off-by: Grygorii Strashko <[email protected]>
---
drivers/net/ethernet/ti/am65-cpsw-nuss.c | 4 +++-
drivers/net/ethernet/ti/am65-cpsw-nuss.h | 1 +
2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
index 501d676fd88b..0ee1c7a5c90f 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
@@ -2005,10 +2005,12 @@ static const struct soc_device_attribute am65_cpsw_socinfo[] = {

static const struct am65_cpsw_pdata am65x_sr1_0 = {
.quirks = AM65_CPSW_QUIRK_I2027_NO_TX_CSUM,
+ .ale_dev_id = "am65x-cpsw2g",
};

static const struct am65_cpsw_pdata j721e_pdata = {
.quirks = 0,
+ .ale_dev_id = "am65x-cpsw2g",
};

static const struct of_device_id am65_cpsw_nuss_of_mtable[] = {
@@ -2145,7 +2147,7 @@ static int am65_cpsw_nuss_probe(struct platform_device *pdev)
ale_params.ale_ageout = AM65_CPSW_ALE_AGEOUT_DEFAULT;
ale_params.ale_ports = common->port_num + 1;
ale_params.ale_regs = common->cpsw_base + AM65_CPSW_NU_ALE_BASE;
- ale_params.dev_id = "am65x-cpsw2g";
+ ale_params.dev_id = common->pdata.ale_dev_id;
ale_params.bus_freq = common->bus_freq;

common->ale = cpsw_ale_create(&ale_params);
diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.h b/drivers/net/ethernet/ti/am65-cpsw-nuss.h
index 993e1d4d3222..9c2186b8eae9 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.h
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.h
@@ -77,6 +77,7 @@ struct am65_cpsw_rx_chn {

struct am65_cpsw_pdata {
u32 quirks;
+ const char *ale_dev_id;
};

struct am65_cpsw_common {
--
2.17.1

2020-10-01 10:55:13

by Grygorii Strashko

[permalink] [raw]
Subject: [PATCH net-next 2/8] net: ethernet: ti: am65-cpsw: move free desc queue mode selection in pdata

In preparation of adding more multi-port K3 CPSW versions move free
descriptor queue mode selection in am65_cpsw_pdata, so it can be selected
basing on DT compatibility property.

Signed-off-by: Grygorii Strashko <[email protected]>
---
drivers/net/ethernet/ti/am65-cpsw-nuss.c | 4 +++-
drivers/net/ethernet/ti/am65-cpsw-nuss.h | 2 ++
2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
index 0ee1c7a5c90f..6cea338df7ad 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
@@ -1606,7 +1606,6 @@ static int am65_cpsw_nuss_init_rx_chns(struct am65_cpsw_common *common)
};
struct k3_ring_cfg fdqring_cfg = {
.elm_size = K3_RINGACC_RING_ELSIZE_8,
- .mode = K3_RINGACC_RING_MODE_MESSAGE,
.flags = K3_RINGACC_RING_SHARED,
};
struct k3_udma_glue_rx_flow_cfg rx_flow_cfg = {
@@ -1620,6 +1619,7 @@ static int am65_cpsw_nuss_init_rx_chns(struct am65_cpsw_common *common)
rx_flow_cfg.ring_rxfdq0_id = fdqring_id;
rx_flow_cfg.rx_cfg.size = max_desc_num;
rx_flow_cfg.rxfdq_cfg.size = max_desc_num;
+ rx_flow_cfg.rxfdq_cfg.mode = common->pdata.fdqring_mode;

ret = k3_udma_glue_rx_flow_init(rx_chn->rx_chn,
i, &rx_flow_cfg);
@@ -2006,11 +2006,13 @@ static const struct soc_device_attribute am65_cpsw_socinfo[] = {
static const struct am65_cpsw_pdata am65x_sr1_0 = {
.quirks = AM65_CPSW_QUIRK_I2027_NO_TX_CSUM,
.ale_dev_id = "am65x-cpsw2g",
+ .fdqring_mode = K3_RINGACC_RING_MODE_MESSAGE,
};

static const struct am65_cpsw_pdata j721e_pdata = {
.quirks = 0,
.ale_dev_id = "am65x-cpsw2g",
+ .fdqring_mode = K3_RINGACC_RING_MODE_MESSAGE,
};

static const struct of_device_id am65_cpsw_nuss_of_mtable[] = {
diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.h b/drivers/net/ethernet/ti/am65-cpsw-nuss.h
index 9c2186b8eae9..b6f228ddc3a0 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.h
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.h
@@ -11,6 +11,7 @@
#include <linux/netdevice.h>
#include <linux/phy.h>
#include <linux/platform_device.h>
+#include <linux/soc/ti/k3-ringacc.h>
#include "am65-cpsw-qos.h"

struct am65_cpts;
@@ -77,6 +78,7 @@ struct am65_cpsw_rx_chn {

struct am65_cpsw_pdata {
u32 quirks;
+ enum k3_ring_mode fdqring_mode;
const char *ale_dev_id;
};

--
2.17.1

2020-10-01 10:55:37

by Grygorii Strashko

[permalink] [raw]
Subject: [PATCH net-next 3/8] net: ethernet: ti: am65-cpsw: use cppi5_desc_is_tdcm()

Use cppi5_desc_is_tdcm() helper for teardown indicator detection instead of
hard-coded value.

Signed-off-by: Grygorii Strashko <[email protected]>
---
drivers/net/ethernet/ti/am65-cpsw-nuss.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
index 6cea338df7ad..65c5446e324e 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
@@ -767,7 +767,7 @@ static int am65_cpsw_nuss_rx_packets(struct am65_cpsw_common *common,
return ret;
}

- if (desc_dma & 0x1) {
+ if (cppi5_desc_is_tdcm(desc_dma)) {
dev_dbg(dev, "%s RX tdown flow: %u\n", __func__, flow_idx);
return 0;
}
@@ -935,7 +935,7 @@ static int am65_cpsw_nuss_tx_compl_packets(struct am65_cpsw_common *common,
if (res == -ENODATA)
break;

- if (desc_dma & 0x1) {
+ if (cppi5_desc_is_tdcm(desc_dma)) {
if (atomic_dec_and_test(&common->tdown_cnt))
complete(&common->tdown_complete);
break;
--
2.17.1

2020-10-01 10:56:50

by Grygorii Strashko

[permalink] [raw]
Subject: [PATCH net-next 8/8] net: ethernet: ti: am65-cpsw: add multi port support in mac-only mode

This patch adds final multi-port support to TI AM65x CPSW driver in
preparation for adding support for multi-port devices, like Main CPSW0 on
K3 J721E SoC or future CPSW3g on K3 AM64x SoC.
- the separate netdev is created for every enabled external Port;
- DMA channels are common/shared for all external Ports and the RX/TX NAPI
and DMA processing assigned to first netdev;
- external Ports are configured in mac-only mode, which is similar to TI
"dual-mac" mode for legacy TI CPSW - packets are sent to the Host port only
in ingress and directly to the Port on egress. No packet switching between
external ports happens.
- every port supports the same features as current AM65x CPSW on external
device.

Signed-off-by: Grygorii Strashko <[email protected]>
---
drivers/net/ethernet/ti/am65-cpsw-nuss.c | 111 ++++++++++++++---------
1 file changed, 70 insertions(+), 41 deletions(-)

diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
index a8094e8e49ca..1658c4f305b5 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
@@ -272,8 +272,8 @@ static int am65_cpsw_nuss_ndo_slave_kill_vid(struct net_device *ndev,
return ret;
}

-static void am65_cpsw_slave_set_promisc_2g(struct am65_cpsw_port *port,
- bool promisc)
+static void am65_cpsw_slave_set_promisc(struct am65_cpsw_port *port,
+ bool promisc)
{
struct am65_cpsw_common *common = port->common;

@@ -298,7 +298,7 @@ static void am65_cpsw_nuss_ndo_slave_set_rx_mode(struct net_device *ndev)
bool promisc;

promisc = !!(ndev->flags & IFF_PROMISC);
- am65_cpsw_slave_set_promisc_2g(port, promisc);
+ am65_cpsw_slave_set_promisc(port, promisc);

if (promisc)
return;
@@ -631,13 +631,13 @@ static int am65_cpsw_nuss_ndo_slave_open(struct net_device *ndev)

am65_cpsw_port_set_sl_mac(port, ndev->dev_addr);

- if (port->slave.mac_only)
+ if (port->slave.mac_only) {
/* enable mac-only mode on port */
cpsw_ale_control_set(common->ale, port->port_id,
ALE_PORT_MACONLY, 1);
- if (AM65_CPSW_IS_CPSW2G(common))
cpsw_ale_control_set(common->ale, port->port_id,
ALE_PORT_NOLEARN, 1);
+ }

port_mask = BIT(port->port_id) | ALE_PORT_HOST;
cpsw_ale_add_ucast(common->ale, ndev->dev_addr,
@@ -1398,7 +1398,7 @@ static int am65_cpsw_nuss_ndo_slave_set_features(struct net_device *ndev,
return 0;
}

-static const struct net_device_ops am65_cpsw_nuss_netdev_ops_2g = {
+static const struct net_device_ops am65_cpsw_nuss_netdev_ops = {
.ndo_open = am65_cpsw_nuss_ndo_slave_open,
.ndo_stop = am65_cpsw_nuss_ndo_slave_stop,
.ndo_start_xmit = am65_cpsw_nuss_ndo_slave_xmit,
@@ -1855,14 +1855,18 @@ static void am65_cpsw_pcpu_stats_free(void *data)
free_percpu(stats);
}

-static int am65_cpsw_nuss_init_ndev_2g(struct am65_cpsw_common *common)
+static int
+am65_cpsw_nuss_init_port_ndev(struct am65_cpsw_common *common, u32 port_idx)
{
struct am65_cpsw_ndev_priv *ndev_priv;
struct device *dev = common->dev;
struct am65_cpsw_port *port;
int ret;

- port = am65_common_get_port(common, 1);
+ port = &common->ports[port_idx];
+
+ if (port->disabled)
+ return 0;

/* alloc netdev */
port->ndev = devm_alloc_etherdev_mqs(common->dev,
@@ -1891,7 +1895,7 @@ static int am65_cpsw_nuss_init_ndev_2g(struct am65_cpsw_common *common)
port->ndev->features = port->ndev->hw_features |
NETIF_F_HW_VLAN_CTAG_FILTER;
port->ndev->vlan_features |= NETIF_F_SG;
- port->ndev->netdev_ops = &am65_cpsw_nuss_netdev_ops_2g;
+ port->ndev->netdev_ops = &am65_cpsw_nuss_netdev_ops;
port->ndev->ethtool_ops = &am65_cpsw_ethtool_ops_slave;

/* Disable TX checksum offload by default due to HW bug */
@@ -1904,18 +1908,33 @@ static int am65_cpsw_nuss_init_ndev_2g(struct am65_cpsw_common *common)

ret = devm_add_action_or_reset(dev, am65_cpsw_pcpu_stats_free,
ndev_priv->stats);
- if (ret) {
- dev_err(dev, "Failed to add percpu stat free action %d\n", ret);
- return ret;
+ if (ret)
+ dev_err(dev, "failed to add percpu stat free action %d\n", ret);
+
+ return ret;
+}
+
+static int am65_cpsw_nuss_init_ndevs(struct am65_cpsw_common *common)
+{
+ struct am65_cpsw_port *port;
+ int ret;
+ int i;
+
+ for (i = 0; i < common->port_num; i++) {
+ ret = am65_cpsw_nuss_init_port_ndev(common, i);
+ if (ret)
+ return ret;
}

+ port = am65_common_get_port(common, 1);
+
netif_napi_add(port->ndev, &common->napi_rx,
am65_cpsw_nuss_rx_poll, NAPI_POLL_WEIGHT);

return ret;
}

-static int am65_cpsw_nuss_ndev_add_napi_2g(struct am65_cpsw_common *common)
+static int am65_cpsw_nuss_ndev_add_tx_napi(struct am65_cpsw_common *common)
{
struct device *dev = common->dev;
struct am65_cpsw_port *port;
@@ -1944,16 +1963,27 @@ static int am65_cpsw_nuss_ndev_add_napi_2g(struct am65_cpsw_common *common)
return ret;
}

-static int am65_cpsw_nuss_ndev_reg_2g(struct am65_cpsw_common *common)
+static void am65_cpsw_nuss_cleanup_ndev(struct am65_cpsw_common *common)
+{
+ struct am65_cpsw_port *port;
+ int i;
+
+ for (i = 0; i < common->port_num; i++) {
+ port = &common->ports[i];
+ if (port->ndev)
+ unregister_netdev(port->ndev);
+ }
+}
+
+static int am65_cpsw_nuss_register_ndevs(struct am65_cpsw_common *common)
{
struct device *dev = common->dev;
struct am65_cpsw_port *port;
- int ret = 0;
+ int ret = 0, i;

- port = am65_common_get_port(common, 1);
- ret = am65_cpsw_nuss_ndev_add_napi_2g(common);
+ ret = am65_cpsw_nuss_ndev_add_tx_napi(common);
if (ret)
- goto err;
+ return ret;

ret = devm_request_irq(dev, common->rx_chns.irq,
am65_cpsw_nuss_rx_irq,
@@ -1961,17 +1991,31 @@ static int am65_cpsw_nuss_ndev_reg_2g(struct am65_cpsw_common *common)
if (ret) {
dev_err(dev, "failure requesting rx irq %u, %d\n",
common->rx_chns.irq, ret);
- goto err;
+ return ret;
+ }
+
+ for (i = 0; i < common->port_num; i++) {
+ port = &common->ports[i];
+
+ if (!port->ndev)
+ continue;
+
+ ret = register_netdev(port->ndev);
+ if (ret) {
+ dev_err(dev, "error registering slave net device%i %d\n",
+ i, ret);
+ goto err_cleanup_ndev;
+ }
}

- ret = register_netdev(port->ndev);
- if (ret)
- dev_err(dev, "error registering slave net device %d\n", ret);

/* can't auto unregister ndev using devm_add_action() due to
* devres release sequence in DD core for DMA
*/
-err:
+ return 0;
+
+err_cleanup_ndev:
+ am65_cpsw_nuss_cleanup_ndev(common);
return ret;
}

@@ -1984,19 +2028,7 @@ int am65_cpsw_nuss_update_tx_chns(struct am65_cpsw_common *common, int num_tx)
if (ret)
return ret;

- return am65_cpsw_nuss_ndev_add_napi_2g(common);
-}
-
-static void am65_cpsw_nuss_cleanup_ndev(struct am65_cpsw_common *common)
-{
- struct am65_cpsw_port *port;
- int i;
-
- for (i = 0; i < common->port_num; i++) {
- port = &common->ports[i];
- if (port->ndev)
- unregister_netdev(port->ndev);
- }
+ return am65_cpsw_nuss_ndev_add_tx_napi(common);
}

struct am65_cpsw_soc_pdata {
@@ -2084,9 +2116,6 @@ static int am65_cpsw_nuss_probe(struct platform_device *pdev)
return -ENOENT;
of_node_put(node);

- if (common->port_num != 1)
- return -EOPNOTSUPP;
-
common->rx_flow_id_base = -1;
init_completion(&common->tdown_complete);
common->tx_ch_num = 1;
@@ -2181,11 +2210,11 @@ static int am65_cpsw_nuss_probe(struct platform_device *pdev)

dev_set_drvdata(dev, common);

- ret = am65_cpsw_nuss_init_ndev_2g(common);
+ ret = am65_cpsw_nuss_init_ndevs(common);
if (ret)
goto err_of_clear;

- ret = am65_cpsw_nuss_ndev_reg_2g(common);
+ ret = am65_cpsw_nuss_register_ndevs(common);
if (ret)
goto err_of_clear;

--
2.17.1

2020-10-01 10:57:16

by Grygorii Strashko

[permalink] [raw]
Subject: [PATCH net-next 4/8] net: ethernet: ti: cpsw_ale: add cpsw_ale_vlan_del_modify()

Add/export cpsw_ale_vlan_del_modify() and use it in cpsw_switchdev instead
of generic cpsw_ale_del_vlan() to avoid mixing 8021Q and switchdev VLAN
offload. This is preparation patch equired by follow up changes.

Signed-off-by: Grygorii Strashko <[email protected]>
---
drivers/net/ethernet/ti/cpsw_ale.c | 24 +++++++++++++++++++++---
drivers/net/ethernet/ti/cpsw_ale.h | 1 +
drivers/net/ethernet/ti/cpsw_switchdev.c | 2 +-
3 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c
index a6a455c32628..b1cce39eda17 100644
--- a/drivers/net/ethernet/ti/cpsw_ale.c
+++ b/drivers/net/ethernet/ti/cpsw_ale.c
@@ -634,8 +634,8 @@ int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port_mask, int untag,
return 0;
}

-static void cpsw_ale_del_vlan_modify(struct cpsw_ale *ale, u32 *ale_entry,
- u16 vid, int port_mask)
+static void cpsw_ale_vlan_del_modify_int(struct cpsw_ale *ale, u32 *ale_entry,
+ u16 vid, int port_mask)
{
int reg_mcast, unreg_mcast;
int members, untag;
@@ -644,6 +644,7 @@ static void cpsw_ale_del_vlan_modify(struct cpsw_ale *ale, u32 *ale_entry,
ALE_ENT_VID_MEMBER_LIST);
members &= ~port_mask;
if (!members) {
+ cpsw_ale_set_vlan_untag(ale, ale_entry, vid, 0);
cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
return;
}
@@ -673,6 +674,23 @@ static void cpsw_ale_del_vlan_modify(struct cpsw_ale *ale, u32 *ale_entry,
ALE_ENT_VID_MEMBER_LIST, members);
}

+int cpsw_ale_vlan_del_modify(struct cpsw_ale *ale, u16 vid, int port_mask)
+{
+ u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
+ int idx;
+
+ idx = cpsw_ale_match_vlan(ale, vid);
+ if (idx < 0)
+ return -ENOENT;
+
+ cpsw_ale_read(ale, idx, ale_entry);
+
+ cpsw_ale_vlan_del_modify_int(ale, ale_entry, vid, port_mask);
+ cpsw_ale_write(ale, idx, ale_entry);
+
+ return 0;
+}
+
int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port_mask)
{
u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
@@ -685,7 +703,7 @@ int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port_mask)
cpsw_ale_read(ale, idx, ale_entry);

if (port_mask) {
- cpsw_ale_del_vlan_modify(ale, ale_entry, vid, port_mask);
+ cpsw_ale_vlan_del_modify_int(ale, ale_entry, vid, port_mask);
} else {
cpsw_ale_set_vlan_untag(ale, ale_entry, vid, 0);
cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
diff --git a/drivers/net/ethernet/ti/cpsw_ale.h b/drivers/net/ethernet/ti/cpsw_ale.h
index 5e4a69662c5f..13fe47687fde 100644
--- a/drivers/net/ethernet/ti/cpsw_ale.h
+++ b/drivers/net/ethernet/ti/cpsw_ale.h
@@ -134,6 +134,7 @@ static inline int cpsw_ale_get_vlan_p0_untag(struct cpsw_ale *ale, u16 vid)

int cpsw_ale_vlan_add_modify(struct cpsw_ale *ale, u16 vid, int port_mask,
int untag_mask, int reg_mcast, int unreg_mcast);
+int cpsw_ale_vlan_del_modify(struct cpsw_ale *ale, u16 vid, int port_mask);
void cpsw_ale_set_unreg_mcast(struct cpsw_ale *ale, int unreg_mcast_mask,
bool add);

diff --git a/drivers/net/ethernet/ti/cpsw_switchdev.c b/drivers/net/ethernet/ti/cpsw_switchdev.c
index 985a929bb957..29747da5c514 100644
--- a/drivers/net/ethernet/ti/cpsw_switchdev.c
+++ b/drivers/net/ethernet/ti/cpsw_switchdev.c
@@ -227,7 +227,7 @@ static int cpsw_port_vlan_del(struct cpsw_priv *priv, u16 vid,
else
port_mask = BIT(priv->emac_port);

- ret = cpsw_ale_del_vlan(cpsw->ale, vid, port_mask);
+ ret = cpsw_ale_vlan_del_modify(cpsw->ale, vid, port_mask);
if (ret != 0)
return ret;

--
2.17.1

2020-10-01 10:57:50

by Grygorii Strashko

[permalink] [raw]
Subject: [PATCH net-next 5/8] net: ethernet: ti: am65-cpsw: fix vlan offload for multi mac mode

The VLAN offload for AM65x CPSW2G is implemented using existing ALE APIs,
which are also used by legacy CPSW drivers.
So, now it always adds current Ext. Port and Host as VLAN members when VLAN
is added by 8021Q core (.ndo_vlan_rx_add_vid) and forcibly removes VLAN
from ALE table in .ndo_vlan_rx_kill_vid(). This works as for AM65x CPSW2G
(which has only one Ext. Port) as for legacy CPSW devices (which can't
support same VLAN on more then one Port in multi mac (dual-mac) mode). But
it doesn't work for the new J721E and AM64x multi port CPSWxG versions
doesn't have such restrictions and allow to offload the same VLAN on any
number of ports.

Now the attempt to add same VLAN on two (or more) K3 CPSWxG Ports will
cause:
- VLAN members mask overwrite when VLAN is added
- VLAN removal from ALE table when any Port removes VLAN

This patch fixes an issue by:
- switching to use cpsw_ale_vlan_add_modify() instead of
cpsw_ale_add_vlan() when VLAN is added to ALE table, so VLAN members
mask will not be overwritten;
- Updates cpsw_ale_del_vlan() as:
if more than one ext. Port is in VLAN member mask
then remove only current port from VLAN member mask
else remove VLAN ALE entry

Example:
add: P1 | P0 (Host) -> members mask: P1 | P0
add: P2 | P0 -> members mask: P2 | P1 | P0
rem: P1 | P0 -> members mask: P2 | P0
rem: P2 | P0 -> members mask: -

The VLAN is forcibly removed if port_mask=0 passed to cpsw_ale_del_vlan()
to preserve existing legacy CPSW drivers functionality.

Signed-off-by: Grygorii Strashko <[email protected]>
---
drivers/net/ethernet/ti/am65-cpsw-nuss.c | 8 +++++---
drivers/net/ethernet/ti/cpsw_ale.c | 19 +++++++++++++++----
2 files changed, 20 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
index 65c5446e324e..fecaf6b8270f 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
@@ -241,8 +241,8 @@ static int am65_cpsw_nuss_ndo_slave_add_vid(struct net_device *ndev,
if (!vid)
unreg_mcast = port_mask;
dev_info(common->dev, "Adding vlan %d to vlan filter\n", vid);
- ret = cpsw_ale_add_vlan(common->ale, vid, port_mask,
- unreg_mcast, port_mask, 0);
+ ret = cpsw_ale_vlan_add_modify(common->ale, vid, port_mask,
+ unreg_mcast, port_mask, 0);

pm_runtime_put(common->dev);
return ret;
@@ -252,6 +252,7 @@ static int am65_cpsw_nuss_ndo_slave_kill_vid(struct net_device *ndev,
__be16 proto, u16 vid)
{
struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
+ struct am65_cpsw_port *port = am65_ndev_to_port(ndev);
int ret;

if (!netif_running(ndev) || !vid)
@@ -264,7 +265,8 @@ static int am65_cpsw_nuss_ndo_slave_kill_vid(struct net_device *ndev,
}

dev_info(common->dev, "Removing vlan %d from vlan filter\n", vid);
- ret = cpsw_ale_del_vlan(common->ale, vid, 0);
+ ret = cpsw_ale_del_vlan(common->ale, vid,
+ BIT(port->port_id) | ALE_PORT_HOST);

pm_runtime_put(common->dev);
return ret;
diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c
index b1cce39eda17..cdc308a2aa3e 100644
--- a/drivers/net/ethernet/ti/cpsw_ale.c
+++ b/drivers/net/ethernet/ti/cpsw_ale.c
@@ -694,7 +694,7 @@ int cpsw_ale_vlan_del_modify(struct cpsw_ale *ale, u16 vid, int port_mask)
int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port_mask)
{
u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
- int idx;
+ int members, idx;

idx = cpsw_ale_match_vlan(ale, vid);
if (idx < 0)
@@ -702,11 +702,22 @@ int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port_mask)

cpsw_ale_read(ale, idx, ale_entry);

- if (port_mask) {
- cpsw_ale_vlan_del_modify_int(ale, ale_entry, vid, port_mask);
- } else {
+ /* if !port_mask - force remove VLAN (legacy).
+ * Check if there are other VLAN members ports
+ * if no - remove VLAN.
+ * if yes it means same VLAN was added to >1 port in multi port mode, so
+ * remove port_mask ports from VLAN ALE entry excluding Host port.
+ */
+ members = cpsw_ale_vlan_get_fld(ale, ale_entry, ALE_ENT_VID_MEMBER_LIST);
+ members &= ~port_mask;
+
+ if (!port_mask || !members) {
+ /* last port or force remove - remove VLAN */
cpsw_ale_set_vlan_untag(ale, ale_entry, vid, 0);
cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
+ } else {
+ port_mask &= ~ALE_PORT_HOST;
+ cpsw_ale_vlan_del_modify_int(ale, ale_entry, vid, port_mask);
}

cpsw_ale_write(ale, idx, ale_entry);
--
2.17.1

2020-10-01 10:58:00

by Grygorii Strashko

[permalink] [raw]
Subject: [PATCH net-next 6/8] net: ethernet: ti: am65-cpsw: keep active if cpts enabled

Some K3 CPSW NUSS instances can lose context after PM runtime ON->OFF->ON
transition depending on integration (including all submodules: CPTS, MDIO,
etc), like J721E Main CPSW (CPSW9G).

In case CPTS is enabled it's initialized during probe and does not expect
to be reset. Hence, keep K3 CPSW active by forbidding PM runtime if CPTS is
enabled.

Signed-off-by: Grygorii Strashko <[email protected]>
---
drivers/net/ethernet/ti/am65-cpsw-nuss.c | 7 +++++++
1 file changed, 7 insertions(+)

diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
index fecaf6b8270f..0bc0eec46709 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
@@ -1727,6 +1727,13 @@ static int am65_cpsw_init_cpts(struct am65_cpsw_common *common)
return ret;
}
common->cpts = cpts;
+ /* Forbid PM runtime if CPTS is running.
+ * K3 CPSWxG modules may completely lose context during ON->OFF
+ * transitions depending on integration.
+ * AM65x/J721E MCU CPSW2G: false
+ * J721E MAIN_CPSW9G: true
+ */
+ pm_runtime_forbid(dev);

return 0;
}
--
2.17.1

2020-10-01 10:58:11

by Grygorii Strashko

[permalink] [raw]
Subject: [PATCH net-next 7/8] net: ethernet: ti: am65-cpsw: prepare xmit/rx path for multi-port devices in mac-only mode

This patch adds multi-port support to TI AM65x CPSW driver xmit/rx path in
preparation for adding support for multi-port devices, like Main CPSW0 on
K3 J721E SoC or future CPSW3g on K3 AM64x SoC.
Hence DMA channels are common/shared for all ext Ports and the RX/TX NAPI
and DMA processing going to be assigned to first netdev this patch:
- ensures all RX descriptors fields are initialized;
- adds synchronization for TX DMA push/pop operation (locking) as
Networking core is not enough any more;
- updates TX bql processing for every packet in
am65_cpsw_nuss_tx_compl_packets() as every completed TX skb can have
different ndev assigned (come from different netdevs).

Signed-off-by: Grygorii Strashko <[email protected]>
---
drivers/net/ethernet/ti/am65-cpsw-nuss.c | 41 +++++++++++++-----------
drivers/net/ethernet/ti/am65-cpsw-nuss.h | 1 +
2 files changed, 23 insertions(+), 19 deletions(-)

diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
index 0bc0eec46709..a8094e8e49ca 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
@@ -375,7 +375,7 @@ static int am65_cpsw_nuss_rx_push(struct am65_cpsw_common *common,

cppi5_hdesc_init(desc_rx, CPPI5_INFO0_HDESC_EPIB_PRESENT,
AM65_CPSW_NAV_PS_DATA_SIZE);
- cppi5_hdesc_attach_buf(desc_rx, 0, 0, buf_dma, skb_tailroom(skb));
+ cppi5_hdesc_attach_buf(desc_rx, buf_dma, skb_tailroom(skb), buf_dma, skb_tailroom(skb));
swdata = cppi5_hdesc_get_swdata(desc_rx);
*((void **)swdata) = skb;

@@ -933,7 +933,9 @@ static int am65_cpsw_nuss_tx_compl_packets(struct am65_cpsw_common *common,
struct am65_cpsw_ndev_priv *ndev_priv;
struct am65_cpsw_ndev_stats *stats;

+ spin_lock(&tx_chn->lock);
res = k3_udma_glue_pop_tx_chn(tx_chn->tx_chn, &desc_dma);
+ spin_unlock(&tx_chn->lock);
if (res == -ENODATA)
break;

@@ -960,31 +962,29 @@ static int am65_cpsw_nuss_tx_compl_packets(struct am65_cpsw_common *common,
stats->tx_bytes += skb->len;
u64_stats_update_end(&stats->syncp);

- total_bytes += skb->len;
+ total_bytes = skb->len;
napi_consume_skb(skb, budget);
num_tx++;
- }
-
- if (!num_tx)
- return 0;

- netif_txq = netdev_get_tx_queue(ndev, chn);
+ netif_txq = netdev_get_tx_queue(ndev, chn);

- netdev_tx_completed_queue(netif_txq, num_tx, total_bytes);
+ netdev_tx_completed_queue(netif_txq, num_tx, total_bytes);

- if (netif_tx_queue_stopped(netif_txq)) {
- /* Check whether the queue is stopped due to stalled tx dma,
- * if the queue is stopped then wake the queue as
- * we have free desc for tx
- */
- __netif_tx_lock(netif_txq, smp_processor_id());
- if (netif_running(ndev) &&
- (k3_cppi_desc_pool_avail(tx_chn->desc_pool) >=
- MAX_SKB_FRAGS))
- netif_tx_wake_queue(netif_txq);
+ if (netif_tx_queue_stopped(netif_txq)) {
+ /* Check whether the queue is stopped due to stalled
+ * tx dma, if the queue is stopped then wake the queue
+ * as we have free desc for tx
+ */
+ __netif_tx_lock(netif_txq, smp_processor_id());
+ if (netif_running(ndev) &&
+ (k3_cppi_desc_pool_avail(tx_chn->desc_pool) >=
+ MAX_SKB_FRAGS))
+ netif_tx_wake_queue(netif_txq);

- __netif_tx_unlock(netif_txq);
+ __netif_tx_unlock(netif_txq);
+ }
}
+
dev_dbg(dev, "%s:%u pkt:%d\n", __func__, chn, num_tx);

return num_tx;
@@ -1141,7 +1141,9 @@ static netdev_tx_t am65_cpsw_nuss_ndo_slave_xmit(struct sk_buff *skb,

cppi5_hdesc_set_pktlen(first_desc, pkt_len);
desc_dma = k3_cppi_desc_pool_virt2dma(tx_chn->desc_pool, first_desc);
+ spin_lock_bh(&tx_chn->lock);
ret = k3_udma_glue_push_tx_chn(tx_chn->tx_chn, first_desc, desc_dma);
+ spin_unlock_bh(&tx_chn->lock);
if (ret) {
dev_err(dev, "can't push desc %d\n", ret);
/* inform bql */
@@ -1498,6 +1500,7 @@ static int am65_cpsw_nuss_init_tx_chns(struct am65_cpsw_common *common)
snprintf(tx_chn->tx_chn_name,
sizeof(tx_chn->tx_chn_name), "tx%d", i);

+ spin_lock_init(&tx_chn->lock);
tx_chn->common = common;
tx_chn->id = i;
tx_chn->descs_num = max_desc_num;
diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.h b/drivers/net/ethernet/ti/am65-cpsw-nuss.h
index b6f228ddc3a0..8e0dc5728253 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.h
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.h
@@ -60,6 +60,7 @@ struct am65_cpsw_tx_chn {
struct am65_cpsw_common *common;
struct k3_cppi_desc_pool *desc_pool;
struct k3_udma_glue_tx_channel *tx_chn;
+ spinlock_t lock; /* protect TX rings in multi-port mode */
int irq;
u32 id;
u32 descs_num;
--
2.17.1

2020-10-01 23:12:12

by Jakub Kicinski

[permalink] [raw]
Subject: Re: [PATCH net-next 0/8] net: ethernet: ti: am65-cpsw: add multi port support in mac-only mode

On Thu, 1 Oct 2020 13:52:50 +0300 Grygorii Strashko wrote:
> This series adds multi-port support in mac-only mode (multi MAC mode) to TI
> AM65x CPSW driver in preparation for enabling support for multi-port devices,
> like Main CPSW0 on K3 J721E SoC or future CPSW3g on K3 AM64x SoC.
>
> The multi MAC mode is implemented by configuring every enabled port in "mac-only"
> mode (all ingress packets are sent only to the Host port and egress packets
> directed to target Ext. Port) and creating separate net_device for
> every enabled Ext. port.

Do I get it right that you select the mode based on platform? Can the
other mode still be supported on these platforms?

Is this a transition to normal DSA mode where ports always have netdevs?

2020-10-02 09:59:13

by Grygorii Strashko

[permalink] [raw]
Subject: Re: [PATCH net-next 0/8] net: ethernet: ti: am65-cpsw: add multi port support in mac-only mode



On 02/10/2020 02:08, Jakub Kicinski wrote:
> On Thu, 1 Oct 2020 13:52:50 +0300 Grygorii Strashko wrote:
>> This series adds multi-port support in mac-only mode (multi MAC mode) to TI
>> AM65x CPSW driver in preparation for enabling support for multi-port devices,
>> like Main CPSW0 on K3 J721E SoC or future CPSW3g on K3 AM64x SoC.
>>
>> The multi MAC mode is implemented by configuring every enabled port in "mac-only"
>> mode (all ingress packets are sent only to the Host port and egress packets
>> directed to target Ext. Port) and creating separate net_device for
>> every enabled Ext. port.
>
> Do I get it right that you select the mode based on platform? Can the
> other mode still be supported on these platforms?
>
> Is this a transition to normal DSA mode where ports always have netdevs?
>

The idea here is to start in multi mac mode by default, as we still have pretty high demand for this.
Then, and we are working on it, the switchdev mode is going to be introduces (not DSA).
The switch between modes will happen by using devlink option -
the approach is similar to what was used for Sitara CPSW cpsw_new.c driver [1].

[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/net/ethernet/ti/cpsw_new.c
--
Best regards,
grygorii

2020-10-02 23:07:48

by Jakub Kicinski

[permalink] [raw]
Subject: Re: [PATCH net-next 0/8] net: ethernet: ti: am65-cpsw: add multi port support in mac-only mode

On Fri, 2 Oct 2020 12:56:43 +0300 Grygorii Strashko wrote:
> On 02/10/2020 02:08, Jakub Kicinski wrote:
> > On Thu, 1 Oct 2020 13:52:50 +0300 Grygorii Strashko wrote:
> >> This series adds multi-port support in mac-only mode (multi MAC mode) to TI
> >> AM65x CPSW driver in preparation for enabling support for multi-port devices,
> >> like Main CPSW0 on K3 J721E SoC or future CPSW3g on K3 AM64x SoC.
> >>
> >> The multi MAC mode is implemented by configuring every enabled port in "mac-only"
> >> mode (all ingress packets are sent only to the Host port and egress packets
> >> directed to target Ext. Port) and creating separate net_device for
> >> every enabled Ext. port.
> >
> > Do I get it right that you select the mode based on platform? Can the
> > other mode still be supported on these platforms?
> >
> > Is this a transition to normal DSA mode where ports always have netdevs?
>
> The idea here is to start in multi mac mode by default, as we still
> have pretty high demand for this. Then, and we are working on it, the
> switchdev mode is going to be introduces (not DSA). The switch
> between modes will happen by using devlink option - the approach is
> similar to what was used for Sitara CPSW cpsw_new.c driver [1].

What's unclear from the patches is whether the default configuration
for already supported platforms will change?

All the patches sound like they are "in preparation for support of K3
J721E" etc. So this is just code restructuring with no user-visible
changes?

2020-10-02 23:11:20

by Jakub Kicinski

[permalink] [raw]
Subject: Re: [PATCH net-next 0/8] net: ethernet: ti: am65-cpsw: add multi port support in mac-only mode

On Fri, 2 Oct 2020 16:04:21 -0700 Jakub Kicinski wrote:
> On Fri, 2 Oct 2020 12:56:43 +0300 Grygorii Strashko wrote:
> > On 02/10/2020 02:08, Jakub Kicinski wrote:
> > > On Thu, 1 Oct 2020 13:52:50 +0300 Grygorii Strashko wrote:
> > >> This series adds multi-port support in mac-only mode (multi MAC mode) to TI
> > >> AM65x CPSW driver in preparation for enabling support for multi-port devices,
> > >> like Main CPSW0 on K3 J721E SoC or future CPSW3g on K3 AM64x SoC.
> > >>
> > >> The multi MAC mode is implemented by configuring every enabled port in "mac-only"
> > >> mode (all ingress packets are sent only to the Host port and egress packets
> > >> directed to target Ext. Port) and creating separate net_device for
> > >> every enabled Ext. port.
> > >
> > > Do I get it right that you select the mode based on platform? Can the
> > > other mode still be supported on these platforms?
> > >
> > > Is this a transition to normal DSA mode where ports always have netdevs?
> >
> > The idea here is to start in multi mac mode by default, as we still
> > have pretty high demand for this. Then, and we are working on it, the
> > switchdev mode is going to be introduces (not DSA). The switch
> > between modes will happen by using devlink option - the approach is
> > similar to what was used for Sitara CPSW cpsw_new.c driver [1].
>
> What's unclear from the patches is whether the default configuration
> for already supported platforms will change?
>
> All the patches sound like they are "in preparation for support of K3
> J721E" etc. So this is just code restructuring with no user-visible
> changes?

Another way of putting the question perhaps would be - is num_ports
always 1 for existing platforms?

2020-10-03 02:10:48

by David Miller

[permalink] [raw]
Subject: Re: [PATCH net-next 7/8] net: ethernet: ti: am65-cpsw: prepare xmit/rx path for multi-port devices in mac-only mode

From: Grygorii Strashko <[email protected]>
Date: Thu, 1 Oct 2020 13:52:57 +0300

> This patch adds multi-port support to TI AM65x CPSW driver xmit/rx path in
> preparation for adding support for multi-port devices, like Main CPSW0 on
> K3 J721E SoC or future CPSW3g on K3 AM64x SoC.
> Hence DMA channels are common/shared for all ext Ports and the RX/TX NAPI
> and DMA processing going to be assigned to first netdev this patch:
> - ensures all RX descriptors fields are initialized;
> - adds synchronization for TX DMA push/pop operation (locking) as
> Networking core is not enough any more;
> - updates TX bql processing for every packet in
> am65_cpsw_nuss_tx_compl_packets() as every completed TX skb can have
> different ndev assigned (come from different netdevs).
>
> Signed-off-by: Grygorii Strashko <[email protected]>

This locking is unnecessary in single-port non-shared DMA situations
and therefore will impose unnecessary performance loss for basically
all existing supported setups.

Please do this another way.

In fact, I would encourage you to find a way to avoid the new atomic
operations even in multi-port configurations.

Thank you.

2020-10-05 10:18:05

by Grygorii Strashko

[permalink] [raw]
Subject: Re: [PATCH net-next 0/8] net: ethernet: ti: am65-cpsw: add multi port support in mac-only mode



On 03/10/2020 02:07, Jakub Kicinski wrote:
> On Fri, 2 Oct 2020 16:04:21 -0700 Jakub Kicinski wrote:
>> On Fri, 2 Oct 2020 12:56:43 +0300 Grygorii Strashko wrote:
>>> On 02/10/2020 02:08, Jakub Kicinski wrote:
>>>> On Thu, 1 Oct 2020 13:52:50 +0300 Grygorii Strashko wrote:
>>>>> This series adds multi-port support in mac-only mode (multi MAC mode) to TI
>>>>> AM65x CPSW driver in preparation for enabling support for multi-port devices,
>>>>> like Main CPSW0 on K3 J721E SoC or future CPSW3g on K3 AM64x SoC.
>>>>>
>>>>> The multi MAC mode is implemented by configuring every enabled port in "mac-only"
>>>>> mode (all ingress packets are sent only to the Host port and egress packets
>>>>> directed to target Ext. Port) and creating separate net_device for
>>>>> every enabled Ext. port.
>>>>
>>>> Do I get it right that you select the mode based on platform? Can the
>>>> other mode still be supported on these platforms?
>>>>
>>>> Is this a transition to normal DSA mode where ports always have netdevs?
>>>
>>> The idea here is to start in multi mac mode by default, as we still
>>> have pretty high demand for this. Then, and we are working on it, the
>>> switchdev mode is going to be introduces (not DSA). The switch
>>> between modes will happen by using devlink option - the approach is
>>> similar to what was used for Sitara CPSW cpsw_new.c driver [1].
>>
>> What's unclear from the patches is whether the default configuration
>> for already supported platforms will change?
>>
>> All the patches sound like they are "in preparation for support of K3
>> J721E" etc. So this is just code restructuring with no user-visible
>> changes?
>
> Another way of putting the question perhaps would be - is num_ports
> always 1 for existing platforms?
>

Yes. Sorry for confusion - all now supported K3 CPSW instances have 1 external port and
these changes should not have affect on them.

--
Best regards,
grygorii

2020-10-05 10:32:16

by Grygorii Strashko

[permalink] [raw]
Subject: Re: [PATCH net-next 7/8] net: ethernet: ti: am65-cpsw: prepare xmit/rx path for multi-port devices in mac-only mode



On 03/10/2020 05:09, David Miller wrote:
> From: Grygorii Strashko <[email protected]>
> Date: Thu, 1 Oct 2020 13:52:57 +0300
>
>> This patch adds multi-port support to TI AM65x CPSW driver xmit/rx path in
>> preparation for adding support for multi-port devices, like Main CPSW0 on
>> K3 J721E SoC or future CPSW3g on K3 AM64x SoC.
>> Hence DMA channels are common/shared for all ext Ports and the RX/TX NAPI
>> and DMA processing going to be assigned to first netdev this patch:
>> - ensures all RX descriptors fields are initialized;
>> - adds synchronization for TX DMA push/pop operation (locking) as
>> Networking core is not enough any more;
>> - updates TX bql processing for every packet in
>> am65_cpsw_nuss_tx_compl_packets() as every completed TX skb can have
>> different ndev assigned (come from different netdevs).
>>
>> Signed-off-by: Grygorii Strashko <[email protected]>
>
> This locking is unnecessary in single-port non-shared DMA situations
> and therefore will impose unnecessary performance loss for basically
> all existing supported setups.
>
> Please do this another way.

ok. I'll try add lock-less push/pop operations and use them for single-port

>
> In fact, I would encourage you to find a way to avoid the new atomic
> operations even in multi-port configurations.

I'm not sure I how :( The DMA channels are shared, while net_device TX queues are separate.
I've thought - hence there is 8 TX DMA channels it should be possible to use qdisc,
like mqprio to segregate traffic between ports and TX DMA channels in which case no
blocking on tx dma locks should happen in .xmit().

Thank you.
--
Best regards,
grygorii