ethdev: remove legacy HASH filter type support
[dpdk.git] / drivers / bus / pci / windows / pci.c
index b1d34ae..b450346 100644 (file)
@@ -1,13 +1,26 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright 2020 Mellanox Technologies, Ltd
  */
+#include <rte_windows.h>
 #include <rte_errno.h>
 #include <rte_log.h>
-
-#include <rte_string_fns.h>
-#include <rte_eal_memconfig.h>
+#include <rte_eal.h>
 
 #include "private.h"
+#include "pci_netuio.h"
+
+#include <devpkey.h>
+
+#ifdef RTE_TOOLCHAIN_GCC
+#include <devpropdef.h>
+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
@@ -36,17 +49,6 @@ rte_pci_unmap_device(struct rte_pci_device *dev __rte_unused)
         */
 }
 
-int
-pci_update_device(const struct rte_pci_addr *addr __rte_unused)
-{
-       /* This function is not implemented on Windows.
-        * We really should short-circuit the call to these functions by
-        * clearing the RTE_PCI_DRV_NEED_MAPPING flag
-        * in the rte_pci_driver flags.
-        */
-       return 0;
-}
-
 /* Read PCI config space. */
 int
 rte_pci_read_config(const struct rte_pci_device *dev __rte_unused,
@@ -146,7 +148,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 +159,225 @@ 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 = (bus_num >> 8) & 0xffff;
+       addr->bus = bus_num & 0xff;
+       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;
+       int ret;
+
+       switch (dev->kdrv) {
+       case RTE_PCI_KDRV_NONE:
+               /* mem_resource - Unneeded for RTE_PCI_KDRV_NONE */
+               dev->mem_resource[0].phys_addr = 0;
+               dev->mem_resource[0].len = 0;
+               dev->mem_resource[0].addr = NULL;
+               break;
+       case RTE_PCI_KDRV_NIC_UIO:
+               /* get device info from netuio kernel driver */
+               ret = get_netuio_device_info(dev_info, dev_info_data, dev);
+               if (ret != 0) {
+                       RTE_LOG(DEBUG, EAL,
+                               "Could not retrieve device info for PCI device "
+                               PCI_PRI_FMT,
+                               dev->addr.domain, dev->addr.bus,
+                               dev->addr.devid, dev->addr.function);
+                       return ret;
+               }
+               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;
+       }
+
+       /* 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;
+
+       return ERROR_SUCCESS;
+}
+
+/*
+ * get string that contains the list of hardware IDs for a device
+ */
+static int
+get_pci_hardware_id(HDEVINFO dev_info, PSP_DEVINFO_DATA device_info_data,
+       char *pci_device_info, size_t pci_device_info_len)
+{
+       BOOL  res;
+
+       /* Retrieve PCI device IDs */
+       res = SetupDiGetDeviceRegistryPropertyA(dev_info, device_info_data,
+                       SPDRP_HARDWAREID, NULL, (BYTE *)pci_device_info,
+                       pci_device_info_len, NULL);
+       if (!res) {
+               RTE_LOG_WIN32_ERR(
+                       "SetupDiGetDeviceRegistryPropertyA(SPDRP_HARDWAREID)");
+               return -1;
+       }
+
+       return 0;
+}
+
+/*
+ * parse the SPDRP_HARDWAREID output and assign to rte_pci_id
+ */
+static int
+parse_pci_hardware_id(const char *buf, struct rte_pci_id *pci_id)
+{
+       int ids = 0;
+       uint16_t vendor_id, device_id;
+       uint32_t subvendor_id = 0;
+
+       ids = sscanf_s(buf, "PCI\\VEN_%" PRIx16 "&DEV_%" PRIx16 "&SUBSYS_%"
+               PRIx32, &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_device_id = subvendor_id >> 16;
+       pci_id->subsystem_vendor_id = subvendor_id & 0xffff;
+       return 0;
+}
+
+static void
+set_kernel_driver_type(PSP_DEVINFO_DATA device_info_data,
+       struct rte_pci_device *dev)
+{
+       /* set kernel driver type based on device class */
+       if (IsEqualGUID(&(device_info_data->ClassGuid), &GUID_DEVCLASS_NETUIO))
+               dev->kdrv = RTE_PCI_KDRV_NIC_UIO;
+       else
+               dev->kdrv = RTE_PCI_KDRV_NONE;
+}
+
+static int
+pci_scan_one(HDEVINFO dev_info, PSP_DEVINFO_DATA device_info_data)
+{
+       struct rte_pci_device *dev;
+       int ret = -1;
+       char  pci_device_info[PATH_MAX];
+       struct rte_pci_addr addr;
+       struct rte_pci_id pci_id;
+
+       dev = malloc(sizeof(*dev));
+       if (dev == NULL)
+               goto end;
+
+       memset(dev, 0, sizeof(*dev));
+
+       ret = get_pci_hardware_id(dev_info, device_info_data,
+               pci_device_info, PATH_MAX);
+       if (ret != 0)
+               goto end;
+
+       ret = parse_pci_hardware_id((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);
+
+       set_kernel_driver_type(device_info_data, 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 +385,49 @@ pci_uio_remap_resource(struct rte_pci_device *dev __rte_unused)
 int
 rte_pci_scan(void)
 {
-       return 0;
+       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(NULL, TEXT("PCI"), NULL,
+               DIGCF_PRESENT | DIGCF_ALLCLASSES);
+       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++;
+               /* we only want to enumerate net & netuio class devices */
+               if (IsEqualGUID(&(device_info_data.ClassGuid),
+                   &GUID_DEVCLASS_NET) ||
+                       IsEqualGUID(&(device_info_data.ClassGuid),
+                           &GUID_DEVCLASS_NETUIO)) {
+                       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);
+       ret = 0;
+end:
+       if (dev_info != INVALID_HANDLE_VALUE)
+               SetupDiDestroyDeviceInfoList(dev_info);
+
+       return ret;
 }