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/getting typo 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]