Commit b7dc79a6 authored by Simona Vetter's avatar Simona Vetter
Browse files

Merge tag 'drm-misc-fixes-2025-07-10' of...

Merge tag 'drm-misc-fixes-2025-07-10' of https://gitlab.freedesktop.org/drm/misc/kernel

 into drm-fixes

drm-misc-fixes for v6.16-rc6 or final:
- Fix nouveau fail on debugfs errors.
- Magic 50 ms to fix nouveau suspend.
- Call rust destructor on drm device release.
- Fix DMA api error handling in tegra/nvdec.
- Fix PVR device reset.
- Habanalabs maintainer update.
- Small memory leak fix when nouveau acpi init fails.
- Do not attempt to bind to any PCI device with AGP capability.
- Make FB's acquire handles on backing object, same as i915/xe already does.
- Fix race in drm_gem_handle_create_tail.

Signed-off-by: default avatarSimona Vetter <simona.vetter@ffwll.ch>
From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/e522cdc7-1787-48f2-97e5-0f94783970ab@linux.intel.com
parents 14e85fab bd46cece
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -10504,7 +10504,7 @@ S: Maintained
F:	block/partitions/efi.*
HABANALABS PCI DRIVER
M:	Ofir Bitton <obitton@habana.ai>
M:	Yaron Avizrat <yaron.avizrat@intel.com>
L:	dri-devel@lists.freedesktop.org
S:	Supported
C:	irc://irc.oftc.net/dri-devel
+8 −8
Original line number Diff line number Diff line
@@ -720,11 +720,6 @@ static const struct pci_device_id agp_amd64_pci_table[] = {

MODULE_DEVICE_TABLE(pci, agp_amd64_pci_table);

static const struct pci_device_id agp_amd64_pci_promisc_table[] = {
	{ PCI_DEVICE_CLASS(0, 0) },
	{ }
};

static DEFINE_SIMPLE_DEV_PM_OPS(agp_amd64_pm_ops, NULL, agp_amd64_resume);

static struct pci_driver agp_amd64_pci_driver = {
@@ -739,6 +734,7 @@ static struct pci_driver agp_amd64_pci_driver = {
/* Not static due to IOMMU code calling it early. */
int __init agp_amd64_init(void)
{
	struct pci_dev *pdev = NULL;
	int err = 0;

	if (agp_off)
@@ -767,9 +763,13 @@ int __init agp_amd64_init(void)
		}

		/* Look for any AGP bridge */
		agp_amd64_pci_driver.id_table = agp_amd64_pci_promisc_table;
		err = driver_attach(&agp_amd64_pci_driver.driver);
		if (err == 0 && agp_bridges_found == 0) {
		for_each_pci_dev(pdev)
			if (pci_find_capability(pdev, PCI_CAP_ID_AGP))
				pci_add_dynid(&agp_amd64_pci_driver,
					      pdev->vendor, pdev->device,
					      pdev->subsystem_vendor,
					      pdev->subsystem_device, 0, 0, 0);
		if (agp_bridges_found == 0) {
			pci_unregister_driver(&agp_amd64_pci_driver);
			err = -ENODEV;
		}
+29 −2
Original line number Diff line number Diff line
@@ -862,11 +862,23 @@ EXPORT_SYMBOL_FOR_TESTS_ONLY(drm_framebuffer_free);
int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb,
			 const struct drm_framebuffer_funcs *funcs)
{
	unsigned int i;
	int ret;
	bool exists;

	if (WARN_ON_ONCE(fb->dev != dev || !fb->format))
		return -EINVAL;

	for (i = 0; i < fb->format->num_planes; i++) {
		if (drm_WARN_ON_ONCE(dev, fb->internal_flags & DRM_FRAMEBUFFER_HAS_HANDLE_REF(i)))
			fb->internal_flags &= ~DRM_FRAMEBUFFER_HAS_HANDLE_REF(i);
		if (fb->obj[i]) {
			exists = drm_gem_object_handle_get_if_exists_unlocked(fb->obj[i]);
			if (exists)
				fb->internal_flags |= DRM_FRAMEBUFFER_HAS_HANDLE_REF(i);
		}
	}

	INIT_LIST_HEAD(&fb->filp_head);

	fb->funcs = funcs;
@@ -875,7 +887,7 @@ int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb,
	ret = __drm_mode_object_add(dev, &fb->base, DRM_MODE_OBJECT_FB,
				    false, drm_framebuffer_free);
	if (ret)
		goto out;
		goto err;

	mutex_lock(&dev->mode_config.fb_lock);
	dev->mode_config.num_fb++;
@@ -883,7 +895,16 @@ int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb,
	mutex_unlock(&dev->mode_config.fb_lock);

	drm_mode_object_register(dev, &fb->base);
out:

	return 0;

err:
	for (i = 0; i < fb->format->num_planes; i++) {
		if (fb->internal_flags & DRM_FRAMEBUFFER_HAS_HANDLE_REF(i)) {
			drm_gem_object_handle_put_unlocked(fb->obj[i]);
			fb->internal_flags &= ~DRM_FRAMEBUFFER_HAS_HANDLE_REF(i);
		}
	}
	return ret;
}
EXPORT_SYMBOL(drm_framebuffer_init);
@@ -960,6 +981,12 @@ EXPORT_SYMBOL(drm_framebuffer_unregister_private);
void drm_framebuffer_cleanup(struct drm_framebuffer *fb)
{
	struct drm_device *dev = fb->dev;
	unsigned int i;

	for (i = 0; i < fb->format->num_planes; i++) {
		if (fb->internal_flags & DRM_FRAMEBUFFER_HAS_HANDLE_REF(i))
			drm_gem_object_handle_put_unlocked(fb->obj[i]);
	}

	mutex_lock(&dev->mode_config.fb_lock);
	list_del(&fb->head);
+33 −15
Original line number Diff line number Diff line
@@ -223,23 +223,34 @@ static void drm_gem_object_handle_get(struct drm_gem_object *obj)
}

/**
 * drm_gem_object_handle_get_unlocked - acquire reference on user-space handles
 * drm_gem_object_handle_get_if_exists_unlocked - acquire reference on user-space handle, if any
 * @obj: GEM object
 *
 * Acquires a reference on the GEM buffer object's handle. Required
 * to keep the GEM object alive. Call drm_gem_object_handle_put_unlocked()
 * to release the reference.
 * Acquires a reference on the GEM buffer object's handle. Required to keep
 * the GEM object alive. Call drm_gem_object_handle_put_if_exists_unlocked()
 * to release the reference. Does nothing if the buffer object has no handle.
 *
 * Returns:
 * True if a handle exists, or false otherwise
 */
void drm_gem_object_handle_get_unlocked(struct drm_gem_object *obj)
bool drm_gem_object_handle_get_if_exists_unlocked(struct drm_gem_object *obj)
{
	struct drm_device *dev = obj->dev;

	guard(mutex)(&dev->object_name_lock);

	drm_WARN_ON(dev, !obj->handle_count); /* first ref taken in create-tail helper */
	/*
	 * First ref taken during GEM object creation, if any. Some
	 * drivers set up internal framebuffers with GEM objects that
	 * do not have a GEM handle. Hence, this counter can be zero.
	 */
	if (!obj->handle_count)
		return false;

	drm_gem_object_handle_get(obj);

	return true;
}
EXPORT_SYMBOL(drm_gem_object_handle_get_unlocked);

/**
 * drm_gem_object_handle_free - release resources bound to userspace handles
@@ -272,7 +283,7 @@ static void drm_gem_object_exported_dma_buf_free(struct drm_gem_object *obj)
}

/**
 * drm_gem_object_handle_put_unlocked - releases reference on user-space handles
 * drm_gem_object_handle_put_unlocked - releases reference on user-space handle
 * @obj: GEM object
 *
 * Releases a reference on the GEM buffer object's handle. Possibly releases
@@ -283,13 +294,13 @@ void drm_gem_object_handle_put_unlocked(struct drm_gem_object *obj)
	struct drm_device *dev = obj->dev;
	bool final = false;

	if (WARN_ON(READ_ONCE(obj->handle_count) == 0))
	if (drm_WARN_ON(dev, READ_ONCE(obj->handle_count) == 0))
		return;

	/*
	 * Must bump handle count first as this may be the last
	* ref, in which case the object would disappear before we
	* checked for a name
	 * ref, in which case the object would disappear before
	 * we checked for a name.
	 */

	mutex_lock(&dev->object_name_lock);
@@ -303,7 +314,6 @@ void drm_gem_object_handle_put_unlocked(struct drm_gem_object *obj)
	if (final)
		drm_gem_object_put(obj);
}
EXPORT_SYMBOL(drm_gem_object_handle_put_unlocked);

/*
 * Called at device or object close to release the file's
@@ -315,6 +325,9 @@ drm_gem_object_release_handle(int id, void *ptr, void *data)
	struct drm_file *file_priv = data;
	struct drm_gem_object *obj = ptr;

	if (drm_WARN_ON(obj->dev, !data))
		return 0;

	if (obj->funcs->close)
		obj->funcs->close(obj, file_priv);

@@ -435,7 +448,7 @@ drm_gem_handle_create_tail(struct drm_file *file_priv,
	idr_preload(GFP_KERNEL);
	spin_lock(&file_priv->table_lock);

	ret = idr_alloc(&file_priv->object_idr, obj, 1, 0, GFP_NOWAIT);
	ret = idr_alloc(&file_priv->object_idr, NULL, 1, 0, GFP_NOWAIT);

	spin_unlock(&file_priv->table_lock);
	idr_preload_end();
@@ -456,6 +469,11 @@ drm_gem_handle_create_tail(struct drm_file *file_priv,
			goto err_revoke;
	}

	/* mirrors drm_gem_handle_delete to avoid races */
	spin_lock(&file_priv->table_lock);
	obj = idr_replace(&file_priv->object_idr, obj, handle);
	WARN_ON(obj != NULL);
	spin_unlock(&file_priv->table_lock);
	*handlep = handle;
	return 0;

+7 −9
Original line number Diff line number Diff line
@@ -99,7 +99,7 @@ void drm_gem_fb_destroy(struct drm_framebuffer *fb)
	unsigned int i;

	for (i = 0; i < fb->format->num_planes; i++)
		drm_gem_object_handle_put_unlocked(fb->obj[i]);
		drm_gem_object_put(fb->obj[i]);

	drm_framebuffer_cleanup(fb);
	kfree(fb);
@@ -182,10 +182,8 @@ int drm_gem_fb_init_with_funcs(struct drm_device *dev,
		if (!objs[i]) {
			drm_dbg_kms(dev, "Failed to lookup GEM object\n");
			ret = -ENOENT;
			goto err_gem_object_handle_put_unlocked;
			goto err_gem_object_put;
		}
		drm_gem_object_handle_get_unlocked(objs[i]);
		drm_gem_object_put(objs[i]);

		min_size = (height - 1) * mode_cmd->pitches[i]
			 + drm_format_info_min_pitch(info, i, width)
@@ -195,22 +193,22 @@ int drm_gem_fb_init_with_funcs(struct drm_device *dev,
			drm_dbg_kms(dev,
				    "GEM object size (%zu) smaller than minimum size (%u) for plane %d\n",
				    objs[i]->size, min_size, i);
			drm_gem_object_handle_put_unlocked(objs[i]);
			drm_gem_object_put(objs[i]);
			ret = -EINVAL;
			goto err_gem_object_handle_put_unlocked;
			goto err_gem_object_put;
		}
	}

	ret = drm_gem_fb_init(dev, fb, mode_cmd, objs, i, funcs);
	if (ret)
		goto err_gem_object_handle_put_unlocked;
		goto err_gem_object_put;

	return 0;

err_gem_object_handle_put_unlocked:
err_gem_object_put:
	while (i > 0) {
		--i;
		drm_gem_object_handle_put_unlocked(objs[i]);
		drm_gem_object_put(objs[i]);
	}
	return ret;
}
Loading