aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDoug Ambrisko <ambrisko@FreeBSD.org>2025-01-09 16:28:37 +0000
committerDoug Ambrisko <ambrisko@FreeBSD.org>2025-01-09 16:52:54 +0000
commit0acab8b3d1336d4db73a9946ef76b4bcd0b0aabe (patch)
tree5248907e9b002263627d3a522eb1b4d547d4c14b
parentfb98fc4755def2cb8ca145751b0e54485d5e2f4a (diff)
enic(4): fix down/up, MTU changes and more
ifconfig down/up cycles was not working. Fix that which is required to support MTU changes. Now doing ifconfig enic0 mtu 3000 for example works. If the MTU is changes in the VIC HW configuration, that is not reflected in and the OS reports the default 1500. I need to look at that but changing it via ifconfig works. So this is different then what Linux does. Change TX interrupt allocation to be in this driver. Change the admin interrupt count to 2. This make multiple queues work but need to be done as pairs so if the VIC has more TX or RX queues setup in the VIC configuration it will use the lesser value. While updating the TX interrupt also add support for devcmd2. Enable checksum offloading. PR: 282095
-rw-r--r--sys/dev/enic/cq_desc.h15
-rw-r--r--sys/dev/enic/enic.h76
-rw-r--r--sys/dev/enic/enic_res.c4
-rw-r--r--sys/dev/enic/enic_res.h2
-rw-r--r--sys/dev/enic/enic_txrx.c39
-rw-r--r--sys/dev/enic/if_enic.c173
-rw-r--r--sys/dev/enic/vnic_cq.h5
-rw-r--r--sys/dev/enic/vnic_dev.c235
-rw-r--r--sys/dev/enic/vnic_dev.h8
-rw-r--r--sys/dev/enic/vnic_intr.c2
-rw-r--r--sys/dev/enic/vnic_intr.h2
-rw-r--r--sys/dev/enic/vnic_resource.h1
-rw-r--r--sys/dev/enic/vnic_rq.c5
-rw-r--r--sys/dev/enic/vnic_rq.h1
-rw-r--r--sys/dev/enic/vnic_rss.h5
-rw-r--r--sys/dev/enic/vnic_wq.c104
-rw-r--r--sys/dev/enic/vnic_wq.h18
17 files changed, 559 insertions, 136 deletions
diff --git a/sys/dev/enic/cq_desc.h b/sys/dev/enic/cq_desc.h
index ae8847c6d9a1..4fb8cce7212e 100644
--- a/sys/dev/enic/cq_desc.h
+++ b/sys/dev/enic/cq_desc.h
@@ -44,14 +44,6 @@ struct cq_desc {
#define CQ_DESC_COMP_NDX_BITS 12
#define CQ_DESC_COMP_NDX_MASK ((1 << CQ_DESC_COMP_NDX_BITS) - 1)
-static inline void cq_color_enc(struct cq_desc *desc, const u8 color)
-{
- if (color)
- desc->type_color |= (1 << CQ_DESC_COLOR_SHIFT);
- else
- desc->type_color &= ~(1 << CQ_DESC_COLOR_SHIFT);
-}
-
static inline void cq_desc_enc(struct cq_desc *desc,
const u8 type, const u8 color, const u16 q_number,
const u16 completed_index)
@@ -87,11 +79,4 @@ static inline void cq_desc_dec(const struct cq_desc *desc_arg,
CQ_DESC_COMP_NDX_MASK;
}
-static inline void cq_color_dec(const struct cq_desc *desc_arg, u8 *color)
-{
- volatile const struct cq_desc *desc = desc_arg;
-
- *color = (desc->type_color >> CQ_DESC_COLOR_SHIFT) & CQ_DESC_COLOR_MASK;
-}
-
#endif /* _CQ_DESC_H_ */
diff --git a/sys/dev/enic/enic.h b/sys/dev/enic/enic.h
index 8c2212726548..eec6de823c9d 100644
--- a/sys/dev/enic/enic.h
+++ b/sys/dev/enic/enic.h
@@ -108,13 +108,13 @@ struct vnic_res {
#define ENIC_DEFAULT_VXLAN_PORT 4789
/*
- * Interrupt 0: LSC and errors
* Interrupt 1: rx queue 0
* Interrupt 2: rx queue 1
* ...
+ * Interrupt x: LSC and errors
*/
#define ENICPMD_LSC_INTR_OFFSET 0
-#define ENICPMD_RXQ_INTR_OFFSET 1
+#define ENICPMD_RXQ_INTR_OFFSET 0
#include "vnic_devcmd.h"
@@ -152,6 +152,9 @@ struct vnic_dev {
u64 args[VNIC_DEVCMD_NARGS];
int in_reset;
struct vnic_intr_coal_timer_info intr_coal_timer_info;
+ struct devcmd2_controller *devcmd2;
+ int (*devcmd_rtn)(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
+ int wait);
void *(*alloc_consistent)(void *priv, size_t size,
bus_addr_t *dma_handle, struct iflib_dma_info *res, u8 *name);
void (*free_consistent)(void *priv, size_t size, void *vaddr,
@@ -175,6 +178,28 @@ struct intr_queue {
struct enic_softc *softc;
};
+#define ENIC_MAX_LINK_SPEEDS 3
+#define ENIC_LINK_SPEED_10G 10000
+#define ENIC_LINK_SPEED_4G 4000
+#define ENIC_LINK_40G_INDEX 2
+#define ENIC_LINK_10G_INDEX 1
+#define ENIC_LINK_4G_INDEX 0
+#define ENIC_RX_COALESCE_RANGE_END 125
+#define ENIC_AIC_TS_BREAK 100
+
+struct enic_rx_coal {
+ u32 small_pkt_range_start;
+ u32 large_pkt_range_start;
+ u32 range_end;
+ u32 use_adaptive_rx_coalesce;
+};
+
+/* Store only the lower range. Higher range is given by fw. */
+struct enic_intr_mod_range {
+ u32 small_pkt_range_start;
+ u32 large_pkt_range_start;
+};
+
struct enic {
struct enic *next;
struct rte_pci_device *pdev;
@@ -267,6 +292,9 @@ struct enic {
uint64_t tx_offload_mask; /* PKT_TX flags accepted */
struct enic_softc *softc;
int port_mtu;
+ struct enic_rx_coal rx_coalesce_setting;
+ u32 rx_coalesce_usecs;
+ u32 tx_coalesce_usecs;
};
struct enic_softc {
@@ -307,11 +335,6 @@ struct enic_softc {
/* Per-instance private data structure */
-static inline unsigned int enic_vnic_rq_count(struct enic *enic)
-{
- return enic->rq_count;
-}
-
static inline unsigned int enic_cq_rq(struct enic *enic, unsigned int rq)
{
return rq;
@@ -323,21 +346,6 @@ static inline unsigned int enic_cq_wq(struct enic *enic, unsigned int wq)
}
static inline uint32_t
-enic_ring_add(uint32_t n_descriptors, uint32_t i0, uint32_t i1)
-{
- uint32_t d = i0 + i1;
- d -= (d >= n_descriptors) ? n_descriptors : 0;
- return d;
-}
-
-static inline uint32_t
-enic_ring_sub(uint32_t n_descriptors, uint32_t i0, uint32_t i1)
-{
- int32_t d = i1 - i0;
- return (uint32_t)((d < 0) ? ((int32_t)n_descriptors + d) : d);
-}
-
-static inline uint32_t
enic_ring_incr(uint32_t n_descriptors, uint32_t idx)
{
idx++;
@@ -346,34 +354,14 @@ enic_ring_incr(uint32_t n_descriptors, uint32_t idx)
return idx;
}
-void enic_free_wq(void *txq);
-int enic_alloc_intr_resources(struct enic *enic);
int enic_setup_finish(struct enic *enic);
-int enic_alloc_wq(struct enic *enic, uint16_t queue_idx,
- unsigned int socket_id, uint16_t nb_desc);
void enic_start_wq(struct enic *enic, uint16_t queue_idx);
int enic_stop_wq(struct enic *enic, uint16_t queue_idx);
void enic_start_rq(struct enic *enic, uint16_t queue_idx);
-void enic_free_rq(void *rxq);
-int enic_set_vnic_res(struct enic *enic);
-int enic_init_rss_nic_cfg(struct enic *enic);
-int enic_set_rss_reta(struct enic *enic, union vnic_rss_cpu *rss_cpu);
-int enic_set_vlan_strip(struct enic *enic);
+int enic_stop_rq(struct enic *enic, uint16_t queue_idx);
+void enic_dev_disable(struct enic *enic);
int enic_enable(struct enic *enic);
int enic_disable(struct enic *enic);
-void enic_remove(struct enic *enic);
-int enic_get_link_status(struct enic *enic);
-void enic_dev_stats_clear(struct enic *enic);
-void enic_add_packet_filter(struct enic *enic);
-int enic_set_mac_address(struct enic *enic, uint8_t *mac_addr);
-int enic_del_mac_address(struct enic *enic, int mac_index);
-unsigned int enic_cleanup_wq(struct enic *enic, struct vnic_wq *wq);
-
-void enic_post_wq_index(struct vnic_wq *wq);
-int enic_probe(struct enic *enic);
-int enic_clsf_init(struct enic *enic);
-void enic_clsf_destroy(struct enic *enic);
-int enic_set_mtu(struct enic *enic, uint16_t new_mtu);
int enic_link_update(struct enic *enic);
bool enic_use_vector_rx_handler(struct enic *enic);
void enic_fdir_info(struct enic *enic);
diff --git a/sys/dev/enic/enic_res.c b/sys/dev/enic/enic_res.c
index d264874557a0..413873ad0fb4 100644
--- a/sys/dev/enic/enic_res.c
+++ b/sys/dev/enic/enic_res.c
@@ -95,11 +95,11 @@ int enic_get_vnic_config(struct enic *enic)
dev_info(enic_get_dev(enic),
"vNIC MAC addr %02x:%02x:%02x:%02x:%02x:%02x "
- "wq/rq %d/%d mtu d, max mtu:%d\n",
+ "wq/rq %d/%d mtu %d, max mtu:%d\n",
enic->mac_addr[0], enic->mac_addr[1], enic->mac_addr[2],
enic->mac_addr[3], enic->mac_addr[4], enic->mac_addr[5],
c->wq_desc_count, c->rq_desc_count,
- /* enic->rte_dev->data->mtu, */ enic->max_mtu);
+ c->mtu, enic->max_mtu);
dev_info(enic_get_dev(enic), "vNIC csum tx/rx %s/%s "
"rss %s intr mode %s type %s timer %d usec "
"loopback tag 0x%04x\n",
diff --git a/sys/dev/enic/enic_res.h b/sys/dev/enic/enic_res.h
index 1a6f3a3ca98f..82963e61a44f 100644
--- a/sys/dev/enic/enic_res.h
+++ b/sys/dev/enic/enic_res.h
@@ -67,7 +67,5 @@ int enic_set_nic_cfg(struct enic *enic, u8 rss_default_cpu, u8 rss_hash_type,
u8 ig_vlan_strip_en);
void enic_get_res_counts(struct enic *enic);
void enic_init_vnic_resources(struct enic *enic);
-int enic_alloc_vnic_resources(struct enic *);
-void enic_free_vnic_resources(struct enic *);
#endif /* _ENIC_RES_H_ */
diff --git a/sys/dev/enic/enic_txrx.c b/sys/dev/enic/enic_txrx.c
index 5a557fc7f94a..169041587d06 100644
--- a/sys/dev/enic/enic_txrx.c
+++ b/sys/dev/enic/enic_txrx.c
@@ -103,6 +103,7 @@ enic_isc_txd_encap(void *vsc, if_pkt_info_t pi)
softc = vsc;
enic = &softc->enic;
+ if_softc_ctx_t scctx = softc->scctx;
wq = &enic->wq[pi->ipi_qsidx];
nsegs = pi->ipi_nsegs;
@@ -112,6 +113,9 @@ enic_isc_txd_encap(void *vsc, if_pkt_info_t pi)
head_idx = wq->head_idx;
desc_count = wq->ring.desc_count;
+ if ((scctx->isc_capenable & IFCAP_RXCSUM) != 0)
+ offload_mode |= WQ_ENET_OFFLOAD_MODE_CSUM;
+
for (i = 0; i < nsegs; i++) {
eop = 0;
cq = 0;
@@ -320,7 +324,7 @@ enic_isc_rxd_flush(void *vsc, uint16_t rxqid, uint8_t flid, qidx_t pidx)
static int
enic_legacy_intr(void *xsc)
{
- return -1;
+ return (1);
}
static inline void
@@ -375,7 +379,7 @@ enic_wq_service(struct vnic_dev *vdev, struct cq_desc *cq_desc, u8 type,
vnic_wq_service(&enic->wq[q_number], cq_desc,
completed_index, NULL, opaque);
- return 0;
+ return (0);
}
static void
@@ -384,7 +388,7 @@ vnic_rq_service(struct vnic_rq *rq, struct cq_desc *cq_desc,
void(*buf_service)(struct vnic_rq *rq, struct cq_desc *cq_desc,
/* struct vnic_rq_buf * *buf, */ int skipped, void *opaque), void *opaque)
{
-
+ if_softc_ctx_t scctx;
if_rxd_info_t ri = (if_rxd_info_t) opaque;
u8 type, color, eop, sop, ingress_port, vlan_stripped;
u8 fcoe, fcoe_sof, fcoe_fc_crc_ok, fcoe_enc_error, fcoe_eof;
@@ -396,6 +400,8 @@ vnic_rq_service(struct vnic_rq *rq, struct cq_desc *cq_desc,
int cqidx;
if_rxd_frag_t frag;
+ scctx = rq->vdev->softc->scctx;
+
cq_enet_rq_desc_dec((struct cq_enet_rq_desc *)cq_desc,
&type, &color, &q_number, &completed_index,
&ingress_port, &fcoe, &eop, &sop, &rss_type,
@@ -419,6 +425,11 @@ vnic_rq_service(struct vnic_rq *rq, struct cq_desc *cq_desc,
ri->iri_cidx = cqidx;
ri->iri_nfrags = 1;
ri->iri_len = bytes_written;
+
+ if ((scctx->isc_capenable & IFCAP_RXCSUM) != 0)
+ if (!csum_not_calc && (tcp_udp_csum_ok || ipv4_csum_ok)) {
+ ri->iri_csum_flags = (CSUM_IP_CHECKED | CSUM_IP_VALID);
+ }
}
static int
@@ -431,7 +442,7 @@ enic_rq_service(struct vnic_dev *vdev, struct cq_desc *cq_desc,
vnic_rq_service(&enic->rq[ri->iri_qsidx], cq_desc, completed_index,
VNIC_RQ_RETURN_DESC, NULL, /* enic_rq_indicate_buf, */ opaque);
- return 0;
+ return (0);
}
void
@@ -468,10 +479,8 @@ enic_stop_wq(struct enic *enic, uint16_t queue_idx)
int ret;
ret = vnic_wq_disable(&enic->wq[queue_idx]);
- if (ret)
- return ret;
- return 0;
+ return (ret);
}
void
@@ -483,3 +492,19 @@ enic_start_rq(struct enic *enic, uint16_t queue_idx)
vnic_rq_enable(rq);
enic_initial_post_rx(enic, rq);
}
+
+int
+enic_stop_rq(struct enic *enic, uint16_t queue_idx)
+{
+ int ret;
+
+ ret = vnic_rq_disable(&enic->rq[queue_idx]);
+
+ return (ret);
+}
+
+
+void
+enic_dev_disable(struct enic *enic) {
+ vnic_dev_disable(enic->vdev);
+}
diff --git a/sys/dev/enic/if_enic.c b/sys/dev/enic/if_enic.c
index dc0c0d028e20..26776244778e 100644
--- a/sys/dev/enic/if_enic.c
+++ b/sys/dev/enic/if_enic.c
@@ -201,11 +201,11 @@ static struct if_shared_ctx enic_sctx_init = {
* descriptor */
.isc_rx_nsegments = 1, /* One mapping per descriptor */
.isc_rx_maxsegsize = ENIC_DEFAULT_RX_MAX_PKT_SIZE,
- .isc_admin_intrcnt = 3,
+ .isc_admin_intrcnt = 2,
.isc_vendor_info = enic_vendor_info_array,
.isc_driver_version = "1",
.isc_driver = &enic_iflib_driver,
- .isc_flags = IFLIB_HAS_RXCQ | IFLIB_HAS_TXCQ,
+ .isc_flags = IFLIB_HAS_RXCQ | IFLIB_HAS_TXCQ | IFLIB_SKIP_MSIX,
/*
* Number of receive queues per receive queue set, with associated
@@ -236,6 +236,99 @@ enic_register(device_t dev)
}
static int
+enic_allocate_msix(struct enic_softc *softc) {
+ if_ctx_t ctx;
+ if_softc_ctx_t scctx;
+ if_shared_ctx_t sctx;
+ device_t dev;
+ cpuset_t cpus;
+ int queues, vectors, requested;
+ int err = 0;
+
+ dev = softc->dev;
+ ctx = softc->ctx;
+ scctx = softc->scctx;
+ sctx = iflib_get_sctx(ctx);
+
+ if (bus_get_cpus(dev, INTR_CPUS, sizeof(cpus), &cpus) != 0) {
+ device_printf(dev, "Unable to fetch CPU list\n");
+ CPU_COPY(&all_cpus, &cpus);
+ }
+
+
+ queues = CPU_COUNT(&cpus);
+ queues = imin(queues, scctx->isc_nrxqsets);
+ queues = imin(queues, scctx->isc_ntxqsets);
+ requested = queues * 2 + sctx->isc_admin_intrcnt;
+ scctx->isc_nrxqsets = queues;
+ scctx->isc_ntxqsets = queues;
+
+ vectors = requested;
+ if ((err = pci_alloc_msix(dev, &vectors)) != 0) {
+ device_printf(dev,
+ "failed to allocate %d MSI-X vectors, err: %d\n", requested,
+ err);
+ err = 1;
+ goto enic_allocate_msix_out;
+ } else {
+ if (vectors != requested) {
+ device_printf(dev,
+ "Unable to allocate sufficient MSI-X vectors "
+ "(got %d, need %d)\n", requested, vectors);
+ pci_release_msi(dev);
+ err = 1;
+ goto enic_allocate_msix_out;
+ }
+ }
+
+ device_printf(dev, "Using MSI-X interrupts with %d vectors\n",
+ vectors);
+
+ scctx->isc_intr = IFLIB_INTR_MSIX;
+ scctx->isc_vectors = vectors;
+
+enic_allocate_msix_out:
+ return (err);
+
+}
+
+static struct enic_intr_mod_range mod_range[ENIC_MAX_LINK_SPEEDS] = {
+ {0, 0}, /* 0 - 4 Gbps */
+ {0, 3}, /* 4 - 10 Gbps */
+ {3, 6}, /* 10 - 40 Gbps */
+};
+
+static void enic_set_rx_coal_setting(struct enic *enic)
+{
+ unsigned int speed;
+ int index = -1;
+ struct enic_rx_coal *rx_coal = &enic->rx_coalesce_setting;
+
+ /* 1. Read the link speed from fw
+ * 2. Pick the default range for the speed
+ * 3. Update it in enic->rx_coalesce_setting
+ */
+ speed = vnic_dev_port_speed(enic->vdev);
+ if (ENIC_LINK_SPEED_10G < speed)
+ index = ENIC_LINK_40G_INDEX;
+ else if (ENIC_LINK_SPEED_4G < speed)
+ index = ENIC_LINK_10G_INDEX;
+ else
+ index = ENIC_LINK_4G_INDEX;
+
+ rx_coal->small_pkt_range_start = mod_range[index].small_pkt_range_start;
+ rx_coal->large_pkt_range_start = mod_range[index].large_pkt_range_start;
+ rx_coal->range_end = ENIC_RX_COALESCE_RANGE_END;
+
+ /* Start with the value provided by UCSM */
+ for (index = 0; index < enic->rq_count; index++)
+ enic->cq[index].cur_rx_coal_timeval =
+ enic->config.intr_timer_usec;
+
+ rx_coal->use_adaptive_rx_coalesce = 1;
+}
+
+static int
enic_attach_pre(if_ctx_t ctx)
{
if_softc_ctx_t scctx;
@@ -283,6 +376,8 @@ enic_attach_pre(if_ctx_t ctx)
ENIC_LOCK(softc);
vnic_dev_register(vdev, &softc->mem, 1);
enic->vdev = vdev;
+ vnic_dev_cmd_init(enic->vdev);
+
vdev->devcmd = vnic_dev_get_res(vdev, RES_TYPE_DEVCMD, 0);
vnic_dev_cmd(vdev, CMD_INIT_v1, &a0, &a1, wait);
@@ -326,6 +421,7 @@ enic_attach_pre(if_ctx_t ctx)
/* Set ingress vlan rewrite mode before vnic initialization */
enic->ig_vlan_rewrite_mode = IG_VLAN_REWRITE_MODE_UNTAG_DEFAULT_VLAN;
+ enic->ig_vlan_rewrite_mode = IG_VLAN_REWRITE_MODE_PRIORITY_TAG_DEFAULT_VLAN;
err = vnic_dev_set_ig_vlan_rewrite_mode(enic->vdev,
enic->ig_vlan_rewrite_mode);
if (err) {
@@ -360,8 +456,10 @@ enic_attach_pre(if_ctx_t ctx)
softc->scctx = iflib_get_softc_ctx(ctx);
scctx = softc->scctx;
scctx->isc_txrx = &enic_txrx;
- scctx->isc_capabilities = scctx->isc_capenable = 0;
+ scctx->isc_capabilities = scctx->isc_capenable = \
+ IFCAP_HWCSUM;
scctx->isc_tx_csum_flags = 0;
+ if_setmtu(softc->ifp, enic->config.mtu);
scctx->isc_max_frame_size = enic->config.mtu + ETHER_HDR_LEN + \
ETHER_CRC_LEN;
scctx->isc_nrxqsets_max = enic->conf_rq_count;
@@ -389,7 +487,6 @@ enic_attach_pre(if_ctx_t ctx)
}
scctx->isc_tx_nsegments = 31;
- scctx->isc_vectors = enic->conf_cq_count;
scctx->isc_msix_bar = -1;
ifmedia_add(softc->media, IFM_ETHER | IFM_AUTO, 0, NULL);
@@ -416,12 +513,20 @@ enic_attach_pre(if_ctx_t ctx)
err = vnic_dev_alloc_stats_mem(enic->vdev);
if (err) {
dev_err(enic, "Failed to allocate cmd memory, aborting\n");
+ goto err_out_dev_close;
+ }
+
+ err = enic_allocate_msix(softc);
+ if (err) {
+ dev_err(enic, "Failed to allocate MSIX, aborting\n");
+ goto err_out_dev_close;
}
return (rc);
err_out_dev_close:
vnic_dev_close(enic->vdev);
+ vnic_dev_deinit_devcmd2(enic->vdev);
err_out_unregister:
free(softc->vdev.devcmd, M_DEVBUF);
free(softc->enic.intr_queues, M_DEVBUF);
@@ -482,9 +587,10 @@ enic_msix_intr_assign(if_ctx_t ctx, int msix)
snprintf(irq_name, sizeof(irq_name), "etxq%d:%d", i -
scctx->isc_nrxqsets, device_get_unit(softc->dev));
-
- iflib_softirq_alloc_generic(ctx, &enic->intr_queues[i].intr_irq, IFLIB_INTR_TX, &enic->wq[i - scctx->isc_nrxqsets], i - scctx->isc_nrxqsets, irq_name);
-
+ iflib_softirq_alloc_generic(ctx,
+ &enic->intr_queues[i].intr_irq, IFLIB_INTR_TX,
+ &enic->wq[i - scctx->isc_nrxqsets], i - scctx->isc_nrxqsets,
+ irq_name);
enic->intr[i].index = i;
enic->intr[i].vdev = enic->vdev;
@@ -567,6 +673,7 @@ enic_attach_post(if_ctx_t ctx)
enic_setup_sysctl(softc);
enic_init_vnic_resources(enic);
+ enic_set_rx_coal_setting(enic);
enic_setup_finish(enic);
ifmedia_add(softc->media, IFM_ETHER | IFM_AUTO, 0, NULL);
@@ -589,7 +696,9 @@ enic_detach(if_ctx_t ctx)
enic_free_irqs(softc);
ENIC_LOCK(softc);
+ vnic_dev_deinit(enic->vdev);
vnic_dev_close(enic->vdev);
+ vnic_dev_deinit_devcmd2(enic->vdev);
free(softc->vdev.devcmd, M_DEVBUF);
pci_disable_busmaster(softc->dev);
enic_pci_mapping_free(softc);
@@ -807,6 +916,11 @@ enic_stop(if_ctx_t ctx)
struct enic *enic;
if_softc_ctx_t scctx;
unsigned int index;
+ struct vnic_wq *wq;
+ struct vnic_rq *rq;
+ struct vnic_cq *cq;
+ unsigned int cq_wq, cq_rq;
+
softc = iflib_get_softc(ctx);
scctx = softc->scctx;
@@ -817,15 +931,36 @@ enic_stop(if_ctx_t ctx)
softc->link_active = 0;
softc->stopped = 1;
+ enic_dev_disable(enic);
+
for (index = 0; index < scctx->isc_ntxqsets; index++) {
enic_stop_wq(enic, index);
vnic_wq_clean(&enic->wq[index]);
vnic_cq_clean(&enic->cq[enic_cq_rq(enic, index)]);
+
+ wq = &softc->enic.wq[index];
+ wq->ring.desc_avail = wq->ring.desc_count - 1;
+ wq->ring.last_count = wq->ring.desc_count;
+ wq->head_idx = 0;
+ wq->tail_idx = 0;
+
+ cq_wq = enic_cq_wq(&softc->enic, index);
+ cq = &softc->enic.cq[cq_wq];
+ cq->ring.desc_avail = cq->ring.desc_count - 1;
}
for (index = 0; index < scctx->isc_nrxqsets; index++) {
+ enic_stop_rq(enic, index);
vnic_rq_clean(&enic->rq[index]);
vnic_cq_clean(&enic->cq[enic_cq_wq(enic, index)]);
+
+ rq = &softc->enic.rq[index];
+ cq_rq = enic_cq_rq(&softc->enic, index);
+ cq = &softc->enic.cq[cq_rq];
+
+ cq->ring.desc_avail = cq->ring.desc_count - 1;
+ rq->ring.desc_avail = rq->ring.desc_count - 1;
+ rq->need_initial_post = true;
}
for (index = 0; index < scctx->isc_vectors; index++) {
@@ -845,6 +980,9 @@ enic_init(if_ctx_t ctx)
scctx = softc->scctx;
enic = &softc->enic;
+
+ enic_init_vnic_resources(enic);
+
for (index = 0; index < scctx->isc_ntxqsets; index++)
enic_prep_wq_for_simple_tx(&softc->enic, index);
@@ -862,6 +1000,8 @@ enic_init(if_ctx_t ctx)
vnic_dev_enable_wait(enic->vdev);
ENIC_UNLOCK(softc);
+ softc->stopped = 0;
+
enic_link_status(softc);
}
@@ -942,12 +1082,14 @@ enic_mtu_set(if_ctx_t ctx, uint32_t mtu)
softc = iflib_get_softc(ctx);
enic = &softc->enic;
+ enic_stop(softc->ctx);
if (mtu > enic->port_mtu){
return (EINVAL);
}
enic->config.mtu = mtu;
scctx->isc_max_frame_size = mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;
+ enic_init(softc->ctx);
return (0);
}
@@ -1026,7 +1168,6 @@ static void
enic_update_admin_status(if_ctx_t ctx)
{
struct enic_softc *softc;
-
softc = iflib_get_softc(ctx);
enic_link_status(softc);
@@ -1357,7 +1498,7 @@ enic_dev_init(struct enic *enic)
if (vnic_dev_overlay_offload_cfg(enic->vdev,
OVERLAY_CFG_VXLAN_PORT_UPDATE, ENIC_DEFAULT_VXLAN_PORT)) {
dev_err(enic, "failed to update vxlan port\n");
- return -EINVAL;
+ return (EINVAL);
}
}
return 0;
@@ -1441,7 +1582,7 @@ enic_dev_wait(struct vnic_dev *vdev, int (*start) (struct vnic_dev *, int),
return 0;
usleep(1000);
}
- return -ETIMEDOUT;
+ return (ETIMEDOUT);
}
static int
@@ -1452,7 +1593,7 @@ enic_map_bar(struct enic_softc *softc, struct enic_bar_info *bar, int bar_num,
if (bar->res != NULL) {
device_printf(softc->dev, "Bar %d already mapped\n", bar_num);
- return EDOOFUS;
+ return (EDOOFUS);
}
bar->rid = PCIR_BAR(bar_num);
@@ -1481,20 +1622,18 @@ enic_init_vnic_resources(struct enic *enic)
unsigned int rxq_interrupt_enable = 0;
unsigned int rxq_interrupt_offset = ENICPMD_RXQ_INTR_OFFSET;
unsigned int txq_interrupt_enable = 0;
- unsigned int txq_interrupt_offset = ENICPMD_RXQ_INTR_OFFSET;
+ unsigned int txq_interrupt_offset;
unsigned int index = 0;
unsigned int cq_idx;
if_softc_ctx_t scctx;
scctx = enic->softc->scctx;
-
rxq_interrupt_enable = 1;
- txq_interrupt_enable = 1;
+ txq_interrupt_enable = 0;
rxq_interrupt_offset = 0;
- txq_interrupt_offset = enic->intr_count - 2;
- txq_interrupt_offset = 1;
+ txq_interrupt_offset = scctx->isc_nrxqsets;
for (index = 0; index < enic->intr_count; index++) {
vnic_intr_alloc(enic->vdev, &enic->intr[index], index);
@@ -1568,7 +1707,7 @@ enic_update_packet_filter(struct enic *enic)
}
static bool
-enic_if_needs_restart(if_ctx_t ctx __unused, enum iflib_restart_event event)
+enic_if_needs_restart(if_ctx_t ctx, enum iflib_restart_event event)
{
switch (event) {
case IFLIB_RESTART_VLAN_CONFIG:
diff --git a/sys/dev/enic/vnic_cq.h b/sys/dev/enic/vnic_cq.h
index 26f9009612c5..b4549ee58c64 100644
--- a/sys/dev/enic/vnic_cq.h
+++ b/sys/dev/enic/vnic_cq.h
@@ -63,6 +63,8 @@ struct vnic_cq {
unsigned int to_clean;
unsigned int last_color;
unsigned int interrupt_offset;
+ unsigned int cur_rx_coal_timeval;
+ unsigned int tobe_rx_coal_timeval;
#ifdef ENIC_AIC
struct vnic_rx_bytes_counter pkt_size_counter;
unsigned int cur_rx_coal_timeval;
@@ -75,15 +77,12 @@ struct vnic_cq {
int nrxqsets_start;
};
-void vnic_cq_free(struct vnic_cq *cq);
void vnic_cq_init(struct vnic_cq *cq, unsigned int flow_control_enable,
unsigned int color_enable, unsigned int cq_head, unsigned int cq_tail,
unsigned int cq_tail_color, unsigned int interrupt_enable,
unsigned int cq_entry_enable, unsigned int message_enable,
unsigned int interrupt_offset, u64 message_addr);
void vnic_cq_clean(struct vnic_cq *cq);
-int vnic_cq_mem_size(struct vnic_cq *cq, unsigned int desc_count,
- unsigned int desc_size);
static inline unsigned int vnic_cq_service(struct vnic_cq *cq,
unsigned int work_to_do,
diff --git a/sys/dev/enic/vnic_dev.c b/sys/dev/enic/vnic_dev.c
index 3425d7372e56..2d555cb2b34d 100644
--- a/sys/dev/enic/vnic_dev.c
+++ b/sys/dev/enic/vnic_dev.c
@@ -44,7 +44,7 @@ static int vnic_dev_discover_res(struct vnic_dev *vdev,
u8 type;
if (num_bars == 0)
- return -EINVAL;
+ return (EINVAL);
rh = malloc(sizeof(*rh), M_DEVBUF, M_NOWAIT | M_ZERO);
mrh = malloc(sizeof(*mrh), M_DEVBUF, M_NOWAIT | M_ZERO);
@@ -52,7 +52,7 @@ static int vnic_dev_discover_res(struct vnic_dev *vdev,
pr_err("vNIC BAR0 res hdr not mem-mapped\n");
free(rh, M_DEVBUF);
free(mrh, M_DEVBUF);
- return -EINVAL;
+ return (EINVAL);
}
/* Check for mgmt vnic in addition to normal vnic */
@@ -69,7 +69,7 @@ static int vnic_dev_discover_res(struct vnic_dev *vdev,
rh->magic, rh->version);
free(rh, M_DEVBUF);
free(mrh, M_DEVBUF);
- return -EINVAL;
+ return (EINVAL);
}
}
@@ -97,6 +97,7 @@ static int vnic_dev_discover_res(struct vnic_dev *vdev,
case RES_TYPE_INTR_CTRL:
case RES_TYPE_INTR_PBA_LEGACY:
case RES_TYPE_DEVCMD:
+ case RES_TYPE_DEVCMD2:
break;
default:
ENIC_BUS_READ_REGION_4(softc, mem, r_offset, (void *)r, sizeof(*r) / 4);
@@ -189,12 +190,12 @@ static int _vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
status = ENIC_BUS_READ_4(devcmd, DEVCMD_STATUS);
if (status == 0xFFFFFFFF) {
/* PCI-e target device is gone */
- return -ENODEV;
+ return (ENODEV);
}
if (status & STAT_BUSY) {
pr_err("Busy devcmd %d\n", _CMD_N(cmd));
- return -EBUSY;
+ return (EBUSY);
}
if (_CMD_DIR(cmd) & _CMD_DIR_WRITE) {
@@ -214,7 +215,7 @@ static int _vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
status = ENIC_BUS_READ_4(devcmd, DEVCMD_STATUS);
if (status == 0xFFFFFFFF) {
/* PCI-e target device is gone */
- return -ENODEV;
+ return (ENODEV);
}
if (!(status & STAT_BUSY)) {
@@ -225,7 +226,7 @@ static int _vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
pr_err("Devcmd %d failed " \
"with error code %d\n",
_CMD_N(cmd), err);
- return err;
+ return (err);
}
if (_CMD_DIR(cmd) & _CMD_DIR_READ) {
@@ -237,7 +238,82 @@ static int _vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
}
pr_err("Timedout devcmd %d\n", _CMD_N(cmd));
- return -ETIMEDOUT;
+ return (ETIMEDOUT);
+}
+
+static int _vnic_dev_cmd2(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
+ int wait)
+{
+ struct devcmd2_controller *dc2c = vdev->devcmd2;
+ struct devcmd2_result *result;
+ u8 color;
+ unsigned int i;
+ u32 fetch_index, new_posted;
+ int delay, err;
+ u32 posted = dc2c->posted;
+
+ fetch_index = ENIC_BUS_READ_4(dc2c->wq_ctrl, TX_FETCH_INDEX);
+ if (fetch_index == 0xFFFFFFFF)
+ return (ENODEV);
+
+ new_posted = (posted + 1) % DEVCMD2_RING_SIZE;
+
+ if (new_posted == fetch_index) {
+ device_printf(dev_from_vnic_dev(vdev),
+ "devcmd2 %d: wq is full. fetch index: %u, posted index: %u\n",
+ _CMD_N(cmd), fetch_index, posted);
+ return (EBUSY);
+ }
+
+ dc2c->cmd_ring[posted].cmd = cmd;
+ dc2c->cmd_ring[posted].flags = 0;
+
+ if ((_CMD_FLAGS(cmd) & _CMD_FLAGS_NOWAIT))
+ dc2c->cmd_ring[posted].flags |= DEVCMD2_FNORESULT;
+ if (_CMD_DIR(cmd) & _CMD_DIR_WRITE)
+ for (i = 0; i < VNIC_DEVCMD_NARGS; i++)
+ dc2c->cmd_ring[posted].args[i] = vdev->args[i];
+
+ ENIC_BUS_WRITE_4(dc2c->wq_ctrl, TX_POSTED_INDEX, new_posted);
+ dc2c->posted = new_posted;
+
+ if (dc2c->cmd_ring[posted].flags & DEVCMD2_FNORESULT)
+ return (0);
+
+ result = dc2c->result + dc2c->next_result;
+ color = dc2c->color;
+
+ dc2c->next_result++;
+ if (dc2c->next_result == dc2c->result_size) {
+ dc2c->next_result = 0;
+ dc2c->color = dc2c->color ? 0 : 1;
+ }
+
+ for (delay = 0; delay < wait; delay++) {
+ if (result->color == color) {
+ if (result->error) {
+ err = result->error;
+ if (err != ERR_ECMDUNKNOWN ||
+ cmd != CMD_CAPABILITY)
+ device_printf(dev_from_vnic_dev(vdev),
+ "Error %d devcmd %d\n", err,
+ _CMD_N(cmd));
+ return (err);
+ }
+ if (_CMD_DIR(cmd) & _CMD_DIR_READ)
+ for (i = 0; i < VNIC_DEVCMD2_NARGS; i++)
+ vdev->args[i] = result->results[i];
+
+ return 0;
+ }
+ udelay(100);
+ }
+
+ device_printf(dev_from_vnic_dev(vdev),
+ "devcmd %d timed out\n", _CMD_N(cmd));
+
+
+ return (ETIMEDOUT);
}
static int vnic_dev_cmd_proxy(struct vnic_dev *vdev,
@@ -253,7 +329,7 @@ static int vnic_dev_cmd_proxy(struct vnic_dev *vdev,
*/
if (nargs > VNIC_DEVCMD_NARGS - 2) {
pr_err("number of args %d exceeds the maximum\n", nargs);
- return -EINVAL;
+ return (EINVAL);
}
memset(vdev->args, 0, sizeof(vdev->args));
@@ -261,9 +337,9 @@ static int vnic_dev_cmd_proxy(struct vnic_dev *vdev,
vdev->args[1] = cmd;
memcpy(&vdev->args[2], args, nargs * sizeof(args[0]));
- err = _vnic_dev_cmd(vdev, proxy_cmd, wait);
+ err = vdev->devcmd_rtn(vdev, proxy_cmd, wait);
if (err)
- return err;
+ return (err);
status = (u32)vdev->args[0];
if (status & STAT_ERROR) {
@@ -271,7 +347,7 @@ static int vnic_dev_cmd_proxy(struct vnic_dev *vdev,
if (err != ERR_ECMDUNKNOWN ||
cmd != CMD_CAPABILITY)
pr_err("Error %d proxy devcmd %d\n", err, _CMD_N(cmd));
- return err;
+ return (err);
}
memcpy(args, &vdev->args[1], nargs * sizeof(args[0]));
@@ -286,16 +362,16 @@ static int vnic_dev_cmd_no_proxy(struct vnic_dev *vdev,
if (nargs > VNIC_DEVCMD_NARGS) {
pr_err("number of args %d exceeds the maximum\n", nargs);
- return -EINVAL;
+ return (EINVAL);
}
memset(vdev->args, 0, sizeof(vdev->args));
memcpy(vdev->args, args, nargs * sizeof(args[0]));
- err = _vnic_dev_cmd(vdev, cmd, wait);
+ err = vdev->devcmd_rtn(vdev, cmd, wait);
memcpy(args, vdev->args, nargs * sizeof(args[0]));
- return err;
+ return (err);
}
int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
@@ -328,7 +404,7 @@ int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
*a1 = args[1];
}
- return err;
+ return (err);
}
int vnic_dev_cmd_args(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
@@ -400,7 +476,7 @@ int vnic_dev_capable_filter_mode(struct vnic_dev *vdev, u32 *mode,
args[1] = 0;
err = vnic_dev_cmd_args(vdev, CMD_CAPABILITY, args, 2, 1000);
if (err)
- return err;
+ return (err);
max_level = args[1];
goto parse_max_level;
} else if (args[2] == FILTER_CAP_MODE_V1) {
@@ -479,7 +555,7 @@ int vnic_dev_spec(struct vnic_dev *vdev, unsigned int offset, size_t size,
break;
}
- return err;
+ return (err);
}
int vnic_dev_stats_clear(struct vnic_dev *vdev)
@@ -497,7 +573,7 @@ int vnic_dev_stats_dump(struct vnic_dev *vdev, struct vnic_stats **stats)
int rc;
if (!vdev->stats)
- return -ENOMEM;
+ return (ENOMEM);
*stats = vdev->stats;
a0 = vdev->stats_res.idi_paddr;
@@ -524,10 +600,10 @@ int vnic_dev_counter_dma_cfg(struct vnic_dev *vdev, u32 period,
int err;
if (num_counters > VNIC_MAX_FLOW_COUNTERS)
- return -ENOMEM;
+ return (ENOMEM);
if (period > 0 && (period < VNIC_COUNTER_DMA_MIN_PERIOD ||
num_counters == 0))
- return -EINVAL;
+ return (EINVAL);
args[0] = num_counters;
args[1] = vdev->flow_counters_res.idi_paddr;
@@ -545,7 +621,7 @@ int vnic_dev_counter_dma_cfg(struct vnic_dev *vdev, u32 period,
vdev->flow_counters_dma_active = (num_counters != 0 &&
period != 0);
- return err;
+ return (err);
}
int vnic_dev_close(struct vnic_dev *vdev)
@@ -593,7 +669,7 @@ int vnic_dev_open_done(struct vnic_dev *vdev, int *done)
err = vnic_dev_cmd(vdev, CMD_OPEN_STATUS, &a0, &a1, wait);
if (err)
- return err;
+ return (err);
*done = (a0 == 0);
@@ -611,7 +687,7 @@ int vnic_dev_get_mac_addr(struct vnic_dev *vdev, u8 *mac_addr)
err = vnic_dev_cmd(vdev, CMD_GET_MAC_ADDR, &a0, &a1, wait);
if (err)
- return err;
+ return (err);
for (i = 0; i < ETH_ALEN; i++)
mac_addr[i] = ((u8 *)&a0)[i];
@@ -636,7 +712,7 @@ int vnic_dev_packet_filter(struct vnic_dev *vdev, int directed, int multicast,
if (err)
pr_err("Can't set packet filter\n");
- return err;
+ return (err);
}
int vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr)
@@ -655,7 +731,7 @@ int vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr)
addr[0], addr[1], addr[2], addr[3], addr[4], addr[5],
err);
- return err;
+ return (err);
}
int vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr)
@@ -674,7 +750,7 @@ int vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr)
addr[0], addr[1], addr[2], addr[3], addr[4], addr[5],
err);
- return err;
+ return (err);
}
int vnic_dev_set_ig_vlan_rewrite_mode(struct vnic_dev *vdev,
@@ -771,7 +847,7 @@ int vnic_dev_notify_unsetcmd(struct vnic_dev *vdev)
vdev->notify_sz = 0;
}
- return err;
+ return (err);
}
int vnic_dev_notify_unset(struct vnic_dev *vdev)
@@ -807,7 +883,8 @@ static int vnic_dev_notify_ready(struct vnic_dev *vdev)
csum += words[i];
} while (csum != words[0]);
- return 1;
+
+ return (1);
}
int vnic_dev_init(struct vnic_dev *vdev, int arg)
@@ -923,7 +1000,7 @@ int vnic_dev_alloc_counter_mem(struct vnic_dev *vdev)
iflib_dma_alloc(softc->ctx, sizeof(struct vnic_counter_counts) * VNIC_MAX_FLOW_COUNTERS, &vdev->flow_counters_res, 0);
vdev->flow_counters = (struct vnic_counter_counts *)vdev->flow_counters_res.idi_vaddr;
vdev->flow_counters_dma_active = 0;
- return vdev->flow_counters == NULL ? -ENOMEM : 0;
+ return (vdev->flow_counters == NULL ? ENOMEM : 0);
}
struct vnic_dev *vnic_dev_register(struct vnic_dev *vdev,
@@ -942,6 +1019,85 @@ err_out:
return NULL;
}
+static int vnic_dev_init_devcmd1(struct vnic_dev *vdev)
+{
+ vdev->devcmd = vnic_dev_get_res(vdev, RES_TYPE_DEVCMD, 0);
+ if (!vdev->devcmd)
+ return (ENODEV);
+ vdev->devcmd_rtn = _vnic_dev_cmd;
+
+ return 0;
+}
+
+static int vnic_dev_init_devcmd2(struct vnic_dev *vdev)
+{
+ int err;
+ unsigned int fetch_index;
+
+
+ err = 0;
+
+ if (vdev->devcmd2)
+ return (0);
+
+ vdev->devcmd2 = malloc(sizeof(*vdev->devcmd2), M_DEVBUF,
+ M_NOWAIT | M_ZERO);
+
+ if (!vdev->devcmd2) {
+ return (ENOMEM);
+ }
+
+ vdev->devcmd2->color = 1;
+ vdev->devcmd2->result_size = DEVCMD2_RING_SIZE;
+
+ err = enic_wq_devcmd2_alloc(vdev, &vdev->devcmd2->wq, DEVCMD2_RING_SIZE,
+ DEVCMD2_DESC_SIZE);
+
+ if (err) {
+ goto err_free_devcmd2;
+ }
+ vdev->devcmd2->wq_ctrl = vdev->devcmd2->wq.ctrl;
+ vdev->devcmd2->cmd_ring = vdev->devcmd2->wq.ring.descs;
+
+ fetch_index = ENIC_BUS_READ_4(vdev->devcmd2->wq.ctrl, TX_FETCH_INDEX);
+ if (fetch_index == 0xFFFFFFFF)
+ return (ENODEV);
+
+ enic_wq_init_start(&vdev->devcmd2->wq, 0, fetch_index, fetch_index, 0,
+ 0);
+ vdev->devcmd2->posted = fetch_index;
+ vnic_wq_enable(&vdev->devcmd2->wq);
+
+ err = vnic_dev_alloc_desc_ring(vdev, &vdev->devcmd2->results_ring,
+ DEVCMD2_RING_SIZE, DEVCMD2_DESC_SIZE);
+ if (err)
+ goto err_free_devcmd2;
+
+ vdev->devcmd2->result = vdev->devcmd2->results_ring.descs;
+ vdev->args[0] = (u64)vdev->devcmd2->results_ring.base_addr |
+ VNIC_PADDR_TARGET;
+ vdev->args[1] = DEVCMD2_RING_SIZE;
+
+ err = _vnic_dev_cmd2(vdev, CMD_INITIALIZE_DEVCMD2, 1000);
+ if (err)
+ goto err_free_devcmd2;
+
+ vdev->devcmd_rtn = _vnic_dev_cmd2;
+
+ return (err);
+
+err_free_devcmd2:
+ err = ENOMEM;
+ if (vdev->devcmd2->wq_ctrl)
+ vnic_wq_free(&vdev->devcmd2->wq);
+ if (vdev->devcmd2->result)
+ vnic_dev_free_desc_ring(vdev, &vdev->devcmd2->results_ring);
+ free(vdev->devcmd2, M_DEVBUF);
+ vdev->devcmd2 = NULL;
+
+ return (err);
+}
+
/*
* vnic_dev_classifier: Add/Delete classifier entries
* @vdev: vdev of the device
@@ -1037,3 +1193,22 @@ bool vnic_dev_counter_query(struct vnic_dev *vdev, uint32_t idx,
device_t dev_from_vnic_dev(struct vnic_dev *vdev) {
return (vdev->softc->dev);
}
+
+int vnic_dev_cmd_init(struct vnic_dev *vdev) {
+ int err;
+ void __iomem *res;
+
+ res = vnic_dev_get_res(vdev, RES_TYPE_DEVCMD2, 0);
+ if (res) {
+ err = vnic_dev_init_devcmd2(vdev);
+ if (err)
+ device_printf(dev_from_vnic_dev(vdev),
+ "DEVCMD2 init failed, Using DEVCMD1\n");
+ else
+ return 0;
+ }
+
+ err = vnic_dev_init_devcmd1(vdev);
+
+ return (err);
+}
diff --git a/sys/dev/enic/vnic_dev.h b/sys/dev/enic/vnic_dev.h
index f8ca29f4e175..5e2d01d985f3 100644
--- a/sys/dev/enic/vnic_dev.h
+++ b/sys/dev/enic/vnic_dev.h
@@ -38,6 +38,7 @@ struct vnic_dev_ring {
unsigned int desc_count;
unsigned int desc_avail;
unsigned int last_count;
+ iflib_dma_info_t ifdip;
};
struct vnic_dev_iomap_info {
@@ -69,6 +70,10 @@ unsigned long vnic_dev_get_res_type_len(struct vnic_dev *vdev,
unsigned int vnic_dev_desc_ring_size(struct vnic_dev_ring *ring,
unsigned int desc_count, unsigned int desc_size);
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);
+void vnic_dev_free_desc_ring(struct vnic_dev *vdev,
+ struct vnic_dev_ring *ring);
int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
u64 *a0, u64 *a1, int wait);
int vnic_dev_cmd_args(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
@@ -143,7 +148,7 @@ struct vnic_dev *vnic_dev_register(struct vnic_dev *vdev,
struct rte_pci_device *vnic_dev_get_pdev(struct vnic_dev *vdev);
int vnic_dev_alloc_stats_mem(struct vnic_dev *vdev);
int vnic_dev_alloc_counter_mem(struct vnic_dev *vdev);
-int vnic_dev_cmd_init(struct vnic_dev *vdev, int fallback);
+int vnic_dev_cmd_init(struct vnic_dev *vdev);
int vnic_dev_get_size(void);
int vnic_dev_int13(struct vnic_dev *vdev, u64 arg, u32 op);
int vnic_dev_perbi(struct vnic_dev *vdev, u64 arg, u32 op);
@@ -164,6 +169,7 @@ bool vnic_dev_counter_alloc(struct vnic_dev *vdev, uint32_t *idx);
bool vnic_dev_counter_free(struct vnic_dev *vdev, uint32_t idx);
bool vnic_dev_counter_query(struct vnic_dev *vdev, uint32_t idx,
bool reset, uint64_t *packets, uint64_t *bytes);
+void vnic_dev_deinit_devcmd2(struct vnic_dev *vdev);
device_t dev_from_vnic_dev(struct vnic_dev *vdev);
diff --git a/sys/dev/enic/vnic_intr.c b/sys/dev/enic/vnic_intr.c
index 38e2ea6e066b..8a6494efd5f3 100644
--- a/sys/dev/enic/vnic_intr.c
+++ b/sys/dev/enic/vnic_intr.c
@@ -21,7 +21,7 @@ int vnic_intr_alloc(struct vnic_dev *vdev, struct vnic_intr *intr,
intr->ctrl = vnic_dev_get_res(vdev, RES_TYPE_INTR_CTRL, index);
if (!intr->ctrl) {
pr_err("Failed to hook INTR[%d].ctrl resource\n", index);
- return -EINVAL;
+ return (EINVAL);
}
return 0;
diff --git a/sys/dev/enic/vnic_intr.h b/sys/dev/enic/vnic_intr.h
index 22db66096aae..6d1e8e1cf050 100644
--- a/sys/dev/enic/vnic_intr.h
+++ b/sys/dev/enic/vnic_intr.h
@@ -76,7 +76,7 @@ static inline void vnic_intr_return_credits(struct vnic_intr *intr,
static inline unsigned int vnic_intr_credits(struct vnic_intr *intr)
{
- return ENIC_BUS_READ_4(intr->ctrl, INTR_CREDITS);
+ return (ENIC_BUS_READ_4(intr->ctrl, INTR_CREDITS));
}
static inline void vnic_intr_return_all_credits(struct vnic_intr *intr)
diff --git a/sys/dev/enic/vnic_resource.h b/sys/dev/enic/vnic_resource.h
index 184bfa7401df..d365b8d914ba 100644
--- a/sys/dev/enic/vnic_resource.h
+++ b/sys/dev/enic/vnic_resource.h
@@ -39,6 +39,7 @@ enum vnic_res_type {
RES_TYPE_MQ_RQ, /* MQ Receive queues */
RES_TYPE_MQ_CQ, /* MQ Completion queues */
RES_TYPE_DEPRECATED1, /* Old version of devcmd 2 */
+ RES_TYPE_DEPRECATED2, /* Old version of devcmd 2 */
RES_TYPE_DEVCMD2, /* Device control region */
RES_TYPE_MAX, /* Count of resource types */
};
diff --git a/sys/dev/enic/vnic_rq.c b/sys/dev/enic/vnic_rq.c
index 3720da5f9aa6..ef30563fa2f3 100644
--- a/sys/dev/enic/vnic_rq.c
+++ b/sys/dev/enic/vnic_rq.c
@@ -40,6 +40,7 @@ void vnic_rq_init(struct vnic_rq *rq, unsigned int cq_index,
fetch_index = 0;
}
+ fetch_index = 0;
vnic_rq_init_start(rq, cq_index,
fetch_index, fetch_index,
error_interrupt_enable,
@@ -50,7 +51,7 @@ void vnic_rq_init(struct vnic_rq *rq, unsigned int cq_index,
unsigned int vnic_rq_error_status(struct vnic_rq *rq)
{
- return ENIC_BUS_READ_4(rq->ctrl, RX_ERROR_STATUS);
+ return (ENIC_BUS_READ_4(rq->ctrl, RX_ERROR_STATUS));
}
void vnic_rq_enable(struct vnic_rq *rq)
@@ -73,7 +74,7 @@ int vnic_rq_disable(struct vnic_rq *rq)
pr_err("Failed to disable RQ[%d]\n", rq->index);
- return -ETIMEDOUT;
+ return (ETIMEDOUT);
}
void vnic_rq_clean(struct vnic_rq *rq)
diff --git a/sys/dev/enic/vnic_rq.h b/sys/dev/enic/vnic_rq.h
index ae8c1fdc39bd..9e3d239809c4 100644
--- a/sys/dev/enic/vnic_rq.h
+++ b/sys/dev/enic/vnic_rq.h
@@ -133,7 +133,6 @@ void vnic_rq_init_start(struct vnic_rq *rq, unsigned int cq_index,
void vnic_rq_init(struct vnic_rq *rq, unsigned int cq_index,
unsigned int error_interrupt_enable,
unsigned int error_interrupt_offset);
-void vnic_rq_error_out(struct vnic_rq *rq, unsigned int error);
unsigned int vnic_rq_error_status(struct vnic_rq *rq);
void vnic_rq_enable(struct vnic_rq *rq);
int vnic_rq_disable(struct vnic_rq *rq);
diff --git a/sys/dev/enic/vnic_rss.h b/sys/dev/enic/vnic_rss.h
index abd7b9f131aa..039041ece5b2 100644
--- a/sys/dev/enic/vnic_rss.h
+++ b/sys/dev/enic/vnic_rss.h
@@ -24,9 +24,4 @@ union vnic_rss_cpu {
u64 raw[32];
};
-void vnic_set_rss_key(union vnic_rss_key *rss_key, u8 *key);
-void vnic_set_rss_cpu(union vnic_rss_cpu *rss_cpu, u8 *cpu);
-void vnic_get_rss_key(union vnic_rss_key *rss_key, u8 *key);
-void vnic_get_rss_cpu(union vnic_rss_cpu *rss_cpu, u8 *cpu);
-
#endif /* _VNIC_RSS_H_ */
diff --git a/sys/dev/enic/vnic_wq.c b/sys/dev/enic/vnic_wq.c
index b032df3392b2..995af3270a21 100644
--- a/sys/dev/enic/vnic_wq.c
+++ b/sys/dev/enic/vnic_wq.c
@@ -7,7 +7,103 @@
#include "vnic_dev.h"
#include "vnic_wq.h"
-void vnic_wq_init_start(struct vnic_wq *wq, unsigned int cq_index,
+int vnic_dev_alloc_desc_ring(struct vnic_dev *vdev,
+ struct vnic_dev_ring *ring, unsigned int desc_count, unsigned int desc_size)
+{
+ iflib_dma_info_t ifdip;
+ int err;
+
+ if ((ifdip = malloc(sizeof(struct iflib_dma_info),
+ M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) {
+ device_printf(dev_from_vnic_dev(vdev),
+ "Unable to allocate DMA info memory\n");
+ return (ENOMEM);
+ }
+
+ err = iflib_dma_alloc(vdev->softc->ctx, desc_count * desc_size,
+ ifdip, 0);
+ if (err) {
+ device_printf(dev_from_vnic_dev(vdev),
+ "Unable to allocate DEVCMD2 descriptors\n");
+ err = ENOMEM;
+ goto err_out_alloc;
+ }
+
+ ring->base_addr = ifdip->idi_paddr;
+ ring->descs = ifdip->idi_vaddr;
+ ring->ifdip = ifdip;
+ ring->desc_size = desc_size;
+ ring->desc_count = desc_count;
+ ring->last_count = 0;
+ ring->desc_avail = ring->desc_count - 1;
+
+ ring->size = ring->desc_count * ring->desc_size;
+ ring->base_align = 512;
+ ring->size_unaligned = ring->size + ring->base_align;
+
+ return (err);
+
+ iflib_dma_free(ifdip);
+
+err_out_alloc:
+ free(ifdip, M_DEVBUF);
+ return (err);
+}
+
+void vnic_dev_free_desc_ring(struct vnic_dev *vdev, struct vnic_dev_ring *ring)
+{
+ if (ring && ring->descs) {
+ iflib_dma_free(ring->ifdip);
+ free(ring->ifdip, M_DEVBUF);
+ ring->descs = NULL;
+ }
+}
+
+void vnic_wq_free(struct vnic_wq *wq) {
+ vnic_dev_free_desc_ring(wq->vdev, &wq->ring);
+ wq->ctrl = NULL;
+}
+
+int enic_wq_devcmd2_alloc(struct vnic_dev *vdev, struct vnic_wq *wq,
+ unsigned int desc_count, unsigned int desc_size)
+{
+ int err;
+
+ wq->index = 0;
+ wq->vdev = vdev;
+
+
+ wq->ctrl = vnic_dev_get_res(vdev, RES_TYPE_DEVCMD2, 0);
+ if (!wq->ctrl)
+ return (EINVAL);
+ vnic_wq_disable(wq);
+ err = vnic_dev_alloc_desc_ring(vdev, &wq->ring, desc_count, desc_size);
+
+ return (err);
+}
+
+void vnic_dev_deinit_devcmd2(struct vnic_dev *vdev)
+{
+ if (vdev->devcmd2) {
+ vnic_wq_disable(&vdev->devcmd2->wq);
+ if (vdev->devcmd2->wq_ctrl)
+ vnic_wq_free(&vdev->devcmd2->wq);
+ if (vdev->devcmd2->result)
+ vnic_dev_free_desc_ring(vdev, &vdev->devcmd2->results_ring);
+ free(vdev->devcmd2, M_DEVBUF);
+ vdev->devcmd2 = NULL;
+ }
+}
+
+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));
+ return (0);
+}
+
+void enic_wq_init_start(struct vnic_wq *wq, unsigned int cq_index,
unsigned int fetch_index, unsigned int posted_index,
unsigned int error_interrupt_enable,
unsigned int error_interrupt_offset)
@@ -33,7 +129,7 @@ void vnic_wq_init(struct vnic_wq *wq, unsigned int cq_index,
unsigned int error_interrupt_enable,
unsigned int error_interrupt_offset)
{
- vnic_wq_init_start(wq, cq_index, 0, 0,
+ enic_wq_init_start(wq, cq_index, 0, 0,
error_interrupt_enable,
error_interrupt_offset);
wq->cq_pend = 0;
@@ -42,7 +138,7 @@ void vnic_wq_init(struct vnic_wq *wq, unsigned int cq_index,
unsigned int vnic_wq_error_status(struct vnic_wq *wq)
{
- return ENIC_BUS_READ_4(wq->ctrl, TX_ERROR_STATUS);
+ return (ENIC_BUS_READ_4(wq->ctrl, TX_ERROR_STATUS));
}
void vnic_wq_enable(struct vnic_wq *wq)
@@ -65,7 +161,7 @@ int vnic_wq_disable(struct vnic_wq *wq)
pr_err("Failed to disable WQ[%d]\n", wq->index);
- return -ETIMEDOUT;
+ return (ETIMEDOUT);
}
void vnic_wq_clean(struct vnic_wq *wq)
diff --git a/sys/dev/enic/vnic_wq.h b/sys/dev/enic/vnic_wq.h
index c4f551de8441..9ef492adba24 100644
--- a/sys/dev/enic/vnic_wq.h
+++ b/sys/dev/enic/vnic_wq.h
@@ -61,6 +61,20 @@ struct vnic_wq {
uint64_t offloads;
};
+struct devcmd2_controller {
+ struct vnic_res *wq_ctrl;
+ struct vnic_devcmd2 *cmd_ring;
+ struct devcmd2_result *result;
+ u16 next_result;
+ u16 result_size;
+ int color;
+ struct vnic_dev_ring results_ring;
+ struct vnic_res *results_ctrl;
+ struct vnic_wq wq;
+ u32 posted;
+};
+
+
static inline unsigned int vnic_wq_desc_avail(struct vnic_wq *wq)
{
/* how many does SW own? */
@@ -92,7 +106,7 @@ buf_idx_incr(uint32_t n_descriptors, uint32_t idx)
}
void vnic_wq_free(struct vnic_wq *wq);
-void vnic_wq_init_start(struct vnic_wq *wq, unsigned int cq_index,
+void enic_wq_init_start(struct vnic_wq *wq, unsigned int cq_index,
unsigned int fetch_index, unsigned int posted_index,
unsigned int error_interrupt_enable,
unsigned int error_interrupt_offset);
@@ -104,5 +118,7 @@ unsigned int vnic_wq_error_status(struct vnic_wq *wq);
void vnic_wq_enable(struct vnic_wq *wq);
int vnic_wq_disable(struct vnic_wq *wq);
void vnic_wq_clean(struct vnic_wq *wq);
+int enic_wq_devcmd2_alloc(struct vnic_dev *vdev, struct vnic_wq *wq,
+ unsigned int desc_count, unsigned int desc_size);
#endif /* _VNIC_WQ_H_ */