net/virtio: support Rx checksum offload
[dpdk.git] / drivers / net / virtio / virtqueue.h
index 99d4fa9..ef0027b 100644 (file)
@@ -66,8 +66,22 @@ struct rte_mbuf;
 
 #define VIRTQUEUE_MAX_NAME_SZ 32
 
-#define RTE_MBUF_DATA_DMA_ADDR(mb) \
-       (uint64_t) ((mb)->buf_physaddr + (mb)->data_off)
+#ifdef RTE_VIRTIO_USER
+/**
+ * Return the physical address (or virtual address in case of
+ * virtio-user) of mbuf data buffer.
+ */
+#define VIRTIO_MBUF_ADDR(mb, vq) (*(uint64_t *)((uintptr_t)(mb) + (vq)->offset))
+#else
+#define VIRTIO_MBUF_ADDR(mb, vq) ((mb)->buf_physaddr)
+#endif
+
+/**
+ * Return the physical address (or virtual address in case of
+ * virtio-user) of mbuf data buffer, taking care of mbuf data offset
+ */
+#define VIRTIO_MBUF_DATA_DMA_ADDR(mb, vq) \
+       (VIRTIO_MBUF_ADDR(mb, vq) + (mb)->data_off)
 
 #define VTNET_SQ_RQ_QUEUE_IDX 0
 #define VTNET_SQ_TQ_QUEUE_IDX 1
@@ -156,23 +170,30 @@ struct virtio_pmd_ctrl {
        uint8_t data[VIRTIO_MAX_CTRL_DATA];
 };
 
+struct vq_desc_extra {
+       void *cookie;
+       uint16_t ndescs;
+};
+
 struct virtqueue {
-       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*/
+       struct virtio_hw  *hw; /**< virtio_hw structure pointer. */
+       struct vring vq_ring;  /**< vring keeping desc, used and avail */
+       /**
+        * Last consumed descriptor in the used table,
+        * trails vq_ring.used->idx.
+        */
+       uint16_t vq_used_cons_idx;
+       uint16_t vq_nentries;  /**< vring desc numbers */
+       uint16_t vq_free_cnt;  /**< num of desc available */
+       uint16_t vq_avail_idx; /**< sync until needed */
+       uint16_t vq_free_thresh; /**< free threshold */
+
+       void *vq_ring_virt_mem;  /**< linear address of vring*/
        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_free_thresh; /**< free threshold */
+       phys_addr_t vq_ring_mem; /**< physical address of vring,
+                                 * or virtual address for virtio_user. */
+
        /**
         * Head of the free chain in the descriptor table. If
         * there are no free descriptors, this will be set to
@@ -180,34 +201,12 @@ struct virtqueue {
         */
        uint16_t  vq_desc_head_idx;
        uint16_t  vq_desc_tail_idx;
-       /**
-        * Last consumed descriptor in the used table,
-        * trails vq_ring.used->idx.
-        */
-       uint16_t vq_used_cons_idx;
-       uint16_t vq_avail_idx;
-       uint64_t mbuf_initializer; /**< value to init mbufs. */
-       phys_addr_t virtio_net_hdr_mem; /**< hdr for each xmit packet */
-
-       struct rte_mbuf **sw_ring; /**< RX software ring. */
-       /* dummy mbuf, for wraparound when processing RX ring. */
-       struct rte_mbuf fake_mbuf;
-
-       /* Statistics */
-       uint64_t        packets;
-       uint64_t        bytes;
-       uint64_t        errors;
-       uint64_t        multicast;
-       uint64_t        broadcast;
-       /* Size bins in array as RFC 2819, undersized [0], 64 [1], etc */
-       uint64_t        size_bins[8];
-
-       uint16_t        *notify_addr;
-
-       struct vq_desc_extra {
-               void              *cookie;
-               uint16_t          ndescs;
-       } vq_descx[0];
+       uint16_t  vq_queue_index;   /**< PCI queue index */
+       uint16_t offset; /**< relative offset to obtain addr in mbuf */
+       uint16_t  *notify_addr;
+       int configured;
+       struct rte_mbuf **sw_ring;  /**< RX software ring. */
+       struct vq_desc_extra vq_descx[0];
 };
 
 /* If multiqueue is provided by host, then we suppport it. */
@@ -224,6 +223,7 @@ struct virtqueue {
  */
 struct virtio_net_hdr {
 #define VIRTIO_NET_HDR_F_NEEDS_CSUM 1    /**< Use csum_start,csum_offset*/
+#define VIRTIO_NET_HDR_F_DATA_VALID 2    /**< Checksum is valid */
        uint8_t flags;
 #define VIRTIO_NET_HDR_GSO_NONE     0    /**< Not a GSO frame */
 #define VIRTIO_NET_HDR_GSO_TCPV4    1    /**< GSO frame, IPv4 TCP (TSO) */
@@ -246,6 +246,25 @@ struct virtio_net_hdr_mrg_rxbuf {
        uint16_t num_buffers; /**< Number of merged rx buffers */
 };
 
+/* Region reserved to allow for transmit header and indirect ring */
+#define VIRTIO_MAX_TX_INDIRECT 8
+struct virtio_tx_region {
+       struct virtio_net_hdr_mrg_rxbuf tx_hdr;
+       struct vring_desc tx_indir[VIRTIO_MAX_TX_INDIRECT]
+                          __attribute__((__aligned__(16)));
+};
+
+/* Chain all the descriptors in the ring with an END */
+static inline void
+vring_desc_init(struct vring_desc *dp, uint16_t n)
+{
+       uint16_t i;
+
+       for (i = 0; i < n - 1; i++)
+               dp[i].next = (uint16_t)(i + 1);
+       dp[i].next = VQ_RING_DESC_CHAIN_END;
+}
+
 /**
  * Tell the backend not to interrupt us.
  */
@@ -286,7 +305,8 @@ vq_update_avail_ring(struct virtqueue *vq, uint16_t desc_idx)
         * descriptor.
         */
        avail_idx = (uint16_t)(vq->vq_avail_idx & (vq->vq_nentries - 1));
-       vq->vq_ring.avail->ring[avail_idx] = desc_idx;
+       if (unlikely(vq->vq_ring.avail->ring[avail_idx] != desc_idx))
+               vq->vq_ring.avail->ring[avail_idx] = desc_idx;
        vq->vq_avail_idx++;
 }