Page MenuHomeFreeBSD

vga_pci: Permit child devices to allocate non-standard BARs
Needs ReviewPublic

Authored by jhb on Tue, Nov 11, 8:43 PM.
Tags
None
Referenced Files
F135689735: D53702.id166268.diff
Tue, Nov 11, 10:21 PM
F135689326: D53702.id.diff
Tue, Nov 11, 10:18 PM
F135688184: D53702.diff
Tue, Nov 11, 10:06 PM
Subscribers

Details

Reviewers
dumbbell
jrtc27
Summary

Pass through requests for non-standard BARs to the PCI bus layer. This
doesn't cache such resources so only one child device can allocate them
at a time.

Fixes: e8b145c2ba74 ("The recent PCI resource allocation ...")

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped
Build Status
Buildable 68560
Build 65443: arc lint + arc unit

Event Timeline

jhb requested review of this revision.Tue, Nov 11, 8:43 PM

This is probably the root cause of the manual BUS_ALLOC_RESOURCE call in drm-kmod I encountered in D53402. Presumably I'll have to bump __FreeBSD_version for this fix, but once this fix is in, intel_alloc_mchbar_resource should in theory be something like this:

/* Allocate space for the MCH regs if needed, return nonzero on error */
static int
intel_alloc_mchbar_resource(struct drm_i915_private *i915)
{
        int reg = GRAPHICS_VER(i915) >= 4 ? MCHBAR_I965 : MCHBAR_I915;
#if defined(__FreeBSD) && defined(__have_vga_pci_fix)
        struct resource *res;

        i915->mch_res_rid = reg;
        res = bus_alloc_resource_any(
            i915->drm.dev->bsddev, SYS_RES_MEMORY, &i915->mch_res_rid, RF_ACTIVE);
        if (i915->mch_res_bsd_res == NULL)
            return -ENOMEM;
        i915->mch_res_bsd_res = res;
        i915->gmch.mch_res.start = rman_get_start(res);
        i915->gmch.mch_res.end = rman_get_end(res);
        return 0;
#else
        u32 temp_lo, temp_hi = 0;
        u64 mchbar_addr;
        int ret;

        if (GRAPHICS_VER(i915) >= 4)
                pci_read_config_dword(i915->gmch.pdev, reg + 4, &temp_hi);
        pci_read_config_dword(i915->gmch.pdev, reg, &temp_lo);
        mchbar_addr = ((u64)temp_hi << 32) | temp_lo;

        /* If ACPI doesn't have it, assume we need to allocate it ourselves */
#ifdef __linux__
        /* CONFIG_PNP is disabled in kconfig.mk */
        if (IS_ENABLED(CONFIG_PNP) && mchbar_addr &&
            pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE))
                return 0;
#endif

        /* Get some space for it */
#ifdef __FreeBSD__
        ret = 0;
        i915->mch_res_rid = 0x100;
        i915->mch_res_bsd_res = bsd_intel_pci_bus_alloc_mem(
            i915->drm.dev->bsddev, &i915->mch_res_rid, MCHBAR_SIZE,
            &i915->gmch.mch_res.start, &i915->gmch.mch_res.end);
        if (i915->mch_res_bsd_res == NULL)
                ret = -ENOMEM;
#else
        i915->gmch.mch_res.name = "i915 MCHBAR";
        i915->gmch.mch_res.flags = IORESOURCE_MEM;
        ret = pci_bus_alloc_resource(i915->gmch.pdev->bus,
                                     &i915->gmch.mch_res,
                                     MCHBAR_SIZE, MCHBAR_SIZE,
                                     PCIBIOS_MIN_MEM,
                                     0, pcibios_align_resource,
                                     i915->gmch.pdev);
#endif
         if (ret) {
                drm_dbg(&i915->drm, "failed bus alloc: %d\n", ret);
                i915->gmch.mch_res.start = 0;
                return ret;
        }

        if (GRAPHICS_VER(i915) >= 4)
                pci_write_config_dword(i915->gmch.pdev, reg + 4,
                                       upper_32_bits(i915->gmch.mch_res.start));

        pci_write_config_dword(i915->gmch.pdev, reg,
                               lower_32_bits(i915->gmch.mch_res.start));
        return 0;
#endif
}

That is, FreeBSD's PCI bus driver understands BARs at non-standard locations and will size the BAR and update the BAR with the allocated space, etc. automatically. There's no need to dink around with adjusting the BAR by hand. You could then also just #ifdef-out bsd_intel_pci_bus_alloc_mem on systems without the vga_pci fix. If it makes it easier, we could land this set of changes first (and the vga_pci change is easy to MFC) before I land my BUS_ALLOC_RESOURCE change.