From 0e7312b9d22dc9a7750246e3386c4faf2cd3c1ea Mon Sep 17 00:00:00 2001 From: Hyong Youb Kim Date: Wed, 9 Sep 2020 06:56:52 -0700 Subject: [PATCH] net/enic: extend VNIC dev API for VF representors VF representors need to proxy devcmd through the PF vnic_dev instance. Extend vnic_dev to accommodate them as follows. 1. Add vnic_vf_rep_register() A VF representor creates its own vnic_dev instance via this function and saves VF ID. When performing devcmd, vnic_dev uses the saved VF ID to proxy devcmd through the PF vnic_dev instance. 2. Add vnic_register_lock() As PF and VF representors appear as independent ports to the application, its threads may invoke APIs on them simultaneously, leading to race conditions on the PF vnic_dev. For example, thread A can query stats on PF port, while thread B queries stats on a VF representor. The PF port invokes this function to provide a lock to vnic_dev. This lock is used to serialize devcmd calls from PF and VF representors. 3. Add utility functions to assist VF representor settings vnic_dev_mtu() and vnic_dev_uif() retrieve vnic MTU and UIF number (uplink index), respectively. Signed-off-by: Hyong Youb Kim Reviewed-by: John Daley --- drivers/net/enic/base/vnic_dev.c | 112 ++++++++++++++++++++++++++++++- drivers/net/enic/base/vnic_dev.h | 4 ++ 2 files changed, 113 insertions(+), 3 deletions(-) diff --git a/drivers/net/enic/base/vnic_dev.c b/drivers/net/enic/base/vnic_dev.c index ac03817f40..aaca07ca67 100644 --- a/drivers/net/enic/base/vnic_dev.c +++ b/drivers/net/enic/base/vnic_dev.c @@ -61,6 +61,16 @@ struct vnic_dev { void (*free_consistent)(void *priv, size_t size, void *vaddr, dma_addr_t dma_handle); + /* + * Used to serialize devcmd access, currently from PF and its + * VF representors. When there are no representors, lock is + * not used. + */ + int locked; + void (*lock)(void *priv); + void (*unlock)(void *priv); + struct vnic_dev *pf_vdev; + int vf_id; }; #define VNIC_MAX_RES_HDR_SIZE \ @@ -84,6 +94,14 @@ void vnic_register_cbacks(struct vnic_dev *vdev, vdev->free_consistent = free_consistent; } +void vnic_register_lock(struct vnic_dev *vdev, void (*lock)(void *priv), + void (*unlock)(void *priv)) +{ + vdev->lock = lock; + vdev->unlock = unlock; + vdev->locked = 0; +} + static int vnic_dev_discover_res(struct vnic_dev *vdev, struct vnic_dev_bar *bar, unsigned int num_bars) { @@ -410,12 +428,39 @@ static int vnic_dev_cmd_no_proxy(struct vnic_dev *vdev, return err; } +void vnic_dev_cmd_proxy_by_index_start(struct vnic_dev *vdev, uint16_t index) +{ + vdev->proxy = PROXY_BY_INDEX; + vdev->proxy_index = index; +} + +void vnic_dev_cmd_proxy_end(struct vnic_dev *vdev) +{ + vdev->proxy = PROXY_NONE; + vdev->proxy_index = 0; +} + int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, uint64_t *a0, uint64_t *a1, int wait) { uint64_t args[2]; + bool vf_rep; + int vf_idx; int err; + vf_rep = false; + if (vdev->pf_vdev) { + vf_rep = true; + vf_idx = vdev->vf_id; + /* Everything below assumes PF vdev */ + vdev = vdev->pf_vdev; + } + if (vdev->lock) + vdev->lock(vdev->priv); + /* For VF representor, proxy devcmd to VF index */ + if (vf_rep) + vnic_dev_cmd_proxy_by_index_start(vdev, vf_idx); + args[0] = *a0; args[1] = *a1; memset(vdev->args, 0, sizeof(vdev->args)); @@ -435,6 +480,10 @@ int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, break; } + if (vf_rep) + vnic_dev_cmd_proxy_end(vdev); + if (vdev->unlock) + vdev->unlock(vdev->priv); if (err == 0) { *a0 = args[0]; *a1 = args[1]; @@ -446,17 +495,41 @@ int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, int vnic_dev_cmd_args(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, uint64_t *args, int nargs, int wait) { + bool vf_rep; + int vf_idx; + int err; + + vf_rep = false; + if (vdev->pf_vdev) { + vf_rep = true; + vf_idx = vdev->vf_id; + vdev = vdev->pf_vdev; + } + if (vdev->lock) + vdev->lock(vdev->priv); + if (vf_rep) + vnic_dev_cmd_proxy_by_index_start(vdev, vf_idx); + switch (vdev->proxy) { case PROXY_BY_INDEX: - return vnic_dev_cmd_proxy(vdev, CMD_PROXY_BY_INDEX, cmd, + err = vnic_dev_cmd_proxy(vdev, CMD_PROXY_BY_INDEX, cmd, args, nargs, wait); + break; case PROXY_BY_BDF: - return vnic_dev_cmd_proxy(vdev, CMD_PROXY_BY_BDF, cmd, + err = vnic_dev_cmd_proxy(vdev, CMD_PROXY_BY_BDF, cmd, args, nargs, wait); + break; case PROXY_NONE: default: - return vnic_dev_cmd_no_proxy(vdev, cmd, args, nargs, wait); + err = vnic_dev_cmd_no_proxy(vdev, cmd, args, nargs, wait); + break; } + + if (vf_rep) + vnic_dev_cmd_proxy_end(vdev); + if (vdev->unlock) + vdev->unlock(vdev->priv); + return err; } int vnic_dev_fw_info(struct vnic_dev *vdev, @@ -1012,6 +1085,22 @@ uint32_t vnic_dev_port_speed(struct vnic_dev *vdev) return vdev->notify_copy.port_speed; } +uint32_t vnic_dev_mtu(struct vnic_dev *vdev) +{ + if (!vnic_dev_notify_ready(vdev)) + return 0; + + return vdev->notify_copy.mtu; +} + +uint32_t vnic_dev_uif(struct vnic_dev *vdev) +{ + if (!vnic_dev_notify_ready(vdev)) + return 0; + + return vdev->notify_copy.uif; +} + uint32_t vnic_dev_intr_coal_timer_usec_to_hw(struct vnic_dev *vdev, uint32_t usec) { @@ -1100,6 +1189,23 @@ err_out: return NULL; } +struct vnic_dev *vnic_vf_rep_register(void *priv, struct vnic_dev *pf_vdev, + int vf_id) +{ + struct vnic_dev *vdev; + + vdev = (struct vnic_dev *)rte_zmalloc("enic-vf-rep-vdev", + sizeof(struct vnic_dev), RTE_CACHE_LINE_SIZE); + if (!vdev) + return NULL; + vdev->priv = priv; + vdev->pf_vdev = pf_vdev; + vdev->vf_id = vf_id; + vdev->alloc_consistent = pf_vdev->alloc_consistent; + vdev->free_consistent = pf_vdev->free_consistent; + return vdev; +} + /* * vnic_dev_classifier: Add/Delete classifier entries * @vdev: vdev of the device diff --git a/drivers/net/enic/base/vnic_dev.h b/drivers/net/enic/base/vnic_dev.h index 02e19c0b8a..30ba57bfcd 100644 --- a/drivers/net/enic/base/vnic_dev.h +++ b/drivers/net/enic/base/vnic_dev.h @@ -80,6 +80,8 @@ void vnic_register_cbacks(struct vnic_dev *vdev, void (*free_consistent)(void *priv, size_t size, void *vaddr, dma_addr_t dma_handle)); +void vnic_register_lock(struct vnic_dev *vdev, void (*lock)(void *priv), + void (*unlock)(void *priv)); void __iomem *vnic_dev_get_res(struct vnic_dev *vdev, enum vnic_res_type type, unsigned int index); dma_addr_t vnic_dev_get_res_bus_addr(struct vnic_dev *vdev, @@ -172,6 +174,8 @@ struct vnic_dev *vnic_dev_register(struct vnic_dev *vdev, void *priv, struct rte_pci_device *pdev, struct vnic_dev_bar *bar, unsigned int num_bars); struct rte_pci_device *vnic_dev_get_pdev(struct vnic_dev *vdev); +struct vnic_dev *vnic_vf_rep_register(void *priv, struct vnic_dev *pf_vdev, + int vf_id); int vnic_dev_alloc_stats_mem(struct vnic_dev *vdev); int vnic_dev_cmd_init(struct vnic_dev *vdev, int fallback); int vnic_dev_get_size(void); -- 2.20.1