mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-18 16:44:27 +08:00
099d1c290e
Lets not trick ourselves into thinking "drm_device" objects are not ref-counted. That's just utterly stupid. We manage "drm_minor" objects on each drm-device and each minor can have an unlimited number of open handles. Each of these handles has the drm_minor (and thus the drm_device) as private-data in the file-handle. Therefore, we may not destroy "drm_device" until all these handles are closed. It is *not* possible to reset all these pointers atomically and restrict access to them, and this is *not* how this is done! Instead, we use ref-counts to make sure the object is valid and not freed. Note that we currently use "dev->open_count" for that, which is *exactly* the same as a reference-count, just open coded. So this patch doesn't change any semantics on DRM devices (well, this patch just introduces the ref-count, anyway. Follow-up patches will replace open_count by it). Also note that generic VFS revoke support could allow us to drop this ref-count again. We could then just synchronously disable any fops->xy() calls. However, this is not the case, yet, and no such patches are in sight (and I seriously question the idea of dropping the ref-cnt again). Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
76 lines
1.7 KiB
C
76 lines
1.7 KiB
C
/*
|
|
* Copyright (C) 2013 NVIDIA Corporation
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*/
|
|
|
|
#include "drm.h"
|
|
|
|
static int drm_host1x_set_busid(struct drm_device *dev,
|
|
struct drm_master *master)
|
|
{
|
|
const char *device = dev_name(dev->dev);
|
|
const char *driver = dev->driver->name;
|
|
const char *bus = dev->dev->bus->name;
|
|
int length;
|
|
|
|
master->unique_len = strlen(bus) + 1 + strlen(device);
|
|
master->unique_size = master->unique_len;
|
|
|
|
master->unique = kmalloc(master->unique_len + 1, GFP_KERNEL);
|
|
if (!master->unique)
|
|
return -ENOMEM;
|
|
|
|
snprintf(master->unique, master->unique_len + 1, "%s:%s", bus, device);
|
|
|
|
length = strlen(driver) + 1 + master->unique_len;
|
|
|
|
dev->devname = kmalloc(length + 1, GFP_KERNEL);
|
|
if (!dev->devname)
|
|
return -ENOMEM;
|
|
|
|
snprintf(dev->devname, length + 1, "%s@%s", driver, master->unique);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static struct drm_bus drm_host1x_bus = {
|
|
.bus_type = DRIVER_BUS_HOST1X,
|
|
.set_busid = drm_host1x_set_busid,
|
|
};
|
|
|
|
int drm_host1x_init(struct drm_driver *driver, struct host1x_device *device)
|
|
{
|
|
struct drm_device *drm;
|
|
int ret;
|
|
|
|
driver->bus = &drm_host1x_bus;
|
|
|
|
drm = drm_dev_alloc(driver, &device->dev);
|
|
if (!drm)
|
|
return -ENOMEM;
|
|
|
|
ret = drm_dev_register(drm, 0);
|
|
if (ret)
|
|
goto err_free;
|
|
|
|
DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", driver->name,
|
|
driver->major, driver->minor, driver->patchlevel,
|
|
driver->date, drm->primary->index);
|
|
|
|
return 0;
|
|
|
|
err_free:
|
|
drm_dev_unref(drm);
|
|
return ret;
|
|
}
|
|
|
|
void drm_host1x_exit(struct drm_driver *driver, struct host1x_device *device)
|
|
{
|
|
struct tegra_drm *tegra = dev_get_drvdata(&device->dev);
|
|
|
|
drm_put_dev(tegra->drm);
|
|
}
|