From nobody Sun Oct 11 13:51:33 2026 X-Original-To: dev-commits-src-main@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 4j2hpZ40M8z6vrQ0 for ; Sun, 11 Oct 2026 13:51:34 +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 "YR2" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4j2hpZ0BfDz4pMX for ; Sun, 11 Oct 2026 13:51:34 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1791726694; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=wV3QmzdVb3l+VWhZDpW+O+4bwfR3TYWw7o79LcdqneA=; b=nBP7PWAdjM2g95ecitsgsA9J2PJr8bZ0pe2hmmeaTTNgPrYaTWdzPaftAhZX+CoS/SiI1g S6soBWx1m7QfbM71mp+wOUbsdPcNwthR5zXs1kcUL9p5uPHaYuGqe2Ctju7Sl2ODHP7Wcy c15qoVc1i7UCnw/07dXm08PsEcMwtSbn0srX6F40DH3YEHLlpjC+J1qp/ykX+frEpPAIWn VscKv7TejddckUwFYhbPvrU7sowgUyhVwacnnE/qlChWC8ZLyAN5uByYRzEOi3JNbySMrq Xc9dw1r1HsN1SFFy/6RByx20z62bMMWadibVl7ZBxHaTV/osGiZyw1Ji2jwhXg== ARC-Seal: i=1; a=rsa-sha256; d=freebsd.org; s=dkim; cv=none; t=1791726694; b=AqgdMaEcLpkCCiWL4Aqv+TMGuNyRzmP+8Rcrt9FJy9/XGaXbz3+wDpI2g97Sx2tDOY6JMW Pfl9yrB/ow+e2qepro94FNC0adcCF4CW/ELU+9h2lpb2ApT35vWjPhbTAfRDfzzx0w4leJ zPt8mmlrgMcjthMKQu8x0MfSj953hGo3BsjQlJZ4HHKnU9BgHtg30FT8Um3c0bGm6gvTwi lDdjUx7uAymdy5os8/euEw2XpEW36q5oU0wsWoiZqKqF//Bm++Gv+3Gb9C9SCfWiuQVglN 3xJxpwFdfpryXpKb/AyES9RgdgZp6xfbSAegS91qnQ46sVffKYYF1OEIXTFB0A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1791726694; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=wV3QmzdVb3l+VWhZDpW+O+4bwfR3TYWw7o79LcdqneA=; b=cfNM0MzGW020hVzI0Mfaeco20zTu3iDnmiBhk2Qg7UW4EFOjCyk9YpHfrGRwV+kivGAfeZ O2HHNCKGP1uUj3Zj+/qmOSUf9Ubt9sqa7Ow8zpk/H7n0lqeO3e+mYs1WBROeCneji4ztGk GXePBnGkmCUlrvBWA/v6KxO3DsV4A1qgdLbbizjDRi6v8G0c8A0RdFrWPVpg9LhOkwx0cI OjlE94Ku6l1nYVDdSOMQnX/TEVN9mWe9f+6pOE2C+wSfSBoJMa1pnruLtvJnWcAZUubmrx deQtAWgtUzQ/DPARwQVzNFaRzsH+bQk9GzWM8W2fGYeFRSYrhA+I8IgxQeT0FQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4j2hpY4Xvdzl1y for ; Sun, 11 Oct 2026 13:51:33 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 36f87 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Sun, 11 Oct 2026 13:51:33 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Bjoern A. Zeeb Subject: git: 7c9ee41f4fe4 - main - LinuxKPI: pci: first round of file cleanup List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org List-Id: Commit messages for the main branch of the src repository List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: bz X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 7c9ee41f4fe4a6de6e5f4c3d7c3a38ff447c8cf3 Auto-Submitted: auto-generated Date: Sun, 11 Oct 2026 13:51:33 +0000 Message-Id: <6acb9465.36f87.54a5b64d@gitrepo.freebsd.org> The branch main has been updated by bz: URL: https://cgit.FreeBSD.org/src/commit/?id=7c9ee41f4fe4a6de6e5f4c3d7c3a38ff447c8cf3 commit 7c9ee41f4fe4a6de6e5f4c3d7c3a38ff447c8cf3 Author: Bjoern A. Zeeb AuthorDate: 2026-06-03 05:36:35 +0000 Commit: Bjoern A. Zeeb CommitDate: 2026-10-11 13:51:11 +0000 LinuxKPI: pci: first round of file cleanup While the multiple sections of the file are mostly clearly separated some bits were spread around. Get the device methods array to the end of the file saving us a lot of forward function delcarations and making it easier to rename them to a common lkpi_ prefix instead of linux_ showing that they are file local internal functions not part of any official LinuxKPI KPI. Sort the various lkpi_pci_* bus attachment functions together, followed by the lkpi_pci_iov_ ones. Then add the pci_[un]register_driver* driver bits. This keeps the group logically together. For the PCI functions then group the pdev allocations and free/release functions--for the two paths--together, giving them more homogeneous names and add comments to some of them so it is more clear which ones are shared ("common") and which ones belong to which code path. Move some helper function around to where they are needed now. There is still more to do for the resource section which sits somewhere in the middle but that will better be a separate pass. For the DMA and backlight parts, rename various private bits to a lkpi_ prefix as well (structures, variables, functions) away from the public linux_ prefix which should belong to the linuxolator in first place. No functional changes intended. Sponsored by: The FreeBSD Foundation MFC after: 3 days Reviewed by: dumbbell (before rebase) Differential Revision: https://reviews.freebsd.org/D57433 --- sys/compat/linuxkpi/common/src/linux_pci.c | 806 +++++++++++++++-------------- 1 file changed, 420 insertions(+), 386 deletions(-) diff --git a/sys/compat/linuxkpi/common/src/linux_pci.c b/sys/compat/linuxkpi/common/src/linux_pci.c index 6b598eb82d76..bd51082fb4d1 100644 --- a/sys/compat/linuxkpi/common/src/linux_pci.c +++ b/sys/compat/linuxkpi/common/src/linux_pci.c @@ -33,6 +33,7 @@ * (1) PCI * (2) DMA * (3) Backlight + * (4) Native bus attachment glue. */ #include @@ -97,27 +98,12 @@ /* Undef the linux function macro defined in linux/pci.h */ #undef pci_get_class -extern int linuxkpi_debug; +static void lkpi_pcim_iomap_table_release(struct device *, void *); +extern int linuxkpi_debug; SYSCTL_DECL(_compat_linuxkpi); -static counter_u64_t lkpi_pci_nseg1_fail; -SYSCTL_COUNTER_U64(_compat_linuxkpi, OID_AUTO, lkpi_pci_nseg1_fail, CTLFLAG_RD, - &lkpi_pci_nseg1_fail, "Count of busdma mapping failures of single-segment"); - -static device_probe_t linux_pci_probe; -static device_attach_t linux_pci_attach; -static device_detach_t linux_pci_detach; -static device_suspend_t linux_pci_suspend; -static device_resume_t linux_pci_resume; -static device_shutdown_t linux_pci_shutdown; -static pci_iov_init_t linux_pci_iov_init; -static pci_iov_uninit_t linux_pci_iov_uninit; -static pci_iov_add_vf_t linux_pci_iov_add_vf; -static int linux_backlight_get_status(device_t dev, struct backlight_props *props); -static int linux_backlight_update_status(device_t dev, struct backlight_props *props); -static int linux_backlight_get_info(device_t dev, struct backlight_info *info); -static void lkpi_pcim_iomap_table_release(struct device *, void *); +static device_method_t pci_methods[]; static struct list_head lkpi_pci_drivers; static struct list_head lkpi_pci_devices; @@ -128,27 +114,6 @@ static spinlock_t lkpi_pci_lock; #define LKPI_PCI_LOCK() spin_lock(&lkpi_pci_lock) #define LKPI_PCI_UNLOCK() spin_unlock(&lkpi_pci_lock) -static device_method_t pci_methods[] = { - DEVMETHOD(device_probe, linux_pci_probe), - DEVMETHOD(device_attach, linux_pci_attach), - DEVMETHOD(device_detach, linux_pci_detach), - DEVMETHOD(device_suspend, linux_pci_suspend), - DEVMETHOD(device_resume, linux_pci_resume), - DEVMETHOD(device_shutdown, linux_pci_shutdown), - DEVMETHOD(pci_iov_init, linux_pci_iov_init), - DEVMETHOD(pci_iov_uninit, linux_pci_iov_uninit), - DEVMETHOD(pci_iov_add_vf, linux_pci_iov_add_vf), - - /* Bus interface. */ - DEVMETHOD(bus_add_child, bus_generic_add_child), - - /* backlight interface */ - DEVMETHOD(backlight_update_status, linux_backlight_update_status), - DEVMETHOD(backlight_get_status, linux_backlight_get_status), - DEVMETHOD(backlight_get_info, linux_backlight_get_info), - DEVMETHOD_END -}; - const char *pci_power_names[] = { "UNKNOWN", "D0", "D1", "D2", "D3hot", "D3cold" }; @@ -176,21 +141,39 @@ struct linux_dma_priv { #define DMA_PRIV_LOCK(priv) mtx_lock(&(priv)->lock) #define DMA_PRIV_UNLOCK(priv) mtx_unlock(&(priv)->lock) -static void -lkpi_set_pcim_iomap_devres(struct pcim_iomap_devres *dr, int bar, - void *res) +static struct resource_list_entry * +lkpi_pci_reserve_bar(struct pci_dev *pdev, struct resource_list *rl, + int type, int rid) { - dr->mmio_table[bar] = (void *)rman_get_bushandle(res); - dr->res_table[bar] = res; + 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)); } -static bool -lkpi_pci_bar_id_valid(int bar) +static struct resource_list_entry * +lkpi_pci_get_rle(struct pci_dev *pdev, int type, int rid, bool reserve_bar) { - if (bar < 0 || bar > PCIR_MAX_BAR_0) - return (false); + struct pci_devinfo *dinfo; + struct resource_list *rl; + struct resource_list_entry *rle; - return (true); + dinfo = device_get_ivars(pdev->dev.bsddev); + rl = &dinfo->resources; + rle = resource_list_find(rl, type, rid); + /* Reserve resources for this BAR if needed. */ + if (rle == NULL && reserve_bar) + rle = lkpi_pci_reserve_bar(pdev, rl, type, rid); + return (rle); } static int @@ -364,12 +347,12 @@ lkpi_pci_get_device(uint32_t vendor, uint32_t device, struct pci_dev *odev) } /* - * Shared function releasing the bus resources which can be built independent - * of the way we allocate/initialization the pdev [pci_upstream_bridge(), - * pcie_find_root_port()]. + * Shared helper function releasing the bus resources which can be built + * independent of the way we allocate/initialization the pdev + * [pci_upstream_bridge(), pcie_find_root_port()]. */ static void -lkpi_pci_dev_bus_release(struct pci_dev *pdev) +lkpi_pci_dev_release_common_bus(struct pci_dev *pdev) { /* Clear the hierarchy recursively to root. */ if (pdev->bus->self != pdev) { @@ -383,9 +366,9 @@ lkpi_pci_dev_bus_release(struct pci_dev *pdev) } } -/* Release resources acquired by lkpifill_pci_dev(). */ +/* Release helper function to free resources acquired by lkpi_pci_dev_init_common(). */ static void -lkpi_pci_dev_fill_release(struct device *dev) +lkpi_pci_dev_release_common(struct device *dev) { struct pci_dev *pdev; @@ -419,6 +402,11 @@ lkpi_pci_dev_fill_release(struct device *dev) kfree(pdev->path_name); } +/* + * This is the .release function for the bus attachments + * [linux_pci_attach_device()], called when the kobj reference drops to 0. + * Note well: there should be no direct calls of this. + */ static void lkpi_pci_dev_release(struct device *dev) { @@ -445,7 +433,7 @@ lkpi_pci_dev_release(struct device *dev) */ /* Clear the hierarchy recursively to root. */ - lkpi_pci_dev_bus_release(pdev); + lkpi_pci_dev_release_common_bus(pdev); LKPI_PCI_LOCK(); list_del(&pdev->links); @@ -455,9 +443,9 @@ lkpi_pci_dev_release(struct device *dev) /* irq? */ - /* Undo lkpifill_pci_dev(). */ + /* Undo lkpi_pci_dev_init_common(). */ /* devres is gone already; went at the very top. */ - lkpi_pci_dev_fill_release(dev); + lkpi_pci_dev_release_common(dev); /* * Lastly, apply an internal hack in order to signal @@ -467,8 +455,32 @@ lkpi_pci_dev_release(struct device *dev) pdev->dev.release = NULL; } +/* + * This is the .release function for lkpinew_pci_dev(), called when the kobj + * reference drops to 0. + * Note well: there should be no direct calls of this. + */ +static void +lkpinew_pci_dev_release(struct device *dev) +{ + struct pci_dev *pdev; + + pdev = to_pci_dev(dev); + + /* The root/bus structure could be built up w/o us having asked for it. */ + lkpi_pci_dev_release_common_bus(pdev); + /* Cleanup the lkpi_pci_dev_init_common() resources. */ + lkpi_pci_dev_release_common(dev); + + free(pdev, M_DEVBUF); +} + +/* + * Helper function to iniatlize most of the pdev, dev, .. parts. + * This is share by both pdev creation code paths (bus or function call). + */ static int -lkpifill_pci_dev(device_t dev, struct pci_dev *pdev) +lkpi_pci_dev_init_common(device_t dev, struct pci_dev *pdev) { struct pci_devinfo *dinfo; int error; @@ -511,7 +523,6 @@ lkpifill_pci_dev(device_t dev, struct pci_dev *pdev) } pdev->dev.bsddev = dev; pdev->dev.parent = &linux_root_device; - pdev->dev.release = lkpi_pci_dev_release; if (pci_msi_count(dev) > 0) pdev->msi_desc = malloc(pci_msi_count(dev) * @@ -528,24 +539,8 @@ lkpifill_pci_dev(device_t dev, struct pci_dev *pdev) } /* - * This is the .release function called when the kobj reference drops to 0. - * There should be no direct calls of this. + * LinuxKPI PCI dev (pdev) creation by function call. */ -static void -lkpinew_pci_dev_release(struct device *dev) -{ - struct pci_dev *pdev; - - pdev = to_pci_dev(dev); - - /* The root/bus structure could be built up w/o us having asked for it. */ - lkpi_pci_dev_bus_release(pdev); - /* Cleanup the lkpifill_pci_dev() resources. */ - lkpi_pci_dev_fill_release(dev); - - free(pdev, M_DEVBUF); -} - struct pci_dev * lkpinew_pci_dev(device_t dev) { @@ -553,7 +548,7 @@ lkpinew_pci_dev(device_t dev) int error; pdev = malloc(sizeof(*pdev), M_DEVBUF, M_WAITOK|M_ZERO); - error = lkpifill_pci_dev(dev, pdev); + error = lkpi_pci_dev_init_common(dev, pdev); if (error != 0) { free(pdev, M_DEVBUF); return (NULL); @@ -628,76 +623,11 @@ lkpi_pci_get_slot(struct pci_bus *pbus, unsigned int devfn) return (pdev); } -static int -linux_pci_probe(device_t dev) -{ - const struct pci_device_id *id; - struct pci_driver *pdrv; - - if ((pdrv = linux_pci_find(dev, &id)) == NULL) - return (ENXIO); - if (device_get_driver(dev) != &pdrv->bsddriver) - return (ENXIO); - device_set_desc(dev, pdrv->name); - - /* Assume BSS initialized (should never return BUS_PROBE_SPECIFIC). */ - if (pdrv->bsd_probe_return == 0) - return (BUS_PROBE_DEFAULT); - else - return (pdrv->bsd_probe_return); -} - -static int -linux_pci_attach(device_t dev) -{ - const struct pci_device_id *id; - struct pci_driver *pdrv; - struct pci_dev *pdev; - - pdrv = linux_pci_find(dev, &id); - pdev = device_get_softc(dev); - - MPASS(pdrv != NULL); - MPASS(pdev != NULL); - - return (linux_pci_attach_device(dev, pdrv, id, pdev)); -} - -static 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)); -} - -static struct resource_list_entry * -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; - 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); -} +/* + * LinuxKPI PCI dev (pdev) initialization/free from the BUS functions. + */ +/* Note well: this function is public and used by, e.g. nvidia-drm. */ int linux_pci_attach_device(device_t dev, struct pci_driver *pdrv, const struct pci_device_id *id, struct pci_dev *pdev) @@ -721,9 +651,10 @@ linux_pci_attach_device(device_t dev, struct pci_driver *pdrv, device_set_ivars(dev, dinfo); } - error = lkpifill_pci_dev(dev, pdev); + error = lkpi_pci_dev_init_common(dev, pdev); if (error != 0) return (error); + pdev->dev.release = lkpi_pci_dev_release; if (isdrm) PCI_GET_ID(device_get_parent(parent), parent, PCI_ID_RID, &rid); @@ -731,7 +662,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, false); + rle = lkpi_pci_get_rle(pdev, SYS_RES_IRQ, 0, false); if (rle != NULL) pdev->dev.irq = rle->start; else @@ -778,22 +709,7 @@ out_err: return (-error); } -static int -linux_pci_detach(device_t dev) -{ - struct pci_dev *pdev; - int error; - - pdev = device_get_softc(dev); - MPASS(pdev != NULL); - - error = linux_pci_detach_device(pdev); - if (error == 0) - device_set_desc(dev, NULL); - - return (error); -} - +/* Note well: this function is public and used by, e.g. nvidia-drm. */ int linux_pci_detach_device(struct pci_dev *pdev) { @@ -804,7 +720,7 @@ linux_pci_detach_device(struct pci_dev *pdev) * We cannot do much here as almost everything will have * to happen as the last reference to the LinuxKPI device * goes away. That will call the release function, - * which lkpifill_pci_dev() set. That is were most + * which lkpi_pci_dev_init_common() set. That is were most * of the cleanup will happen. But before that give * the driver a chance to cleanup. * The big problem is that the Linux KPI does not @@ -847,6 +763,9 @@ linux_pci_detach_device(struct pci_dev *pdev) return (EBUSY); } +/* + * Devres resource functions. + */ static int lkpi_pci_disable_dev(struct device *dev) { @@ -974,6 +893,15 @@ linuxkpi_pcim_iomap_table(struct pci_dev *pdev) return (dr->mmio_table); } +static bool +lkpi_pci_bar_id_valid(int bar) +{ + if (bar < 0 || bar > PCIR_MAX_BAR_0) + return (false); + + return (true); +} + static struct resource * _lkpi_pci_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen __unused) { @@ -1045,6 +973,14 @@ linuxkpi_pci_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen) return (linuxkpi_pci_iomap_range(pdev, bar, 0, maxlen)); } +static void +lkpi_set_pcim_iomap_devres(struct pcim_iomap_devres *dr, int bar, + void *res) +{ + dr->mmio_table[bar] = (void *)rman_get_bushandle(res); + dr->res_table[bar] = res; +} + void * linuxkpi_pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen) { @@ -1162,140 +1098,9 @@ lkpi_pcim_iomap_table_release(struct device *dev, void *p) } } -static int -linux_pci_suspend(device_t dev) -{ - const struct dev_pm_ops *pmops; - struct pm_message pm = { }; - struct pci_dev *pdev; - int error; - - error = 0; - linux_set_current(curthread); - pdev = device_get_softc(dev); - pmops = pdev->pdrv->driver.pm; - - if (pdev->pdrv->suspend != NULL) - error = -pdev->pdrv->suspend(pdev, pm); - else if (pmops != NULL && pmops->suspend != NULL) { - error = -pmops->suspend(&pdev->dev); - if (error == 0 && pmops->suspend_late != NULL) - error = -pmops->suspend_late(&pdev->dev); - if (error == 0 && pmops->suspend_noirq != NULL) - error = -pmops->suspend_noirq(&pdev->dev); - } - return (error); -} - -static int -linux_pci_resume(device_t dev) -{ - const struct dev_pm_ops *pmops; - struct pci_dev *pdev; - int error; - - error = 0; - linux_set_current(curthread); - pdev = device_get_softc(dev); - pmops = pdev->pdrv->driver.pm; - - if (pdev->pdrv->resume != NULL) - error = -pdev->pdrv->resume(pdev); - else if (pmops != NULL && pmops->resume != NULL) { - if (pmops->resume_early != NULL) - error = -pmops->resume_early(&pdev->dev); - if (error == 0 && pmops->resume != NULL) - error = -pmops->resume(&pdev->dev); - } - return (error); -} - -static int -linux_pci_shutdown(device_t dev) -{ - struct pci_dev *pdev; - - linux_set_current(curthread); - pdev = device_get_softc(dev); - if (pdev->pdrv->shutdown != NULL) - pdev->pdrv->shutdown(pdev); - return (0); -} - -static int -linux_pci_iov_init(device_t dev, uint16_t num_vfs, const nvlist_t *pf_config) -{ - struct pci_dev *pdev; - int error; - - linux_set_current(curthread); - pdev = device_get_softc(dev); - if (pdev->pdrv->bsd_iov_init != NULL) - error = pdev->pdrv->bsd_iov_init(dev, num_vfs, pf_config); - else - error = EINVAL; - return (error); -} - -static void -linux_pci_iov_uninit(device_t dev) -{ - struct pci_dev *pdev; - - linux_set_current(curthread); - pdev = device_get_softc(dev); - if (pdev->pdrv->bsd_iov_uninit != NULL) - pdev->pdrv->bsd_iov_uninit(dev); -} - -static int -linux_pci_iov_add_vf(device_t dev, uint16_t vfnum, const nvlist_t *vf_config) -{ - struct pci_dev *pdev; - int error; - - linux_set_current(curthread); - pdev = device_get_softc(dev); - if (pdev->pdrv->bsd_iov_add_vf != NULL) - error = pdev->pdrv->bsd_iov_add_vf(dev, vfnum, vf_config); - else - error = EINVAL; - return (error); -} - -static int -_linux_pci_register_driver(struct pci_driver *pdrv, devclass_t dc) -{ - int error; - - linux_set_current(curthread); - LKPI_PCI_LOCK(); - list_add(&pdrv->node, &lkpi_pci_drivers); - LKPI_PCI_UNLOCK(); - if (pdrv->bsddriver.name == NULL) - pdrv->bsddriver.name = pdrv->name; - pdrv->bsddriver.methods = pci_methods; - pdrv->bsddriver.size = sizeof(struct pci_dev); - - bus_topo_lock(); - error = devclass_add_driver(dc, &pdrv->bsddriver, - BUS_PASS_DEFAULT, &pdrv->bsdclass); - bus_topo_unlock(); - return (-error); -} - -int -linux_pci_register_driver(struct pci_driver *pdrv) -{ - devclass_t dc; - - pdrv->isdrm = strcmp(pdrv->name, "drmn") == 0; - dc = pdrv->isdrm ? devclass_create("vgapci") : devclass_find("pci"); - if (dc == NULL) - return (-ENXIO); - return (_linux_pci_register_driver(pdrv, dc)); -} - +/* + * Resource functions. + */ static struct resource_list_entry * lkpi_pci_get_bar(struct pci_dev *pdev, int bar, bool reserve) { @@ -1305,7 +1110,7 @@ lkpi_pci_get_bar(struct pci_dev *pdev, int bar, bool reserve) if (type < 0) return (NULL); bar = PCIR_BAR(bar); - return (linux_pci_get_rle(pdev, type, bar, reserve)); + return (lkpi_pci_get_rle(pdev, type, bar, reserve)); } struct device * @@ -1489,57 +1294,15 @@ linuxkpi_pci_release_region(struct pci_dev *pdev, int bar) void linuxkpi_pci_release_regions(struct pci_dev *pdev) { - int i; - - for (i = 0; i <= PCIR_MAX_BAR_0; i++) - pci_release_region(pdev, i); -} - -int -linux_pci_register_drm_driver(struct pci_driver *pdrv) -{ - devclass_t dc; - - dc = devclass_create("vgapci"); - if (dc == NULL) - return (-ENXIO); - pdrv->isdrm = true; - pdrv->name = "drmn"; - return (_linux_pci_register_driver(pdrv, dc)); -} - -void -linux_pci_unregister_driver(struct pci_driver *pdrv) -{ - devclass_t bus; - - bus = devclass_find(pdrv->isdrm ? "vgapci" : "pci"); - - LKPI_PCI_LOCK(); - list_del(&pdrv->node); - LKPI_PCI_UNLOCK(); - bus_topo_lock(); - if (bus != NULL) - devclass_delete_driver(bus, &pdrv->bsddriver); - bus_topo_unlock(); -} - -void -linux_pci_unregister_drm_driver(struct pci_driver *pdrv) -{ - devclass_t bus; - - bus = devclass_find("vgapci"); + int i; - LKPI_PCI_LOCK(); - list_del(&pdrv->node); - LKPI_PCI_UNLOCK(); - bus_topo_lock(); - if (bus != NULL) - devclass_delete_driver(bus, &pdrv->bsddriver); - bus_topo_unlock(); + for (i = 0; i <= PCIR_MAX_BAR_0; i++) + pci_release_region(pdev, i); } +/* + * MSI(-X) functions. + */ int linuxkpi_pci_enable_msix(struct pci_dev *pdev, struct msix_entry *entries, int nreq) @@ -1566,7 +1329,7 @@ linuxkpi_pci_enable_msix(struct pci_dev *pdev, struct msix_entry *entries, pci_release_msi(pdev->dev.bsddev); return avail; } - rle = linux_pci_get_rle(pdev, SYS_RES_IRQ, 1, false); + rle = lkpi_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++) @@ -1599,7 +1362,7 @@ _lkpi_pci_enable_msi_range(struct pci_dev *pdev, int minvec, int maxvec) return (-ENOSPC); } - rle = linux_pci_get_rle(pdev, SYS_RES_IRQ, 1, false); + rle = lkpi_pci_get_rle(pdev, SYS_RES_IRQ, 1, false); pdev->dev.irq_start = rle->start; pdev->dev.irq_end = rle->start + nvec; pdev->irq = rle->start; @@ -1726,6 +1489,248 @@ linuxkpi_pci_unmap_rom(struct pci_dev *pdev, void *rom) vga_pci_unmap_bios(device_get_parent(dev), rom); } +/* + * device_* bus functions for PCI. + */ +static int +lkpi_pci_probe(device_t dev) +{ + const struct pci_device_id *id; + struct pci_driver *pdrv; + + if ((pdrv = linux_pci_find(dev, &id)) == NULL) + return (ENXIO); + if (device_get_driver(dev) != &pdrv->bsddriver) + return (ENXIO); + device_set_desc(dev, pdrv->name); + + /* Assume BSS initialized (should never return BUS_PROBE_SPECIFIC). */ + if (pdrv->bsd_probe_return == 0) + return (BUS_PROBE_DEFAULT); + else + return (pdrv->bsd_probe_return); +} + +static int +lkpi_pci_attach(device_t dev) +{ + const struct pci_device_id *id; + struct pci_driver *pdrv; + struct pci_dev *pdev; + + pdrv = linux_pci_find(dev, &id); + pdev = device_get_softc(dev); + + MPASS(pdrv != NULL); + MPASS(pdev != NULL); + + return (linux_pci_attach_device(dev, pdrv, id, pdev)); +} + +static int +lkpi_pci_detach(device_t dev) +{ + struct pci_dev *pdev; + int error; + + pdev = device_get_softc(dev); + MPASS(pdev != NULL); + + error = linux_pci_detach_device(pdev); + if (error == 0) + device_set_desc(dev, NULL); + + return (error); +} + +static int +lkpi_pci_suspend(device_t dev) +{ + const struct dev_pm_ops *pmops; + struct pm_message pm = { }; + struct pci_dev *pdev; + int error; + + error = 0; + linux_set_current(curthread); + pdev = device_get_softc(dev); + pmops = pdev->pdrv->driver.pm; + + if (pdev->pdrv->suspend != NULL) + error = -pdev->pdrv->suspend(pdev, pm); + else if (pmops != NULL && pmops->suspend != NULL) { + error = -pmops->suspend(&pdev->dev); + if (error == 0 && pmops->suspend_late != NULL) + error = -pmops->suspend_late(&pdev->dev); + if (error == 0 && pmops->suspend_noirq != NULL) + error = -pmops->suspend_noirq(&pdev->dev); + } + return (error); +} + +static int +lkpi_pci_resume(device_t dev) +{ + const struct dev_pm_ops *pmops; + struct pci_dev *pdev; + int error; + + error = 0; + linux_set_current(curthread); + pdev = device_get_softc(dev); + pmops = pdev->pdrv->driver.pm; + + if (pdev->pdrv->resume != NULL) + error = -pdev->pdrv->resume(pdev); + else if (pmops != NULL && pmops->resume != NULL) { + if (pmops->resume_early != NULL) + error = -pmops->resume_early(&pdev->dev); + if (error == 0 && pmops->resume != NULL) + error = -pmops->resume(&pdev->dev); + } + return (error); +} + +static int +lkpi_pci_shutdown(device_t dev) +{ + struct pci_dev *pdev; + + linux_set_current(curthread); + pdev = device_get_softc(dev); + if (pdev->pdrv->shutdown != NULL) + pdev->pdrv->shutdown(pdev); + return (0); +} + +/* + * PCI IOV bus functions. + */ +static int +lkpi_pci_iov_init(device_t dev, uint16_t num_vfs, const nvlist_t *pf_config) +{ + struct pci_dev *pdev; + int error; + + linux_set_current(curthread); + pdev = device_get_softc(dev); + if (pdev->pdrv->bsd_iov_init != NULL) + error = pdev->pdrv->bsd_iov_init(dev, num_vfs, pf_config); + else + error = EINVAL; + return (error); +} + +static void +lkpi_pci_iov_uninit(device_t dev) +{ + struct pci_dev *pdev; + + linux_set_current(curthread); + pdev = device_get_softc(dev); + if (pdev->pdrv->bsd_iov_uninit != NULL) + pdev->pdrv->bsd_iov_uninit(dev); +} + +static int +lkpi_pci_iov_add_vf(device_t dev, uint16_t vfnum, const nvlist_t *vf_config) +{ + struct pci_dev *pdev; + int error; + + linux_set_current(curthread); + pdev = device_get_softc(dev); + if (pdev->pdrv->bsd_iov_add_vf != NULL) + error = pdev->pdrv->bsd_iov_add_vf(dev, vfnum, vf_config); + else + error = EINVAL; + return (error); +} + +/* + * LinuxKPI driver (un)registration. + */ +static int +lkpi_pci_register_driver(struct pci_driver *pdrv, devclass_t dc) +{ + int error; + + linux_set_current(curthread); + LKPI_PCI_LOCK(); + list_add(&pdrv->node, &lkpi_pci_drivers); + LKPI_PCI_UNLOCK(); + if (pdrv->bsddriver.name == NULL) + pdrv->bsddriver.name = pdrv->name; + pdrv->bsddriver.methods = pci_methods; + pdrv->bsddriver.size = sizeof(struct pci_dev); + + bus_topo_lock(); + error = devclass_add_driver(dc, &pdrv->bsddriver, + BUS_PASS_DEFAULT, &pdrv->bsdclass); + bus_topo_unlock(); + return (-error); +} + +int +linux_pci_register_driver(struct pci_driver *pdrv) +{ + devclass_t dc; + + pdrv->isdrm = strcmp(pdrv->name, "drmn") == 0; + dc = pdrv->isdrm ? devclass_create("vgapci") : devclass_find("pci"); + if (dc == NULL) + return (-ENXIO); + return (lkpi_pci_register_driver(pdrv, dc)); +} + +int +linux_pci_register_drm_driver(struct pci_driver *pdrv) +{ + devclass_t dc; + + dc = devclass_create("vgapci"); + if (dc == NULL) + return (-ENXIO); + pdrv->isdrm = true; + pdrv->name = "drmn"; + return (lkpi_pci_register_driver(pdrv, dc)); +} + +void +linux_pci_unregister_driver(struct pci_driver *pdrv) +{ + devclass_t bus; + + bus = devclass_find(pdrv->isdrm ? "vgapci" : "pci"); + + LKPI_PCI_LOCK(); + list_del(&pdrv->node); + LKPI_PCI_UNLOCK(); + bus_topo_lock(); + if (bus != NULL) + devclass_delete_driver(bus, &pdrv->bsddriver); + bus_topo_unlock(); +} + +void +linux_pci_unregister_drm_driver(struct pci_driver *pdrv) +{ + devclass_t bus; + + bus = devclass_find("vgapci"); + + LKPI_PCI_LOCK(); + list_del(&pdrv->node); + LKPI_PCI_UNLOCK(); + bus_topo_lock(); + if (bus != NULL) + devclass_delete_driver(bus, &pdrv->bsddriver); + bus_topo_unlock(); +} + +/* + * PCI SYSINIT. + */ static void lkpi_pci_init(void *arg __unused) { @@ -1745,57 +1750,61 @@ SYSUNINIT(lkpi_pci_uninit, SI_SUB_DRIVERS, SI_ORDER_SECOND, lkpi_pci_uninit, NUL /* -------------------------------------------------------------------------- */ /* DMA */ +static counter_u64_t lkpi_pci_nseg1_fail; +SYSCTL_COUNTER_U64(_compat_linuxkpi, OID_AUTO, lkpi_pci_nseg1_fail, CTLFLAG_RD, + &lkpi_pci_nseg1_fail, "Count of busdma mapping failures of single-segment"); + CTASSERT(sizeof(dma_addr_t) <= sizeof(uint64_t)); -struct linux_dma_obj { +struct lkpi_dma_obj { void *vaddr; uint64_t dma_addr; bus_dmamap_t dmamap; bus_dma_tag_t dmat; }; *** 262 LINES SKIPPED ***