diff --git a/sys/dev/drm/i915/i915_gem_gtt.c b/sys/dev/drm/i915/i915_gem_gtt.c --- a/sys/dev/drm/i915/i915_gem_gtt.c +++ b/sys/dev/drm/i915/i915_gem_gtt.c @@ -2962,6 +2962,13 @@ int i915_gem_init_ggtt(struct drm_i915_private *dev_priv) } #ifdef __DragonFly__ + /* + * Remember the fictitious range we register below so that + * i915_ggtt_cleanup_hw() can hand it back (mirrors the radeon + * lifecycle, radeon_device.c:1493/1566). Without this, every + * driver re-attach leaks the fake vm_page array and burns one of + * the 8 global slots in drm_vm.c, until attach fails with EBUSY. + */ + dev_priv->ggtt.fictitious_registered = true; DRM_INFO("taking over the fictitious range 0x%lx-0x%lx\n", dev_priv->ggtt.gmadr.start, dev_priv->ggtt.mappable_end); vm_phys_fictitious_reg_range(dev_priv->ggtt.gmadr.start, @@ -3013,6 +3020,15 @@ void i915_ggtt_cleanup_hw(struct drm_i915_private *dev_priv) arch_phys_wc_del(ggtt->mtrr); io_mapping_fini(&ggtt->iomap); +#ifdef __DragonFly__ + /* + * All GGTT vmas have been unbound and the iomap is gone: hand the + * aperture's fictitious range back so a later re-attach (module + * reload or re-probe) gets a clean table and no leak. + */ + if (ggtt->fictitious_registered) + vm_phys_fictitious_unreg_range(ggtt->gmadr.start, + ggtt->gmadr.start + + min(ggtt->vm.total, ggtt->mappable_end)); +#endif i915_gem_cleanup_stolen(dev_priv); } diff --git a/sys/dev/drm/i915/i915_gem_gtt.h b/sys/dev/drm/i915/i915_gem_gtt.h --- a/sys/dev/drm/i915/i915_gem_gtt.h +++ b/sys/dev/drm/i915/i915_gem_gtt.h @@ -398,6 +398,10 @@ struct i915_ggtt { bool do_idle_maps; +#ifdef __DragonFly__ + bool fictitious_registered; +#endif + int mtrr; u32 pin_bias;