From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 23C3EA0350; Mon, 22 Jun 2020 09:56:30 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id E18C61D5D9; Mon, 22 Jun 2020 09:55:50 +0200 (CEST) Received: from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129]) by dpdk.org (Postfix) with ESMTP id 0B8F21D57A for ; Mon, 22 Jun 2020 09:55:42 +0200 (CEST) Received: from Internal Mail-Server by MTLPINE1 (envelope-from talshn@mellanox.com) with SMTP; 22 Jun 2020 10:55:41 +0300 Received: from l-wincomp04-vm.labs.mlnx (l-wincomp04-vm.mtl.labs.mlnx [10.237.1.5]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id 05M7tdC8017100; Mon, 22 Jun 2020 10:55:41 +0300 From: talshn@mellanox.com To: dev@dpdk.org Cc: thomas@monjalon.net, pallavi.kadam@intel.com, dmitry.kozliuk@gmail.com, david.marchand@redhat.com, grive@u256.net, ranjit.menon@intel.com, navasile@linux.microsoft.com, harini.ramakrishnan@microsoft.com, ocardona@microsoft.com, anatoly.burakov@intel.com, fady@mellanox.com, bruce.richardson@intel.com, Tal Shnaiderman Date: Mon, 22 Jun 2020 10:55:28 +0300 Message-Id: <20200622075529.24180-9-talshn@mellanox.com> X-Mailer: git-send-email 2.16.1.windows.4 In-Reply-To: <20200622075529.24180-1-talshn@mellanox.com> References: <20200621102612.22740-2-talshn@mellanox.com> <20200622075529.24180-1-talshn@mellanox.com> Subject: [dpdk-dev] [PATCH v8 8/9] bus/pci: support Windows with bifurcated drivers X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" From: Tal Shnaiderman Uses SetupAPI.h functions to scan PCI tree. Uses DEVPKEY_Device_Numa_Node to get the PCI NUMA node. Uses SPDRP_BUSNUMBER and SPDRP_BUSNUMBER to get the BDF. scanning currently supports types RTE_KDRV_NONE. Signed-off-by: Tal Shnaiderman --- drivers/bus/pci/windows/pci.c | 246 ++++++++++++++++++++++++++- lib/librte_eal/rte_eal_exports.def | 1 + lib/librte_eal/windows/include/rte_windows.h | 1 + 3 files changed, 245 insertions(+), 3 deletions(-) diff --git a/drivers/bus/pci/windows/pci.c b/drivers/bus/pci/windows/pci.c index b1d34ae11c..ac92239520 100644 --- a/drivers/bus/pci/windows/pci.c +++ b/drivers/bus/pci/windows/pci.c @@ -1,14 +1,27 @@ /* SPDX-License-Identifier: BSD-3-Clause * Copyright 2020 Mellanox Technologies, Ltd */ +#include #include #include - -#include #include +#include #include "private.h" +#include + +#ifdef RTE_TOOLCHAIN_GCC +#include +DEFINE_DEVPROPKEY(DEVPKEY_Device_Numa_Node, 0x540b947e, 0x8b40, 0x45bc, + 0xa8, 0xa2, 0x6a, 0x0b, 0x89, 0x4c, 0xbd, 0xa2, 3); +#endif + +/* + * This code is used to simulate a PCI probe by parsing information in + * the registry hive for PCI devices. + */ + /* The functions below are not implemented on Windows, * but need to be defined for compilation purposes */ @@ -146,7 +159,6 @@ rte_pci_ioport_write(struct rte_pci_ioport *p __rte_unused, */ } - /* remap the PCI resource of a PCI device in anonymous virtual memory */ int pci_uio_remap_resource(struct rte_pci_device *dev __rte_unused) @@ -158,6 +170,195 @@ pci_uio_remap_resource(struct rte_pci_device *dev __rte_unused) */ return -1; } + +static int +get_device_pci_address(HDEVINFO dev_info, + PSP_DEVINFO_DATA device_info_data, struct rte_pci_addr *addr) +{ + BOOL res; + ULONG bus_num, dev_and_func; + + res = SetupDiGetDeviceRegistryProperty(dev_info, device_info_data, + SPDRP_BUSNUMBER, NULL, (PBYTE)&bus_num, sizeof(bus_num), NULL); + if (!res) { + RTE_LOG_WIN32_ERR( + "SetupDiGetDeviceRegistryProperty(SPDRP_BUSNUMBER)"); + return -1; + } + + res = SetupDiGetDeviceRegistryProperty(dev_info, device_info_data, + SPDRP_ADDRESS, NULL, (PBYTE)&dev_and_func, sizeof(dev_and_func), + NULL); + if (!res) { + RTE_LOG_WIN32_ERR( + "SetupDiGetDeviceRegistryProperty(SPDRP_ADDRESS)"); + return -1; + } + + addr->domain = 0; + addr->bus = bus_num; + addr->devid = dev_and_func >> 16; + addr->function = dev_and_func & 0xffff; + return 0; +} + +static int +get_device_resource_info(HDEVINFO dev_info, + PSP_DEVINFO_DATA dev_info_data, struct rte_pci_device *dev) +{ + DEVPROPTYPE property_type; + DWORD numa_node; + BOOL res; + + switch (dev->kdrv) { + case RTE_KDRV_NONE: + /* Get NUMA node using DEVPKEY_Device_Numa_Node */ + res = SetupDiGetDevicePropertyW(dev_info, dev_info_data, + &DEVPKEY_Device_Numa_Node, &property_type, + (BYTE *)&numa_node, sizeof(numa_node), NULL, 0); + if (!res) { + RTE_LOG_WIN32_ERR( + "SetupDiGetDevicePropertyW" + "(DEVPKEY_Device_Numa_Node)"); + return -1; + } + dev->device.numa_node = numa_node; + /* mem_resource - Unneeded for RTE_KDRV_NONE */ + dev->mem_resource[0].phys_addr = 0; + dev->mem_resource[0].len = 0; + dev->mem_resource[0].addr = NULL; + break; + default: + /* kernel driver type is unsupported */ + RTE_LOG(DEBUG, EAL, + "kernel driver type for PCI device " PCI_PRI_FMT "," + " is unsupported", + dev->addr.domain, dev->addr.bus, + dev->addr.devid, dev->addr.function); + return -1; + } + + return ERROR_SUCCESS; +} +/* + * get_pci_hardware_info from the SPDRP_HARDWAREID output + */ +static int +get_pci_hardware_info(const char *buf, struct rte_pci_id *pci_id) +{ + int ids = 0; + uint16_t vendor_id, device_id, subvendor_id = 0; + + ids = sscanf_s(buf, "PCI\\VEN_%x&DEV_%x&SUBSYS_%x", &vendor_id, + &device_id, &subvendor_id); + if (ids != 3) + return -1; + + pci_id->vendor_id = vendor_id; + pci_id->device_id = device_id; + pci_id->subsystem_vendor_id = subvendor_id >> 16; + pci_id->subsystem_device_id = subvendor_id & 0xffff; + return 0; +} + +static void +get_kernel_driver_type(struct rte_pci_device *dev) +{ + /* + * If another kernel driver is supported the relevant checking + * functions should be here + */ + dev->kdrv = RTE_KDRV_NONE; +} + +static int +pci_scan_one(HDEVINFO dev_info, PSP_DEVINFO_DATA device_info_data) +{ + struct rte_pci_device *dev; + int ret = -1; + + dev = malloc(sizeof(*dev)); + if (dev == NULL) { + goto end; + } + + memset(dev, 0, sizeof(*dev)); + + char pci_device_info[PATH_MAX]; + BOOL res; + struct rte_pci_addr addr; + struct rte_pci_id pci_id; + + /* Retrieve PCI device IDs */ + res = SetupDiGetDeviceRegistryPropertyA(dev_info, device_info_data, + SPDRP_HARDWAREID, NULL, (BYTE *)&pci_device_info, + sizeof(pci_device_info), NULL); + if (!res) { + RTE_LOG_WIN32_ERR( + "SetupDiGetDeviceRegistryPropertyA(SPDRP_HARDWAREID)"); + goto end; + } + + ret = get_pci_hardware_info((const char *)&pci_device_info, &pci_id); + if (ret != 0) { + /* + * We won't add this device, but we want to continue + * looking for supported devices + */ + ret = ERROR_CONTINUE; + goto end; + } + + ret = get_device_pci_address(dev_info, device_info_data, &addr); + if (ret != 0) + goto end; + + dev->addr = addr; + dev->id = pci_id; + dev->max_vfs = 0; /* TODO: get max_vfs */ + + pci_name_set(dev); + + get_kernel_driver_type(dev); + + /* get resources */ + if (get_device_resource_info(dev_info, device_info_data, dev) + != ERROR_SUCCESS) { + goto end; + } + + /* device is valid, add in list (sorted) */ + if (TAILQ_EMPTY(&rte_pci_bus.device_list)) { + rte_pci_add_device(dev); + } else { + struct rte_pci_device *dev2 = NULL; + int ret; + + TAILQ_FOREACH(dev2, &rte_pci_bus.device_list, next) { + ret = rte_pci_addr_cmp(&dev->addr, &dev2->addr); + if (ret > 0) { + continue; + } else if (ret < 0) { + rte_pci_insert_device(dev2, dev); + } else { /* already registered */ + dev2->kdrv = dev->kdrv; + dev2->max_vfs = dev->max_vfs; + memmove(dev2->mem_resource, dev->mem_resource, + sizeof(dev->mem_resource)); + free(dev); + } + return 0; + } + rte_pci_add_device(dev); + } + + return 0; +end: + if (dev) + free(dev); + return ret; +} + /* * Scan the contents of the PCI bus * and add all network class devices into the devices list. @@ -165,5 +366,44 @@ pci_uio_remap_resource(struct rte_pci_device *dev __rte_unused) int rte_pci_scan(void) { + int ret = -1; + DWORD device_index = 0, found_device = 0; + HDEVINFO dev_info; + SP_DEVINFO_DATA device_info_data; + + /* for debug purposes, PCI can be disabled */ + if (!rte_eal_has_pci()) + return 0; + + dev_info = SetupDiGetClassDevs(&GUID_DEVCLASS_NET, TEXT("PCI"), NULL, + DIGCF_PRESENT); + if (dev_info == INVALID_HANDLE_VALUE) { + RTE_LOG_WIN32_ERR("SetupDiGetClassDevs(pci_scan)"); + RTE_LOG(ERR, EAL, "Unable to enumerate PCI devices.\n"); + goto end; + } + + device_info_data.cbSize = sizeof(SP_DEVINFO_DATA); + device_index = 0; + + while (SetupDiEnumDeviceInfo(dev_info, device_index, + &device_info_data)) { + device_index++; + ret = pci_scan_one(dev_info, &device_info_data); + if (ret == ERROR_SUCCESS) + found_device++; + else if (ret != ERROR_CONTINUE) + goto end; + + memset(&device_info_data, 0, sizeof(SP_DEVINFO_DATA)); + device_info_data.cbSize = sizeof(SP_DEVINFO_DATA); + } + + RTE_LOG(DEBUG, EAL, "PCI scan found %lu devices\n", found_device); return 0; +end: + if (dev_info != INVALID_HANDLE_VALUE) + SetupDiDestroyDeviceInfoList(dev_info); + + return ret; } diff --git a/lib/librte_eal/rte_eal_exports.def b/lib/librte_eal/rte_eal_exports.def index 919a92fba9..374e654264 100644 --- a/lib/librte_eal/rte_eal_exports.def +++ b/lib/librte_eal/rte_eal_exports.def @@ -9,6 +9,7 @@ EXPORTS rte_devargs_remove rte_eal_get_configuration rte_eal_has_hugepages + rte_eal_has_pci rte_eal_init rte_eal_iova_mode rte_eal_mp_remote_launch diff --git a/lib/librte_eal/windows/include/rte_windows.h b/lib/librte_eal/windows/include/rte_windows.h index 899ed7d874..725ac4f9b2 100644 --- a/lib/librte_eal/windows/include/rte_windows.h +++ b/lib/librte_eal/windows/include/rte_windows.h @@ -25,6 +25,7 @@ #include #include #include +#include /* Have GUIDs defined. */ #ifndef INITGUID -- 2.16.1.windows.4