DF-4678 / fix.diff
--- a/sys/dev/drm/i915/i915_gem_stolen.c +++ b/sys/dev/drm/i915/i915_gem_stolen.c @@ -88,14 +88,28 @@ static struct rman stolen_rman; struct linux_resource *res; - stolen_rman.rm_start = start; - stolen_rman.rm_end = start + n; - stolen_rman.rm_type = RMAN_ARRAY; - stolen_rman.rm_descr = name; - if (rman_init(&stolen_rman, -1)) - return NULL; - - if (rman_manage_region(&stolen_rman, stolen_rman.rm_start, stolen_rman.rm_end)) + /* + * NB: this shim cannot provide the Linux devm conflict check + * against other drivers; it only keeps driver-local bookkeeping. + * Initialize the static rman once (a second rman_init() would + * re-insert it into the global rman_head and leak the old lock), + * and use inclusive end bounds (rman ranges are [start, end]). + */ + static int stolen_rman_inited; + + if (!stolen_rman_inited) { + stolen_rman.rm_start = start; + stolen_rman.rm_end = start + n - 1; + stolen_rman.rm_type = RMAN_ARRAY; + stolen_rman.rm_descr = name; + if (rman_init(&stolen_rman, -1)) + return NULL; + stolen_rman_inited = 1; + } + + if (n == 0 || start + n - 1 < start) + return NULL; + if (rman_manage_region(&stolen_rman, start, start + n - 1)) return NULL; res = kmalloc(sizeof(*res), M_DRM, GFP_KERNEL); |