i40e/base: adjust register definitions and relevant
[dpdk.git] / lib / librte_pmd_virtio / virtqueue.h
index 29dd233..9d6079e 100644 (file)
@@ -37,7 +37,6 @@
 #include <stdint.h>
 
 #include <rte_atomic.h>
-#include <rte_mbuf.h>
 #include <rte_memory.h>
 #include <rte_memzone.h>
 #include <rte_mempool.h>
 #include "virtio_ring.h"
 #include "virtio_logs.h"
 
-#define mb()  rte_mb()
-#define wmb() rte_wmb()
-#define rmb() rte_rmb()
+struct rte_mbuf;
+
+/*
+ * Per virtio_config.h in Linux.
+ *     For virtio_pci on SMP, we don't need to order with respect to MMIO
+ *     accesses through relaxed memory I/O windows, so smp_mb() et al are
+ *     sufficient.
+ *
+ * This driver is for virtio_pci on SMP and therefore can assume
+ * weaker (compiler barriers)
+ */
+#define virtio_mb()    rte_mb()
+#define virtio_rmb()   rte_compiler_barrier()
+#define virtio_wmb()   rte_compiler_barrier()
 
 #ifdef RTE_PMD_PACKET_PREFETCH
 #define rte_packet_prefetch(p)  rte_prefetch1(p)
@@ -59,8 +69,7 @@
 #define VIRTQUEUE_MAX_NAME_SZ 32
 
 #define RTE_MBUF_DATA_DMA_ADDR(mb) \
-       (uint64_t) ((mb)->buf_physaddr + (uint64_t)((char *)((mb)->pkt.data) - \
-       (char *)(mb)->buf_addr))
+       (uint64_t) ((mb)->buf_physaddr + (mb)->data_off)
 
 #define VTNET_SQ_RQ_QUEUE_IDX 0
 #define VTNET_SQ_TQ_QUEUE_IDX 1
@@ -90,6 +99,34 @@ enum { VTNET_RQ = 0, VTNET_TQ = 1, VTNET_CQ = 2 };
 #define VIRTIO_NET_CTRL_RX_NOUNI        4
 #define VIRTIO_NET_CTRL_RX_NOBCAST      5
 
+/**
+ * Control the MAC
+ *
+ * The MAC filter table is managed by the hypervisor, the guest should
+ * assume the size is infinite.  Filtering should be considered
+ * non-perfect, ie. based on hypervisor resources, the guest may
+ * received packets from sources not specified in the filter list.
+ *
+ * In addition to the class/cmd header, the TABLE_SET command requires
+ * two out scatterlists.  Each contains a 4 byte count of entries followed
+ * by a concatenated byte stream of the ETH_ALEN MAC addresses.  The
+ * first sg list contains unicast addresses, the second is for multicast.
+ * This functionality is present if the VIRTIO_NET_F_CTRL_RX feature
+ * is available.
+ *
+ * The ADDR_SET command requests one out scatterlist, it contains a
+ * 6 bytes MAC address. This functionality is present if the
+ * VIRTIO_NET_F_CTRL_MAC_ADDR feature is available.
+ */
+struct virtio_net_ctrl_mac {
+       uint32_t entries;
+       uint8_t macs[][ETHER_ADDR_LEN];
+} __attribute__((__packed__));
+
+#define VIRTIO_NET_CTRL_MAC    1
+ #define VIRTIO_NET_CTRL_MAC_TABLE_SET        0
+ #define VIRTIO_NET_CTRL_MAC_ADDR_SET         1
+
 /**
  * Control VLAN filtering
  *
@@ -113,7 +150,7 @@ typedef uint8_t virtio_net_ctrl_ack;
 #define VIRTIO_NET_OK     0
 #define VIRTIO_NET_ERR    1
 
-#define VIRTIO_MAX_CTRL_DATA 128
+#define VIRTIO_MAX_CTRL_DATA 2048
 
 struct virtio_pmd_ctrl {
        struct virtio_net_ctrl_hdr hdr;
@@ -122,23 +159,22 @@ struct virtio_pmd_ctrl {
 };
 
 struct virtqueue {
-       char        vq_name[VIRTQUEUE_MAX_NAME_SZ];
        struct virtio_hw         *hw;     /**< virtio_hw structure pointer. */
        const struct rte_memzone *mz;     /**< mem zone to populate RX ring. */
        const struct rte_memzone *virtio_net_hdr_mz; /**< memzone to populate hdr. */
        struct rte_mempool       *mpool;  /**< mempool for mbuf allocation */
        uint16_t    queue_id;             /**< DPDK queue index. */
        uint8_t     port_id;              /**< Device port identifier. */
+       uint16_t    vq_queue_index;       /**< PCI queue index */
 
        void        *vq_ring_virt_mem;    /**< linear address of vring*/
-       int         vq_alignment;
-       int         vq_ring_size;
+       unsigned int vq_ring_size;
        phys_addr_t vq_ring_mem;          /**< physical address of vring */
 
        struct vring vq_ring;    /**< vring keeping desc, used and avail */
        uint16_t    vq_free_cnt; /**< num of desc available */
        uint16_t    vq_nentries; /**< vring desc numbers */
-       uint16_t    vq_queue_index;       /**< PCI queue index */
+       uint16_t    vq_free_thresh; /**< free threshold */
        /**
         * Head of the free chain in the descriptor table. If
         * there are no free descriptors, this will be set to
@@ -174,6 +210,10 @@ struct virtqueue {
 #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN        1
 #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX        0x8000
 #endif
+#ifndef VIRTIO_NET_F_CTRL_MAC_ADDR
+#define VIRTIO_NET_F_CTRL_MAC_ADDR 0x800000
+#define VIRTIO_NET_CTRL_MAC_ADDR_SET         1
+#endif
 
 /**
  * This is the first element of the scatter-gather list.  If you don't
@@ -224,14 +264,14 @@ virtqueue_full(const struct virtqueue *vq)
 
 #define VIRTQUEUE_NUSED(vq) ((uint16_t)((vq)->vq_ring.used->idx - (vq)->vq_used_cons_idx))
 
-static inline void __attribute__((always_inline))
+static inline void
 vq_update_avail_idx(struct virtqueue *vq)
 {
-       rte_compiler_barrier();
+       virtio_wmb();
        vq->vq_ring.avail->idx = vq->vq_avail_idx;
 }
 
-static inline void __attribute__((always_inline))
+static inline void
 vq_update_avail_ring(struct virtqueue *vq, uint16_t desc_idx)
 {
        uint16_t avail_idx;
@@ -247,194 +287,33 @@ vq_update_avail_ring(struct virtqueue *vq, uint16_t desc_idx)
        vq->vq_avail_idx++;
 }
 
-static inline int __attribute__((always_inline))
+static inline int
 virtqueue_kick_prepare(struct virtqueue *vq)
 {
        return !(vq->vq_ring.used->flags & VRING_USED_F_NO_NOTIFY);
 }
 
-static inline void __attribute__((always_inline))
+static inline void
 virtqueue_notify(struct virtqueue *vq)
 {
        /*
-        * Ensure updated avail->idx is visible to host. mb() necessary?
+        * Ensure updated avail->idx is visible to host.
         * For virtio on IA, the notificaiton is through io port operation
         * which is a serialization instruction itself.
         */
        VIRTIO_WRITE_REG_2(vq->hw, VIRTIO_PCI_QUEUE_NOTIFY, vq->vq_queue_index);
 }
 
-static inline void __attribute__((always_inline))
-vq_ring_free_chain(struct virtqueue *vq, uint16_t desc_idx)
-{
-       struct vring_desc *dp, *dp_tail;
-       struct vq_desc_extra *dxp;
-       uint16_t desc_idx_last = desc_idx;
-
-       dp  = &vq->vq_ring.desc[desc_idx];
-       dxp = &vq->vq_descx[desc_idx];
-       vq->vq_free_cnt = (uint16_t)(vq->vq_free_cnt + dxp->ndescs);
-       if ((dp->flags & VRING_DESC_F_INDIRECT) == 0) {
-               while (dp->flags & VRING_DESC_F_NEXT) {
-                       desc_idx_last = dp->next;
-                       dp = &vq->vq_ring.desc[dp->next];
-               }
-       }
-       dxp->ndescs = 0;
-
-       /*
-        * We must append the existing free chain, if any, to the end of
-        * newly freed chain. If the virtqueue was completely used, then
-        * head would be VQ_RING_DESC_CHAIN_END (ASSERTed above).
-        */
-       if (vq->vq_desc_tail_idx == VQ_RING_DESC_CHAIN_END) {
-               vq->vq_desc_head_idx = desc_idx;
-       } else {
-               dp_tail = &vq->vq_ring.desc[vq->vq_desc_tail_idx];
-               dp_tail->next = desc_idx;
-       }
-
-       vq->vq_desc_tail_idx = desc_idx_last;
-       dp->next = VQ_RING_DESC_CHAIN_END;
-}
-
-static inline int __attribute__((always_inline))
-virtqueue_enqueue_recv_refill(struct virtqueue *vq, struct rte_mbuf *cookie)
-{
-       struct vq_desc_extra *dxp;
-       struct vring_desc *start_dp;
-       uint16_t needed = 1;
-       uint16_t head_idx, idx;
-
-       if (unlikely(vq->vq_free_cnt == 0))
-               return -ENOSPC;
-       if (unlikely(vq->vq_free_cnt < needed))
-               return -EMSGSIZE;
-
-       head_idx = vq->vq_desc_head_idx;
-       if (unlikely(head_idx >= vq->vq_nentries))
-               return -EFAULT;
-
-       idx = head_idx;
-       dxp = &vq->vq_descx[idx];
-       dxp->cookie = (void *)cookie;
-       dxp->ndescs = needed;
-
-       start_dp = vq->vq_ring.desc;
-       start_dp[idx].addr  =
-               (uint64_t) (cookie->buf_physaddr + RTE_PKTMBUF_HEADROOM - sizeof(struct virtio_net_hdr));
-       start_dp[idx].len   = cookie->buf_len - RTE_PKTMBUF_HEADROOM + sizeof(struct virtio_net_hdr);
-       start_dp[idx].flags =  VRING_DESC_F_WRITE;
-       idx = start_dp[idx].next;
-       vq->vq_desc_head_idx = idx;
-       if (vq->vq_desc_head_idx == VQ_RING_DESC_CHAIN_END)
-               vq->vq_desc_tail_idx = idx;
-       vq->vq_free_cnt = (uint16_t)(vq->vq_free_cnt - needed);
-       vq_update_avail_ring(vq, head_idx);
-
-       return 0;
-}
-
-static inline int __attribute__((always_inline))
-virtqueue_enqueue_xmit(struct virtqueue *txvq, struct rte_mbuf *cookie)
-{
-       struct vq_desc_extra *dxp;
-       struct vring_desc *start_dp;
-       uint16_t needed = 2;
-       uint16_t head_idx, idx;
-
-       if (unlikely(txvq->vq_free_cnt == 0))
-               return -ENOSPC;
-       if (unlikely(txvq->vq_free_cnt < needed))
-               return -EMSGSIZE;
-       head_idx = txvq->vq_desc_head_idx;
-       if (unlikely(head_idx >= txvq->vq_nentries))
-               return -EFAULT;
-
-       idx = head_idx;
-       dxp = &txvq->vq_descx[idx];
-       if (dxp->cookie != NULL)
-               rte_pktmbuf_free_seg(dxp->cookie);
-       dxp->cookie = (void *)cookie;
-       dxp->ndescs = needed;
-
-       start_dp = txvq->vq_ring.desc;
-       start_dp[idx].addr  =
-               txvq->virtio_net_hdr_mem + idx * sizeof(struct virtio_net_hdr);
-       start_dp[idx].len   = sizeof(struct virtio_net_hdr);
-       start_dp[idx].flags = VRING_DESC_F_NEXT;
-       idx = start_dp[idx].next;
-       start_dp[idx].addr  = RTE_MBUF_DATA_DMA_ADDR(cookie);
-       start_dp[idx].len   = cookie->pkt.data_len;
-       start_dp[idx].flags = 0;
-       idx = start_dp[idx].next;
-       txvq->vq_desc_head_idx = idx;
-       if (txvq->vq_desc_head_idx == VQ_RING_DESC_CHAIN_END)
-               txvq->vq_desc_tail_idx = idx;
-       txvq->vq_free_cnt = (uint16_t)(txvq->vq_free_cnt - needed);
-       vq_update_avail_ring(txvq, head_idx);
-
-       return 0;
-}
-
-static inline uint16_t __attribute__((always_inline))
-virtqueue_dequeue_burst_rx(struct virtqueue *vq, struct rte_mbuf **rx_pkts, uint32_t *len, uint16_t num)
-{
-       struct vring_used_elem *uep;
-       struct rte_mbuf *cookie;
-       uint16_t used_idx, desc_idx;
-       uint16_t i;
-
-       /*  Caller does the check */
-       for (i = 0; i < num; i++) {
-               used_idx = (uint16_t)(vq->vq_used_cons_idx & (vq->vq_nentries - 1));
-               uep = &vq->vq_ring.used->ring[used_idx];
-               desc_idx = (uint16_t) uep->id;
-               len[i] = uep->len;
-               cookie = (struct rte_mbuf *)vq->vq_descx[desc_idx].cookie;
-
-               if (unlikely(cookie == NULL)) {
-                       PMD_DRV_LOG(ERR, "vring descriptor with no mbuf cookie at %u",
-                               vq->vq_used_cons_idx);
-                       break;
-               }
-
-               rte_prefetch0(cookie);
-               rte_packet_prefetch(cookie->pkt.data);
-               rx_pkts[i]  = cookie;
-               vq->vq_used_cons_idx++;
-               vq_ring_free_chain(vq, desc_idx);
-               vq->vq_descx[desc_idx].cookie = NULL;
-       }
-
-       return i;
-}
-
-static inline uint16_t __attribute__((always_inline))
-virtqueue_dequeue_pkt_tx(struct virtqueue *vq)
-{
-       struct vring_used_elem *uep;
-       uint16_t used_idx, desc_idx;
-
-       used_idx = (uint16_t)(vq->vq_used_cons_idx & (vq->vq_nentries - 1));
-       uep = &vq->vq_ring.used->ring[used_idx];
-       desc_idx = (uint16_t) uep->id;
-       vq->vq_used_cons_idx++;
-       vq_ring_free_chain(vq, desc_idx);
-
-       return 0;
-}
-
 #ifdef RTE_LIBRTE_VIRTIO_DEBUG_DUMP
 #define VIRTQUEUE_DUMP(vq) do { \
        uint16_t used_idx, nused; \
        used_idx = (vq)->vq_ring.used->idx; \
        nused = (uint16_t)(used_idx - (vq)->vq_used_cons_idx); \
        PMD_INIT_LOG(DEBUG, \
-         "VQ: %s - size=%d; free=%d; used=%d; desc_head_idx=%d;" \
+         "VQ: - size=%d; free=%d; used=%d; desc_head_idx=%d;" \
          " avail.idx=%d; used_cons_idx=%d; used.idx=%d;" \
          " avail.flags=0x%x; used.flags=0x%x", \
-         (vq)->vq_name, (vq)->vq_nentries, (vq)->vq_free_cnt, nused, \
+         (vq)->vq_nentries, (vq)->vq_free_cnt, nused, \
          (vq)->vq_desc_head_idx, (vq)->vq_ring.avail->idx, \
          (vq)->vq_used_cons_idx, (vq)->vq_ring.used->idx, \
          (vq)->vq_ring.avail->flags, (vq)->vq_ring.used->flags); \