From 465fa37b7cd1633d94369655d9c537f30a63cf29 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Fran=C3=A7ois=20Tigeot?= Date: Tue, 27 Aug 2019 23:51:51 +0200 Subject: [PATCH] drm: Enable drm_pcie_get_max_link_width() Partially obtained from FreeBSD. --- sys/dev/drm/drm_pci.c | 16 ++- sys/dev/drm/include/linux/pci.h | 106 ++++++++++++++++++ sys/dev/drm/include/uapi/linux/pci.h | 4 +- .../include/uapi/linux/{pci.h => pci_regs.h} | 52 +++++++-- sys/dev/video/vga/Makefile | 1 + 5 files changed, 168 insertions(+), 11 deletions(-) copy sys/dev/drm/include/uapi/linux/{pci.h => pci_regs.h} (58%) diff --git a/sys/dev/drm/drm_pci.c b/sys/dev/drm/drm_pci.c index 94909c9565..29441a48f7 100644 --- a/sys/dev/drm/drm_pci.c +++ b/sys/dev/drm/drm_pci.c @@ -438,11 +438,22 @@ int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *mask) } EXPORT_SYMBOL(drm_pcie_get_speed_cap_mask); -#if 0 +static int +pcie_capability_read_dword(struct pci_dev *dev, int pos, u32 *dst) +{ + if (pos & 3) + return -EINVAL; + + if (!pcie_capability_reg_implemented(dev, pos)) + return -EINVAL; + + return pci_read_config_dword(dev, pci_pcie_cap(dev) + pos, dst); +} + int drm_pcie_get_max_link_width(struct drm_device *dev, u32 *mlw) { struct pci_dev *root; - u32 lnkcap; + u32 lnkcap = 0; *mlw = 0; if (!dev->pdev) @@ -458,7 +469,6 @@ int drm_pcie_get_max_link_width(struct drm_device *dev, u32 *mlw) return 0; } EXPORT_SYMBOL(drm_pcie_get_max_link_width); -#endif #else diff --git a/sys/dev/drm/include/linux/pci.h b/sys/dev/drm/include/linux/pci.h index 6c84312886..4504f8e74f 100644 --- a/sys/dev/drm/include/linux/pci.h +++ b/sys/dev/drm/include/linux/pci.h @@ -361,4 +361,110 @@ pci_pcie_cap(struct pci_dev *pdev) /* DRM_MAX_PCI_RESOURCE */ #define DEVICE_COUNT_RESOURCE 6 +#include + +/* From FreeBSD */ +static inline bool pcie_cap_has_devctl(const struct pci_dev *dev) +{ + return true; +} + +static inline int +pci_find_capability(struct pci_dev *pdev, int capid) +{ + int reg; + + if (pci_find_extcap(pdev->dev.bsddev, capid, ®)) + return (0); + return (reg); +} + +static inline u16 pcie_flags_reg(struct pci_dev *dev) +{ + int pos; + u16 reg16; + + pos = pci_find_capability(dev, PCI_CAP_ID_EXP); + if (!pos) + return 0; + + pci_read_config_word(dev, pos + PCI_EXP_FLAGS, ®16); + + return reg16; +} + +static inline int pci_pcie_type(struct pci_dev *dev) +{ + return (pcie_flags_reg(dev) & PCI_EXP_FLAGS_TYPE) >> 4; +} + + +static inline int pcie_cap_version(struct pci_dev *dev) +{ + return pcie_flags_reg(dev) & PCI_EXP_FLAGS_VERS; +} + +static inline bool pcie_cap_has_lnkctl(struct pci_dev *dev) +{ + int type = pci_pcie_type(dev); + + return pcie_cap_version(dev) > 1 || + type == PCI_EXP_TYPE_ROOT_PORT || + type == PCI_EXP_TYPE_ENDPOINT || + type == PCI_EXP_TYPE_LEG_END; +} + +static inline bool pcie_cap_has_sltctl(struct pci_dev *dev) +{ + int type = pci_pcie_type(dev); + + return pcie_cap_version(dev) > 1 || type == PCI_EXP_TYPE_ROOT_PORT || + (type == PCI_EXP_TYPE_DOWNSTREAM && + pcie_flags_reg(dev) & PCI_EXP_FLAGS_SLOT); +} + +static inline bool pcie_cap_has_rtctl(struct pci_dev *dev) +{ + int type = pci_pcie_type(dev); + + return pcie_cap_version(dev) > 1 || type == PCI_EXP_TYPE_ROOT_PORT || + type == PCI_EXP_TYPE_RC_EC; +} + +static inline bool +pcie_capability_reg_implemented(struct pci_dev *dev, int pos) +{ + if (!pci_is_pcie(dev->dev.bsddev)) + return false; + + switch (pos) { + case PCI_EXP_FLAGS_TYPE: + return true; + case PCI_EXP_DEVCAP: + case PCI_EXP_DEVCTL: + case PCI_EXP_DEVSTA: + return pcie_cap_has_devctl(dev); + case PCI_EXP_LNKCAP: + case PCI_EXP_LNKCTL: + case PCI_EXP_LNKSTA: + return pcie_cap_has_lnkctl(dev); + case PCI_EXP_SLTCAP: + case PCI_EXP_SLTCTL: + case PCI_EXP_SLTSTA: + return pcie_cap_has_sltctl(dev); + case PCI_EXP_RTCTL: + case PCI_EXP_RTCAP: + case PCI_EXP_RTSTA: + return pcie_cap_has_rtctl(dev); + case PCI_EXP_DEVCAP2: + case PCI_EXP_DEVCTL2: + case PCI_EXP_LNKCAP2: + case PCI_EXP_LNKCTL2: + case PCI_EXP_LNKSTA2: + return pcie_cap_version(dev) > 1; + default: + return false; + } +} + #endif /* LINUX_PCI_H */ diff --git a/sys/dev/drm/include/uapi/linux/pci.h b/sys/dev/drm/include/uapi/linux/pci.h index 9d3d470873..65b1b232fe 100644 --- a/sys/dev/drm/include/uapi/linux/pci.h +++ b/sys/dev/drm/include/uapi/linux/pci.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 François Tigeot + * Copyright (c) 2018-2019 François Tigeot * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,6 +27,8 @@ #ifndef _UAPI_LINUX_PCI_H_ #define _UAPI_LINUX_PCI_H_ +#include + #define PCI_DEVFN(slot, func) ((((slot) & 0x1f) << 3) | ((func) & 0x07)) #define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f) #define PCI_FUNC(devfn) ((devfn) & 0x07) diff --git a/sys/dev/drm/include/uapi/linux/pci.h b/sys/dev/drm/include/uapi/linux/pci_regs.h similarity index 58% copy from sys/dev/drm/include/uapi/linux/pci.h copy to sys/dev/drm/include/uapi/linux/pci_regs.h index 9d3d470873..051f3e4b21 100644 --- a/sys/dev/drm/include/uapi/linux/pci.h +++ b/sys/dev/drm/include/uapi/linux/pci_regs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 François Tigeot + * Copyright (c) 2019 François Tigeot * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,11 +24,49 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef _UAPI_LINUX_PCI_H_ -#define _UAPI_LINUX_PCI_H_ +#ifndef UAPI_LINUX_PCIREGS_H +#define UAPI_LINUX_PCIREGS_H -#define PCI_DEVFN(slot, func) ((((slot) & 0x1f) << 3) | ((func) & 0x07)) -#define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f) -#define PCI_FUNC(devfn) ((devfn) & 0x07) +#define PCI_EXP_RTCAP 30 -#endif /* _UAPI_LINUX_PCI_H_ */ +#define PCI_EXP_FLAGS 2 +#define PCI_EXP_FLAGS_VERS 0x000f +#define PCI_EXP_FLAGS_TYPE 0x00f0 + +#define PCI_EXP_DEVCAP 4 + +#define PCI_EXP_LNKCAP 12 + +#define PCI_EXP_DEVCTL 8 +#define PCI_EXP_DEVCTL2 40 + +#define PCI_EXP_LNKSTA 18 +#define PCI_EXP_LNKSTA2 50 + +#define PCI_EXP_SLTCAP 20 + +#define PCI_CAP_ID_EXP 0x10 + +#define PCI_EXP_TYPE_ENDPOINT 0x0 +#define PCI_EXP_TYPE_LEG_END 0x1 +#define PCI_EXP_TYPE_ROOT_PORT 0x4 +#define PCI_EXP_TYPE_DOWNSTREAM 0x6 +#define PCI_EXP_TYPE_RC_EC 0xa + +#define PCI_EXP_SLTCTL 24 + +#define PCI_EXP_SLTSTA 26 + +#define PCI_EXP_FLAGS_SLOT 0x0100 + +#define PCI_EXP_RTCTL 28 + +#define PCI_EXP_RTSTA 32 + +#define PCI_EXP_DEVCAP2 36 + +#define PCI_EXP_LNKCAP2 44 + +#define PCI_EXP_LNKCAP_MLW 0x000003f0 + +#endif /* UAPI_LINUX_PCIREGS_H */ diff --git a/sys/dev/video/vga/Makefile b/sys/dev/video/vga/Makefile index cb8366f392..27ee20bb99 100755 --- a/sys/dev/video/vga/Makefile +++ b/sys/dev/video/vga/Makefile @@ -3,5 +3,6 @@ SRCS= vga_switcheroo.c SRCS+= device_if.h bus_if.h pci_if.h KCFLAGS+= -I${SYSDIR}/dev/drm/include +KCFLAGS+= -I${SYSDIR}/dev/drm/include/uapi .include -- 2.41.0