Re: [PATCH v2 7/7] virtio: add 1.0 support
From: Xie, Huawei <hidden>
Date: 2016-01-14 07:50:09
On 1/12/2016 2:58 PM, Yuanhan Liu wrote:
Modern (v1.0) virtio pci device defines several pci capabilities. Each cap has a configure structure corresponding to it, and the cap.bar and cap.offset fields tell us where to find it. Firstly, we map the pci resources by rte_eal_pci_map_device(). We then could easily locate to a cfg structure by:
s/Locate/Locate to/
cfg_addr = dev->mem_resources[cap.bar].addr + cap.offset;
Therefore, the entrance of enabling modern (v1.0) pci device support
is to iterate the pci capability lists, and to locate some configs
we care; and they are:
- common cfg
For generic virtio and virtuqueu configuration, such as setting/gettingtypo for virtqueue
features, enabling a specific queue, and so on. - nofity cfg Combining with `queue_notify_off' from common cfg, we could use it to notify a specific virt queue. - device cfg Where virtio_net_config structure locates.
is located
If any of above cap is not found, we fallback to the legacy virtio
[SNIP]
+#define MODERN_READ_DEF(nr_bits, type) \
+static inline type \
+modern_read##nr_bits(type *addr) \
+{ \
+ return *(volatile type *)addr; \
+}
+
+#define MODERN_WRITE_DEF(nr_bits, type) \
+static inline void \
+modern_write##nr_bits(type val, type *addr) \
+{ \
+ *(volatile type *)addr = val; \
+}
+
+MODERN_READ_DEF (8, uint8_t)
+MODERN_WRITE_DEF(8, uint8_t)
+
+MODERN_READ_DEF (16, uint16_t)
+MODERN_WRITE_DEF(16, uint16_t)
+
+MODERN_READ_DEF (32, uint32_t)
+MODERN_WRITE_DEF(32, uint32_t)
+
+static inline void
+modern_write64_twopart(uint64_t val, uint32_t *lo, uint32_t *hi)
+{
+ modern_write32((uint32_t)val, lo);
+ modern_write32(val >> 32, hi);
+}
+This is normal mmio read/write operation. ioread8/16/32/64 or just readxx is more meaningful name here.
+static void
[SNIP]
+ +static void +modern_write_dev_config(struct virtio_hw *hw, uint64_t offset, + void *src, int length)
define src as const [snip]
+static inline void * +get_cfg_addr(struct rte_pci_device *dev, struct virtio_pci_cap *cap)
No explicit inline for non performance critical functions.
+{
+ uint8_t bar = cap->bar;
+ uint32_t length = cap->length;
+ uint32_t offset = cap->offset;
+ uint8_t *base;
+
+ if (unlikely(bar > 5)) {Don't use constant value number whenever possible No likely/unlikely for non performance critical functions
+ PMD_INIT_LOG(ERR, "invalid bar: %u", bar);
+ return NULL;
+ }
+
+ if (unlikely(offset + length > dev->mem_resource[bar].len)) {
+ PMD_INIT_LOG(ERR,
+ "invalid cap: overflows bar space: %u > %"PRIu64,
+ offset + length, dev->mem_resource[bar].len);
+ return NULL;
+ }
+
+ base = dev->mem_resource[bar].addr;
+ if (unlikely(base == NULL)) {
+ PMD_INIT_LOG(ERR, "bar %u base addr is NULL", bar);
+ return NULL;
+ }
+
+ return base + offset;
+}
+
+static int
+virtio_read_caps(struct rte_pci_device *dev, struct virtio_hw *hw)
+{
+ uint8_t pos;
+ struct virtio_pci_cap cap;
+ int ret;
+
+ if (rte_eal_pci_map_device(dev) < 0) {
+ PMD_INIT_LOG(DEBUG, "failed to map pci device!");s /DEBUG/ERR/
+ return -1; + } + + ret = rte_eal_pci_read_config(dev, &pos, 1, PCI_CAPABILITY_LIST); +
[snip]