Commit b6c24725 authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm-misc-fixes-2021-11-11' of git://anongit.freedesktop.org/drm/drm-misc into drm-next

 * dma-buf: name_lock fixes
 * prime: Keep object ref during mmap
 * nouveau: Fix a refcount issue; Fix device removal; Protect client
   list with dedicated mutex; Fix address CE0 address calculation
 * ttm: Fix race condition during BO eviction
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/YYzY6jeox9EeI15i@linux-uq9g.fritz.box
parents 447212bb 7120a447
...@@ -1359,6 +1359,8 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused) ...@@ -1359,6 +1359,8 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
if (ret) if (ret)
goto error_unlock; goto error_unlock;
spin_lock(&buf_obj->name_lock);
seq_printf(s, "%08zu\t%08x\t%08x\t%08ld\t%s\t%08lu\t%s\n", seq_printf(s, "%08zu\t%08x\t%08x\t%08ld\t%s\t%08lu\t%s\n",
buf_obj->size, buf_obj->size,
buf_obj->file->f_flags, buf_obj->file->f_mode, buf_obj->file->f_flags, buf_obj->file->f_mode,
...@@ -1366,6 +1368,7 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused) ...@@ -1366,6 +1368,7 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
buf_obj->exp_name, buf_obj->exp_name,
file_inode(buf_obj->file)->i_ino, file_inode(buf_obj->file)->i_ino,
buf_obj->name ?: ""); buf_obj->name ?: "");
spin_unlock(&buf_obj->name_lock);
dma_resv_for_each_fence(&cursor, buf_obj->resv, true, fence) { dma_resv_for_each_fence(&cursor, buf_obj->resv, true, fence) {
seq_printf(s, "\t%s fence: %s %s %ssignalled\n", seq_printf(s, "\t%s fence: %s %s %ssignalled\n",
......
...@@ -719,11 +719,13 @@ int drm_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma) ...@@ -719,11 +719,13 @@ int drm_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
if (obj->funcs && obj->funcs->mmap) { if (obj->funcs && obj->funcs->mmap) {
vma->vm_ops = obj->funcs->vm_ops; vma->vm_ops = obj->funcs->vm_ops;
drm_gem_object_get(obj);
ret = obj->funcs->mmap(obj, vma); ret = obj->funcs->mmap(obj, vma);
if (ret) if (ret) {
drm_gem_object_put(obj);
return ret; return ret;
}
vma->vm_private_data = obj; vma->vm_private_data = obj;
drm_gem_object_get(obj);
return 0; return 0;
} }
......
...@@ -562,6 +562,7 @@ nouveau_drm_device_init(struct drm_device *dev) ...@@ -562,6 +562,7 @@ nouveau_drm_device_init(struct drm_device *dev)
nvkm_dbgopt(nouveau_debug, "DRM"); nvkm_dbgopt(nouveau_debug, "DRM");
INIT_LIST_HEAD(&drm->clients); INIT_LIST_HEAD(&drm->clients);
mutex_init(&drm->clients_lock);
spin_lock_init(&drm->tile.lock); spin_lock_init(&drm->tile.lock);
/* workaround an odd issue on nvc1 by disabling the device's /* workaround an odd issue on nvc1 by disabling the device's
...@@ -632,6 +633,7 @@ nouveau_drm_device_init(struct drm_device *dev) ...@@ -632,6 +633,7 @@ nouveau_drm_device_init(struct drm_device *dev)
static void static void
nouveau_drm_device_fini(struct drm_device *dev) nouveau_drm_device_fini(struct drm_device *dev)
{ {
struct nouveau_cli *cli, *temp_cli;
struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_drm *drm = nouveau_drm(dev);
if (nouveau_pmops_runtime()) { if (nouveau_pmops_runtime()) {
...@@ -656,9 +658,28 @@ nouveau_drm_device_fini(struct drm_device *dev) ...@@ -656,9 +658,28 @@ nouveau_drm_device_fini(struct drm_device *dev)
nouveau_ttm_fini(drm); nouveau_ttm_fini(drm);
nouveau_vga_fini(drm); nouveau_vga_fini(drm);
/*
* There may be existing clients from as-yet unclosed files. For now,
* clean them up here rather than deferring until the file is closed,
* but this likely not correct if we want to support hot-unplugging
* properly.
*/
mutex_lock(&drm->clients_lock);
list_for_each_entry_safe(cli, temp_cli, &drm->clients, head) {
list_del(&cli->head);
mutex_lock(&cli->mutex);
if (cli->abi16)
nouveau_abi16_fini(cli->abi16);
mutex_unlock(&cli->mutex);
nouveau_cli_fini(cli);
kfree(cli);
}
mutex_unlock(&drm->clients_lock);
nouveau_cli_fini(&drm->client); nouveau_cli_fini(&drm->client);
nouveau_cli_fini(&drm->master); nouveau_cli_fini(&drm->master);
nvif_parent_dtor(&drm->parent); nvif_parent_dtor(&drm->parent);
mutex_destroy(&drm->clients_lock);
kfree(drm); kfree(drm);
} }
...@@ -796,7 +817,7 @@ nouveau_drm_device_remove(struct drm_device *dev) ...@@ -796,7 +817,7 @@ nouveau_drm_device_remove(struct drm_device *dev)
struct nvkm_client *client; struct nvkm_client *client;
struct nvkm_device *device; struct nvkm_device *device;
drm_dev_unregister(dev); drm_dev_unplug(dev);
client = nvxx_client(&drm->client.base); client = nvxx_client(&drm->client.base);
device = nvkm_device_find(client->device); device = nvkm_device_find(client->device);
...@@ -1090,9 +1111,9 @@ nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv) ...@@ -1090,9 +1111,9 @@ nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv)
fpriv->driver_priv = cli; fpriv->driver_priv = cli;
mutex_lock(&drm->client.mutex); mutex_lock(&drm->clients_lock);
list_add(&cli->head, &drm->clients); list_add(&cli->head, &drm->clients);
mutex_unlock(&drm->client.mutex); mutex_unlock(&drm->clients_lock);
done: done:
if (ret && cli) { if (ret && cli) {
...@@ -1110,6 +1131,16 @@ nouveau_drm_postclose(struct drm_device *dev, struct drm_file *fpriv) ...@@ -1110,6 +1131,16 @@ nouveau_drm_postclose(struct drm_device *dev, struct drm_file *fpriv)
{ {
struct nouveau_cli *cli = nouveau_cli(fpriv); struct nouveau_cli *cli = nouveau_cli(fpriv);
struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_drm *drm = nouveau_drm(dev);
int dev_index;
/*
* The device is gone, and as it currently stands all clients are
* cleaned up in the removal codepath. In the future this may change
* so that we can support hot-unplugging, but for now we immediately
* return to avoid a double-free situation.
*/
if (!drm_dev_enter(dev, &dev_index))
return;
pm_runtime_get_sync(dev->dev); pm_runtime_get_sync(dev->dev);
...@@ -1118,14 +1149,15 @@ nouveau_drm_postclose(struct drm_device *dev, struct drm_file *fpriv) ...@@ -1118,14 +1149,15 @@ nouveau_drm_postclose(struct drm_device *dev, struct drm_file *fpriv)
nouveau_abi16_fini(cli->abi16); nouveau_abi16_fini(cli->abi16);
mutex_unlock(&cli->mutex); mutex_unlock(&cli->mutex);
mutex_lock(&drm->client.mutex); mutex_lock(&drm->clients_lock);
list_del(&cli->head); list_del(&cli->head);
mutex_unlock(&drm->client.mutex); mutex_unlock(&drm->clients_lock);
nouveau_cli_fini(cli); nouveau_cli_fini(cli);
kfree(cli); kfree(cli);
pm_runtime_mark_last_busy(dev->dev); pm_runtime_mark_last_busy(dev->dev);
pm_runtime_put_autosuspend(dev->dev); pm_runtime_put_autosuspend(dev->dev);
drm_dev_exit(dev_index);
} }
static const struct drm_ioctl_desc static const struct drm_ioctl_desc
......
...@@ -139,6 +139,11 @@ struct nouveau_drm { ...@@ -139,6 +139,11 @@ struct nouveau_drm {
struct list_head clients; struct list_head clients;
/**
* @clients_lock: Protects access to the @clients list of &struct nouveau_cli.
*/
struct mutex clients_lock;
u8 old_pm_cap; u8 old_pm_cap;
struct { struct {
......
...@@ -162,10 +162,14 @@ nouveau_svmm_bind(struct drm_device *dev, void *data, ...@@ -162,10 +162,14 @@ nouveau_svmm_bind(struct drm_device *dev, void *data,
*/ */
mm = get_task_mm(current); mm = get_task_mm(current);
if (!mm) {
return -EINVAL;
}
mmap_read_lock(mm); mmap_read_lock(mm);
if (!cli->svm.svmm) { if (!cli->svm.svmm) {
mmap_read_unlock(mm); mmap_read_unlock(mm);
mmput(mm);
return -EINVAL; return -EINVAL;
} }
......
...@@ -78,6 +78,6 @@ int ...@@ -78,6 +78,6 @@ int
gt215_ce_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, gt215_ce_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_engine **pengine) struct nvkm_engine **pengine)
{ {
return nvkm_falcon_new_(&gt215_ce, device, type, inst, return nvkm_falcon_new_(&gt215_ce, device, type, -1,
(device->chipset != 0xaf), 0x104000, pengine); (device->chipset != 0xaf), 0x104000, pengine);
} }
...@@ -3147,8 +3147,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func, ...@@ -3147,8 +3147,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
WARN_ON(device->chip->ptr.inst & ~((1 << ARRAY_SIZE(device->ptr)) - 1)); \ WARN_ON(device->chip->ptr.inst & ~((1 << ARRAY_SIZE(device->ptr)) - 1)); \
for (j = 0; device->chip->ptr.inst && j < ARRAY_SIZE(device->ptr); j++) { \ for (j = 0; device->chip->ptr.inst && j < ARRAY_SIZE(device->ptr); j++) { \
if ((device->chip->ptr.inst & BIT(j)) && (subdev_mask & BIT_ULL(type))) { \ if ((device->chip->ptr.inst & BIT(j)) && (subdev_mask & BIT_ULL(type))) { \
int inst = (device->chip->ptr.inst == 1) ? -1 : (j); \ ret = device->chip->ptr.ctor(device, (type), (j), &device->ptr[j]); \
ret = device->chip->ptr.ctor(device, (type), inst, &device->ptr[j]); \
subdev = nvkm_device_subdev(device, (type), (j)); \ subdev = nvkm_device_subdev(device, (type), (j)); \
if (ret) { \ if (ret) { \
nvkm_subdev_del(&subdev); \ nvkm_subdev_del(&subdev); \
......
...@@ -619,7 +619,8 @@ static bool ttm_bo_evict_swapout_allowable(struct ttm_buffer_object *bo, ...@@ -619,7 +619,8 @@ static bool ttm_bo_evict_swapout_allowable(struct ttm_buffer_object *bo,
*busy = !ret; *busy = !ret;
} }
if (ret && place && !bo->bdev->funcs->eviction_valuable(bo, place)) { if (ret && place && (bo->resource->mem_type != place->mem_type ||
!bo->bdev->funcs->eviction_valuable(bo, place))) {
ret = false; ret = false;
if (*locked) { if (*locked) {
dma_resv_unlock(bo->base.resv); dma_resv_unlock(bo->base.resv);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment