Commit cb7e88e7 authored by Ben Skeggs's avatar Ben Skeggs

drm/nouveau: hang drm client of a master

TTM memory allocations will be hanging off the DRM's client, but the
locking needed to do so gets really tricky with all the other use of
the DRM's object tree.

To solve this, we make the normal DRM client a child of a new master,
where the memory allocations will be done from instead.

This also solves a potential race with client creation.
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 6be4421a
...@@ -117,7 +117,9 @@ nouveau_cli_fini(struct nouveau_cli *cli) ...@@ -117,7 +117,9 @@ nouveau_cli_fini(struct nouveau_cli *cli)
nvkm_vm_ref(NULL, &nvxx_client(&cli->base)->vm, NULL); nvkm_vm_ref(NULL, &nvxx_client(&cli->base)->vm, NULL);
usif_client_fini(cli); usif_client_fini(cli);
nvif_device_fini(&cli->device); nvif_device_fini(&cli->device);
mutex_lock(&cli->drm->master.lock);
nvif_client_fini(&cli->base); nvif_client_fini(&cli->base);
mutex_unlock(&cli->drm->master.lock);
} }
static int static int
...@@ -132,12 +134,16 @@ nouveau_cli_init(struct nouveau_drm *drm, const char *sname, ...@@ -132,12 +134,16 @@ nouveau_cli_init(struct nouveau_drm *drm, const char *sname,
mutex_init(&cli->mutex); mutex_init(&cli->mutex);
usif_client_init(cli); usif_client_init(cli);
if (cli == &drm->client) { mutex_init(&cli->lock);
if (cli == &drm->master) {
ret = nvif_driver_init(NULL, nouveau_config, nouveau_debug, ret = nvif_driver_init(NULL, nouveau_config, nouveau_debug,
cli->name, device, &cli->base); cli->name, device, &cli->base);
} else { } else {
ret = nvif_client_init(&drm->client.base, cli->name, device, mutex_lock(&drm->master.lock);
ret = nvif_client_init(&drm->master.base, cli->name, device,
&cli->base); &cli->base);
mutex_unlock(&drm->master.lock);
} }
if (ret) { if (ret) {
NV_ERROR(drm, "Client allocation failed: %d\n", ret); NV_ERROR(drm, "Client allocation failed: %d\n", ret);
...@@ -433,6 +439,10 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags) ...@@ -433,6 +439,10 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
dev->dev_private = drm; dev->dev_private = drm;
drm->dev = dev; drm->dev = dev;
ret = nouveau_cli_init(drm, "DRM-master", &drm->master);
if (ret)
return ret;
ret = nouveau_cli_init(drm, "DRM", &drm->client); ret = nouveau_cli_init(drm, "DRM", &drm->client);
if (ret) if (ret)
return ret; return ret;
...@@ -518,6 +528,7 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags) ...@@ -518,6 +528,7 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
nouveau_vga_fini(drm); nouveau_vga_fini(drm);
fail_device: fail_device:
nouveau_cli_fini(&drm->client); nouveau_cli_fini(&drm->client);
nouveau_cli_fini(&drm->master);
kfree(drm); kfree(drm);
return ret; return ret;
} }
...@@ -550,6 +561,7 @@ nouveau_drm_unload(struct drm_device *dev) ...@@ -550,6 +561,7 @@ nouveau_drm_unload(struct drm_device *dev)
if (drm->hdmi_device) if (drm->hdmi_device)
pci_dev_put(drm->hdmi_device); pci_dev_put(drm->hdmi_device);
nouveau_cli_fini(&drm->client); nouveau_cli_fini(&drm->client);
nouveau_cli_fini(&drm->master);
kfree(drm); kfree(drm);
} }
...@@ -618,7 +630,7 @@ nouveau_do_suspend(struct drm_device *dev, bool runtime) ...@@ -618,7 +630,7 @@ nouveau_do_suspend(struct drm_device *dev, bool runtime)
} }
NV_DEBUG(drm, "suspending object tree...\n"); NV_DEBUG(drm, "suspending object tree...\n");
ret = nvif_client_suspend(&drm->client.base); ret = nvif_client_suspend(&drm->master.base);
if (ret) if (ret)
goto fail_client; goto fail_client;
...@@ -642,7 +654,7 @@ nouveau_do_resume(struct drm_device *dev, bool runtime) ...@@ -642,7 +654,7 @@ nouveau_do_resume(struct drm_device *dev, bool runtime)
struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_drm *drm = nouveau_drm(dev);
NV_DEBUG(drm, "resuming object tree...\n"); NV_DEBUG(drm, "resuming object tree...\n");
nvif_client_resume(&drm->client.base); nvif_client_resume(&drm->master.base);
NV_DEBUG(drm, "resuming fence...\n"); NV_DEBUG(drm, "resuming fence...\n");
if (drm->fence && nouveau_fence(drm)->resume) if (drm->fence && nouveau_fence(drm)->resume)
......
...@@ -97,6 +97,8 @@ struct nouveau_cli { ...@@ -97,6 +97,8 @@ struct nouveau_cli {
struct list_head objects; struct list_head objects;
struct list_head notifys; struct list_head notifys;
char name[32]; char name[32];
struct mutex lock;
}; };
static inline struct nouveau_cli * static inline struct nouveau_cli *
...@@ -109,6 +111,7 @@ nouveau_cli(struct drm_file *fpriv) ...@@ -109,6 +111,7 @@ nouveau_cli(struct drm_file *fpriv)
#include <nvif/device.h> #include <nvif/device.h>
struct nouveau_drm { struct nouveau_drm {
struct nouveau_cli master;
struct nouveau_cli client; struct nouveau_cli client;
struct drm_device *dev; struct drm_device *dev;
......
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