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