bus/pci: ignore missing NUMA node on Windows
[dpdk.git] / drivers / bus / pci / windows / pci.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2020 Mellanox Technologies, Ltd
3  */
4 #include <rte_windows.h>
5 #include <rte_errno.h>
6 #include <rte_log.h>
7 #include <rte_eal.h>
8
9 #include "private.h"
10 #include "pci_netuio.h"
11
12 #include <devpkey.h>
13 #include <regstr.h>
14
15 #if defined RTE_TOOLCHAIN_GCC && (__MINGW64_VERSION_MAJOR < 8)
16 #include <devpropdef.h>
17 DEFINE_DEVPROPKEY(DEVPKEY_Device_Numa_Node, 0x540b947e, 0x8b40, 0x45bc,
18         0xa8, 0xa2, 0x6a, 0x0b, 0x89, 0x4c, 0xbd, 0xa2, 3);
19 #endif
20
21 /*
22  * This code is used to simulate a PCI probe by parsing information in
23  * the registry hive for PCI devices.
24  */
25
26 /* The functions below are not implemented on Windows,
27  * but need to be defined for compilation purposes
28  */
29
30 /* Map pci device */
31 int
32 rte_pci_map_device(struct rte_pci_device *dev __rte_unused)
33 {
34         /* This function is not implemented on Windows.
35          * We really should short-circuit the call to these functions by
36          * clearing the RTE_PCI_DRV_NEED_MAPPING flag
37          * in the rte_pci_driver flags.
38          */
39         return 0;
40 }
41
42 /* Unmap pci device */
43 void
44 rte_pci_unmap_device(struct rte_pci_device *dev __rte_unused)
45 {
46         /* This function is not implemented on Windows.
47          * We really should short-circuit the call to these functions by
48          * clearing the RTE_PCI_DRV_NEED_MAPPING flag
49          * in the rte_pci_driver flags.
50          */
51 }
52
53 /* Read PCI config space. */
54 int
55 rte_pci_read_config(const struct rte_pci_device *dev __rte_unused,
56         void *buf __rte_unused, size_t len __rte_unused,
57         off_t offset __rte_unused)
58 {
59         /* This function is not implemented on Windows.
60          * We really should short-circuit the call to these functions by
61          * clearing the RTE_PCI_DRV_NEED_MAPPING flag
62          * in the rte_pci_driver flags.
63          */
64         return 0;
65 }
66
67 /* Write PCI config space. */
68 int
69 rte_pci_write_config(const struct rte_pci_device *dev __rte_unused,
70         const void *buf __rte_unused, size_t len __rte_unused,
71         off_t offset __rte_unused)
72 {
73         /* This function is not implemented on Windows.
74          * We really should short-circuit the call to these functions by
75          * clearing the RTE_PCI_DRV_NEED_MAPPING flag
76          * in the rte_pci_driver flags.
77          */
78         return 0;
79 }
80
81 enum rte_iova_mode
82 pci_device_iova_mode(const struct rte_pci_driver *pdrv __rte_unused,
83                 const struct rte_pci_device *pdev __rte_unused)
84 {
85         /* This function is not implemented on Windows.
86          * We really should short-circuit the call to these functions by
87          * clearing the RTE_PCI_DRV_NEED_MAPPING flag
88          * in the rte_pci_driver flags.
89          */
90         return RTE_IOVA_DC;
91 }
92
93 int
94 rte_pci_ioport_map(struct rte_pci_device *dev __rte_unused,
95         int bar __rte_unused, struct rte_pci_ioport *p __rte_unused)
96 {
97         /* This function is not implemented on Windows.
98          * We really should short-circuit the call to these functions by
99          * clearing the RTE_PCI_DRV_NEED_MAPPING flag
100          * in the rte_pci_driver flags.
101          */
102         return -1;
103 }
104
105
106 void
107 rte_pci_ioport_read(struct rte_pci_ioport *p __rte_unused,
108         void *data __rte_unused, size_t len __rte_unused,
109         off_t offset __rte_unused)
110 {
111         /* This function is not implemented on Windows.
112          * We really should short-circuit the call to these functions by
113          * clearing the RTE_PCI_DRV_NEED_MAPPING flag
114          * in the rte_pci_driver flags.
115          */
116 }
117
118 int
119 rte_pci_ioport_unmap(struct rte_pci_ioport *p __rte_unused)
120 {
121         /* This function is not implemented on Windows.
122          * We really should short-circuit the call to these functions by
123          * clearing the RTE_PCI_DRV_NEED_MAPPING flag
124          * in the rte_pci_driver flags.
125          */
126         return -1;
127 }
128
129 bool
130 pci_device_iommu_support_va(const struct rte_pci_device *dev __rte_unused)
131 {
132         /* This function is not implemented on Windows.
133          * We really should short-circuit the call to these functions by
134          * clearing the RTE_PCI_DRV_NEED_MAPPING flag
135          * in the rte_pci_driver flags.
136          */
137         return false;
138 }
139
140 void
141 rte_pci_ioport_write(struct rte_pci_ioport *p __rte_unused,
142                 const void *data __rte_unused, size_t len __rte_unused,
143                 off_t offset __rte_unused)
144 {
145         /* This function is not implemented on Windows.
146          * We really should short-circuit the call to these functions by
147          * clearing the RTE_PCI_DRV_NEED_MAPPING flag
148          * in the rte_pci_driver flags.
149          */
150 }
151
152 /* remap the PCI resource of a PCI device in anonymous virtual memory */
153 int
154 pci_uio_remap_resource(struct rte_pci_device *dev __rte_unused)
155 {
156         /* This function is not implemented on Windows.
157          * We really should short-circuit the call to these functions by
158          * clearing the RTE_PCI_DRV_NEED_MAPPING flag
159          * in the rte_pci_driver flags.
160          */
161         return -1;
162 }
163
164 static int
165 get_device_pci_address(HDEVINFO dev_info,
166         PSP_DEVINFO_DATA device_info_data, struct rte_pci_addr *addr)
167 {
168         BOOL  res;
169         ULONG bus_num, dev_and_func;
170
171         res = SetupDiGetDeviceRegistryProperty(dev_info, device_info_data,
172                 SPDRP_BUSNUMBER, NULL, (PBYTE)&bus_num, sizeof(bus_num), NULL);
173         if (!res) {
174                 RTE_LOG_WIN32_ERR(
175                         "SetupDiGetDeviceRegistryProperty(SPDRP_BUSNUMBER)");
176                 return -1;
177         }
178
179         res = SetupDiGetDeviceRegistryProperty(dev_info, device_info_data,
180                 SPDRP_ADDRESS, NULL, (PBYTE)&dev_and_func, sizeof(dev_and_func),
181                 NULL);
182         if (!res) {
183                 RTE_LOG_WIN32_ERR(
184                         "SetupDiGetDeviceRegistryProperty(SPDRP_ADDRESS)");
185                 return -1;
186         }
187
188         addr->domain = (bus_num >> 8) & 0xffff;
189         addr->bus = bus_num & 0xff;
190         addr->devid = dev_and_func >> 16;
191         addr->function = dev_and_func & 0xffff;
192         return 0;
193 }
194
195 static int
196 get_device_resource_info(HDEVINFO dev_info,
197         PSP_DEVINFO_DATA dev_info_data, struct rte_pci_device *dev)
198 {
199         DEVPROPTYPE property_type;
200         DWORD numa_node;
201         BOOL  res;
202         int ret;
203
204         switch (dev->kdrv) {
205         case RTE_PCI_KDRV_NONE:
206                 /* mem_resource - Unneeded for RTE_PCI_KDRV_NONE */
207                 dev->mem_resource[0].phys_addr = 0;
208                 dev->mem_resource[0].len = 0;
209                 dev->mem_resource[0].addr = NULL;
210                 break;
211         case RTE_PCI_KDRV_NIC_UIO:
212                 /* get device info from netuio kernel driver */
213                 ret = get_netuio_device_info(dev_info, dev_info_data, dev);
214                 if (ret != 0) {
215                         RTE_LOG(DEBUG, EAL,
216                                 "Could not retrieve device info for PCI device "
217                                 PCI_PRI_FMT,
218                                 dev->addr.domain, dev->addr.bus,
219                                 dev->addr.devid, dev->addr.function);
220                         return ret;
221                 }
222                 break;
223         default:
224                 /* kernel driver type is unsupported */
225                 RTE_LOG(DEBUG, EAL,
226                         "Kernel driver type for PCI device " PCI_PRI_FMT ","
227                         " is unsupported",
228                         dev->addr.domain, dev->addr.bus,
229                         dev->addr.devid, dev->addr.function);
230                 return -1;
231         }
232
233         /* Get NUMA node using DEVPKEY_Device_Numa_Node */
234         res = SetupDiGetDevicePropertyW(dev_info, dev_info_data,
235                 &DEVPKEY_Device_Numa_Node, &property_type,
236                 (BYTE *)&numa_node, sizeof(numa_node), NULL, 0);
237         if (!res) {
238                 DWORD error = GetLastError();
239                 if (error == ERROR_NOT_FOUND) {
240                         /* On older CPUs, NUMA is not bound to PCIe locality. */
241                         dev->device.numa_node = 0;
242                         return ERROR_SUCCESS;
243                 }
244                 RTE_LOG_WIN32_ERR("SetupDiGetDevicePropertyW"
245                         "(DEVPKEY_Device_Numa_Node)");
246                 return -1;
247         }
248         dev->device.numa_node = numa_node;
249
250         return ERROR_SUCCESS;
251 }
252
253 /*
254  * get string that contains the list of hardware IDs for a device
255  */
256 static int
257 get_pci_hardware_id(HDEVINFO dev_info, PSP_DEVINFO_DATA device_info_data,
258         char *pci_device_info, size_t pci_device_info_len)
259 {
260         BOOL  res;
261
262         /* Retrieve PCI device IDs */
263         res = SetupDiGetDeviceRegistryPropertyA(dev_info, device_info_data,
264                         SPDRP_HARDWAREID, NULL, (BYTE *)pci_device_info,
265                         pci_device_info_len, NULL);
266         if (!res) {
267                 RTE_LOG_WIN32_ERR(
268                         "SetupDiGetDeviceRegistryPropertyA(SPDRP_HARDWAREID)");
269                 return -1;
270         }
271
272         return 0;
273 }
274
275 /*
276  * parse the SPDRP_HARDWAREID output and assign to rte_pci_id
277  */
278 static int
279 parse_pci_hardware_id(const char *buf, struct rte_pci_id *pci_id)
280 {
281         int ids = 0;
282         uint16_t vendor_id, device_id;
283         uint32_t subvendor_id = 0;
284
285         ids = sscanf_s(buf, "PCI\\VEN_%" PRIx16 "&DEV_%" PRIx16 "&SUBSYS_%"
286                 PRIx32, &vendor_id, &device_id, &subvendor_id);
287         if (ids != 3)
288                 return -1;
289
290         pci_id->vendor_id = vendor_id;
291         pci_id->device_id = device_id;
292         pci_id->subsystem_device_id = subvendor_id >> 16;
293         pci_id->subsystem_vendor_id = subvendor_id & 0xffff;
294         return 0;
295 }
296
297 static void
298 set_kernel_driver_type(PSP_DEVINFO_DATA device_info_data,
299         struct rte_pci_device *dev)
300 {
301         /* set kernel driver type based on device class */
302         if (IsEqualGUID(&(device_info_data->ClassGuid), &GUID_DEVCLASS_NETUIO))
303                 dev->kdrv = RTE_PCI_KDRV_NIC_UIO;
304         else
305                 dev->kdrv = RTE_PCI_KDRV_NONE;
306 }
307
308 static int
309 pci_scan_one(HDEVINFO dev_info, PSP_DEVINFO_DATA device_info_data)
310 {
311         struct rte_pci_device *dev;
312         int ret = -1;
313         char  pci_device_info[REGSTR_VAL_MAX_HCID_LEN];
314         struct rte_pci_addr addr;
315         struct rte_pci_id pci_id;
316
317         dev = malloc(sizeof(*dev));
318         if (dev == NULL)
319                 goto end;
320
321         memset(dev, 0, sizeof(*dev));
322
323         ret = get_pci_hardware_id(dev_info, device_info_data,
324                 pci_device_info, sizeof(pci_device_info));
325         if (ret != 0)
326                 goto end;
327
328         ret = parse_pci_hardware_id((const char *)&pci_device_info, &pci_id);
329         if (ret != 0) {
330                 /*
331                  * We won't add this device, but we want to continue
332                  * looking for supported devices
333                  */
334                 ret = ERROR_CONTINUE;
335                 goto end;
336         }
337
338         ret = get_device_pci_address(dev_info, device_info_data, &addr);
339         if (ret != 0)
340                 goto end;
341
342         dev->addr = addr;
343         dev->id = pci_id;
344         dev->max_vfs = 0; /* TODO: get max_vfs */
345
346         pci_name_set(dev);
347
348         set_kernel_driver_type(device_info_data, dev);
349
350         /* get resources */
351         if (get_device_resource_info(dev_info, device_info_data, dev)
352                         != ERROR_SUCCESS) {
353                 goto end;
354         }
355
356         /* device is valid, add in list (sorted) */
357         if (TAILQ_EMPTY(&rte_pci_bus.device_list)) {
358                 rte_pci_add_device(dev);
359         } else {
360                 struct rte_pci_device *dev2 = NULL;
361                 int ret;
362
363                 TAILQ_FOREACH(dev2, &rte_pci_bus.device_list, next) {
364                         ret = rte_pci_addr_cmp(&dev->addr, &dev2->addr);
365                         if (ret > 0) {
366                                 continue;
367                         } else if (ret < 0) {
368                                 rte_pci_insert_device(dev2, dev);
369                         } else { /* already registered */
370                                 dev2->kdrv = dev->kdrv;
371                                 dev2->max_vfs = dev->max_vfs;
372                                 memmove(dev2->mem_resource, dev->mem_resource,
373                                         sizeof(dev->mem_resource));
374                                 free(dev);
375                         }
376                         return 0;
377                 }
378                 rte_pci_add_device(dev);
379         }
380
381         return 0;
382 end:
383         if (dev)
384                 free(dev);
385         return ret;
386 }
387
388 /*
389  * Scan the contents of the PCI bus
390  * and add all network class devices into the devices list.
391  */
392 int
393 rte_pci_scan(void)
394 {
395         int   ret = -1;
396         DWORD device_index = 0, found_device = 0;
397         HDEVINFO dev_info;
398         SP_DEVINFO_DATA device_info_data;
399
400         /* for debug purposes, PCI can be disabled */
401         if (!rte_eal_has_pci())
402                 return 0;
403
404         dev_info = SetupDiGetClassDevs(NULL, TEXT("PCI"), NULL,
405                 DIGCF_PRESENT | DIGCF_ALLCLASSES);
406         if (dev_info == INVALID_HANDLE_VALUE) {
407                 RTE_LOG_WIN32_ERR("SetupDiGetClassDevs(pci_scan)");
408                 RTE_LOG(ERR, EAL, "Unable to enumerate PCI devices.\n");
409                 goto end;
410         }
411
412         device_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
413         device_index = 0;
414
415         while (SetupDiEnumDeviceInfo(dev_info, device_index,
416             &device_info_data)) {
417                 device_index++;
418                 /* we only want to enumerate net & netuio class devices */
419                 if (IsEqualGUID(&(device_info_data.ClassGuid),
420                     &GUID_DEVCLASS_NET) ||
421                         IsEqualGUID(&(device_info_data.ClassGuid),
422                             &GUID_DEVCLASS_NETUIO)) {
423                         ret = pci_scan_one(dev_info, &device_info_data);
424                         if (ret == ERROR_SUCCESS)
425                                 found_device++;
426                         else if (ret != ERROR_CONTINUE)
427                                 goto end;
428                 }
429                 memset(&device_info_data, 0, sizeof(SP_DEVINFO_DATA));
430                 device_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
431         }
432
433         RTE_LOG(DEBUG, EAL, "PCI scan found %lu devices\n", found_device);
434         ret = 0;
435 end:
436         if (dev_info != INVALID_HANDLE_VALUE)
437                 SetupDiDestroyDeviceInfoList(dev_info);
438
439         return ret;
440 }