diff options
author | Emmanuel Vadot <manu@FreeBSD.org> | 2020-12-10 16:47:11 +0000 |
---|---|---|
committer | Emmanuel Vadot <manu@FreeBSD.org> | 2021-01-12 11:31:00 +0000 |
commit | 105a37cac76b971f7a94409fbdc4f508a7e97fa0 (patch) | |
tree | d93f05ded14b77aa8ff4a13b691c0dc611ecaf2d | |
parent | 8517a547a05209c7da2c895e2d7c296ec54dd068 (diff) | |
download | src-105a37cac76b971f7a94409fbdc4f508a7e97fa0.tar.gz src-105a37cac76b971f7a94409fbdc4f508a7e97fa0.zip |
linuxkpi: Add more pci functions needed by DRM
-pci_get_class : This function search for a matching pci device based on
the class/subclass and returns a newly created pci_dev.
- pci_{save,restore}_state : This is analogous to ours with the same name
- pci_is_root_bus : Return true if this is the root bus
- pci_get_domain_bus_and_slot : This function search for a matching pci
device based on domain, bus and slot/function concat into a single
unsigned int (devfn) and returns a newly created pci_dev
- pci_bus_{read,write}_config* : Read/Write to the config space.
While here add some helper function to alloc and fill the pci_dev struct.
Reviewed by: hselasky, bz (older version)
Differential Revision: https://reviews.freebsd.org/D27550
-rw-r--r-- | sys/compat/linuxkpi/common/include/linux/pci.h | 96 | ||||
-rw-r--r-- | sys/compat/linuxkpi/common/src/linux_pci.c | 75 | ||||
-rw-r--r-- | sys/dev/mlx4/mlx4_core/mlx4_main.c | 2 | ||||
-rw-r--r-- | sys/dev/mlx5/mlx5_core/mlx5_main.c | 6 |
4 files changed, 166 insertions, 13 deletions
diff --git a/sys/compat/linuxkpi/common/include/linux/pci.h b/sys/compat/linuxkpi/common/include/linux/pci.h index 643bc7cc2630..6338f5795f0a 100644 --- a/sys/compat/linuxkpi/common/include/linux/pci.h +++ b/sys/compat/linuxkpi/common/include/linux/pci.h @@ -460,6 +460,9 @@ linux_pci_disable_msi(struct pci_dev *pdev) pdev->msi_enabled = false; } +#define pci_free_irq_vectors(pdev) \ + linux_pci_disable_msi(pdev) + unsigned long pci_resource_start(struct pci_dev *pdev, int bar); unsigned long pci_resource_len(struct pci_dev *pdev, int bar); @@ -702,6 +705,23 @@ pci_iounmap(struct pci_dev *dev, void *res) } } +static inline void +lkpi_pci_save_state(struct pci_dev *pdev) +{ + + pci_save_state(pdev->dev.bsddev); +} + +static inline void +lkpi_pci_restore_state(struct pci_dev *pdev) +{ + + pci_restore_state(pdev->dev.bsddev); +} + +#define pci_save_state(dev) lkpi_pci_save_state(dev) +#define pci_restore_state(dev) lkpi_pci_restore_state(dev) + #define DEFINE_PCI_DEVICE_TABLE(_table) \ const struct pci_device_id _table[] __devinitdata @@ -1058,4 +1078,80 @@ pci_dev_present(const struct pci_device_id *cur) return (0); } +static inline bool +pci_is_root_bus(struct pci_bus *pbus) +{ + + return (pbus->self == NULL); +} + +struct pci_dev *lkpi_pci_get_domain_bus_and_slot(int domain, + unsigned int bus, unsigned int devfn); +#define pci_get_domain_bus_and_slot(domain, bus, devfn) \ + lkpi_pci_get_domain_bus_and_slot(domain, bus, devfn) + +static inline int +pci_domain_nr(struct pci_bus *pbus) +{ + + return (pci_get_domain(pbus->self->dev.bsddev)); +} + +static inline int +pci_bus_read_config(struct pci_bus *bus, unsigned int devfn, + int pos, uint32_t *val, int len) +{ + + *val = pci_read_config(bus->self->dev.bsddev, pos, len); + return (0); +} + +static inline int +pci_bus_read_config_word(struct pci_bus *bus, unsigned int devfn, int pos, u16 *val) +{ + uint32_t tmp; + int ret; + + ret = pci_bus_read_config(bus, devfn, pos, &tmp, 2); + *val = (u16)tmp; + return (ret); +} + +static inline int +pci_bus_read_config_byte(struct pci_bus *bus, unsigned int devfn, int pos, u8 *val) +{ + uint32_t tmp; + int ret; + + ret = pci_bus_read_config(bus, devfn, pos, &tmp, 1); + *val = (u8)tmp; + return (ret); +} + +static inline int +pci_bus_write_config(struct pci_bus *bus, unsigned int devfn, int pos, + uint32_t val, int size) +{ + + pci_write_config(bus->self->dev.bsddev, pos, val, size); + return (0); +} + +static inline int +pci_bus_write_config_byte(struct pci_bus *bus, unsigned int devfn, int pos, + uint8_t val) +{ + return (pci_bus_write_config(bus, devfn, pos, val, 1)); +} + +static inline int +pci_bus_write_config_word(struct pci_bus *bus, unsigned int devfn, int pos, + uint16_t val) +{ + return (pci_bus_write_config(bus, devfn, pos, val, 2)); +} + +struct pci_dev *lkpi_pci_get_class(unsigned int class, struct pci_dev *from); +#define pci_get_class(class, from) lkpi_pci_get_class(class, from) + #endif /* _LINUX_PCI_H_ */ diff --git a/sys/compat/linuxkpi/common/src/linux_pci.c b/sys/compat/linuxkpi/common/src/linux_pci.c index be61c2dba3d2..0e184b64884b 100644 --- a/sys/compat/linuxkpi/common/src/linux_pci.c +++ b/sys/compat/linuxkpi/common/src/linux_pci.c @@ -70,6 +70,9 @@ __FBSDID("$FreeBSD$"); #include "backlight_if.h" #include "pcib_if.h" +/* Undef the linux function macro defined in linux/pci.h */ +#undef pci_get_class + static device_probe_t linux_pci_probe; static device_attach_t linux_pci_attach; static device_detach_t linux_pci_detach; @@ -210,6 +213,67 @@ linux_pci_find(device_t dev, const struct pci_device_id **idp) return (NULL); } +static void +lkpifill_pci_dev(device_t dev, struct pci_dev *pdev) +{ + + pdev->devfn = PCI_DEVFN(pci_get_slot(dev), pci_get_function(dev)); + pdev->vendor = pci_get_vendor(dev); + pdev->device = pci_get_device(dev); + pdev->class = pci_get_class(dev); + pdev->revision = pci_get_revid(dev); + pdev->dev.bsddev = dev; + pdev->bus->self = pdev; + pdev->bus->number = pci_get_bus(dev); + pdev->bus->domain = pci_get_domain(dev); +} + +static struct pci_dev * +lkpinew_pci_dev(device_t dev) +{ + struct pci_dev *pdev; + struct pci_bus *pbus; + + pdev = malloc(sizeof(*pdev), M_DEVBUF, M_WAITOK|M_ZERO); + pbus = malloc(sizeof(*pbus), M_DEVBUF, M_WAITOK|M_ZERO); + pdev->bus = pbus; + lkpifill_pci_dev(dev, pdev); + return (pdev); +} + +struct pci_dev * +lkpi_pci_get_class(unsigned int class, struct pci_dev *from) +{ + device_t dev; + device_t devfrom = NULL; + struct pci_dev *pdev; + + if (from != NULL) + devfrom = from->dev.bsddev; + + dev = pci_find_class_from(class >> 16, (class >> 8) & 0xFF, devfrom); + if (dev == NULL) + return (NULL); + + pdev = lkpinew_pci_dev(dev); + return (pdev); +} + +struct pci_dev * +lkpi_pci_get_domain_bus_and_slot(int domain, unsigned int bus, + unsigned int devfn) +{ + device_t dev; + struct pci_dev *pdev; + + dev = pci_find_dbsf(domain, bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); + if (dev == NULL) + return (NULL); + + pdev = lkpinew_pci_dev(dev); + return (pdev); +} + static int linux_pci_probe(device_t dev) { @@ -245,7 +309,6 @@ linux_pci_attach_device(device_t dev, struct pci_driver *pdrv, const struct pci_device_id *id, struct pci_dev *pdev) { struct resource_list_entry *rle; - struct pci_bus *pbus; struct pci_devinfo *dinfo; device_t parent; uintptr_t rid; @@ -264,8 +327,9 @@ linux_pci_attach_device(device_t dev, struct pci_driver *pdrv, dinfo = device_get_ivars(dev); } + pdev->bus = malloc(sizeof(*pdev->bus), M_DEVBUF, M_WAITOK | M_ZERO); + lkpifill_pci_dev(dev, pdev); pdev->dev.parent = &linux_root_device; - pdev->dev.bsddev = dev; INIT_LIST_HEAD(&pdev->dev.irqents); if (isdrm) PCI_GET_ID(device_get_parent(parent), parent, PCI_ID_RID, &rid); @@ -276,8 +340,6 @@ linux_pci_attach_device(device_t dev, struct pci_driver *pdrv, pdev->vendor = dinfo->cfg.vendor; pdev->subsystem_vendor = dinfo->cfg.subvendor; pdev->subsystem_device = dinfo->cfg.subdevice; - pdev->class = pci_get_class(dev); - pdev->revision = pci_get_revid(dev); pdev->pdrv = pdrv; kobject_init(&pdev->dev.kobj, &linux_dev_ktype); kobject_set_name(&pdev->dev.kobj, device_get_nameunit(dev)); @@ -294,11 +356,6 @@ linux_pci_attach_device(device_t dev, struct pci_driver *pdrv, goto out_dma_init; TAILQ_INIT(&pdev->mmio); - pbus = malloc(sizeof(*pbus), M_DEVBUF, M_WAITOK | M_ZERO); - pbus->self = pdev; - pbus->number = pci_get_bus(dev); - pbus->domain = pci_get_domain(dev); - pdev->bus = pbus; spin_lock(&pci_lock); list_add(&pdev->links, &pci_devices); diff --git a/sys/dev/mlx4/mlx4_core/mlx4_main.c b/sys/dev/mlx4/mlx4_core/mlx4_main.c index ee17418388eb..48cc2fc7d3f6 100644 --- a/sys/dev/mlx4/mlx4_core/mlx4_main.c +++ b/sys/dev/mlx4/mlx4_core/mlx4_main.c @@ -3781,7 +3781,7 @@ static int mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id) return ret; } else { device_set_desc(pdev->dev.bsddev, mlx4_description); - pci_save_state(pdev->dev.bsddev); + pci_save_state(pdev); } snprintf(dev->fw_str, sizeof(dev->fw_str), "%d.%d.%d", diff --git a/sys/dev/mlx5/mlx5_core/mlx5_main.c b/sys/dev/mlx5/mlx5_core/mlx5_main.c index 27326d692261..37a55f65683c 100644 --- a/sys/dev/mlx5/mlx5_core/mlx5_main.c +++ b/sys/dev/mlx5/mlx5_core/mlx5_main.c @@ -1634,7 +1634,7 @@ static int init_one(struct pci_dev *pdev, } #endif - pci_save_state(bsddev); + pci_save_state(pdev); return 0; clean_health: @@ -1709,8 +1709,8 @@ static pci_ers_result_t mlx5_pci_slot_reset(struct pci_dev *pdev) } pci_set_master(pdev); pci_set_powerstate(pdev->dev.bsddev, PCI_POWERSTATE_D0); - pci_restore_state(pdev->dev.bsddev); - pci_save_state(pdev->dev.bsddev); + pci_restore_state(pdev); + pci_save_state(pdev); return err ? PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_RECOVERED; } |