]>
git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/dpdk/drivers/bus/pci/bsd/pci.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2014 Intel Corporation
12 #include <sys/types.h>
18 #include <sys/queue.h>
20 #include <sys/ioctl.h>
21 #include <sys/pciio.h>
22 #include <dev/pci/pcireg.h>
24 #if defined(RTE_ARCH_X86)
25 #include <machine/cpufunc.h>
28 #include <rte_interrupts.h>
31 #include <rte_bus_pci.h>
32 #include <rte_common.h>
33 #include <rte_launch.h>
34 #include <rte_memory.h>
36 #include <rte_per_lcore.h>
37 #include <rte_lcore.h>
38 #include <rte_malloc.h>
39 #include <rte_string_fns.h>
40 #include <rte_debug.h>
41 #include <rte_devargs.h>
43 #include "eal_filesystem.h"
48 * PCI probing under BSD
50 * This code is used to simulate a PCI probe by parsing information in
51 * sysfs. Moreover, when a registered driver matches a device, the
52 * kernel driver currently using it is unloaded and replaced by
53 * igb_uio module, which is a very minimal userland driver for Intel
54 * network card, only providing access to PCI BAR to applications, and
55 * enabling bus master.
58 extern struct rte_pci_bus rte_pci_bus
;
62 rte_pci_map_device(struct rte_pci_device
*dev
)
66 /* try mapping the NIC resources */
68 case RTE_KDRV_NIC_UIO
:
69 /* map resources for devices that use uio */
70 ret
= pci_uio_map_resource(dev
);
74 " Not managed by a supported kernel driver, skipped\n");
82 /* Unmap pci device */
84 rte_pci_unmap_device(struct rte_pci_device
*dev
)
86 /* try unmapping the NIC resources */
88 case RTE_KDRV_NIC_UIO
:
89 /* unmap resources for devices that use uio */
90 pci_uio_unmap_resource(dev
);
94 " Not managed by a supported kernel driver, skipped\n");
100 pci_uio_free_resource(struct rte_pci_device
*dev
,
101 struct mapped_pci_resource
*uio_res
)
105 if (dev
->intr_handle
.fd
) {
106 close(dev
->intr_handle
.fd
);
107 dev
->intr_handle
.fd
= -1;
108 dev
->intr_handle
.type
= RTE_INTR_HANDLE_UNKNOWN
;
113 pci_uio_alloc_resource(struct rte_pci_device
*dev
,
114 struct mapped_pci_resource
**uio_res
)
116 char devname
[PATH_MAX
]; /* contains the /dev/uioX */
117 struct rte_pci_addr
*loc
;
121 snprintf(devname
, sizeof(devname
), "/dev/uio@pci:%u:%u:%u",
122 dev
->addr
.bus
, dev
->addr
.devid
, dev
->addr
.function
);
124 if (access(devname
, O_RDWR
) < 0) {
125 RTE_LOG(WARNING
, EAL
, " "PCI_PRI_FMT
" not managed by UIO driver, "
126 "skipping\n", loc
->domain
, loc
->bus
, loc
->devid
, loc
->function
);
130 /* save fd if in primary process */
131 dev
->intr_handle
.fd
= open(devname
, O_RDWR
);
132 if (dev
->intr_handle
.fd
< 0) {
133 RTE_LOG(ERR
, EAL
, "Cannot open %s: %s\n",
134 devname
, strerror(errno
));
137 dev
->intr_handle
.type
= RTE_INTR_HANDLE_UIO
;
139 /* allocate the mapping details for secondary processes*/
140 *uio_res
= rte_zmalloc("UIO_RES", sizeof(**uio_res
), 0);
141 if (*uio_res
== NULL
) {
143 "%s(): cannot store uio mmap details\n", __func__
);
147 strlcpy((*uio_res
)->path
, devname
, sizeof((*uio_res
)->path
));
148 memcpy(&(*uio_res
)->pci_addr
, &dev
->addr
, sizeof((*uio_res
)->pci_addr
));
153 pci_uio_free_resource(dev
, *uio_res
);
158 pci_uio_map_resource_by_index(struct rte_pci_device
*dev
, int res_idx
,
159 struct mapped_pci_resource
*uio_res
, int map_idx
)
166 struct pci_map
*maps
;
168 maps
= uio_res
->maps
;
169 devname
= uio_res
->path
;
170 pagesz
= sysconf(_SC_PAGESIZE
);
172 /* allocate memory to keep path */
173 maps
[map_idx
].path
= rte_malloc(NULL
, strlen(devname
) + 1, 0);
174 if (maps
[map_idx
].path
== NULL
) {
175 RTE_LOG(ERR
, EAL
, "Cannot allocate memory for path: %s\n",
181 * open resource file, to mmap it
183 fd
= open(devname
, O_RDWR
);
185 RTE_LOG(ERR
, EAL
, "Cannot open %s: %s\n",
186 devname
, strerror(errno
));
190 /* if matching map is found, then use it */
191 offset
= res_idx
* pagesz
;
192 mapaddr
= pci_map_resource(NULL
, fd
, (off_t
)offset
,
193 (size_t)dev
->mem_resource
[res_idx
].len
, 0);
195 if (mapaddr
== MAP_FAILED
)
198 maps
[map_idx
].phaddr
= dev
->mem_resource
[res_idx
].phys_addr
;
199 maps
[map_idx
].size
= dev
->mem_resource
[res_idx
].len
;
200 maps
[map_idx
].addr
= mapaddr
;
201 maps
[map_idx
].offset
= offset
;
202 strcpy(maps
[map_idx
].path
, devname
);
203 dev
->mem_resource
[res_idx
].addr
= mapaddr
;
208 rte_free(maps
[map_idx
].path
);
213 pci_scan_one(int dev_pci_fd
, struct pci_conf
*conf
)
215 struct rte_pci_device
*dev
;
216 struct pci_bar_io bar
;
219 dev
= malloc(sizeof(*dev
));
224 memset(dev
, 0, sizeof(*dev
));
225 dev
->device
.bus
= &rte_pci_bus
.bus
;
227 dev
->addr
.domain
= conf
->pc_sel
.pc_domain
;
228 dev
->addr
.bus
= conf
->pc_sel
.pc_bus
;
229 dev
->addr
.devid
= conf
->pc_sel
.pc_dev
;
230 dev
->addr
.function
= conf
->pc_sel
.pc_func
;
233 dev
->id
.vendor_id
= conf
->pc_vendor
;
236 dev
->id
.device_id
= conf
->pc_device
;
238 /* get subsystem_vendor id */
239 dev
->id
.subsystem_vendor_id
= conf
->pc_subvendor
;
241 /* get subsystem_device id */
242 dev
->id
.subsystem_device_id
= conf
->pc_subdevice
;
245 dev
->id
.class_id
= (conf
->pc_class
<< 16) |
246 (conf
->pc_subclass
<< 8) |
249 /* TODO: get max_vfs */
252 /* FreeBSD has no NUMA support (yet) */
253 dev
->device
.numa_node
= 0;
257 /* FreeBSD has only one pass through driver */
258 dev
->kdrv
= RTE_KDRV_NIC_UIO
;
260 /* parse resources */
261 switch (conf
->pc_hdr
& PCIM_HDRTYPE
) {
262 case PCIM_HDRTYPE_NORMAL
:
263 max
= PCIR_MAX_BAR_0
;
265 case PCIM_HDRTYPE_BRIDGE
:
266 max
= PCIR_MAX_BAR_1
;
268 case PCIM_HDRTYPE_CARDBUS
:
269 max
= PCIR_MAX_BAR_2
;
275 for (i
= 0; i
<= max
; i
++) {
276 bar
.pbi_sel
= conf
->pc_sel
;
277 bar
.pbi_reg
= PCIR_BAR(i
);
278 if (ioctl(dev_pci_fd
, PCIOCGETBAR
, &bar
) < 0)
281 dev
->mem_resource
[i
].len
= bar
.pbi_length
;
282 if (PCI_BAR_IO(bar
.pbi_base
)) {
283 dev
->mem_resource
[i
].addr
= (void *)(bar
.pbi_base
& ~((uint64_t)0xf));
286 dev
->mem_resource
[i
].phys_addr
= bar
.pbi_base
& ~((uint64_t)0xf);
289 /* device is valid, add in list (sorted) */
290 if (TAILQ_EMPTY(&rte_pci_bus
.device_list
)) {
291 rte_pci_add_device(dev
);
294 struct rte_pci_device
*dev2
= NULL
;
297 TAILQ_FOREACH(dev2
, &rte_pci_bus
.device_list
, next
) {
298 ret
= rte_pci_addr_cmp(&dev
->addr
, &dev2
->addr
);
302 rte_pci_insert_device(dev2
, dev
);
303 } else { /* already registered */
304 dev2
->kdrv
= dev
->kdrv
;
305 dev2
->max_vfs
= dev
->max_vfs
;
307 memmove(dev2
->mem_resource
,
309 sizeof(dev
->mem_resource
));
314 rte_pci_add_device(dev
);
325 * Scan the content of the PCI bus, and add the devices in the devices
326 * list. Call pci_scan_one() for each pci entry found.
332 unsigned dev_count
= 0;
333 struct pci_conf matches
[16];
334 struct pci_conf_io conf_io
= {
338 .match_buf_len
= sizeof(matches
),
339 .matches
= &matches
[0],
341 struct rte_pci_addr pci_addr
;
343 /* for debug purposes, PCI can be disabled */
344 if (!rte_eal_has_pci())
347 fd
= open("/dev/pci", O_RDONLY
);
349 RTE_LOG(ERR
, EAL
, "%s(): error opening /dev/pci\n", __func__
);
355 if (ioctl(fd
, PCIOCGETCONF
, &conf_io
) < 0) {
356 RTE_LOG(ERR
, EAL
, "%s(): error with ioctl on /dev/pci: %s\n",
357 __func__
, strerror(errno
));
361 for (i
= 0; i
< conf_io
.num_matches
; i
++) {
362 pci_addr
.domain
= matches
[i
].pc_sel
.pc_domain
;
363 pci_addr
.bus
= matches
[i
].pc_sel
.pc_bus
;
364 pci_addr
.devid
= matches
[i
].pc_sel
.pc_dev
;
365 pci_addr
.function
= matches
[i
].pc_sel
.pc_func
;
367 if (rte_pci_ignore_device(&pci_addr
))
370 if (pci_scan_one(fd
, &matches
[i
]) < 0)
374 dev_count
+= conf_io
.num_matches
;
375 } while(conf_io
.status
== PCI_GETCONF_MORE_DEVS
);
379 RTE_LOG(DEBUG
, EAL
, "PCI scan found %u devices\n", dev_count
);
389 pci_device_iommu_support_va(__rte_unused
const struct rte_pci_device
*dev
)
395 pci_device_iova_mode(const struct rte_pci_driver
*pdrv __rte_unused
,
396 const struct rte_pci_device
*pdev
)
398 /* Supports only RTE_KDRV_NIC_UIO */
399 if (pdev
->kdrv
!= RTE_KDRV_NIC_UIO
)
400 RTE_LOG(DEBUG
, EAL
, "Unsupported kernel driver? Defaulting to IOVA as 'PA'\n");
406 pci_update_device(const struct rte_pci_addr
*addr
)
409 struct pci_conf matches
[2];
410 struct pci_match_conf match
= {
412 .pc_domain
= addr
->domain
,
414 .pc_dev
= addr
->devid
,
415 .pc_func
= addr
->function
,
418 struct pci_conf_io conf_io
= {
422 .match_buf_len
= sizeof(matches
),
423 .matches
= &matches
[0],
426 fd
= open("/dev/pci", O_RDONLY
);
428 RTE_LOG(ERR
, EAL
, "%s(): error opening /dev/pci\n", __func__
);
432 if (ioctl(fd
, PCIOCGETCONF
, &conf_io
) < 0) {
433 RTE_LOG(ERR
, EAL
, "%s(): error with ioctl on /dev/pci: %s\n",
434 __func__
, strerror(errno
));
438 if (conf_io
.num_matches
!= 1)
441 if (pci_scan_one(fd
, &matches
[0]) < 0)
454 /* Read PCI config space. */
455 int rte_pci_read_config(const struct rte_pci_device
*dev
,
456 void *buf
, size_t len
, off_t offset
)
460 /* Copy Linux implementation's behaviour */
461 const int return_len
= len
;
464 .pc_domain
= dev
->addr
.domain
,
465 .pc_bus
= dev
->addr
.bus
,
466 .pc_dev
= dev
->addr
.devid
,
467 .pc_func
= dev
->addr
.function
,
472 fd
= open("/dev/pci", O_RDWR
);
474 RTE_LOG(ERR
, EAL
, "%s(): error opening /dev/pci\n", __func__
);
479 size
= (len
>= 4) ? 4 : ((len
>= 2) ? 2 : 1);
482 if (ioctl(fd
, PCIOCREAD
, &pi
) < 0)
484 memcpy(buf
, &pi
.pi_data
, size
);
486 buf
= (char *)buf
+ size
;
500 /* Write PCI config space. */
501 int rte_pci_write_config(const struct rte_pci_device
*dev
,
502 const void *buf
, size_t len
, off_t offset
)
508 .pc_domain
= dev
->addr
.domain
,
509 .pc_bus
= dev
->addr
.bus
,
510 .pc_dev
= dev
->addr
.devid
,
511 .pc_func
= dev
->addr
.function
,
514 .pi_data
= *(const uint32_t *)buf
,
518 if (len
== 3 || len
> sizeof(pi
.pi_data
)) {
519 RTE_LOG(ERR
, EAL
, "%s(): invalid pci read length\n", __func__
);
523 memcpy(&pi
.pi_data
, buf
, len
);
525 fd
= open("/dev/pci", O_RDWR
);
527 RTE_LOG(ERR
, EAL
, "%s(): error opening /dev/pci\n", __func__
);
531 if (ioctl(fd
, PCIOCWRITE
, &pi
) < 0)
544 rte_pci_ioport_map(struct rte_pci_device
*dev
, int bar
,
545 struct rte_pci_ioport
*p
)
550 #if defined(RTE_ARCH_X86)
551 case RTE_KDRV_NIC_UIO
:
552 if (rte_eal_iopl_init() != 0) {
553 RTE_LOG(ERR
, EAL
, "%s(): insufficient ioport permissions for PCI device %s\n",
554 __func__
, dev
->name
);
557 if ((uintptr_t) dev
->mem_resource
[bar
].addr
<= UINT16_MAX
) {
558 p
->base
= (uintptr_t)dev
->mem_resource
[bar
].addr
;
576 pci_uio_ioport_read(struct rte_pci_ioport
*p
,
577 void *data
, size_t len
, off_t offset
)
579 #if defined(RTE_ARCH_X86)
582 unsigned short reg
= p
->base
+ offset
;
584 for (d
= data
; len
> 0; d
+= size
, reg
+= size
, len
-= size
) {
587 *(uint32_t *)d
= inl(reg
);
588 } else if (len
>= 2) {
590 *(uint16_t *)d
= inw(reg
);
600 RTE_SET_USED(offset
);
605 rte_pci_ioport_read(struct rte_pci_ioport
*p
,
606 void *data
, size_t len
, off_t offset
)
608 switch (p
->dev
->kdrv
) {
609 case RTE_KDRV_NIC_UIO
:
610 pci_uio_ioport_read(p
, data
, len
, offset
);
618 pci_uio_ioport_write(struct rte_pci_ioport
*p
,
619 const void *data
, size_t len
, off_t offset
)
621 #if defined(RTE_ARCH_X86)
624 unsigned short reg
= p
->base
+ offset
;
626 for (s
= data
; len
> 0; s
+= size
, reg
+= size
, len
-= size
) {
629 outl(reg
, *(const uint32_t *)s
);
630 } else if (len
>= 2) {
632 outw(reg
, *(const uint16_t *)s
);
642 RTE_SET_USED(offset
);
647 rte_pci_ioport_write(struct rte_pci_ioport
*p
,
648 const void *data
, size_t len
, off_t offset
)
650 switch (p
->dev
->kdrv
) {
651 case RTE_KDRV_NIC_UIO
:
652 pci_uio_ioport_write(p
, data
, len
, offset
);
660 rte_pci_ioport_unmap(struct rte_pci_ioport
*p
)
664 switch (p
->dev
->kdrv
) {
665 #if defined(RTE_ARCH_X86)
666 case RTE_KDRV_NIC_UIO
: