From: Thierry Reding treding@nvidia.com
This series of patches gets rid of the host1x drm_bus implementation in Tegra DRM. It introduces a drm_dev_set_unique() function that is used to statically set the unique name of the device, thereby eliminating the last remaining need for drm_bus.
There are also a couple of patches to update documentation and explain how other drivers can use the same mechanism to get rid of the drm_bus midlayer. This should be easy to do for both drm_platform and drm_usb, but drm_pci is still a special case, though Daniel Vetter has plans on how to get rid of drm_bus for PCI drivers too.
Compared to v2 I've left out the conversion to the component helpers because nobody could be bothered to look at the patches. As a result I've decided to stick with the existing implementation that has proven to work equally well.
Thierry
Thierry Reding (4): drm: Introduce drm_dev_set_unique() drm: Add device registration documentation drm: Document how to register devices without struct drm_bus drm/tegra: Remove host1x drm_bus implementation
Documentation/DocBook/drm.tmpl | 36 +++++++++++++++++++ drivers/gpu/drm/drm_ioctl.c | 24 +++++++++---- drivers/gpu/drm/drm_pci.c | 80 ++++++++++++++++++++---------------------- drivers/gpu/drm/drm_platform.c | 15 ++++---- drivers/gpu/drm/drm_stub.c | 48 +++++++++++++++++++------ drivers/gpu/drm/drm_usb.c | 20 ++++++++++- drivers/gpu/drm/tegra/Makefile | 1 - drivers/gpu/drm/tegra/bus.c | 64 --------------------------------- drivers/gpu/drm/tegra/drm.c | 35 +++++++++++++++--- drivers/gpu/drm/tegra/drm.h | 4 --- include/drm/drmP.h | 2 ++ 11 files changed, 187 insertions(+), 142 deletions(-) delete mode 100644 drivers/gpu/drm/tegra/bus.c
From: Thierry Reding treding@nvidia.com
Add a helper function that allows drivers to statically set the unique name of the device. This will allow platform and USB drivers to get rid of their DRM bus implementations and directly use drm_dev_alloc() and drm_dev_register().
Reviewed-by: Daniel Vetter daniel.vetter@ffwll.ch Signed-off-by: Thierry Reding treding@nvidia.com --- Changes in v3: - address comments by David Herrmann: - return -EINVAL when dev->unique not set in drm_set_busid() - group together drm_dev_*() functions - use drm_dev_ prefix
Changes in v2: - move drm_set_unique() to drivers/gpu/drm/drm_stub.c - add kernel-doc
drivers/gpu/drm/drm_ioctl.c | 24 ++++++++++++++++++------ drivers/gpu/drm/drm_stub.c | 26 ++++++++++++++++++++++++++ include/drm/drmP.h | 2 ++ 3 files changed, 46 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index 38269d5aa333..69c61f392e66 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -131,13 +131,25 @@ static int drm_set_busid(struct drm_device *dev, struct drm_file *file_priv) if (master->unique != NULL) drm_unset_busid(dev, master);
- ret = dev->driver->bus->set_busid(dev, master); - if (ret) - goto err; + if (dev->driver->bus && dev->driver->bus->set_busid) { + ret = dev->driver->bus->set_busid(dev, master); + if (ret) { + drm_unset_busid(dev, master); + return ret; + } + } else { + if (WARN(dev->unique == NULL, + "No drm_bus.set_busid() implementation provided by " + "%ps. Use drm_dev_set_unique() to set the unique " + "name explicitly.", dev->driver)) + return -EINVAL; + + master->unique = kstrdup(dev->unique, GFP_KERNEL); + if (master->unique) + master->unique_len = strlen(dev->unique); + } + return 0; -err: - drm_unset_busid(dev, master); - return ret; }
/** diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index 3727ac8bc310..6d55392376dd 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -650,6 +650,7 @@ static void drm_dev_release(struct kref *ref) drm_minor_free(dev, DRM_MINOR_CONTROL);
mutex_destroy(&dev->master_mutex); + kfree(dev->unique); kfree(dev); }
@@ -777,3 +778,28 @@ void drm_dev_unregister(struct drm_device *dev) drm_minor_unregister(dev, DRM_MINOR_CONTROL); } EXPORT_SYMBOL(drm_dev_unregister); + +/** + * drm_dev_set_unique - Set the unique name of a DRM device + * @dev: device of which to set the unique name + * @fmt: format string for unique name + * + * Sets the unique name of a DRM device using the specified format string and + * a variable list of arguments. Drivers can use this at driver probe time if + * the unique name of the devices they drive is static. + * + * Return: 0 on success or a negative error code on failure. + */ +int drm_dev_set_unique(struct drm_device *dev, const char *fmt, ...) +{ + va_list ap; + + kfree(dev->unique); + + va_start(ap, fmt); + dev->unique = kvasprintf(GFP_KERNEL, fmt, ap); + va_end(ap); + + return dev->unique ? 0 : -ENOMEM; +} +EXPORT_SYMBOL(drm_dev_set_unique); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 12f10bc2395f..c511a3d63fd1 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1055,6 +1055,7 @@ struct drm_device { struct drm_minor *render; /**< Render node */ atomic_t unplugged; /**< Flag whether dev is dead */ struct inode *anon_inode; /**< inode for private address-space */ + char *unique; /**< unique name of the device */ /*@} */
/** \name Locks */ @@ -1614,6 +1615,7 @@ void drm_dev_ref(struct drm_device *dev); void drm_dev_unref(struct drm_device *dev); int drm_dev_register(struct drm_device *dev, unsigned long flags); void drm_dev_unregister(struct drm_device *dev); +int drm_dev_set_unique(struct drm_device *dev, const char *fmt, ...);
struct drm_minor *drm_minor_acquire(unsigned int minor_id); void drm_minor_release(struct drm_minor *minor);
Hi
On Thu, May 22, 2014 at 12:21 PM, Thierry Reding thierry.reding@gmail.com wrote:
From: Thierry Reding treding@nvidia.com
Add a helper function that allows drivers to statically set the unique name of the device. This will allow platform and USB drivers to get rid of their DRM bus implementations and directly use drm_dev_alloc() and drm_dev_register().
Reviewed-by: Daniel Vetter daniel.vetter@ffwll.ch Signed-off-by: Thierry Reding treding@nvidia.com
Reviewed-by: David Herrmann dh.herrmann@gmail.com
Thanks David
Changes in v3:
- address comments by David Herrmann:
- return -EINVAL when dev->unique not set in drm_set_busid()
- group together drm_dev_*() functions
- use drm_dev_ prefix
Changes in v2:
- move drm_set_unique() to drivers/gpu/drm/drm_stub.c
- add kernel-doc
drivers/gpu/drm/drm_ioctl.c | 24 ++++++++++++++++++------ drivers/gpu/drm/drm_stub.c | 26 ++++++++++++++++++++++++++ include/drm/drmP.h | 2 ++ 3 files changed, 46 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index 38269d5aa333..69c61f392e66 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -131,13 +131,25 @@ static int drm_set_busid(struct drm_device *dev, struct drm_file *file_priv) if (master->unique != NULL) drm_unset_busid(dev, master);
ret = dev->driver->bus->set_busid(dev, master);
if (ret)
goto err;
if (dev->driver->bus && dev->driver->bus->set_busid) {
ret = dev->driver->bus->set_busid(dev, master);
if (ret) {
drm_unset_busid(dev, master);
return ret;
}
} else {
if (WARN(dev->unique == NULL,
"No drm_bus.set_busid() implementation provided by "
"%ps. Use drm_dev_set_unique() to set the unique "
"name explicitly.", dev->driver))
return -EINVAL;
master->unique = kstrdup(dev->unique, GFP_KERNEL);
if (master->unique)
master->unique_len = strlen(dev->unique);
}
return 0;
-err:
drm_unset_busid(dev, master);
return ret;
}
/** diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index 3727ac8bc310..6d55392376dd 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -650,6 +650,7 @@ static void drm_dev_release(struct kref *ref) drm_minor_free(dev, DRM_MINOR_CONTROL);
mutex_destroy(&dev->master_mutex);
kfree(dev->unique); kfree(dev);
}
@@ -777,3 +778,28 @@ void drm_dev_unregister(struct drm_device *dev) drm_minor_unregister(dev, DRM_MINOR_CONTROL); } EXPORT_SYMBOL(drm_dev_unregister);
+/**
- drm_dev_set_unique - Set the unique name of a DRM device
- @dev: device of which to set the unique name
- @fmt: format string for unique name
- Sets the unique name of a DRM device using the specified format string and
- a variable list of arguments. Drivers can use this at driver probe time if
- the unique name of the devices they drive is static.
- Return: 0 on success or a negative error code on failure.
- */
+int drm_dev_set_unique(struct drm_device *dev, const char *fmt, ...) +{
va_list ap;
kfree(dev->unique);
va_start(ap, fmt);
dev->unique = kvasprintf(GFP_KERNEL, fmt, ap);
va_end(ap);
return dev->unique ? 0 : -ENOMEM;
+} +EXPORT_SYMBOL(drm_dev_set_unique); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 12f10bc2395f..c511a3d63fd1 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1055,6 +1055,7 @@ struct drm_device { struct drm_minor *render; /**< Render node */ atomic_t unplugged; /**< Flag whether dev is dead */ struct inode *anon_inode; /**< inode for private address-space */
char *unique; /**< unique name of the device */ /*@} */ /** \name Locks */
@@ -1614,6 +1615,7 @@ void drm_dev_ref(struct drm_device *dev); void drm_dev_unref(struct drm_device *dev); int drm_dev_register(struct drm_device *dev, unsigned long flags); void drm_dev_unregister(struct drm_device *dev); +int drm_dev_set_unique(struct drm_device *dev, const char *fmt, ...);
struct drm_minor *drm_minor_acquire(unsigned int minor_id); void drm_minor_release(struct drm_minor *minor); -- 1.9.2
From: Thierry Reding treding@nvidia.com
Describe how devices are registered using the drm_*_init() functions. Adding this to docbook requires a largish set of changes to the comments in drm_{pci,usb,platform}.c since they are doxygen-style rather than proper kernel-doc and therefore mess with the docbook generation.
While at it, mark usage of drm_put_dev() as discouraged in favour of calling drm_dev_unregister() and drm_dev_unref() directly.
Signed-off-by: Thierry Reding treding@nvidia.com --- Changes in v3: - add note that drm_put_dev() should not be used in new drivers - use !E to include all exported functions in DocBook
Documentation/DocBook/drm.tmpl | 10 ++++++ drivers/gpu/drm/drm_pci.c | 80 ++++++++++++++++++++---------------------- drivers/gpu/drm/drm_platform.c | 15 ++++---- drivers/gpu/drm/drm_stub.c | 22 ++++++------ drivers/gpu/drm/drm_usb.c | 20 ++++++++++- 5 files changed, 85 insertions(+), 62 deletions(-)
diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index ec81c20a17db..438edcd566b5 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -282,6 +282,16 @@ char *date;</synopsis> </sect3> </sect2> <sect2> + <title>Device Registration</title> + <para> + A number of functions are provided to help with device registration. + The functions deal with PCI, USB and platform devices, respectively. + </para> +!Edrivers/gpu/drm/drm_pci.c +!Edrivers/gpu/drm/drm_usb.c +!Edrivers/gpu/drm/drm_platform.c + </sect2> + <sect2> <title>Driver Load</title> <para> The <methodname>load</methodname> method is the driver and device diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c index d237de36a07a..020cfd934854 100644 --- a/drivers/gpu/drm/drm_pci.c +++ b/drivers/gpu/drm/drm_pci.c @@ -1,17 +1,3 @@ -/* drm_pci.h -- PCI DMA memory management wrappers for DRM -*- linux-c -*- */ -/** - * \file drm_pci.c - * \brief Functions and ioctls to manage PCI memory - * - * \warning These interfaces aren't stable yet. - * - * \todo Implement the remaining ioctl's for the PCI pools. - * \todo The wrappers here are so thin that they would be better off inlined.. - * - * \author José Fonseca jrfonseca@tungstengraphics.com - * \author Leif Delgass ldelgass@retinalburn.net - */ - /* * Copyright 2003 José Fonseca. * Copyright 2003 Leif Delgass. @@ -42,12 +28,14 @@ #include <linux/export.h> #include <drm/drmP.h>
-/**********************************************************************/ -/** \name PCI memory */ -/*@{*/ - /** - * \brief Allocate a PCI consistent memory block, for DMA. + * drm_pci_alloc - Allocate a PCI consistent memory block, for DMA. + * @dev: DRM device + * @size: size of block to allocate + * @align: alignment of block + * + * Return: A handle to the allocated memory block on success or NULL on + * failure. */ drm_dma_handle_t *drm_pci_alloc(struct drm_device * dev, size_t size, size_t align) { @@ -88,8 +76,8 @@ drm_dma_handle_t *drm_pci_alloc(struct drm_device * dev, size_t size, size_t ali
EXPORT_SYMBOL(drm_pci_alloc);
-/** - * \brief Free a PCI consistent memory block without freeing its descriptor. +/* + * Free a PCI consistent memory block without freeing its descriptor. * * This function is for internal use in the Linux-specific DRM core code. */ @@ -111,7 +99,9 @@ void __drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah) }
/** - * \brief Free a PCI consistent memory block + * drm_pci_free - Free a PCI consistent memory block + * @dev: DRM device + * @dmah: handle to memory block */ void drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah) { @@ -226,17 +216,16 @@ static int drm_pci_irq_by_busid(struct drm_device *dev, struct drm_irq_busid *p) }
/** - * Get interrupt from bus id. - * - * \param inode device inode. - * \param file_priv DRM file private. - * \param cmd command. - * \param arg user argument, pointing to a drm_irq_busid structure. - * \return zero on success or a negative number on failure. + * drm_irq_by_busid - Get interrupt from bus ID + * @dev: DRM device + * @data: IOCTL parameter pointing to a drm_irq_busid structure + * @file_priv: DRM file private. * * Finds the PCI device with the specified bus id and gets its IRQ number. * This IOCTL is deprecated, and will now return EINVAL for any busid not equal * to that of the device that this DRM instance attached to. + * + * Return: 0 on success or a negative error code on failure. */ int drm_irq_by_busid(struct drm_device *dev, void *data, struct drm_file *file_priv) @@ -285,15 +274,16 @@ static struct drm_bus drm_pci_bus = { };
/** - * Register. - * - * \param pdev - PCI device structure - * \param ent entry from the PCI ID table with device type flags - * \return zero on success or a negative number on failure. + * drm_get_pci_dev - Register a PCI device with the DRM subsystem + * @pdev: PCI device + * @ent: entry from the PCI ID table that matches @pdev + * @driver: DRM device driver * * Attempt to gets inter module "drm" information. If we are first * then register the character device and inter module information. * Try and register, if we fail to register, backout previous work. + * + * Return: 0 on success or a negative error code on failure. */ int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent, struct drm_driver *driver) @@ -346,15 +336,14 @@ err_free: EXPORT_SYMBOL(drm_get_pci_dev);
/** - * PCI device initialization. Called direct from modules at load time. + * drm_pci_init - Register matching PCI devices with the DRM subsystem + * @driver: DRM device driver + * @pdriver: PCI device driver * - * \return zero on success or a negative number on failure. + * Initializes a drm_device structures, registering the stubs and initializing + * the AGP device. * - * Initializes a drm_device structures,registering the - * stubs and initializing the AGP device. - * - * Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and - * after the initialization for driver customization. + * Return: 0 on success or a negative error code on failure. */ int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver) { @@ -458,7 +447,14 @@ int drm_pci_set_unique(struct drm_device *dev,
EXPORT_SYMBOL(drm_pci_init);
-/*@}*/ +/** + * drm_pci_exit - Unregister matching PCI devices from the DRM subsystem + * @driver: DRM device driver + * @pdriver: PCI device driver + * + * Unregisters one or more devices matched by a PCI driver from the DRM + * subsystem. + */ void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver) { struct drm_device *dev, *tmp; diff --git a/drivers/gpu/drm/drm_platform.c b/drivers/gpu/drm/drm_platform.c index 234e0bc1ae51..d5b76f148c12 100644 --- a/drivers/gpu/drm/drm_platform.c +++ b/drivers/gpu/drm/drm_platform.c @@ -106,17 +106,16 @@ static struct drm_bus drm_platform_bus = { };
/** - * Platform device initialization. Called direct from modules. + * drm_platform_init - Register a platform device with the DRM subsystem + * @driver: DRM device driver + * @platform_device: platform device to register * - * \return zero on success or a negative number on failure. - * - * Initializes a drm_device structures,registering the - * stubs + * Registers the specified DRM device driver and platform device with the DRM + * subsystem, initializing a drm_device structure and calling the driver's + * .load() function. * - * Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and - * after the initialization for driver customization. + * Return: 0 on success or a negative error code on failure. */ - int drm_platform_init(struct drm_driver *driver, struct platform_device *platform_device) { DRM_DEBUG("\n"); diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index 6d55392376dd..14d16464000a 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -1,16 +1,11 @@ -/** - * \file drm_stub.h - * Stub support - * - * \author Rickard E. (Rik) Faith faith@valinux.com - */ - /* * Created: Fri Jan 19 10:48:35 2001 by faith@acm.org * * Copyright 2001 VA Linux Systems, Inc., Sunnyvale, California. * All Rights Reserved. * + * Author Rickard E. (Rik) Faith faith@valinux.com + * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation @@ -425,11 +420,15 @@ void drm_minor_release(struct drm_minor *minor) }
/** - * Called via drm_exit() at module unload time or when pci device is - * unplugged. + * drm_put_dev - Unregister and release a DRM device + * @dev: DRM device * - * Cleans up all DRM device, calling drm_lastclose(). + * Called at module unload time or when a PCI device is unplugged. * + * Use of this function is discouraged. It will eventually go away completely. + * Please use drm_dev_unregister() and drm_dev_unref() explicitly instead. + * + * Cleans up all DRM device, calling drm_lastclose(). */ void drm_put_dev(struct drm_device *dev) { @@ -536,7 +535,7 @@ static void drm_fs_inode_free(struct inode *inode) }
/** - * drm_dev_alloc - Allocate new drm device + * drm_dev_alloc - Allocate new DRM device * @driver: DRM driver to allocate device for * @parent: Parent device object * @@ -690,6 +689,7 @@ EXPORT_SYMBOL(drm_dev_unref); /** * drm_dev_register - Register DRM device * @dev: Device to register + * @flags: Flags passed to the driver's .load() function * * Register the DRM device @dev with the system, advertise device to user-space * and start normal device operation. @dev must be allocated via drm_dev_alloc() diff --git a/drivers/gpu/drm/drm_usb.c b/drivers/gpu/drm/drm_usb.c index c6c7c29ad46f..f2fe94aab901 100644 --- a/drivers/gpu/drm/drm_usb.c +++ b/drivers/gpu/drm/drm_usb.c @@ -45,7 +45,17 @@ static int drm_usb_set_busid(struct drm_device *dev, static struct drm_bus drm_usb_bus = { .set_busid = drm_usb_set_busid, }; - + +/** + * drm_usb_init - Register matching USB devices with the DRM subsystem + * @driver: DRM device driver + * @udriver: USB device driver + * + * Registers one or more devices matched by a USB driver with the DRM + * subsystem. + * + * Return: 0 on success or a negative error code on failure. + */ int drm_usb_init(struct drm_driver *driver, struct usb_driver *udriver) { int res; @@ -58,6 +68,14 @@ int drm_usb_init(struct drm_driver *driver, struct usb_driver *udriver) } EXPORT_SYMBOL(drm_usb_init);
+/** + * drm_usb_exit - Unregister matching USB devices from the DRM subsystem + * @driver: DRM device driver + * @udriver: USB device driver + * + * Unregisters one or more devices matched by a USB driver from the DRM + * subsystem. + */ void drm_usb_exit(struct drm_driver *driver, struct usb_driver *udriver) {
On Thu, May 22, 2014 at 12:21:22PM +0200, Thierry Reding wrote:
From: Thierry Reding treding@nvidia.com
Describe how devices are registered using the drm_*_init() functions. Adding this to docbook requires a largish set of changes to the comments in drm_{pci,usb,platform}.c since they are doxygen-style rather than proper kernel-doc and therefore mess with the docbook generation.
While at it, mark usage of drm_put_dev() as discouraged in favour of calling drm_dev_unregister() and drm_dev_unref() directly.
Signed-off-by: Thierry Reding treding@nvidia.com
tbh not sure how much value this really provides, since most of these should either be ripped out, moved somewhere else (e.g. the pcie speed cap thing) or deprecated. Otoh pretty docs rarely hurt, so
Acked-by: Daniel Vetter daniel.vetter@ffwll.ch
since I didn't bother to review in-depth. -Daniel
Changes in v3:
- add note that drm_put_dev() should not be used in new drivers
- use !E to include all exported functions in DocBook
Documentation/DocBook/drm.tmpl | 10 ++++++ drivers/gpu/drm/drm_pci.c | 80 ++++++++++++++++++++---------------------- drivers/gpu/drm/drm_platform.c | 15 ++++---- drivers/gpu/drm/drm_stub.c | 22 ++++++------ drivers/gpu/drm/drm_usb.c | 20 ++++++++++- 5 files changed, 85 insertions(+), 62 deletions(-)
diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index ec81c20a17db..438edcd566b5 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -282,6 +282,16 @@ char *date;</synopsis> </sect3> </sect2> <sect2>
<title>Device Registration</title>
<para>
A number of functions are provided to help with device registration.
The functions deal with PCI, USB and platform devices, respectively.
</para>
+!Edrivers/gpu/drm/drm_pci.c +!Edrivers/gpu/drm/drm_usb.c +!Edrivers/gpu/drm/drm_platform.c
</sect2>
<sect2> <title>Driver Load</title> <para> The <methodname>load</methodname> method is the driver and device
diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c index d237de36a07a..020cfd934854 100644 --- a/drivers/gpu/drm/drm_pci.c +++ b/drivers/gpu/drm/drm_pci.c @@ -1,17 +1,3 @@ -/* drm_pci.h -- PCI DMA memory management wrappers for DRM -*- linux-c -*- */ -/**
- \file drm_pci.c
- \brief Functions and ioctls to manage PCI memory
- \warning These interfaces aren't stable yet.
- \todo Implement the remaining ioctl's for the PCI pools.
- \todo The wrappers here are so thin that they would be better off inlined..
- \author José Fonseca jrfonseca@tungstengraphics.com
- \author Leif Delgass ldelgass@retinalburn.net
- */
/*
- Copyright 2003 José Fonseca.
- Copyright 2003 Leif Delgass.
@@ -42,12 +28,14 @@ #include <linux/export.h> #include <drm/drmP.h>
-/**********************************************************************/ -/** \name PCI memory */ -/*@{*/
/**
- \brief Allocate a PCI consistent memory block, for DMA.
- drm_pci_alloc - Allocate a PCI consistent memory block, for DMA.
- @dev: DRM device
- @size: size of block to allocate
- @align: alignment of block
- Return: A handle to the allocated memory block on success or NULL on
*/
- failure.
drm_dma_handle_t *drm_pci_alloc(struct drm_device * dev, size_t size, size_t align) { @@ -88,8 +76,8 @@ drm_dma_handle_t *drm_pci_alloc(struct drm_device * dev, size_t size, size_t ali
EXPORT_SYMBOL(drm_pci_alloc);
-/**
- \brief Free a PCI consistent memory block without freeing its descriptor.
+/*
*/
- Free a PCI consistent memory block without freeing its descriptor.
- This function is for internal use in the Linux-specific DRM core code.
@@ -111,7 +99,9 @@ void __drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah) }
/**
- \brief Free a PCI consistent memory block
- drm_pci_free - Free a PCI consistent memory block
- @dev: DRM device
*/
- @dmah: handle to memory block
void drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah) { @@ -226,17 +216,16 @@ static int drm_pci_irq_by_busid(struct drm_device *dev, struct drm_irq_busid *p) }
/**
- Get interrupt from bus id.
- \param inode device inode.
- \param file_priv DRM file private.
- \param cmd command.
- \param arg user argument, pointing to a drm_irq_busid structure.
- \return zero on success or a negative number on failure.
- drm_irq_by_busid - Get interrupt from bus ID
- @dev: DRM device
- @data: IOCTL parameter pointing to a drm_irq_busid structure
- @file_priv: DRM file private.
- Finds the PCI device with the specified bus id and gets its IRQ number.
- This IOCTL is deprecated, and will now return EINVAL for any busid not equal
- to that of the device that this DRM instance attached to.
*/
- Return: 0 on success or a negative error code on failure.
int drm_irq_by_busid(struct drm_device *dev, void *data, struct drm_file *file_priv) @@ -285,15 +274,16 @@ static struct drm_bus drm_pci_bus = { };
/**
- Register.
- \param pdev - PCI device structure
- \param ent entry from the PCI ID table with device type flags
- \return zero on success or a negative number on failure.
- drm_get_pci_dev - Register a PCI device with the DRM subsystem
- @pdev: PCI device
- @ent: entry from the PCI ID table that matches @pdev
- @driver: DRM device driver
- Attempt to gets inter module "drm" information. If we are first
- then register the character device and inter module information.
- Try and register, if we fail to register, backout previous work.
*/
- Return: 0 on success or a negative error code on failure.
int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent, struct drm_driver *driver) @@ -346,15 +336,14 @@ err_free: EXPORT_SYMBOL(drm_get_pci_dev);
/**
- PCI device initialization. Called direct from modules at load time.
- drm_pci_init - Register matching PCI devices with the DRM subsystem
- @driver: DRM device driver
- @pdriver: PCI device driver
- \return zero on success or a negative number on failure.
- Initializes a drm_device structures, registering the stubs and initializing
- the AGP device.
- Initializes a drm_device structures,registering the
- stubs and initializing the AGP device.
- Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and
- after the initialization for driver customization.
*/
- Return: 0 on success or a negative error code on failure.
int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver) { @@ -458,7 +447,14 @@ int drm_pci_set_unique(struct drm_device *dev,
EXPORT_SYMBOL(drm_pci_init);
-/*@}*/ +/**
- drm_pci_exit - Unregister matching PCI devices from the DRM subsystem
- @driver: DRM device driver
- @pdriver: PCI device driver
- Unregisters one or more devices matched by a PCI driver from the DRM
- subsystem.
- */
void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver) { struct drm_device *dev, *tmp; diff --git a/drivers/gpu/drm/drm_platform.c b/drivers/gpu/drm/drm_platform.c index 234e0bc1ae51..d5b76f148c12 100644 --- a/drivers/gpu/drm/drm_platform.c +++ b/drivers/gpu/drm/drm_platform.c @@ -106,17 +106,16 @@ static struct drm_bus drm_platform_bus = { };
/**
- Platform device initialization. Called direct from modules.
- drm_platform_init - Register a platform device with the DRM subsystem
- @driver: DRM device driver
- @platform_device: platform device to register
- \return zero on success or a negative number on failure.
- Initializes a drm_device structures,registering the
- stubs
- Registers the specified DRM device driver and platform device with the DRM
- subsystem, initializing a drm_device structure and calling the driver's
- .load() function.
- Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and
- after the initialization for driver customization.
*/
- Return: 0 on success or a negative error code on failure.
int drm_platform_init(struct drm_driver *driver, struct platform_device *platform_device) { DRM_DEBUG("\n"); diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index 6d55392376dd..14d16464000a 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -1,16 +1,11 @@ -/**
- \file drm_stub.h
- Stub support
- \author Rickard E. (Rik) Faith faith@valinux.com
- */
/*
- Created: Fri Jan 19 10:48:35 2001 by faith@acm.org
- Copyright 2001 VA Linux Systems, Inc., Sunnyvale, California.
- All Rights Reserved.
- Author Rickard E. (Rik) Faith faith@valinux.com
- Permission is hereby granted, free of charge, to any person obtaining a
- copy of this software and associated documentation files (the "Software"),
- to deal in the Software without restriction, including without limitation
@@ -425,11 +420,15 @@ void drm_minor_release(struct drm_minor *minor) }
/**
- Called via drm_exit() at module unload time or when pci device is
- unplugged.
- drm_put_dev - Unregister and release a DRM device
- @dev: DRM device
- Cleans up all DRM device, calling drm_lastclose().
- Called at module unload time or when a PCI device is unplugged.
- Use of this function is discouraged. It will eventually go away completely.
- Please use drm_dev_unregister() and drm_dev_unref() explicitly instead.
*/
- Cleans up all DRM device, calling drm_lastclose().
void drm_put_dev(struct drm_device *dev) { @@ -536,7 +535,7 @@ static void drm_fs_inode_free(struct inode *inode) }
/**
- drm_dev_alloc - Allocate new drm device
- drm_dev_alloc - Allocate new DRM device
- @driver: DRM driver to allocate device for
- @parent: Parent device object
@@ -690,6 +689,7 @@ EXPORT_SYMBOL(drm_dev_unref); /**
- drm_dev_register - Register DRM device
- @dev: Device to register
- @flags: Flags passed to the driver's .load() function
- Register the DRM device @dev with the system, advertise device to user-space
- and start normal device operation. @dev must be allocated via drm_dev_alloc()
diff --git a/drivers/gpu/drm/drm_usb.c b/drivers/gpu/drm/drm_usb.c index c6c7c29ad46f..f2fe94aab901 100644 --- a/drivers/gpu/drm/drm_usb.c +++ b/drivers/gpu/drm/drm_usb.c @@ -45,7 +45,17 @@ static int drm_usb_set_busid(struct drm_device *dev, static struct drm_bus drm_usb_bus = { .set_busid = drm_usb_set_busid, };
+/**
- drm_usb_init - Register matching USB devices with the DRM subsystem
- @driver: DRM device driver
- @udriver: USB device driver
- Registers one or more devices matched by a USB driver with the DRM
- subsystem.
- Return: 0 on success or a negative error code on failure.
- */
int drm_usb_init(struct drm_driver *driver, struct usb_driver *udriver) { int res; @@ -58,6 +68,14 @@ int drm_usb_init(struct drm_driver *driver, struct usb_driver *udriver) } EXPORT_SYMBOL(drm_usb_init);
+/**
- drm_usb_exit - Unregister matching USB devices from the DRM subsystem
- @driver: DRM device driver
- @udriver: USB device driver
- Unregisters one or more devices matched by a USB driver from the DRM
- subsystem.
- */
void drm_usb_exit(struct drm_driver *driver, struct usb_driver *udriver) { -- 1.9.2
From: Thierry Reding treding@nvidia.com
With the recent addition of the drm_set_unique() function, devices can now be registered without requiring a drm_bus. Add a brief description to the DRM docbook to show how that can be achieved.
Signed-off-by: Thierry Reding treding@nvidia.com --- Changes in v3: - replace drm_dev_put() recommendation by explicit drm_dev_unregister() followed by drm_dev_unref() - use !E in DocBook to insert kernel-doc for all exported symbols
Documentation/DocBook/drm.tmpl | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+)
diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 438edcd566b5..09f8788fec3f 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -142,6 +142,12 @@ to register it with the DRM subsystem. </para> <para> + Newer drivers that no longer require a <structname>drm_bus</structname> + structure can alternatively use the low-level device initialization and + registration functions such as <function>drm_dev_alloc()</function> and + <function>drm_dev_register()</function> directly. + </para> + <para> The <structname>drm_driver</structname> structure contains static information that describes the driver and features it supports, and pointers to methods that the DRM core will call to implement the DRM API. @@ -290,6 +296,26 @@ char *date;</synopsis> !Edrivers/gpu/drm/drm_pci.c !Edrivers/gpu/drm/drm_usb.c !Edrivers/gpu/drm/drm_platform.c + <para> + New drivers that no longer rely on the services provided by the + <structname>drm_bus</structname> structure can call the low-level + device registration functions directly. The + <function>drm_dev_alloc()</function> function can be used to allocate + and initialize a new <structname>drm_device</structname> structure. + Drivers will typically want to perform some additional setup on this + structure, such as allocating driver-specific data and storing a + pointer to it in the DRM device's <structfield>dev_private</structfield> + field. Drivers should also set the device's unique name using the + <function>drm_dev_set_unique()</function> function. After it has been + set up a device can be registered with the DRM subsystem by calling + <function>drm_dev_register()</function>. This will cause the device to + be exposed to userspace and will call the driver's + <structfield>.load()</structfield> implementation. When a device is + removed, the DRM device can safely be unregistered and freed by calling + <function>drm_dev_unregister()</function> followed by a call to + <function>drm_dev_unref()</function>. + </para> +!Edrivers/gpu/drm/drm_stub.c </sect2> <sect2> <title>Driver Load</title>
On Thu, May 22, 2014 at 12:21:23PM +0200, Thierry Reding wrote:
From: Thierry Reding treding@nvidia.com
With the recent addition of the drm_set_unique() function, devices can now be registered without requiring a drm_bus. Add a brief description to the DRM docbook to show how that can be achieved.
Signed-off-by: Thierry Reding treding@nvidia.com
Reviewed-by: Daniel Vetter daniel.vetter@ffwll.ch
Changes in v3:
- replace drm_dev_put() recommendation by explicit drm_dev_unregister() followed by drm_dev_unref()
- use !E in DocBook to insert kernel-doc for all exported symbols
Documentation/DocBook/drm.tmpl | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+)
diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 438edcd566b5..09f8788fec3f 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -142,6 +142,12 @@ to register it with the DRM subsystem. </para> <para>
Newer drivers that no longer require a <structname>drm_bus</structname>
structure can alternatively use the low-level device initialization and
registration functions such as <function>drm_dev_alloc()</function> and
<function>drm_dev_register()</function> directly.
</para>
<para> The <structname>drm_driver</structname> structure contains static information that describes the driver and features it supports, and pointers to methods that the DRM core will call to implement the DRM API.
@@ -290,6 +296,26 @@ char *date;</synopsis> !Edrivers/gpu/drm/drm_pci.c !Edrivers/gpu/drm/drm_usb.c !Edrivers/gpu/drm/drm_platform.c
<para>
New drivers that no longer rely on the services provided by the
<structname>drm_bus</structname> structure can call the low-level
device registration functions directly. The
<function>drm_dev_alloc()</function> function can be used to allocate
and initialize a new <structname>drm_device</structname> structure.
Drivers will typically want to perform some additional setup on this
structure, such as allocating driver-specific data and storing a
pointer to it in the DRM device's <structfield>dev_private</structfield>
field. Drivers should also set the device's unique name using the
<function>drm_dev_set_unique()</function> function. After it has been
set up a device can be registered with the DRM subsystem by calling
<function>drm_dev_register()</function>. This will cause the device to
be exposed to userspace and will call the driver's
<structfield>.load()</structfield> implementation. When a device is
removed, the DRM device can safely be unregistered and freed by calling
<function>drm_dev_unregister()</function> followed by a call to
<function>drm_dev_unref()</function>.
</para>
+!Edrivers/gpu/drm/drm_stub.c </sect2> <sect2> <title>Driver Load</title> -- 1.9.2
From: Thierry Reding treding@nvidia.com
The DRM core can now cope with drivers that don't have an associated struct drm_bus, so the host1x implementation is no longer useful.
Signed-off-by: Thierry Reding treding@nvidia.com --- drivers/gpu/drm/tegra/Makefile | 1 - drivers/gpu/drm/tegra/bus.c | 64 ------------------------------------------ drivers/gpu/drm/tegra/drm.c | 35 +++++++++++++++++++---- drivers/gpu/drm/tegra/drm.h | 4 --- 4 files changed, 30 insertions(+), 74 deletions(-) delete mode 100644 drivers/gpu/drm/tegra/bus.c
diff --git a/drivers/gpu/drm/tegra/Makefile b/drivers/gpu/drm/tegra/Makefile index d43f21bb4596..2c66a8db9da4 100644 --- a/drivers/gpu/drm/tegra/Makefile +++ b/drivers/gpu/drm/tegra/Makefile @@ -1,7 +1,6 @@ ccflags-$(CONFIG_DRM_TEGRA_DEBUG) += -DDEBUG
tegra-drm-y := \ - bus.o \ drm.o \ gem.o \ fb.o \ diff --git a/drivers/gpu/drm/tegra/bus.c b/drivers/gpu/drm/tegra/bus.c deleted file mode 100644 index b3a66d65cb53..000000000000 --- a/drivers/gpu/drm/tegra/bus.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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 *bus = dev->dev->bus->name; - - 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); - - return 0; -} - -static struct drm_bus drm_host1x_bus = { - .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); -} diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index d492c2f12ca8..fd736efd14bd 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c @@ -33,7 +33,6 @@ static int tegra_drm_load(struct drm_device *drm, unsigned long flags) if (!tegra) return -ENOMEM;
- dev_set_drvdata(drm->dev, tegra); mutex_init(&tegra->clients_lock); INIT_LIST_HEAD(&tegra->clients); drm->dev_private = tegra; @@ -644,14 +643,40 @@ int tegra_drm_unregister_client(struct tegra_drm *tegra, return 0; }
-static int host1x_drm_probe(struct host1x_device *device) +static int host1x_drm_probe(struct host1x_device *dev) { - return drm_host1x_init(&tegra_drm_driver, device); + struct drm_driver *driver = &tegra_drm_driver; + struct drm_device *drm; + int err; + + drm = drm_dev_alloc(driver, &dev->dev); + if (!drm) + return -ENOMEM; + + drm_dev_set_unique(drm, dev_name(&dev->dev)); + dev_set_drvdata(&dev->dev, drm); + + err = drm_dev_register(drm, 0); + if (err < 0) + goto unref; + + 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; + +unref: + drm_dev_unref(drm); + return err; }
-static int host1x_drm_remove(struct host1x_device *device) +static int host1x_drm_remove(struct host1x_device *dev) { - drm_host1x_exit(&tegra_drm_driver, device); + struct drm_device *drm = dev_get_drvdata(&dev->dev); + + drm_dev_unregister(drm); + drm_dev_unref(drm);
return 0; } diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h index d100f706d818..0d30689dff01 100644 --- a/drivers/gpu/drm/tegra/drm.h +++ b/drivers/gpu/drm/tegra/drm.h @@ -249,10 +249,6 @@ static inline int tegra_output_check_mode(struct tegra_output *output, return output ? -ENOSYS : -EINVAL; }
-/* from bus.c */ -int drm_host1x_init(struct drm_driver *driver, struct host1x_device *device); -void drm_host1x_exit(struct drm_driver *driver, struct host1x_device *device); - /* from rgb.c */ int tegra_dc_rgb_probe(struct tegra_dc *dc); int tegra_dc_rgb_remove(struct tegra_dc *dc);
dri-devel@lists.freedesktop.org