X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fenic%2Fbase%2Fvnic_dev.c;h=aaca07ca67e546f49c8dc45dd6068af1c312f8da;hb=57ddbf7edd9c5041603e224fbbb62c11ce423135;hp=162e9c2f2404efb70a86a3ae8b8dcb88f04a945e;hpb=0e804034dc9a5e27aa3bd9763457cd70e8970b81;p=dpdk.git diff --git a/drivers/net/enic/base/vnic_dev.c b/drivers/net/enic/base/vnic_dev.c index 162e9c2f24..aaca07ca67 100644 --- a/drivers/net/enic/base/vnic_dev.c +++ b/drivers/net/enic/base/vnic_dev.c @@ -1,45 +1,19 @@ -/* - * Copyright 2008-2014 Cisco Systems, Inc. All rights reserved. +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2008-2017 Cisco Systems, Inc. All rights reserved. * Copyright 2007 Nuova Systems, Inc. All rights reserved. - * - * Copyright (c) 2014, Cisco Systems, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * */ #include #include #include +#include #include "vnic_dev.h" #include "vnic_resource.h" #include "vnic_devcmd.h" +#include "vnic_nic.h" #include "vnic_stats.h" +#include "vnic_flowman.h" enum vnic_proxy_type { @@ -55,9 +29,9 @@ struct vnic_res { }; struct vnic_intr_coal_timer_info { - u32 mul; - u32 div; - u32 max_usec; + uint32_t mul; + uint32_t div; + uint32_t max_usec; }; struct vnic_dev { @@ -69,23 +43,34 @@ struct vnic_dev { struct vnic_devcmd_notify *notify; struct vnic_devcmd_notify notify_copy; dma_addr_t notify_pa; - u32 notify_sz; + uint32_t notify_sz; dma_addr_t linkstatus_pa; struct vnic_stats *stats; dma_addr_t stats_pa; struct vnic_devcmd_fw_info *fw_info; dma_addr_t fw_info_pa; + struct fm_info *flowman_info; + dma_addr_t flowman_info_pa; enum vnic_proxy_type proxy; - u32 proxy_index; - u64 args[VNIC_DEVCMD_NARGS]; - u16 split_hdr_size; + uint32_t proxy_index; + uint64_t args[VNIC_DEVCMD_NARGS]; int in_reset; struct vnic_intr_coal_timer_info intr_coal_timer_info; void *(*alloc_consistent)(void *priv, size_t size, - dma_addr_t *dma_handle, u8 *name); + dma_addr_t *dma_handle, uint8_t *name); 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 \ @@ -100,7 +85,7 @@ void *vnic_dev_priv(struct vnic_dev *vdev) void vnic_register_cbacks(struct vnic_dev *vdev, void *(*alloc_consistent)(void *priv, size_t size, - dma_addr_t *dma_handle, u8 *name), + dma_addr_t *dma_handle, uint8_t *name), void (*free_consistent)(void *priv, size_t size, void *vaddr, dma_addr_t dma_handle)) @@ -109,13 +94,21 @@ 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) { struct vnic_resource_header __iomem *rh; struct mgmt_barmap_hdr __iomem *mrh; struct vnic_resource __iomem *r; - u8 type; + uint8_t type; if (num_bars == 0) return -EINVAL; @@ -153,10 +146,10 @@ static int vnic_dev_discover_res(struct vnic_dev *vdev, while ((type = ioread8(&r->type)) != RES_TYPE_EOL) { - u8 bar_num = ioread8(&r->bar); - u32 bar_offset = ioread32(&r->bar_offset); - u32 count = ioread32(&r->count); - u32 len; + uint8_t bar_num = ioread8(&r->bar); + uint32_t bar_offset = ioread32(&r->bar_offset); + uint32_t count = ioread32(&r->count); + uint32_t len; r++; @@ -251,16 +244,6 @@ unsigned int vnic_dev_desc_ring_size(struct vnic_dev_ring *ring, return ring->size_unaligned; } -void vnic_set_hdr_split_size(struct vnic_dev *vdev, u16 size) -{ - vdev->split_hdr_size = size; -} - -u16 vnic_get_hdr_split_size(struct vnic_dev *vdev) -{ - return vdev->split_hdr_size; -} - void vnic_dev_clear_desc_ring(struct vnic_dev_ring *ring) { memset(ring->descs, 0, ring->size); @@ -269,16 +252,16 @@ void vnic_dev_clear_desc_ring(struct vnic_dev_ring *ring) int vnic_dev_alloc_desc_ring(struct vnic_dev *vdev, struct vnic_dev_ring *ring, unsigned int desc_count, unsigned int desc_size, - __attribute__((unused)) unsigned int socket_id, + __rte_unused unsigned int socket_id, char *z_name) { - void *alloc_addr = NULL; + void *alloc_addr; dma_addr_t alloc_pa = 0; vnic_dev_desc_ring_size(ring, desc_count, desc_size); alloc_addr = vdev->alloc_consistent(vdev->priv, ring->size_unaligned, - &alloc_pa, (u8 *)z_name); + &alloc_pa, (uint8_t *)z_name); if (!alloc_addr) { pr_err("Failed to allocate ring (size=%d), aborting\n", (int)ring->size); @@ -298,7 +281,7 @@ int vnic_dev_alloc_desc_ring(struct vnic_dev *vdev, ring->base_addr = VNIC_ALIGN(ring->base_addr_unaligned, ring->base_align); - ring->descs = (u8 *)ring->descs_unaligned + + ring->descs = (uint8_t *)ring->descs_unaligned + (ring->base_addr - ring->base_addr_unaligned); vnic_dev_clear_desc_ring(ring); @@ -308,7 +291,7 @@ int vnic_dev_alloc_desc_ring(struct vnic_dev *vdev, return 0; } -void vnic_dev_free_desc_ring(__attribute__((unused)) struct vnic_dev *vdev, +void vnic_dev_free_desc_ring(__rte_unused struct vnic_dev *vdev, struct vnic_dev_ring *ring) { if (ring->descs) { @@ -326,7 +309,7 @@ static int _vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, struct vnic_devcmd __iomem *devcmd = vdev->devcmd; unsigned int i; int delay; - u32 status; + uint32_t status; int err; status = ioread32(&devcmd->status); @@ -343,7 +326,7 @@ static int _vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, if (_CMD_DIR(cmd) & _CMD_DIR_WRITE) { for (i = 0; i < VNIC_DEVCMD_NARGS; i++) writeq(vdev->args[i], &devcmd->args[i]); - wmb(); /* complete all writes initiated till now */ + rte_wmb(); /* complete all writes initiated till now */ } iowrite32(cmd, &devcmd->cmd); @@ -353,7 +336,7 @@ static int _vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, for (delay = 0; delay < wait; delay++) { - udelay(100); + usleep(100); status = ioread32(&devcmd->status); if (status == 0xFFFFFFFF) { @@ -364,7 +347,9 @@ static int _vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, if (!(status & STAT_BUSY)) { if (status & STAT_ERROR) { err = -(int)readq(&devcmd->args[0]); - if (cmd != CMD_CAPABILITY) + if (cmd != CMD_CAPABILITY && + cmd != CMD_OVERLAY_OFFLOAD_CTRL && + cmd != CMD_GET_SUPP_FEATURE_VER) pr_err("Devcmd %d failed " \ "with error code %d\n", _CMD_N(cmd), err); @@ -372,7 +357,7 @@ static int _vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, } if (_CMD_DIR(cmd) & _CMD_DIR_READ) { - rmb();/* finish all reads initiated till now */ + rte_rmb();/* finish all reads */ for (i = 0; i < VNIC_DEVCMD_NARGS; i++) vdev->args[i] = readq(&devcmd->args[i]); } @@ -387,9 +372,9 @@ static int _vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, static int vnic_dev_cmd_proxy(struct vnic_dev *vdev, enum vnic_devcmd_cmd proxy_cmd, enum vnic_devcmd_cmd cmd, - u64 *args, int nargs, int wait) + uint64_t *args, int nargs, int wait) { - u32 status; + uint32_t status; int err; /* @@ -410,7 +395,7 @@ static int vnic_dev_cmd_proxy(struct vnic_dev *vdev, if (err) return err; - status = (u32)vdev->args[0]; + status = (uint32_t)vdev->args[0]; if (status & STAT_ERROR) { err = (int)vdev->args[1]; if (err != ERR_ECMDUNKNOWN || @@ -425,7 +410,7 @@ static int vnic_dev_cmd_proxy(struct vnic_dev *vdev, } static int vnic_dev_cmd_no_proxy(struct vnic_dev *vdev, - enum vnic_devcmd_cmd cmd, u64 *args, int nargs, int wait) + enum vnic_devcmd_cmd cmd, uint64_t *args, int nargs, int wait) { int err; @@ -443,18 +428,12 @@ 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, u16 index) +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_by_bdf_start(struct vnic_dev *vdev, u16 bdf) -{ - vdev->proxy = PROXY_BY_BDF; - vdev->proxy_index = bdf; -} - void vnic_dev_cmd_proxy_end(struct vnic_dev *vdev) { vdev->proxy = PROXY_NONE; @@ -462,11 +441,26 @@ void vnic_dev_cmd_proxy_end(struct vnic_dev *vdev) } int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, - u64 *a0, u64 *a1, int wait) + uint64_t *a0, uint64_t *a1, int wait) { - u64 args[2]; + 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)); @@ -486,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]; @@ -495,22 +493,72 @@ 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, - u64 *args, int nargs, int wait) + 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; } -static int vnic_dev_advanced_filters_cap(struct vnic_dev *vdev, u64 *args, +int vnic_dev_fw_info(struct vnic_dev *vdev, + struct vnic_devcmd_fw_info **fw_info) +{ + char name[RTE_MEMZONE_NAMESIZE]; + uint64_t a0, a1 = 0; + int wait = 1000; + int err = 0; + static uint32_t instance; + + if (!vdev->fw_info) { + snprintf((char *)name, sizeof(name), "vnic_fw_info-%u", + instance++); + vdev->fw_info = vdev->alloc_consistent(vdev->priv, + sizeof(struct vnic_devcmd_fw_info), + &vdev->fw_info_pa, (uint8_t *)name); + if (!vdev->fw_info) + return -ENOMEM; + a0 = vdev->fw_info_pa; + a1 = sizeof(struct vnic_devcmd_fw_info); + err = vnic_dev_cmd(vdev, CMD_MCPU_FW_INFO, + &a0, &a1, wait); + } + *fw_info = vdev->fw_info; + return err; +} + +static int vnic_dev_advanced_filters_cap(struct vnic_dev *vdev, uint64_t *args, int nargs) { memset(args, 0, nargs * sizeof(*args)); @@ -521,18 +569,84 @@ static int vnic_dev_advanced_filters_cap(struct vnic_dev *vdev, u64 *args, int vnic_dev_capable_adv_filters(struct vnic_dev *vdev) { - u64 a0 = CMD_ADD_ADV_FILTER, a1 = 0; + uint64_t a0 = CMD_ADD_ADV_FILTER, a1 = 0; int wait = 1000; int err; err = vnic_dev_cmd(vdev, CMD_CAPABILITY, &a0, &a1, wait); if (err) return 0; - return (a1 >= (u32)FILTER_DPDK_1); + return (a1 >= (uint32_t)FILTER_DPDK_1); +} + +int vnic_dev_flowman_cmd(struct vnic_dev *vdev, uint64_t *args, int nargs) +{ + int wait = 1000; + + return vnic_dev_cmd_args(vdev, CMD_FLOW_MANAGER_OP, args, nargs, wait); +} + +static int vnic_dev_flowman_enable(struct vnic_dev *vdev, uint32_t *mode, + uint8_t *filter_actions) +{ + char name[RTE_MEMZONE_NAMESIZE]; + uint64_t args[3]; + uint64_t ops; + static uint32_t instance; + + /* flowman devcmd available? */ + if (!vnic_dev_capable(vdev, CMD_FLOW_MANAGER_OP)) + return 0; + /* Have the version we are using? */ + args[0] = FM_API_VERSION_QUERY; + if (vnic_dev_flowman_cmd(vdev, args, 1)) + return 0; + if ((args[0] & (1ULL << FM_VERSION)) == 0) + return 0; + /* Select the version */ + args[0] = FM_API_VERSION_SELECT; + args[1] = FM_VERSION; + if (vnic_dev_flowman_cmd(vdev, args, 2)) + return 0; + /* Can we get fm_info? */ + if (!vdev->flowman_info) { + snprintf((char *)name, sizeof(name), "vnic_fm_info-%u", + instance++); + vdev->flowman_info = vdev->alloc_consistent(vdev->priv, + sizeof(struct fm_info), + &vdev->flowman_info_pa, (uint8_t *)name); + if (!vdev->flowman_info) + return 0; + } + args[0] = FM_INFO_QUERY; + args[1] = vdev->flowman_info_pa; + args[2] = sizeof(struct fm_info); + if (vnic_dev_flowman_cmd(vdev, args, 3)) + return 0; + /* Have required operations? */ + ops = (1ULL << FMOP_END) | + (1ULL << FMOP_DROP) | + (1ULL << FMOP_RQ_STEER) | + (1ULL << FMOP_EXACT_MATCH) | + (1ULL << FMOP_MARK) | + (1ULL << FMOP_TAG) | + (1ULL << FMOP_EG_HAIRPIN) | + (1ULL << FMOP_ENCAP) | + (1ULL << FMOP_DECAP_NOSTRIP); + if ((vdev->flowman_info->fm_op_mask & ops) != ops) + return 0; + /* Good to use flowman now */ + *mode = FILTER_FLOWMAN; + *filter_actions = FILTER_ACTION_RQ_STEERING_FLAG | + FILTER_ACTION_FILTER_ID_FLAG | + FILTER_ACTION_COUNTER_FLAG | + FILTER_ACTION_DROP_FLAG; + return 1; } -/* Determine the "best" filtering mode VIC is capaible of. Returns one of 3 +/* Determine the "best" filtering mode VIC is capaible of. Returns one of 4 * value or 0 on error: + * FILTER_FLOWMAN- flowman api capable * FILTER_DPDK_1- advanced filters availabile * FILTER_USNIC_IP_FLAG - advanced filters but with the restriction that * the IP layer must explicitly specified. I.e. cannot have a UDP @@ -541,23 +655,23 @@ int vnic_dev_capable_adv_filters(struct vnic_dev *vdev) * all other filter types are not available. * Retrun true in filter_tags if supported */ -int vnic_dev_capable_filter_mode(struct vnic_dev *vdev, u32 *mode, - u8 *filter_tags) +int vnic_dev_capable_filter_mode(struct vnic_dev *vdev, uint32_t *mode, + uint8_t *filter_actions) { - u64 args[4]; + uint64_t args[4]; int err; - u32 max_level = 0; + uint32_t max_level = 0; + + /* If flowman is available, use it as it is the most capable API */ + if (vnic_dev_flowman_enable(vdev, mode, filter_actions)) + return 0; err = vnic_dev_advanced_filters_cap(vdev, args, 4); - /* determine if filter tags are available */ - if (err) - *filter_tags = 0; - if ((args[2] == FILTER_CAP_MODE_V1) && - (args[3] & FILTER_ACTION_FILTER_ID_FLAG)) - *filter_tags = 1; - else - *filter_tags = 0; + /* determine supported filter actions */ + *filter_actions = FILTER_ACTION_RQ_STEERING_FLAG; /* always available */ + if (args[2] == FILTER_CAP_MODE_V1) + *filter_actions = args[3]; if (err || ((args[0] == 1) && (args[1] == 0))) { /* Adv filter Command not supported or adv filters available but @@ -582,16 +696,32 @@ int vnic_dev_capable_filter_mode(struct vnic_dev *vdev, u32 *mode, } max_level = args[1]; parse_max_level: - if (max_level >= (u32)FILTER_USNIC_IP) + if (max_level >= (uint32_t)FILTER_USNIC_IP) *mode = FILTER_USNIC_IP; else *mode = FILTER_IPV4_5TUPLE; return 0; } +void vnic_dev_capable_udp_rss_weak(struct vnic_dev *vdev, bool *cfg_chk, + bool *weak) +{ + uint64_t a0 = CMD_NIC_CFG, a1 = 0; + int wait = 1000; + int err; + + *cfg_chk = false; + *weak = false; + err = vnic_dev_cmd(vdev, CMD_CAPABILITY, &a0, &a1, wait); + if (err == 0 && a0 != 0 && a1 != 0) { + *cfg_chk = true; + *weak = !!((a1 >> 32) & CMD_NIC_CFG_CAPF_UDP_WEAK); + } +} + int vnic_dev_capable(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd) { - u64 a0 = (u32)cmd, a1 = 0; + uint64_t a0 = (uint32_t)cmd, a1 = 0; int wait = 1000; int err; @@ -603,7 +733,7 @@ int vnic_dev_capable(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd) int vnic_dev_spec(struct vnic_dev *vdev, unsigned int offset, size_t size, void *value) { - u64 a0, a1; + uint64_t a0, a1; int wait = 1000; int err; @@ -614,16 +744,16 @@ int vnic_dev_spec(struct vnic_dev *vdev, unsigned int offset, size_t size, switch (size) { case 1: - *(u8 *)value = (u8)a0; + *(uint8_t *)value = (uint8_t)a0; break; case 2: - *(u16 *)value = (u16)a0; + *(uint16_t *)value = (uint16_t)a0; break; case 4: - *(u32 *)value = (u32)a0; + *(uint32_t *)value = (uint32_t)a0; break; case 8: - *(u64 *)value = a0; + *(uint64_t *)value = a0; break; default: BUG(); @@ -635,7 +765,7 @@ int vnic_dev_spec(struct vnic_dev *vdev, unsigned int offset, size_t size, int vnic_dev_stats_clear(struct vnic_dev *vdev) { - u64 a0 = 0, a1 = 0; + uint64_t a0 = 0, a1 = 0; int wait = 1000; return vnic_dev_cmd(vdev, CMD_STATS_CLEAR, &a0, &a1, wait); @@ -643,19 +773,11 @@ int vnic_dev_stats_clear(struct vnic_dev *vdev) int vnic_dev_stats_dump(struct vnic_dev *vdev, struct vnic_stats **stats) { - u64 a0, a1; + uint64_t a0, a1; int wait = 1000; - static u32 instance; - char name[NAME_MAX]; - if (!vdev->stats) { - snprintf((char *)name, sizeof(name), - "vnic_stats-%d", instance++); - vdev->stats = vdev->alloc_consistent(vdev->priv, - sizeof(struct vnic_stats), &vdev->stats_pa, (u8 *)name); - if (!vdev->stats) - return -ENOMEM; - } + if (!vdev->stats) + return -ENOMEM; *stats = vdev->stats; a0 = vdev->stats_pa; @@ -666,24 +788,15 @@ int vnic_dev_stats_dump(struct vnic_dev *vdev, struct vnic_stats **stats) int vnic_dev_close(struct vnic_dev *vdev) { - u64 a0 = 0, a1 = 0; + uint64_t a0 = 0, a1 = 0; int wait = 1000; return vnic_dev_cmd(vdev, CMD_CLOSE, &a0, &a1, wait); } -/** Deprecated. @see vnic_dev_enable_wait */ -int vnic_dev_enable(struct vnic_dev *vdev) -{ - u64 a0 = 0, a1 = 0; - int wait = 1000; - - return vnic_dev_cmd(vdev, CMD_ENABLE, &a0, &a1, wait); -} - int vnic_dev_enable_wait(struct vnic_dev *vdev) { - u64 a0 = 0, a1 = 0; + uint64_t a0 = 0, a1 = 0; int wait = 1000; if (vnic_dev_capable(vdev, CMD_ENABLE_WAIT)) @@ -694,7 +807,7 @@ int vnic_dev_enable_wait(struct vnic_dev *vdev) int vnic_dev_disable(struct vnic_dev *vdev) { - u64 a0 = 0, a1 = 0; + uint64_t a0 = 0, a1 = 0; int wait = 1000; return vnic_dev_cmd(vdev, CMD_DISABLE, &a0, &a1, wait); @@ -702,7 +815,7 @@ int vnic_dev_disable(struct vnic_dev *vdev) int vnic_dev_open(struct vnic_dev *vdev, int arg) { - u64 a0 = (u32)arg, a1 = 0; + uint64_t a0 = (uint32_t)arg, a1 = 0; int wait = 1000; return vnic_dev_cmd(vdev, CMD_OPEN, &a0, &a1, wait); @@ -710,7 +823,7 @@ int vnic_dev_open(struct vnic_dev *vdev, int arg) int vnic_dev_open_done(struct vnic_dev *vdev, int *done) { - u64 a0 = 0, a1 = 0; + uint64_t a0 = 0, a1 = 0; int wait = 1000; int err; @@ -725,46 +838,21 @@ int vnic_dev_open_done(struct vnic_dev *vdev, int *done) return 0; } -int vnic_dev_soft_reset(struct vnic_dev *vdev, int arg) -{ - u64 a0 = (u32)arg, a1 = 0; - int wait = 1000; - - return vnic_dev_cmd(vdev, CMD_SOFT_RESET, &a0, &a1, wait); -} - -int vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done) -{ - u64 a0 = 0, a1 = 0; - int wait = 1000; - int err; - - *done = 0; - - err = vnic_dev_cmd(vdev, CMD_SOFT_RESET_STATUS, &a0, &a1, wait); - if (err) - return err; - - *done = (a0 == 0); - - return 0; -} - -int vnic_dev_get_mac_addr(struct vnic_dev *vdev, u8 *mac_addr) +int vnic_dev_get_mac_addr(struct vnic_dev *vdev, uint8_t *mac_addr) { - u64 a0 = 0, a1 = 0; + uint64_t a0 = 0, a1 = 0; int wait = 1000; int err, i; - for (i = 0; i < ETH_ALEN; i++) + for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) mac_addr[i] = 0; err = vnic_dev_cmd(vdev, CMD_GET_MAC_ADDR, &a0, &a1, wait); if (err) return err; - for (i = 0; i < ETH_ALEN; i++) - mac_addr[i] = ((u8 *)&a0)[i]; + for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) + mac_addr[i] = ((uint8_t *)&a0)[i]; return 0; } @@ -772,7 +860,7 @@ int vnic_dev_get_mac_addr(struct vnic_dev *vdev, u8 *mac_addr) int vnic_dev_packet_filter(struct vnic_dev *vdev, int directed, int multicast, int broadcast, int promisc, int allmulti) { - u64 a0, a1 = 0; + uint64_t a0, a1 = 0; int wait = 1000; int err; @@ -789,15 +877,15 @@ int vnic_dev_packet_filter(struct vnic_dev *vdev, int directed, int multicast, return err; } -int vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr) +int vnic_dev_add_addr(struct vnic_dev *vdev, uint8_t *addr) { - u64 a0 = 0, a1 = 0; + uint64_t a0 = 0, a1 = 0; int wait = 1000; int err; int i; - for (i = 0; i < ETH_ALEN; i++) - ((u8 *)&a0)[i] = addr[i]; + for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) + ((uint8_t *)&a0)[i] = addr[i]; err = vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a0, &a1, wait); if (err) @@ -808,15 +896,15 @@ int vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr) return err; } -int vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr) +int vnic_dev_del_addr(struct vnic_dev *vdev, uint8_t *addr) { - u64 a0 = 0, a1 = 0; + uint64_t a0 = 0, a1 = 0; int wait = 1000; int err; int i; - for (i = 0; i < ETH_ALEN; i++) - ((u8 *)&a0)[i] = addr[i]; + for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) + ((uint8_t *)&a0)[i] = addr[i]; err = vnic_dev_cmd(vdev, CMD_ADDR_DEL, &a0, &a1, wait); if (err) @@ -828,9 +916,9 @@ int vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr) } int vnic_dev_set_ig_vlan_rewrite_mode(struct vnic_dev *vdev, - u8 ig_vlan_rewrite_mode) + uint8_t ig_vlan_rewrite_mode) { - u64 a0 = ig_vlan_rewrite_mode, a1 = 0; + uint64_t a0 = ig_vlan_rewrite_mode, a1 = 0; int wait = 1000; if (vnic_dev_capable(vdev, CMD_IG_VLAN_REWRITE_MODE)) @@ -840,19 +928,6 @@ int vnic_dev_set_ig_vlan_rewrite_mode(struct vnic_dev *vdev, return 0; } -int vnic_dev_raise_intr(struct vnic_dev *vdev, u16 intr) -{ - u64 a0 = intr, a1 = 0; - int wait = 1000; - int err; - - err = vnic_dev_cmd(vdev, CMD_IAR, &a0, &a1, wait); - if (err) - pr_err("Failed to raise INTR[%d], err %d\n", intr, err); - - return err; -} - void vnic_dev_set_reset_flag(struct vnic_dev *vdev, int state) { vdev->in_reset = state; @@ -864,9 +939,9 @@ static inline int vnic_dev_in_reset(struct vnic_dev *vdev) } int vnic_dev_notify_setcmd(struct vnic_dev *vdev, - void *notify_addr, dma_addr_t notify_pa, u16 intr) + void *notify_addr, dma_addr_t notify_pa, uint16_t intr) { - u64 a0, a1; + uint64_t a0, a1; int wait = 1000; int r; @@ -876,23 +951,23 @@ int vnic_dev_notify_setcmd(struct vnic_dev *vdev, vdev->notify_pa = notify_pa; } - a0 = (u64)notify_pa; - a1 = ((u64)intr << 32) & 0x0000ffff00000000ULL; + a0 = (uint64_t)notify_pa; + a1 = ((uint64_t)intr << 32) & 0x0000ffff00000000ULL; a1 += sizeof(struct vnic_devcmd_notify); r = vnic_dev_cmd(vdev, CMD_NOTIFY, &a0, &a1, wait); if (!vnic_dev_in_reset(vdev)) - vdev->notify_sz = (r == 0) ? (u32)a1 : 0; + vdev->notify_sz = (r == 0) ? (uint32_t)a1 : 0; return r; } -int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr) +int vnic_dev_notify_set(struct vnic_dev *vdev, uint16_t intr) { void *notify_addr = NULL; dma_addr_t notify_pa = 0; - char name[NAME_MAX]; - static u32 instance; + char name[RTE_MEMZONE_NAMESIZE]; + static uint32_t instance; if (vdev->notify || vdev->notify_pa) { return vnic_dev_notify_setcmd(vdev, vdev->notify, @@ -900,10 +975,10 @@ int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr) } if (!vnic_dev_in_reset(vdev)) { snprintf((char *)name, sizeof(name), - "vnic_notify-%d", instance++); + "vnic_notify-%u", instance++); notify_addr = vdev->alloc_consistent(vdev->priv, sizeof(struct vnic_devcmd_notify), - ¬ify_pa, (u8 *)name); + ¬ify_pa, (uint8_t *)name); if (!notify_addr) return -ENOMEM; } @@ -913,7 +988,7 @@ int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr) int vnic_dev_notify_unsetcmd(struct vnic_dev *vdev) { - u64 a0, a1; + uint64_t a0, a1; int wait = 1000; int err; @@ -945,10 +1020,10 @@ int vnic_dev_notify_unset(struct vnic_dev *vdev) static int vnic_dev_notify_ready(struct vnic_dev *vdev) { - u32 *words; + uint32_t *words; unsigned int nwords = vdev->notify_sz / 4; unsigned int i; - u32 csum; + uint32_t csum; if (!vdev->notify || !vdev->notify_sz) return 0; @@ -956,7 +1031,7 @@ static int vnic_dev_notify_ready(struct vnic_dev *vdev) do { csum = 0; rte_memcpy(&vdev->notify_copy, vdev->notify, vdev->notify_sz); - words = (u32 *)&vdev->notify_copy; + words = (uint32_t *)&vdev->notify_copy; for (i = 1; i < nwords; i++) csum += words[i]; } while (csum != words[0]); @@ -966,7 +1041,7 @@ static int vnic_dev_notify_ready(struct vnic_dev *vdev) int vnic_dev_init(struct vnic_dev *vdev, int arg) { - u64 a0 = (u32)arg, a1 = 0; + uint64_t a0 = (uint32_t)arg, a1 = 0; int wait = 1000; int r = 0; @@ -985,14 +1060,6 @@ int vnic_dev_init(struct vnic_dev *vdev, int arg) return r; } -int vnic_dev_deinit(struct vnic_dev *vdev) -{ - u64 a0 = 0, a1 = 0; - int wait = 1000; - - return vnic_dev_cmd(vdev, CMD_DEINIT, &a0, &a1, wait); -} - void vnic_dev_intr_coal_timer_info_default(struct vnic_dev *vdev) { /* Default: hardware intr coal timer is in units of 1.5 usecs */ @@ -1010,7 +1077,7 @@ int vnic_dev_link_status(struct vnic_dev *vdev) return vdev->notify_copy.link_state; } -u32 vnic_dev_port_speed(struct vnic_dev *vdev) +uint32_t vnic_dev_port_speed(struct vnic_dev *vdev) { if (!vnic_dev_notify_ready(vdev)) return 0; @@ -1018,35 +1085,53 @@ u32 vnic_dev_port_speed(struct vnic_dev *vdev) return vdev->notify_copy.port_speed; } -void vnic_dev_set_intr_mode(struct vnic_dev *vdev, - enum vnic_dev_intr_mode intr_mode) +uint32_t vnic_dev_mtu(struct vnic_dev *vdev) { - vdev->intr_mode = intr_mode; + if (!vnic_dev_notify_ready(vdev)) + return 0; + + return vdev->notify_copy.mtu; } -enum vnic_dev_intr_mode vnic_dev_get_intr_mode( - struct vnic_dev *vdev) +uint32_t vnic_dev_uif(struct vnic_dev *vdev) { - return vdev->intr_mode; + if (!vnic_dev_notify_ready(vdev)) + return 0; + + return vdev->notify_copy.uif; } -u32 vnic_dev_intr_coal_timer_usec_to_hw(struct vnic_dev *vdev, u32 usec) +uint32_t vnic_dev_intr_coal_timer_usec_to_hw(struct vnic_dev *vdev, + uint32_t usec) { return (usec * vdev->intr_coal_timer_info.mul) / vdev->intr_coal_timer_info.div; } -u32 vnic_dev_intr_coal_timer_hw_to_usec(struct vnic_dev *vdev, u32 hw_cycles) +uint32_t vnic_dev_intr_coal_timer_hw_to_usec(struct vnic_dev *vdev, + uint32_t hw_cycles) { return (hw_cycles * vdev->intr_coal_timer_info.div) / vdev->intr_coal_timer_info.mul; } -u32 vnic_dev_get_intr_coal_timer_max(struct vnic_dev *vdev) +uint32_t vnic_dev_get_intr_coal_timer_max(struct vnic_dev *vdev) { return vdev->intr_coal_timer_info.max_usec; } +int vnic_dev_alloc_stats_mem(struct vnic_dev *vdev) +{ + char name[RTE_MEMZONE_NAMESIZE]; + static uint32_t instance; + + snprintf((char *)name, sizeof(name), "vnic_stats-%u", instance++); + vdev->stats = vdev->alloc_consistent(vdev->priv, + sizeof(struct vnic_stats), + &vdev->stats_pa, (uint8_t *)name); + return vdev->stats == NULL ? -ENOMEM : 0; +} + void vnic_dev_unregister(struct vnic_dev *vdev) { if (vdev) { @@ -1059,6 +1144,10 @@ void vnic_dev_unregister(struct vnic_dev *vdev) vdev->free_consistent(vdev->priv, sizeof(struct vnic_stats), vdev->stats, vdev->stats_pa); + if (vdev->flowman_info) + vdev->free_consistent(vdev->priv, + sizeof(struct fm_info), + vdev->flowman_info, vdev->flowman_info_pa); if (vdev->fw_info) vdev->free_consistent(vdev->priv, sizeof(struct vnic_devcmd_fw_info), @@ -1072,7 +1161,7 @@ struct vnic_dev *vnic_dev_register(struct vnic_dev *vdev, unsigned int num_bars) { if (!vdev) { - char name[NAME_MAX]; + char name[RTE_MEMZONE_NAMESIZE]; snprintf((char *)name, sizeof(name), "%s-vnic", pdev->device.name); vdev = (struct vnic_dev *)rte_zmalloc_socket(name, @@ -1100,21 +1189,21 @@ err_out: return NULL; } -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) { - return vdev->pdev; -} + struct vnic_dev *vdev; -int vnic_dev_set_mac_addr(struct vnic_dev *vdev, u8 *mac_addr) -{ - u64 a0, a1 = 0; - int wait = 1000; - int i; - - for (i = 0; i < ETH_ALEN; i++) - ((u8 *)&a0)[i] = mac_addr[i]; - - return vnic_dev_cmd(vdev, CMD_SET_MAC_ADDR, &a0, &a1, wait); + 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; } /* @@ -1132,16 +1221,16 @@ int vnic_dev_set_mac_addr(struct vnic_dev *vdev, u8 *mac_addr) * @data: filter data * @action: action data */ -int vnic_dev_classifier(struct vnic_dev *vdev, u8 cmd, u16 *entry, +int vnic_dev_classifier(struct vnic_dev *vdev, uint8_t cmd, uint16_t *entry, struct filter_v2 *data, struct filter_action_v2 *action_v2) { - u64 a0 = 0, a1 = 0; + uint64_t a0 = 0, a1 = 0; int wait = 1000; dma_addr_t tlv_pa; int ret = -EINVAL; struct filter_tlv *tlv, *tlv_va; - u64 tlv_size; - u32 filter_size, action_size; + uint64_t tlv_size; + uint32_t filter_size, action_size; static unsigned int unique_id; char z_name[RTE_MEMZONE_NAMESIZE]; enum vnic_devcmd_cmd dev_cmd; @@ -1156,9 +1245,9 @@ int vnic_dev_classifier(struct vnic_dev *vdev, u8 cmd, u16 *entry, tlv_size = filter_size + action_size + 2*sizeof(struct filter_tlv); snprintf((char *)z_name, sizeof(z_name), - "vnic_clsf_%d", unique_id++); + "vnic_clsf_%u", unique_id++); tlv_va = vdev->alloc_consistent(vdev->priv, - tlv_size, &tlv_pa, (u8 *)z_name); + tlv_size, &tlv_pa, (uint8_t *)z_name); if (!tlv_va) return -ENOMEM; tlv = tlv_va; @@ -1177,7 +1266,7 @@ int vnic_dev_classifier(struct vnic_dev *vdev, u8 cmd, u16 *entry, tlv->length = action_size; memcpy(&tlv->val, (void *)action_v2, action_size); ret = vnic_dev_cmd(vdev, dev_cmd, &a0, &a1, wait); - *entry = (u16)a0; + *entry = (uint16_t)a0; vdev->free_consistent(vdev->priv, tlv_size, tlv_va, tlv_pa); } else if (cmd == CLSF_DEL) { a0 = *entry; @@ -1186,3 +1275,48 @@ int vnic_dev_classifier(struct vnic_dev *vdev, u8 cmd, u16 *entry, return ret; } + +int vnic_dev_overlay_offload_ctrl(struct vnic_dev *vdev, uint8_t overlay, + uint8_t config) +{ + uint64_t a0 = overlay; + uint64_t a1 = config; + int wait = 1000; + + return vnic_dev_cmd(vdev, CMD_OVERLAY_OFFLOAD_CTRL, &a0, &a1, wait); +} + +int vnic_dev_overlay_offload_cfg(struct vnic_dev *vdev, uint8_t overlay, + uint16_t vxlan_udp_port_number) +{ + uint64_t a1 = vxlan_udp_port_number; + uint64_t a0 = overlay; + int wait = 1000; + + return vnic_dev_cmd(vdev, CMD_OVERLAY_OFFLOAD_CFG, &a0, &a1, wait); +} + +int vnic_dev_capable_vxlan(struct vnic_dev *vdev) +{ + uint64_t a0 = VIC_FEATURE_VXLAN; + uint64_t a1 = 0; + int wait = 1000; + int ret; + + ret = vnic_dev_cmd(vdev, CMD_GET_SUPP_FEATURE_VER, &a0, &a1, wait); + /* 1 if the NIC can do VXLAN for both IPv4 and IPv6 with multiple WQs */ + return ret == 0 && + (a1 & (FEATURE_VXLAN_IPV6 | FEATURE_VXLAN_MULTI_WQ)) == + (FEATURE_VXLAN_IPV6 | FEATURE_VXLAN_MULTI_WQ); +} + +int vnic_dev_capable_geneve(struct vnic_dev *vdev) +{ + uint64_t a0 = VIC_FEATURE_GENEVE; + uint64_t a1 = 0; + int wait = 1000; + int ret; + + ret = vnic_dev_cmd(vdev, CMD_GET_SUPP_FEATURE_VER, &a0, &a1, wait); + return ret == 0 && (a1 & FEATURE_GENEVE_OPTIONS); +}