 099d1c290e
			
		
	
	
	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>
		
			
				
	
	
		
			75 lines
		
	
	
	
		
			1.7 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			75 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);
 | |
| }
 |