Module Name: src Committed By: riastradh Date: Sun Jun 23 00:53:48 UTC 2024
Modified Files: src/sys/external/bsd/drm2/linux: linux_pci.c Log Message: linux_pci: Nix pci enumeration kludges. Now that we can pass a cookie through, this stuff will be a little less fragile. To generate a diff of this commit: cvs rdiff -u -r1.28 -r1.29 src/sys/external/bsd/drm2/linux/linux_pci.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/external/bsd/drm2/linux/linux_pci.c diff -u src/sys/external/bsd/drm2/linux/linux_pci.c:1.28 src/sys/external/bsd/drm2/linux/linux_pci.c:1.29 --- src/sys/external/bsd/drm2/linux/linux_pci.c:1.28 Sun May 19 17:36:08 2024 +++ src/sys/external/bsd/drm2/linux/linux_pci.c Sun Jun 23 00:53:48 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: linux_pci.c,v 1.28 2024/05/19 17:36:08 riastradh Exp $ */ +/* $NetBSD: linux_pci.c,v 1.29 2024/06/23 00:53:48 riastradh Exp $ */ /*- * Copyright (c) 2013 The NetBSD Foundation, Inc. @@ -35,7 +35,7 @@ #endif #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux_pci.c,v 1.28 2024/05/19 17:36:08 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_pci.c,v 1.29 2024/06/23 00:53:48 riastradh Exp $"); #if NACPICA > 0 #include <dev/acpi/acpivar.h> @@ -573,24 +573,20 @@ pci_bus_alloc_resource(struct pci_bus *b return 0; } -/* - * XXX Mega-kludgerific! pci_get_bus_and_slot and pci_get_class are - * defined only for their single purposes in i915drm, in - * i915_get_bridge_dev and intel_detect_pch. We can't define them more - * generally without adapting pci_find_device (and pci_enumerate_bus - * internally) to pass a cookie through. - */ +struct pci_domain_bus_and_slot { + int domain, bus, slot; +}; static int -pci_kludgey_match_bus0_dev0_func0(const struct pci_attach_args *pa) +pci_match_domain_bus_and_slot(void *cookie, const struct pci_attach_args *pa) { + const struct pci_domain_bus_and_slot *C = cookie; - /* XXX domain */ - if (pa->pa_bus != 0) + if (pci_get_segment(pa->pa_pc) != C->domain) return 0; - if (pa->pa_device != 0) + if (pa->pa_bus != C->bus) return 0; - if (pa->pa_function != 0) + if (PCI_DEVFN(pa->pa_device, pa->pa_function) != C->slot) return 0; return 1; @@ -600,12 +596,10 @@ struct pci_dev * pci_get_domain_bus_and_slot(int domain, int bus, int slot) { struct pci_attach_args pa; + struct pci_domain_bus_and_slot context = {domain, bus, slot}, + *C = &context; - KASSERT(domain == 0); - KASSERT(bus == 0); - KASSERT(slot == PCI_DEVFN(0, 0)); - - if (!pci_find_device(&pa, &pci_kludgey_match_bus0_dev0_func0)) + if (!pci_find_device1(&pa, &pci_match_domain_bus_and_slot, C)) return NULL; struct pci_dev *const pdev = kmem_zalloc(sizeof(*pdev), KM_SLEEP); @@ -614,101 +608,59 @@ pci_get_domain_bus_and_slot(int domain, return pdev; } -static int -pci_kludgey_match_isa_bridge(const struct pci_attach_args *pa) -{ - - if (PCI_CLASS(pa->pa_class) != PCI_CLASS_BRIDGE) - return 0; - if (PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_BRIDGE_ISA) - return 0; - - return 1; -} - -static int -pci_kludgey_match_other_display(const struct pci_attach_args *pa) +void +pci_dev_put(struct pci_dev *pdev) { - if (PCI_CLASS(pa->pa_class) != PCI_CLASS_DISPLAY) - return 0; - if (PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_DISPLAY_MISC) - return 0; + if (pdev == NULL) + return; - return 1; + KASSERT(ISSET(pdev->pd_kludges, NBPCI_KLUDGE_GET_MUMBLE)); + kmem_free(pdev->bus, sizeof(*pdev->bus)); + kmem_free(pdev, sizeof(*pdev)); } -static int -pci_kludgey_match_vga_display(const struct pci_attach_args *pa) -{ - - if (PCI_CLASS(pa->pa_class) != PCI_CLASS_DISPLAY) - return 0; - if (PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_DISPLAY_VGA) - return 0; - - return 1; -} +struct pci_get_class_state { + uint32_t class_subclass_shifted; + const struct pci_dev *from; +}; static int -pci_kludgey_match_3d_display(const struct pci_attach_args *pa) +pci_get_class_match(void *cookie, const struct pci_attach_args *pa) { + struct pci_get_class_state *C = cookie; - if (PCI_CLASS(pa->pa_class) != PCI_CLASS_DISPLAY) + if (C->from) { + if ((pci_get_segment(C->from->pd_pa.pa_pc) == + pci_get_segment(pa->pa_pc)) && + C->from->pd_pa.pa_bus == pa->pa_bus && + C->from->pd_pa.pa_device == pa->pa_device && + C->from->pd_pa.pa_function == pa->pa_function) + C->from = NULL; return 0; - if (PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_DISPLAY_3D) + } + if (C->class_subclass_shifted != + (PCI_CLASS(pa->pa_class) << 8 | PCI_SUBCLASS(pa->pa_class))) return 0; return 1; } -void -pci_dev_put(struct pci_dev *pdev) -{ - - if (pdev == NULL) - return; - - KASSERT(ISSET(pdev->pd_kludges, NBPCI_KLUDGE_GET_MUMBLE)); - kmem_free(pdev->bus, sizeof(*pdev->bus)); - kmem_free(pdev, sizeof(*pdev)); -} - -struct pci_dev * /* XXX i915/amdgpu kludge */ +struct pci_dev * pci_get_class(uint32_t class_subclass_shifted, struct pci_dev *from) { + struct pci_get_class_state context = {class_subclass_shifted, from}, + *C = &context; struct pci_attach_args pa; + struct pci_dev *pdev = NULL; - if (from != NULL) { - pci_dev_put(from); - return NULL; - } - - switch (class_subclass_shifted) { - case PCI_CLASS_BRIDGE_ISA << 8: - if (!pci_find_device(&pa, &pci_kludgey_match_isa_bridge)) - return NULL; - break; - case PCI_CLASS_DISPLAY_OTHER << 8: - if (!pci_find_device(&pa, &pci_kludgey_match_other_display)) - return NULL; - break; - case PCI_CLASS_DISPLAY_VGA << 8: - if (!pci_find_device(&pa, &pci_kludgey_match_vga_display)) - return NULL; - break; - case PCI_CLASS_DISPLAY_3D << 8: - if (!pci_find_device(&pa, &pci_kludgey_match_3d_display)) - return NULL; - break; - default: - panic("unknown pci_get_class: %"PRIx32, - class_subclass_shifted); - } - - struct pci_dev *const pdev = kmem_zalloc(sizeof(*pdev), KM_SLEEP); + if (!pci_find_device1(&pa, &pci_get_class_match, C)) + goto out; + pdev = kmem_zalloc(sizeof(*pdev), KM_SLEEP); linux_pci_dev_init(pdev, NULL, NULL, &pa, NBPCI_KLUDGE_GET_MUMBLE); +out: if (from) + pci_dev_put(from); return pdev; }