| 
									
										
										
										
											2013-10-14 14:43:22 +02:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * 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: provide device-refcount
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>
											
										 
											2014-01-29 10:21:36 +01:00
										 |  |  | 	drm_dev_unref(drm); | 
					
						
							| 
									
										
										
										
											2013-10-14 14:43:22 +02:00
										 |  |  | 	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); | 
					
						
							|  |  |  | } |