From d4d1a0481eae0e6f8d37c0d98252e7f36f190ae9 Mon Sep 17 00:00:00 2001 From: Shijith Thotton Date: Thu, 12 Sep 2024 11:55:02 +0530 Subject: [PATCH] lib/pem: allow use of more interrupt per virtio device A virtio device can utilize multiple interrupts to notify the host about incoming packets when the SDP VF is configured with more than one ring. During PEM initialization, the number of rings per VF is determined, and additional interrupts are configured based on the number of rings set for each VF. Below are the host Rx performance with increasing flows and 8 IRQ: Flows Rx PPS 1 1630400 2 4239808 4 8720704 16 12342592 Signed-off-by: Shijith Thotton Change-Id: Ibc49f942a9ced701b54a25137c6764fc0e054686 Reviewed-on: https://sj1git1.cavium.com/c/IP/SW/dataplane/dpu-offload/+/135467 Tested-by: sa_ip-toolkits-Jenkins Reviewed-by: Nithin Kumar Dabilpuram --- lib/pem/dao_pem.h | 6 ++++-- lib/pem/pem.c | 33 +++++++++++++++++++++++++-------- lib/pem/sdp.c | 12 ++++++------ lib/pem/sdp.h | 13 +++++++++---- lib/virtio/virtio_dev.c | 3 ++- lib/virtio/virtio_dev_priv.h | 6 ++++-- lib/virtio_net/virtio_netdev.c | 8 +++++--- 7 files changed, 55 insertions(+), 26 deletions(-) diff --git a/lib/pem/dao_pem.h b/lib/pem/dao_pem.h index f485382..981d9fc 100644 --- a/lib/pem/dao_pem.h +++ b/lib/pem/dao_pem.h @@ -163,7 +163,9 @@ size_t dao_pem_host_page_sz(uint16_t pem_devid); * @param vfid * VF device ID. * @param intr_addr - * Pointer to the address that triggers host interrupt upon write. + * Pointer to an array of addresses to be filled that triggers host interrupt upon write. + * @return + * Number of interrupts configured. */ -void dao_pem_host_interrupt_setup(uint16_t pem_devid, int vfid, uint64_t **intr_addr); +uint8_t dao_pem_host_interrupt_setup(uint16_t pem_devid, int vfid, uint64_t **intr_addr); #endif /* __INCLUDE_DAO_PEM_H__ */ diff --git a/lib/pem/pem.c b/lib/pem/pem.c index da31031..5371c36 100644 --- a/lib/pem/pem.c +++ b/lib/pem/pem.c @@ -390,17 +390,34 @@ dao_pem_host_page_sz(uint16_t pem_devid) return pem->host_page_sz; } -void +uint8_t dao_pem_host_interrupt_setup(uint16_t pem_devid, int vfid, uint64_t **intr_addr) { struct pem *pem = &pem_devices[pem_devid]; - int ring_idx = vfid - 1; + int idx, ring_idx; + uint64_t reg_val; + uint8_t rpvf; - sdp_reg_write(&pem->sdp_pdev, SDP_EPVF_RINGX(ring_idx), vfid); - sdp_reg_write(&pem->sdp_pdev, SDP_RX_OUT_ENABLE(ring_idx), 0x1); - sdp_reg_write(&pem->sdp_pdev, SDP_RX_OUT_CNTS(ring_idx), 0x1); - sdp_reg_write(&pem->sdp_pdev, SDP_RX_OUT_INT_LEVELS(ring_idx), ~0xfUL); + reg_val = sdp_reg_read(&pem->sdp_pdev, SDP_EPFX_RINFO(0)); + rpvf = (reg_val >> SDP_EPFX_RINFO_RPVF_SHIFT) & 0xf; - __atomic_store_n(intr_addr, sdp_reg_addr(&pem->sdp_pdev, SDP_RX_OUT_CNTS(ring_idx)), - __ATOMIC_RELAXED); + if (!rpvf) { + dao_err("No rings configured per VF, host interrupts unsupported"); + return 0; + } + + for (idx = 0; idx < rpvf; idx++) { + ring_idx = idx + (vfid - 1) * rpvf; + + sdp_reg_write(&pem->sdp_pdev, SDP_EPVF_RINGX(ring_idx), vfid); + sdp_reg_write(&pem->sdp_pdev, SDP_RX_OUT_ENABLE(ring_idx), 0x1); + sdp_reg_write(&pem->sdp_pdev, SDP_RX_OUT_CNTS(ring_idx), 0x1); + sdp_reg_write(&pem->sdp_pdev, SDP_RX_OUT_INT_LEVELS(ring_idx), ~0xfUL); + + __atomic_store_n(intr_addr, sdp_reg_addr(&pem->sdp_pdev, SDP_RX_OUT_CNTS(ring_idx)), + __ATOMIC_RELAXED); + intr_addr++; + } + + return rpvf; } diff --git a/lib/pem/sdp.c b/lib/pem/sdp.c index 7ccbb54..e1e1676 100644 --- a/lib/pem/sdp.c +++ b/lib/pem/sdp.c @@ -15,9 +15,6 @@ #include #define SDP_PLAT_DEV_NAME "86e000000000.dpi_sdp_regs" -#define SDP_EPFX_RINFO(x) (0x800209f0UL | (x) << 25) -#define SDP_MAC0_PF_RING_CTL 0x8002c000 -#define SDP_EPFX_RINFO_NVFS_MASK DAO_GENMASK_ULL(54, 48) int sdp_reg_write(struct dao_vfio_platform_device *sdp_pdev, uint64_t offset, uint64_t val) @@ -60,11 +57,14 @@ sdp_init(struct dao_vfio_platform_device *sdp_pdev) } reg_val = sdp_reg_read(sdp_pdev, SDP_EPFX_RINFO(0)); - reg_val &= SDP_EPFX_RINFO_NVFS_MASK; - /* 0 ring per PF and 1 ring per VF. */ - reg_val |= (1UL << 32); + reg_val &= ~SDP_EPFX_RINFO_SRN_MASK; sdp_reg_write(sdp_pdev, SDP_EPFX_RINFO(0), reg_val); + /* Disable PF Ring */ + reg_val = sdp_reg_read(sdp_pdev, SDP_MAC0_PF_RING_CTL); + reg_val &= ~SDP_MAC0_PF_RING_CTL_RPPF_MASK; + sdp_reg_write(sdp_pdev, SDP_MAC0_PF_RING_CTL, reg_val); + return 0; } diff --git a/lib/pem/sdp.h b/lib/pem/sdp.h index f7b65ba..77365e4 100644 --- a/lib/pem/sdp.h +++ b/lib/pem/sdp.h @@ -9,10 +9,15 @@ #include -#define SDP_EPVF_RINGX(x) (0x80026000 | (x) << 4) -#define SDP_RX_OUT_ENABLE(x) (0x80010170 | (x) << 17) -#define SDP_RX_OUT_CNTS(x) (0x80010100 | (x) << 17) -#define SDP_RX_OUT_INT_LEVELS(x) (0x80010110 | (x) << 17) +#define SDP_RX_OUT_ENABLE(x) (0x80010170 | (x) << 17) +#define SDP_RX_OUT_CNTS(x) (0x80010100 | (x) << 17) +#define SDP_RX_OUT_INT_LEVELS(x) (0x80010110 | (x) << 17) +#define SDP_MAC0_PF_RING_CTL (0x8002c000) +#define SDP_MAC0_PF_RING_CTL_RPPF_MASK DAO_GENMASK_ULL(21, 16) +#define SDP_EPVF_RINGX(x) (0x80026000 | (x) << 4) +#define SDP_EPFX_RINFO(x) (0x800209f0 | (x) << 25) +#define SDP_EPFX_RINFO_RPVF_SHIFT 32 +#define SDP_EPFX_RINFO_SRN_MASK DAO_GENMASK_ULL(6, 0) int sdp_init(struct dao_vfio_platform_device *sdp_pdev); uint64_t sdp_reg_read(struct dao_vfio_platform_device *sdp_pdev, uint64_t offset); diff --git a/lib/virtio/virtio_dev.c b/lib/virtio/virtio_dev.c index 0f11bfd..18c06ff 100644 --- a/lib/virtio/virtio_dev.c +++ b/lib/virtio/virtio_dev.c @@ -1104,7 +1104,8 @@ virtio_dev_init(struct virtio_dev *dev) dev->feature_bits = dev->dev_feature_bits; /* Setup virtio device host interrupt for the vring call */ - dao_pem_host_interrupt_setup(dev->pem_devid, dev->dev_id + 1, &dev->cb_intr_addr); + dev->nb_cb_intrs = + dao_pem_host_interrupt_setup(dev->pem_devid, dev->dev_id + 1, dev->cb_intr_addr); /* Register control register region */ rc = dao_pem_ctrl_region_register(dev->pem_devid, (uintptr_t)dev->common_cfg, diff --git a/lib/virtio/virtio_dev_priv.h b/lib/virtio/virtio_dev_priv.h index 36d6633..b1c258a 100644 --- a/lib/virtio/virtio_dev_priv.h +++ b/lib/virtio/virtio_dev_priv.h @@ -34,7 +34,8 @@ #define PCI_CAP_ID_VNDR 0x09 #define PCI_CAP_BAR 4 -#define VIRTIO_DMA_TMO_MS 3000 +#define VIRTIO_DMA_TMO_MS 3000 +#define VIRTIO_MAX_CB_INTRS 8 enum virtio_dev_type { VIRTIO_DEV_TYPE_NET, @@ -179,7 +180,8 @@ struct virtio_dev { uint64_t feature_bits; uint16_t prev_queue_select; uint32_t prev_drv_feature_select; - uint64_t *cb_intr_addr; + uint64_t *cb_intr_addr[VIRTIO_MAX_CB_INTRS]; + uint8_t nb_cb_intrs; uint8_t driver_ok_pend; uint8_t queue_select_pend; diff --git a/lib/virtio_net/virtio_netdev.c b/lib/virtio_net/virtio_netdev.c index d573168..a5b6187 100644 --- a/lib/virtio_net/virtio_netdev.c +++ b/lib/virtio_net/virtio_netdev.c @@ -254,16 +254,18 @@ virtio_netdev_cb_interrupt_conf(struct virtio_netdev *netdev) uint32_t max_vqs = netdev->dev.max_virtio_queues - 1; struct virtio_dev *dev = &netdev->dev; struct virtio_net_queue *queue; - uint32_t i; + uint32_t i, intr_idx; + intr_idx = 0; for (i = 0; i < max_vqs; i++) { queue = netdev->qs[i]; - if (!queue) + if (!queue || i % 2) continue; - queue->cb_intr_addr = dev->cb_intr_addr; + queue->cb_intr_addr = dev->cb_intr_addr[intr_idx]; queue->cb_notify_addr = queue->notify_addr + 1; __atomic_store_n(queue->cb_notify_addr, 0, __ATOMIC_RELAXED); + intr_idx = (intr_idx + 1) % dev->nb_cb_intrs; } dao_dbg("[dev %u] Enabled driver events for %u queues", dev->dev_id, max_vqs);