This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "".
The branch, devel/native-drivers has been updated via 4bd608048e6fa77d3154b8d90b85fc2b66c6bf1a (commit) via 9411a5b8adb5a704155602546ac0afcb975c69fa (commit) via c87b85e87e80462e52e2e7d6a827ae8948ac92ac (commit) via 46ccbc95c13ae7e61462467e1fe60fb00ba09620 (commit) via d073f151fd711ea3bf39711f1d235b8e89d52522 (commit) via c3cda8e1dfbe5a8665d52b167700590bcbfae488 (commit) via 13a5240a9a4035c8c4fb1f03f2113799390c305b (commit) via b339fbc523120497346298d95c5c1102e70c1826 (commit) via 3c372d43de115af127c6fd2d34f365b73b87734b (commit) via 539b29acce1ba915a7c8c65c56a4e5fc9be1ff44 (commit) via 04af087d3523f6db809b979d2a23975de0cc4de8 (commit) via 77f6dd878c4095e9cbb7c9237a0564c62ebc92c3 (commit) via 606b19d60c015a6ac14ef83146ca1019530de4a0 (commit) via 41cfdd1f67e0a44aa3aed04f4ddbaa53b5c43b38 (commit) via 485779a031f467eb242dec0a164b7380612494a4 (commit) via 6cd43041e55bd73a02ca202f835e590b3ad5c354 (commit) via 65419c16086369f86dea068e54ce492526fa4f41 (commit) via d22c949cc466bf28de559855a1cb525740578137 (commit) via 637353bbd96770741cbb58711c78c9dc01e4ea34 (commit) via 387b402c4f2fc0694b6e0fe68ee4be8a2bd42442 (commit) via ebdf6e27af66a58fff6a17a1c6c2cd6ae85909f1 (commit) via cc97d3ae6d6d4c07ec77e7b33e2529154fb0ed24 (commit) via 94cb17b703f1efba6a89207b893d9f4ef5297d8d (commit) via c04eff910a7b18f47365f90fadb6133474e9cae5 (commit) via 201a96f9bbcbabd904362ba05a179c72689a578e (commit) via 3edee38da55876e36f654a5d1a4b87c2ea5b8bfe (commit) via 8d22e0e2013596403ae6a35457cdf30b0a0c559b (commit) via d61d32590d1772b70b8dcd0d0ec44d29029d7443 (commit) via 66b363634fe1bba003cdb9e4e49a5980fc8c79f4 (commit) via bd1b1adf37dd8d252f7daf761d4ae9a6d1ef156a (commit) via 4fafec8378b6e7d0b353d851e724ab27eb002b27 (commit) via 63d92eb289261d1534b5b9e1e04291faa5e45d30 (commit) via 82419a31e6d1846e0676edfa7fb511a23098f5a9 (commit) via c0aeacf23dddfb7feae47fef6e4d10d6bdb9c812 (commit) via dd0498bb104c7319e2ec56b61e4d585167ea6c53 (commit) via e826613858543e50a2ec74598f8c2c6fd4bfa064 (commit) via 503722802274ff5de09144613d9262e2cfdb3077 (commit) via 5329228e260d36de62c3edf3c1a3f08ab95fd558 (commit) via 74d880d7e20ab4825868bd2013b164d4bc90eb45 (commit) via 825f75ed8644ef57c5648961e7982daf13cd9375 (commit) via 18977d0684ef7a26ddd6777ca341f7b1ca9e5c3e (commit) via f4d54b8831df52878b66bb145124a9adb4beab28 (commit) via e733d6ba6382ccbf9d6c84a6a10bf720c2e16c0d (commit) via ec6510b33e8b96d6d6670efb9dc3c9101baed6c6 (commit) via af4565caa0f9d171db466554ee631338b9844cbe (commit) via f5120355753ae3d69f81010cb9131abffdfb03fc (commit) via afa7e20ab3b7a6e68a556f00b49aa19ea4a29be6 (commit) via e3108af2f0b58c2ceca422b418439bba5de04b11 (commit) via 54228421977f94d9da752290540c6ec4dc5306a0 (commit) via 605e77187211dbb0716e4124f249c7f0f88567f7 (commit) via 940c54bbd1c0c16ea2b6a6f6737d151deeba1e43 (commit) via 91ceea49a975c6fcd61ab1c992a502350d673eeb (commit) via b46702e5ef368c9aaf9d6cea7d32b07adb881ce3 (commit) via 48dfcade1602e9cc9bb8cd3251037508aef146cd (commit) via 2aa9a05b11bdfac0c0126384d4677b3f9c561a78 (commit) via df978d9b4e766c8e1cb1a88a28d98318840fee22 (commit) via cd196cf12f957456b24c844b2c38be5062130cf1 (commit) via dee4a7512c21a8b7f15a4a05e6736de373df92f0 (commit) via f70ff3bc542961d52f9b0f867298014650c8e49e (commit) via 700c0ac917fedf532e9a7e21c42624faa4b09a5f (commit) via 20aba9a17664fb8d5261bece23a1c20f1a3465f7 (commit) via ce4bd52afcef245b069acfe8dc53bd62aec576fd (commit) via 01b5f7e0c0bcec5beb58c99573906b1a4ee8e5f0 (commit) via 5e8f87ae22ca0c3e6137f91f15c967aec958a67e (commit) via 9e10a562dfb67b7a37c67fecff3de00be798961a (commit) via 86d651b86c10dd77603354110644ad346dfb3e26 (commit) via bc3cad50ec6668064bae1af164875c93832caff8 (commit) via 9c747985d4c448ef737376c5c8180b78ae1e7378 (commit) via 698f370e71db55624e1bd78063569369f86db389 (commit) via 482eeee380d40596131826c1103ed89247bd17e5 (commit) via 254190ffcdb51549ee23846f33fd45513656b78c (commit) via 52877c96e12bf62614df0482175384565a851083 (commit) via 133e7fc06147486fff5ab3393b1a791ab97d19d3 (commit) via 8c9ce8c63eed9d01fec54c09bd17040914abd623 (commit) via 2b57c7d7b96eef16c36b8b0020b3dd78acc82660 (commit) via cbced85824c4c03c0b35396d559ebfb187237569 (commit) via 1217fbaed0aee2ee395c131bb7fd2e201214ed31 (commit) via 927b57f21124f31e23fd7f72dddcc93a5248ed53 (commit) via 1bcf171f00973bcc21baadf9919a61cd6abdf713 (commit) via edca8cd1e55898826f79383b689c2c4bd2c28b3a (commit) via ec0c3145fcafa09ae3a79875e7e07dd4794583cc (commit) via aa64630294bed950641e99fa1c87725f521a0002 (commit) via 53b4c4aed8cc6e9caf379725e9ed1d2d36f04f10 (commit) via 77f9451a2acf4465e6a64f24b1dfdca56787f0ce (commit) via fce14d1496e7da19e2f0eb53339eea5a4204c03d (commit) via cc33578e327d5f6787711a71a60500c4be98bf63 (commit) via 4ab7a7b22b15011eb69c3e473278db13319aba52 (commit) via 53b735f14a9a1df23b054f15ce148e2fa36abe0f (commit) via 4df71d3f5450452a654bb7e94f8b3fed948ed31e (commit) via 326192cd87888abbea6c0dbdd3dc972db41f3325 (commit) via 55e6afa29bdc2ae314bada7ac5648049909e1775 (commit) via ff51f6363c9fad843f7872ad8048740d10368dd1 (commit) via 6a119c79b59de3c8ee9e51f3ceba9d26f24c3ce4 (commit) via 7d162deafa22535f8fab9ea39dcb4e3e0e7850b0 (commit) via adaa3b434086346402999d09c2223681aba4b1a4 (commit) via c657f3f3d9b2c5832b42a4344a526bf7d0c76a5d (commit) via e02f5545f97f90a75f2595bb1e9068f64bff133e (commit) via d0d0bd9787ee43db39ad4e7e9b224e70664d5663 (commit) via 7dc5f21c7ca88e6c19d34dc1933eddef190add7a (commit) via 209c3a2e255de7aa82c4f08f8abb41c04bb3d86d (commit) via ae4f1d82ed704992c1d8284c23795b9e076b33b9 (commit) via d2b3aa9a7ffc3028eedc7dbeb6257d7efd91bc05 (commit) via 66305f01a57741dc5eca061364e65a5f4da8584f (commit) via afeda4d14bb6f449cb269680cdbd56b26726eedf (commit) via 1b259a7a4e573080f4debc542cab7a0b996f4c88 (commit) via 4ce7bdf3d99cc1d7634a80f961fc0e9e7523a0ac (commit) via 55fd230da7d8515452c08256f8fd8471d32d7601 (commit) via b529f843814f70068de2090e02df632113afa800 (commit) via fa78c11ad2de706ce07a7691168bdb5b58d060d4 (commit) via 5a2376365df984e160b92463be37740786a10bd6 (commit) via 3f3d7651c7cd7ba3b941904bbcbdabcac9a7dfd0 (commit) via 72a4e9f9bad9dfeaafba4e29a7450ee7edca5d1c (commit) via 7f3624154ff59ab85352c35e1c6df3c9597f9f51 (commit) via bbefeae66a2a6ac6c9386bb8a083022b7f323fc9 (commit) via a08dba6c24af81142efc6176eae2bdd561b478e3 (commit) via 1c02e217fac2ed2d015205ad36bd86c4924ce6cc (commit) via a3bc051085b95170101a3f81379e78c48e5a636c (commit) via fa281989523b82177f974abe7b4adfec47705dfa (commit) via 3bacbfd55edf76b897a4b2e5c62b59ca6fa95331 (commit) via 37b430cb9e8f6834a3c76ab108489cec719b9e32 (commit) via 4d38a376cd9976dfbeb565e509c028d07dfb1ed8 (commit) via c16af6486eea240609f334b1bdc81a11404275de (commit) from c0f99c441feadd1566b7e92789b11c30c6ee3f64 (commit)
Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below.
- Log ----------------------------------------------------------------- commit 4bd608048e6fa77d3154b8d90b85fc2b66c6bf1a Author: Christophe Milard christophe.milard@linaro.org Date: Thu Nov 3 14:24:49 2016 +0100
linux-gen: _ishmphy: adding function for physical address query
The function _odp_ishmphy_getphy() is added to query for physical addresses (given a virtual address) This function is meant to be used to populate the physical address of packet segments which are to be used by drivers (without iommu). The function _odp_ishmphy_can_getphy(), also added, return true if _odp_ishmphy_getphy() is able to works (as it requires specific permission)
Signed-off-by: Christophe Milard christophe.milard@linaro.org
diff --git a/platform/linux-generic/_ishmphy.c b/platform/linux-generic/_ishmphy.c index 76ec5728..fb4c97c9 100644 --- a/platform/linux-generic/_ishmphy.c +++ b/platform/linux-generic/_ishmphy.c @@ -40,6 +40,8 @@ static uint64_t common_va_len; #define MAP_ANONYMOUS MAP_ANON #endif
+#define PAGEMAP_FILE "/proc/self/pagemap" + /* Book some virtual address space * This function is called at odp_init_global() time to pre-book some * virtual address space inherited by all odpthreads (i.e. descendant @@ -207,3 +209,82 @@ int _odp_ishmphy_unmap(void *start, uint64_t len, int flags) ODP_ERR("_ishmphy_free failure: %s\n", strerror(errno)); return ret; } + +/* + * Get physical address from virtual address addr. + */ +phys_addr_t _odp_ishmphy_getphy(const void *addr) +{ + unsigned int page_sz; + int fd; + off_t offset; + int read_bytes; + uint64_t page; + phys_addr_t phys_addr; + + /* get normal page sizes: */ + page_sz = odp_sys_page_size(); + + /* read 8 bytes (uint64_t) at position N*8, where N is addr/page_sz */ + fd = open(PAGEMAP_FILE, O_RDONLY); + if (fd < 0) { + ODP_ERR("cannot open " PAGEMAP_FILE ": %s\n", + strerror(errno)); + return PHYS_ADDR_INVALID; + } + + offset = ((unsigned long)addr / page_sz) * sizeof(uint64_t); + if (lseek(fd, offset, SEEK_SET) == (off_t)-1) { + ODP_ERR("cannot seek " PAGEMAP_FILE ": %s\n", + strerror(errno)); + close(fd); + return PHYS_ADDR_INVALID; + } + + read_bytes = read(fd, &page, sizeof(uint64_t)); + close(fd); + if (read_bytes < 0) { + ODP_ERR("cannot read " PAGEMAP_FILE ": %s\n", + strerror(errno)); + return PHYS_ADDR_INVALID; + } else if (read_bytes != sizeof(uint64_t)) { + ODP_ERR("read %d bytes from " PAGEMAP_FILE " " + "but expected %d:\n", + read_bytes, sizeof(uint64_t)); + return PHYS_ADDR_INVALID; + } + + /* some kernel return PFN zero when permission is denied: */ + if (!(page & 0x7fffffffffffffULL)) + return PHYS_ADDR_INVALID; + + /* + * the pfn (page frame number) are bits 0-54 (see + * pagemap.txt in linux Documentation) + */ + phys_addr = ((page & 0x7fffffffffffffULL) * page_sz) + + ((unsigned long)addr % page_sz); + + return phys_addr; +} + +/* + * check if physical address are readable + * return true if physical addresses can be retrieved. + * Just do a test to see if it works + */ +int _odp_ishmphy_can_getphy(void) +{ + int block_index; + phys_addr_t phy; + + /* allocate a block, locked in memory and try to grab its phy address */ + block_index = _odp_ishm_reserve(NULL, 10, -1, 0, _ODP_ISHM_LOCK, 0); + phy = _odp_ishmphy_getphy((void *)_odp_ishm_address(block_index)); + _odp_ishm_free_by_index(block_index); + + if (phy == PHYS_ADDR_INVALID) + return 0; + + return 1; +} diff --git a/platform/linux-generic/include/_ishmphy_internal.h b/platform/linux-generic/include/_ishmphy_internal.h index 4fe560fd..31b154bd 100644 --- a/platform/linux-generic/include/_ishmphy_internal.h +++ b/platform/linux-generic/include/_ishmphy_internal.h @@ -13,11 +13,25 @@ extern "C" {
#include <stdint.h>
+typedef uint64_t phys_addr_t; /* Physical address definition. */ +#define PHYS_ADDR_INVALID ((phys_addr_t)-1) + void *_odp_ishmphy_book_va(uintptr_t len, intptr_t align); int _odp_ishmphy_unbook_va(void); void *_odp_ishmphy_map(int fd, void *start, uint64_t size, int flags); int _odp_ishmphy_unmap(void *start, uint64_t len, int flags);
+/* + * check if physical address are readable + * return true if physical addresses can be retrieved. + */ +int _odp_ishmphy_can_getphy(void); + +/* + * Get physical address from virtual address addr. + */ +phys_addr_t _odp_ishmphy_getphy(const void *addr); + #ifdef __cplusplus } #endif
commit 9411a5b8adb5a704155602546ac0afcb975c69fa Author: Josep Puigdemont josep.puigdemont@linaro.org Date: Fri Sep 22 13:56:47 2017 +0200
virtio_pci: read configuration layout functions
Functions for reading virtio-net's configuration layout.
Signed-off-by: Josep Puigdemont josep.puigdemont@linaro.org
diff --git a/platform/linux-generic/pktio/virtio_pci.c b/platform/linux-generic/pktio/virtio_pci.c index 1203887f..376ddbea 100644 --- a/platform/linux-generic/pktio/virtio_pci.c +++ b/platform/linux-generic/pktio/virtio_pci.c @@ -451,6 +451,42 @@ static void virtio_get_hwaddr(struct virtio_hw *hw) } }
+static void virtio_get_status(struct virtio_hw *hw) +{ + struct virtio_net_config config; + + if (!vtpci_with_feature(hw, VIRTIO_NET_F_STATUS)) { + ODP_PRINT("No support for VIRTIO_NET_F_STATUS\n"); + return; + } + + vtpci_read_dev_config(hw, + ODPDRV_OFFSETOF(struct virtio_net_config, + status), + &config.status, sizeof(config.status)); + + ODP_PRINT("Status is %u\n", config.status); +} + +static uint16_t virtio_get_num_queues(struct virtio_hw *hw) +{ + uint16_t max_pairs; + + if (!vtpci_with_feature(hw, VIRTIO_NET_F_MQ)) { + ODP_PRINT("No support for VIRTIO_NET_F_MQ\n"); + return 1; + } + + vtpci_read_dev_config(hw, + ODPDRV_OFFSETOF(struct virtio_net_config, + max_virtqueue_pairs), + &max_pairs, sizeof(max_pairs)); + + ODP_PRINT("Device supports maximum of %u virtqueue pairs\n", max_pairs); + + return max_pairs; +} + static int virtio_init_ethdev(struct virtio_hw *hw) { const struct virtio_pci_ops *ops = hw->vtpci_ops; @@ -481,6 +517,21 @@ static int virtio_init_ethdev(struct virtio_hw *hw) }
virtio_get_hwaddr(hw); + virtio_get_status(hw); + + /* some features depend on F_CTRL_VQ being available */ + if (vtpci_with_feature(hw, VIRTIO_NET_F_CTRL_VQ)) { + uint16_t num_pairs; + + num_pairs = virtio_get_num_queues(hw); + /* FIXME: find out minimum available */ + hw->max_tx_queues = num_pairs; + hw->max_rx_queues = num_pairs; + } else { + hw->cvq = NULL; + hw->max_tx_queues = 1; + hw->max_rx_queues = 1; + }
return 0; }
commit c87b85e87e80462e52e2e7d6a827ae8948ac92ac Author: Josep Puigdemont josep.puigdemont@linaro.org Date: Fri Sep 22 11:14:26 2017 +0200
virtio_pci: function to show features
Signed-off-by: Josep Puigdemont josep.puigdemont@linaro.org
diff --git a/platform/linux-generic/pktio/virtio_pci.c b/platform/linux-generic/pktio/virtio_pci.c index 0c780309..1203887f 100644 --- a/platform/linux-generic/pktio/virtio_pci.c +++ b/platform/linux-generic/pktio/virtio_pci.c @@ -63,6 +63,50 @@ 1u << VIRTIO_NET_F_MRG_RXBUF | \ 1ULL << VIRTIO_F_VERSION_1)
+static void virtio_print_features(const struct virtio_hw *hw) +{ + if (vtpci_with_feature(hw, VIRTIO_NET_F_CSUM)) + ODP_PRINT("VIRTIO_NET_F_CSUM\n"); + if (vtpci_with_feature(hw, VIRTIO_NET_F_GUEST_CSUM)) + ODP_PRINT("VIRTIO_NET_F_GUEST_CSUM\n"); + if (vtpci_with_feature(hw, VIRTIO_NET_F_MAC)) + ODP_PRINT("VIRTIO_NET_F_MAC\n"); + if (vtpci_with_feature(hw, VIRTIO_NET_F_GUEST_TSO4)) + ODP_PRINT("VIRTIO_NET_F_GUEST_TSO4\n"); + if (vtpci_with_feature(hw, VIRTIO_NET_F_GUEST_TSO6)) + ODP_PRINT("VIRTIO_NET_F_GUEST_TSO6\n"); + if (vtpci_with_feature(hw, VIRTIO_NET_F_GUEST_ECN)) + ODP_PRINT("VIRTIO_NET_F_GUEST_ECN\n"); + if (vtpci_with_feature(hw, VIRTIO_NET_F_GUEST_UFO)) + ODP_PRINT("VIRTIO_NET_F_GUEST_UFO\n"); + if (vtpci_with_feature(hw, VIRTIO_NET_F_HOST_TSO4)) + ODP_PRINT("VIRTIO_NET_F_HOST_TSO4\n"); + if (vtpci_with_feature(hw, VIRTIO_NET_F_HOST_TSO6)) + ODP_PRINT("VIRTIO_NET_F_HOST_TSO6\n"); + if (vtpci_with_feature(hw, VIRTIO_NET_F_HOST_ECN)) + ODP_PRINT("VIRTIO_NET_F_HOST_ECN\n"); + if (vtpci_with_feature(hw, VIRTIO_NET_F_HOST_UFO)) + ODP_PRINT("VIRTIO_NET_F_HOST_UFO\n"); + if (vtpci_with_feature(hw, VIRTIO_NET_F_MRG_RXBUF)) + ODP_PRINT("VIRTIO_NET_F_MRG_RXBUF\n"); + if (vtpci_with_feature(hw, VIRTIO_NET_F_STATUS)) + ODP_PRINT("VIRTIO_NET_F_STATUS\n"); + if (vtpci_with_feature(hw, VIRTIO_NET_F_CTRL_VQ)) + ODP_PRINT("VIRTIO_NET_F_CTRL_VQ\n"); + if (vtpci_with_feature(hw, VIRTIO_NET_F_CTRL_RX)) + ODP_PRINT("VIRTIO_NET_F_CTRL_RX\n"); + if (vtpci_with_feature(hw, VIRTIO_NET_F_CTRL_VLAN)) + ODP_PRINT("VIRTIO_NET_F_CTRL_VLAN\n"); + if (vtpci_with_feature(hw, VIRTIO_NET_F_CTRL_RX_EXTRA)) + ODP_PRINT("VIRTIO_NET_F_CTRL_RX_EXTRA\n"); + if (vtpci_with_feature(hw, VIRTIO_NET_F_GUEST_ANNOUNCE)) + ODP_PRINT("VIRTIO_NET_F_GUEST_ANNOUNCE\n"); + if (vtpci_with_feature(hw, VIRTIO_NET_F_MQ)) + ODP_PRINT("VIRTIO_NET_F_MQ\n"); + if (vtpci_with_feature(hw, VIRTIO_NET_F_CTRL_MAC_ADDR)) + ODP_PRINT("VIRTIO_NET_F_CTRL_MAC_ADDR\n"); +} + static inline uint8_t io_read8(uint8_t *addr) { return *(volatile uint8_t *)addr; @@ -428,6 +472,7 @@ static int virtio_init_ethdev(struct virtio_hw *hw) }
ops->set_features(hw, hw->guest_features); + virtio_print_features(hw);
ops->set_status(hw, VIRTIO_CONFIG_STATUS_FEATURES_OK); if (!(ops->get_status(hw) & VIRTIO_CONFIG_STATUS_FEATURES_OK)) {
commit 46ccbc95c13ae7e61462467e1fe60fb00ba09620 Author: Josep Puigdemont josep.puigdemont@linaro.org Date: Tue Aug 29 14:48:16 2017 +0200
virtio_pci: common functions for virtio PCI devices
Port from DPDK and François work from branch pci-uio-virtio: https://git.linaro.org/people/francois.ozog/odp.git (removing support for legacy virtio devices)
Signed-off-by: Josep Puigdemont josep.puigdemont@linaro.org
diff --git a/platform/linux-generic/Makefile.am b/platform/linux-generic/Makefile.am index 4d3d3610..2b1e4143 100644 --- a/platform/linux-generic/Makefile.am +++ b/platform/linux-generic/Makefile.am @@ -260,6 +260,7 @@ __LIB__libodp_linux_la_SOURCES = \ pktio/sysfs.c \ pktio/tap.c \ pktio/virtio.c \ + pktio/virtio_pci.c \ pktio/ring.c \ pool/generic.c \ pool/subsystem.c \ diff --git a/platform/linux-generic/include/drv_pci_internal.h b/platform/linux-generic/include/drv_pci_internal.h index ccd61606..fca7d2ef 100644 --- a/platform/linux-generic/include/drv_pci_internal.h +++ b/platform/linux-generic/include/drv_pci_internal.h @@ -11,6 +11,9 @@ extern "C" { #endif
+#define PCI_CAPABILITY_LIST 0x34 +#define PCI_CAP_ID_VNDR 0x09 + /* Nb. of values in PCI resource file format. */ #define PCI_RESOURCE_FMT_NVAL 3 /** Nb. of values in PCI device address string. */ @@ -106,6 +109,7 @@ typedef struct user_access_ops_t { const void *data, size_t len, off_t offset); } user_access_ops_t;
+ /* structure for PCI device: */ typedef struct pci_dev_t { struct pci_dev_t *next; @@ -116,6 +120,8 @@ typedef struct pci_dev_t { enum pci_kernel_driver kdrv; /* Kernel driver */ struct user_access_context_t *user_access_context; const struct user_access_ops_t *user_access_ops; + void *driver_data; + void *device_data; } pci_dev_t;
/* path where PCI devices are shown in sysfs: */ diff --git a/platform/linux-generic/pktio/virtio.c b/platform/linux-generic/pktio/virtio.c index 9b15c2d3..ddeb46f1 100644 --- a/platform/linux-generic/pktio/virtio.c +++ b/platform/linux-generic/pktio/virtio.c @@ -25,6 +25,8 @@ #include <drv_pci_internal.h> #include <odp_pktio_ops_virtio.h>
+#include "virtio_pci.h" + #define PCI_PKTIO_PREFIX "pci:" #define PCI_PKTIO_PREFIX_LEN (sizeof(PCI_PKTIO_PREFIX) - 1)
@@ -59,19 +61,8 @@ static int virtio_open(odp_pktio_t id ODP_UNUSED, pktio_entry_t *pktio_entry, return -1; }
- /* Find suitable DevIO DDF module to work with the driver. */ - if (pci_dev->kdrv == PCI_KDRV_UIO_GENERIC) { - /* probing would be done for each possible DevIO */ - if (uio_access_ops.probe(pci_dev)) { - ODP_ERR("Could not enable DevIO for device %s\n", - devname); - pci_close_device(pci_dev); - return -1; - } - pci_dev->user_access_ops = &uio_access_ops; - } else { - ODP_ERR("Could not find suitable DevIO for device %s\n", - devname); + if (virtio_pci_init(pci_dev)) { + ODP_ERR("virtio: Could not open device %s\n", devname); pci_close_device(pci_dev); return -1; } diff --git a/platform/linux-generic/pktio/virtio_pci.c b/platform/linux-generic/pktio/virtio_pci.c new file mode 100644 index 00000000..0c780309 --- /dev/null +++ b/platform/linux-generic/pktio/virtio_pci.c @@ -0,0 +1,505 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#ifdef ODP_PKTIO_VIRTIO + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#include <stdint.h> +#include <dirent.h> +#include <fcntl.h> +#include <string.h> +#include <inttypes.h> + +#include <config.h> +#include <odp_drv.h> +#include <odp_debug_internal.h> +#include <drv_pci_internal.h> + +#include "virtio_pci.h" + +/* Features desired/implemented by this driver. */ +#define VIRTIO_NET_DRIVER_FEATURES \ + (1u << VIRTIO_NET_F_MAC | \ + 1u << VIRTIO_NET_F_STATUS | \ + 1u << VIRTIO_NET_F_MQ | \ + 1u << VIRTIO_NET_F_CTRL_MAC_ADDR | \ + 1u << VIRTIO_NET_F_CTRL_VQ | \ + 1u << VIRTIO_NET_F_CTRL_RX | \ + 1u << VIRTIO_NET_F_CTRL_VLAN | \ + 1u << VIRTIO_NET_F_MRG_RXBUF | \ + 1ULL << VIRTIO_F_VERSION_1) + +static inline uint8_t io_read8(uint8_t *addr) +{ + return *(volatile uint8_t *)addr; +} + +static inline void io_write8(uint8_t val, uint8_t *addr) +{ + *(volatile uint8_t *)addr = val; +} + +static inline uint16_t io_read16(uint16_t *addr) +{ + return *(volatile uint16_t *)addr; +} + +static inline void io_write16(uint16_t val, uint16_t *addr) +{ + *(volatile uint16_t *)addr = val; +} + +static inline uint32_t io_read32(uint32_t *addr) +{ + return *(volatile uint32_t *)addr; +} + +static inline void io_write32(uint32_t val, uint32_t *addr) +{ + *(volatile uint32_t *)addr = val; +} + +static inline void io_write64_twopart(uint64_t val, uint32_t *lo, uint32_t *hi) +{ + io_write32(val & ((1ULL << 32) - 1), lo); + io_write32(val >> 32, hi); +} + +static void modern_read_dev_config(struct virtio_hw *hw, size_t offset, + void *dst, int length) +{ + int i; + uint8_t *p; + uint8_t old_gen, new_gen; + + do { + old_gen = io_read8(&hw->common_cfg->config_generation); + + p = dst; + for (i = 0; i < length; i++) + *p++ = io_read8((uint8_t *)hw->dev_cfg + offset + i); + + new_gen = io_read8(&hw->common_cfg->config_generation); + } while (old_gen != new_gen); +} + +static void modern_write_dev_config(struct virtio_hw *hw, size_t offset, + const void *src, int length) +{ + int i; + const uint8_t *p = src; + + for (i = 0; i < length; i++) + io_write8(*p++, (uint8_t *)hw->dev_cfg + offset + i); +} + +static uint64_t modern_get_features(struct virtio_hw *hw) +{ + uint32_t features_lo, features_hi; + + io_write32(0, &hw->common_cfg->device_feature_select); + features_lo = io_read32(&hw->common_cfg->device_feature); + + io_write32(1, &hw->common_cfg->device_feature_select); + features_hi = io_read32(&hw->common_cfg->device_feature); + + return ((uint64_t)features_hi << 32) | features_lo; +} + +static void modern_set_features(struct virtio_hw *hw, uint64_t features) +{ + io_write32(0, &hw->common_cfg->guest_feature_select); + io_write32(features & ((1ULL << 32) - 1), + &hw->common_cfg->guest_feature); + + io_write32(1, &hw->common_cfg->guest_feature_select); + io_write32(features >> 32, + &hw->common_cfg->guest_feature); +} + +static uint8_t modern_get_status(struct virtio_hw *hw) +{ + return io_read8(&hw->common_cfg->device_status); +} + +static void modern_set_status(struct virtio_hw *hw, uint8_t status) +{ + io_write8(status, &hw->common_cfg->device_status); +} + +static void modern_reset(struct virtio_hw *hw) +{ + modern_set_status(hw, VIRTIO_CONFIG_STATUS_RESET); + modern_get_status(hw); +} + +static uint8_t modern_get_isr(struct virtio_hw *hw) +{ + return io_read8(hw->isr); +} + +static uint16_t modern_set_config_irq(struct virtio_hw *hw, uint16_t vec) +{ + io_write16(vec, &hw->common_cfg->msix_config); + return io_read16(&hw->common_cfg->msix_config); +} + +static uint16_t modern_get_queue_num(struct virtio_hw *hw, uint16_t queue_id) +{ + io_write16(queue_id, &hw->common_cfg->queue_select); + return io_read16(&hw->common_cfg->queue_size); +} + +static int modern_setup_queue(struct virtio_hw *hw, struct virtqueue *vq) +{ + (void)hw; + (void)vq; + return 0; +} + +static void modern_del_queue(struct virtio_hw *hw, struct virtqueue *vq) +{ + (void)hw; + (void)vq; +} + +static void modern_notify_queue(struct virtio_hw *hw, struct virtqueue *vq) +{ + (void)hw; + (void)vq; +} + +static const struct virtio_pci_ops modern_ops = { + .read_dev_cfg = modern_read_dev_config, + .write_dev_cfg = modern_write_dev_config, + .reset = modern_reset, + .get_status = modern_get_status, + .set_status = modern_set_status, + .get_features = modern_get_features, + .set_features = modern_set_features, + .get_isr = modern_get_isr, + .set_config_irq = modern_set_config_irq, + .get_queue_num = modern_get_queue_num, + .setup_queue = modern_setup_queue, + .del_queue = modern_del_queue, + .notify_queue = modern_notify_queue, +}; + + +void vtpci_read_dev_config(struct virtio_hw *hw, size_t offset, + void *dst, int length) +{ + hw->vtpci_ops->read_dev_cfg(hw, offset, dst, length); +} + +void vtpci_write_dev_config(struct virtio_hw *hw, size_t offset, + const void *src, int length) +{ + hw->vtpci_ops->write_dev_cfg(hw, offset, src, length); +} + +uint64_t vtpci_negotiate_features(struct virtio_hw *hw, uint64_t host_features) +{ + uint64_t features; + + /* + * Limit negotiated features to what the driver, virtqueue, and + * host all support. + */ + features = host_features & hw->guest_features; + hw->vtpci_ops->set_features(hw, features); + + return features; +} + +void vtpci_reset(struct virtio_hw *hw) +{ + hw->vtpci_ops->set_status(hw, VIRTIO_CONFIG_STATUS_RESET); + /* flush status write */ + hw->vtpci_ops->get_status(hw); +} + +void vtpci_reinit_complete(struct virtio_hw *hw) +{ + vtpci_set_status(hw, VIRTIO_CONFIG_STATUS_DRIVER_OK); +} + +void vtpci_set_status(struct virtio_hw *hw, uint8_t status) +{ + if (status != VIRTIO_CONFIG_STATUS_RESET) + status |= hw->vtpci_ops->get_status(hw); + + hw->vtpci_ops->set_status(hw, status); +} + +uint8_t vtpci_get_status(struct virtio_hw *hw) +{ + return hw->vtpci_ops->get_status(hw); +} + +uint8_t vtpci_isr(struct virtio_hw *hw) +{ + return hw->vtpci_ops->get_isr(hw); +} + + +/* Enable one vector (0) for Link State Intrerrupt */ +uint16_t vtpci_irq_config(struct virtio_hw *hw, uint16_t vec) +{ + return hw->vtpci_ops->set_config_irq(hw, vec); +} + +static void *get_cfg_addr(pci_dev_t *dev, struct virtio_pci_cap *cap) +{ + uint8_t bar = cap->bar; + uint32_t length = cap->length; + uint32_t offset = cap->offset; + uint8_t *base; + + if (bar > 5) { + ODP_ERR("invalid bar: %u\n", bar); + return NULL; + } + + if (offset + length < offset) { + ODP_ERR("offset(%u) + length(%u) overflows\n", + offset, length); + return NULL; + } + + if (offset + length > dev->bar[bar].len) { + ODP_ERR("invalid cap: overflows bar space: %u > %\n" PRIu64, + offset + length, dev->bar[bar].len); + return NULL; + } + + base = dev->bar[bar].addr; + if (base == NULL) { + ODP_ERR("bar %u base addr is NULL\n", bar); + return NULL; + } + + return base + offset; +} + +static int virtio_read_caps(pci_dev_t *dev, struct virtio_hw *hw) +{ + uint8_t pos; + struct virtio_pci_cap cap; + int ret; + + if (dev->user_access_ops->map_resource(dev)) { + ODP_DBG("failed to map pci device!\n"); + return -1; + } + + ret = pci_read_config(dev, &pos, 1, PCI_CAPABILITY_LIST); + if (ret < 0) { + ODP_DBG("failed to read pci capability list\n"); + return -1; + } + + while (pos) { + ret = pci_read_config(dev, &cap, sizeof(cap), pos); + if (ret < 0) { + ODP_ERR("failed to read pci cap at pos: %x\n", pos); + break; + } + + if (cap.cap_vndr != PCI_CAP_ID_VNDR) { + ODP_DBG("[%2x] skipping non VNDR cap id: %02x\n", + pos, cap.cap_vndr); + goto next; + } + + ODP_DBG("[%2x] cfg type: %u, bar: %u, offset: %04x, len: %u\n", + pos, cap.cfg_type, cap.bar, cap.offset, cap.length); + + switch (cap.cfg_type) { + case VIRTIO_PCI_CAP_COMMON_CFG: + hw->common_cfg = get_cfg_addr(dev, &cap); + break; + case VIRTIO_PCI_CAP_NOTIFY_CFG: + pci_read_config(dev, &hw->notify_off_multiplier, + 4, pos + sizeof(cap)); + hw->notify_base = get_cfg_addr(dev, &cap); + break; + case VIRTIO_PCI_CAP_DEVICE_CFG: + hw->dev_cfg = get_cfg_addr(dev, &cap); + break; + case VIRTIO_PCI_CAP_ISR_CFG: + hw->isr = get_cfg_addr(dev, &cap); + break; + } + +next: + pos = cap.cap_next; + } + + if (hw->common_cfg == NULL || hw->notify_base == NULL || + hw->dev_cfg == NULL || hw->isr == NULL) { + ODP_DBG("no modern virtio pci device found.\n"); + return -1; + } + + ODP_DBG("found modern virtio pci device.\n"); + + ODP_DBG("common cfg mapped at: %p\n", hw->common_cfg); + ODP_DBG("device cfg mapped at: %p\n", hw->dev_cfg); + ODP_DBG("isr cfg mapped at: %p\n", hw->isr); + ODP_DBG("notify base: %p, notify off multiplier: %u\n", + hw->notify_base, hw->notify_off_multiplier); + + return 0; +} + +static void virtio_get_hwaddr(struct virtio_hw *hw) +{ + if (vtpci_with_feature(hw, VIRTIO_NET_F_MAC)) { + vtpci_read_dev_config(hw, + ODPDRV_OFFSETOF(struct virtio_net_config, + mac), + &hw->mac_addr, + 6); + ODP_PRINT("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", + hw->mac_addr[0], + hw->mac_addr[1], + hw->mac_addr[2], + hw->mac_addr[3], + hw->mac_addr[4], + hw->mac_addr[5]); + } else { + ODP_PRINT("No support for VIRTIO_NET_F_MAC\n"); + } +} + +static int virtio_init_ethdev(struct virtio_hw *hw) +{ + const struct virtio_pci_ops *ops = hw->vtpci_ops; + uint64_t device_features = 0; + + ODP_PRINT("Init VirtIO Net device\n"); + + ops->reset(hw); + ops->set_status(hw, VIRTIO_CONFIG_STATUS_ACK); + ops->set_status(hw, VIRTIO_CONFIG_STATUS_DRIVER); + device_features = ops->get_features(hw); + + /* accept only those feature this driver also supports */ + hw->guest_features = device_features & VIRTIO_NET_DRIVER_FEATURES; + + if (!vtpci_with_feature(hw, VIRTIO_F_VERSION_1)) { + ODP_ERR("VirtIO device does not comply with VirtIO 1.0 spec\n"); + return -1; + } + + ops->set_features(hw, hw->guest_features); + + ops->set_status(hw, VIRTIO_CONFIG_STATUS_FEATURES_OK); + if (!(ops->get_status(hw) & VIRTIO_CONFIG_STATUS_FEATURES_OK)) { + ODP_ERR("VirtIO device error negotiationg features\n"); + return -1; + } + + virtio_get_hwaddr(hw); + + return 0; +} + +/* FIXME: this should be registered as a DevIO */ +extern const user_access_ops_t uio_access_ops; + +/* + * Return -1: + * if there is error mapping with VFIO/UIO. + * if port map error when driver type is KDRV_NONE. + * if whitelisted but driver type is KDRV_UNKNOWN. + * Return 1 if kernel driver is managing the device. + * Return 0 on success. + */ +int virtio_pci_init(pci_dev_t *dev) +{ + struct virtio_hw *hw = NULL; + + if (dev->id.vendor_id != VIRTIO_PCI_VENDOR_ID) + return -1; + + if (dev->id.device_id != VIRTIO_PCI_LEGACY_DEVICE_ID_NET && + dev->id.device_id != VIRTIO_PCI_MODERN_DEVICE_ID_NET) + return -1; + + hw = malloc(sizeof(struct virtio_hw)); + if (hw == NULL) + return -1; + memset(hw, 0, sizeof(struct virtio_hw)); + + /* Find suitable DevIO module that works with this device */ + if (dev->kdrv == PCI_KDRV_UIO_GENERIC) { + /* probing would be done for each possible DevIO */ + if (uio_access_ops.probe(dev) != 0) + goto err_free; + dev->user_access_ops = &uio_access_ops; + } else { + ODP_ERR("Could not find suitable DevIO for device\n"); + goto err_free; + } + + /* + * Try if we can succeed reading virtio pci caps, which exists + * only on modern pci device. + */ + if (virtio_read_caps(dev, hw) != 0) { + /* we only support modern interface */ + ODP_ERR("virtio_pci: could not read device capabilities\n"); + goto err_free; + } + + hw->dev = dev; + hw->vtpci_ops = &modern_ops; + hw->modern = 1; + if (virtio_init_ethdev(hw) != 0) + goto err_free; + dev->driver_data = (void *)hw; + + return 0; + +err_free: + free(hw); + return -1; +} + +#endif diff --git a/platform/linux-generic/pktio/virtio_pci.h b/platform/linux-generic/pktio/virtio_pci.h new file mode 100644 index 00000000..3e176315 --- /dev/null +++ b/platform/linux-generic/pktio/virtio_pci.h @@ -0,0 +1,320 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _VIRTIO_PCI_H_ +#define _VIRTIO_PCI_H_ + +#include <stdint.h> + +#include <drv_pci_internal.h> + +struct virtqueue; +struct virtnet_ctl; + +/* VirtIO PCI vendor/device ID. */ +#define VIRTIO_PCI_VENDOR_ID 0x1AF4 +#define VIRTIO_PCI_LEGACY_DEVICE_ID_NET 0x1000 +#define VIRTIO_PCI_MODERN_DEVICE_ID_NET 0x1041 + +/* VirtIO ABI version, this must match exactly. */ +#define VIRTIO_PCI_ABI_VERSION 0 + +/* + * VirtIO Header, located in BAR 0. + */ +#define VIRTIO_PCI_HOST_FEATURES 0 /* host's supported features (32bit, RO)*/ +#define VIRTIO_PCI_GUEST_FEATURES 4 /* guest's supported features (32, RW) */ +#define VIRTIO_PCI_QUEUE_PFN 8 /* physical address of VQ (32, RW) */ +#define VIRTIO_PCI_QUEUE_NUM 12 /* number of ring entries (16, RO) */ +#define VIRTIO_PCI_QUEUE_SEL 14 /* current VQ selection (16, RW) */ +#define VIRTIO_PCI_QUEUE_NOTIFY 16 /* notify host regarding VQ (16, RW) */ +#define VIRTIO_PCI_STATUS 18 /* device status register (8, RW) */ +#define VIRTIO_PCI_ISR 19 /* interrupt status register, reading + * also clears the register (8, RO) */ +/* Only if MSIX is enabled: */ +#define VIRTIO_MSI_CONFIG_VECTOR 20 /* configuration change vector (16, RW) */ +#define VIRTIO_MSI_QUEUE_VECTOR 22 /* vector for selected VQ notifications + (16, RW) */ + +/* The bit of the ISR which indicates a device has an interrupt. */ +#define VIRTIO_PCI_ISR_INTR 0x1 +/* The bit of the ISR which indicates a device configuration change. */ +#define VIRTIO_PCI_ISR_CONFIG 0x2 +/* Vector value used to disable MSI for queue. */ +#define VIRTIO_MSI_NO_VECTOR 0xFFFF + +/* VirtIO device IDs. */ +#define VIRTIO_ID_NETWORK 0x01 +#define VIRTIO_ID_BLOCK 0x02 +#define VIRTIO_ID_CONSOLE 0x03 +#define VIRTIO_ID_ENTROPY 0x04 +#define VIRTIO_ID_BALLOON 0x05 +#define VIRTIO_ID_IOMEMORY 0x06 +#define VIRTIO_ID_9P 0x09 + +/* Status byte for guest to report progress. */ +#define VIRTIO_CONFIG_STATUS_RESET 0x00 +#define VIRTIO_CONFIG_STATUS_ACK 0x01 +#define VIRTIO_CONFIG_STATUS_DRIVER 0x02 +#define VIRTIO_CONFIG_STATUS_DRIVER_OK 0x04 +#define VIRTIO_CONFIG_STATUS_FEATURES_OK 0x08 +#define VIRTIO_CONFIG_STATUS_FAILED 0x80 + +/* + * Each virtqueue indirect descriptor list must be physically contiguous. + * To allow us to malloc(9) each list individually, limit the number + * supported to what will fit in one page. With 4KB pages, this is a limit + * of 256 descriptors. If there is ever a need for more, we can switch to + * contigmalloc(9) for the larger allocations, similar to what + * bus_dmamem_alloc(9) does. + * + * Note the sizeof(struct vring_desc) is 16 bytes. + */ +#define VIRTIO_MAX_INDIRECT ((int) (PAGE_SIZE / 16)) + +/* The feature bitmap for virtio net */ +#define VIRTIO_NET_F_CSUM 0 /* Host handles pkts w/ partial csum */ +#define VIRTIO_NET_F_GUEST_CSUM 1 /* Guest handles pkts w/ partial csum */ +#define VIRTIO_NET_F_MAC 5 /* Host has given MAC address. */ +#define VIRTIO_NET_F_GUEST_TSO4 7 /* Guest can handle TSOv4 in. */ +#define VIRTIO_NET_F_GUEST_TSO6 8 /* Guest can handle TSOv6 in. */ +#define VIRTIO_NET_F_GUEST_ECN 9 /* Guest can handle TSO[6] w/ ECN in. */ +#define VIRTIO_NET_F_GUEST_UFO 10 /* Guest can handle UFO in. */ +#define VIRTIO_NET_F_HOST_TSO4 11 /* Host can handle TSOv4 in. */ +#define VIRTIO_NET_F_HOST_TSO6 12 /* Host can handle TSOv6 in. */ +#define VIRTIO_NET_F_HOST_ECN 13 /* Host can handle TSO[6] w/ ECN in. */ +#define VIRTIO_NET_F_HOST_UFO 14 /* Host can handle UFO in. */ +#define VIRTIO_NET_F_MRG_RXBUF 15 /* Host can merge receive buffers. */ +#define VIRTIO_NET_F_STATUS 16 /* virtio_net_config.status available */ +#define VIRTIO_NET_F_CTRL_VQ 17 /* Control channel available */ +#define VIRTIO_NET_F_CTRL_RX 18 /* Control channel RX mode support */ +#define VIRTIO_NET_F_CTRL_VLAN 19 /* Control channel VLAN filtering */ +#define VIRTIO_NET_F_CTRL_RX_EXTRA 20 /* Extra RX mode control support */ +#define VIRTIO_NET_F_GUEST_ANNOUNCE 21 /* Guest can announce device on the + * network */ +#define VIRTIO_NET_F_MQ 22 /* Device supports Receive Flow + * Steering */ +#define VIRTIO_NET_F_CTRL_MAC_ADDR 23 /* Set MAC address */ + +/* Do we get callbacks when the ring is completely used, even if we've + * suppressed them? */ +#define VIRTIO_F_NOTIFY_ON_EMPTY 24 + +/* Can the device handle any descriptor layout? */ +#define VIRTIO_F_ANY_LAYOUT 27 + +/* We support indirect buffer descriptors */ +#define VIRTIO_RING_F_INDIRECT_DESC 28 + +#define VIRTIO_F_VERSION_1 32 + +/* + * Some VirtIO feature bits (currently bits 28 through 31) are + * reserved for the transport being used (eg. virtio_ring), the + * rest are per-device feature bits. + */ +#define VIRTIO_TRANSPORT_F_START 28 +#define VIRTIO_TRANSPORT_F_END 32 + +/* The Guest publishes the used index for which it expects an interrupt + * at the end of the avail ring. Host should ignore the avail->flags field. */ +/* The Host publishes the avail index for which it expects a kick + * at the end of the used ring. Guest should ignore the used->flags field. */ +#define VIRTIO_RING_F_EVENT_IDX 29 + +#define VIRTIO_NET_S_LINK_UP 1 /* Link is up */ +#define VIRTIO_NET_S_ANNOUNCE 2 /* Announcement is needed */ + +/* + * Maximum number of virtqueues per device. + */ +#define VIRTIO_MAX_VIRTQUEUES 8 + +/* Common configuration */ +#define VIRTIO_PCI_CAP_COMMON_CFG 1 +/* Notifications */ +#define VIRTIO_PCI_CAP_NOTIFY_CFG 2 +/* ISR Status */ +#define VIRTIO_PCI_CAP_ISR_CFG 3 +/* Device specific configuration */ +#define VIRTIO_PCI_CAP_DEVICE_CFG 4 +/* PCI configuration access */ +#define VIRTIO_PCI_CAP_PCI_CFG 5 + +/* This is the PCI capability header: */ +struct virtio_pci_cap { + uint8_t cap_vndr; /* Generic PCI field: PCI_CAP_ID_VNDR */ + uint8_t cap_next; /* Generic PCI field: next ptr. */ + uint8_t cap_len; /* Generic PCI field: capability length */ + uint8_t cfg_type; /* Identifies the structure. */ + uint8_t bar; /* Where to find it. */ + uint8_t padding[3]; /* Pad to full dword. */ + uint32_t offset; /* Offset within bar. */ + uint32_t length; /* Length of the structure, in bytes. */ +}; + +struct virtio_pci_notify_cap { + struct virtio_pci_cap cap; + uint32_t notify_off_multiplier; /* Multiplier for queue_notify_off. */ +}; + +/* Fields in VIRTIO_PCI_CAP_COMMON_CFG: */ +struct virtio_pci_common_cfg { + /* About the whole device. */ + uint32_t device_feature_select; /* read-write */ + uint32_t device_feature; /* read-only */ + uint32_t guest_feature_select; /* read-write */ + uint32_t guest_feature; /* read-write */ + uint16_t msix_config; /* read-write */ + uint16_t num_queues; /* read-only */ + uint8_t device_status; /* read-write */ + uint8_t config_generation; /* read-only */ + + /* About a specific virtqueue. */ + uint16_t queue_select; /* read-write */ + uint16_t queue_size; /* read-write, power of 2. */ + uint16_t queue_msix_vector; /* read-write */ + uint16_t queue_enable; /* read-write */ + uint16_t queue_notify_off; /* read-only */ + uint32_t queue_desc_lo; /* read-write */ + uint32_t queue_desc_hi; /* read-write */ + uint32_t queue_avail_lo; /* read-write */ + uint32_t queue_avail_hi; /* read-write */ + uint32_t queue_used_lo; /* read-write */ + uint32_t queue_used_hi; /* read-write */ +}; + +struct virtio_hw; + +struct virtio_pci_ops { + void (*read_dev_cfg)(struct virtio_hw *hw, size_t offset, + void *dst, int len); + void (*write_dev_cfg)(struct virtio_hw *hw, size_t offset, + const void *src, int len); + void (*reset)(struct virtio_hw *hw); + + uint8_t (*get_status)(struct virtio_hw *hw); + void (*set_status)(struct virtio_hw *hw, uint8_t status); + + uint64_t (*get_features)(struct virtio_hw *hw); + void (*set_features)(struct virtio_hw *hw, uint64_t features); + + uint8_t (*get_isr)(struct virtio_hw *hw); + + uint16_t (*set_config_irq)(struct virtio_hw *hw, uint16_t vec); + + uint16_t (*get_queue_num)(struct virtio_hw *hw, uint16_t queue_id); + int (*setup_queue)(struct virtio_hw *hw, struct virtqueue *vq); + void (*del_queue)(struct virtio_hw *hw, struct virtqueue *vq); + void (*notify_queue)(struct virtio_hw *hw, struct virtqueue *vq); +}; + +struct virtio_net_config; + +/* it's ugly, and it will be fixed */ +#define driver_data_t virtio_hw + +struct driver_data_t { + struct virtnet_ctl *cvq; + pci_ioport_t io; + uint64_t guest_features; + uint32_t max_tx_queues; + uint32_t max_rx_queues; + uint16_t vtnet_hdr_size; + uint8_t vlan_strip; + uint8_t use_msix; + uint8_t started; + uint8_t modern; + uint8_t mac_addr[6]; + uint32_t notify_off_multiplier; + uint8_t *isr; + uint16_t *notify_base; + pci_dev_t *dev; + struct virtio_pci_common_cfg *common_cfg; + struct virtio_net_config *dev_cfg; + const struct virtio_pci_ops *vtpci_ops; + void *virtio_user_dev; +}; + +/* + * This structure is just a reference to read + * net device specific config space; it just a chodu structure + * + */ +struct virtio_net_config { + /* The config defining mac address (if VIRTIO_NET_F_MAC) */ + uint8_t mac[6]; + /* See VIRTIO_NET_F_STATUS and VIRTIO_NET_S_* above */ + uint16_t status; + uint16_t max_virtqueue_pairs; +} __attribute__((packed)); + +/* + * How many bits to shift physical queue address written to QUEUE_PFN. + * 12 is historical, and due to x86 page size. + */ +#define VIRTIO_PCI_QUEUE_ADDR_SHIFT 12 + +/* The alignment to use between consumer and producer parts of vring. */ +#define VIRTIO_PCI_VRING_ALIGN 4096 + +static inline int +vtpci_with_feature(const struct virtio_hw *hw, uint64_t bit) +{ + return (hw->guest_features & (1ULL << bit)) != 0; +} + +/* + * Function declaration from virtio_pci.c + */ +int vtpci_init(pci_dev_t *, struct virtio_hw *); +void vtpci_reset(struct virtio_hw *); + +void vtpci_reinit_complete(struct virtio_hw *); + +uint8_t vtpci_get_status(struct virtio_hw *); +void vtpci_set_status(struct virtio_hw *, uint8_t); + +uint64_t vtpci_negotiate_features(struct virtio_hw *, uint64_t); + +void vtpci_write_dev_config(struct virtio_hw *, size_t, const void *, int); + +void vtpci_read_dev_config(struct virtio_hw *, size_t, void *, int); + +uint8_t vtpci_isr(struct virtio_hw *); + +uint16_t vtpci_irq_config(struct virtio_hw *, uint16_t); + +int virtio_pci_init(pci_dev_t *dev); + +#endif /* _VIRTIO_PCI_H_ */
commit d073f151fd711ea3bf39711f1d235b8e89d52522 Author: Josep Puigdemont josep.puigdemont@linaro.org Date: Tue Aug 29 14:02:46 2017 +0200
drv_pci: port ioport operations from DPDK.
This is ported from DPDK, copied from initial port by François at: https://git.linaro.org/people/francois.ozog/odp.git (27237321a)
Signed-off-by: Josep Puigdemont josep.puigdemont@linaro.org
diff --git a/platform/linux-generic/drv_pci.c b/platform/linux-generic/drv_pci.c index d90bfa6e..065ba33d 100644 --- a/platform/linux-generic/drv_pci.c +++ b/platform/linux-generic/drv_pci.c @@ -652,6 +652,84 @@ int _odp_pci_term_global(void) return 0; }
+int pci_ioport_map(pci_dev_t *dev , int idx, pci_ioport_t *p) +{ + int ret = -1; + + if (dev == NULL || dev->user_access_ops == NULL) { + ODP_DBG("Called pci_unmap_device with NULL device or " + "dev->user_access_ops.\n"); + return -1; + } + + if (dev->user_access_ops->ioport_map == NULL) { + ODP_DBG("Called pci_unmap_device with ioport_map==NULL.\n"); + return -1; + } + + ret = dev->user_access_ops->ioport_map(dev, idx, p); + + if (!ret) + p->dev = dev; + + return ret; +} + +int pci_ioport_unmap(pci_dev_t *dev, pci_ioport_t *p ) +{ + int ret = -1; + + if (dev == NULL || dev->user_access_ops == NULL) { + ODP_DBG("Called pci_unmap_device with NULL device or " + "dev->user_access_ops.\n"); + return -1; + } + + if (dev->user_access_ops->ioport_unmap == NULL) { + ODP_DBG("Called pci_unmap_device with " + "pci_ioport_unmap==NULL.\n"); + return -1; + } + + ret = dev->user_access_ops->ioport_unmap(dev, p); + + return ret; +} + +void pci_ioport_read(pci_dev_t *dev, pci_ioport_t *p, void *data, size_t len, + off_t offset) +{ + if (dev == NULL || dev->user_access_ops == NULL) { + ODP_DBG("Called pci_unmap_device with NULL device or " + "dev->user_access_ops.\n"); + return ; + } + + if (dev->user_access_ops->ioport_read == NULL) { + ODP_DBG("Called pci_unmap_device with ioport_read==NULL.\n"); + return ; + } + + dev->user_access_ops->ioport_read(dev, p, data, len, offset); +} + +void pci_ioport_write(pci_dev_t *dev, pci_ioport_t *p ODP_UNUSED, + const void *data ODP_UNUSED, size_t len ODP_UNUSED, + off_t offset ODP_UNUSED) +{ + if (dev == NULL || dev->user_access_ops == NULL) { + ODP_DBG("Called pci_unmap_device with NULL device or " + "dev->user_access_ops.\n"); + return ; + } + + if (dev->user_access_ops->ioport_write == NULL) { + ODP_DBG("Called pci_unmap_device with ioport_write==NULL.\n"); + return ; + } + + dev->user_access_ops->ioport_write(dev, p, data, len, offset); +}
/* pci drivers use this function to open a PCI device from the /sys/bus filesystem * It returns a pci_dev_t struct with several fields filled in. The driver can diff --git a/platform/linux-generic/include/drv_pci_internal.h b/platform/linux-generic/include/drv_pci_internal.h index 7fab1375..ccd61606 100644 --- a/platform/linux-generic/include/drv_pci_internal.h +++ b/platform/linux-generic/include/drv_pci_internal.h @@ -67,7 +67,7 @@ enum pci_kernel_driver {
/** * A structure used to access io resources for a pci device. - * rte_pci_ioport is arch, os, driver specific, and should not be used outside + * pci_ioport_t is arch, os, driver specific, and should not be used outside * of pci ioport api. */ typedef struct pci_ioport_t { @@ -120,8 +120,18 @@ typedef struct pci_dev_t {
/* path where PCI devices are shown in sysfs: */ const char *pci_get_sysfs_path(void); + +/* read from PCI configuration area len bytes at offset */ int pci_read_config(pci_dev_t *dev, void *buf, size_t len, off_t offset);
+/* IO port operations */ +int pci_ioport_map(pci_dev_t *dev, int bar, pci_ioport_t *p); +int pci_ioport_unmap(pci_dev_t *dev, pci_ioport_t *p); +void pci_ioport_read(pci_dev_t *dev, pci_ioport_t *p, void *data, size_t len, + off_t offset); +void pci_ioport_write(pci_dev_t *dev, pci_ioport_t *p,const void *data, + size_t len, off_t offset); + struct pci_dev_t *pci_open_device(const char *); int pci_close_device(pci_dev_t *);
commit c3cda8e1dfbe5a8665d52b167700590bcbfae488 Author: Josep Puigdemont josep.puigdemont@linaro.org Date: Tue Aug 22 14:02:44 2017 +0200
drv_pci: add pci_read_config method.
Signed-off-by: Josep Puigdemont josep.puigdemont@linaro.org
diff --git a/platform/linux-generic/drv_pci.c b/platform/linux-generic/drv_pci.c index c75c1768..d90bfa6e 100644 --- a/platform/linux-generic/drv_pci.c +++ b/platform/linux-generic/drv_pci.c @@ -157,6 +157,21 @@ const char *pci_get_sysfs_path(void) return path; }
+int pci_read_config(pci_dev_t *dev, void *buf, size_t len, off_t offset) +{ + if (dev == NULL || dev->user_access_ops == NULL) { + ODP_DBG("Called pci_read_config with NULL device or dev->user_access_ops.\n"); + return -1; + } + + if (dev->user_access_ops->read_config == NULL) { + ODP_DBG("Called pci_read_config with read_config==NULL.\n"); + return -1; + } + + return dev->user_access_ops->read_config(dev, buf, len, offset); +} + /* * parse a sysfs (or other) file containing one integer value * return this positive integer, or -1 on error diff --git a/platform/linux-generic/include/drv_pci_internal.h b/platform/linux-generic/include/drv_pci_internal.h index b1095c03..7fab1375 100644 --- a/platform/linux-generic/include/drv_pci_internal.h +++ b/platform/linux-generic/include/drv_pci_internal.h @@ -120,6 +120,7 @@ typedef struct pci_dev_t {
/* path where PCI devices are shown in sysfs: */ const char *pci_get_sysfs_path(void); +int pci_read_config(pci_dev_t *dev, void *buf, size_t len, off_t offset);
struct pci_dev_t *pci_open_device(const char *); int pci_close_device(pci_dev_t *);
commit 13a5240a9a4035c8c4fb1f03f2113799390c305b Author: Josep Puigdemont josep.puigdemont@linaro.org Date: Tue Aug 22 09:32:06 2017 +0200
uio_pci: initial port from DPDK
This is a modified version of an initial UIO driver from: https://git.linaro.org/people/francois.ozog/odp.git
in turn taken from DPDK
Signed-off-by: Josep Puigdemont josep.puigdemont@linaro.org
diff --git a/platform/linux-generic/Makefile.am b/platform/linux-generic/Makefile.am index 11b03b60..4d3d3610 100644 --- a/platform/linux-generic/Makefile.am +++ b/platform/linux-generic/Makefile.am @@ -290,6 +290,7 @@ __LIB__libodp_linux_la_SOURCES = \ drv_barrier.c \ drv_driver.c \ drv_pci.c \ + drv_pci_uio.c \ drv_shm.c \ drv_spinlock.c
diff --git a/platform/linux-generic/drv_pci.c b/platform/linux-generic/drv_pci.c index 04a73772..c75c1768 100644 --- a/platform/linux-generic/drv_pci.c +++ b/platform/linux-generic/drv_pci.c @@ -637,6 +637,7 @@ int _odp_pci_term_global(void) return 0; }
+ /* pci drivers use this function to open a PCI device from the /sys/bus filesystem * It returns a pci_dev_t struct with several fields filled in. The driver can * then decide if it can handle the device or not based on device ID. @@ -669,3 +670,13 @@ pci_dev_t *pci_open_device(const char *dev)
return pci_dev; } + +int pci_close_device(pci_dev_t *dev) +{ + if (dev->user_access_ops != NULL) + dev->user_access_ops->unmap_resource(dev); + + free_dev(dev); + + return 0; +} diff --git a/platform/linux-generic/drv_pci_uio.c b/platform/linux-generic/drv_pci_uio.c new file mode 100644 index 00000000..d11c868c --- /dev/null +++ b/platform/linux-generic/drv_pci_uio.c @@ -0,0 +1,622 @@ +#/* Copyright (c) 2016, Linaro Limited +* All rights reserved. +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +/* Many of this functions have been inspired by their dpdk counterpart, + * hence the following copyright and license: + */ + +/* + * BSD LICENSE + * + * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. + * All rights reserved. + */ + +/** + * @file + * PCI interface for UIO drivers + */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#include <stdio.h> + +#if !defined (ARM_ARCHITECTURE) +#include <sys/io.h> +#endif + +#include <sys/types.h> +#include <sys/stat.h> +#include <ctype.h> +#include <stdlib.h> +#include <string.h> +#include <dirent.h> +#include <linux/limits.h> +#include <unistd.h> +#include <errno.h> +#include <malloc.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <linux/pci_regs.h> +#include <_str_functions_internal.h> + +#include <odp_posix_extensions.h> +#include <odp_config_internal.h> +#include <odp_internal.h> +#include <odp/drv/shm.h> +#include <odp_debug_internal.h> + +#include <drv_pci_internal.h> + +typedef struct user_access_context_t { + int uio_num; /**< device number assigned by UIO: /dev/uioX */ + int uio_fd; /**< file descriptor for /dev/uioX */ + int uio_cfg_fd; /**< file descriptor for accessing device's config space */ + int nb_maps; + struct pci_map maps[PCI_MAX_RESOURCE]; + char path[PATH_MAX]; +} user_access_context_t; + +void *pci_map_addr = NULL; + + +/* map a particular resource from a file */ +static void *pci_uio_map_resource(void *requested_addr, int fd, off_t offset, + size_t size, int additional_flags) +{ + void *mapaddr; + + /* Map the PCI memory resource of device */ + mapaddr = mmap(requested_addr, size, PROT_READ | PROT_WRITE, + MAP_SHARED | additional_flags, fd, offset); + if (mapaddr == MAP_FAILED) { + ODP_ERR("%s(): cannot mmap(%d, %p, 0x%lx, 0x%lx): %s (%p)\n", + __func__, fd, requested_addr, + (unsigned long)size, (unsigned long)offset, + strerror(errno), mapaddr); + } else { + ODP_ERR(" PCI memory mapped at %p\n", mapaddr); + } + + return mapaddr; +} + +static int pci_uio_set_bus_master(pci_dev_t *dev) +{ + uint16_t reg; + int ret; + int cfg_fd = dev->user_access_context->uio_cfg_fd; + + ret = pread(cfg_fd, ®, sizeof(reg), PCI_COMMAND); + if (ret != sizeof(reg)) { + ODP_ERR("Cannot read command from PCI config space!\n"); + return -1; + } + + /* return if bus mastering is already on */ + if (reg & PCI_COMMAND_MASTER) + return 0; + + reg |= PCI_COMMAND_MASTER; + + ret = pwrite(cfg_fd, ®, sizeof(reg), PCI_COMMAND); + if (ret != sizeof(reg)) { + ODP_ERR("Cannot write command to PCI config space!\n"); + return -1; + } + + return 0; +} + +/* + * Return the uioX char device used for a pci device. On success, return + * the UIO number and fill dstbuf string with the path of the device in + * sysfs. On error, return a negative value. In this case dstbuf is + * invalid. + */ +static int pci_uio_get_uio_dev(pci_dev_t *dev, char *dstbuf, + unsigned int buflen) +{ + struct pci_addr_t *loc = &dev->addr; + unsigned int uio_num; + struct dirent *e; + DIR *dir; + char dirname[PATH_MAX]; + + /* depending on kernel version, uio can be located in uio/uioX + * or uio:uioX */ + + snprintf(dirname, sizeof(dirname), + "%s/" PCI_PRI_FMT "/uio", pci_get_sysfs_path(), + loc->domain, loc->bus, loc->devid, loc->function); + + dir = opendir(dirname); + if (dir == NULL) { + /* retry with the parent directory */ + snprintf(dirname, sizeof(dirname), + "%s/" PCI_PRI_FMT, pci_get_sysfs_path(), + loc->domain, loc->bus, loc->devid, loc->function); + dir = opendir(dirname); + + if (dir == NULL) { + ODP_ERR("Cannot opendir %s\n", dirname); + return -1; + } + } + + /* take the first file starting with "uio" */ + while ((e = readdir(dir)) != NULL) { + /* format could be uio%d ...*/ + int shortprefix_len = sizeof("uio") - 1; + /* ... or uio:uio%d */ + int longprefix_len = sizeof("uio:uio") - 1; + char *endptr; + + if (strncmp(e->d_name, "uio", 3) != 0) + continue; + + /* first try uio%d */ + errno = 0; + uio_num = strtoull(e->d_name + shortprefix_len, &endptr, 10); + if (errno == 0 && endptr != (e->d_name + shortprefix_len)) { + snprintf(dstbuf, buflen, "%s/uio%u", dirname, uio_num); + break; + } + + /* then try uio:uio%d */ + errno = 0; + uio_num = strtoull(e->d_name + longprefix_len, &endptr, 10); + if (errno == 0 && endptr != (e->d_name + longprefix_len)) { + snprintf(dstbuf, buflen, "%s/uio:uio%u", dirname, + uio_num); + break; + } + } + closedir(dir); + + /* No uio resource found */ + if (e == NULL) + return -1; + + return uio_num; +} + +static void pci_uio_free_context(struct pci_dev_t *dev) +{ + user_access_context_t *ctx = dev->user_access_context; + + if (ctx->uio_cfg_fd >= 0) { + close(ctx->uio_cfg_fd); + } + if (ctx->uio_fd >= 0) { + close(ctx->uio_fd); + } + + dev->user_access_context = NULL; + free(ctx); +} + +static int pci_uio_prepare_context(pci_dev_t *dev) +{ + char dirname[PATH_MAX]; + char cfgname[PATH_MAX]; + int uio_num; + struct pci_addr_t *loc; + user_access_context_t *ctx; + + ctx = malloc(sizeof(user_access_context_t)); + if (ctx == NULL) + return -1; + + memset(ctx, 0, sizeof(user_access_context_t)); + + loc = &dev->addr; + + /* find uio resource */ + uio_num = pci_uio_get_uio_dev(dev, dirname, sizeof(dirname)); + if (uio_num < 0) { + ODP_ERR(" "PCI_PRI_FMT" not managed by UIO driver, " + "skipping\n", loc->domain, loc->bus, loc->devid, + loc->function); + return 1; + } + + ctx->uio_num = uio_num; + snprintf(ctx->path, sizeof(dev->user_access_context->path), + "/dev/uio%u", uio_num); + dev->user_access_context = ctx; + + ctx->uio_fd = open(ctx->path, O_RDWR); + if (ctx->uio_fd < 0) { + ODP_ERR("Cannot open %s: %s\n", ctx->path, strerror(errno)); + goto error; + } + + snprintf(cfgname, sizeof(cfgname), + "/sys/class/uio/uio%u/device/config", uio_num); + ctx->uio_cfg_fd = open(cfgname, O_RDWR); + if (ctx->uio_cfg_fd < 0) { + ODP_ERR("Cannot open %s: %s\n", cfgname, strerror(errno)); + goto error; + } + + /* set bus master that is not done by uio_pci_generic */ + if (pci_uio_set_bus_master(dev)) { + ODP_ERR("Cannot set up bus mastering!\n"); + goto error; + } + + return 0; + +error: + pci_uio_free_context(dev); + return -1; +} + + +static int pci_uio_map_resource_by_index(pci_dev_t *dev, int res_idx, + int map_idx) +{ + int fd; + char devname[PATH_MAX]; + void *mapaddr; + struct pci_addr_t *loc; + user_access_context_t *ctx; + + loc = &dev->addr; + ctx = dev->user_access_context; + + /* update devname for mmap */ + snprintf(devname, sizeof(devname), + "%s/" PCI_PRI_FMT "/resource%d", + pci_get_sysfs_path(), + loc->domain, loc->bus, loc->devid, + loc->function, res_idx); + + /* allocate memory to keep path */ + ctx->maps[map_idx].path = malloc(strlen(devname) + 1); + if (ctx->maps[map_idx].path == NULL) { + ODP_ERR("Cannot allocate memory for path: %s\n", + strerror(errno)); + return -ENOMEM; + } + + /* + * open resource file, to mmap it + */ + fd = open(devname, O_RDWR); + if (fd < 0) { + ODP_ERR("Cannot open %s: %s\n", + devname, strerror(errno)); + goto error; + } + + /* try mapping somewhere close to the end of hugepages */ + //if (pci_map_addr == NULL) pci_map_addr = pci_find_max_end_va(); + + mapaddr = pci_uio_map_resource(pci_map_addr, fd, 0, + (size_t)dev->bar[res_idx].len, 0); + close(fd); + if (mapaddr == MAP_FAILED) + goto error; + + //pci_map_addr = (void*)((uintptr_t)mapaddr + (size_t)dev->bar[res_idx].len); + + ctx->maps[map_idx].phaddr = dev->bar[res_idx].phys_addr; + ctx->maps[map_idx].size = dev->bar[res_idx].len; + ctx->maps[map_idx].addr = mapaddr; + ctx->maps[map_idx].offset = 0; + strcpy(ctx->maps[map_idx].path, devname); + dev->bar[res_idx].addr = mapaddr; + + return 0; + +error: + free(ctx->maps[map_idx].path); + ctx->maps[map_idx].path = NULL; + return -1; +} + + +static int pci_uio_map_resources(pci_dev_t *dev) +{ + int map_idx = 0; + + /* don't call before probing*/ + if (dev->user_access_context == NULL) + return -1; + + /* we've been here before, no need to try again */ + if (dev->user_access_context->nb_maps != 0) + return 0; + + /* Map all BARs */ + for (int i = 0; i != PCI_MAX_RESOURCE; i++) { + uint64_t phaddr = dev->bar[i].phys_addr; + + /* skip empty BAR */ + if (phaddr == 0) + continue; + + if (pci_uio_map_resource_by_index(dev, i, map_idx)) + goto error; + + map_idx++; + } + + dev->user_access_context->nb_maps = map_idx; + + return 0; + +error: +#ifdef ACTIVATED + for (i = 0; i < map_idx; i++) { + pci_unmap_resource(uio_res->maps[i].addr, + (size_t)uio_res->maps[i].size); + rte_free(uio_res->maps[i].path); + } + pci_uio_free_resource(dev, uio_res); + dev->user_access_context->nb_maps = 0; +#endif + return -1; +} + +static int pci_uio_unmap_resources(pci_dev_t *dev) +{ + if (dev == NULL) + return -1; +#ifdef ACTIVATED + /* find an entry for the device */ + uio_res = pci_uio_find_resource(dev); + if (uio_res == NULL) + return; + + /* unmap all resources */ + pci_uio_unmap(uio_res); + + /* free uio resource */ + free(uio_res); + + /* close fd if in primary process */ + if (dev->user_access_context->uio_cfg_fd >= 0) { + close(dev->user_access_context->uio_cfg_fd); + } +#endif + return 0; +} + +static int pci_uio_read_config(pci_dev_t *dev, void *buf, size_t len, + off_t offset) +{ + return pread(dev->user_access_context->uio_cfg_fd, buf, len, offset); +} + +static int pci_uio_write_config(pci_dev_t *dev, void *buf, size_t len, + off_t offset) +{ + return pwrite(dev->user_access_context->uio_cfg_fd, buf, len, offset); +} + +#if !defined(ARM_ARCHITECTURE) +static int pci_uio_ioport_map(pci_dev_t* dev, int idx ODP_UNUSED, + pci_ioport_t *p) +{ + uint16_t start, end; + FILE *fp; + char *line = NULL; + char pci_id[16]; + int found = 0; + size_t linesz; + + snprintf(pci_id, sizeof(pci_id), PCI_PRI_FMT, + dev->addr.domain, dev->addr.bus, + dev->addr.devid, dev->addr.function); + + fp = fopen("/proc/ioports", "r"); + if (fp == NULL) { + ODP_ERR("%s(): can't open ioports\n", __func__); + return -1; + } + + while (getdelim(&line, &linesz, '\n', fp) > 0) { + char *ptr = line; + char *left; + int n; + + n = strcspn(ptr, ":"); + ptr[n] = 0; + left = &ptr[n + 1]; + + while (*left && isspace(*left)) + left++; + + if (!strncmp(left, pci_id, strlen(pci_id))) { + found = 1; + + while (*ptr && isspace(*ptr)) + ptr++; + + sscanf(ptr, "%04hx-%04hx", &start, &end); + + break; + } + } + + free(line); + fclose(fp); + + if (!found) + return -1; + + p->base = start; + ODP_PRINT("PCI Port IO found start=0x%x\n", start); + + return 0; +} +#else +int pci_uio_ioport_map(struct rte_pci_device *dev, int bar, + struct rte_pci_ioport *p) +{ + FILE *f; + char buf[BUFSIZ]; + char filename[PATH_MAX]; + uint64_t phys_addr, end_addr, flags; + int fd, i; + void *addr; + + /* open and read addresses of the corresponding resource in sysfs */ + snprintf(filename, sizeof(filename), "%s/" PCI_PRI_FMT "/resource", + pci_get_sysfs_path(), dev->addr.domain, dev->addr.bus, + dev->addr.devid, dev->addr.function); + f = fopen(filename, "r"); + if (f == NULL) { + RTE_LOG(ERR, EAL, "Cannot open sysfs resource: %s\n", + strerror(errno)); + return -1; + } + for (i = 0; i < bar + 1; i++) { + if (fgets(buf, sizeof(buf), f) == NULL) { + RTE_LOG(ERR, EAL, "Cannot read sysfs resource\n"); + goto error; + } + } + if (pci_parse_one_sysfs_resource(buf, sizeof(buf), &phys_addr, + &end_addr, &flags) < 0) + goto error; + if ((flags & IORESOURCE_IO) == 0) { + RTE_LOG(ERR, EAL, "BAR %d is not an IO resource\n", bar); + goto error; + } + snprintf(filename, sizeof(filename), "%s/" PCI_PRI_FMT "/resource%d", + pci_get_sysfs_path(), dev->addr.domain, dev->addr.bus, + dev->addr.devid, dev->addr.function, bar); + + /* mmap the pci resource */ + fd = open(filename, O_RDWR); + if (fd < 0) { + RTE_LOG(ERR, EAL, "Cannot open %s: %s\n", filename, + strerror(errno)); + goto error; + } + addr = mmap(NULL, end_addr + 1, PROT_READ | PROT_WRITE, + MAP_SHARED, fd, 0); + close(fd); + if (addr == MAP_FAILED) { + RTE_LOG(ERR, EAL, "Cannot mmap IO port resource: %s\n", + strerror(errno)); + goto error; + } + + /* strangely, the base address is mmap addr + phys_addr */ + p->base = (uintptr_t)addr + phys_addr; + p->len = end_addr + 1; + RTE_LOG(DEBUG, EAL, "PCI Port IO found start=0x%"PRIx64"\n", p->base); + fclose(f); + + return 0; + +error: + fclose(f); + return -1; +} +#endif + +static int pci_uio_ioport_unmap(pci_dev_t* dev ODP_UNUSED, pci_ioport_t *p ODP_UNUSED) +{ + int ret = -1; + return ret; +} + + +static void pci_uio_ioport_read(pci_dev_t* dev ODP_UNUSED, pci_ioport_t *p, + void *data, size_t len, off_t offset) +{ + uint8_t *d; + int size; + uintptr_t reg = p->base + offset; + + for (d = data; len > 0; d += size, reg += size, len -= size) { + if (len >= 4) { + size = 4; +#if !defined(ARM_ARCHITECTURE) + *(uint32_t *)d = inl(reg); +#else + *(uint32_t *)d = *(volatile uint32_t *)reg; +#endif + } else if (len >= 2) { + size = 2; +#if !defined(ARM_ARCHITECTURE) + *(uint16_t *)d = inw(reg); +#else + *(uint16_t *)d = *(volatile uint16_t *)reg; +#endif + } else { + size = 1; +#if !defined(ARM_ARCHITECTURE) + *d = inb(reg); +#else + *d = *(volatile uint8_t *)reg; +#endif + } + } +} + +static void pci_uio_ioport_write(pci_dev_t* dev ODP_UNUSED, pci_ioport_t *p, + const void *data, size_t len, off_t offset) +{ + const uint8_t *s; + int size; + uintptr_t reg = p->base + offset; + + for (s = data; len > 0; s += size, reg += size, len -= size) { + if (len >= 4) { + size = 4; +#if !defined(ARM_ARCHITECTURE) + outl_p(*(const uint32_t *)s, reg); +#else + *(volatile uint32_t *)reg = *(const uint32_t *)s; +#endif + } else if (len >= 2) { + size = 2; +#if !defined(ARM_ARCHITECTURE) + outw_p(*(const uint16_t *)s, reg); +#else + *(volatile uint16_t *)reg = *(const uint16_t *)s; +#endif + } else { + size = 1; +#if !defined(ARM_ARCHITECTURE) + outb_p(*s, reg); +#else + *(volatile uint8_t *)reg = *s; +#endif + } + } +} + +static int pci_uio_probe(struct pci_dev_t *dev) +{ + int ret; + + ret = pci_uio_prepare_context(dev); + if (ret) + return ret; + + return 0; +} + +const user_access_ops_t uio_access_ops = { + .probe = pci_uio_probe, + .map_resource = pci_uio_map_resources, + .unmap_resource = pci_uio_unmap_resources, + .read_config = pci_uio_read_config, + .write_config = pci_uio_write_config, + .ioport_map = pci_uio_ioport_map, + .ioport_unmap = pci_uio_ioport_unmap, + .ioport_read = pci_uio_ioport_read, + .ioport_write = pci_uio_ioport_write +}; diff --git a/platform/linux-generic/include/drv_pci_internal.h b/platform/linux-generic/include/drv_pci_internal.h index ec4ec029..b1095c03 100644 --- a/platform/linux-generic/include/drv_pci_internal.h +++ b/platform/linux-generic/include/drv_pci_internal.h @@ -122,6 +122,7 @@ typedef struct pci_dev_t { const char *pci_get_sysfs_path(void);
struct pci_dev_t *pci_open_device(const char *); +int pci_close_device(pci_dev_t *);
#ifdef __cplusplus } diff --git a/platform/linux-generic/pktio/virtio.c b/platform/linux-generic/pktio/virtio.c index 9767c1a2..9b15c2d3 100644 --- a/platform/linux-generic/pktio/virtio.c +++ b/platform/linux-generic/pktio/virtio.c @@ -28,6 +28,9 @@ #define PCI_PKTIO_PREFIX "pci:" #define PCI_PKTIO_PREFIX_LEN (sizeof(PCI_PKTIO_PREFIX) - 1)
+/* FIXME: this should be registered as a DevIO */ +extern const user_access_ops_t uio_access_ops; + static int virtio_init_global(void) { ODP_PRINT("PKTIO: initialized pci interface.\n"); @@ -56,6 +59,23 @@ static int virtio_open(odp_pktio_t id ODP_UNUSED, pktio_entry_t *pktio_entry, return -1; }
+ /* Find suitable DevIO DDF module to work with the driver. */ + if (pci_dev->kdrv == PCI_KDRV_UIO_GENERIC) { + /* probing would be done for each possible DevIO */ + if (uio_access_ops.probe(pci_dev)) { + ODP_ERR("Could not enable DevIO for device %s\n", + devname); + pci_close_device(pci_dev); + return -1; + } + pci_dev->user_access_ops = &uio_access_ops; + } else { + ODP_ERR("Could not find suitable DevIO for device %s\n", + devname); + pci_close_device(pci_dev); + return -1; + } + virtio_entry = odp_ops_data(pktio_entry, virtio); memset(virtio_entry, 0, sizeof(pktio_ops_virtio_data_t)); snprintf(virtio_entry->name, sizeof(virtio_entry->name),
commit b339fbc523120497346298d95c5c1102e70c1826 Author: Josep Puigdemont josep.puigdemont@linaro.org Date: Thu Aug 17 14:40:10 2017 +0200
drv_pci: define methods for PCI device access
Signed-off-by: Josep Puigdemont josep.puigdemont@linaro.org Signed-off-by: François Ozog francois.ozog@linaro.org
diff --git a/platform/linux-generic/include/drv_pci_internal.h b/platform/linux-generic/include/drv_pci_internal.h index 85c3f72e..ec4ec029 100644 --- a/platform/linux-generic/include/drv_pci_internal.h +++ b/platform/linux-generic/include/drv_pci_internal.h @@ -29,6 +29,8 @@ extern "C" { /* name of the shmem area containing the list of enumerated PCI devices: */ #define PCI_ENUMED_DEV "_ODP_PCI_ENUMERATED_DEVICES"
+#define PCI_PRI_FMT "%.4" PRIx16 ":%.2" PRIx8 ":%.2" PRIx8 ".%" PRIx8 + /* structure describing a PCI address: */ typedef struct pci_addr_t { uint16_t domain; /* Device domain */ @@ -63,6 +65,47 @@ enum pci_kernel_driver { PCI_KDRV_NONE, };
+/** + * A structure used to access io resources for a pci device. + * rte_pci_ioport is arch, os, driver specific, and should not be used outside + * of pci ioport api. + */ +typedef struct pci_ioport_t { + struct pci_dev_t *dev; + uint64_t base; + uint64_t len; /* only filled for memory mapped ports */ +} pci_ioport_t; + +/** + * A structure describing a PCI mapping. + */ +struct pci_map { + void *addr; + char *path; + uint64_t offset; + uint64_t size; + uint64_t phaddr; +}; + +/* Opaque type defined by each user access implementation */ +typedef struct user_access_context_t user_access_context; + +typedef struct user_access_ops_t { + int(*probe)(struct pci_dev_t *dev); + int(*map_resource)(struct pci_dev_t *dev); + int(*unmap_resource)(struct pci_dev_t *dev); + int(*read_config)(struct pci_dev_t *dev, void *buf, size_t len, + off_t offset); + int(*write_config)(struct pci_dev_t *dev, void *buf, size_t len, + off_t offset); + int(*ioport_map)(struct pci_dev_t *dev, int idx, pci_ioport_t *p); + int(*ioport_unmap)(struct pci_dev_t *dev, pci_ioport_t *p); + void(*ioport_read)(struct pci_dev_t *dev, pci_ioport_t *p, + void *data, size_t len, off_t offset); + void(*ioport_write)(struct pci_dev_t *dev, pci_ioport_t *p, + const void *data, size_t len, off_t offset); +} user_access_ops_t; + /* structure for PCI device: */ typedef struct pci_dev_t { struct pci_dev_t *next; @@ -71,6 +114,8 @@ typedef struct pci_dev_t { pci_resource_t bar[PCI_MAX_RESOURCE]; /* PCI Resources */ uint16_t max_vfs; /* sriov enable if not zero */ enum pci_kernel_driver kdrv; /* Kernel driver */ + struct user_access_context_t *user_access_context; + const struct user_access_ops_t *user_access_ops; } pci_dev_t;
/* path where PCI devices are shown in sysfs: */
commit 3c372d43de115af127c6fd2d34f365b73b87734b Author: Josep Puigdemont josep.puigdemont@linaro.org Date: Mon Aug 14 15:39:24 2017 +0200
virtio: update pktio structure
Add device id and pci device structure to pktio's.
Signed-off-by: Josep Puigdemont josep.puigdemont@linaro.org
diff --git a/platform/linux-generic/include/odp_pktio_ops_virtio.h b/platform/linux-generic/include/odp_pktio_ops_virtio.h index a8ace414..93e7f000 100644 --- a/platform/linux-generic/include/odp_pktio_ops_virtio.h +++ b/platform/linux-generic/include/odp_pktio_ops_virtio.h @@ -7,7 +7,11 @@ #ifndef ODP_PACKET_VIRTIO_H #define ODP_PACKET_VIRTIO_H
+#include <drv_pci_internal.h> + typedef struct { + struct pci_dev_t *pci_dev; + int dev_id; char name[32]; /**< Unique identifier name */ } pktio_ops_virtio_data_t;
commit 539b29acce1ba915a7c8c65c56a4e5fc9be1ff44 Author: Josep Puigdemont josep.puigdemont@linaro.org Date: Thu Aug 10 16:25:47 2017 +0200
drv_pci.c: scan devices on demand
Only the devices required by PacketIO open are scanned and added to the list of known devices. The pci interface now adds a function to open the device on-demand.
The pci_dump_all() function has been updated to report the current kernel driver and BARs.
Signed-off-by: Josep Puigdemont josep.puigdemont@linaro.org
diff --git a/platform/linux-generic/drv_pci.c b/platform/linux-generic/drv_pci.c index 07b1786b..04a73772 100644 --- a/platform/linux-generic/drv_pci.c +++ b/platform/linux-generic/drv_pci.c @@ -106,6 +106,7 @@ static pci_dev_t *alloc_dev(void) return NULL;
admin_data->d.avail = dev->next; + dev->next = NULL;
return dev; } @@ -143,6 +144,19 @@ do_exit: * in sysfs. */
+#define SYSFS_PCI_DEVICES "/sys/bus/pci/devices" + +const char *pci_get_sysfs_path(void) +{ + const char *path = NULL; + + path = getenv("SYSFS_PCI_DEVICES"); + if (path == NULL) + return SYSFS_PCI_DEVICES; + + return path; +} + /* * parse a sysfs (or other) file containing one integer value * return this positive integer, or -1 on error @@ -366,8 +380,9 @@ error: * the given device (dev) is filled with the data from the sysfs entry. * returns 0 on success, -1 on failure. */ -static int pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus, - uint8_t devid, uint8_t function, pci_dev_t **devlist) +static pci_dev_t *pci_scan_one(const char *dirname, uint16_t domain, + uint8_t bus, uint8_t devid, uint8_t function, + pci_dev_t **devlist) { char filename[PATH_MAX]; unsigned long tmp; @@ -378,7 +393,7 @@ static int pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus,
dev = alloc_dev(); if (dev == NULL) - return -1; + return NULL;
memset(dev, 0, sizeof(*dev)); dev->addr.domain = domain; @@ -390,7 +405,7 @@ static int pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus, snprintf(filename, sizeof(filename), "%s/vendor", dirname); if (pci_parse_sysfs_value(filename, &tmp) < 0) { free_dev(dev); - return -1; + return NULL; } dev->id.vendor_id = (uint16_t)tmp;
@@ -398,7 +413,7 @@ static int pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus, snprintf(filename, sizeof(filename), "%s/device", dirname); if (pci_parse_sysfs_value(filename, &tmp) < 0) { free_dev(dev); - return -1; + return NULL; } dev->id.device_id = (uint16_t)tmp;
@@ -407,7 +422,7 @@ static int pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus, dirname); if (pci_parse_sysfs_value(filename, &tmp) < 0) { free_dev(dev); - return -1; + return NULL; } dev->id.subsystem_vendor_id = (uint16_t)tmp;
@@ -416,7 +431,7 @@ static int pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus, dirname); if (pci_parse_sysfs_value(filename, &tmp) < 0) { free_dev(dev); - return -1; + return NULL; } dev->id.subsystem_device_id = (uint16_t)tmp;
@@ -425,7 +440,7 @@ static int pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus, dirname); if (pci_parse_sysfs_value(filename, &tmp) < 0) { free_dev(dev); - return -1; + return NULL; } /* the least 24 bits are valid: class, subclass, program interface */ dev->id.class_id = (uint32_t)tmp & PCI_CLASS_ANY_ID; @@ -449,7 +464,7 @@ static int pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus, if (pci_parse_sysfs_resource(filename, dev) < 0) { ODP_ERR("cannot parse resource\n"); free_dev(dev); - return -1; + return NULL; }
/* parse driver */ @@ -458,7 +473,7 @@ static int pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus, if (ret < 0) { ODP_ERR("Fail to get kernel driver\n"); free_dev(dev); - return -1; + return NULL; } if (!ret) { if (!strcmp(driver, "vfio-pci")) @@ -477,12 +492,12 @@ static int pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus, if (!(*devlist)) { *devlist = dev; dev->next = NULL; - return 0; + return dev; } if (pci_address_compare(&dev->addr, &(*devlist)->addr) < 0) { dev->next = *devlist; *devlist = dev; - return 0; + return dev; } for (dev2 = *devlist; dev2->next; dev2 = dev2->next) { ret = pci_address_compare(&dev->addr, @@ -499,13 +514,15 @@ static int pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus, memmove(dev2->bar, dev->bar, sizeof(dev->bar)); free_dev(dev); } - return 0; + return dev; } dev2->next = dev; dev->next = NULL; - return 0; + return dev; }
+#if 0 /* FIXME */ + /* * Scan the content of the PCI bus, and fill the PCI enumerated device list */ @@ -517,7 +534,7 @@ static int pci_scan(void) uint16_t domain; uint8_t bus, devid, function;
- dir = opendir(PCI_SYSFS_DEVICES_ROOT); + dir = opendir(pci_get_sysfs_path());
if (dir == NULL) { ODP_DBG("opendir failed: %s\n", strerror(errno)); @@ -542,12 +559,15 @@ static int pci_scan(void) return 0; }
+#endif + /* * output a printout of the scanned PCI devices (debug purpose) */ static int pci_dump_scanned(void) { pci_dev_t *dev; + const char *driver;
if (admin_data == NULL) return -1; @@ -603,12 +623,6 @@ int _odp_pci_init_global(void) if (alloc_admin_data()) return -1;
- /* scan for PCI devices: */ - pci_scan(); - - /* print (debug) the list of scanned devices: */ - pci_dump_scanned(); - ODP_DBG("PCI interface initialized\n");
return 0; @@ -623,20 +637,35 @@ int _odp_pci_term_global(void) return 0; }
-/* returns a device ID, currently only "advisable" as there are not checks - * for duplicates. - * On error it returns a negative number. +/* pci drivers use this function to open a PCI device from the /sys/bus filesystem + * It returns a pci_dev_t struct with several fields filled in. The driver can + * then decide if it can handle the device or not based on device ID. + * On error it returns NULL. */ -int pci_open_device(const char *dev) +pci_dev_t *pci_open_device(const char *dev) { uint16_t domain; uint8_t bus, device, function; - static int id = 0; + char dirname[PATH_MAX]; + pci_dev_t *pci_dev; + + if (admin_data == NULL || admin_data->d.avail == NULL) + return NULL;
if (parse_pci_addr_format(dev, &domain, &bus, &device, &function)) { ODP_ERR("Error in device: %s\n", dev); - return -1; + return NULL; }
- return id++; + snprintf(dirname, sizeof(dirname), "%s/%s", + pci_get_sysfs_path(), dev); + pci_dev = pci_scan_one(dirname, domain, bus, device, function, + &admin_data->d.used); + if (pci_dev == NULL) + return NULL; + + if (pci_dump_scanned()) + ODP_ERR("Could not dump\n"); + + return pci_dev; } diff --git a/platform/linux-generic/include/drv_pci_internal.h b/platform/linux-generic/include/drv_pci_internal.h index 14b4aa63..85c3f72e 100644 --- a/platform/linux-generic/include/drv_pci_internal.h +++ b/platform/linux-generic/include/drv_pci_internal.h @@ -11,9 +11,6 @@ extern "C" { #endif
-/* path where PCI devices are shown in sysfs: */ -#define PCI_SYSFS_DEVICES_ROOT "/sys/bus/pci/devices" - /* Nb. of values in PCI resource file format. */ #define PCI_RESOURCE_FMT_NVAL 3 /** Nb. of values in PCI device address string. */ @@ -76,7 +73,10 @@ typedef struct pci_dev_t { enum pci_kernel_driver kdrv; /* Kernel driver */ } pci_dev_t;
-int pci_open_device(const char *dev); +/* path where PCI devices are shown in sysfs: */ +const char *pci_get_sysfs_path(void); + +struct pci_dev_t *pci_open_device(const char *);
#ifdef __cplusplus } diff --git a/platform/linux-generic/pktio/virtio.c b/platform/linux-generic/pktio/virtio.c index 435569e3..9767c1a2 100644 --- a/platform/linux-generic/pktio/virtio.c +++ b/platform/linux-generic/pktio/virtio.c @@ -40,6 +40,7 @@ static int virtio_open(odp_pktio_t id ODP_UNUSED, pktio_entry_t *pktio_entry, static unsigned int dev_id = 0; pktio_ops_virtio_data_t *virtio_entry; const char *pci_device; + pci_dev_t *pci_dev;
if (strncmp(devname, PCI_PKTIO_PREFIX, PCI_PKTIO_PREFIX_LEN)) return -1; @@ -48,7 +49,8 @@ static int virtio_open(odp_pktio_t id ODP_UNUSED, pktio_entry_t *pktio_entry,
ODP_PRINT("virtio_open: %s\n", pci_device);
- if (pci_open_device(pci_device) < 0) { + pci_dev = pci_open_device(pci_device); + if (pci_dev == NULL) { ODP_ERR("pci: could not open PCI device %s as a VirtIO device\n", pci_device); return -1;
commit 04af087d3523f6db809b979d2a23975de0cc4de8 Author: Josep Puigdemont josep.puigdemont@linaro.org Date: Tue Nov 14 00:35:37 2017 +0100
drv_pci: use preallocated shm
Signed-off-by: Josep Puigdemont josep.puigdemont@linaro.org
diff --git a/platform/linux-generic/drv_pci.c b/platform/linux-generic/drv_pci.c index 26408fca..07b1786b 100644 --- a/platform/linux-generic/drv_pci.c +++ b/platform/linux-generic/drv_pci.c @@ -29,6 +29,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <inttypes.h> #include <dirent.h> #include <linux/limits.h> #include <unistd.h> @@ -39,11 +40,103 @@ #include <odp_posix_extensions.h> #include <odp_config_internal.h> #include <odp_internal.h> -#include <odp/drv/shm.h> +#include <odp/api/shared_memory.h> #include <odp_debug_internal.h> +#include <odp_align_internal.h>
#include <drv_pci_internal.h>
+#define MAX_PCI_DEVICES 16 + +typedef union { + pci_dev_t d; + uint8_t pad[ROUNDUP_CACHE_LINE(sizeof(pci_dev_t))]; +} pci_dev_item_t; + +typedef struct pci_admin_data { + pci_dev_t *avail; + pci_dev_t *used; + odp_shm_t shm; +} pci_admin_data_t; + +typedef union { + struct pci_admin_data d; + uint8_t pad[ROUNDUP_CACHE_LINE(sizeof(struct pci_admin_data))]; +} pci_admin_data_u; + +static pci_admin_data_u *admin_data; + +static int alloc_admin_data(void) +{ + uint64_t size; + pci_dev_item_t *item; + odp_shm_t shm; + + size = sizeof(pci_admin_data_u) + + sizeof(pci_dev_item_t) * MAX_PCI_DEVICES; + + shm = odp_shm_reserve(PCI_ENUMED_DEV, size, 0, ODP_SHM_SINGLE_VA); + if (shm == ODP_SHM_INVALID) + return -1; + + admin_data = odp_shm_addr(shm); + if (!admin_data) + return -1; + + item = (pci_dev_item_t *)((uint8_t *)admin_data + + sizeof(pci_admin_data_u)); + admin_data->d.avail = (pci_dev_t *)item; + admin_data->d.used = NULL; + admin_data->d.shm = shm; + + for (int i = 0; i < MAX_PCI_DEVICES - 1; ++i) + item[i].d.next = (pci_dev_t *)&item[i + 1]; + + item[MAX_PCI_DEVICES - 1].d.next = NULL; + + return 0; +} + +static pci_dev_t *alloc_dev(void) +{ + pci_dev_t *dev; + + dev = admin_data->d.avail; + if (admin_data->d.avail == NULL) + return NULL; + + admin_data->d.avail = dev->next; + + return dev; +} + +static void free_dev(pci_dev_t *dev) +{ + if (dev == NULL) + return; + + if (admin_data->d.used == NULL) + goto do_exit; + + if (dev == admin_data->d.used) { + admin_data->d.used = dev->next; + } else { + pci_dev_t *prev = admin_data->d.used; + pci_dev_t *curr = prev->next; + + while (curr != NULL && curr != dev) { + curr = curr->next; + prev = prev->next; + } + if (curr == dev) + prev->next = curr->next; + } + +do_exit: + dev->next = admin_data->d.avail; + admin_data->d.avail = dev; +} + /* * PCI probing: * these functions are used to simulate a PCI probe by parsing information @@ -283,7 +376,7 @@ static int pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus, pci_dev_t *dev; pci_dev_t *dev2;
- dev = malloc(sizeof(*dev)); + dev = alloc_dev(); if (dev == NULL) return -1;
@@ -296,7 +389,7 @@ static int pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus, /* get vendor id */ snprintf(filename, sizeof(filename), "%s/vendor", dirname); if (pci_parse_sysfs_value(filename, &tmp) < 0) { - free(dev); + free_dev(dev); return -1; } dev->id.vendor_id = (uint16_t)tmp; @@ -304,7 +397,7 @@ static int pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus, /* get device id */ snprintf(filename, sizeof(filename), "%s/device", dirname); if (pci_parse_sysfs_value(filename, &tmp) < 0) { - free(dev); + free_dev(dev); return -1; } dev->id.device_id = (uint16_t)tmp; @@ -313,7 +406,7 @@ static int pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus, snprintf(filename, sizeof(filename), "%s/subsystem_vendor", dirname); if (pci_parse_sysfs_value(filename, &tmp) < 0) { - free(dev); + free_dev(dev); return -1; } dev->id.subsystem_vendor_id = (uint16_t)tmp; @@ -322,7 +415,7 @@ static int pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus, snprintf(filename, sizeof(filename), "%s/subsystem_device", dirname); if (pci_parse_sysfs_value(filename, &tmp) < 0) { - free(dev); + free_dev(dev); return -1; } dev->id.subsystem_device_id = (uint16_t)tmp; @@ -331,7 +424,7 @@ static int pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus, snprintf(filename, sizeof(filename), "%s/class", dirname); if (pci_parse_sysfs_value(filename, &tmp) < 0) { - free(dev); + free_dev(dev); return -1; } /* the least 24 bits are valid: class, subclass, program interface */ @@ -355,7 +448,7 @@ static int pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus, snprintf(filename, sizeof(filename), "%s/resource", dirname); if (pci_parse_sysfs_resource(filename, dev) < 0) { ODP_ERR("cannot parse resource\n"); - free(dev); + free_dev(dev); return -1; }
@@ -364,7 +457,7 @@ static int pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus, ret = pci_get_kernel_driver_by_path(filename, driver); if (ret < 0) { ODP_ERR("Fail to get kernel driver\n"); - free(dev); + free_dev(dev); return -1; } if (!ret) { @@ -404,7 +497,7 @@ static int pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus, dev2->kdrv = dev->kdrv; dev2->max_vfs = dev->max_vfs; memmove(dev2->bar, dev->bar, sizeof(dev->bar)); - free(dev); + free_dev(dev); } return 0; } @@ -422,15 +515,7 @@ static int pci_scan(void) DIR *dir; char dirname[PATH_MAX]; uint16_t domain; - uint16_t devcount = 0; uint8_t bus, devid, function; - pci_dev_t *dev; - pci_dev_t *dev2; - pci_dev_t *devlist = NULL; /* temporary malloc'd list head */ - pci_dev_t *pci_enumerated_dev; /* final list head */ - int size; - int index; - odpdrv_shm_t shm;
dir = opendir(PCI_SYSFS_DEVICES_ROOT);
@@ -449,61 +534,12 @@ static int pci_scan(void)
snprintf(dirname, sizeof(dirname), "%s/%s", PCI_SYSFS_DEVICES_ROOT, e->d_name); - if (pci_scan_one(dirname, domain, bus, devid, function, - &devlist) < 0) - goto error; - devcount++; + pci_scan_one(dirname, domain, bus, devid, function, + &(admin_data->d.used)); } closedir(dir);
- /* - * At this point devlist is the malloc'd ordered PCI device list: - * We can now allocate the final list, as we now know the needed - * size, and copy the scanned devices in it, as none of them are - * referenced by pointers at this stage. - * The allocated memory is allocated as shared and SINGLE_VA'd so - * that any odp thread (i.e. pthread or process) can refer pci - * dev as pointers - */ - size = sizeof(pci_dev_t) * devcount; - shm = odpdrv_shm_reserve(PCI_ENUMED_DEV, size, 0, ODPDRV_SHM_SINGLE_VA); - if (shm == ODPDRV_SHM_INVALID) - goto error; - - pci_enumerated_dev = odpdrv_shm_addr(shm); - - for (index = 0, dev = devlist; dev != NULL; dev = dev->next, index++) { - memcpy(&pci_enumerated_dev[index], - dev, - sizeof(pci_dev_t)); - pci_enumerated_dev[index].next = &pci_enumerated_dev[index + 1]; - } - pci_enumerated_dev[index - 1].next = NULL; - - if (index != devcount) - ODP_ERR("pci enumeration error (bug!)\n"); - - /* free the malloc'd list: */ - dev = devlist; - while (dev != NULL) { - dev2 = dev->next; - free(dev); - dev = dev2; - } - return 0; - -error: - closedir(dir); - - /* free the malloc'd list: */ - dev = devlist; - while (dev != NULL) { - dev2 = dev->next; - free(dev); - dev = dev2; - } - return -1; }
/* @@ -511,40 +547,62 @@ error: */ static int pci_dump_scanned(void) { - odpdrv_shm_t shm; pci_dev_t *dev; - pci_dev_t *devlist;
- shm = odpdrv_shm_lookup_by_name(PCI_ENUMED_DEV); - if (shm == ODPDRV_SHM_INVALID) - return -1; - - devlist = odpdrv_shm_addr(shm); - if (!devlist) + if (admin_data == NULL) return -1;
ODP_DBG("list of scanned PCI devices:\n"); - for (dev = devlist; dev != NULL; dev = dev->next) - ODP_DBG("%04" PRIx16 ":" - "%02" PRIx8 ":" - "%02" PRIx8 ":" - "%02" PRIx8 ": " - "vendor:%04" PRIx16 ", " - "device:%04" PRIx16 ", " - "class:%04" PRIx16 "\n", - dev->addr.domain, - dev->addr.bus, - dev->addr.devid, - dev->addr.function, - dev->id.vendor_id, - dev->id.device_id, - dev->id.class_id); + for (dev = admin_data->d.used; dev != NULL; dev = dev->next) { + switch (dev->kdrv) { + case PCI_KDRV_VFIO: + driver = "vfio"; + break; + case PCI_KDRV_IGB_UIO: + driver = "igb_uio"; + break; + case PCI_KDRV_UIO_GENERIC: + driver = "uio_pci_generic"; + break; + default: + driver = "unknown"; + } + ODP_PRINT("PCI DEVICE:" + "%04" PRIx16 ":" + "%02" PRIx8 ":" + "%02" PRIx8 ":" + "%02" PRIx8 ": " + "vendor:%04" PRIx16 ", " + "device:%04" PRIx16 ", " + "class:%04" PRIx16 ", " + "driver: %s\n", + dev->addr.domain, + dev->addr.bus, + dev->addr.devid, + dev->addr.function, + dev->id.vendor_id, + dev->id.device_id, + dev->id.class_id, + driver); + for (int i = 0; i < PCI_MAX_RESOURCE; i++) { + if (dev->bar[i].phys_addr == 0) + continue; + ODP_PRINT("\tBAR_%d: phys_addr: %" PRIx64 " -> " + "%p, %" PRIx64 " bytes\n", + i, dev->bar[i].phys_addr, + dev->bar[i].addr, + dev->bar[i].len); + } + }
return 0; }
int _odp_pci_init_global(void) { + if (alloc_admin_data()) + return -1; + /* scan for PCI devices: */ pci_scan();
@@ -559,7 +617,8 @@ int _odp_pci_init_global(void) int _odp_pci_term_global(void) { /* free the enumarated PCI device list (if any) */ - odpdrv_shm_free_by_name(PCI_ENUMED_DEV); + if (admin_data) + odp_shm_free(admin_data->d.shm);
return 0; }
commit 77f6dd878c4095e9cbb7c9237a0564c62ebc92c3 Author: Josep Puigdemont josep.puigdemont@linaro.org Date: Wed Aug 9 17:18:33 2017 +0200
virtio/pci: create device on demand
Signed-off-by: Josep Puigdemont josep.puigdemont@linaro.org
diff --git a/platform/linux-generic/drv_pci.c b/platform/linux-generic/drv_pci.c index 6b74a0a6..26408fca 100644 --- a/platform/linux-generic/drv_pci.c +++ b/platform/linux-generic/drv_pci.c @@ -507,7 +507,7 @@ error: }
/* - *output a printout of the scanned PCI devices (debug purpose) + * output a printout of the scanned PCI devices (debug purpose) */ static int pci_dump_scanned(void) { @@ -551,6 +551,8 @@ int _odp_pci_init_global(void) /* print (debug) the list of scanned devices: */ pci_dump_scanned();
+ ODP_DBG("PCI interface initialized\n"); + return 0; }
@@ -561,3 +563,21 @@ int _odp_pci_term_global(void)
return 0; } + +/* returns a device ID, currently only "advisable" as there are not checks + * for duplicates. + * On error it returns a negative number. + */ +int pci_open_device(const char *dev) +{ + uint16_t domain; + uint8_t bus, device, function; + static int id = 0; + + if (parse_pci_addr_format(dev, &domain, &bus, &device, &function)) { + ODP_ERR("Error in device: %s\n", dev); + return -1; + } + + return id++; +} diff --git a/platform/linux-generic/include/drv_pci_internal.h b/platform/linux-generic/include/drv_pci_internal.h index 24be1e29..14b4aa63 100644 --- a/platform/linux-generic/include/drv_pci_internal.h +++ b/platform/linux-generic/include/drv_pci_internal.h @@ -76,6 +76,8 @@ typedef struct pci_dev_t { enum pci_kernel_driver kdrv; /* Kernel driver */ } pci_dev_t;
+int pci_open_device(const char *dev); + #ifdef __cplusplus } #endif diff --git a/platform/linux-generic/pktio/virtio.c b/platform/linux-generic/pktio/virtio.c index b46a642a..435569e3 100644 --- a/platform/linux-generic/pktio/virtio.c +++ b/platform/linux-generic/pktio/virtio.c @@ -22,6 +22,7 @@ #include <odp_debug_internal.h> #include <odp/api/hints.h>
+#include <drv_pci_internal.h> #include <odp_pktio_ops_virtio.h>
#define PCI_PKTIO_PREFIX "pci:" @@ -34,20 +35,29 @@ static int virtio_init_global(void) }
static int virtio_open(odp_pktio_t id ODP_UNUSED, pktio_entry_t *pktio_entry, - const char *devname, odp_pool_t pool ODP_UNUSED) + const char *devname, odp_pool_t pool ODP_UNUSED) { static unsigned int dev_id = 0; - pktio_ops_virtio_data_t *virtio_entry = odp_ops_data(pktio_entry, - virtio); + pktio_ops_virtio_data_t *virtio_entry; + const char *pci_device;
if (strncmp(devname, PCI_PKTIO_PREFIX, PCI_PKTIO_PREFIX_LEN)) return -1;
+ pci_device = devname + PCI_PKTIO_PREFIX_LEN; + + ODP_PRINT("virtio_open: %s\n", pci_device); + + if (pci_open_device(pci_device) < 0) { + ODP_ERR("pci: could not open PCI device %s as a VirtIO device\n", + pci_device); + return -1; + } + + virtio_entry = odp_ops_data(pktio_entry, virtio); memset(virtio_entry, 0, sizeof(pktio_ops_virtio_data_t)); - snprintf(virtio_entry->name, - sizeof(virtio_entry->name), - "virtio_%u", - dev_id++); + snprintf(virtio_entry->name, sizeof(virtio_entry->name), + "virtio_%u", dev_id++);
ODP_PRINT("virtio: opened %s\n", virtio_entry->name);
@@ -60,13 +70,13 @@ static int virtio_close(pktio_entry_t *pktio_entry ODP_UNUSED) }
static int virtio_recv(pktio_entry_t *pktio_entry ODP_UNUSED, int index ODP_UNUSED, - odp_packet_t pkts[] ODP_UNUSED, int len ODP_UNUSED) + odp_packet_t pkts[] ODP_UNUSED, int len ODP_UNUSED) { return 0; }
static int virtio_send(pktio_entry_t *pktio_entry ODP_UNUSED, int index ODP_UNUSED, - const odp_packet_t pkt_tbl[] ODP_UNUSED, int len) + const odp_packet_t pkt_tbl[] ODP_UNUSED, int len) { return len; }
commit 606b19d60c015a6ac14ef83146ca1019530de4a0 Author: Christophe Milard christophe.milard@linaro.org Date: Wed Sep 14 13:55:43 2016 +0200
drv_pci: PCI scanning and parsing functions
Utility functions for scanning the PCI bus, parsing BFD strings and other useful functionality.
Signed-off-by: Christophe Milard christophe.milard@linaro.org
diff --git a/platform/linux-generic/Makefile.am b/platform/linux-generic/Makefile.am index 4dbdb813..11b03b60 100644 --- a/platform/linux-generic/Makefile.am +++ b/platform/linux-generic/Makefile.am @@ -155,6 +155,7 @@ noinst_HEADERS = \ include/_ishmpool_internal.h \ include/_str_functions_internal.h \ include/drv_driver_internal.h \ + include/drv_pci_internal.h \ include/odp_align_internal.h \ include/odp_atomic_internal.h \ include/odp_buffer_inlines.h \ @@ -288,6 +289,7 @@ __LIB__libodp_linux_la_SOURCES = \ drv_atomic.c \ drv_barrier.c \ drv_driver.c \ + drv_pci.c \ drv_shm.c \ drv_spinlock.c
diff --git a/platform/linux-generic/drv_pci.c b/platform/linux-generic/drv_pci.c new file mode 100644 index 00000000..6b74a0a6 --- /dev/null +++ b/platform/linux-generic/drv_pci.c @@ -0,0 +1,563 @@ +/* Copyright (c) 2016, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* Many of this functions have been inspired by their dpdk counterpart, + * hence the following license: + */ + +/* + * BSD LICENSE + * + * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. + * All rights reserved. + */ + +/** + * @file + * PCI interface for drivers + */ + +#ifndef _DEFAULT_SOURCE +#define _DEFAULT_SOURCE +#endif + +#include <sys/types.h> +#include <sys/stat.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <dirent.h> +#include <linux/limits.h> +#include <unistd.h> +#include <errno.h> + +#include <config.h> +#include <_str_functions_internal.h> +#include <odp_posix_extensions.h> +#include <odp_config_internal.h> +#include <odp_internal.h> +#include <odp/drv/shm.h> +#include <odp_debug_internal.h> + +#include <drv_pci_internal.h> + +/* + * PCI probing: + * these functions are used to simulate a PCI probe by parsing information + * in sysfs. + */ + +/* + * parse a sysfs (or other) file containing one integer value + * return this positive integer, or -1 on error + */ +static int pci_parse_sysfs_value(const char *filename, unsigned long *val) +{ + FILE *f; + char buf[BUFSIZ]; + char *end = NULL; + + f = fopen(filename, "r"); + if (f == NULL) { + ODP_ERR("cannot open sysfs file %s\n", filename); + return -1; + } + + if (fgets(buf, sizeof(buf), f) == NULL) { + ODP_ERR("cannot read sysfs file %s\n", filename); + fclose(f); + return -1; + } + *val = strtoul(buf, &end, 0); + if ((buf[0] == '\0') || (end == NULL) || (*end != '\n')) { + ODP_ERR("cannot parse sysfs value %s\n", filename); + fclose(f); + return -1; + } + fclose(f); + return 0; +} + +/* + * given a path (filename) such as "/sys/bus/pci/devices/0000:23:00.0/driver", + * returns the driver name (a string) in dri_name. + * The returned name is simply what the "driver" links points to. + * returns 0 on success, -1 on failure. + */ +static int pci_get_kernel_driver_by_path(const char *filename, char *dri_name) +{ + char path[PATH_MAX]; + char *name; + + if (!filename || !dri_name) + return -1; + + if (realpath(filename, path) == NULL) + return -1; + + name = strrchr(path, '/'); + if (name) { + strncpy(dri_name, name + 1, strlen(name + 1) + 1); + return 0; + } + + return -1; +} + +/* + * parse one line of the "resource" sysfs file (note that the 'line' + * string is modified) + * Sets phys_addr, end_addr, and flags as read from the given line. + * returns 0 on success, -1 on failure. + */ +static int pci_parse_one_sysfs_resource(char *line, size_t len, + uint64_t *phys_addr, + uint64_t *end_addr, uint64_t *flags) +{ + union pci_resource_info { + struct { + char *phys_addr; + char *end_addr; + char *flags; + }; + char *ptrs[PCI_RESOURCE_FMT_NVAL]; + } res_info; + + if (_odp_strsplit(line, len, res_info.ptrs, 3, ' ') != 3) { + ODP_ERR("bad PCI resource format!\n"); + return -1; + } + errno = 0; + *phys_addr = strtoull(res_info.phys_addr, NULL, 16); + *end_addr = strtoull(res_info.end_addr, NULL, 16); + *flags = strtoull(res_info.flags, NULL, 16); + if (errno != 0) { + ODP_ERR("bad PCI resource format!\n"); + return -1; + } + + return 0; +} + +/* + * parse the "resource" sysfs file + * filename is expected to be something like: + * /sys/bus/pci/devices/0000:23:00.0/resource + * returns 0 on success, -1 on failure. + */ +static int pci_parse_sysfs_resource(const char *filename, pci_dev_t *dev) +{ + FILE *f; + char buf[BUFSIZ]; + int i; + uint64_t phys_addr, end_addr, flags; + + f = fopen(filename, "r"); + if (f == NULL) { + ODP_ERR("Cannot open sysfs resource!\n"); + return -1; + } + + for (i = 0; i < PCI_MAX_RESOURCE; i++) { + if (fgets(buf, sizeof(buf), f) == NULL) { + ODP_ERR("cannot read resource\n"); + goto error; + } + if (pci_parse_one_sysfs_resource(buf, sizeof(buf), &phys_addr, + &end_addr, &flags) < 0) + goto error; + + if (flags & IORESOURCE_MEM) { + dev->bar[i].phys_addr = phys_addr; + dev->bar[i].len = end_addr - phys_addr + 1; + /* not mapped for now */ + dev->bar[i].addr = NULL; + } + } + fclose(f); + return 0; + +error: + fclose(f); + return -1; +} + +/* + * compare two PCI device addresses. + * Returns: + * 0 on equal PCI address. + * Positive on addr is greater than addr2. + * Negative on addr is less than addr2, or error. + */ +static inline int pci_address_compare(const struct pci_addr_t *addr, + const struct pci_addr_t *addr2) +{ + uint64_t dev_addr, dev_addr2; + + if ((addr == NULL) || (addr2 == NULL)) + return -1; + + dev_addr = (addr->domain << 24) | (addr->bus << 16) | + (addr->devid << 8) | addr->function; + dev_addr2 = (addr2->domain << 24) | (addr2->bus << 16) | + (addr2->devid << 8) | addr2->function; + + if (dev_addr > dev_addr2) + return 1; + else if (dev_addr < dev_addr2) + return -1; + else + return 0; +} + +/* + * split up a pci address into its constituent parts. + */ +static int parse_pci_addr_format(const char *buf, uint16_t *domain, + uint8_t *bus, uint8_t *devid, + uint8_t *function) +{ + int bufsize; + char *buf_copy; + union splitaddr { + struct { + char *domain; + char *bus; + char *devid; + char *function; + }; + char *str[PCI_FMT_NVAL]; /* last separator is "." not ":" */ + } splitaddr; + + /* copy original address to avoid damaging it with _odp_strsplit: */ + bufsize = strlen(buf) + 1; + buf_copy = malloc(bufsize); + strcpy(buf_copy, buf); + + if (buf_copy == NULL) + return -1; + + /* first split on ':' */ + if (_odp_strsplit(buf_copy, bufsize, splitaddr.str, PCI_FMT_NVAL, ':') + != PCI_FMT_NVAL - 1) + goto error; + /* final split is on '.' between devid and function */ + splitaddr.function = strchr(splitaddr.devid, '.'); + if (splitaddr.function == NULL) + goto error; + *splitaddr.function++ = '\0'; + + /* now convert to int values */ + errno = 0; + *domain = (uint16_t)strtoul(splitaddr.domain, NULL, 16); + *bus = (uint8_t)strtoul(splitaddr.bus, NULL, 16); + *devid = (uint8_t)strtoul(splitaddr.devid, NULL, 16); + *function = (uint8_t)strtoul(splitaddr.function, NULL, 10); + if (errno != 0) + goto error; + + free(buf_copy); /* free the copy made with strdup */ + return 0; +error: + free(buf_copy); + return -1; +} + +/* + * Scan one pci sysfs entry, and fill the device list from it. + * dirname should point to a sysfs pci dev entry, e.g. + * /sys/bus/pci/devices/0000:23:00.0 + * the given device (dev) is filled with the data from the sysfs entry. + * returns 0 on success, -1 on failure. + */ +static int pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus, + uint8_t devid, uint8_t function, pci_dev_t **devlist) +{ + char filename[PATH_MAX]; + unsigned long tmp; + char driver[PATH_MAX]; + int ret; + pci_dev_t *dev; + pci_dev_t *dev2; + + dev = malloc(sizeof(*dev)); + if (dev == NULL) + return -1; + + memset(dev, 0, sizeof(*dev)); + dev->addr.domain = domain; + dev->addr.bus = bus; + dev->addr.devid = devid; + dev->addr.function = function; + + /* get vendor id */ + snprintf(filename, sizeof(filename), "%s/vendor", dirname); + if (pci_parse_sysfs_value(filename, &tmp) < 0) { + free(dev); + return -1; + } + dev->id.vendor_id = (uint16_t)tmp; + + /* get device id */ + snprintf(filename, sizeof(filename), "%s/device", dirname); + if (pci_parse_sysfs_value(filename, &tmp) < 0) { + free(dev); + return -1; + } + dev->id.device_id = (uint16_t)tmp; + + /* get subsystem_vendor id */ + snprintf(filename, sizeof(filename), "%s/subsystem_vendor", + dirname); + if (pci_parse_sysfs_value(filename, &tmp) < 0) { + free(dev); + return -1; + } + dev->id.subsystem_vendor_id = (uint16_t)tmp; + + /* get subsystem_device id */ + snprintf(filename, sizeof(filename), "%s/subsystem_device", + dirname); + if (pci_parse_sysfs_value(filename, &tmp) < 0) { + free(dev); + return -1; + } + dev->id.subsystem_device_id = (uint16_t)tmp; + + /* get class_id */ + snprintf(filename, sizeof(filename), "%s/class", + dirname); + if (pci_parse_sysfs_value(filename, &tmp) < 0) { + free(dev); + return -1; + } + /* the least 24 bits are valid: class, subclass, program interface */ + dev->id.class_id = (uint32_t)tmp & PCI_CLASS_ANY_ID; + + /* get max_vfs */ + dev->max_vfs = 0; + snprintf(filename, sizeof(filename), "%s/max_vfs", dirname); + if (!access(filename, F_OK) && + pci_parse_sysfs_value(filename, &tmp) == 0) + dev->max_vfs = (uint16_t)tmp; + else { + snprintf(filename, sizeof(filename), + "%s/sriov_numvfs", dirname); + if (!access(filename, F_OK) && + pci_parse_sysfs_value(filename, &tmp) == 0) + dev->max_vfs = (uint16_t)tmp; + } + + /* parse resources */ + snprintf(filename, sizeof(filename), "%s/resource", dirname); + if (pci_parse_sysfs_resource(filename, dev) < 0) { + ODP_ERR("cannot parse resource\n"); + free(dev); + return -1; + } + + /* parse driver */ + snprintf(filename, sizeof(filename), "%s/driver", dirname); + ret = pci_get_kernel_driver_by_path(filename, driver); + if (ret < 0) { + ODP_ERR("Fail to get kernel driver\n"); + free(dev); + return -1; + } + if (!ret) { + if (!strcmp(driver, "vfio-pci")) + dev->kdrv = PCI_KDRV_VFIO; + else if (!strcmp(driver, "igb_uio")) + dev->kdrv = PCI_KDRV_IGB_UIO; + else if (!strcmp(driver, "uio_pci_generic")) + dev->kdrv = PCI_KDRV_UIO_GENERIC; + else + dev->kdrv = PCI_KDRV_UNKNOWN; + } else { + dev->kdrv = PCI_KDRV_NONE; + } + + /* device is valid, add in list (sorted): */ + if (!(*devlist)) { + *devlist = dev; + dev->next = NULL; + return 0; + } + if (pci_address_compare(&dev->addr, &(*devlist)->addr) < 0) { + dev->next = *devlist; + *devlist = dev; + return 0; + } + for (dev2 = *devlist; dev2->next; dev2 = dev2->next) { + ret = pci_address_compare(&dev->addr, + &dev2->next->addr); + if (ret > 0) + continue; + + if (ret < 0) { + dev->next = dev2->next; + dev2->next = dev; + } else { /* already registered */ + dev2->kdrv = dev->kdrv; + dev2->max_vfs = dev->max_vfs; + memmove(dev2->bar, dev->bar, sizeof(dev->bar)); + free(dev); + } + return 0; + } + dev2->next = dev; + dev->next = NULL; + return 0; +} + +/* + * Scan the content of the PCI bus, and fill the PCI enumerated device list + */ +static int pci_scan(void) +{ + struct dirent *e; + DIR *dir; + char dirname[PATH_MAX]; + uint16_t domain; + uint16_t devcount = 0; + uint8_t bus, devid, function; + pci_dev_t *dev; + pci_dev_t *dev2; + pci_dev_t *devlist = NULL; /* temporary malloc'd list head */ + pci_dev_t *pci_enumerated_dev; /* final list head */ + int size; + int index; + odpdrv_shm_t shm; + + dir = opendir(PCI_SYSFS_DEVICES_ROOT); + + if (dir == NULL) { + ODP_DBG("opendir failed: %s\n", strerror(errno)); + return -1; + } + + while ((e = readdir(dir)) != NULL) { + if (e->d_name[0] == '.') + continue; + + if (parse_pci_addr_format(e->d_name, &domain, + &bus, &devid, &function) != 0) + continue; + + snprintf(dirname, sizeof(dirname), "%s/%s", + PCI_SYSFS_DEVICES_ROOT, e->d_name); + if (pci_scan_one(dirname, domain, bus, devid, function, + &devlist) < 0) + goto error; + devcount++; + } + closedir(dir); + + /* + * At this point devlist is the malloc'd ordered PCI device list: + * We can now allocate the final list, as we now know the needed + * size, and copy the scanned devices in it, as none of them are + * referenced by pointers at this stage. + * The allocated memory is allocated as shared and SINGLE_VA'd so + * that any odp thread (i.e. pthread or process) can refer pci + * dev as pointers + */ + size = sizeof(pci_dev_t) * devcount; + shm = odpdrv_shm_reserve(PCI_ENUMED_DEV, size, 0, ODPDRV_SHM_SINGLE_VA); + if (shm == ODPDRV_SHM_INVALID) + goto error; + + pci_enumerated_dev = odpdrv_shm_addr(shm); + + for (index = 0, dev = devlist; dev != NULL; dev = dev->next, index++) { + memcpy(&pci_enumerated_dev[index], + dev, + sizeof(pci_dev_t)); + pci_enumerated_dev[index].next = &pci_enumerated_dev[index + 1]; + } + pci_enumerated_dev[index - 1].next = NULL; + + if (index != devcount) + ODP_ERR("pci enumeration error (bug!)\n"); + + /* free the malloc'd list: */ + dev = devlist; + while (dev != NULL) { + dev2 = dev->next; + free(dev); + dev = dev2; + } + + return 0; + +error: + closedir(dir); + + /* free the malloc'd list: */ + dev = devlist; + while (dev != NULL) { + dev2 = dev->next; + free(dev); + dev = dev2; + } + return -1; +} + +/* + *output a printout of the scanned PCI devices (debug purpose) + */ +static int pci_dump_scanned(void) +{ + odpdrv_shm_t shm; + pci_dev_t *dev; + pci_dev_t *devlist; + + shm = odpdrv_shm_lookup_by_name(PCI_ENUMED_DEV); + if (shm == ODPDRV_SHM_INVALID) + return -1; + + devlist = odpdrv_shm_addr(shm); + if (!devlist) + return -1; + + ODP_DBG("list of scanned PCI devices:\n"); + for (dev = devlist; dev != NULL; dev = dev->next) + ODP_DBG("%04" PRIx16 ":" + "%02" PRIx8 ":" + "%02" PRIx8 ":" + "%02" PRIx8 ": " + "vendor:%04" PRIx16 ", " + "device:%04" PRIx16 ", " + "class:%04" PRIx16 "\n", + dev->addr.domain, + dev->addr.bus, + dev->addr.devid, + dev->addr.function, + dev->id.vendor_id, + dev->id.device_id, + dev->id.class_id); + + return 0; +} + +int _odp_pci_init_global(void) +{ + /* scan for PCI devices: */ + pci_scan(); + + /* print (debug) the list of scanned devices: */ + pci_dump_scanned(); + + return 0; +} + +int _odp_pci_term_global(void) +{ + /* free the enumarated PCI device list (if any) */ + odpdrv_shm_free_by_name(PCI_ENUMED_DEV); + + return 0; +} diff --git a/platform/linux-generic/include/drv_pci_internal.h b/platform/linux-generic/include/drv_pci_internal.h new file mode 100644 index 00000000..24be1e29 --- /dev/null +++ b/platform/linux-generic/include/drv_pci_internal.h @@ -0,0 +1,83 @@ +/* Copyright (c) 2016, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DRV_PCI_INTERNAL_H_ +#define DRV_PCI_INTERNAL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* path where PCI devices are shown in sysfs: */ +#define PCI_SYSFS_DEVICES_ROOT "/sys/bus/pci/devices" + +/* Nb. of values in PCI resource file format. */ +#define PCI_RESOURCE_FMT_NVAL 3 +/** Nb. of values in PCI device address string. */ +#define PCI_FMT_NVAL 4 + +/* Maximum number of PCI resources (BAR regions). */ +#define PCI_MAX_RESOURCE 6 + +/* IO resource type (flag section of PCI resource file): */ +#define IORESOURCE_IO 0x00000100 +#define IORESOURCE_MEM 0x00000200 + +/* Any PCI device identifier (vendor, device, ...) */ +#define PCI_CLASS_ANY_ID (0xffffff) + +/* name of the shmem area containing the list of enumerated PCI devices: */ +#define PCI_ENUMED_DEV "_ODP_PCI_ENUMERATED_DEVICES" + +/* structure describing a PCI address: */ +typedef struct pci_addr_t { + uint16_t domain; /* Device domain */ + uint8_t bus; /* Device bus */ + uint8_t devid; /* Device ID */ + uint8_t function; /* Device function. */ +} pci_addr_t; + +/* structure describing an ID for a PCI device: */ +typedef struct pci_id_t { + uint32_t class_id; /* Class ID */ + uint16_t vendor_id; /* Vendor ID or PCI_ANY_ID. */ + uint16_t device_id; /* Device ID or PCI_ANY_ID. */ + uint16_t subsystem_vendor_id; /* Subsystem vendor ID or PCI_ANY_ID. */ + uint16_t subsystem_device_id; /* Subsystem device ID or PCI_ANY_ID. */ +} pci_id_t; + +/* structure describing a PCI resource (BAR region): */ +typedef struct pci_resource_t { + uint64_t phys_addr;/* Physical address, 0 if no resource. */ + void *addr; /* address (virtual, user space) of the BAR region */ + uint64_t len; /* size of the region, in bytes */ +} pci_resource_t; + +/* enum telling which kernel driver is currentely bound to the pci device: */ +enum pci_kernel_driver { + PCI_KDRV_UNKNOWN = 0, + PCI_KDRV_IGB_UIO, + PCI_KDRV_VFIO, + PCI_KDRV_UIO_GENERIC, + PCI_KDRV_NIC_UIO, + PCI_KDRV_NONE, +}; + +/* structure for PCI device: */ +typedef struct pci_dev_t { + struct pci_dev_t *next; + pci_addr_t addr; /* PCI location. */ + pci_id_t id; /* PCI ID. */ + pci_resource_t bar[PCI_MAX_RESOURCE]; /* PCI Resources */ + uint16_t max_vfs; /* sriov enable if not zero */ + enum pci_kernel_driver kdrv; /* Kernel driver */ +} pci_dev_t; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/platform/linux-generic/include/odp_internal.h b/platform/linux-generic/include/odp_internal.h index 6811d8d0..b2a27ba6 100644 --- a/platform/linux-generic/include/odp_internal.h +++ b/platform/linux-generic/include/odp_internal.h @@ -78,6 +78,7 @@ enum init_stage { IPSEC_EVENTS_INIT, IPSEC_SAD_INIT, MODULES_INIT, + PCI_INIT, ALL_INIT /* All init stages completed */ };
@@ -155,6 +156,9 @@ int _odp_ipsec_events_term_global(void);
int _odp_modules_init_global(void);
+int _odp_pci_init_global(void); +int _odp_pci_term_global(void); + int cpuinfo_parser(FILE *file, system_info_t *sysinfo); uint64_t odp_cpufreq_id(const char *filename, int id); uint64_t odp_cpu_hz_current(int id); diff --git a/platform/linux-generic/odp_init.c b/platform/linux-generic/odp_init.c index 0268a3bd..c93475f0 100644 --- a/platform/linux-generic/odp_init.c +++ b/platform/linux-generic/odp_init.c @@ -217,6 +217,12 @@ int odp_init_global(odp_instance_t *instance, } stage = TRAFFIC_MNGR_INIT;
+ if (_odp_pci_init_global()) { + ODP_ERR("ODP pci init failed.\n"); + goto init_failed; + } + stage = PCI_INIT; + if (_odp_int_name_tbl_init_global()) { ODP_ERR("ODP name table init failed\n"); goto init_failed; @@ -292,6 +298,13 @@ int _odp_term_global(enum init_stage stage) } /* Fall through */
+ case PCI_INIT: + if (_odp_pci_term_global()) { + ODP_ERR("PCI term failed.\n"); + rc = -1; + } + /* Fall through */ + case NAME_TABLE_INIT: if (_odp_int_name_tbl_term_global()) { ODP_ERR("Name table term failed.\n");
commit 41cfdd1f67e0a44aa3aed04f4ddbaa53b5c43b38 Author: Christophe Milard christophe.milard@linaro.org Date: Wed Sep 14 14:51:08 2016 +0200
linux-gen: _str_functions: string handling functions
String handlling functions (which were originally part of odp_system_info.c) are gathered in a separated file, so they can be reused by others
Signed-off-by: Christophe Milard christophe.milard@linaro.org
diff --git a/platform/linux-generic/Makefile.am b/platform/linux-generic/Makefile.am index 9b9936dd..4dbdb813 100644 --- a/platform/linux-generic/Makefile.am +++ b/platform/linux-generic/Makefile.am @@ -153,6 +153,7 @@ noinst_HEADERS = \ include/_ishm_internal.h \ include/_ishmphy_internal.h \ include/_ishmpool_internal.h \ + include/_str_functions_internal.h \ include/drv_driver_internal.h \ include/odp_align_internal.h \ include/odp_atomic_internal.h \ @@ -221,6 +222,7 @@ __LIB__libodp_linux_la_SOURCES = \ _ishmphy.c \ _ishmpool.c \ _modules.c \ + _str_functions.c \ odp_atomic.c \ odp_barrier.c \ odp_bitmap.c \ diff --git a/platform/linux-generic/_str_functions.c b/platform/linux-generic/_str_functions.c new file mode 100644 index 00000000..eeb664bc --- /dev/null +++ b/platform/linux-generic/_str_functions.c @@ -0,0 +1,102 @@ +/* Copyright (c) 2016, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * BSD LICENSE + * + * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. + * All rights reserved. + */ + +#include <odp_posix_extensions.h> + +#include <odp_internal.h> +#include <odp_debug_internal.h> +#include <_str_functions_internal.h> +#include <odp/api/align.h> +#include <errno.h> +#include <string.h> +#include <stdio.h> +#include <inttypes.h> +#include <ctype.h> + +/* + * split string into tokens. largely "inspired" by dpdk: + * lib/librte_eal/common/eal_common_string_fns.c: rte_strsplit + */ +int _odp_strsplit(char *string, int stringlen, + char **tokens, int maxtokens, char delim) +{ + int i, tok = 0; + int tokstart = 1; /* first token is right at start of string */ + + if (string == NULL || tokens == NULL) + return -1; + + for (i = 0; i < stringlen; i++) { + if (string[i] == '\0' || tok >= maxtokens) + break; + if (tokstart) { + tokstart = 0; + tokens[tok++] = &string[i]; + } + if (string[i] == delim) { + string[i] = '\0'; + tokstart = 1; + } + } + return tok; +} + +/* + * Converts a numeric string to the equivalent uint64_t value. + * As well as straight number conversion, also recognises the suffixes + * k, m and g for kilobytes, megabytes and gigabytes respectively. + * + * If a negative number is passed in i.e. a string with the first non-black + * character being "-", zero is returned. Zero is also returned in the case of + * an error with the strtoull call in the function. + * largely "inspired" by dpdk: + * lib/librte_eal/common/include/rte_common.h: rte_str_to_size + * + * param str + * String containing number to convert. + * return + * Number. + */ +uint64_t _odp_str_to_size(const char *str) +{ + char *endptr; + unsigned long long size; + + while (isspace((int)*str)) + str++; + if (*str == '-') + return 0; + + errno = 0; + size = strtoull(str, &endptr, 0); + if (errno) + return 0; + + if (*endptr == ' ') + endptr++; /* allow 1 space gap */ + + switch (*endptr) { + case 'G': + case 'g': + size *= 1024; /* fall-through */ + case 'M': + case 'm': + size *= 1024; /* fall-through */ + case 'K': + case 'k': + size *= 1024; /* fall-through */ + default: + break; + } + return size; +} diff --git a/platform/linux-generic/include/_str_functions_internal.h b/platform/linux-generic/include/_str_functions_internal.h new file mode 100644 index 00000000..403b97ae --- /dev/null +++ b/platform/linux-generic/include/_str_functions_internal.h @@ -0,0 +1,25 @@ +/* Copyright (c) 2016, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _STR_FUNCTIONS_INTERNAL_H +#define _STR_FUNCTIONS_INTERNAL_H + +#include <string.h> +#include <odp_internal.h> + +#ifdef __cplusplus +extern "C" { +#endif + +uint64_t _odp_str_to_size(const char *str); +int _odp_strsplit(char *string, int stringlen, + char **tokens, int maxtokens, char delim); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/platform/linux-generic/odp_system_info.c b/platform/linux-generic/odp_system_info.c index 3cbe1d3d..fbc011de 100644 --- a/platform/linux-generic/odp_system_info.c +++ b/platform/linux-generic/odp_system_info.c @@ -19,6 +19,7 @@ #include <odp/api/version.h> #include <odp_internal.h> #include <odp_debug_internal.h> +#include <_str_functions_internal.h> #include <odp/api/align.h> #include <odp/api/cpu.h> #include <errno.h> @@ -108,84 +109,6 @@ static uint64_t default_huge_page_size(void) return 0; }
-/* - * split string into tokens. largely "inspired" by dpdk: - * lib/librte_eal/common/eal_common_string_fns.c: rte_strsplit - */ -static int strsplit(char *string, int stringlen, - char **tokens, int maxtokens, char delim) -{ - int i, tok = 0; - int tokstart = 1; /* first token is right at start of string */ - - if (string == NULL || tokens == NULL) - return -1; - - for (i = 0; i < stringlen; i++) { - if (string[i] == '\0' || tok >= maxtokens) - break; - if (tokstart) { - tokstart = 0; - tokens[tok++] = &string[i]; - } - if (string[i] == delim) { - string[i] = '\0'; - tokstart = 1; - } - } - return tok; -} - -/* - * Converts a numeric string to the equivalent uint64_t value. - * As well as straight number conversion, also recognises the suffixes - * k, m and g for kilobytes, megabytes and gigabytes respectively. - * - * If a negative number is passed in i.e. a string with the first non-black - * character being "-", zero is returned. Zero is also returned in the case of - * an error with the strtoull call in the function. - * largely "inspired" by dpdk: - * lib/librte_eal/common/include/rte_common.h: rte_str_to_size - * - * param str - * String containing number to convert. - * return - * Number. - */ -static inline uint64_t str_to_size(const char *str) -{ - char *endptr; - unsigned long long size; - - while (isspace((int)*str)) - str++; - if (*str == '-') - return 0; - - errno = 0; - size = strtoull(str, &endptr, 0); - if (errno) - return 0; - - if (*endptr == ' ') - endptr++; /* allow 1 space gap */ - - switch (*endptr) { - case 'G': - case 'g': - size *= 1024; /* fall-through */ - case 'M': - case 'm': - size *= 1024; /* fall-through */ - case 'K': - case 'k': - size *= 1024; /* fall-through */ - default: - break; - } - return size; -} - /* * returns a malloced string containing the name of the directory for * huge pages of a given size (0 for default) @@ -227,8 +150,9 @@ static char *get_hugepage_dir(uint64_t hugepage_sz) hugepage_sz = default_size;
while (fgets(buf, sizeof(buf), fd)) { - if (strsplit(buf, sizeof(buf), tokens, - _FIELDNAME_MAX, split_tok) != _FIELDNAME_MAX) { + if (_odp_strsplit(buf, sizeof(buf), tokens, + _FIELDNAME_MAX, + split_tok) != _FIELDNAME_MAX) { ODP_ERR("Error parsing %s\n", proc_mounts); break; /* return NULL */ } @@ -247,7 +171,7 @@ static char *get_hugepage_dir(uint64_t hugepage_sz) /* there is an explicit page size, so check it */ else { pagesz = - str_to_size(&pagesz_str[pagesize_opt_len]); + _odp_str_to_size(&pagesz_str[pagesize_opt_len]); if (pagesz == hugepage_sz) { retval = strdup(tokens[MOUNTPT]); break;
commit 485779a031f467eb242dec0a164b7380612494a4 Author: Josep Puigdemont josep.puigdemont@linaro.org Date: Wed Jun 28 10:30:09 2017 +0200
pktio: virtio: stub for a VirtIO-based packet IO
Signed-off-by: Josep Puigdemont josep.puigdemont@linaro.org
diff --git a/platform/linux-generic/Makefile.am b/platform/linux-generic/Makefile.am index 56ef03c6..9b9936dd 100644 --- a/platform/linux-generic/Makefile.am +++ b/platform/linux-generic/Makefile.am @@ -186,6 +186,7 @@ noinst_HEADERS = \ include/odp_pktio_ops_pcap.h \ include/odp_pktio_ops_socket.h \ include/odp_pktio_ops_tap.h \ + include/odp_pktio_ops_virtio.h \ include/odp_pktio_ops_subsystem.h \ include/odp_pkt_queue_internal.h \ include/odp_queue_subsystem.h \ @@ -255,6 +256,7 @@ __LIB__libodp_linux_la_SOURCES = \ pktio/socket_mmap.c \ pktio/sysfs.c \ pktio/tap.c \ + pktio/virtio.c \ pktio/ring.c \ pool/generic.c \ pool/subsystem.c \ diff --git a/platform/linux-generic/include/odp_pktio_ops_virtio.h b/platform/linux-generic/include/odp_pktio_ops_virtio.h new file mode 100644 index 00000000..a8ace414 --- /dev/null +++ b/platform/linux-generic/include/odp_pktio_ops_virtio.h @@ -0,0 +1,14 @@ +/* Copyright (c) 2017, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ODP_PACKET_VIRTIO_H +#define ODP_PACKET_VIRTIO_H + +typedef struct { + char name[32]; /**< Unique identifier name */ +} pktio_ops_virtio_data_t; + +#endif diff --git a/platform/linux-generic/m4/configure.m4 b/platform/linux-generic/m4/configure.m4 index fc29f9cb..61a43fb8 100644 --- a/platform/linux-generic/m4/configure.m4 +++ b/platform/linux-generic/m4/configure.m4 @@ -47,3 +47,6 @@ AC_DEFINE([ODP_PKTIO_SOCKET], [1],
AC_DEFINE([ODP_PKTIO_SOCKET_MMAP], [1], [Define to 1 to enable SOCKET_MMAP packet I/O support]) + +AC_DEFINE([ODP_PKTIO_VIRTIO], [1], + [Define to 1 to enable VirtIO packet I/O support]) diff --git a/platform/linux-generic/pktio/subsystem.c b/platform/linux-generic/pktio/subsystem.c index a3b36c14..17bc1164 100644 --- a/platform/linux-generic/pktio/subsystem.c +++ b/platform/linux-generic/pktio/subsystem.c @@ -44,6 +44,9 @@ extern int enable_link_socket_mmap_pktio_ops; #ifdef ODP_PKTIO_TAP extern int enable_link_tap_pktio_ops; #endif +#ifdef ODP_PKTIO_VIRTIO +extern int enable_link_virtio_pktio_ops; +#endif
ODP_SUBSYSTEM_CONSTRUCTOR(pktio_ops) { @@ -73,4 +76,7 @@ ODP_SUBSYSTEM_CONSTRUCTOR(pktio_ops) #ifdef ODP_PKTIO_TAP enable_link_tap_pktio_ops = 1; #endif +#ifdef ODP_PKTIO_VIRTIO + enable_link_virtio_pktio_ops = 1; +#endif } diff --git a/platform/linux-generic/pktio/virtio.c b/platform/linux-generic/pktio/virtio.c new file mode 100644 index 00000000..b46a642a --- /dev/null +++ b/platform/linux-generic/pktio/virtio.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2017, Linaro Limited + * + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * devices are spcified as: pci:domain:bus:device.function + */ + +#include "config.h" + +#ifdef ODP_PKTIO_VIRTIO + +#include <stdio.h> + +#include <odp_api.h> +#include <odp_packet_internal.h> +#include <odp_packet_io_internal.h> + +#include <odp_classification_internal.h> +#include <odp_debug_internal.h> +#include <odp/api/hints.h> + +#include <odp_pktio_ops_virtio.h> + +#define PCI_PKTIO_PREFIX "pci:" +#define PCI_PKTIO_PREFIX_LEN (sizeof(PCI_PKTIO_PREFIX) - 1) + +static int virtio_init_global(void) +{ + ODP_PRINT("PKTIO: initialized pci interface.\n"); + return 0; +} + +static int virtio_open(odp_pktio_t id ODP_UNUSED, pktio_entry_t *pktio_entry, + const char *devname, odp_pool_t pool ODP_UNUSED) +{ + static unsigned int dev_id = 0; + pktio_ops_virtio_data_t *virtio_entry = odp_ops_data(pktio_entry, + virtio); + + if (strncmp(devname, PCI_PKTIO_PREFIX, PCI_PKTIO_PREFIX_LEN)) + return -1; + + memset(virtio_entry, 0, sizeof(pktio_ops_virtio_data_t)); + snprintf(virtio_entry->name, + sizeof(virtio_entry->name), + "virtio_%u", + dev_id++); + + ODP_PRINT("virtio: opened %s\n", virtio_entry->name); + + return 0; +} + +static int virtio_close(pktio_entry_t *pktio_entry ODP_UNUSED) +{ + return 0; +} + +static int virtio_recv(pktio_entry_t *pktio_entry ODP_UNUSED, int index ODP_UNUSED, + odp_packet_t pkts[] ODP_UNUSED, int len ODP_UNUSED) +{ + return 0; +} + +static int virtio_send(pktio_entry_t *pktio_entry ODP_UNUSED, int index ODP_UNUSED, + const odp_packet_t pkt_tbl[] ODP_UNUSED, int len) +{ + return len; +} + +static pktio_ops_module_t virtio_pktio_ops = { + .base = { + .name = "virtio-net", + .init_local = NULL, + .term_local = NULL, + .init_global = virtio_init_global, + .term_global = NULL, + }, + .open = virtio_open, + .close = virtio_close, + .start = NULL, + .stop = NULL, + .stats = NULL, + .stats_reset = NULL, + .pktin_ts_res = NULL, + .pktin_ts_from_ns = NULL, + .recv = virtio_recv, + .send = virtio_send, + .mtu_get = NULL, + .promisc_mode_set = NULL, + .promisc_mode_get = NULL, + .mac_get = NULL, + .link_status = NULL, + .capability = NULL, + .config = NULL, + .input_queues_config = NULL, + .output_queues_config = NULL, + .print = NULL, +}; + +ODP_MODULE_CONSTRUCTOR(virtio_pktio_ops) +{ + odp_module_constructor(&virtio_pktio_ops); + + odp_subsystem_register_module(pktio_ops, &virtio_pktio_ops); +} + +/* Temporary variable to enable linking this module in, + * shall be removed later + */ +int enable_link_virtio_pktio_ops = 0; + +#endif
-----------------------------------------------------------------------
Summary of changes: .gitignore | 4 +- .shippable.yml | 45 + .travis.yml | 36 +- DEPENDENCIES | 6 +- Makefile.am | 20 +- configure.ac | 23 +- doc/users-guide/users-guide.adoc | 18 + example/Makefile.am | 2 + example/Makefile.inc | 4 +- example/classifier/Makefile.am | 9 +- example/classifier/odp_classifier.c | 14 +- example/generator/Makefile.am | 9 +- example/generator/odp_generator.c | 12 +- example/hello/Makefile.am | 6 +- example/ipfragreass/Makefile.am | 27 +- example/ipsec/Makefile.am | 53 +- example/ipsec/odp_ipsec.c | 12 +- example/l2fwd/odp_l2fwd.c | 2 +- example/l2fwd_simple/Makefile.am | 9 +- example/l2fwd_simple/l2fwd_simple_run.sh | 3 +- example/l3fwd/Makefile.am | 15 +- example/l3fwd/odp_l3fwd.c | 63 +- example/l3fwd/odp_l3fwd_run.sh | 2 +- example/packet/Makefile.am | 9 +- example/packet/odp_pktio.c | 12 +- example/packet/pktio_run.sh | 8 +- example/switch/Makefile.am | 9 +- example/switch/odp_switch.c | 14 +- example/switch/switch_run.sh | 2 +- example/time/Makefile.am | 9 +- example/timer/Makefile.am | 15 +- example/timer/odp_timer_test.c | 10 +- example/traffic_mgmt/Makefile.am | 10 +- example/traffic_mgmt/odp_traffic_mgmt.c | 30 +- helper/.gitignore | 1 + helper/Makefile.am | 57 +- {pkgconfig => helper}/libodphelper.pc.in | 0 helper/m4/configure.m4 | 3 +- helper/test/Makefile.am | 18 +- helper/test/linux/Makefile.am | 5 - helper/test/odpthreads_as_processes | 2 +- helper/test/odpthreads_as_pthreads | 2 +- include/Makefile.am | 163 +++ include/odp/api/spec/ipsec.h | 20 +- include/odp/api/spec/packet.h | 25 +- include/odp/api/spec/pool.h | 16 + include/odp/api/spec/shared_memory.h | 74 +- m4/ax_valgrind_check.m4 | 23 +- m4/odp_atomic.m4 | 95 ++ m4/odp_openssl.m4 | 60 + {platform/linux-generic/m4 => m4}/odp_timer.m4 | 7 +- m4/odp_visibility.m4 | 21 + platform/Makefile.inc | 90 -- platform/linux-dpdk/Makefile.am | 6 + .../linux-dpdk/include/odp/api/plat/timer_types.h | 4 +- platform/linux-dpdk/include/odp_packet_internal.h | 15 + .../linux-dpdk}/libodp-dpdk.pc.in | 0 platform/linux-dpdk/m4/configure.m4 | 16 +- platform/linux-dpdk/m4/odp_openssl.m4 | 1 - platform/linux-dpdk/m4/odp_timer.m4 | 1 - platform/linux-dpdk/m4/performance.m4 | 1 + platform/linux-dpdk/odp_init.c | 36 +- platform/linux-dpdk/odp_packet.c | 325 +++-- .../linux-dpdk/test}/.gitignore | 0 platform/linux-dpdk/test/Makefile.am | 35 + .../linux-dpdk/test}/Makefile.inc | 13 +- .../test/validation/api/pktio/.gitignore | 1 + .../test}/validation/api/pktio/Makefile.am | 0 .../linux-dpdk/test/validation/api/pktio/pktio_env | 1 + .../test}/validation/api/pktio/pktio_run.sh | 0 .../linux-dpdk/test}/wrapper-script.sh | 0 platform/linux-generic/.gitignore | 1 + platform/linux-generic/Makefile.am | 438 +++---- platform/linux-generic/_ishm.c | 118 +- platform/linux-generic/_ishmphy.c | 81 ++ platform/linux-generic/_str_functions.c | 102 ++ .../linux-generic/arch/default/odp_sysinfo_parse.c | 5 + .../linux-generic/arch/mips64/odp_sysinfo_parse.c | 5 + .../linux-generic/arch/powerpc/odp_sysinfo_parse.c | 5 + .../linux-generic/arch/x86/odp_sysinfo_parse.c | 36 + platform/linux-generic/drv_pci.c | 775 ++++++++++++ platform/linux-generic/drv_pci_uio.c | 622 ++++++++++ platform/linux-generic/include/_ishm_internal.h | 1 + platform/linux-generic/include/_ishmphy_internal.h | 14 + .../include/_str_functions_internal.h | 25 + platform/linux-generic/include/drv_pci_internal.h | 148 +++ .../include/odp/api/plat/timer_types.h | 4 +- .../linux-generic/include/odp_buffer_internal.h | 9 +- .../linux-generic/include/odp_config_internal.h | 17 +- .../linux-generic/include/odp_debug_internal.h | 2 +- platform/linux-generic/include/odp_internal.h | 13 + .../linux-generic/include/odp_ipsec_internal.h | 201 ++++ .../linux-generic/include/odp_packet_internal.h | 21 +- .../linux-generic/include/odp_pktio_ops_virtio.h | 18 + platform/linux-generic/include/odp_pool_internal.h | 3 +- platform/linux-generic/include/protocols/ip.h | 1 + .../linux-generic}/libodp-linux.pc.in | 0 platform/linux-generic/m4/configure.m4 | 101 +- platform/linux-generic/m4/odp_dpdk.m4 | 4 +- platform/linux-generic/m4/odp_netmap.m4 | 4 +- platform/linux-generic/m4/odp_openssl.m4 | 37 - platform/linux-generic/m4/odp_pcap.m4 | 4 +- {test => platform}/linux-generic/m4/performance.m4 | 2 + platform/linux-generic/odp_event.c | 4 + platform/linux-generic/odp_init.c | 39 + platform/linux-generic/odp_ipsec.c | 1251 ++++++++++++++++++-- platform/linux-generic/odp_ipsec_events.c | 156 +++ platform/linux-generic/odp_ipsec_sad.c | 500 ++++++++ platform/linux-generic/odp_packet.c | 413 +++++-- platform/linux-generic/odp_packet_io.c | 34 +- platform/linux-generic/odp_pkt_queue.c | 22 +- platform/linux-generic/odp_shared_memory.c | 5 + platform/linux-generic/odp_sorted_list.c | 12 +- platform/linux-generic/odp_system_info.c | 93 +- platform/linux-generic/odp_timer.c | 110 +- platform/linux-generic/odp_timer_wheel.c | 44 +- platform/linux-generic/odp_traffic_mngr.c | 42 +- platform/linux-generic/pktio/dpdk.c | 105 +- platform/linux-generic/pktio/loopback.c | 25 + platform/linux-generic/pktio/netmap.c | 17 +- platform/linux-generic/pktio/socket_mmap.c | 2 +- platform/linux-generic/pktio/subsystem.c | 6 + platform/linux-generic/pktio/tap.c | 117 +- platform/linux-generic/pktio/virtio.c | 139 +++ platform/linux-generic/pktio/virtio_pci.c | 601 ++++++++++ platform/linux-generic/pktio/virtio_pci.h | 320 +++++ platform/linux-generic/pool/generic.c | 103 +- .../linux-generic/test}/.gitignore | 1 + platform/linux-generic/test/Makefile.am | 57 + .../linux-generic/test}/Makefile.inc | 4 +- .../linux-generic/test}/mmap_vlan_ins/.gitignore | 0 .../linux-generic/test}/mmap_vlan_ins/Makefile.am | 2 +- .../test}/mmap_vlan_ins/mmap_vlan_ins.c | 0 .../test}/mmap_vlan_ins/mmap_vlan_ins.sh | 0 .../linux-generic/test/mmap_vlan_ins}/pktio_env | 0 .../linux-generic/test}/mmap_vlan_ins/vlan.pcap | Bin .../linux-generic/test/performance}/.gitignore | 0 .../linux-generic/test}/performance/Makefile.am | 0 .../test}/performance/odp_scheduling_run_proc.sh | 2 +- .../linux-generic/test}/pktio_ipc/.gitignore | 0 .../linux-generic/test}/pktio_ipc/Makefile.am | 0 .../linux-generic/test}/pktio_ipc/ipc_common.c | 8 +- .../linux-generic/test}/pktio_ipc/ipc_common.h | 0 .../linux-generic/test}/pktio_ipc/pktio_ipc1.c | 0 .../linux-generic/test}/pktio_ipc/pktio_ipc2.c | 0 .../linux-generic/test}/pktio_ipc/pktio_ipc_run.sh | 0 .../linux-generic/test}/ring/.gitignore | 0 .../linux-generic/test}/ring/Makefile.am | 2 +- .../linux-generic/test}/ring/ring_basic.c | 0 .../linux-generic/test}/ring/ring_main.c | 0 .../linux-generic/test}/ring/ring_stress.c | 0 .../linux-generic/test}/ring/ring_suites.c | 0 .../linux-generic/test}/ring/ring_suites.h | 0 .../linux-generic/test/validation/Makefile.inc | 1 + .../linux-generic/test/validation/api/Makefile.inc | 1 + .../test/validation/api/pktio}/.gitignore | 0 .../test}/validation/api/pktio/Makefile.am | 0 .../test/validation/api/pktio}/pktio_env | 0 .../test}/validation/api/pktio/pktio_run.sh | 2 +- .../test}/validation/api/pktio/pktio_run_dpdk.sh | 4 +- .../test}/validation/api/pktio/pktio_run_netmap.sh | 2 +- .../test}/validation/api/pktio/pktio_run_pcap.sh | 2 +- .../test}/validation/api/pktio/pktio_run_tap.sh | 2 +- .../test}/validation/api/shmem/.gitignore | 0 .../test}/validation/api/shmem/Makefile.am | 2 +- .../test}/validation/api/shmem/shmem_common.h | 0 .../test}/validation/api/shmem/shmem_linux.c | 8 +- .../test}/validation/api/shmem/shmem_linux.h | 0 .../test}/validation/api/shmem/shmem_odp1.c | 0 .../test}/validation/api/shmem/shmem_odp1.h | 0 .../test}/validation/api/shmem/shmem_odp2.c | 0 .../test}/validation/api/shmem/shmem_odp2.h | 0 scripts/Dockerfile | 26 + scripts/build-pktio-dpdk | 8 +- scripts/ci-checkpatches.sh | 22 +- test/Makefile.am | 2 +- test/Makefile.inc | 3 +- test/README | 2 +- test/{common_plat => }/common/Makefile.am | 7 + test/{common_plat => }/common/mask_common.c | 0 test/{common_plat => }/common/mask_common.h | 0 test/{common_plat => }/common/odp_cunit_common.c | 0 test/{common_plat => }/common/odp_cunit_common.h | 0 .../{linux-generic/run-test => common/run-test.sh} | 0 test/{ => common}/test_debug.h | 0 test/common_plat/Makefile.am | 7 - test/common_plat/m4/configure.m4 | 39 - test/common_plat/validation/api/Makefile.am | 27 - test/common_plat/validation/api/Makefile.inc | 13 - test/common_plat/validation/api/ipsec/.gitignore | 1 - test/common_plat/validation/api/ipsec/Makefile.am | 10 - test/common_plat/validation/api/ipsec/ipsec.c | 44 - test/common_plat/validation/api/ipsec/ipsec.h | 24 - test/common_plat/validation/api/ipsec/ipsec_main.c | 12 - test/common_plat/validation/drv/Makefile.inc | 1 - test/linux-dpdk/Makefile.am | 56 - test/linux-dpdk/m4/configure.m4 | 4 - test/linux-dpdk/run-test | 1 - test/linux-dpdk/validation/api/pktio/.gitignore | 1 - test/linux-dpdk/validation/api/pktio/pktio_env | 1 - test/linux-generic/Makefile.am | 90 -- test/linux-generic/m4/configure.m4 | 9 - test/linux-generic/validation/Makefile.inc | 1 - test/linux-generic/validation/api/Makefile.inc | 1 - test/linux-generic/validation/api/pktio/.gitignore | 2 - test/m4/configure.m4 | 40 +- test/{common_plat => }/m4/miscellaneous.m4 | 0 test/{common_plat => }/m4/performance.m4 | 0 test/{common_plat => }/m4/validation.m4 | 2 +- test/{common_plat => }/miscellaneous/.gitignore | 0 test/{common_plat => }/miscellaneous/Makefile.am | 4 +- .../miscellaneous/odp_api_from_cpp.cpp | 0 test/{common_plat => }/performance/.gitignore | 0 test/{common_plat => }/performance/Makefile.am | 17 +- test/{common_plat => }/performance/dummy_crc.h | 0 .../performance/odp_bench_packet.c | 14 +- test/{common_plat => }/performance/odp_crypto.c | 0 test/{common_plat => }/performance/odp_l2fwd.c | 14 +- .../{common_plat => }/performance/odp_l2fwd_run.sh | 5 +- .../performance/odp_pktio_ordered.c | 14 +- .../performance/odp_pktio_ordered_run.sh | 0 .../{common_plat => }/performance/odp_pktio_perf.c | 42 +- .../performance/odp_sched_latency.c | 0 .../performance/odp_sched_latency_run.sh | 0 .../{common_plat => }/performance/odp_scheduling.c | 12 +- .../performance/odp_scheduling_run.sh | 0 test/{common_plat => }/performance/udp64.pcap | Bin test/{common_plat => }/validation/Makefile.am | 0 test/{common_plat => }/validation/Makefile.inc | 4 +- test/{linux-generic => validation/api}/.gitignore | 0 test/validation/api/Makefile.am | 79 ++ test/validation/api/Makefile.inc | 6 + test/{common_plat => }/validation/api/README | 0 .../validation/api/atomic/.gitignore | 0 .../validation/api/atomic/Makefile.am | 2 +- .../validation/api/atomic/atomic.c | 0 .../validation/api/atomic/atomic.h | 0 .../validation/api/atomic/atomic_main.c | 0 .../validation/api/barrier/.gitignore | 0 .../validation/api/barrier/Makefile.am | 2 +- .../validation/api/barrier/barrier.c | 0 .../validation/api/barrier/barrier.h | 0 .../validation/api/barrier/barrier_main.c | 0 .../validation/api/buffer/.gitignore | 0 .../validation/api/buffer/Makefile.am | 2 +- .../validation/api/buffer/buffer.c | 0 .../validation/api/buffer/buffer.h | 0 .../validation/api/buffer/buffer_main.c | 0 .../validation/api/chksum/.gitignore | 0 .../validation/api/chksum/Makefile.am | 0 .../validation/api/chksum/chksum.c | 0 .../validation/api/chksum/chksum.h | 0 .../validation/api/chksum/chksum_main.c | 0 .../validation/api/classification/.gitignore | 0 .../validation/api/classification/Makefile.am | 2 +- .../validation/api/classification/classification.c | 0 .../validation/api/classification/classification.h | 0 .../api/classification/classification_main.c | 0 .../api/classification/odp_classification_basic.c | 0 .../api/classification/odp_classification_common.c | 0 .../classification/odp_classification_test_pmr.c | 0 .../api/classification/odp_classification_tests.c | 0 .../classification/odp_classification_testsuites.h | 0 .../validation/api/cpumask/.gitignore | 0 .../validation/api/cpumask/Makefile.am | 2 +- .../validation/api/cpumask/cpumask.c | 0 .../validation/api/cpumask/cpumask.h | 0 .../validation/api/cpumask/cpumask_main.c | 0 .../validation/api/crypto/.gitignore | 0 .../validation/api/crypto/Makefile.am | 2 +- .../validation/api/crypto/crypto.c | 0 .../validation/api/crypto/crypto.h | 0 .../validation/api/crypto/crypto_main.c | 0 .../validation/api/crypto/odp_crypto_test_inp.c | 0 .../validation/api/crypto/odp_crypto_test_inp.h | 0 .../validation/api/crypto/test_vectors.h | 0 .../validation/api/crypto/test_vectors_len.h | 0 .../validation/api/errno/.gitignore | 0 .../validation/api/errno/Makefile.am | 2 +- .../{common_plat => }/validation/api/errno/errno.c | 0 .../{common_plat => }/validation/api/errno/errno.h | 0 .../validation/api/errno/errno_main.c | 0 .../validation/api/hash/.gitignore | 0 .../validation/api/hash/Makefile.am | 2 +- test/{common_plat => }/validation/api/hash/hash.c | 0 test/{common_plat => }/validation/api/hash/hash.h | 0 .../validation/api/hash/hash_main.c | 0 .../validation/api/init/.gitignore | 0 .../validation/api/init/Makefile.am | 2 +- test/{common_plat => }/validation/api/init/init.c | 0 test/{common_plat => }/validation/api/init/init.h | 0 .../validation/api/init/init_main_abort.c | 0 .../validation/api/init/init_main_log.c | 0 .../validation/api/init/init_main_ok.c | 0 test/validation/api/ipsec/.gitignore | 4 + test/validation/api/ipsec/Makefile.am | 27 + test/validation/api/ipsec/ipsec.c | 887 ++++++++++++++ test/validation/api/ipsec/ipsec.h | 89 ++ test/validation/api/ipsec/ipsec_async.c | 55 + test/validation/api/ipsec/ipsec_inline_in.c | 56 + test/validation/api/ipsec/ipsec_inline_out.c | 56 + test/validation/api/ipsec/ipsec_sync.c | 53 + test/validation/api/ipsec/ipsec_sync_in.c | 27 + test/validation/api/ipsec/ipsec_test_in.c | 815 +++++++++++++ test/validation/api/ipsec/ipsec_test_out.c | 348 ++++++ test/validation/api/ipsec/test_vectors.h | 965 +++++++++++++++ .../validation/api/lock/.gitignore | 0 .../validation/api/lock/Makefile.am | 2 +- test/{common_plat => }/validation/api/lock/lock.c | 0 test/{common_plat => }/validation/api/lock/lock.h | 0 .../validation/api/lock/lock_main.c | 0 .../validation/api/packet/.gitignore | 0 .../validation/api/packet/Makefile.am | 2 +- .../validation/api/packet/packet.c | 36 +- .../validation/api/packet/packet.h | 0 .../validation/api/packet/packet_main.c | 0 .../validation/api/pktio/.gitignore | 0 .../validation/api/pktio/Makefile.am | 2 +- .../validation/api/pktio/parser.c | 0 .../validation/api/pktio/parser.h | 0 .../{common_plat => }/validation/api/pktio/pktio.c | 0 .../{common_plat => }/validation/api/pktio/pktio.h | 0 .../validation/api/pktio/pktio_main.c | 0 .../validation/api/pool/.gitignore | 0 .../validation/api/pool/Makefile.am | 2 +- test/{common_plat => }/validation/api/pool/pool.c | 0 test/{common_plat => }/validation/api/pool/pool.h | 0 .../validation/api/pool/pool_main.c | 0 .../validation/api/queue/.gitignore | 0 .../validation/api/queue/Makefile.am | 2 +- .../{common_plat => }/validation/api/queue/queue.c | 0 .../{common_plat => }/validation/api/queue/queue.h | 0 .../validation/api/queue/queue_main.c | 0 .../validation/api/random/.gitignore | 0 .../validation/api/random/Makefile.am | 2 +- .../validation/api/random/random.c | 0 .../validation/api/random/random.h | 0 .../validation/api/random/random_main.c | 0 .../validation/api/scheduler/.gitignore | 0 .../validation/api/scheduler/Makefile.am | 2 +- .../validation/api/scheduler/scheduler.c | 0 .../validation/api/scheduler/scheduler.h | 0 .../validation/api/scheduler/scheduler_main.c | 0 .../validation/api/shmem/.gitignore | 0 .../validation/api/shmem/Makefile.am | 2 +- .../{common_plat => }/validation/api/shmem/shmem.c | 26 +- .../{common_plat => }/validation/api/shmem/shmem.h | 0 .../validation/api/shmem/shmem_main.c | 0 .../validation/api/std_clib/.gitignore | 0 .../validation/api/std_clib/Makefile.am | 2 +- .../validation/api/std_clib/std_clib.c | 0 .../validation/api/std_clib/std_clib.h | 0 .../validation/api/std_clib/std_clib_main.c | 0 .../validation/api/system/.gitignore | 0 .../validation/api/system/Makefile.am | 2 +- .../validation/api/system/system.c | 0 .../validation/api/system/system.h | 0 .../validation/api/system/system_main.c | 0 .../validation/api/thread/.gitignore | 0 .../validation/api/thread/Makefile.am | 2 +- .../validation/api/thread/thread.c | 0 .../validation/api/thread/thread.h | 0 .../validation/api/thread/thread_main.c | 0 .../validation/api/time/.gitignore | 0 .../validation/api/time/Makefile.am | 2 +- test/{common_plat => }/validation/api/time/time.c | 0 test/{common_plat => }/validation/api/time/time.sh | 2 +- .../validation/api/time/time_main.c | 0 .../validation/api/time/time_test.h | 0 .../validation/api/timer/.gitignore | 0 .../validation/api/timer/Makefile.am | 2 +- .../{common_plat => }/validation/api/timer/timer.c | 0 .../{common_plat => }/validation/api/timer/timer.h | 0 .../validation/api/timer/timer_main.c | 0 .../validation/api/traffic_mngr/.gitignore | 0 .../validation/api/traffic_mngr/Makefile.am | 2 +- .../validation/api/traffic_mngr/traffic_mngr.c | 0 .../validation/api/traffic_mngr/traffic_mngr.h | 0 .../validation/api/traffic_mngr/traffic_mngr.sh | 2 +- .../api/traffic_mngr/traffic_mngr_main.c | 0 .../performance => validation/drv}/.gitignore | 0 test/{common_plat => }/validation/drv/Makefile.am | 0 test/validation/drv/Makefile.inc | 1 + test/{common_plat => }/validation/drv/README | 0 .../validation/drv/drvatomic/.gitignore | 0 .../validation/drv/drvatomic/Makefile.am | 0 .../validation/drv/drvatomic/drvatomic.c | 0 .../validation/drv/drvatomic/drvatomic.h | 0 .../validation/drv/drvatomic/drvatomic_main.c | 0 .../validation/drv/drvdriver/.gitignore | 0 .../validation/drv/drvdriver/Makefile.am | 0 .../validation/drv/drvdriver/drvdriver_device.c | 0 .../validation/drv/drvdriver/drvdriver_device.h | 0 .../drv/drvdriver/drvdriver_device_main.c | 0 .../validation/drv/drvdriver/drvdriver_devio.c | 0 .../validation/drv/drvdriver/drvdriver_devio.h | 0 .../drv/drvdriver/drvdriver_devio_main.c | 0 .../validation/drv/drvdriver/drvdriver_driver.c | 0 .../validation/drv/drvdriver/drvdriver_driver.h | 0 .../drv/drvdriver/drvdriver_driver_main.c | 0 .../validation/drv/drvdriver/drvdriver_enumr.c | 0 .../validation/drv/drvdriver/drvdriver_enumr.h | 0 .../drv/drvdriver/drvdriver_enumr_class.c | 0 .../drv/drvdriver/drvdriver_enumr_class.h | 0 .../drv/drvdriver/drvdriver_enumr_class_main.c | 0 .../drv/drvdriver/drvdriver_enumr_main.c | 0 .../validation/drv/drvshmem/.gitignore | 0 .../validation/drv/drvshmem/Makefile.am | 0 .../validation/drv/drvshmem/drvshmem.c | 0 .../validation/drv/drvshmem/drvshmem.h | 0 .../validation/drv/drvshmem/drvshmem_main.c | 0 411 files changed, 11000 insertions(+), 1898 deletions(-) create mode 100644 .shippable.yml create mode 100644 helper/.gitignore rename {pkgconfig => helper}/libodphelper.pc.in (100%) delete mode 100644 helper/test/linux/Makefile.am create mode 100644 include/Makefile.am create mode 100644 m4/odp_atomic.m4 create mode 100644 m4/odp_openssl.m4 rename {platform/linux-generic/m4 => m4}/odp_timer.m4 (63%) create mode 100644 m4/odp_visibility.m4 rename {pkgconfig => platform/linux-dpdk}/libodp-dpdk.pc.in (100%) delete mode 120000 platform/linux-dpdk/m4/odp_openssl.m4 delete mode 120000 platform/linux-dpdk/m4/odp_timer.m4 create mode 120000 platform/linux-dpdk/m4/performance.m4 copy {test/linux-dpdk => platform/linux-dpdk/test}/.gitignore (100%) create mode 100644 platform/linux-dpdk/test/Makefile.am rename {test/linux-dpdk => platform/linux-dpdk/test}/Makefile.inc (61%) create mode 120000 platform/linux-dpdk/test/validation/api/pktio/.gitignore rename {test/linux-dpdk => platform/linux-dpdk/test}/validation/api/pktio/Makefile.am (100%) create mode 120000 platform/linux-dpdk/test/validation/api/pktio/pktio_env rename {test/linux-dpdk => platform/linux-dpdk/test}/validation/api/pktio/pktio_run.sh (100%) rename {test/linux-dpdk => platform/linux-dpdk/test}/wrapper-script.sh (100%) create mode 100644 platform/linux-generic/_str_functions.c create mode 100644 platform/linux-generic/drv_pci.c create mode 100644 platform/linux-generic/drv_pci_uio.c create mode 100644 platform/linux-generic/include/_str_functions_internal.h create mode 100644 platform/linux-generic/include/drv_pci_internal.h create mode 100644 platform/linux-generic/include/odp_ipsec_internal.h create mode 100644 platform/linux-generic/include/odp_pktio_ops_virtio.h rename {pkgconfig => platform/linux-generic}/libodp-linux.pc.in (100%) delete mode 100644 platform/linux-generic/m4/odp_openssl.m4 rename {test => platform}/linux-generic/m4/performance.m4 (93%) create mode 100644 platform/linux-generic/odp_ipsec_events.c create mode 100644 platform/linux-generic/odp_ipsec_sad.c create mode 100644 platform/linux-generic/pktio/virtio.c create mode 100644 platform/linux-generic/pktio/virtio_pci.c create mode 100644 platform/linux-generic/pktio/virtio_pci.h rename {test/linux-dpdk => platform/linux-generic/test}/.gitignore (57%) create mode 100644 platform/linux-generic/test/Makefile.am rename {test/linux-generic => platform/linux-generic/test}/Makefile.inc (82%) rename {test/linux-generic => platform/linux-generic/test}/mmap_vlan_ins/.gitignore (100%) rename {test/linux-generic => platform/linux-generic/test}/mmap_vlan_ins/Makefile.am (88%) rename {test/linux-generic => platform/linux-generic/test}/mmap_vlan_ins/mmap_vlan_ins.c (100%) rename {test/linux-generic => platform/linux-generic/test}/mmap_vlan_ins/mmap_vlan_ins.sh (100%) rename {test/linux-generic/validation/api/pktio => platform/linux-generic/test/mmap_vlan_ins}/pktio_env (100%) rename {test/linux-generic => platform/linux-generic/test}/mmap_vlan_ins/vlan.pcap (100%) rename {test/common_plat/validation/api => platform/linux-generic/test/performance}/.gitignore (100%) rename {test/linux-generic => platform/linux-generic/test}/performance/Makefile.am (100%) rename {test/linux-generic => platform/linux-generic/test}/performance/odp_scheduling_run_proc.sh (90%) rename {test/linux-generic => platform/linux-generic/test}/pktio_ipc/.gitignore (100%) rename {test/linux-generic => platform/linux-generic/test}/pktio_ipc/Makefile.am (100%) rename {test/linux-generic => platform/linux-generic/test}/pktio_ipc/ipc_common.c (94%) rename {test/linux-generic => platform/linux-generic/test}/pktio_ipc/ipc_common.h (100%) rename {test/linux-generic => platform/linux-generic/test}/pktio_ipc/pktio_ipc1.c (100%) rename {test/linux-generic => platform/linux-generic/test}/pktio_ipc/pktio_ipc2.c (100%) rename {test/linux-generic => platform/linux-generic/test}/pktio_ipc/pktio_ipc_run.sh (100%) rename {test/linux-generic => platform/linux-generic/test}/ring/.gitignore (100%) rename {test/linux-generic => platform/linux-generic/test}/ring/Makefile.am (89%) rename {test/linux-generic => platform/linux-generic/test}/ring/ring_basic.c (100%) rename {test/linux-generic => platform/linux-generic/test}/ring/ring_main.c (100%) rename {test/linux-generic => platform/linux-generic/test}/ring/ring_stress.c (100%) rename {test/linux-generic => platform/linux-generic/test}/ring/ring_suites.c (100%) rename {test/linux-generic => platform/linux-generic/test}/ring/ring_suites.h (100%) create mode 100644 platform/linux-generic/test/validation/Makefile.inc create mode 100644 platform/linux-generic/test/validation/api/Makefile.inc rename {test/common_plat/validation/drv => platform/linux-generic/test/validation/api/pktio}/.gitignore (100%) rename {test/linux-generic => platform/linux-generic/test}/validation/api/pktio/Makefile.am (100%) rename {test/linux-generic/mmap_vlan_ins => platform/linux-generic/test/validation/api/pktio}/pktio_env (100%) rename {test/linux-generic => platform/linux-generic/test}/validation/api/pktio/pktio_run.sh (97%) rename {test/linux-generic => platform/linux-generic/test}/validation/api/pktio/pktio_run_dpdk.sh (92%) rename {test/linux-generic => platform/linux-generic/test}/validation/api/pktio/pktio_run_netmap.sh (97%) rename {test/linux-generic => platform/linux-generic/test}/validation/api/pktio/pktio_run_pcap.sh (93%) rename {test/linux-generic => platform/linux-generic/test}/validation/api/pktio/pktio_run_tap.sh (97%) rename {test/linux-generic => platform/linux-generic/test}/validation/api/shmem/.gitignore (100%) rename {test/linux-generic => platform/linux-generic/test}/validation/api/shmem/Makefile.am (90%) rename {test/linux-generic => platform/linux-generic/test}/validation/api/shmem/shmem_common.h (100%) rename {test/linux-generic => platform/linux-generic/test}/validation/api/shmem/shmem_linux.c (97%) rename {test/linux-generic => platform/linux-generic/test}/validation/api/shmem/shmem_linux.h (100%) rename {test/linux-generic => platform/linux-generic/test}/validation/api/shmem/shmem_odp1.c (100%) rename {test/linux-generic => platform/linux-generic/test}/validation/api/shmem/shmem_odp1.h (100%) rename {test/linux-generic => platform/linux-generic/test}/validation/api/shmem/shmem_odp2.c (100%) rename {test/linux-generic => platform/linux-generic/test}/validation/api/shmem/shmem_odp2.h (100%) create mode 100644 scripts/Dockerfile rename test/{common_plat => }/common/Makefile.am (82%) rename test/{common_plat => }/common/mask_common.c (100%) rename test/{common_plat => }/common/mask_common.h (100%) rename test/{common_plat => }/common/odp_cunit_common.c (100%) rename test/{common_plat => }/common/odp_cunit_common.h (100%) rename test/{linux-generic/run-test => common/run-test.sh} (100%) rename test/{ => common}/test_debug.h (100%) delete mode 100644 test/common_plat/Makefile.am delete mode 100644 test/common_plat/m4/configure.m4 delete mode 100644 test/common_plat/validation/api/Makefile.am delete mode 100644 test/common_plat/validation/api/Makefile.inc delete mode 100644 test/common_plat/validation/api/ipsec/.gitignore delete mode 100644 test/common_plat/validation/api/ipsec/Makefile.am delete mode 100644 test/common_plat/validation/api/ipsec/ipsec.c delete mode 100644 test/common_plat/validation/api/ipsec/ipsec.h delete mode 100644 test/common_plat/validation/api/ipsec/ipsec_main.c delete mode 100644 test/common_plat/validation/drv/Makefile.inc delete mode 100644 test/linux-dpdk/Makefile.am delete mode 100644 test/linux-dpdk/m4/configure.m4 delete mode 120000 test/linux-dpdk/run-test delete mode 120000 test/linux-dpdk/validation/api/pktio/.gitignore delete mode 120000 test/linux-dpdk/validation/api/pktio/pktio_env delete mode 100644 test/linux-generic/Makefile.am delete mode 100644 test/linux-generic/m4/configure.m4 delete mode 100644 test/linux-generic/validation/Makefile.inc delete mode 100644 test/linux-generic/validation/api/Makefile.inc delete mode 100644 test/linux-generic/validation/api/pktio/.gitignore rename test/{common_plat => }/m4/miscellaneous.m4 (100%) rename test/{common_plat => }/m4/performance.m4 (100%) rename test/{common_plat => }/m4/validation.m4 (96%) rename test/{common_plat => }/miscellaneous/.gitignore (100%) rename test/{common_plat => }/miscellaneous/Makefile.am (58%) rename test/{common_plat => }/miscellaneous/odp_api_from_cpp.cpp (100%) rename test/{common_plat => }/performance/.gitignore (100%) rename test/{common_plat => }/performance/Makefile.am (69%) rename test/{common_plat => }/performance/dummy_crc.h (100%) rename test/{common_plat => }/performance/odp_bench_packet.c (98%) rename test/{common_plat => }/performance/odp_crypto.c (100%) rename test/{common_plat => }/performance/odp_l2fwd.c (98%) rename test/{common_plat => }/performance/odp_l2fwd_run.sh (94%) rename test/{common_plat => }/performance/odp_pktio_ordered.c (98%) rename test/{common_plat => }/performance/odp_pktio_ordered_run.sh (100%) rename test/{common_plat => }/performance/odp_pktio_perf.c (97%) rename test/{common_plat => }/performance/odp_sched_latency.c (100%) rename test/{common_plat => }/performance/odp_sched_latency_run.sh (100%) rename test/{common_plat => }/performance/odp_scheduling.c (97%) rename test/{common_plat => }/performance/odp_scheduling_run.sh (100%) rename test/{common_plat => }/performance/udp64.pcap (100%) rename test/{common_plat => }/validation/Makefile.am (100%) rename test/{common_plat => }/validation/Makefile.inc (83%) rename test/{linux-generic => validation/api}/.gitignore (100%) create mode 100644 test/validation/api/Makefile.am create mode 100644 test/validation/api/Makefile.inc rename test/{common_plat => }/validation/api/README (100%) rename test/{common_plat => }/validation/api/atomic/.gitignore (100%) rename test/{common_plat => }/validation/api/atomic/Makefile.am (77%) rename test/{common_plat => }/validation/api/atomic/atomic.c (100%) rename test/{common_plat => }/validation/api/atomic/atomic.h (100%) rename test/{common_plat => }/validation/api/atomic/atomic_main.c (100%) rename test/{common_plat => }/validation/api/barrier/.gitignore (100%) rename test/{common_plat => }/validation/api/barrier/Makefile.am (77%) rename test/{common_plat => }/validation/api/barrier/barrier.c (100%) rename test/{common_plat => }/validation/api/barrier/barrier.h (100%) rename test/{common_plat => }/validation/api/barrier/barrier_main.c (100%) rename test/{common_plat => }/validation/api/buffer/.gitignore (100%) rename test/{common_plat => }/validation/api/buffer/Makefile.am (77%) rename test/{common_plat => }/validation/api/buffer/buffer.c (100%) rename test/{common_plat => }/validation/api/buffer/buffer.h (100%) rename test/{common_plat => }/validation/api/buffer/buffer_main.c (100%) rename test/{common_plat => }/validation/api/chksum/.gitignore (100%) rename test/{common_plat => }/validation/api/chksum/Makefile.am (100%) rename test/{common_plat => }/validation/api/chksum/chksum.c (100%) rename test/{common_plat => }/validation/api/chksum/chksum.h (100%) rename test/{common_plat => }/validation/api/chksum/chksum_main.c (100%) rename test/{common_plat => }/validation/api/classification/.gitignore (100%) rename test/{common_plat => }/validation/api/classification/Makefile.am (89%) rename test/{common_plat => }/validation/api/classification/classification.c (100%) rename test/{common_plat => }/validation/api/classification/classification.h (100%) rename test/{common_plat => }/validation/api/classification/classification_main.c (100%) rename test/{common_plat => }/validation/api/classification/odp_classification_basic.c (100%) rename test/{common_plat => }/validation/api/classification/odp_classification_common.c (100%) rename test/{common_plat => }/validation/api/classification/odp_classification_test_pmr.c (100%) rename test/{common_plat => }/validation/api/classification/odp_classification_tests.c (100%) rename test/{common_plat => }/validation/api/classification/odp_classification_testsuites.h (100%) rename test/{common_plat => }/validation/api/cpumask/.gitignore (100%) rename test/{common_plat => }/validation/api/cpumask/Makefile.am (80%) rename test/{common_plat => }/validation/api/cpumask/cpumask.c (100%) rename test/{common_plat => }/validation/api/cpumask/cpumask.h (100%) rename test/{common_plat => }/validation/api/cpumask/cpumask_main.c (100%) rename test/{common_plat => }/validation/api/crypto/.gitignore (100%) rename test/{common_plat => }/validation/api/crypto/Makefile.am (87%) rename test/{common_plat => }/validation/api/crypto/crypto.c (100%) rename test/{common_plat => }/validation/api/crypto/crypto.h (100%) rename test/{common_plat => }/validation/api/crypto/crypto_main.c (100%) rename test/{common_plat => }/validation/api/crypto/odp_crypto_test_inp.c (100%) rename test/{common_plat => }/validation/api/crypto/odp_crypto_test_inp.h (100%) rename test/{common_plat => }/validation/api/crypto/test_vectors.h (100%) rename test/{common_plat => }/validation/api/crypto/test_vectors_len.h (100%) rename test/{common_plat => }/validation/api/errno/.gitignore (100%) rename test/{common_plat => }/validation/api/errno/Makefile.am (77%) rename test/{common_plat => }/validation/api/errno/errno.c (100%) rename test/{common_plat => }/validation/api/errno/errno.h (100%) rename test/{common_plat => }/validation/api/errno/errno_main.c (100%) rename test/{common_plat => }/validation/api/hash/.gitignore (100%) rename test/{common_plat => }/validation/api/hash/Makefile.am (77%) rename test/{common_plat => }/validation/api/hash/hash.c (100%) rename test/{common_plat => }/validation/api/hash/hash.h (100%) rename test/{common_plat => }/validation/api/hash/hash_main.c (100%) rename test/{common_plat => }/validation/api/init/.gitignore (100%) rename test/{common_plat => }/validation/api/init/Makefile.am (85%) rename test/{common_plat => }/validation/api/init/init.c (100%) rename test/{common_plat => }/validation/api/init/init.h (100%) rename test/{common_plat => }/validation/api/init/init_main_abort.c (100%) rename test/{common_plat => }/validation/api/init/init_main_log.c (100%) rename test/{common_plat => }/validation/api/init/init_main_ok.c (100%) create mode 100644 test/validation/api/ipsec/.gitignore create mode 100644 test/validation/api/ipsec/Makefile.am create mode 100644 test/validation/api/ipsec/ipsec.c create mode 100644 test/validation/api/ipsec/ipsec.h create mode 100644 test/validation/api/ipsec/ipsec_async.c create mode 100644 test/validation/api/ipsec/ipsec_inline_in.c create mode 100644 test/validation/api/ipsec/ipsec_inline_out.c create mode 100644 test/validation/api/ipsec/ipsec_sync.c create mode 100644 test/validation/api/ipsec/ipsec_sync_in.c create mode 100644 test/validation/api/ipsec/ipsec_test_in.c create mode 100644 test/validation/api/ipsec/ipsec_test_out.c create mode 100644 test/validation/api/ipsec/test_vectors.h rename test/{common_plat => }/validation/api/lock/.gitignore (100%) rename test/{common_plat => }/validation/api/lock/Makefile.am (77%) rename test/{common_plat => }/validation/api/lock/lock.c (100%) rename test/{common_plat => }/validation/api/lock/lock.h (100%) rename test/{common_plat => }/validation/api/lock/lock_main.c (100%) rename test/{common_plat => }/validation/api/packet/.gitignore (100%) rename test/{common_plat => }/validation/api/packet/Makefile.am (77%) rename test/{common_plat => }/validation/api/packet/packet.c (98%) rename test/{common_plat => }/validation/api/packet/packet.h (100%) rename test/{common_plat => }/validation/api/packet/packet_main.c (100%) rename test/{common_plat => }/validation/api/pktio/.gitignore (100%) rename test/{common_plat => }/validation/api/pktio/Makefile.am (79%) rename test/{common_plat => }/validation/api/pktio/parser.c (100%) rename test/{common_plat => }/validation/api/pktio/parser.h (100%) rename test/{common_plat => }/validation/api/pktio/pktio.c (100%) rename test/{common_plat => }/validation/api/pktio/pktio.h (100%) rename test/{common_plat => }/validation/api/pktio/pktio_main.c (100%) rename test/{common_plat => }/validation/api/pool/.gitignore (100%) rename test/{common_plat => }/validation/api/pool/Makefile.am (77%) rename test/{common_plat => }/validation/api/pool/pool.c (100%) rename test/{common_plat => }/validation/api/pool/pool.h (100%) rename test/{common_plat => }/validation/api/pool/pool_main.c (100%) rename test/{common_plat => }/validation/api/queue/.gitignore (100%) rename test/{common_plat => }/validation/api/queue/Makefile.am (77%) rename test/{common_plat => }/validation/api/queue/queue.c (100%) rename test/{common_plat => }/validation/api/queue/queue.h (100%) rename test/{common_plat => }/validation/api/queue/queue_main.c (100%) rename test/{common_plat => }/validation/api/random/.gitignore (100%) rename test/{common_plat => }/validation/api/random/Makefile.am (77%) rename test/{common_plat => }/validation/api/random/random.c (100%) rename test/{common_plat => }/validation/api/random/random.h (100%) rename test/{common_plat => }/validation/api/random/random_main.c (100%) rename test/{common_plat => }/validation/api/scheduler/.gitignore (100%) rename test/{common_plat => }/validation/api/scheduler/Makefile.am (78%) rename test/{common_plat => }/validation/api/scheduler/scheduler.c (100%) rename test/{common_plat => }/validation/api/scheduler/scheduler.h (100%) rename test/{common_plat => }/validation/api/scheduler/scheduler_main.c (100%) rename test/{common_plat => }/validation/api/shmem/.gitignore (100%) rename test/{common_plat => }/validation/api/shmem/Makefile.am (77%) rename test/{common_plat => }/validation/api/shmem/shmem.c (97%) rename test/{common_plat => }/validation/api/shmem/shmem.h (100%) rename test/{common_plat => }/validation/api/shmem/shmem_main.c (100%) rename test/{common_plat => }/validation/api/std_clib/.gitignore (100%) rename test/{common_plat => }/validation/api/std_clib/Makefile.am (77%) rename test/{common_plat => }/validation/api/std_clib/std_clib.c (100%) rename test/{common_plat => }/validation/api/std_clib/std_clib.h (100%) rename test/{common_plat => }/validation/api/std_clib/std_clib_main.c (100%) rename test/{common_plat => }/validation/api/system/.gitignore (100%) rename test/{common_plat => }/validation/api/system/Makefile.am (77%) rename test/{common_plat => }/validation/api/system/system.c (100%) rename test/{common_plat => }/validation/api/system/system.h (100%) rename test/{common_plat => }/validation/api/system/system_main.c (100%) rename test/{common_plat => }/validation/api/thread/.gitignore (100%) rename test/{common_plat => }/validation/api/thread/Makefile.am (84%) rename test/{common_plat => }/validation/api/thread/thread.c (100%) rename test/{common_plat => }/validation/api/thread/thread.h (100%) rename test/{common_plat => }/validation/api/thread/thread_main.c (100%) rename test/{common_plat => }/validation/api/time/.gitignore (100%) rename test/{common_plat => }/validation/api/time/Makefile.am (89%) rename test/{common_plat => }/validation/api/time/time.c (100%) rename test/{common_plat => }/validation/api/time/time.sh (93%) rename test/{common_plat => }/validation/api/time/time_main.c (100%) rename test/{common_plat => }/validation/api/time/time_test.h (100%) rename test/{common_plat => }/validation/api/timer/.gitignore (100%) rename test/{common_plat => }/validation/api/timer/Makefile.am (77%) rename test/{common_plat => }/validation/api/timer/timer.c (100%) rename test/{common_plat => }/validation/api/timer/timer.h (100%) rename test/{common_plat => }/validation/api/timer/timer_main.c (100%) rename test/{common_plat => }/validation/api/traffic_mngr/.gitignore (100%) rename test/{common_plat => }/validation/api/traffic_mngr/Makefile.am (89%) rename test/{common_plat => }/validation/api/traffic_mngr/traffic_mngr.c (100%) rename test/{common_plat => }/validation/api/traffic_mngr/traffic_mngr.h (100%) rename test/{common_plat => }/validation/api/traffic_mngr/traffic_mngr.sh (93%) rename test/{common_plat => }/validation/api/traffic_mngr/traffic_mngr_main.c (100%) rename test/{linux-generic/performance => validation/drv}/.gitignore (100%) rename test/{common_plat => }/validation/drv/Makefile.am (100%) create mode 100644 test/validation/drv/Makefile.inc rename test/{common_plat => }/validation/drv/README (100%) rename test/{common_plat => }/validation/drv/drvatomic/.gitignore (100%) rename test/{common_plat => }/validation/drv/drvatomic/Makefile.am (100%) rename test/{common_plat => }/validation/drv/drvatomic/drvatomic.c (100%) rename test/{common_plat => }/validation/drv/drvatomic/drvatomic.h (100%) rename test/{common_plat => }/validation/drv/drvatomic/drvatomic_main.c (100%) rename test/{common_plat => }/validation/drv/drvdriver/.gitignore (100%) rename test/{common_plat => }/validation/drv/drvdriver/Makefile.am (100%) rename test/{common_plat => }/validation/drv/drvdriver/drvdriver_device.c (100%) rename test/{common_plat => }/validation/drv/drvdriver/drvdriver_device.h (100%) rename test/{common_plat => }/validation/drv/drvdriver/drvdriver_device_main.c (100%) rename test/{common_plat => }/validation/drv/drvdriver/drvdriver_devio.c (100%) rename test/{common_plat => }/validation/drv/drvdriver/drvdriver_devio.h (100%) rename test/{common_plat => }/validation/drv/drvdriver/drvdriver_devio_main.c (100%) rename test/{common_plat => }/validation/drv/drvdriver/drvdriver_driver.c (100%) rename test/{common_plat => }/validation/drv/drvdriver/drvdriver_driver.h (100%) rename test/{common_plat => }/validation/drv/drvdriver/drvdriver_driver_main.c (100%) rename test/{common_plat => }/validation/drv/drvdriver/drvdriver_enumr.c (100%) rename test/{common_plat => }/validation/drv/drvdriver/drvdriver_enumr.h (100%) rename test/{common_plat => }/validation/drv/drvdriver/drvdriver_enumr_class.c (100%) rename test/{common_plat => }/validation/drv/drvdriver/drvdriver_enumr_class.h (100%) rename test/{common_plat => }/validation/drv/drvdriver/drvdriver_enumr_class_main.c (100%) rename test/{common_plat => }/validation/drv/drvdriver/drvdriver_enumr_main.c (100%) rename test/{common_plat => }/validation/drv/drvshmem/.gitignore (100%) rename test/{common_plat => }/validation/drv/drvshmem/Makefile.am (100%) rename test/{common_plat => }/validation/drv/drvshmem/drvshmem.c (100%) rename test/{common_plat => }/validation/drv/drvshmem/drvshmem.h (100%) rename test/{common_plat => }/validation/drv/drvshmem/drvshmem_main.c (100%)
hooks/post-receive