mirror of
https://kernel.googlesource.com/pub/scm/linux/kernel/git/torvalds/linux
synced 2025-10-07 06:44:06 +10:00
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: Simona 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
This commit is contained in:
commit
b7dc79a633
@ -10504,7 +10504,7 @@ S: Maintained
|
|||||||
F: block/partitions/efi.*
|
F: block/partitions/efi.*
|
||||||
|
|
||||||
HABANALABS PCI DRIVER
|
HABANALABS PCI DRIVER
|
||||||
M: Ofir Bitton <obitton@habana.ai>
|
M: Yaron Avizrat <yaron.avizrat@intel.com>
|
||||||
L: dri-devel@lists.freedesktop.org
|
L: dri-devel@lists.freedesktop.org
|
||||||
S: Supported
|
S: Supported
|
||||||
C: irc://irc.oftc.net/dri-devel
|
C: irc://irc.oftc.net/dri-devel
|
||||||
|
@ -720,11 +720,6 @@ static const struct pci_device_id agp_amd64_pci_table[] = {
|
|||||||
|
|
||||||
MODULE_DEVICE_TABLE(pci, 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 DEFINE_SIMPLE_DEV_PM_OPS(agp_amd64_pm_ops, NULL, agp_amd64_resume);
|
||||||
|
|
||||||
static struct pci_driver agp_amd64_pci_driver = {
|
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. */
|
/* Not static due to IOMMU code calling it early. */
|
||||||
int __init agp_amd64_init(void)
|
int __init agp_amd64_init(void)
|
||||||
{
|
{
|
||||||
|
struct pci_dev *pdev = NULL;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if (agp_off)
|
if (agp_off)
|
||||||
@ -767,9 +763,13 @@ int __init agp_amd64_init(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Look for any AGP bridge */
|
/* Look for any AGP bridge */
|
||||||
agp_amd64_pci_driver.id_table = agp_amd64_pci_promisc_table;
|
for_each_pci_dev(pdev)
|
||||||
err = driver_attach(&agp_amd64_pci_driver.driver);
|
if (pci_find_capability(pdev, PCI_CAP_ID_AGP))
|
||||||
if (err == 0 && agp_bridges_found == 0) {
|
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);
|
pci_unregister_driver(&agp_amd64_pci_driver);
|
||||||
err = -ENODEV;
|
err = -ENODEV;
|
||||||
}
|
}
|
||||||
|
@ -862,11 +862,23 @@ EXPORT_SYMBOL_FOR_TESTS_ONLY(drm_framebuffer_free);
|
|||||||
int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb,
|
int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb,
|
||||||
const struct drm_framebuffer_funcs *funcs)
|
const struct drm_framebuffer_funcs *funcs)
|
||||||
{
|
{
|
||||||
|
unsigned int i;
|
||||||
int ret;
|
int ret;
|
||||||
|
bool exists;
|
||||||
|
|
||||||
if (WARN_ON_ONCE(fb->dev != dev || !fb->format))
|
if (WARN_ON_ONCE(fb->dev != dev || !fb->format))
|
||||||
return -EINVAL;
|
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);
|
INIT_LIST_HEAD(&fb->filp_head);
|
||||||
|
|
||||||
fb->funcs = funcs;
|
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,
|
ret = __drm_mode_object_add(dev, &fb->base, DRM_MODE_OBJECT_FB,
|
||||||
false, drm_framebuffer_free);
|
false, drm_framebuffer_free);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto err;
|
||||||
|
|
||||||
mutex_lock(&dev->mode_config.fb_lock);
|
mutex_lock(&dev->mode_config.fb_lock);
|
||||||
dev->mode_config.num_fb++;
|
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);
|
mutex_unlock(&dev->mode_config.fb_lock);
|
||||||
|
|
||||||
drm_mode_object_register(dev, &fb->base);
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_framebuffer_init);
|
EXPORT_SYMBOL(drm_framebuffer_init);
|
||||||
@ -960,6 +981,12 @@ EXPORT_SYMBOL(drm_framebuffer_unregister_private);
|
|||||||
void drm_framebuffer_cleanup(struct drm_framebuffer *fb)
|
void drm_framebuffer_cleanup(struct drm_framebuffer *fb)
|
||||||
{
|
{
|
||||||
struct drm_device *dev = fb->dev;
|
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);
|
mutex_lock(&dev->mode_config.fb_lock);
|
||||||
list_del(&fb->head);
|
list_del(&fb->head);
|
||||||
|
@ -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
|
* @obj: GEM object
|
||||||
*
|
*
|
||||||
* Acquires a reference on the GEM buffer object's handle. Required
|
* Acquires a reference on the GEM buffer object's handle. Required to keep
|
||||||
* to keep the GEM object alive. Call drm_gem_object_handle_put_unlocked()
|
* the GEM object alive. Call drm_gem_object_handle_put_if_exists_unlocked()
|
||||||
* to release the reference.
|
* 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;
|
struct drm_device *dev = obj->dev;
|
||||||
|
|
||||||
guard(mutex)(&dev->object_name_lock);
|
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);
|
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
|
* 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
|
* @obj: GEM object
|
||||||
*
|
*
|
||||||
* Releases a reference on the GEM buffer object's handle. Possibly releases
|
* Releases a reference on the GEM buffer object's handle. Possibly releases
|
||||||
@ -283,14 +294,14 @@ void drm_gem_object_handle_put_unlocked(struct drm_gem_object *obj)
|
|||||||
struct drm_device *dev = obj->dev;
|
struct drm_device *dev = obj->dev;
|
||||||
bool final = false;
|
bool final = false;
|
||||||
|
|
||||||
if (WARN_ON(READ_ONCE(obj->handle_count) == 0))
|
if (drm_WARN_ON(dev, READ_ONCE(obj->handle_count) == 0))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Must bump handle count first as this may be the last
|
* Must bump handle count first as this may be the last
|
||||||
* ref, in which case the object would disappear before we
|
* ref, in which case the object would disappear before
|
||||||
* checked for a name
|
* we checked for a name.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
mutex_lock(&dev->object_name_lock);
|
mutex_lock(&dev->object_name_lock);
|
||||||
if (--obj->handle_count == 0) {
|
if (--obj->handle_count == 0) {
|
||||||
@ -303,7 +314,6 @@ void drm_gem_object_handle_put_unlocked(struct drm_gem_object *obj)
|
|||||||
if (final)
|
if (final)
|
||||||
drm_gem_object_put(obj);
|
drm_gem_object_put(obj);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_gem_object_handle_put_unlocked);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called at device or object close to release the file's
|
* 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_file *file_priv = data;
|
||||||
struct drm_gem_object *obj = ptr;
|
struct drm_gem_object *obj = ptr;
|
||||||
|
|
||||||
|
if (drm_WARN_ON(obj->dev, !data))
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (obj->funcs->close)
|
if (obj->funcs->close)
|
||||||
obj->funcs->close(obj, file_priv);
|
obj->funcs->close(obj, file_priv);
|
||||||
|
|
||||||
@ -435,7 +448,7 @@ drm_gem_handle_create_tail(struct drm_file *file_priv,
|
|||||||
idr_preload(GFP_KERNEL);
|
idr_preload(GFP_KERNEL);
|
||||||
spin_lock(&file_priv->table_lock);
|
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);
|
spin_unlock(&file_priv->table_lock);
|
||||||
idr_preload_end();
|
idr_preload_end();
|
||||||
@ -456,6 +469,11 @@ drm_gem_handle_create_tail(struct drm_file *file_priv,
|
|||||||
goto err_revoke;
|
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;
|
*handlep = handle;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@ void drm_gem_fb_destroy(struct drm_framebuffer *fb)
|
|||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
for (i = 0; i < fb->format->num_planes; 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);
|
drm_framebuffer_cleanup(fb);
|
||||||
kfree(fb);
|
kfree(fb);
|
||||||
@ -182,10 +182,8 @@ int drm_gem_fb_init_with_funcs(struct drm_device *dev,
|
|||||||
if (!objs[i]) {
|
if (!objs[i]) {
|
||||||
drm_dbg_kms(dev, "Failed to lookup GEM object\n");
|
drm_dbg_kms(dev, "Failed to lookup GEM object\n");
|
||||||
ret = -ENOENT;
|
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]
|
min_size = (height - 1) * mode_cmd->pitches[i]
|
||||||
+ drm_format_info_min_pitch(info, i, width)
|
+ 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,
|
drm_dbg_kms(dev,
|
||||||
"GEM object size (%zu) smaller than minimum size (%u) for plane %d\n",
|
"GEM object size (%zu) smaller than minimum size (%u) for plane %d\n",
|
||||||
objs[i]->size, min_size, i);
|
objs[i]->size, min_size, i);
|
||||||
drm_gem_object_handle_put_unlocked(objs[i]);
|
drm_gem_object_put(objs[i]);
|
||||||
ret = -EINVAL;
|
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);
|
ret = drm_gem_fb_init(dev, fb, mode_cmd, objs, i, funcs);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err_gem_object_handle_put_unlocked;
|
goto err_gem_object_put;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_gem_object_handle_put_unlocked:
|
err_gem_object_put:
|
||||||
while (i > 0) {
|
while (i > 0) {
|
||||||
--i;
|
--i;
|
||||||
drm_gem_object_handle_put_unlocked(objs[i]);
|
drm_gem_object_put(objs[i]);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -161,7 +161,7 @@ void drm_sysfs_lease_event(struct drm_device *dev);
|
|||||||
|
|
||||||
/* drm_gem.c */
|
/* drm_gem.c */
|
||||||
int drm_gem_init(struct drm_device *dev);
|
int drm_gem_init(struct drm_device *dev);
|
||||||
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);
|
||||||
void drm_gem_object_handle_put_unlocked(struct drm_gem_object *obj);
|
void drm_gem_object_handle_put_unlocked(struct drm_gem_object *obj);
|
||||||
int drm_gem_handle_create_tail(struct drm_file *file_priv,
|
int drm_gem_handle_create_tail(struct drm_file *file_priv,
|
||||||
struct drm_gem_object *obj,
|
struct drm_gem_object *obj,
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
//! * <https://github.com/erwanvivien/fast_qr>
|
//! * <https://github.com/erwanvivien/fast_qr>
|
||||||
//! * <https://github.com/bjguillot/qr>
|
//! * <https://github.com/bjguillot/qr>
|
||||||
|
|
||||||
use kernel::{prelude::*, str::CStr};
|
use kernel::prelude::*;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd)]
|
||||||
struct Version(usize);
|
struct Version(usize);
|
||||||
|
@ -386,13 +386,13 @@ pvr_power_reset(struct pvr_device *pvr_dev, bool hard_reset)
|
|||||||
if (!err) {
|
if (!err) {
|
||||||
if (hard_reset) {
|
if (hard_reset) {
|
||||||
pvr_dev->fw_dev.booted = false;
|
pvr_dev->fw_dev.booted = false;
|
||||||
WARN_ON(pm_runtime_force_suspend(from_pvr_device(pvr_dev)->dev));
|
WARN_ON(pvr_power_device_suspend(from_pvr_device(pvr_dev)->dev));
|
||||||
|
|
||||||
err = pvr_fw_hard_reset(pvr_dev);
|
err = pvr_fw_hard_reset(pvr_dev);
|
||||||
if (err)
|
if (err)
|
||||||
goto err_device_lost;
|
goto err_device_lost;
|
||||||
|
|
||||||
err = pm_runtime_force_resume(from_pvr_device(pvr_dev)->dev);
|
err = pvr_power_device_resume(from_pvr_device(pvr_dev)->dev);
|
||||||
pvr_dev->fw_dev.booted = true;
|
pvr_dev->fw_dev.booted = true;
|
||||||
if (err)
|
if (err)
|
||||||
goto err_device_lost;
|
goto err_device_lost;
|
||||||
|
@ -314,14 +314,10 @@ nouveau_debugfs_fini(struct nouveau_drm *drm)
|
|||||||
drm->debugfs = NULL;
|
drm->debugfs = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
void
|
||||||
nouveau_module_debugfs_init(void)
|
nouveau_module_debugfs_init(void)
|
||||||
{
|
{
|
||||||
nouveau_debugfs_root = debugfs_create_dir("nouveau", NULL);
|
nouveau_debugfs_root = debugfs_create_dir("nouveau", NULL);
|
||||||
if (IS_ERR(nouveau_debugfs_root))
|
|
||||||
return PTR_ERR(nouveau_debugfs_root);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -24,7 +24,7 @@ extern void nouveau_debugfs_fini(struct nouveau_drm *);
|
|||||||
|
|
||||||
extern struct dentry *nouveau_debugfs_root;
|
extern struct dentry *nouveau_debugfs_root;
|
||||||
|
|
||||||
int nouveau_module_debugfs_init(void);
|
void nouveau_module_debugfs_init(void);
|
||||||
void nouveau_module_debugfs_fini(void);
|
void nouveau_module_debugfs_fini(void);
|
||||||
#else
|
#else
|
||||||
static inline void
|
static inline void
|
||||||
@ -42,10 +42,9 @@ nouveau_debugfs_fini(struct nouveau_drm *drm)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline void
|
||||||
nouveau_module_debugfs_init(void)
|
nouveau_module_debugfs_init(void)
|
||||||
{
|
{
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
|
@ -1461,9 +1461,7 @@ nouveau_drm_init(void)
|
|||||||
if (!nouveau_modeset)
|
if (!nouveau_modeset)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ret = nouveau_module_debugfs_init();
|
nouveau_module_debugfs_init();
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
#ifdef CONFIG_NOUVEAU_PLATFORM_DRIVER
|
#ifdef CONFIG_NOUVEAU_PLATFORM_DRIVER
|
||||||
platform_driver_register(&nouveau_platform_driver);
|
platform_driver_register(&nouveau_platform_driver);
|
||||||
|
@ -719,7 +719,6 @@ r535_gsp_acpi_caps(acpi_handle handle, CAPS_METHOD_DATA *caps)
|
|||||||
union acpi_object argv4 = {
|
union acpi_object argv4 = {
|
||||||
.buffer.type = ACPI_TYPE_BUFFER,
|
.buffer.type = ACPI_TYPE_BUFFER,
|
||||||
.buffer.length = 4,
|
.buffer.length = 4,
|
||||||
.buffer.pointer = kmalloc(argv4.buffer.length, GFP_KERNEL),
|
|
||||||
}, *obj;
|
}, *obj;
|
||||||
|
|
||||||
caps->status = 0xffff;
|
caps->status = 0xffff;
|
||||||
@ -727,17 +726,22 @@ r535_gsp_acpi_caps(acpi_handle handle, CAPS_METHOD_DATA *caps)
|
|||||||
if (!acpi_check_dsm(handle, &NVOP_DSM_GUID, NVOP_DSM_REV, BIT_ULL(0x1a)))
|
if (!acpi_check_dsm(handle, &NVOP_DSM_GUID, NVOP_DSM_REV, BIT_ULL(0x1a)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
argv4.buffer.pointer = kmalloc(argv4.buffer.length, GFP_KERNEL);
|
||||||
|
if (!argv4.buffer.pointer)
|
||||||
|
return;
|
||||||
|
|
||||||
obj = acpi_evaluate_dsm(handle, &NVOP_DSM_GUID, NVOP_DSM_REV, 0x1a, &argv4);
|
obj = acpi_evaluate_dsm(handle, &NVOP_DSM_GUID, NVOP_DSM_REV, 0x1a, &argv4);
|
||||||
if (!obj)
|
if (!obj)
|
||||||
return;
|
goto done;
|
||||||
|
|
||||||
if (WARN_ON(obj->type != ACPI_TYPE_BUFFER) ||
|
if (WARN_ON(obj->type != ACPI_TYPE_BUFFER) ||
|
||||||
WARN_ON(obj->buffer.length != 4))
|
WARN_ON(obj->buffer.length != 4))
|
||||||
return;
|
goto done;
|
||||||
|
|
||||||
caps->status = 0;
|
caps->status = 0;
|
||||||
caps->optimusCaps = *(u32 *)obj->buffer.pointer;
|
caps->optimusCaps = *(u32 *)obj->buffer.pointer;
|
||||||
|
|
||||||
|
done:
|
||||||
ACPI_FREE(obj);
|
ACPI_FREE(obj);
|
||||||
|
|
||||||
kfree(argv4.buffer.pointer);
|
kfree(argv4.buffer.pointer);
|
||||||
@ -754,24 +758,28 @@ r535_gsp_acpi_jt(acpi_handle handle, JT_METHOD_DATA *jt)
|
|||||||
union acpi_object argv4 = {
|
union acpi_object argv4 = {
|
||||||
.buffer.type = ACPI_TYPE_BUFFER,
|
.buffer.type = ACPI_TYPE_BUFFER,
|
||||||
.buffer.length = sizeof(caps),
|
.buffer.length = sizeof(caps),
|
||||||
.buffer.pointer = kmalloc(argv4.buffer.length, GFP_KERNEL),
|
|
||||||
}, *obj;
|
}, *obj;
|
||||||
|
|
||||||
jt->status = 0xffff;
|
jt->status = 0xffff;
|
||||||
|
|
||||||
|
argv4.buffer.pointer = kmalloc(argv4.buffer.length, GFP_KERNEL);
|
||||||
|
if (!argv4.buffer.pointer)
|
||||||
|
return;
|
||||||
|
|
||||||
obj = acpi_evaluate_dsm(handle, &JT_DSM_GUID, JT_DSM_REV, 0x1, &argv4);
|
obj = acpi_evaluate_dsm(handle, &JT_DSM_GUID, JT_DSM_REV, 0x1, &argv4);
|
||||||
if (!obj)
|
if (!obj)
|
||||||
return;
|
goto done;
|
||||||
|
|
||||||
if (WARN_ON(obj->type != ACPI_TYPE_BUFFER) ||
|
if (WARN_ON(obj->type != ACPI_TYPE_BUFFER) ||
|
||||||
WARN_ON(obj->buffer.length != 4))
|
WARN_ON(obj->buffer.length != 4))
|
||||||
return;
|
goto done;
|
||||||
|
|
||||||
jt->status = 0;
|
jt->status = 0;
|
||||||
jt->jtCaps = *(u32 *)obj->buffer.pointer;
|
jt->jtCaps = *(u32 *)obj->buffer.pointer;
|
||||||
jt->jtRevId = (jt->jtCaps & 0xfff00000) >> 20;
|
jt->jtRevId = (jt->jtCaps & 0xfff00000) >> 20;
|
||||||
jt->bSBIOSCaps = 0;
|
jt->bSBIOSCaps = 0;
|
||||||
|
|
||||||
|
done:
|
||||||
ACPI_FREE(obj);
|
ACPI_FREE(obj);
|
||||||
|
|
||||||
kfree(argv4.buffer.pointer);
|
kfree(argv4.buffer.pointer);
|
||||||
@ -1744,6 +1752,13 @@ r535_gsp_fini(struct nvkm_gsp *gsp, bool suspend)
|
|||||||
nvkm_gsp_sg_free(gsp->subdev.device, &gsp->sr.sgt);
|
nvkm_gsp_sg_free(gsp->subdev.device, &gsp->sr.sgt);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO: Debug the GSP firmware / RPC handling to find out why
|
||||||
|
* without this Turing (but none of the other architectures)
|
||||||
|
* ends up resetting all channels after resume.
|
||||||
|
*/
|
||||||
|
msleep(50);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = r535_gsp_rpc_unloading_guest_driver(gsp, suspend);
|
ret = r535_gsp_rpc_unloading_guest_driver(gsp, suspend);
|
||||||
|
@ -261,10 +261,8 @@ static int nvdec_load_falcon_firmware(struct nvdec *nvdec)
|
|||||||
|
|
||||||
if (!client->group) {
|
if (!client->group) {
|
||||||
virt = dma_alloc_coherent(nvdec->dev, size, &iova, GFP_KERNEL);
|
virt = dma_alloc_coherent(nvdec->dev, size, &iova, GFP_KERNEL);
|
||||||
|
if (!virt)
|
||||||
err = dma_mapping_error(nvdec->dev, iova);
|
return -ENOMEM;
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
} else {
|
} else {
|
||||||
virt = tegra_drm_alloc(tegra, size, &iova);
|
virt = tegra_drm_alloc(tegra, size, &iova);
|
||||||
if (IS_ERR(virt))
|
if (IS_ERR(virt))
|
||||||
|
@ -300,6 +300,9 @@ struct drm_file {
|
|||||||
*
|
*
|
||||||
* Mapping of mm object handles to object pointers. Used by the GEM
|
* Mapping of mm object handles to object pointers. Used by the GEM
|
||||||
* subsystem. Protected by @table_lock.
|
* subsystem. Protected by @table_lock.
|
||||||
|
*
|
||||||
|
* Note that allocated entries might be NULL as a transient state when
|
||||||
|
* creating or deleting a handle.
|
||||||
*/
|
*/
|
||||||
struct idr object_idr;
|
struct idr object_idr;
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#ifndef __DRM_FRAMEBUFFER_H__
|
#ifndef __DRM_FRAMEBUFFER_H__
|
||||||
#define __DRM_FRAMEBUFFER_H__
|
#define __DRM_FRAMEBUFFER_H__
|
||||||
|
|
||||||
|
#include <linux/bits.h>
|
||||||
#include <linux/ctype.h>
|
#include <linux/ctype.h>
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
@ -100,6 +101,8 @@ struct drm_framebuffer_funcs {
|
|||||||
unsigned num_clips);
|
unsigned num_clips);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define DRM_FRAMEBUFFER_HAS_HANDLE_REF(_i) BIT(0u + (_i))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct drm_framebuffer - frame buffer object
|
* struct drm_framebuffer - frame buffer object
|
||||||
*
|
*
|
||||||
@ -188,6 +191,10 @@ struct drm_framebuffer {
|
|||||||
* DRM_MODE_FB_MODIFIERS.
|
* DRM_MODE_FB_MODIFIERS.
|
||||||
*/
|
*/
|
||||||
int flags;
|
int flags;
|
||||||
|
/**
|
||||||
|
* @internal_flags: Framebuffer flags like DRM_FRAMEBUFFER_HAS_HANDLE_REF.
|
||||||
|
*/
|
||||||
|
unsigned int internal_flags;
|
||||||
/**
|
/**
|
||||||
* @filp_head: Placed on &drm_file.fbs, protected by &drm_file.fbs_lock.
|
* @filp_head: Placed on &drm_file.fbs, protected by &drm_file.fbs_lock.
|
||||||
*/
|
*/
|
||||||
|
@ -66,7 +66,7 @@ impl<T: drm::Driver> Device<T> {
|
|||||||
open: Some(drm::File::<T::File>::open_callback),
|
open: Some(drm::File::<T::File>::open_callback),
|
||||||
postclose: Some(drm::File::<T::File>::postclose_callback),
|
postclose: Some(drm::File::<T::File>::postclose_callback),
|
||||||
unload: None,
|
unload: None,
|
||||||
release: None,
|
release: Some(Self::release),
|
||||||
master_set: None,
|
master_set: None,
|
||||||
master_drop: None,
|
master_drop: None,
|
||||||
debugfs_init: None,
|
debugfs_init: None,
|
||||||
@ -162,6 +162,16 @@ impl<T: drm::Driver> Device<T> {
|
|||||||
// SAFETY: `ptr` is valid by the safety requirements of this function.
|
// SAFETY: `ptr` is valid by the safety requirements of this function.
|
||||||
unsafe { &*ptr.cast() }
|
unsafe { &*ptr.cast() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" fn release(ptr: *mut bindings::drm_device) {
|
||||||
|
// SAFETY: `ptr` is a valid pointer to a `struct drm_device` and embedded in `Self`.
|
||||||
|
let this = unsafe { Self::from_drm_device(ptr) };
|
||||||
|
|
||||||
|
// SAFETY:
|
||||||
|
// - When `release` runs it is guaranteed that there is no further access to `this`.
|
||||||
|
// - `this` is valid for dropping.
|
||||||
|
unsafe { core::ptr::drop_in_place(this) };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: drm::Driver> Deref for Device<T> {
|
impl<T: drm::Driver> Deref for Device<T> {
|
||||||
|
@ -10,7 +10,6 @@ use crate::{
|
|||||||
drm,
|
drm,
|
||||||
error::{to_result, Result},
|
error::{to_result, Result},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
str::CStr,
|
|
||||||
types::ARef,
|
types::ARef,
|
||||||
};
|
};
|
||||||
use macros::vtable;
|
use macros::vtable;
|
||||||
|
Loading…
Reference in New Issue
Block a user