Skip to content

Commit

Permalink
lib/pem: allow use of more interrupt per virtio device
Browse files Browse the repository at this point in the history
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 <sthotton@marvell.com>
Change-Id: Ibc49f942a9ced701b54a25137c6764fc0e054686
Reviewed-on: https://sj1git1.cavium.com/c/IP/SW/dataplane/dpu-offload/+/135467
Tested-by: sa_ip-toolkits-Jenkins <sa_ip-toolkits-jenkins@marvell.com>
Reviewed-by: Nithin Kumar Dabilpuram <ndabilpuram@marvell.com>
  • Loading branch information
Shijith Thotton authored and jerinjacobk committed Oct 1, 2024
1 parent f4d3610 commit d4d1a04
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 26 deletions.
6 changes: 4 additions & 2 deletions lib/pem/dao_pem.h
Original file line number Diff line number Diff line change
Expand Up @@ -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__ */
33 changes: 25 additions & 8 deletions lib/pem/pem.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
12 changes: 6 additions & 6 deletions lib/pem/sdp.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,6 @@
#include <dao_util.h>

#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)
Expand Down Expand Up @@ -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;
}

Expand Down
13 changes: 9 additions & 4 deletions lib/pem/sdp.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,15 @@

#include <dao_vfio_platform.h>

#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);
Expand Down
3 changes: 2 additions & 1 deletion lib/virtio/virtio_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
6 changes: 4 additions & 2 deletions lib/virtio/virtio_dev_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand Down
8 changes: 5 additions & 3 deletions lib/virtio_net/virtio_netdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit d4d1a04

Please sign in to comment.