From 930a38fd7879509db13098f50144226ebc32249b Mon Sep 17 00:00:00 2001 From: Leonid Komarianskyi Date: Fri, 22 Dec 2023 10:35:26 +0200 Subject: [PATCH 1/6] net: renesas: rswitch: do not set IRQ delay for TSNs IRQ delays were introduced because without them VMQs perform a lot of interrupts. This mechanism is needed for VMQs to reduce the amount of interrupts and as a result, improve performance. On the other hand, any delays, while using TSNs lead to bandwidth reduction, so in such cases delay should be zeroed. Signed-off-by: Leonid Komarianskyi Reviewed-by: Dmytro Firsov --- drivers/net/ethernet/renesas/rswitch_xenback.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/renesas/rswitch_xenback.c b/drivers/net/ethernet/renesas/rswitch_xenback.c index d1b95afd9061fb..46d14042613c0b 100644 --- a/drivers/net/ethernet/renesas/rswitch_xenback.c +++ b/drivers/net/ethernet/renesas/rswitch_xenback.c @@ -212,9 +212,6 @@ static int rswitch_vmq_back_probe(struct xenbus_device *dev, be->tx_chain->osid = be->osid; be->rx_chain->osid = be->osid; - rswitch_gwca_chain_set_irq_delay(priv, be->tx_chain, chain_irq_delay); - rswitch_gwca_chain_set_irq_delay(priv, be->rx_chain, chain_irq_delay); - snprintf(be->name, sizeof(be->name) - 1, "rswitch-vmq-osid%d", be->osid); be->if_num = xenbus_read_unsigned(dev->otherend, "if-num", 255); @@ -232,6 +229,8 @@ static int rswitch_vmq_back_probe(struct xenbus_device *dev, err); goto fail; } + rswitch_gwca_chain_set_irq_delay(priv, be->tx_chain, chain_irq_delay); + rswitch_gwca_chain_set_irq_delay(priv, be->rx_chain, chain_irq_delay); } else if (strcmp(type_str, "tsn") == 0) { struct rswitch_device *rdev = rswitch_find_rdev_by_port(be->rswitch_priv, @@ -249,6 +248,8 @@ static int rswitch_vmq_back_probe(struct xenbus_device *dev, err = -ENODEV; goto fail; } + rswitch_gwca_chain_set_irq_delay(priv, be->tx_chain, 0); + rswitch_gwca_chain_set_irq_delay(priv, be->rx_chain, 0); be->type = RSWITCH_PV_TSN; netif_dormant_on(rdev->ndev); From 90891a1194e4f69ded355123c9fc7a4e46bb9ea4 Mon Sep 17 00:00:00 2001 From: Leonid Komarianskyi Date: Wed, 17 Jan 2024 13:10:30 +0200 Subject: [PATCH 2/6] [WIP] separate napi tx and rx DomD and DomU work fine, reduced performance due to previous version down to ~10%. Signed-off-by: Leonid Komarianskyi --- drivers/net/ethernet/renesas/rswitch.c | 101 +++++++++++++----- drivers/net/ethernet/renesas/rswitch.h | 2 + .../net/ethernet/renesas/rswitch_xenback.c | 2 + .../net/ethernet/renesas/rswitch_xenfront.c | 4 +- 4 files changed, 83 insertions(+), 26 deletions(-) diff --git a/drivers/net/ethernet/renesas/rswitch.c b/drivers/net/ethernet/renesas/rswitch.c index 4d7b2ca3404e97..26e036d4c87c1e 100644 --- a/drivers/net/ethernet/renesas/rswitch.c +++ b/drivers/net/ethernet/renesas/rswitch.c @@ -1154,8 +1154,6 @@ void rswitch_enadis_rdev_irqs(struct rswitch_device *rdev, bool enable) if (rdev->rx_learning_chain) rswitch_enadis_data_irq(rdev->priv, rdev->rx_learning_chain->index, enable); - rswitch_enadis_data_irq(rdev->priv, rdev->tx_chain->index, - enable); } else { if (enable) rswitch_vmq_front_rx_done(rdev); @@ -1439,6 +1437,31 @@ int rswitch_tx_free(struct net_device *ndev, bool free_txed_only) return free_num; } +int rswitch_tx_poll(struct napi_struct *napi, int budget) +{ + struct net_device *ndev = napi->dev; + struct rswitch_device *rdev = ndev_to_rdev(ndev); + struct rswitch_private *priv = rdev->priv; + int num; + unsigned long flags; + + num = rswitch_tx_free(ndev, true); + /* We have free descriptors to process new TX packages */ + if (budget && napi_complete_done(napi, num)) { + if (!rswitch_is_front_dev(rdev)) { + spin_lock_irqsave(&priv->lock, flags); + rswitch_enadis_data_irq(rdev->priv, rdev->tx_chain->index, + true); + spin_unlock_irqrestore(&priv->lock, flags); + } else { + rswitch_vmq_front_trigger_tx(rdev); + } + } + netif_wake_subqueue(ndev, 0); + + return min(num, budget - 1); +} + int rswitch_poll(struct napi_struct *napi, int budget) { struct net_device *ndev = napi->dev; @@ -1448,7 +1471,6 @@ int rswitch_poll(struct napi_struct *napi, int budget) int quota = budget; retry: - rswitch_tx_free(ndev, true); if (rswitch_rx(ndev, "a)) goto out; @@ -1457,8 +1479,6 @@ int rswitch_poll(struct napi_struct *napi, int budget) else if (rdev->rx_learning_chain && rswitch_is_chain_rxed(rdev->rx_learning_chain, DT_FEMPTY)) goto retry; - netif_wake_subqueue(ndev, 0); - if (napi_complete_done(napi, budget - quota)) { spin_lock_irqsave(&priv->lock, flags); /* Re-enable RX/TX interrupts */ @@ -2232,6 +2252,7 @@ static int rswitch_open(struct net_device *ndev) unsigned long flags; napi_enable(&rdev->napi); + napi_enable(&rdev->tx_napi); if (!parallel_mode && rdev->etha) { if (!rdev->etha->operated) { @@ -2311,6 +2332,7 @@ static int rswitch_open(struct net_device *ndev) phy_stop(ndev->phydev); rswitch_phy_deinit(rdev); rswitch_mii_unregister(rdev); + napi_disable(&rdev->tx_napi); napi_disable(&rdev->napi); goto out; }; @@ -2324,6 +2346,7 @@ static int rswitch_stop(struct net_device *ndev) phy_stop(ndev->phydev); napi_disable(&rdev->napi); + napi_disable(&rdev->tx_napi); if (!rswitch_is_front_dev(rdev)) { rdev->priv->chan_running &= ~BIT(rdev->port); @@ -4190,6 +4213,7 @@ static int rswitch_ndev_create(struct rswitch_private *priv, int index, bool rmo ndev->netdev_ops = &rswitch_netdev_ops; netif_napi_add(ndev, &rdev->napi, rswitch_poll, 64); + netif_tx_napi_add(ndev, &rdev->tx_napi, rswitch_tx_poll, 64); /* FIXME: it seems S4 VPF has FWPBFCSDC0/1 only so that we cannot set * CSD = 1 (rx_default_chain->index = 1) for FWPBFCS03. So, use index = 0 @@ -4236,6 +4260,7 @@ static int rswitch_ndev_create(struct rswitch_private *priv, int index, bool rmo rswitch_rxdmac_free(ndev, priv); out_rxdmac: + netif_napi_del(&rdev->tx_napi); netif_napi_del(&rdev->napi); free_netdev(ndev); @@ -4277,12 +4302,39 @@ static void rswitch_coma_init(struct rswitch_private *priv) iowrite32(CABPPFLC_INIT_VALUE, priv->addr + CABPPFLC0); } -static void rswitch_queue_interrupt(struct rswitch_device *rdev) +static void rswitch_queue_rmon_interrupt(struct rswitch_gwca_chain *c) { - if (!rdev->mondev) { - if (napi_schedule_prep(&rdev->napi)) { + struct rswitch_device *rdev = c->rdev; + struct rswitch_private *priv = rdev->priv; + int i; + + /* Schedule napi for all rmon devices as they share the same chain. */ + for (i = 0; i < RSWITCH_MAX_RMON_DEV; i++) { + if (priv->rmon_dev[i] && napi_schedule_prep(&priv->rmon_dev[i]->napi)) { + spin_lock(&rdev->priv->lock); + rswitch_enadis_data_irq(priv->rmon_dev[i]->priv, + priv->rmon_dev[i]->rx_default_chain->index, + false); + spin_unlock(&rdev->priv->lock); + __napi_schedule(&priv->rmon_dev[i]->napi); + } + } +} + +static void rswitch_queue_rdev_interrupt(struct rswitch_gwca_chain *c) +{ + struct rswitch_device *rdev = c->rdev; + + if (c->dir_tx) { + if (napi_schedule_prep(&rdev->tx_napi)) { spin_lock(&rdev->priv->lock); rswitch_enadis_data_irq(rdev->priv, rdev->tx_chain->index, false); + spin_unlock(&rdev->priv->lock); + __napi_schedule(&rdev->tx_napi); + } + } else { + if (napi_schedule_prep(&rdev->napi)) { + spin_lock(&rdev->priv->lock); rswitch_enadis_data_irq(rdev->priv, rdev->rx_default_chain->index, false); if (rdev->rx_learning_chain) { rswitch_enadis_data_irq(rdev->priv, @@ -4291,23 +4343,18 @@ static void rswitch_queue_interrupt(struct rswitch_device *rdev) spin_unlock(&rdev->priv->lock); __napi_schedule(&rdev->napi); } - } else { - struct rswitch_private *priv = rdev->priv; - int i; + } + +} - /* Schedule napi for all rmon devices as - * they share the same chain. - */ - for (i = 0; i < RSWITCH_MAX_RMON_DEV; i++) { - if (priv->rmon_dev[i] && napi_schedule_prep(&priv->rmon_dev[i]->napi)) { - spin_lock(&rdev->priv->lock); - rswitch_enadis_data_irq(priv->rmon_dev[i]->priv, - priv->rmon_dev[i]->rx_default_chain->index, - false); - spin_unlock(&rdev->priv->lock); - __napi_schedule(&priv->rmon_dev[i]->napi); - } - } +static void rswitch_queue_interrupt(struct rswitch_gwca_chain *c) +{ + struct rswitch_device *rdev = c->rdev; + + if (!rdev->mondev) { + rswitch_queue_rdev_interrupt(c); + } else { + rswitch_queue_rmon_interrupt(c); } } @@ -4326,7 +4373,7 @@ static irqreturn_t __maybe_unused rswitch_data_irq(struct rswitch_private *priv, rswitch_ack_data_irq(priv, c->index); if (!c->back_info) - rswitch_queue_interrupt(c->rdev); + rswitch_queue_interrupt(c); else rswitch_vmq_back_data_irq(c); } @@ -4977,8 +5024,10 @@ static int vlan_dev_register(struct net_device *ndev) goto err_rx; netif_napi_add(ndev, &rdev->napi, rswitch_poll, 64); + netif_tx_napi_add(ndev, &rdev->tx_napi, rswitch_tx_poll, 64); netdev_info(ndev, "MAC address %pMn", ndev->dev_addr); napi_enable(&rdev->napi); + napi_enable(&rdev->tx_napi); return 0; err_rx: rswitch_txdmac_free(ndev, priv); @@ -5037,6 +5086,8 @@ static void vlan_dev_unregister(struct net_device *ndev) rdev = ndev_to_rdev(ndev); rswitch_rxdmac_free(ndev, priv); rswitch_txdmac_free(ndev, priv); + napi_disable(&rdev->tx_napi); + netif_napi_del(&rdev->tx_napi); napi_disable(&rdev->napi); netif_napi_del(&rdev->napi); diff --git a/drivers/net/ethernet/renesas/rswitch.h b/drivers/net/ethernet/renesas/rswitch.h index b54e2e14e253c1..1ea0d506cfe262 100644 --- a/drivers/net/ethernet/renesas/rswitch.h +++ b/drivers/net/ethernet/renesas/rswitch.h @@ -280,6 +280,7 @@ struct rswitch_device { struct rswitch_private *priv; struct net_device *ndev; struct napi_struct napi; + struct napi_struct tx_napi; void __iomem *addr; struct rswitch_gwca_chain *tx_chain; struct rswitch_gwca_chain *rx_default_chain; @@ -448,6 +449,7 @@ void rswitch_rxdmac_free(struct net_device *ndev, struct rswitch_private *priv); void rswitch_ndev_unregister(struct rswitch_device *rdev, int index); int rswitch_poll(struct napi_struct *napi, int budget); +int rswitch_tx_poll(struct napi_struct *napi, int budget); int rswitch_tx_free(struct net_device *ndev, bool free_txed_only); void rswitch_gwca_chain_register(struct rswitch_private *priv, diff --git a/drivers/net/ethernet/renesas/rswitch_xenback.c b/drivers/net/ethernet/renesas/rswitch_xenback.c index 46d14042613c0b..97bde28116115e 100644 --- a/drivers/net/ethernet/renesas/rswitch_xenback.c +++ b/drivers/net/ethernet/renesas/rswitch_xenback.c @@ -90,6 +90,7 @@ rswitch_vmq_back_ndev_register(struct rswitch_private *priv, int index) ndev->netdev_ops = &rswitch_netdev_ops; netif_napi_add(ndev, &rdev->napi, rswitch_poll, 64); + netif_tx_napi_add(ndev, &rdev->tx_napi, rswitch_tx_poll, 64); eth_hw_addr_random(ndev); @@ -111,6 +112,7 @@ rswitch_vmq_back_ndev_register(struct rswitch_private *priv, int index) rswitch_rxdmac_free(ndev, priv); out_rxdmac: + netif_napi_del(&rdev->tx_napi); netif_napi_del(&rdev->napi); free_netdev(ndev); diff --git a/drivers/net/ethernet/renesas/rswitch_xenfront.c b/drivers/net/ethernet/renesas/rswitch_xenfront.c index 52021a176471f8..5d5361a72c0151 100644 --- a/drivers/net/ethernet/renesas/rswitch_xenfront.c +++ b/drivers/net/ethernet/renesas/rswitch_xenfront.c @@ -117,6 +117,7 @@ static int rswitch_vmq_front_ndev_register(struct rswitch_device *rdev, rdev->port = rdev->priv->gwca.index; netif_napi_add(ndev, &rdev->napi, rswitch_poll, 64); + netif_tx_napi_add(ndev, &rdev->tx_napi, rswitch_tx_poll, 64); if (!mac) eth_hw_addr_random(ndev); @@ -148,6 +149,7 @@ static int rswitch_vmq_front_ndev_register(struct rswitch_device *rdev, rswitch_rxdmac_free(ndev, NULL); out_rxdmac: + netif_napi_del(&rdev->tx_napi); netif_napi_del(&rdev->napi); return err; @@ -166,7 +168,7 @@ static irqreturn_t rswitch_vmq_front_tx_interrupt(int irq, void *dev_id) { struct rswitch_device *rdev = dev_id; - napi_schedule(&rdev->napi); + napi_schedule(&rdev->tx_napi); /* TODO: This is better, but there is a possibility for locking issues */ /* rswitch_tx_free(rdev->ndev, true); */ From 108ef12054f9ee5150511f2aa7de2537af49202d Mon Sep 17 00:00:00 2001 From: Leonid Komarianskyi Date: Wed, 31 Jan 2024 14:14:18 +0200 Subject: [PATCH 3/6] [WIP] add per-domain synchronization between VMQ tx->rx chains Signed-off-by: Leonid Komarianskyi --- drivers/net/ethernet/renesas/rswitch.c | 53 +++++++++++++++++++ drivers/net/ethernet/renesas/rswitch.h | 8 +++ .../net/ethernet/renesas/rswitch_xenback.c | 22 ++++++++ .../net/ethernet/renesas/rswitch_xenfront.c | 27 ++++++++++ 4 files changed, 110 insertions(+) diff --git a/drivers/net/ethernet/renesas/rswitch.c b/drivers/net/ethernet/renesas/rswitch.c index 26e036d4c87c1e..dc60f51f14b848 100644 --- a/drivers/net/ethernet/renesas/rswitch.c +++ b/drivers/net/ethernet/renesas/rswitch.c @@ -1205,6 +1205,7 @@ static bool rswitch_rx_chain(struct net_device *ndev, int *quota, struct rswitch struct rswitch_device *rdev = ndev_to_rdev(ndev); struct rswitch_private *priv = rdev->priv; int boguscnt = c->dirty + c->num_ring - c->cur; + int rx_counter = 0; int entry = c->cur % c->num_ring; struct rswitch_ext_ts_desc *desc = &c->rx_ring[entry]; int limit; @@ -1212,6 +1213,7 @@ static bool rswitch_rx_chain(struct net_device *ndev, int *quota, struct rswitch struct sk_buff *skb; dma_addr_t dma_addr; u32 get_ts; + u64 rxed = 0; boguscnt = min(boguscnt, *quota); limit = boguscnt; @@ -1346,6 +1348,8 @@ static bool rswitch_rx_chain(struct net_device *ndev, int *quota, struct rswitch napi_gro_receive(&rdev->napi, skb); rdev->ndev->stats.rx_packets++; rdev->ndev->stats.rx_bytes += pkt_len; + if (rdev->is_vmq) + rx_counter++; next: c->rx_bufs[entry] = NULL; @@ -1378,6 +1382,19 @@ static bool rswitch_rx_chain(struct net_device *ndev, int *quota, struct rswitch desc->die_dt = DT_FEMPTY | DIE; } + if (rdev->is_vmq) { + if (rswitch_is_front_dev(rdev)) { + rxed = READ_ONCE(rdev->vmq_info->front_rx); + rxed += rx_counter; + WRITE_ONCE(rdev->vmq_info->front_rx, rxed); + } else { + rxed = READ_ONCE(rdev->vmq_info->back_rx); + rxed += rx_counter; + WRITE_ONCE(rdev->vmq_info->back_rx, rxed); + } + } + + *quota -= limit - (++boguscnt); return boguscnt <= 0; @@ -2435,16 +2452,35 @@ static int rswitch_start_xmit(struct sk_buff *skb, struct net_device *ndev) unsigned long flags; struct rswitch_gwca_chain *c = rdev->tx_chain; int i, num_desc, pkt_len, size; + int rx_chain_free = RX_RING_SIZE; + u64 txed; spin_lock_irqsave(&rdev->lock, flags); num_desc = skb->len % MAX_DESC_SZ ? skb->len / MAX_DESC_SZ + 1 : skb->len / MAX_DESC_SZ; + if (rdev->is_vmq) { + if (rswitch_is_front_dev(rdev)) { + rx_chain_free = RX_RING_SIZE - + (READ_ONCE(rdev->vmq_info->front_tx) - + READ_ONCE(rdev->vmq_info->back_rx)); + } else { + rx_chain_free = RX_RING_SIZE - + (READ_ONCE(rdev->vmq_info->back_tx) - + READ_ONCE(rdev->vmq_info->front_rx)); + } + } if (c->cur - c->dirty > c->num_ring - num_desc) { netif_stop_subqueue(ndev, 0); ret = NETDEV_TX_BUSY; goto out; } + + if (num_desc > rx_chain_free) { + curr_time = ktime_get(); + ret = NETDEV_TX_BUSY; + goto out; + } if (skb_put_padto(skb, ETH_ZLEN)) goto out; @@ -2529,6 +2565,18 @@ static int rswitch_start_xmit(struct sk_buff *skb, struct net_device *ndev) desc->die_dt = DT_FSINGLE | DIE; } + if (rdev->is_vmq) { + if (rswitch_is_front_dev(rdev)) { + txed = READ_ONCE(rdev->vmq_info->front_tx); + txed += num_desc; + WRITE_ONCE(rdev->vmq_info->front_tx, txed); + } else { + txed = READ_ONCE(rdev->vmq_info->back_tx); + txed += num_desc; + WRITE_ONCE(rdev->vmq_info->back_tx, txed); + } + } + c->cur += num_desc; rswitch_trigger_chain(rdev->priv, c); @@ -4087,6 +4135,7 @@ int rswitch_rxdmac_init(struct net_device *ndev, struct rswitch_private *priv, RX_RING_SIZE); if (err < 0) goto put_learning; + err = rswitch_gwca_chain_init(ndev, priv, rdev->rx_learning_chain, false, RX_RING_SIZE); if (err < 0) @@ -4095,6 +4144,7 @@ int rswitch_rxdmac_init(struct net_device *ndev, struct rswitch_private *priv, err = rswitch_gwca_chain_ext_ts_format(ndev, priv, rdev->rx_default_chain); if (err < 0) goto free_learning; + err = rswitch_gwca_chain_ext_ts_format(ndev, priv, rdev->rx_learning_chain); if (err < 0) goto free_learning; @@ -4251,6 +4301,8 @@ static int rswitch_ndev_create(struct rswitch_private *priv, int index, bool rmo } } + rdev->is_vmq = false; + /* Print device information */ netdev_info(ndev, "MAC address %pMn", ndev->dev_addr); @@ -5026,6 +5078,7 @@ static int vlan_dev_register(struct net_device *ndev) netif_napi_add(ndev, &rdev->napi, rswitch_poll, 64); netif_tx_napi_add(ndev, &rdev->tx_napi, rswitch_tx_poll, 64); netdev_info(ndev, "MAC address %pMn", ndev->dev_addr); + rdev->is_vmq = false; napi_enable(&rdev->napi); napi_enable(&rdev->tx_napi); return 0; diff --git a/drivers/net/ethernet/renesas/rswitch.h b/drivers/net/ethernet/renesas/rswitch.h index 1ea0d506cfe262..b1a7f1a79123dd 100644 --- a/drivers/net/ethernet/renesas/rswitch.h +++ b/drivers/net/ethernet/renesas/rswitch.h @@ -275,6 +275,12 @@ struct rswitch_filters { DECLARE_BITMAP(cascade, PFL_CADF_N); }; +struct rswitch_vmq_status { + uint64_t front_tx, front_rx; + uint64_t back_tx, back_rx; + uint64_t tx_ring_size, rx_ring_size; +}; + struct rswitch_device { struct list_head list; struct rswitch_private *priv; @@ -308,6 +314,8 @@ struct rswitch_device { */ struct device *vlan_parent; bool mondev; + struct rswitch_vmq_status *vmq_info; + bool is_vmq; }; struct rswitch_private { diff --git a/drivers/net/ethernet/renesas/rswitch_xenback.c b/drivers/net/ethernet/renesas/rswitch_xenback.c index 97bde28116115e..644526ad0a56cd 100644 --- a/drivers/net/ethernet/renesas/rswitch_xenback.c +++ b/drivers/net/ethernet/renesas/rswitch_xenback.c @@ -103,6 +103,8 @@ rswitch_vmq_back_ndev_register(struct rswitch_private *priv, int index) if (err < 0) goto out_txdmac; + rdev->is_vmq = true; + /* Print device information */ netdev_info(ndev, "MAC address %pMn", ndev->dev_addr); @@ -374,11 +376,15 @@ static int rswitch_vmq_back_connect(struct xenbus_device *dev) struct rswitch_vmq_back_info *be = dev_get_drvdata(&dev->dev); unsigned int tx_evt; unsigned int rx_evt; + unsigned int gref; int err; + struct gnttab_map_grant_ref map; + struct page *page; err = xenbus_gather(XBT_NIL, dev->otherend, "tx-evtch", "%u", &tx_evt, "rx-evtch", "%u", &rx_evt, + "gref", "%u", &gref, NULL); if (err) { xenbus_dev_fatal(dev, err, "Failed to read front-end info: %d", err); @@ -427,6 +433,22 @@ static int rswitch_vmq_back_connect(struct xenbus_device *dev) break; } + + err = gnttab_alloc_pages(1, &page); + if (err) { + pr_err("Failed to allocate GNT page %d\n", err); + return err; + } + + gnttab_set_map_op(&map, (uintptr_t)pfn_to_kaddr(page_to_xen_pfn((page))), + GNTMAP_host_map, gref, dev->otherend_id); + err = gnttab_map_refs(&map, NULL, &page, 1); + if (err) { + pr_err("Failed to map grant refs %d\n", err); + } else { + be->rdev->vmq_info = (struct rswitch_vmq_status *)page_address(page); + } + return err; } diff --git a/drivers/net/ethernet/renesas/rswitch_xenfront.c b/drivers/net/ethernet/renesas/rswitch_xenfront.c index 5d5361a72c0151..da8519506dcd44 100644 --- a/drivers/net/ethernet/renesas/rswitch_xenfront.c +++ b/drivers/net/ethernet/renesas/rswitch_xenfront.c @@ -139,6 +139,7 @@ static int rswitch_vmq_front_ndev_register(struct rswitch_device *rdev, /* Print device information */ netdev_info(ndev, "MAC address %pMn", ndev->dev_addr); + rdev->is_vmq = true; return 0; @@ -200,6 +201,7 @@ static int rswitch_vmq_front_connect(struct net_device *dev) char *type; char *mac_str; u8 mac[ETH_ALEN]; + int ret, gref; tx_chain_id = xenbus_read_unsigned(np->xbdev->otherend, "tx-chain-id", 0); @@ -238,8 +240,25 @@ static int rswitch_vmq_front_connect(struct net_device *dev) err = rswitch_vmq_front_ndev_register(rdev, type, index, tx_chain_id, rx_chain_id, mac_str ? mac : NULL); + + rdev->vmq_info = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO); + /* TODO: correct process error */ + if (!rdev->vmq_info) { + pr_err("rdev->rswitch_vmq_status ERROR\n"); + return -1; + } + + gref = gnttab_grant_foreign_access(np->xbdev->otherend_id, + virt_to_gfn(rdev->vmq_info), 0); kfree(type); + WRITE_ONCE(rdev->vmq_info->front_tx, 0); + WRITE_ONCE(rdev->vmq_info->front_rx, 0); + WRITE_ONCE(rdev->vmq_info->back_tx, 0); + WRITE_ONCE(rdev->vmq_info->back_rx, 0); + WRITE_ONCE(rdev->vmq_info->tx_ring_size, RX_RING_SIZE); + WRITE_ONCE(rdev->vmq_info->rx_ring_size, TX_RING_SIZE); + if (mac_str) kfree(mac_str); @@ -297,6 +316,14 @@ static int rswitch_vmq_front_connect(struct net_device *dev) return err; } + ret = xenbus_printf(XBT_NIL, np->xbdev->nodename, "gref", + "%u", gref); + if (err) { + xenbus_dev_fatal(np->xbdev, err, + "Failed to write TX event channel id: %d\n", err); + return err; + } + return 0; } From 934c2b1fc239b05dcc0e78cee33118f8dbdc02ab Mon Sep 17 00:00:00 2001 From: Leonid Komarianskyi Date: Wed, 31 Jan 2024 17:22:04 +0200 Subject: [PATCH 4/6] [WIP] do not create learning chain for VMQ devices Signed-off-by: Leonid Komarianskyi --- drivers/net/ethernet/renesas/rswitch.c | 28 +++++++++++++++++--------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/renesas/rswitch.c b/drivers/net/ethernet/renesas/rswitch.c index dc60f51f14b848..e4cb321e1b7f85 100644 --- a/drivers/net/ethernet/renesas/rswitch.c +++ b/drivers/net/ethernet/renesas/rswitch.c @@ -4116,7 +4116,7 @@ int rswitch_rxdmac_init(struct net_device *ndev, struct rswitch_private *priv, rdev->rx_default_chain = rswitch_gwca_get(priv); if (!rdev->rx_default_chain) return -EBUSY; - if (!parallel_mode) { + if (!parallel_mode && !rdev->is_vmq) { rdev->rx_learning_chain = rswitch_gwca_get(priv); if (!rdev->rx_learning_chain) goto put_default; @@ -4136,27 +4136,35 @@ int rswitch_rxdmac_init(struct net_device *ndev, struct rswitch_private *priv, if (err < 0) goto put_learning; - err = rswitch_gwca_chain_init(ndev, priv, rdev->rx_learning_chain, false, - RX_RING_SIZE); - if (err < 0) - goto free_default; + if (!rdev->is_vmq) { + err = rswitch_gwca_chain_init(ndev, priv, rdev->rx_learning_chain, false, + RX_RING_SIZE); + if (err < 0) + goto free_default; + } err = rswitch_gwca_chain_ext_ts_format(ndev, priv, rdev->rx_default_chain); if (err < 0) goto free_learning; - err = rswitch_gwca_chain_ext_ts_format(ndev, priv, rdev->rx_learning_chain); - if (err < 0) - goto free_learning; + if (!rdev->is_vmq) { + err = rswitch_gwca_chain_ext_ts_format(ndev, priv, rdev->rx_learning_chain); + if (err < 0) + goto free_learning; + } else { + rdev->rx_learning_chain = NULL; + } return 0; free_learning: - rswitch_gwca_chain_free(ndev, priv, rdev->rx_learning_chain); + if (!rdev->is_vmq) + rswitch_gwca_chain_free(ndev, priv, rdev->rx_learning_chain); free_default: rswitch_gwca_chain_free(ndev, priv, rdev->rx_default_chain); put_learning: - rswitch_gwca_put(priv, rdev->rx_learning_chain); + if (!rdev->is_vmq) + rswitch_gwca_put(priv, rdev->rx_learning_chain); put_default: rswitch_gwca_put(priv, rdev->rx_default_chain); From ac6bbacc464162a6c8eba06972f82c596254d2b8 Mon Sep 17 00:00:00 2001 From: Leonid Komarianskyi Date: Wed, 31 Jan 2024 17:22:35 +0200 Subject: [PATCH 5/6] [WIP] increase chain ring size up to 10240 Signed-off-by: Leonid Komarianskyi --- drivers/net/ethernet/renesas/rswitch.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/renesas/rswitch.h b/drivers/net/ethernet/renesas/rswitch.h index b1a7f1a79123dd..1d556a30ec2ab8 100644 --- a/drivers/net/ethernet/renesas/rswitch.h +++ b/drivers/net/ethernet/renesas/rswitch.h @@ -209,8 +209,8 @@ struct rswitch_gwca_chain { #define RSWITCH_MAX_NUM_NDEV 8 #define RSWITCH_MAX_NUM_L23 256 -#define TX_RING_SIZE 1024 -#define RX_RING_SIZE 1024 +#define TX_RING_SIZE 10240 +#define RX_RING_SIZE 10240 #define RSWITCH_ALIGN 128 #define RSWITCH_MAX_CTAG_PCP 7 From bade029c851e9727d33bcda80a4094aaf96ff085 Mon Sep 17 00:00:00 2001 From: Leonid Komarianskyi Date: Wed, 31 Jan 2024 17:24:46 +0200 Subject: [PATCH 6/6] net: ethernet: renesas: fix uninitialized list Currently, in case of disabling L3 offload while using VMQs in DomD the system will hang, due to accessing to uninitialized list. Signed-off-by: Leonid Komarianskyi --- drivers/net/ethernet/renesas/rswitch_xenback.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ethernet/renesas/rswitch_xenback.c b/drivers/net/ethernet/renesas/rswitch_xenback.c index 644526ad0a56cd..0890e111ac8f87 100644 --- a/drivers/net/ethernet/renesas/rswitch_xenback.c +++ b/drivers/net/ethernet/renesas/rswitch_xenback.c @@ -82,6 +82,9 @@ rswitch_vmq_back_ndev_register(struct rswitch_private *priv, int index) spin_lock_init(&rdev->lock); INIT_LIST_HEAD(&rdev->routing_list); +#if IS_ENABLED(CONFIG_IP_MROUTE) + INIT_LIST_HEAD(&rdev->mult_routing_list); +#endif ndev->features = NETIF_F_RXCSUM; ndev->hw_features = NETIF_F_RXCSUM;