From nobody Sun Oct 17 14:37:39 2021 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 9852C17F26BD; Sun, 17 Oct 2021 14:37:40 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4HXMzm2Dtnz4b6C; Sun, 17 Oct 2021 14:37:40 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 135936BB6; Sun, 17 Oct 2021 14:37:40 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 19HEbemJ074447; Sun, 17 Oct 2021 14:37:40 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 19HEbdOV074446; Sun, 17 Oct 2021 14:37:39 GMT (envelope-from git) Date: Sun, 17 Oct 2021 14:37:39 GMT Message-Id: <202110171437.19HEbdOV074446@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Jessica Clarke Subject: git: 82098c8bb5b3 - main - LinuxKPI: Support lazy BAR allocation List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: jrtc27 X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 82098c8bb5b303c7c8b48e7537fadfe74b375bd3 Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by jrtc27: URL: https://cgit.FreeBSD.org/src/commit/?id=82098c8bb5b303c7c8b48e7537fadfe74b375bd3 commit 82098c8bb5b303c7c8b48e7537fadfe74b375bd3 Author: Jessica Clarke AuthorDate: 2021-10-17 14:32:35 +0000 Commit: Jessica Clarke CommitDate: 2021-10-17 14:32:35 +0000 LinuxKPI: Support lazy BAR allocation Linux KPIs like pci_resource_start/len assume that BARs have been allocated, but FreeBSD lazily allocates BARs if it cannot allocate the firmware-allocated BARs. Thus using the Linux KPIs must force allocation of the BARs rather than returning 0 for the start and length, which can crash drm-kmod drivers that assume the BARs are valid. This is needed for the AMDGPU driver to be able to attach on SiFive's HiFive Unmatched. Reviewed by: hselasky, jhb, mav MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D32447 --- sys/compat/linuxkpi/common/include/linux/pci.h | 22 +++++++++++++++------- sys/compat/linuxkpi/common/src/linux_pci.c | 25 ++++++++++++++++++++++--- sys/dev/pci/pci.c | 2 +- sys/dev/pci/pci_private.h | 4 ++++ 4 files changed, 42 insertions(+), 11 deletions(-) diff --git a/sys/compat/linuxkpi/common/include/linux/pci.h b/sys/compat/linuxkpi/common/include/linux/pci.h index a80e6965915d..2bac82de2af5 100644 --- a/sys/compat/linuxkpi/common/include/linux/pci.h +++ b/sys/compat/linuxkpi/common/include/linux/pci.h @@ -311,19 +311,27 @@ pci_resource_type(struct pci_dev *pdev, int bar) return (SYS_RES_MEMORY); } +struct resource_list_entry *linux_pci_reserve_bar(struct pci_dev *pdev, + struct resource_list *rl, int type, int rid); + static inline struct resource_list_entry * -linux_pci_get_rle(struct pci_dev *pdev, int type, int rid) +linux_pci_get_rle(struct pci_dev *pdev, int type, int rid, bool reserve_bar) { struct pci_devinfo *dinfo; struct resource_list *rl; + struct resource_list_entry *rle; dinfo = device_get_ivars(pdev->dev.bsddev); rl = &dinfo->resources; - return resource_list_find(rl, type, rid); + rle = resource_list_find(rl, type, rid); + /* Reserve resources for this BAR if needed. */ + if (rle == NULL && reserve_bar) + rle = linux_pci_reserve_bar(pdev, rl, type, rid); + return (rle); } static inline struct resource_list_entry * -linux_pci_get_bar(struct pci_dev *pdev, int bar) +linux_pci_get_bar(struct pci_dev *pdev, int bar, bool reserve) { int type; @@ -331,7 +339,7 @@ linux_pci_get_bar(struct pci_dev *pdev, int bar) if (type < 0) return (NULL); bar = PCIR_BAR(bar); - return (linux_pci_get_rle(pdev, type, bar)); + return (linux_pci_get_rle(pdev, type, bar, reserve)); } static inline struct device * @@ -521,7 +529,7 @@ pci_release_region(struct pci_dev *pdev, int bar) struct pci_devres *dr; struct pci_mmio_region *mmio, *p; - if ((rle = linux_pci_get_bar(pdev, bar)) == NULL) + if ((rle = linux_pci_get_bar(pdev, bar, false)) == NULL) return; /* @@ -779,7 +787,7 @@ pci_enable_msix(struct pci_dev *pdev, struct msix_entry *entries, int nreq) pci_release_msi(pdev->dev.bsddev); return avail; } - rle = linux_pci_get_rle(pdev, SYS_RES_IRQ, 1); + rle = linux_pci_get_rle(pdev, SYS_RES_IRQ, 1, false); pdev->dev.irq_start = rle->start; pdev->dev.irq_end = rle->start + avail; for (i = 0; i < nreq; i++) @@ -832,7 +840,7 @@ pci_enable_msi(struct pci_dev *pdev) if ((error = -pci_alloc_msi(pdev->dev.bsddev, &avail)) != 0) return error; - rle = linux_pci_get_rle(pdev, SYS_RES_IRQ, 1); + rle = linux_pci_get_rle(pdev, SYS_RES_IRQ, 1, false); pdev->dev.irq_start = rle->start; pdev->dev.irq_end = rle->start + avail; pdev->irq = rle->start; diff --git a/sys/compat/linuxkpi/common/src/linux_pci.c b/sys/compat/linuxkpi/common/src/linux_pci.c index 44ed4b22de6f..780ba38d18dd 100644 --- a/sys/compat/linuxkpi/common/src/linux_pci.c +++ b/sys/compat/linuxkpi/common/src/linux_pci.c @@ -409,7 +409,7 @@ linux_pci_attach_device(device_t dev, struct pci_driver *pdrv, PCI_GET_ID(parent, dev, PCI_ID_RID, &rid); pdev->devfn = rid; pdev->pdrv = pdrv; - rle = linux_pci_get_rle(pdev, SYS_RES_IRQ, 0); + rle = linux_pci_get_rle(pdev, SYS_RES_IRQ, 0, false); if (rle != NULL) pdev->dev.irq = rle->start; else @@ -665,6 +665,25 @@ linux_pci_register_driver(struct pci_driver *pdrv) return (_linux_pci_register_driver(pdrv, dc)); } +struct resource_list_entry * +linux_pci_reserve_bar(struct pci_dev *pdev, struct resource_list *rl, + int type, int rid) +{ + device_t dev; + struct resource *res; + + KASSERT(type == SYS_RES_IOPORT || type == SYS_RES_MEMORY, + ("trying to reserve non-BAR type %d", type)); + + dev = pdev->pdrv != NULL && pdev->pdrv->isdrm ? + device_get_parent(pdev->dev.bsddev) : pdev->dev.bsddev; + res = pci_reserve_map(device_get_parent(dev), dev, type, &rid, 0, ~0, + 1, 1, 0); + if (res == NULL) + return (NULL); + return (resource_list_find(rl, type, rid)); +} + unsigned long pci_resource_start(struct pci_dev *pdev, int bar) { @@ -672,7 +691,7 @@ pci_resource_start(struct pci_dev *pdev, int bar) rman_res_t newstart; device_t dev; - if ((rle = linux_pci_get_bar(pdev, bar)) == NULL) + if ((rle = linux_pci_get_bar(pdev, bar, true)) == NULL) return (0); dev = pdev->pdrv != NULL && pdev->pdrv->isdrm ? device_get_parent(pdev->dev.bsddev) : pdev->dev.bsddev; @@ -689,7 +708,7 @@ pci_resource_len(struct pci_dev *pdev, int bar) { struct resource_list_entry *rle; - if ((rle = linux_pci_get_bar(pdev, bar)) == NULL) + if ((rle = linux_pci_get_bar(pdev, bar, true)) == NULL) return (0); return (rle->count); } diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index c215083d3121..702f9fc3aa05 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -5365,7 +5365,7 @@ DB_SHOW_COMMAND(pciregs, db_pci_dump) } #endif /* DDB */ -static struct resource * +struct resource * pci_reserve_map(device_t dev, device_t child, int type, int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int num, u_int flags) diff --git a/sys/dev/pci/pci_private.h b/sys/dev/pci/pci_private.h index 095f22db69a9..4c6c8ddf051a 100644 --- a/sys/dev/pci/pci_private.h +++ b/sys/dev/pci/pci_private.h @@ -163,6 +163,10 @@ void pci_read_bar(device_t dev, int reg, pci_addr_t *mapp, struct pci_map *pci_add_bar(device_t dev, int reg, pci_addr_t value, pci_addr_t size); +struct resource *pci_reserve_map(device_t dev, device_t child, int type, + int *rid, rman_res_t start, rman_res_t end, + rman_res_t count, u_int num, u_int flags); + struct resource *pci_alloc_multi_resource(device_t dev, device_t child, int type, int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_long num, u_int flags);