aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/enic
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/enic')
-rw-r--r--sys/dev/enic/cq_desc.h15
-rw-r--r--sys/dev/enic/enic.h78
-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.c192
-rw-r--r--sys/dev/enic/vnic_cq.c2
-rw-r--r--sys/dev/enic/vnic_cq.h9
-rw-r--r--sys/dev/enic/vnic_dev.c244
-rw-r--r--sys/dev/enic/vnic_dev.h9
-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.c7
-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.c106
-rw-r--r--sys/dev/enic/vnic_wq.h18
18 files changed, 570 insertions, 166 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 6d0eb8563efd..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;
@@ -228,7 +253,7 @@ struct enic {
/* interrupt vectors (len = conf_intr_count) */
struct vnic_intr *intr;
- struct intr_queue *intr_queues;;
+ struct intr_queue *intr_queues;
unsigned int intr_count; /* equals enabled interrupts (lsc + rxqs) */
@@ -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..35620fece6bf 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);
@@ -397,8 +494,7 @@ enic_attach_pre(if_ctx_t ctx)
ifmedia_add(softc->media, IFM_ETHER | IFM_10_FL, 0, NULL);
/*
- * Allocate the CQ here since TX is called first before RX for now
- * assume RX and TX are the same
+ * Allocate the CQ here since TX is called first before RX.
*/
if (softc->enic.cq == NULL)
softc->enic.cq = malloc(sizeof(struct vnic_cq) *
@@ -407,8 +503,6 @@ enic_attach_pre(if_ctx_t ctx)
if (softc->enic.cq == NULL)
return (ENOMEM);
- softc->enic.cq->ntxqsets = softc->enic.wq_count + softc->enic.rq_count;
-
/*
* Allocate the consistent memory for stats and counters upfront so
* both primary and secondary processes can access them.
@@ -416,12 +510,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 +584,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 +670,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 +693,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);
@@ -626,7 +732,7 @@ enic_tx_queues_alloc(if_ctx_t ctx, caddr_t * vaddrs, uint64_t * paddrs,
for (q = 0; q < ntxqsets; q++) {
struct vnic_wq *wq;
struct vnic_cq *cq;
- unsigned int cq_wq;
+ unsigned int cq_wq;
wq = &softc->enic.wq[q];
cq_wq = enic_cq_wq(&softc->enic, q);
@@ -646,7 +752,6 @@ enic_tx_queues_alloc(if_ctx_t ctx, caddr_t * vaddrs, uint64_t * paddrs,
wq->head_idx = 0;
wq->tail_idx = 0;
- wq->ring.size = wq->ring.desc_count * wq->ring.desc_size;
wq->ring.descs = vaddrs[q * ntxqs + 0];
wq->ring.base_addr = paddrs[q * ntxqs + 0];
@@ -659,7 +764,6 @@ enic_tx_queues_alloc(if_ctx_t ctx, caddr_t * vaddrs, uint64_t * paddrs,
cq->ring.desc_count = softc->scctx->isc_ntxd[q];
cq->ring.desc_avail = cq->ring.desc_count - 1;
- cq->ring.size = cq->ring.desc_count * cq->ring.desc_size;
cq->ring.descs = vaddrs[q * ntxqs + 1];
cq->ring.base_addr = paddrs[q * ntxqs + 1];
@@ -715,7 +819,6 @@ enic_rx_queues_alloc(if_ctx_t ctx, caddr_t * vaddrs, uint64_t * paddrs,
cq->ring.desc_count = softc->scctx->isc_nrxd[1];
cq->ring.desc_avail = cq->ring.desc_count - 1;
- cq->ring.size = cq->ring.desc_count * cq->ring.desc_size;
cq->ring.descs = vaddrs[q * nrxqs + 0];
cq->ring.base_addr = paddrs[q * nrxqs + 0];
@@ -731,7 +834,6 @@ enic_rx_queues_alloc(if_ctx_t ctx, caddr_t * vaddrs, uint64_t * paddrs,
rq->ring.desc_count = softc->scctx->isc_nrxd[0];
rq->ring.desc_avail = rq->ring.desc_count - 1;
- rq->ring.size = rq->ring.desc_count * rq->ring.desc_size;
rq->ring.descs = vaddrs[q * nrxqs + 1];
rq->ring.base_addr = paddrs[q * nrxqs + 1];
rq->need_initial_post = true;
@@ -807,6 +909,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 +924,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 +973,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 +993,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 +1075,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 +1161,6 @@ static void
enic_update_admin_status(if_ctx_t ctx)
{
struct enic_softc *softc;
-
softc = iflib_get_softc(ctx);
enic_link_status(softc);
@@ -1100,7 +1234,9 @@ enic_setup_txq_sysctl(struct vnic_wq *wq, int i, struct sysctl_ctx_list *ctx,
{
struct sysctl_oid *txsnode;
struct sysctl_oid_list *txslist;
- struct vnic_stats *stats = wq[i].vdev->stats;
+ struct vnic_stats *stats;
+
+ stats = wq[i].vdev->stats;
txsnode = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "hstats",
CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Host Statistics");
@@ -1136,7 +1272,9 @@ enic_setup_rxq_sysctl(struct vnic_rq *rq, int i, struct sysctl_ctx_list *ctx,
{
struct sysctl_oid *rxsnode;
struct sysctl_oid_list *rxslist;
- struct vnic_stats *stats = rq[i].vdev->stats;
+ struct vnic_stats *stats;
+
+ stats = rq[i].vdev->stats;
rxsnode = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "hstats",
CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Host Statistics");
@@ -1357,7 +1495,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 +1579,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 +1590,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 +1619,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 +1704,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.c b/sys/dev/enic/vnic_cq.c
index 72de29e5a381..bd3629530a61 100644
--- a/sys/dev/enic/vnic_cq.c
+++ b/sys/dev/enic/vnic_cq.c
@@ -40,6 +40,4 @@ void vnic_cq_clean(struct vnic_cq *cq)
ENIC_BUS_WRITE_4(cq->ctrl, CQ_HEAD, 0);
ENIC_BUS_WRITE_4(cq->ctrl, CQ_TAIL, 0);
ENIC_BUS_WRITE_4(cq->ctrl, CQ_TAIL_COLOR, 1);
-
- vnic_dev_clear_desc_ring(&cq->ring);
}
diff --git a/sys/dev/enic/vnic_cq.h b/sys/dev/enic/vnic_cq.h
index 26f9009612c5..7f875d57ed74 100644
--- a/sys/dev/enic/vnic_cq.h
+++ b/sys/dev/enic/vnic_cq.h
@@ -63,27 +63,22 @@ 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;
unsigned int tobe_rx_coal_timeval;
ktime_t prev_ts;
#endif
- int ntxqsets;
- int nrxqsets;
- int ntxqsets_start;
- 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..a8228aed69aa 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);
@@ -167,17 +168,12 @@ unsigned int vnic_dev_desc_ring_size(struct vnic_dev_ring *ring,
ring->desc_size = VNIC_ALIGN(desc_size, desc_align);
- ring->size = ring->desc_count * ring->desc_size;
- ring->size_unaligned = ring->size + ring->base_align;
+ ring->size_unaligned = ring->desc_count * ring->desc_size \
+ + ring->base_align;
return ring->size_unaligned;
}
-void vnic_dev_clear_desc_ring(struct vnic_dev_ring *ring)
-{
- memset(ring->descs, 0, ring->size);
-}
-
static int _vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
int wait)
{
@@ -189,12 +185,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 +210,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 +221,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 +233,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 +324,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 +332,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 +342,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 +357,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 +399,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 +471,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 +550,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 +568,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 +595,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 +616,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 +664,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 +682,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 +707,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 +726,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 +745,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 +842,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 +878,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 +995,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 +1014,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 +1188,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..66583f4d278d 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 {
@@ -68,7 +69,10 @@ unsigned long vnic_dev_get_res_type_len(struct vnic_dev *vdev,
enum vnic_res_type type);
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 +147,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 +168,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..4c02347579b1 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)
@@ -92,6 +93,4 @@ void vnic_rq_clean(struct vnic_rq *rq)
}
ENIC_BUS_WRITE_4(rq->ctrl, RX_POSTED_INDEX, fetch_index);
-
- vnic_dev_clear_desc_ring(&rq->ring);
}
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..1d3120798798 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->base_align = 512;
+ ring->size_unaligned = ring->desc_count * ring->desc_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)
@@ -84,6 +180,4 @@ void vnic_wq_clean(struct vnic_wq *wq)
ENIC_BUS_WRITE_4(wq->ctrl, TX_FETCH_INDEX, 0);
ENIC_BUS_WRITE_4(wq->ctrl, TX_POSTED_INDEX, 0);
ENIC_BUS_WRITE_4(wq->ctrl, TX_ERROR_STATUS, 0);
-
- vnic_dev_clear_desc_ring(&wq->ring);
}
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_ */