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