From 01d73a6967f12fe6c4bbde1834a9fe662264a2eb Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Thu, 27 May 2010 13:40:24 -0600 Subject: drm: Remove drm_resource wrappers Remove the drm_resource wrappers and directly use the actual PCI and/or platform functions in their place. [airlied: fixup nouveau properly to build] Signed-off-by: Jordan Crouse Reviewed-by: Matt Turner Signed-off-by: Dave Airlie --- include/drm/drmP.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'include') diff --git a/include/drm/drmP.h b/include/drm/drmP.h index c1b987158dfa..8f7f5cb4a86d 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1273,10 +1273,6 @@ extern int drm_freebufs(struct drm_device *dev, void *data, extern int drm_mapbufs(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int drm_order(unsigned long size); -extern resource_size_t drm_get_resource_start(struct drm_device *dev, - unsigned int resource); -extern resource_size_t drm_get_resource_len(struct drm_device *dev, - unsigned int resource); /* DMA support (drm_dma.h) */ extern int drm_dma_setup(struct drm_device *dev); -- cgit v1.2.3 From dcdb167402cbdca1d021bdfa5f63995ee0a79317 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Thu, 27 May 2010 13:40:25 -0600 Subject: drm: Add support for platform devices to register as DRM devices Allow platform devices without PCI resources to be DRM devices. [airlied: fixup warnings with dev pointers] Signed-off-by: Jordan Crouse Signed-off-by: Dave Airlie --- drivers/gpu/drm/Kconfig | 4 +- drivers/gpu/drm/Makefile | 2 +- drivers/gpu/drm/drm_drv.c | 37 ++------- drivers/gpu/drm/drm_edid.c | 4 +- drivers/gpu/drm/drm_info.c | 23 ++++-- drivers/gpu/drm/drm_ioctl.c | 71 +++++++++++------ drivers/gpu/drm/drm_irq.c | 15 ++-- drivers/gpu/drm/drm_pci.c | 143 ++++++++++++++++++++++++++++++++++ drivers/gpu/drm/drm_platform.c | 122 +++++++++++++++++++++++++++++ drivers/gpu/drm/drm_stub.c | 89 +-------------------- drivers/gpu/drm/drm_sysfs.c | 3 +- drivers/gpu/drm/i915/i915_dma.c | 1 + drivers/gpu/drm/i915/i915_drv.c | 2 +- drivers/gpu/drm/nouveau/nouveau_drv.c | 2 +- drivers/gpu/drm/radeon/radeon_drv.c | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 2 +- include/drm/drmP.h | 52 +++++++++++-- 17 files changed, 402 insertions(+), 172 deletions(-) create mode 100644 drivers/gpu/drm/drm_platform.c (limited to 'include') diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 88910e5a2c77..520ab23d8a3f 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -6,7 +6,7 @@ # menuconfig DRM tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)" - depends on (AGP || AGP=n) && PCI && !EMULATED_CMPXCHG && MMU + depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && MMU select I2C select I2C_ALGOBIT select SLOW_WORK @@ -17,7 +17,7 @@ menuconfig DRM These modules provide support for synchronization, security, and DMA transfers. Please see for more details. You should also select and configure AGP - (/dev/agpgart) support. + (/dev/agpgart) support if it is available for your platform. config DRM_KMS_HELPER tristate diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index abe3f446ca48..b4b2b480d0ce 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -9,7 +9,7 @@ drm-y := drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \ drm_drv.o drm_fops.o drm_gem.o drm_ioctl.o drm_irq.o \ drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \ drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \ - drm_sysfs.o drm_hashtab.o drm_sman.o drm_mm.o \ + drm_platform.o drm_sysfs.o drm_hashtab.o drm_sman.o drm_mm.o \ drm_crtc.o drm_modes.o drm_edid.o \ drm_info.o drm_debugfs.o drm_encoder_slave.o diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 4a66201edaec..510bc87d98f6 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -243,47 +243,20 @@ int drm_lastclose(struct drm_device * dev) * * Initializes an array of drm_device structures, and attempts to * initialize all available devices, using consecutive minors, registering the - * stubs and initializing the AGP device. + * stubs and initializing the device. * * Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and * after the initialization for driver customization. */ int drm_init(struct drm_driver *driver) { - struct pci_dev *pdev = NULL; - const struct pci_device_id *pid; - int i; - DRM_DEBUG("\n"); - INIT_LIST_HEAD(&driver->device_list); - if (driver->driver_features & DRIVER_MODESET) - return pci_register_driver(&driver->pci_driver); - - /* If not using KMS, fall back to stealth mode manual scanning. */ - for (i = 0; driver->pci_driver.id_table[i].vendor != 0; i++) { - pid = &driver->pci_driver.id_table[i]; - - /* Loop around setting up a DRM device for each PCI device - * matching our ID and device class. If we had the internal - * function that pci_get_subsys and pci_get_class used, we'd - * be able to just pass pid in instead of doing a two-stage - * thing. - */ - pdev = NULL; - while ((pdev = - pci_get_subsys(pid->vendor, pid->device, pid->subvendor, - pid->subdevice, pdev)) != NULL) { - if ((pdev->class & pid->class_mask) != pid->class) - continue; - - /* stealth mode requires a manual probe */ - pci_dev_get(pdev); - drm_get_dev(pdev, pid, driver); - } - } - return 0; + if (driver->driver_features & DRIVER_USE_PLATFORM_DEVICE) + return drm_platform_init(driver); + else + return drm_pci_init(driver); } EXPORT_SYMBOL(drm_init); diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index c1981861bbbd..83d8072066cb 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -282,7 +282,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) return block; carp: - dev_warn(&connector->dev->pdev->dev, "%s: EDID block %d invalid.\n", + dev_warn(connector->dev->dev, "%s: EDID block %d invalid.\n", drm_get_connector_name(connector), j); out: @@ -1626,7 +1626,7 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid) return 0; } if (!drm_edid_is_valid(edid)) { - dev_warn(&connector->dev->pdev->dev, "%s: EDID invalid.\n", + dev_warn(connector->dev->dev, "%s: EDID invalid.\n", drm_get_connector_name(connector)); return 0; } diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c index f0f6c6b93f3a..2ef2c7827243 100644 --- a/drivers/gpu/drm/drm_info.c +++ b/drivers/gpu/drm/drm_info.c @@ -51,13 +51,24 @@ int drm_name_info(struct seq_file *m, void *data) if (!master) return 0; - if (master->unique) { - seq_printf(m, "%s %s %s\n", - dev->driver->pci_driver.name, - pci_name(dev->pdev), master->unique); + if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE)) { + if (master->unique) { + seq_printf(m, "%s %s %s\n", + dev->driver->platform_device->name, + dev_name(dev->dev), master->unique); + } else { + seq_printf(m, "%s\n", + dev->driver->platform_device->name); + } } else { - seq_printf(m, "%s %s\n", dev->driver->pci_driver.name, - pci_name(dev->pdev)); + if (master->unique) { + seq_printf(m, "%s %s %s\n", + dev->driver->pci_driver.name, + dev_name(dev->dev), master->unique); + } else { + seq_printf(m, "%s %s\n", dev->driver->pci_driver.name, + dev_name(dev->dev)); + } } return 0; diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index 9b9ff46c2378..76d3d18056dd 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -132,32 +132,57 @@ static int drm_set_busid(struct drm_device *dev, struct drm_file *file_priv) struct drm_master *master = file_priv->master; int len; - if (master->unique != NULL) - return -EBUSY; - - master->unique_len = 40; - master->unique_size = master->unique_len; - master->unique = kmalloc(master->unique_size, GFP_KERNEL); - if (master->unique == NULL) - return -ENOMEM; + if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE)) { + master->unique_len = 10 + strlen(dev->platformdev->name); + master->unique = kmalloc(master->unique_len + 1, GFP_KERNEL); + + if (master->unique == NULL) + return -ENOMEM; + + len = snprintf(master->unique, master->unique_len, + "platform:%s", dev->platformdev->name); + + if (len > master->unique_len) + DRM_ERROR("Unique buffer overflowed\n"); + + dev->devname = + kmalloc(strlen(dev->platformdev->name) + + master->unique_len + 2, GFP_KERNEL); + + if (dev->devname == NULL) + return -ENOMEM; + + sprintf(dev->devname, "%s@%s", dev->platformdev->name, + master->unique); + + } else { + master->unique_len = 40; + master->unique_size = master->unique_len; + master->unique = kmalloc(master->unique_size, GFP_KERNEL); + if (master->unique == NULL) + return -ENOMEM; + + len = snprintf(master->unique, master->unique_len, + "pci:%04x:%02x:%02x.%d", + drm_get_pci_domain(dev), + dev->pdev->bus->number, + PCI_SLOT(dev->pdev->devfn), + PCI_FUNC(dev->pdev->devfn)); + if (len >= master->unique_len) + DRM_ERROR("buffer overflow"); + else + master->unique_len = len; - len = snprintf(master->unique, master->unique_len, "pci:%04x:%02x:%02x.%d", - drm_get_pci_domain(dev), - dev->pdev->bus->number, - PCI_SLOT(dev->pdev->devfn), - PCI_FUNC(dev->pdev->devfn)); - if (len >= master->unique_len) - DRM_ERROR("buffer overflow"); - else - master->unique_len = len; + dev->devname = + kmalloc(strlen(dev->driver->pci_driver.name) + + master->unique_len + 2, GFP_KERNEL); - dev->devname = kmalloc(strlen(dev->driver->pci_driver.name) + - master->unique_len + 2, GFP_KERNEL); - if (dev->devname == NULL) - return -ENOMEM; + if (dev->devname == NULL) + return -ENOMEM; - sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name, - master->unique); + sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name, + master->unique); + } return 0; } diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index a263b7070fc6..6353b625e099 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -57,6 +57,9 @@ int drm_irq_by_busid(struct drm_device *dev, void *data, { struct drm_irq_busid *p = data; + if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE)) + return -EINVAL; + if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) return -EINVAL; @@ -211,7 +214,7 @@ int drm_irq_install(struct drm_device *dev) if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) return -EINVAL; - if (dev->pdev->irq == 0) + if (drm_dev_to_irq(dev) == 0) return -EINVAL; mutex_lock(&dev->struct_mutex); @@ -229,7 +232,7 @@ int drm_irq_install(struct drm_device *dev) dev->irq_enabled = 1; mutex_unlock(&dev->struct_mutex); - DRM_DEBUG("irq=%d\n", dev->pdev->irq); + DRM_DEBUG("irq=%d\n", drm_dev_to_irq(dev)); /* Before installing handler */ dev->driver->irq_preinstall(dev); @@ -302,14 +305,14 @@ int drm_irq_uninstall(struct drm_device * dev) if (!irq_enabled) return -EINVAL; - DRM_DEBUG("irq=%d\n", dev->pdev->irq); + DRM_DEBUG("irq=%d\n", drm_dev_to_irq(dev)); if (!drm_core_check_feature(dev, DRIVER_MODESET)) vga_client_register(dev->pdev, NULL, NULL, NULL); dev->driver->irq_uninstall(dev); - free_irq(dev->pdev->irq, dev); + free_irq(drm_dev_to_irq(dev), dev); return 0; } @@ -341,7 +344,7 @@ int drm_control(struct drm_device *dev, void *data, if (drm_core_check_feature(dev, DRIVER_MODESET)) return 0; if (dev->if_version < DRM_IF_VERSION(1, 2) && - ctl->irq != dev->pdev->irq) + ctl->irq != drm_dev_to_irq(dev)) return -EINVAL; return drm_irq_install(dev); case DRM_UNINST_HANDLER: @@ -651,7 +654,7 @@ int drm_wait_vblank(struct drm_device *dev, void *data, int ret = 0; unsigned int flags, seq, crtc; - if ((!dev->pdev->irq) || (!dev->irq_enabled)) + if ((!drm_dev_to_irq(dev)) || (!dev->irq_enabled)) return -EINVAL; if (vblwait->request.type & _DRM_VBLANK_SIGNAL) diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c index 2ea9ad4a8d69..e20f78b542a7 100644 --- a/drivers/gpu/drm/drm_pci.c +++ b/drivers/gpu/drm/drm_pci.c @@ -124,4 +124,147 @@ void drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah) EXPORT_SYMBOL(drm_pci_free); +#ifdef CONFIG_PCI +/** + * 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. + * + * 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. + */ +int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent, + struct drm_driver *driver) +{ + struct drm_device *dev; + int ret; + + DRM_DEBUG("\n"); + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return -ENOMEM; + + ret = pci_enable_device(pdev); + if (ret) + goto err_g1; + + pci_set_master(pdev); + + dev->pdev = pdev; + dev->dev = &pdev->dev; + + dev->pci_device = pdev->device; + dev->pci_vendor = pdev->vendor; + +#ifdef __alpha__ + dev->hose = pdev->sysdata; +#endif + + if ((ret = drm_fill_in_dev(dev, ent, driver))) { + printk(KERN_ERR "DRM: Fill_in_dev failed.\n"); + goto err_g2; + } + + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + pci_set_drvdata(pdev, dev); + ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL); + if (ret) + goto err_g2; + } + + if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY))) + goto err_g3; + + if (dev->driver->load) { + ret = dev->driver->load(dev, ent->driver_data); + if (ret) + goto err_g4; + } + + /* setup the grouping for the legacy output */ + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + ret = drm_mode_group_init_legacy_group(dev, + &dev->primary->mode_group); + if (ret) + goto err_g4; + } + + list_add_tail(&dev->driver_item, &driver->device_list); + + DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n", + driver->name, driver->major, driver->minor, driver->patchlevel, + driver->date, pci_name(pdev), dev->primary->index); + + return 0; + +err_g4: + drm_put_minor(&dev->primary); +err_g3: + if (drm_core_check_feature(dev, DRIVER_MODESET)) + drm_put_minor(&dev->control); +err_g2: + pci_disable_device(pdev); +err_g1: + kfree(dev); + return ret; +} +EXPORT_SYMBOL(drm_get_pci_dev); + +/** + * PCI device initialization. Called via drm_init at module load time, + * + * \return zero on success or a negative number on failure. + * + * 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. + */ +int drm_pci_init(struct drm_driver *driver) +{ + struct pci_dev *pdev = NULL; + const struct pci_device_id *pid; + int i; + + if (driver->driver_features & DRIVER_MODESET) + return pci_register_driver(&driver->pci_driver); + + /* If not using KMS, fall back to stealth mode manual scanning. */ + for (i = 0; driver->pci_driver.id_table[i].vendor != 0; i++) { + pid = &driver->pci_driver.id_table[i]; + + /* Loop around setting up a DRM device for each PCI device + * matching our ID and device class. If we had the internal + * function that pci_get_subsys and pci_get_class used, we'd + * be able to just pass pid in instead of doing a two-stage + * thing. + */ + pdev = NULL; + while ((pdev = + pci_get_subsys(pid->vendor, pid->device, pid->subvendor, + pid->subdevice, pdev)) != NULL) { + if ((pdev->class & pid->class_mask) != pid->class) + continue; + + /* stealth mode requires a manual probe */ + pci_dev_get(pdev); + drm_get_pci_dev(pdev, pid, driver); + } + } + return 0; +} + +#else + +int drm_pci_init(struct drm_driver *driver) +{ + return -1; +} + +#endif /*@}*/ diff --git a/drivers/gpu/drm/drm_platform.c b/drivers/gpu/drm/drm_platform.c new file mode 100644 index 000000000000..460e9a3afa8d --- /dev/null +++ b/drivers/gpu/drm/drm_platform.c @@ -0,0 +1,122 @@ +/* + * Derived from drm_pci.c + * + * Copyright 2003 José Fonseca. + * Copyright 2003 Leif Delgass. + * Copyright (c) 2009, Code Aurora Forum. + * All Rights Reserved. + * + * 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 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "drmP.h" + +/** + * Register. + * + * \param platdev - Platform device struture + * \return zero on success or a negative number on failure. + * + * 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. + */ + +int drm_get_platform_dev(struct platform_device *platdev, + struct drm_driver *driver) +{ + struct drm_device *dev; + int ret; + + DRM_DEBUG("\n"); + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return -ENOMEM; + + dev->platformdev = platdev; + dev->dev = &platdev->dev; + + ret = drm_fill_in_dev(dev, NULL, driver); + + if (ret) { + printk(KERN_ERR "DRM: Fill_in_dev failed.\n"); + goto err_g1; + } + + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + dev_set_drvdata(&platdev->dev, dev); + ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL); + if (ret) + goto err_g1; + } + + ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY); + if (ret) + goto err_g2; + + if (dev->driver->load) { + ret = dev->driver->load(dev, 0); + if (ret) + goto err_g3; + } + + /* setup the grouping for the legacy output */ + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + ret = drm_mode_group_init_legacy_group(dev, + &dev->primary->mode_group); + if (ret) + goto err_g3; + } + + list_add_tail(&dev->driver_item, &driver->device_list); + + DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", + driver->name, driver->major, driver->minor, driver->patchlevel, + driver->date, dev->primary->index); + + return 0; + +err_g3: + drm_put_minor(&dev->primary); +err_g2: + if (drm_core_check_feature(dev, DRIVER_MODESET)) + drm_put_minor(&dev->control); +err_g1: + kfree(dev); + return ret; +} +EXPORT_SYMBOL(drm_get_platform_dev); + +/** + * Platform device initialization. Called via drm_init at module load time, + * + * \return zero on success or a negative number on failure. + * + * Initializes a drm_device structures,registering the + * stubs + * + * Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and + * after the initialization for driver customization. + */ + +int drm_platform_init(struct drm_driver *driver) +{ + return drm_get_platform_dev(driver->platform_device, driver); +} diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index a0c365f2e521..63575e2fa882 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -224,7 +224,7 @@ int drm_dropmaster_ioctl(struct drm_device *dev, void *data, return 0; } -static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev, +int drm_fill_in_dev(struct drm_device *dev, const struct pci_device_id *ent, struct drm_driver *driver) { @@ -245,14 +245,6 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev, idr_init(&dev->drw_idr); - dev->pdev = pdev; - dev->pci_device = pdev->device; - dev->pci_vendor = pdev->vendor; - -#ifdef __alpha__ - dev->hose = pdev->sysdata; -#endif - if (drm_ht_create(&dev->map_hash, 12)) { return -ENOMEM; } @@ -321,7 +313,7 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev, * create the proc init entry via proc_init(). This routines assigns * minor numbers to secondary heads of multi-headed cards */ -static int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int type) +int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int type) { struct drm_minor *new_minor; int ret; @@ -387,83 +379,6 @@ err_idr: return ret; } -/** - * 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. - * - * 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. - */ -int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, - struct drm_driver *driver) -{ - struct drm_device *dev; - int ret; - - DRM_DEBUG("\n"); - - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) - return -ENOMEM; - - ret = pci_enable_device(pdev); - if (ret) - goto err_g1; - - pci_set_master(pdev); - if ((ret = drm_fill_in_dev(dev, pdev, ent, driver))) { - printk(KERN_ERR "DRM: Fill_in_dev failed.\n"); - goto err_g2; - } - - if (drm_core_check_feature(dev, DRIVER_MODESET)) { - pci_set_drvdata(pdev, dev); - ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL); - if (ret) - goto err_g2; - } - - if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY))) - goto err_g3; - - if (dev->driver->load) { - ret = dev->driver->load(dev, ent->driver_data); - if (ret) - goto err_g4; - } - - /* setup the grouping for the legacy output */ - if (drm_core_check_feature(dev, DRIVER_MODESET)) { - ret = drm_mode_group_init_legacy_group(dev, &dev->primary->mode_group); - if (ret) - goto err_g4; - } - - list_add_tail(&dev->driver_item, &driver->device_list); - - DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n", - driver->name, driver->major, driver->minor, driver->patchlevel, - driver->date, pci_name(pdev), dev->primary->index); - - return 0; - -err_g4: - drm_put_minor(&dev->primary); -err_g3: - if (drm_core_check_feature(dev, DRIVER_MODESET)) - drm_put_minor(&dev->control); -err_g2: - pci_disable_device(pdev); -err_g1: - kfree(dev); - return ret; -} -EXPORT_SYMBOL(drm_get_dev); - /** * Put a secondary minor number. * diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index 3a3a451d0bf8..14d9d829ef27 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c @@ -488,7 +488,8 @@ int drm_sysfs_device_add(struct drm_minor *minor) int err; char *minor_str; - minor->kdev.parent = &minor->dev->pdev->dev; + minor->kdev.parent = minor->dev->dev; + minor->kdev.class = drm_class; minor->kdev.release = drm_sysfs_device_release; minor->kdev.devt = minor->device; diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 9fe2d08d9e9d..9bed5617e0ea 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -34,6 +34,7 @@ #include "i915_drm.h" #include "i915_drv.h" #include "i915_trace.h" +#include #include #include #include diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 5c51e45ab68d..b7aecf5ea1fc 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -435,7 +435,7 @@ int i965_reset(struct drm_device *dev, u8 flags) static int __devinit i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - return drm_get_dev(pdev, ent, &driver); + return drm_get_pci_dev(pdev, ent, &driver); } static void diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c index c6079e36669d..f60a2b2ae445 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.c +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c @@ -132,7 +132,7 @@ static struct drm_driver driver; static int __devinit nouveau_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - return drm_get_dev(pdev, ent, &driver); + return drm_get_pci_dev(pdev, ent, &driver); } static void diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 4afba1eca2a7..683e281b4092 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -236,7 +236,7 @@ static struct drm_driver kms_driver; static int __devinit radeon_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - return drm_get_dev(pdev, ent, &kms_driver); + return drm_get_pci_dev(pdev, ent, &kms_driver); } static void diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 0c9c0811f42d..f7f248dbff58 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -758,7 +758,7 @@ static struct drm_driver driver = { static int vmw_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - return drm_get_dev(pdev, ent, &driver); + return drm_get_pci_dev(pdev, ent, &driver); } static int __init vmwgfx_init(void) diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 8f7f5cb4a86d..6235169d5950 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -9,6 +9,7 @@ /* * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. + * Copyright (c) 2009-2010, Code Aurora Forum. * All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -48,6 +49,7 @@ #include #include #include +#include #include #include #include /* For (un)lock_kernel */ @@ -144,6 +146,7 @@ extern void drm_ut_debug_printk(unsigned int request_level, #define DRIVER_IRQ_VBL2 0x800 #define DRIVER_GEM 0x1000 #define DRIVER_MODESET 0x2000 +#define DRIVER_USE_PLATFORM_DEVICE 0x4000 /***********************************************************************/ /** \name Begin the DRM... */ @@ -823,6 +826,7 @@ struct drm_driver { int num_ioctls; struct file_operations fops; struct pci_driver pci_driver; + struct platform_device *platform_device; /* List of devices hanging off this driver */ struct list_head device_list; }; @@ -1015,12 +1019,16 @@ struct drm_device { struct drm_agp_head *agp; /**< AGP data */ + struct device *dev; /**< Device structure */ struct pci_dev *pdev; /**< PCI device structure */ int pci_vendor; /**< PCI vendor id */ int pci_device; /**< PCI device id */ #ifdef __alpha__ struct pci_controller *hose; #endif + + struct platform_device *platformdev; /**< Platform device struture */ + struct drm_sg_mem *sg; /**< Scatter gather memory */ int num_crtcs; /**< Number of CRTCs on this device */ void *dev_private; /**< device private data */ @@ -1060,17 +1068,21 @@ struct drm_device { }; -static inline int drm_dev_to_irq(struct drm_device *dev) -{ - return dev->pdev->irq; -} - static __inline__ int drm_core_check_feature(struct drm_device *dev, int feature) { return ((dev->driver->driver_features & feature) ? 1 : 0); } + +static inline int drm_dev_to_irq(struct drm_device *dev) +{ + if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE)) + return platform_get_irq(dev->platformdev, 0); + else + return dev->pdev->irq; +} + #ifdef __alpha__ #define drm_get_pci_domain(dev) dev->hose->index #else @@ -1347,8 +1359,11 @@ extern int drm_dropmaster_ioctl(struct drm_device *dev, void *data, struct drm_master *drm_master_create(struct drm_minor *minor); extern struct drm_master *drm_master_get(struct drm_master *master); extern void drm_master_put(struct drm_master **master); -extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, - struct drm_driver *driver); +extern int drm_get_pci_dev(struct pci_dev *pdev, + const struct pci_device_id *ent, + struct drm_driver *driver); +extern int drm_get_platform_dev(struct platform_device *pdev, + struct drm_driver *driver); extern void drm_put_dev(struct drm_device *dev); extern int drm_put_minor(struct drm_minor **minor); extern unsigned int drm_debug; @@ -1525,6 +1540,9 @@ static __inline__ struct drm_local_map *drm_core_findmap(struct drm_device *dev, static __inline__ int drm_device_is_agp(struct drm_device *dev) { + if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE)) + return 0; + if (dev->driver->device_is_agp != NULL) { int err = (*dev->driver->device_is_agp) (dev); @@ -1538,7 +1556,10 @@ static __inline__ int drm_device_is_agp(struct drm_device *dev) static __inline__ int drm_device_is_pcie(struct drm_device *dev) { - return pci_find_capability(dev->pdev, PCI_CAP_ID_EXP); + if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE)) + return 0; + else + return pci_find_capability(dev->pdev, PCI_CAP_ID_EXP); } static __inline__ void drm_core_dropmap(struct drm_local_map *map) @@ -1546,6 +1567,21 @@ static __inline__ void drm_core_dropmap(struct drm_local_map *map) } #include "drm_mem_util.h" + +static inline void *drm_get_device(struct drm_device *dev) +{ + if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE)) + return dev->platformdev; + else + return dev->pdev; +} + +extern int drm_platform_init(struct drm_driver *driver); +extern int drm_pci_init(struct drm_driver *driver); +extern int drm_fill_in_dev(struct drm_device *dev, + const struct pci_device_id *ent, + struct drm_driver *driver); +int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int type); /*@}*/ #endif /* __KERNEL__ */ -- cgit v1.2.3 From b9c2c9ae882f058084e13e339925dbf8d2d20271 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 1 Jul 2010 16:48:09 -0700 Subject: drm: add per-event vblank event trace points Allows us to track each process that requests and completes events. Signed-off-by: Jesse Barnes Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_irq.c | 8 +++++++ drivers/gpu/drm/drm_trace.h | 57 ++++++++++++++++++++++++++++++++++----------- include/drm/drmP.h | 2 ++ 3 files changed, 53 insertions(+), 14 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 6d201a89441c..c2ecb3ed009f 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -588,6 +588,7 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe, return -ENOMEM; e->pipe = pipe; + e->base.pid = current->pid; e->event.base.type = DRM_EVENT_VBLANK; e->event.base.length = sizeof e->event; e->event.user_data = vblwait->request.signal; @@ -615,6 +616,9 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe, DRM_DEBUG("event on vblank count %d, current %d, crtc %d\n", vblwait->request.sequence, seq, pipe); + trace_drm_vblank_event_queued(current->pid, pipe, + vblwait->request.sequence); + e->event.sequence = vblwait->request.sequence; if ((seq - vblwait->request.sequence) <= (1 << 23)) { e->event.tv_sec = now.tv_sec; @@ -622,6 +626,8 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe, drm_vblank_put(dev, e->pipe); list_add_tail(&e->base.link, &e->base.file_priv->event_list); wake_up_interruptible(&e->base.file_priv->event_wait); + trace_drm_vblank_event_delivered(current->pid, pipe, + vblwait->request.sequence); } else { list_add_tail(&e->base.link, &dev->vblank_event_list); } @@ -752,6 +758,8 @@ void drm_handle_vblank_events(struct drm_device *dev, int crtc) drm_vblank_put(dev, e->pipe); list_move_tail(&e->base.link, &e->base.file_priv->event_list); wake_up_interruptible(&e->base.file_priv->event_wait); + trace_drm_vblank_event_delivered(e->base.pid, e->pipe, + e->event.sequence); } spin_unlock_irqrestore(&dev->event_lock, flags); diff --git a/drivers/gpu/drm/drm_trace.h b/drivers/gpu/drm/drm_trace.h index 8a92683f14ec..03ea964aa604 100644 --- a/drivers/gpu/drm/drm_trace.h +++ b/drivers/gpu/drm/drm_trace.h @@ -11,22 +11,51 @@ #define TRACE_INCLUDE_FILE drm_trace TRACE_EVENT(drm_vblank_event, + TP_PROTO(int crtc, unsigned int seq), + TP_ARGS(crtc, seq), + TP_STRUCT__entry( + __field(int, crtc) + __field(unsigned int, seq) + ), + TP_fast_assign( + __entry->crtc = crtc; + __entry->seq = seq; + ), + TP_printk("crtc=%d, seq=%d", __entry->crtc, __entry->seq) +); - TP_PROTO(int crtc, unsigned int seq), - - TP_ARGS(crtc, seq), - - TP_STRUCT__entry( - __field(int, crtc) - __field(unsigned int, seq) - ), - - TP_fast_assign( - __entry->crtc = crtc; - __entry->seq = seq; - ), +TRACE_EVENT(drm_vblank_event_queued, + TP_PROTO(pid_t pid, int crtc, unsigned int seq), + TP_ARGS(pid, crtc, seq), + TP_STRUCT__entry( + __field(pid_t, pid) + __field(int, crtc) + __field(unsigned int, seq) + ), + TP_fast_assign( + __entry->pid = pid; + __entry->crtc = crtc; + __entry->seq = seq; + ), + TP_printk("pid=%d, crtc=%d, seq=%d", __entry->pid, __entry->crtc, \ + __entry->seq) +); - TP_printk("crtc=%d, seq=%d", __entry->crtc, __entry->seq) +TRACE_EVENT(drm_vblank_event_delivered, + TP_PROTO(pid_t pid, int crtc, unsigned int seq), + TP_ARGS(pid, crtc, seq), + TP_STRUCT__entry( + __field(pid_t, pid) + __field(int, crtc) + __field(unsigned int, seq) + ), + TP_fast_assign( + __entry->pid = pid; + __entry->crtc = crtc; + __entry->seq = seq; + ), + TP_printk("pid=%d, crtc=%d, seq=%d", __entry->pid, __entry->crtc, \ + __entry->seq) ); #endif /* _DRM_TRACE_H_ */ diff --git a/include/drm/drmP.h b/include/drm/drmP.h index c1b987158dfa..8364a705f125 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -403,6 +403,8 @@ struct drm_pending_event { struct drm_event *event; struct list_head link; struct drm_file *file_priv; + pid_t pid; /* pid of requester, no guarantee it's valid by the time + we deliver the event, for tracing only */ void (*destroy)(struct drm_pending_event *event); }; -- cgit v1.2.3 From db3307a9f7b8078c654021e3b35354a2b09a8e67 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 2 Jul 2010 15:02:12 +0100 Subject: drm: kill drm_mm_node->private Only ever assigned, never used. Signed-off-by: Daniel Vetter [glisse: I will re-add if needed for range-restricted allocations] Signed-off-by: Chris Wilson Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/i915_gem.c | 4 +--- drivers/gpu/drm/ttm/ttm_bo.c | 6 ------ drivers/gpu/drm/ttm/ttm_bo_util.c | 2 -- include/drm/drm_mm.h | 1 - 4 files changed, 1 insertion(+), 12 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 074385882ccf..75061b305b8c 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2633,10 +2633,8 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) if (free_space != NULL) { obj_priv->gtt_space = drm_mm_get_block(free_space, obj->size, alignment); - if (obj_priv->gtt_space != NULL) { - obj_priv->gtt_space->private = obj; + if (obj_priv->gtt_space != NULL) obj_priv->gtt_offset = obj_priv->gtt_space->start; - } } if (obj_priv->gtt_space == NULL) { /* If the gtt is empty and we're still having trouble diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 555ebb12ace8..9763288c6b2d 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -476,7 +476,6 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo, bool remove_all) ++put_count; } if (bo->mem.mm_node) { - bo->mem.mm_node->private = NULL; drm_mm_put_block(bo->mem.mm_node); bo->mem.mm_node = NULL; } @@ -670,7 +669,6 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo, bool interruptible, printk(KERN_ERR TTM_PFX "Buffer eviction failed\n"); spin_lock(&glob->lru_lock); if (evict_mem.mm_node) { - evict_mem.mm_node->private = NULL; drm_mm_put_block(evict_mem.mm_node); evict_mem.mm_node = NULL; } @@ -929,8 +927,6 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo, mem->mm_node = node; mem->mem_type = mem_type; mem->placement = cur_flags; - if (node) - node->private = bo; return 0; } @@ -973,7 +969,6 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo, interruptible, no_wait_reserve, no_wait_gpu); if (ret == 0 && mem->mm_node) { mem->placement = cur_flags; - mem->mm_node->private = bo; return 0; } if (ret == -ERESTARTSYS) @@ -1029,7 +1024,6 @@ int ttm_bo_move_buffer(struct ttm_buffer_object *bo, out_unlock: if (ret && mem.mm_node) { spin_lock(&glob->lru_lock); - mem.mm_node->private = NULL; drm_mm_put_block(mem.mm_node); spin_unlock(&glob->lru_lock); } diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 13012a1f1486..7cffb3e04232 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -353,8 +353,6 @@ static int ttm_buffer_object_transfer(struct ttm_buffer_object *bo, fbo->vm_node = NULL; fbo->sync_obj = driver->sync_obj_ref(bo->sync_obj); - if (fbo->mem.mm_node) - fbo->mem.mm_node->private = (void *)fbo; kref_init(&fbo->list_kref); kref_init(&fbo->kref); fbo->destroy = &ttm_transfered_destroy; diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h index 4c10be39a43b..da94071b1703 100644 --- a/include/drm/drm_mm.h +++ b/include/drm/drm_mm.h @@ -48,7 +48,6 @@ struct drm_mm_node { unsigned long start; unsigned long size; struct drm_mm *mm; - void *private; }; struct drm_mm { -- cgit v1.2.3 From d1024ce91ff4c2c4ccbf692d204c71cbf215157a Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 2 Jul 2010 15:02:14 +0100 Subject: drm: sane naming for drm_mm.c Yeah, I've kinda noticed that fl_entry is the free stack. Still give it (and the memory node list ml_entry) decent names. Signed-off-by: Daniel Vetter Acked-by: Thomas Hellstrom Signed-off-by: Chris Wilson Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_mm.c | 72 +++++++++++++++++++++++------------------------- include/drm/drm_mm.h | 11 +++++--- 2 files changed, 42 insertions(+), 41 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index a5a7a16c4301..d2267ffd2b7a 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -64,8 +64,8 @@ static struct drm_mm_node *drm_mm_kmalloc(struct drm_mm *mm, int atomic) else { child = list_entry(mm->unused_nodes.next, - struct drm_mm_node, fl_entry); - list_del(&child->fl_entry); + struct drm_mm_node, free_stack); + list_del(&child->free_stack); --mm->num_unused; } spin_unlock(&mm->unused_lock); @@ -94,7 +94,7 @@ int drm_mm_pre_get(struct drm_mm *mm) return ret; } ++mm->num_unused; - list_add_tail(&node->fl_entry, &mm->unused_nodes); + list_add_tail(&node->free_stack, &mm->unused_nodes); } spin_unlock(&mm->unused_lock); return 0; @@ -116,8 +116,8 @@ static int drm_mm_create_tail_node(struct drm_mm *mm, child->start = start; child->mm = mm; - list_add_tail(&child->ml_entry, &mm->ml_entry); - list_add_tail(&child->fl_entry, &mm->fl_entry); + list_add_tail(&child->node_list, &mm->node_list); + list_add_tail(&child->free_stack, &mm->free_stack); return 0; } @@ -132,15 +132,15 @@ static struct drm_mm_node *drm_mm_split_at_start(struct drm_mm_node *parent, if (unlikely(child == NULL)) return NULL; - INIT_LIST_HEAD(&child->fl_entry); + INIT_LIST_HEAD(&child->free_stack); child->free = 0; child->size = size; child->start = parent->start; child->mm = parent->mm; - list_add_tail(&child->ml_entry, &parent->ml_entry); - INIT_LIST_HEAD(&child->fl_entry); + list_add_tail(&child->node_list, &parent->node_list); + INIT_LIST_HEAD(&child->free_stack); parent->size -= size; parent->start += size; @@ -168,7 +168,7 @@ struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *node, } if (node->size == size) { - list_del_init(&node->fl_entry); + list_del_init(&node->free_stack); node->free = 0; } else { node = drm_mm_split_at_start(node, size, atomic); @@ -206,7 +206,7 @@ struct drm_mm_node *drm_mm_get_block_range_generic(struct drm_mm_node *node, } if (node->size == size) { - list_del_init(&node->fl_entry); + list_del_init(&node->free_stack); node->free = 0; } else { node = drm_mm_split_at_start(node, size, atomic); @@ -228,8 +228,8 @@ void drm_mm_put_block(struct drm_mm_node *cur) { struct drm_mm *mm = cur->mm; - struct list_head *cur_head = &cur->ml_entry; - struct list_head *root_head = &mm->ml_entry; + struct list_head *cur_head = &cur->node_list; + struct list_head *root_head = &mm->node_list; struct drm_mm_node *prev_node = NULL; struct drm_mm_node *next_node; @@ -237,7 +237,7 @@ void drm_mm_put_block(struct drm_mm_node *cur) if (cur_head->prev != root_head) { prev_node = - list_entry(cur_head->prev, struct drm_mm_node, ml_entry); + list_entry(cur_head->prev, struct drm_mm_node, node_list); if (prev_node->free) { prev_node->size += cur->size; merged = 1; @@ -245,15 +245,15 @@ void drm_mm_put_block(struct drm_mm_node *cur) } if (cur_head->next != root_head) { next_node = - list_entry(cur_head->next, struct drm_mm_node, ml_entry); + list_entry(cur_head->next, struct drm_mm_node, node_list); if (next_node->free) { if (merged) { prev_node->size += next_node->size; - list_del(&next_node->ml_entry); - list_del(&next_node->fl_entry); + list_del(&next_node->node_list); + list_del(&next_node->free_stack); spin_lock(&mm->unused_lock); if (mm->num_unused < MM_UNUSED_TARGET) { - list_add(&next_node->fl_entry, + list_add(&next_node->free_stack, &mm->unused_nodes); ++mm->num_unused; } else @@ -268,12 +268,12 @@ void drm_mm_put_block(struct drm_mm_node *cur) } if (!merged) { cur->free = 1; - list_add(&cur->fl_entry, &mm->fl_entry); + list_add(&cur->free_stack, &mm->free_stack); } else { - list_del(&cur->ml_entry); + list_del(&cur->node_list); spin_lock(&mm->unused_lock); if (mm->num_unused < MM_UNUSED_TARGET) { - list_add(&cur->fl_entry, &mm->unused_nodes); + list_add(&cur->free_stack, &mm->unused_nodes); ++mm->num_unused; } else kfree(cur); @@ -287,7 +287,6 @@ struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm, unsigned long size, unsigned alignment, int best_match) { - const struct list_head *free_stack = &mm->fl_entry; struct drm_mm_node *entry; struct drm_mm_node *best; unsigned long best_size; @@ -296,7 +295,7 @@ struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm, best = NULL; best_size = ~0UL; - list_for_each_entry(entry, free_stack, fl_entry) { + list_for_each_entry(entry, &mm->free_stack, free_stack) { wasted = 0; if (entry->size < size) @@ -329,7 +328,6 @@ struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm, unsigned long end, int best_match) { - const struct list_head *free_stack = &mm->fl_entry; struct drm_mm_node *entry; struct drm_mm_node *best; unsigned long best_size; @@ -338,7 +336,7 @@ struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm, best = NULL; best_size = ~0UL; - list_for_each_entry(entry, free_stack, fl_entry) { + list_for_each_entry(entry, &mm->free_stack, free_stack) { wasted = 0; if (entry->size < size) @@ -373,7 +371,7 @@ EXPORT_SYMBOL(drm_mm_search_free_in_range); int drm_mm_clean(struct drm_mm * mm) { - struct list_head *head = &mm->ml_entry; + struct list_head *head = &mm->node_list; return (head->next->next == head); } @@ -381,8 +379,8 @@ EXPORT_SYMBOL(drm_mm_clean); int drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size) { - INIT_LIST_HEAD(&mm->ml_entry); - INIT_LIST_HEAD(&mm->fl_entry); + INIT_LIST_HEAD(&mm->node_list); + INIT_LIST_HEAD(&mm->free_stack); INIT_LIST_HEAD(&mm->unused_nodes); mm->num_unused = 0; spin_lock_init(&mm->unused_lock); @@ -393,25 +391,25 @@ EXPORT_SYMBOL(drm_mm_init); void drm_mm_takedown(struct drm_mm * mm) { - struct list_head *bnode = mm->fl_entry.next; + struct list_head *bnode = mm->free_stack.next; struct drm_mm_node *entry; struct drm_mm_node *next; - entry = list_entry(bnode, struct drm_mm_node, fl_entry); + entry = list_entry(bnode, struct drm_mm_node, free_stack); - if (entry->ml_entry.next != &mm->ml_entry || - entry->fl_entry.next != &mm->fl_entry) { + if (entry->node_list.next != &mm->node_list || + entry->free_stack.next != &mm->free_stack) { DRM_ERROR("Memory manager not clean. Delaying takedown\n"); return; } - list_del(&entry->fl_entry); - list_del(&entry->ml_entry); + list_del(&entry->free_stack); + list_del(&entry->node_list); kfree(entry); spin_lock(&mm->unused_lock); - list_for_each_entry_safe(entry, next, &mm->unused_nodes, fl_entry) { - list_del(&entry->fl_entry); + list_for_each_entry_safe(entry, next, &mm->unused_nodes, free_stack) { + list_del(&entry->free_stack); kfree(entry); --mm->num_unused; } @@ -426,7 +424,7 @@ void drm_mm_debug_table(struct drm_mm *mm, const char *prefix) struct drm_mm_node *entry; int total_used = 0, total_free = 0, total = 0; - list_for_each_entry(entry, &mm->ml_entry, ml_entry) { + list_for_each_entry(entry, &mm->node_list, node_list) { printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8ld: %s\n", prefix, entry->start, entry->start + entry->size, entry->size, entry->free ? "free" : "used"); @@ -447,7 +445,7 @@ int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm) struct drm_mm_node *entry; int total_used = 0, total_free = 0, total = 0; - list_for_each_entry(entry, &mm->ml_entry, ml_entry) { + list_for_each_entry(entry, &mm->node_list, node_list) { seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: %s\n", entry->start, entry->start + entry->size, entry->size, entry->free ? "free" : "used"); total += entry->size; if (entry->free) diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h index da94071b1703..e8740cc185cf 100644 --- a/include/drm/drm_mm.h +++ b/include/drm/drm_mm.h @@ -42,8 +42,8 @@ #endif struct drm_mm_node { - struct list_head fl_entry; - struct list_head ml_entry; + struct list_head free_stack; + struct list_head node_list; int free; unsigned long start; unsigned long size; @@ -51,8 +51,11 @@ struct drm_mm_node { }; struct drm_mm { - struct list_head fl_entry; - struct list_head ml_entry; + /* List of free memory blocks, most recently freed ordered. */ + struct list_head free_stack; + /* List of all memory nodes, ordered according to the (increasing) start + * address of the memory node. */ + struct list_head node_list; struct list_head unused_nodes; int num_unused; spinlock_t unused_lock; -- cgit v1.2.3 From 709ea97145c125b3811ff70429e90ebdb0e832e5 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 2 Jul 2010 15:02:16 +0100 Subject: drm: implement helper functions for scanning lru list These helper functions can be used to efficiently scan lru list for eviction. Eviction becomes a three stage process: 1. Scanning through the lru list until a suitable hole has been found. 2. Scan backwards to restore drm_mm consistency and find out which objects fall into the hole. 3. Evict the objects that fall into the hole. These helper functions don't allocate any memory (at the price of not allowing any other concurrent operations). Hence this can also be used for ttm (which does lru scanning under a spinlock). Evicting objects in this fashion should be more fair than the current approach by i915 (scan the lru for a object large enough to contain the new object). It's also more efficient than the current approach used by ttm (uncoditionally evict objects from the lru until there's enough free space). Signed-Off-by: Daniel Vetter Acked-by: Thomas Hellstrom Signed-off-by: Chris Wilson Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_mm.c | 167 +++++++++++++++++++++++++++++++++++++++++++++-- include/drm/drm_mm.h | 15 ++++- 2 files changed, 177 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index fd86a6c13aac..da99edc50888 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -53,9 +53,9 @@ static struct drm_mm_node *drm_mm_kmalloc(struct drm_mm *mm, int atomic) struct drm_mm_node *child; if (atomic) - child = kmalloc(sizeof(*child), GFP_ATOMIC); + child = kzalloc(sizeof(*child), GFP_ATOMIC); else - child = kmalloc(sizeof(*child), GFP_KERNEL); + child = kzalloc(sizeof(*child), GFP_KERNEL); if (unlikely(child == NULL)) { spin_lock(&mm->unused_lock); @@ -85,7 +85,7 @@ int drm_mm_pre_get(struct drm_mm *mm) spin_lock(&mm->unused_lock); while (mm->num_unused < MM_UNUSED_TARGET) { spin_unlock(&mm->unused_lock); - node = kmalloc(sizeof(*node), GFP_KERNEL); + node = kzalloc(sizeof(*node), GFP_KERNEL); spin_lock(&mm->unused_lock); if (unlikely(node == NULL)) { @@ -134,7 +134,6 @@ static struct drm_mm_node *drm_mm_split_at_start(struct drm_mm_node *parent, INIT_LIST_HEAD(&child->free_stack); - child->free = 0; child->size = size; child->start = parent->start; child->mm = parent->mm; @@ -235,6 +234,9 @@ void drm_mm_put_block(struct drm_mm_node *cur) int merged = 0; + BUG_ON(cur->scanned_block || cur->scanned_prev_free + || cur->scanned_next_free); + if (cur_head->prev != root_head) { prev_node = list_entry(cur_head->prev, struct drm_mm_node, node_list); @@ -312,6 +314,8 @@ struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm, struct drm_mm_node *best; unsigned long best_size; + BUG_ON(mm->scanned_blocks); + best = NULL; best_size = ~0UL; @@ -343,6 +347,8 @@ struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm, struct drm_mm_node *best; unsigned long best_size; + BUG_ON(mm->scanned_blocks); + best = NULL; best_size = ~0UL; @@ -366,6 +372,158 @@ struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm, } EXPORT_SYMBOL(drm_mm_search_free_in_range); +/** + * Initializa lru scanning. + * + * This simply sets up the scanning routines with the parameters for the desired + * hole. + * + * Warning: As long as the scan list is non-empty, no other operations than + * adding/removing nodes to/from the scan list are allowed. + */ +void drm_mm_init_scan(struct drm_mm *mm, unsigned long size, + unsigned alignment) +{ + mm->scan_alignment = alignment; + mm->scan_size = size; + mm->scanned_blocks = 0; + mm->scan_hit_start = 0; + mm->scan_hit_size = 0; +} +EXPORT_SYMBOL(drm_mm_init_scan); + +/** + * Add a node to the scan list that might be freed to make space for the desired + * hole. + * + * Returns non-zero, if a hole has been found, zero otherwise. + */ +int drm_mm_scan_add_block(struct drm_mm_node *node) +{ + struct drm_mm *mm = node->mm; + struct list_head *prev_free, *next_free; + struct drm_mm_node *prev_node, *next_node; + + mm->scanned_blocks++; + + prev_free = next_free = NULL; + + BUG_ON(node->free); + node->scanned_block = 1; + node->free = 1; + + if (node->node_list.prev != &mm->node_list) { + prev_node = list_entry(node->node_list.prev, struct drm_mm_node, + node_list); + + if (prev_node->free) { + list_del(&prev_node->node_list); + + node->start = prev_node->start; + node->size += prev_node->size; + + prev_node->scanned_prev_free = 1; + + prev_free = &prev_node->free_stack; + } + } + + if (node->node_list.next != &mm->node_list) { + next_node = list_entry(node->node_list.next, struct drm_mm_node, + node_list); + + if (next_node->free) { + list_del(&next_node->node_list); + + node->size += next_node->size; + + next_node->scanned_next_free = 1; + + next_free = &next_node->free_stack; + } + } + + /* The free_stack list is not used for allocated objects, so these two + * pointers can be abused (as long as no allocations in this memory + * manager happens). */ + node->free_stack.prev = prev_free; + node->free_stack.next = next_free; + + if (check_free_mm_node(node, mm->scan_size, mm->scan_alignment)) { + mm->scan_hit_start = node->start; + mm->scan_hit_size = node->size; + + return 1; + } + + return 0; +} +EXPORT_SYMBOL(drm_mm_scan_add_block); + +/** + * Remove a node from the scan list. + * + * Nodes _must_ be removed in the exact same order from the scan list as they + * have been added, otherwise the internal state of the memory manager will be + * corrupted. + * + * When the scan list is empty, the selected memory nodes can be freed. An + * immediatly following drm_mm_search_free with best_match = 0 will then return + * the just freed block (because its at the top of the free_stack list). + * + * Returns one if this block should be evicted, zero otherwise. Will always + * return zero when no hole has been found. + */ +int drm_mm_scan_remove_block(struct drm_mm_node *node) +{ + struct drm_mm *mm = node->mm; + struct drm_mm_node *prev_node, *next_node; + + mm->scanned_blocks--; + + BUG_ON(!node->scanned_block); + node->scanned_block = 0; + node->free = 0; + + prev_node = list_entry(node->free_stack.prev, struct drm_mm_node, + free_stack); + next_node = list_entry(node->free_stack.next, struct drm_mm_node, + free_stack); + + if (prev_node) { + BUG_ON(!prev_node->scanned_prev_free); + prev_node->scanned_prev_free = 0; + + list_add_tail(&prev_node->node_list, &node->node_list); + + node->start = prev_node->start + prev_node->size; + node->size -= prev_node->size; + } + + if (next_node) { + BUG_ON(!next_node->scanned_next_free); + next_node->scanned_next_free = 0; + + list_add(&next_node->node_list, &node->node_list); + + node->size -= next_node->size; + } + + INIT_LIST_HEAD(&node->free_stack); + + /* Only need to check for containement because start&size for the + * complete resulting free block (not just the desired part) is + * stored. */ + if (node->start >= mm->scan_hit_start && + node->start + node->size + <= mm->scan_hit_start + mm->scan_hit_size) { + return 1; + } + + return 0; +} +EXPORT_SYMBOL(drm_mm_scan_remove_block); + int drm_mm_clean(struct drm_mm * mm) { struct list_head *head = &mm->node_list; @@ -380,6 +538,7 @@ int drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size) INIT_LIST_HEAD(&mm->free_stack); INIT_LIST_HEAD(&mm->unused_nodes); mm->num_unused = 0; + mm->scanned_blocks = 0; spin_lock_init(&mm->unused_lock); return drm_mm_create_tail_node(mm, start, size, 0); diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h index e8740cc185cf..bf01531193d5 100644 --- a/include/drm/drm_mm.h +++ b/include/drm/drm_mm.h @@ -44,7 +44,10 @@ struct drm_mm_node { struct list_head free_stack; struct list_head node_list; - int free; + unsigned free : 1; + unsigned scanned_block : 1; + unsigned scanned_prev_free : 1; + unsigned scanned_next_free : 1; unsigned long start; unsigned long size; struct drm_mm *mm; @@ -59,6 +62,11 @@ struct drm_mm { struct list_head unused_nodes; int num_unused; spinlock_t unused_lock; + unsigned scan_alignment; + unsigned long scan_size; + unsigned long scan_hit_start; + unsigned scan_hit_size; + unsigned scanned_blocks; }; /* @@ -135,6 +143,11 @@ static inline struct drm_mm *drm_get_mm(struct drm_mm_node *block) return block->mm; } +void drm_mm_init_scan(struct drm_mm *mm, unsigned long size, + unsigned alignment); +int drm_mm_scan_add_block(struct drm_mm_node *node); +int drm_mm_scan_remove_block(struct drm_mm_node *node); + extern void drm_mm_debug_table(struct drm_mm *mm, const char *prefix); #ifdef CONFIG_DEBUG_FS int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm); -- cgit v1.2.3 From 5c8d7171cc4984351af802a525675d50ae555a7b Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 11 Jun 2010 17:04:35 -0400 Subject: drm/kms: add crtc disable function More explicit than dpms. Same as the encoder disable function. Need this to explicity disconnect plls from crtcs for reuse when you plls:crtcs ratio isn't 1:1. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc_helper.c | 5 ++++- include/drm/drm_crtc_helper.h | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 9b2a54117c91..fa1323ff56b3 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -241,7 +241,10 @@ void drm_helper_disable_unused_functions(struct drm_device *dev) struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; crtc->enabled = drm_helper_crtc_in_use(crtc); if (!crtc->enabled) { - crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); + if (crtc_funcs->disable) + (*crtc_funcs->disable)(crtc); + else + (*crtc_funcs->dpms)(crtc, DRM_MODE_DPMS_OFF); crtc->fb = NULL; } } diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h index 1121f7799c6f..7e3c9766acba 100644 --- a/include/drm/drm_crtc_helper.h +++ b/include/drm/drm_crtc_helper.h @@ -63,6 +63,9 @@ struct drm_crtc_helper_funcs { /* reload the current crtc LUT */ void (*load_lut)(struct drm_crtc *crtc); + + /* disable crtc when not in use - more explicit than dpms off */ + void (*disable)(struct drm_crtc *crtc); }; struct drm_encoder_helper_funcs { -- cgit v1.2.3 From 92897b5c669f5e819ff2596fe6228ca2e4904981 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 16 Jul 2010 15:09:17 +1000 Subject: drm: add "auto" dithering method There's no convenient/reliable way for drivers to both obey the dithering mode property, and to be able to attempt to provide a good default in all cases. This commit adds an "auto" method to the property which drivers can default to if they wish, whilst still allowing the user to override the choice as they do now. Signed-off-by: Ben Skeggs Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc.c | 1 + include/drm/drm_mode.h | 1 + 2 files changed, 2 insertions(+) (limited to 'include') diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index b5802cf6664e..d8d65f4232a9 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -80,6 +80,7 @@ static struct drm_prop_enum_list drm_dithering_mode_enum_list[] = { { DRM_MODE_DITHERING_OFF, "Off" }, { DRM_MODE_DITHERING_ON, "On" }, + { DRM_MODE_DITHERING_AUTO, "Automatic" }, }; /* diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h index c5ba1636613c..0fc7397c8f1f 100644 --- a/include/drm/drm_mode.h +++ b/include/drm/drm_mode.h @@ -74,6 +74,7 @@ /* Dithering mode options */ #define DRM_MODE_DITHERING_OFF 0 #define DRM_MODE_DITHERING_ON 1 +#define DRM_MODE_DITHERING_AUTO 2 /* Dirty info options */ #define DRM_MODE_DIRTY_OFF 0 -- cgit v1.2.3 From e7aeeba6a8fb86ac52bcffa0b72942f784f2b37f Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 4 Jun 2010 13:10:12 -0400 Subject: drm/radeon/kms/r6xx+: add query for tile config (v2) Userspace needs this information to access tiled buffers via the CPU. v2: rebased on evergreen accel changes Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/evergreen.c | 1 + drivers/gpu/drm/radeon/r600.c | 2 +- drivers/gpu/drm/radeon/radeon.h | 3 +++ drivers/gpu/drm/radeon/radeon_drv.c | 3 ++- drivers/gpu/drm/radeon/radeon_kms.c | 12 ++++++++++++ drivers/gpu/drm/radeon/rv770.c | 3 ++- include/drm/radeon_drm.h | 1 + 7 files changed, 22 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 1b7da39cc587..957d5067ad9c 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -1132,6 +1132,7 @@ static void evergreen_gpu_init(struct radeon_device *rdev) rdev->config.evergreen.max_backends) & EVERGREEN_MAX_BACKENDS_MASK)); + rdev->config.evergreen.tile_config = gb_addr_config; WREG32(GB_BACKEND_MAP, gb_backend_map); WREG32(GB_ADDR_CONFIG, gb_addr_config); WREG32(DMIF_ADDR_CONFIG, gb_addr_config); diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 15fe6c214034..aa36ef69ba61 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -1623,7 +1623,7 @@ void r600_gpu_init(struct radeon_device *rdev) r600_count_pipe_bits((cc_rb_backend_disable & R6XX_MAX_BACKENDS_MASK) >> 16)), (cc_rb_backend_disable >> 16)); - + rdev->config.r600.tile_config = tiling_config; tiling_config |= BACKEND_MAP(backend_map); WREG32(GB_TILING_CONFIG, tiling_config); WREG32(DCP_TILING_CONFIG, tiling_config & 0xffff); diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index d4d776d2f1e0..be8420e65f01 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -914,6 +914,7 @@ struct r600_asic { unsigned tiling_nbanks; unsigned tiling_npipes; unsigned tiling_group_size; + unsigned tile_config; struct r100_gpu_lockup lockup; }; @@ -938,6 +939,7 @@ struct rv770_asic { unsigned tiling_nbanks; unsigned tiling_npipes; unsigned tiling_group_size; + unsigned tile_config; struct r100_gpu_lockup lockup; }; @@ -963,6 +965,7 @@ struct evergreen_asic { unsigned tiling_nbanks; unsigned tiling_npipes; unsigned tiling_group_size; + unsigned tile_config; }; union radeon_asic_config { diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index ed0ceb3fc40a..6f8a2e572878 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -46,9 +46,10 @@ * - 2.3.0 - add MSPOS + 3D texture + r500 VAP regs * - 2.4.0 - add crtc id query * - 2.5.0 - add get accel 2 to work around ddx breakage for evergreen + * - 2.6.0 - add tiling config query (r6xx+) */ #define KMS_DRIVER_MAJOR 2 -#define KMS_DRIVER_MINOR 5 +#define KMS_DRIVER_MINOR 6 #define KMS_DRIVER_PATCHLEVEL 0 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); int radeon_driver_unload_kms(struct drm_device *dev); diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 70fda6361cd0..9012e6fbadb6 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -147,6 +147,18 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) case RADEON_INFO_ACCEL_WORKING2: value = rdev->accel_working; break; + case RADEON_INFO_TILING_CONFIG: + if (rdev->family >= CHIP_CEDAR) + value = rdev->config.evergreen.tile_config; + else if (rdev->family >= CHIP_RV770) + value = rdev->config.rv770.tile_config; + else if (rdev->family >= CHIP_R600) + value = rdev->config.r600.tile_config; + else { + DRM_DEBUG("tiling config is r6xx+ only!\n"); + return -EINVAL; + } + break; default: DRM_DEBUG("Invalid request %d\n", info->request); return -EINVAL; diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 836c15ab84d1..236fe6681922 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -674,8 +674,9 @@ static void rv770_gpu_init(struct radeon_device *rdev) r600_count_pipe_bits((cc_rb_backend_disable & R7XX_MAX_BACKENDS_MASK) >> 16)), (cc_rb_backend_disable >> 16)); - gb_tiling_config |= BACKEND_MAP(backend_map); + rdev->config.rv770.tile_config = gb_tiling_config; + gb_tiling_config |= BACKEND_MAP(backend_map); WREG32(GB_TILING_CONFIG, gb_tiling_config); WREG32(DCP_TILING_CONFIG, (gb_tiling_config & 0xffff)); diff --git a/include/drm/radeon_drm.h b/include/drm/radeon_drm.h index 5347063e9d5a..ac5f0403d537 100644 --- a/include/drm/radeon_drm.h +++ b/include/drm/radeon_drm.h @@ -904,6 +904,7 @@ struct drm_radeon_cs { #define RADEON_INFO_ACCEL_WORKING 0x03 #define RADEON_INFO_CRTC_FROM_ID 0x04 #define RADEON_INFO_ACCEL_WORKING2 0x05 +#define RADEON_INFO_TILING_CONFIG 0x06 struct drm_radeon_info { uint32_t request; -- cgit v1.2.3 From e190bfe56841551b1ad5abb42ebd0c4798cc8c01 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Thu, 22 Jul 2010 17:06:18 +0200 Subject: drm: Import driver for the sil164 I2C TMDS transmitter. sil164 transmitters are used for DVI outputs on Intel/nvidia and ATI setups. So far only nouveau can use this driver. Signed-off-by: Francisco Jerez Tested-by: Patrice Mandin Signed-off-by: Dave Airlie --- drivers/gpu/drm/i2c/Makefile | 3 + drivers/gpu/drm/i2c/sil164_drv.c | 462 +++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/nouveau/Kconfig | 9 + include/drm/i2c/sil164.h | 63 ++++++ 4 files changed, 537 insertions(+) create mode 100644 drivers/gpu/drm/i2c/sil164_drv.c create mode 100644 include/drm/i2c/sil164.h (limited to 'include') diff --git a/drivers/gpu/drm/i2c/Makefile b/drivers/gpu/drm/i2c/Makefile index 6d2abaf35ba2..92862563e7ee 100644 --- a/drivers/gpu/drm/i2c/Makefile +++ b/drivers/gpu/drm/i2c/Makefile @@ -2,3 +2,6 @@ ccflags-y := -Iinclude/drm ch7006-y := ch7006_drv.o ch7006_mode.o obj-$(CONFIG_DRM_I2C_CH7006) += ch7006.o + +sil164-y := sil164_drv.o +obj-$(CONFIG_DRM_I2C_SIL164) += sil164.o diff --git a/drivers/gpu/drm/i2c/sil164_drv.c b/drivers/gpu/drm/i2c/sil164_drv.c new file mode 100644 index 000000000000..0b6773290c08 --- /dev/null +++ b/drivers/gpu/drm/i2c/sil164_drv.c @@ -0,0 +1,462 @@ +/* + * Copyright (C) 2010 Francisco Jerez. + * All Rights Reserved. + * + * 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 the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include "drmP.h" +#include "drm_crtc_helper.h" +#include "drm_encoder_slave.h" +#include "i2c/sil164.h" + +struct sil164_priv { + struct sil164_encoder_params config; + struct i2c_client *duallink_slave; + + uint8_t saved_state[0x10]; + uint8_t saved_slave_state[0x10]; +}; + +#define to_sil164_priv(x) \ + ((struct sil164_priv *)to_encoder_slave(x)->slave_priv) + +#define sil164_dbg(client, format, ...) do { \ + if (drm_debug & DRM_UT_KMS) \ + dev_printk(KERN_DEBUG, &client->dev, \ + "%s: " format, __func__, ## __VA_ARGS__); \ + } while (0) +#define sil164_info(client, format, ...) \ + dev_info(&client->dev, format, __VA_ARGS__) +#define sil164_err(client, format, ...) \ + dev_err(&client->dev, format, __VA_ARGS__) + +#define SIL164_I2C_ADDR_MASTER 0x38 +#define SIL164_I2C_ADDR_SLAVE 0x39 + +/* HW register definitions */ + +#define SIL164_VENDOR_LO 0x0 +#define SIL164_VENDOR_HI 0x1 +#define SIL164_DEVICE_LO 0x2 +#define SIL164_DEVICE_HI 0x3 +#define SIL164_REVISION 0x4 +#define SIL164_FREQ_MIN 0x6 +#define SIL164_FREQ_MAX 0x7 +#define SIL164_CONTROL0 0x8 +# define SIL164_CONTROL0_POWER_ON 0x01 +# define SIL164_CONTROL0_EDGE_RISING 0x02 +# define SIL164_CONTROL0_INPUT_24BIT 0x04 +# define SIL164_CONTROL0_DUAL_EDGE 0x08 +# define SIL164_CONTROL0_HSYNC_ON 0x10 +# define SIL164_CONTROL0_VSYNC_ON 0x20 +#define SIL164_DETECT 0x9 +# define SIL164_DETECT_INTR_STAT 0x01 +# define SIL164_DETECT_HOTPLUG_STAT 0x02 +# define SIL164_DETECT_RECEIVER_STAT 0x04 +# define SIL164_DETECT_INTR_MODE_RECEIVER 0x00 +# define SIL164_DETECT_INTR_MODE_HOTPLUG 0x08 +# define SIL164_DETECT_OUT_MODE_HIGH 0x00 +# define SIL164_DETECT_OUT_MODE_INTR 0x10 +# define SIL164_DETECT_OUT_MODE_RECEIVER 0x20 +# define SIL164_DETECT_OUT_MODE_HOTPLUG 0x30 +# define SIL164_DETECT_VSWING_STAT 0x80 +#define SIL164_CONTROL1 0xa +# define SIL164_CONTROL1_DESKEW_ENABLE 0x10 +# define SIL164_CONTROL1_DESKEW_INCR_SHIFT 5 +#define SIL164_GPIO 0xb +#define SIL164_CONTROL2 0xc +# define SIL164_CONTROL2_FILTER_ENABLE 0x01 +# define SIL164_CONTROL2_FILTER_SETTING_SHIFT 1 +# define SIL164_CONTROL2_DUALLINK_MASTER 0x40 +# define SIL164_CONTROL2_SYNC_CONT 0x80 +#define SIL164_DUALLINK 0xd +# define SIL164_DUALLINK_ENABLE 0x10 +# define SIL164_DUALLINK_SKEW_SHIFT 5 +#define SIL164_PLLZONE 0xe +# define SIL164_PLLZONE_STAT 0x08 +# define SIL164_PLLZONE_FORCE_ON 0x10 +# define SIL164_PLLZONE_FORCE_HIGH 0x20 + +/* HW access functions */ + +static void +sil164_write(struct i2c_client *client, uint8_t addr, uint8_t val) +{ + uint8_t buf[] = {addr, val}; + int ret; + + ret = i2c_master_send(client, buf, ARRAY_SIZE(buf)); + if (ret < 0) + sil164_err(client, "Error %d writing to subaddress 0x%x\n", + ret, addr); +} + +static uint8_t +sil164_read(struct i2c_client *client, uint8_t addr) +{ + uint8_t val; + int ret; + + ret = i2c_master_send(client, &addr, sizeof(addr)); + if (ret < 0) + goto fail; + + ret = i2c_master_recv(client, &val, sizeof(val)); + if (ret < 0) + goto fail; + + return val; + +fail: + sil164_err(client, "Error %d reading from subaddress 0x%x\n", + ret, addr); + return 0; +} + +static void +sil164_save_state(struct i2c_client *client, uint8_t *state) +{ + int i; + + for (i = 0x8; i <= 0xe; i++) + state[i] = sil164_read(client, i); +} + +static void +sil164_restore_state(struct i2c_client *client, uint8_t *state) +{ + int i; + + for (i = 0x8; i <= 0xe; i++) + sil164_write(client, i, state[i]); +} + +static void +sil164_set_power_state(struct i2c_client *client, bool on) +{ + uint8_t control0 = sil164_read(client, SIL164_CONTROL0); + + if (on) + control0 |= SIL164_CONTROL0_POWER_ON; + else + control0 &= ~SIL164_CONTROL0_POWER_ON; + + sil164_write(client, SIL164_CONTROL0, control0); +} + +static void +sil164_init_state(struct i2c_client *client, + struct sil164_encoder_params *config, + bool duallink) +{ + sil164_write(client, SIL164_CONTROL0, + SIL164_CONTROL0_HSYNC_ON | + SIL164_CONTROL0_VSYNC_ON | + (config->input_edge ? SIL164_CONTROL0_EDGE_RISING : 0) | + (config->input_width ? SIL164_CONTROL0_INPUT_24BIT : 0) | + (config->input_dual ? SIL164_CONTROL0_DUAL_EDGE : 0)); + + sil164_write(client, SIL164_DETECT, + SIL164_DETECT_INTR_STAT | + SIL164_DETECT_OUT_MODE_RECEIVER); + + sil164_write(client, SIL164_CONTROL1, + (config->input_skew ? SIL164_CONTROL1_DESKEW_ENABLE : 0) | + (((config->input_skew + 4) & 0x7) + << SIL164_CONTROL1_DESKEW_INCR_SHIFT)); + + sil164_write(client, SIL164_CONTROL2, + SIL164_CONTROL2_SYNC_CONT | + (config->pll_filter ? 0 : SIL164_CONTROL2_FILTER_ENABLE) | + (4 << SIL164_CONTROL2_FILTER_SETTING_SHIFT)); + + sil164_write(client, SIL164_PLLZONE, 0); + + if (duallink) + sil164_write(client, SIL164_DUALLINK, + SIL164_DUALLINK_ENABLE | + (((config->duallink_skew + 4) & 0x7) + << SIL164_DUALLINK_SKEW_SHIFT)); + else + sil164_write(client, SIL164_DUALLINK, 0); +} + +/* DRM encoder functions */ + +static void +sil164_encoder_set_config(struct drm_encoder *encoder, void *params) +{ + struct sil164_priv *priv = to_sil164_priv(encoder); + + priv->config = *(struct sil164_encoder_params *)params; +} + +static void +sil164_encoder_dpms(struct drm_encoder *encoder, int mode) +{ + struct sil164_priv *priv = to_sil164_priv(encoder); + bool on = (mode == DRM_MODE_DPMS_ON); + bool duallink = (on && encoder->crtc->mode.clock > 165000); + + sil164_set_power_state(drm_i2c_encoder_get_client(encoder), on); + + if (priv->duallink_slave) + sil164_set_power_state(priv->duallink_slave, duallink); +} + +static void +sil164_encoder_save(struct drm_encoder *encoder) +{ + struct sil164_priv *priv = to_sil164_priv(encoder); + + sil164_save_state(drm_i2c_encoder_get_client(encoder), + priv->saved_state); + + if (priv->duallink_slave) + sil164_save_state(priv->duallink_slave, + priv->saved_slave_state); +} + +static void +sil164_encoder_restore(struct drm_encoder *encoder) +{ + struct sil164_priv *priv = to_sil164_priv(encoder); + + sil164_restore_state(drm_i2c_encoder_get_client(encoder), + priv->saved_state); + + if (priv->duallink_slave) + sil164_restore_state(priv->duallink_slave, + priv->saved_slave_state); +} + +static bool +sil164_encoder_mode_fixup(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + return true; +} + +static int +sil164_encoder_mode_valid(struct drm_encoder *encoder, + struct drm_display_mode *mode) +{ + struct sil164_priv *priv = to_sil164_priv(encoder); + + if (mode->clock < 32000) + return MODE_CLOCK_LOW; + + if (mode->clock > 330000 || + (mode->clock > 165000 && !priv->duallink_slave)) + return MODE_CLOCK_HIGH; + + return MODE_OK; +} + +static void +sil164_encoder_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct sil164_priv *priv = to_sil164_priv(encoder); + bool duallink = adjusted_mode->clock > 165000; + + sil164_init_state(drm_i2c_encoder_get_client(encoder), + &priv->config, duallink); + + if (priv->duallink_slave) + sil164_init_state(priv->duallink_slave, + &priv->config, duallink); + + sil164_encoder_dpms(encoder, DRM_MODE_DPMS_ON); +} + +static enum drm_connector_status +sil164_encoder_detect(struct drm_encoder *encoder, + struct drm_connector *connector) +{ + struct i2c_client *client = drm_i2c_encoder_get_client(encoder); + + if (sil164_read(client, SIL164_DETECT) & SIL164_DETECT_HOTPLUG_STAT) + return connector_status_connected; + else + return connector_status_disconnected; +} + +static int +sil164_encoder_get_modes(struct drm_encoder *encoder, + struct drm_connector *connector) +{ + return 0; +} + +static int +sil164_encoder_create_resources(struct drm_encoder *encoder, + struct drm_connector *connector) +{ + return 0; +} + +static int +sil164_encoder_set_property(struct drm_encoder *encoder, + struct drm_connector *connector, + struct drm_property *property, + uint64_t val) +{ + return 0; +} + +static void +sil164_encoder_destroy(struct drm_encoder *encoder) +{ + struct sil164_priv *priv = to_sil164_priv(encoder); + + if (priv->duallink_slave) + i2c_unregister_device(priv->duallink_slave); + + kfree(priv); + drm_i2c_encoder_destroy(encoder); +} + +static struct drm_encoder_slave_funcs sil164_encoder_funcs = { + .set_config = sil164_encoder_set_config, + .destroy = sil164_encoder_destroy, + .dpms = sil164_encoder_dpms, + .save = sil164_encoder_save, + .restore = sil164_encoder_restore, + .mode_fixup = sil164_encoder_mode_fixup, + .mode_valid = sil164_encoder_mode_valid, + .mode_set = sil164_encoder_mode_set, + .detect = sil164_encoder_detect, + .get_modes = sil164_encoder_get_modes, + .create_resources = sil164_encoder_create_resources, + .set_property = sil164_encoder_set_property, +}; + +/* I2C driver functions */ + +static int +sil164_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + int vendor = sil164_read(client, SIL164_VENDOR_HI) << 8 | + sil164_read(client, SIL164_VENDOR_LO); + int device = sil164_read(client, SIL164_DEVICE_HI) << 8 | + sil164_read(client, SIL164_DEVICE_LO); + int rev = sil164_read(client, SIL164_REVISION); + + if (vendor != 0x1 || device != 0x6) { + sil164_dbg(client, "Unknown device %x:%x.%x\n", + vendor, device, rev); + return -ENODEV; + } + + sil164_info(client, "Detected device %x:%x.%x\n", + vendor, device, rev); + + return 0; +} + +static int +sil164_remove(struct i2c_client *client) +{ + return 0; +} + +static struct i2c_client * +sil164_detect_slave(struct i2c_client *client) +{ + struct i2c_adapter *adap = client->adapter; + struct i2c_msg msg = { + .addr = SIL164_I2C_ADDR_SLAVE, + .len = 0, + }; + const struct i2c_board_info info = { + I2C_BOARD_INFO("sil164", SIL164_I2C_ADDR_SLAVE) + }; + + if (i2c_transfer(adap, &msg, 1) != 1) { + sil164_dbg(adap, "No dual-link slave found."); + return NULL; + } + + return i2c_new_device(adap, &info); +} + +static int +sil164_encoder_init(struct i2c_client *client, + struct drm_device *dev, + struct drm_encoder_slave *encoder) +{ + struct sil164_priv *priv; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + encoder->slave_priv = priv; + encoder->slave_funcs = &sil164_encoder_funcs; + + priv->duallink_slave = sil164_detect_slave(client); + + return 0; +} + +static struct i2c_device_id sil164_ids[] = { + { "sil164", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, sil164_ids); + +static struct drm_i2c_encoder_driver sil164_driver = { + .i2c_driver = { + .probe = sil164_probe, + .remove = sil164_remove, + .driver = { + .name = "sil164", + }, + .id_table = sil164_ids, + }, + .encoder_init = sil164_encoder_init, +}; + +/* Module initialization */ + +static int __init +sil164_init(void) +{ + return drm_i2c_encoder_register(THIS_MODULE, &sil164_driver); +} + +static void __exit +sil164_exit(void) +{ + drm_i2c_encoder_unregister(&sil164_driver); +} + +MODULE_AUTHOR("Francisco Jerez "); +MODULE_DESCRIPTION("Silicon Image sil164 TMDS transmitter driver"); +MODULE_LICENSE("GPL and additional rights"); + +module_init(sil164_init); +module_exit(sil164_exit); diff --git a/drivers/gpu/drm/nouveau/Kconfig b/drivers/gpu/drm/nouveau/Kconfig index b6f5239c2efb..d2d28048efb2 100644 --- a/drivers/gpu/drm/nouveau/Kconfig +++ b/drivers/gpu/drm/nouveau/Kconfig @@ -41,4 +41,13 @@ config DRM_I2C_CH7006 This driver is currently only useful if you're also using the nouveau driver. + +config DRM_I2C_SIL164 + tristate "Silicon Image sil164 TMDS transmitter" + default m if DRM_NOUVEAU + help + Support for sil164 and similar single-link (or dual-link + when used in pairs) TMDS transmitters, used in some nVidia + video cards. + endmenu diff --git a/include/drm/i2c/sil164.h b/include/drm/i2c/sil164.h new file mode 100644 index 000000000000..205e27384c83 --- /dev/null +++ b/include/drm/i2c/sil164.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2010 Francisco Jerez. + * All Rights Reserved. + * + * 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 the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef __DRM_I2C_SIL164_H__ +#define __DRM_I2C_SIL164_H__ + +/** + * struct sil164_encoder_params + * + * Describes how the sil164 is connected to the GPU. It should be used + * as the @params parameter of its @set_config method. + * + * See "http://www.siliconimage.com/docs/SiI-DS-0021-E-164.pdf". + */ +struct sil164_encoder_params { + enum { + SIL164_INPUT_EDGE_FALLING = 0, + SIL164_INPUT_EDGE_RISING + } input_edge; + + enum { + SIL164_INPUT_WIDTH_12BIT = 0, + SIL164_INPUT_WIDTH_24BIT + } input_width; + + enum { + SIL164_INPUT_SINGLE_EDGE = 0, + SIL164_INPUT_DUAL_EDGE + } input_dual; + + enum { + SIL164_PLL_FILTER_ON = 0, + SIL164_PLL_FILTER_OFF, + } pll_filter; + + int input_skew; /** < Allowed range [-4, 3], use 0 for no de-skew. */ + int duallink_skew; /** < Allowed range [-4, 3]. */ +}; + +#endif -- cgit v1.2.3 From ab9e1f5966591dc3e811418e96ba04f284c52458 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 13 Jul 2010 11:11:11 +1000 Subject: drm/radeon: add basic zmask/hiz support (v4) This interface allows userspace to request hyperz support, it probably needs more locking, and really reporting that you can have hyperz is racy since someone else might get it before you do. v2: modify so we pass 0 valued packets to let DDX/r300c keep working. also fixed incorrect 0x4f1c reference. v3: fixup zb_bw_cntl so older drivers keep working v4: add locking, fixup SC_HYPERZ_EN - patch stream to disable hiz Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r100.c | 5 ++++ drivers/gpu/drm/radeon/r100d.h | 2 ++ drivers/gpu/drm/radeon/r300.c | 44 ++++++++++++++++++++++++++++++++--- drivers/gpu/drm/radeon/r300d.h | 2 ++ drivers/gpu/drm/radeon/radeon.h | 2 ++ drivers/gpu/drm/radeon/radeon_drv.c | 2 +- drivers/gpu/drm/radeon/radeon_kms.c | 13 ++++++++++- drivers/gpu/drm/radeon/reg_srcs/r300 | 13 ----------- drivers/gpu/drm/radeon/reg_srcs/r420 | 14 +---------- drivers/gpu/drm/radeon/reg_srcs/rs600 | 13 ----------- drivers/gpu/drm/radeon/reg_srcs/rv515 | 13 ----------- include/drm/radeon_drm.h | 1 + 12 files changed, 67 insertions(+), 57 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 4c48df464355..e817a0bb5eb4 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -1803,6 +1803,11 @@ static int r100_packet3_check(struct radeon_cs_parser *p, return r; break; /* triggers drawing using indices to vertex buffer */ + case PACKET3_3D_CLEAR_HIZ: + case PACKET3_3D_CLEAR_ZMASK: + if (p->rdev->hyperz_filp != p->filp) + return -EINVAL; + break; case PACKET3_NOP: break; default: diff --git a/drivers/gpu/drm/radeon/r100d.h b/drivers/gpu/drm/radeon/r100d.h index d016b16fa116..b121b6c678d4 100644 --- a/drivers/gpu/drm/radeon/r100d.h +++ b/drivers/gpu/drm/radeon/r100d.h @@ -48,10 +48,12 @@ #define PACKET3_3D_DRAW_IMMD 0x29 #define PACKET3_3D_DRAW_INDX 0x2A #define PACKET3_3D_LOAD_VBPNTR 0x2F +#define PACKET3_3D_CLEAR_ZMASK 0x32 #define PACKET3_INDX_BUFFER 0x33 #define PACKET3_3D_DRAW_VBUF_2 0x34 #define PACKET3_3D_DRAW_IMMD_2 0x35 #define PACKET3_3D_DRAW_INDX_2 0x36 +#define PACKET3_3D_CLEAR_HIZ 0x37 #define PACKET3_BITBLT_MULTI 0x9B #define PACKET0(reg, n) (CP_PACKET0 | \ diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index 58eab5d47305..c827738ad7dd 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -1048,14 +1048,47 @@ static int r300_packet0_check(struct radeon_cs_parser *p, /* RB3D_COLOR_CHANNEL_MASK */ track->color_channel_mask = idx_value; break; - case 0x4d1c: + case 0x43a4: + /* SC_HYPERZ_EN */ + /* r300c emits this register - we need to disable hyperz for it + * without complaining */ + if (p->rdev->hyperz_filp != p->filp) { + if (idx_value & 0x1) + ib[idx] = idx_value & ~1; + } + break; + case 0x4f1c: /* ZB_BW_CNTL */ track->zb_cb_clear = !!(idx_value & (1 << 5)); + if (p->rdev->hyperz_filp != p->filp) { + if (idx_value & (R300_HIZ_ENABLE | + R300_RD_COMP_ENABLE | + R300_WR_COMP_ENABLE | + R300_FAST_FILL_ENABLE)) + goto fail; + } break; case 0x4e04: /* RB3D_BLENDCNTL */ track->blend_read_enable = !!(idx_value & (1 << 2)); break; + case 0x4f28: /* ZB_DEPTHCLEARVALUE */ + break; + case 0x4f30: /* ZB_MASK_OFFSET */ + case 0x4f34: /* ZB_ZMASK_PITCH */ + case 0x4f44: /* ZB_HIZ_OFFSET */ + case 0x4f54: /* ZB_HIZ_PITCH */ + if (idx_value && (p->rdev->hyperz_filp != p->filp)) + goto fail; + break; + case 0x4028: + if (idx_value && (p->rdev->hyperz_filp != p->filp)) + goto fail; + /* GB_Z_PEQ_CONFIG */ + if (p->rdev->family >= CHIP_RV350) + break; + goto fail; + break; case 0x4be8: /* valid register only on RV530 */ if (p->rdev->family == CHIP_RV530) @@ -1066,8 +1099,8 @@ static int r300_packet0_check(struct radeon_cs_parser *p, } return 0; fail: - printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n", - reg, idx); + printk(KERN_ERR "Forbidden register 0x%04X in cs at %d (val=%08x)\n", + reg, idx, idx_value); return -EINVAL; } @@ -1161,6 +1194,11 @@ static int r300_packet3_check(struct radeon_cs_parser *p, return r; } break; + case PACKET3_3D_CLEAR_HIZ: + case PACKET3_3D_CLEAR_ZMASK: + if (p->rdev->hyperz_filp != p->filp) + return -EINVAL; + break; case PACKET3_NOP: break; default: diff --git a/drivers/gpu/drm/radeon/r300d.h b/drivers/gpu/drm/radeon/r300d.h index 968a33317fbf..0c036c60d9df 100644 --- a/drivers/gpu/drm/radeon/r300d.h +++ b/drivers/gpu/drm/radeon/r300d.h @@ -48,10 +48,12 @@ #define PACKET3_3D_DRAW_IMMD 0x29 #define PACKET3_3D_DRAW_INDX 0x2A #define PACKET3_3D_LOAD_VBPNTR 0x2F +#define PACKET3_3D_CLEAR_ZMASK 0x32 #define PACKET3_INDX_BUFFER 0x33 #define PACKET3_3D_DRAW_VBUF_2 0x34 #define PACKET3_3D_DRAW_IMMD_2 0x35 #define PACKET3_3D_DRAW_INDX_2 0x36 +#define PACKET3_3D_CLEAR_HIZ 0x37 #define PACKET3_BITBLT_MULTI 0x9B #define PACKET0(reg, n) (CP_PACKET0 | \ diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index c84f9a311550..368fecf0c2b7 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1098,6 +1098,8 @@ struct radeon_device { bool powered_down; struct notifier_block acpi_nb; + /* only one userspace can use Hyperz features at a time */ + struct drm_file *hyperz_filp; }; int radeon_device_init(struct radeon_device *rdev, diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 6f8a2e572878..795403b0e2cd 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -46,7 +46,7 @@ * - 2.3.0 - add MSPOS + 3D texture + r500 VAP regs * - 2.4.0 - add crtc id query * - 2.5.0 - add get accel 2 to work around ddx breakage for evergreen - * - 2.6.0 - add tiling config query (r6xx+) + * - 2.6.0 - add tiling config query (r6xx+), add initial HiZ support (r300->r500) */ #define KMS_DRIVER_MAJOR 2 #define KMS_DRIVER_MINOR 6 diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index dd0a78e954a8..e5b705427389 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -159,6 +159,15 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) DRM_DEBUG_KMS("tiling config is r6xx+ only!\n"); return -EINVAL; } + case RADEON_INFO_WANT_HYPERZ: + mutex_lock(&dev->struct_mutex); + if (rdev->hyperz_filp) + value = 0; + else { + rdev->hyperz_filp = filp; + value = 1; + } + mutex_unlock(&dev->struct_mutex); break; default: DRM_DEBUG_KMS("Invalid request %d\n", info->request); @@ -199,9 +208,11 @@ void radeon_driver_postclose_kms(struct drm_device *dev, void radeon_driver_preclose_kms(struct drm_device *dev, struct drm_file *file_priv) { + struct radeon_device *rdev = dev->dev_private; + if (rdev->hyperz_filp == file_priv) + rdev->hyperz_filp = NULL; } - /* * VBlank related functions. */ diff --git a/drivers/gpu/drm/radeon/reg_srcs/r300 b/drivers/gpu/drm/radeon/reg_srcs/r300 index 1e97b2d129fd..b506ec1cab4b 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/r300 +++ b/drivers/gpu/drm/radeon/reg_srcs/r300 @@ -187,7 +187,6 @@ r300 0x4f60 0x4364 RS_INST_13 0x4368 RS_INST_14 0x436C RS_INST_15 -0x43A4 SC_HYPERZ_EN 0x43A8 SC_EDGERULE 0x43B0 SC_CLIP_0_A 0x43B4 SC_CLIP_0_B @@ -716,16 +715,4 @@ r300 0x4f60 0x4F08 ZB_STENCILREFMASK 0x4F14 ZB_ZTOP 0x4F18 ZB_ZCACHE_CTLSTAT -0x4F1C ZB_BW_CNTL -0x4F28 ZB_DEPTHCLEARVALUE -0x4F30 ZB_ZMASK_OFFSET -0x4F34 ZB_ZMASK_PITCH -0x4F38 ZB_ZMASK_WRINDEX -0x4F3C ZB_ZMASK_DWORD -0x4F40 ZB_ZMASK_RDINDEX -0x4F44 ZB_HIZ_OFFSET -0x4F48 ZB_HIZ_WRINDEX -0x4F4C ZB_HIZ_DWORD -0x4F50 ZB_HIZ_RDINDEX -0x4F54 ZB_HIZ_PITCH 0x4F58 ZB_ZPASS_DATA diff --git a/drivers/gpu/drm/radeon/reg_srcs/r420 b/drivers/gpu/drm/radeon/reg_srcs/r420 index e958980d00f1..8c1214c2390f 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/r420 +++ b/drivers/gpu/drm/radeon/reg_srcs/r420 @@ -130,6 +130,7 @@ r420 0x4f60 0x401C GB_SELECT 0x4020 GB_AA_CONFIG 0x4024 GB_FIFO_SIZE +0x4028 GB_Z_PEQ_CONFIG 0x4100 TX_INVALTAGS 0x4200 GA_POINT_S0 0x4204 GA_POINT_T0 @@ -187,7 +188,6 @@ r420 0x4f60 0x4364 RS_INST_13 0x4368 RS_INST_14 0x436C RS_INST_15 -0x43A4 SC_HYPERZ_EN 0x43A8 SC_EDGERULE 0x43B0 SC_CLIP_0_A 0x43B4 SC_CLIP_0_B @@ -782,16 +782,4 @@ r420 0x4f60 0x4F08 ZB_STENCILREFMASK 0x4F14 ZB_ZTOP 0x4F18 ZB_ZCACHE_CTLSTAT -0x4F1C ZB_BW_CNTL -0x4F28 ZB_DEPTHCLEARVALUE -0x4F30 ZB_ZMASK_OFFSET -0x4F34 ZB_ZMASK_PITCH -0x4F38 ZB_ZMASK_WRINDEX -0x4F3C ZB_ZMASK_DWORD -0x4F40 ZB_ZMASK_RDINDEX -0x4F44 ZB_HIZ_OFFSET -0x4F48 ZB_HIZ_WRINDEX -0x4F4C ZB_HIZ_DWORD -0x4F50 ZB_HIZ_RDINDEX -0x4F54 ZB_HIZ_PITCH 0x4F58 ZB_ZPASS_DATA diff --git a/drivers/gpu/drm/radeon/reg_srcs/rs600 b/drivers/gpu/drm/radeon/reg_srcs/rs600 index 83e8bc0c2bb2..0828d80396f2 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/rs600 +++ b/drivers/gpu/drm/radeon/reg_srcs/rs600 @@ -187,7 +187,6 @@ rs600 0x6d40 0x4364 RS_INST_13 0x4368 RS_INST_14 0x436C RS_INST_15 -0x43A4 SC_HYPERZ_EN 0x43A8 SC_EDGERULE 0x43B0 SC_CLIP_0_A 0x43B4 SC_CLIP_0_B @@ -782,16 +781,4 @@ rs600 0x6d40 0x4F08 ZB_STENCILREFMASK 0x4F14 ZB_ZTOP 0x4F18 ZB_ZCACHE_CTLSTAT -0x4F1C ZB_BW_CNTL -0x4F28 ZB_DEPTHCLEARVALUE -0x4F30 ZB_ZMASK_OFFSET -0x4F34 ZB_ZMASK_PITCH -0x4F38 ZB_ZMASK_WRINDEX -0x4F3C ZB_ZMASK_DWORD -0x4F40 ZB_ZMASK_RDINDEX -0x4F44 ZB_HIZ_OFFSET -0x4F48 ZB_HIZ_WRINDEX -0x4F4C ZB_HIZ_DWORD -0x4F50 ZB_HIZ_RDINDEX -0x4F54 ZB_HIZ_PITCH 0x4F58 ZB_ZPASS_DATA diff --git a/drivers/gpu/drm/radeon/reg_srcs/rv515 b/drivers/gpu/drm/radeon/reg_srcs/rv515 index 1e46233985eb..8293855f5f0d 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/rv515 +++ b/drivers/gpu/drm/radeon/reg_srcs/rv515 @@ -235,7 +235,6 @@ rv515 0x6d40 0x4354 RS_INST_13 0x4358 RS_INST_14 0x435C RS_INST_15 -0x43A4 SC_HYPERZ_EN 0x43A8 SC_EDGERULE 0x43B0 SC_CLIP_0_A 0x43B4 SC_CLIP_0_B @@ -479,17 +478,5 @@ rv515 0x6d40 0x4F08 ZB_STENCILREFMASK 0x4F14 ZB_ZTOP 0x4F18 ZB_ZCACHE_CTLSTAT -0x4F1C ZB_BW_CNTL -0x4F28 ZB_DEPTHCLEARVALUE -0x4F30 ZB_ZMASK_OFFSET -0x4F34 ZB_ZMASK_PITCH -0x4F38 ZB_ZMASK_WRINDEX -0x4F3C ZB_ZMASK_DWORD -0x4F40 ZB_ZMASK_RDINDEX -0x4F44 ZB_HIZ_OFFSET -0x4F48 ZB_HIZ_WRINDEX -0x4F4C ZB_HIZ_DWORD -0x4F50 ZB_HIZ_RDINDEX -0x4F54 ZB_HIZ_PITCH 0x4F58 ZB_ZPASS_DATA 0x4FD4 ZB_STENCILREFMASK_BF diff --git a/include/drm/radeon_drm.h b/include/drm/radeon_drm.h index ac5f0403d537..0acaf8f91437 100644 --- a/include/drm/radeon_drm.h +++ b/include/drm/radeon_drm.h @@ -905,6 +905,7 @@ struct drm_radeon_cs { #define RADEON_INFO_CRTC_FROM_ID 0x04 #define RADEON_INFO_ACCEL_WORKING2 0x05 #define RADEON_INFO_TILING_CONFIG 0x06 +#define RADEON_INFO_WANT_HYPERZ 0x07 struct drm_radeon_info { uint32_t request; -- cgit v1.2.3 From ba4420c224c2808f2661cf8428f43ceef7a73a4a Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 9 Mar 2010 10:56:52 +1000 Subject: drm: move ttm global code to core drm I wrote this for the prime sharing work, but I also noticed other external non-upstream drivers from a large company carrying a similiar patch, so I may as well ship it in master. Signed-off-by: Dave Airlie --- drivers/gpu/drm/Makefile | 2 +- drivers/gpu/drm/drm_drv.c | 1 + drivers/gpu/drm/drm_global.c | 112 +++++++++++++++++++++++++++++++ drivers/gpu/drm/nouveau/nouveau_drv.h | 2 +- drivers/gpu/drm/nouveau/nouveau_ttm.c | 20 +++--- drivers/gpu/drm/radeon/radeon.h | 2 +- drivers/gpu/drm/radeon/radeon_ttm.c | 20 +++--- drivers/gpu/drm/ttm/Makefile | 2 +- drivers/gpu/drm/ttm/ttm_bo.c | 4 +- drivers/gpu/drm/ttm/ttm_global.c | 112 ------------------------------- drivers/gpu/drm/ttm/ttm_module.c | 4 -- drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c | 20 +++--- include/drm/drm.h | 2 + include/drm/drmP.h | 2 + include/drm/drm_global.h | 53 +++++++++++++++ include/drm/ttm/ttm_bo_driver.h | 7 +- include/drm/ttm/ttm_module.h | 20 ------ 18 files changed, 211 insertions(+), 176 deletions(-) create mode 100644 drivers/gpu/drm/drm_global.c delete mode 100644 drivers/gpu/drm/ttm/ttm_global.c create mode 100644 include/drm/drm_global.h (limited to 'include') diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index df8f92322865..f3a23a329f4e 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -12,7 +12,7 @@ drm-y := drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \ drm_platform.o drm_sysfs.o drm_hashtab.o drm_sman.o drm_mm.o \ drm_crtc.o drm_modes.o drm_edid.o \ drm_info.o drm_debugfs.o drm_encoder_slave.o \ - drm_trace_points.o + drm_trace_points.o drm_global.o drm-$(CONFIG_COMPAT) += drm_ioc32.o diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index b5a51686f492..d5b349d279f5 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -288,6 +288,7 @@ static int __init drm_core_init(void) { int ret = -ENOMEM; + drm_global_init(); idr_init(&drm_minors_idr); if (register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops)) diff --git a/drivers/gpu/drm/drm_global.c b/drivers/gpu/drm/drm_global.c new file mode 100644 index 000000000000..c87dc96444de --- /dev/null +++ b/drivers/gpu/drm/drm_global.c @@ -0,0 +1,112 @@ +/************************************************************************** + * + * Copyright 2008-2009 VMware, Inc., Palo Alto, CA., USA + * All Rights Reserved. + * + * 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 the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ +/* + * Authors: Thomas Hellstrom + */ + +#include +#include +#include +#include "drm_global.h" + +struct drm_global_item { + struct mutex mutex; + void *object; + int refcount; +}; + +static struct drm_global_item glob[DRM_GLOBAL_NUM]; + +void drm_global_init(void) +{ + int i; + + for (i = 0; i < DRM_GLOBAL_NUM; ++i) { + struct drm_global_item *item = &glob[i]; + mutex_init(&item->mutex); + item->object = NULL; + item->refcount = 0; + } +} + +void drm_global_release(void) +{ + int i; + for (i = 0; i < DRM_GLOBAL_NUM; ++i) { + struct drm_global_item *item = &glob[i]; + BUG_ON(item->object != NULL); + BUG_ON(item->refcount != 0); + } +} + +int drm_global_item_ref(struct drm_global_reference *ref) +{ + int ret; + struct drm_global_item *item = &glob[ref->global_type]; + void *object; + + mutex_lock(&item->mutex); + if (item->refcount == 0) { + item->object = kzalloc(ref->size, GFP_KERNEL); + if (unlikely(item->object == NULL)) { + ret = -ENOMEM; + goto out_err; + } + + ref->object = item->object; + ret = ref->init(ref); + if (unlikely(ret != 0)) + goto out_err; + + } + ++item->refcount; + ref->object = item->object; + object = item->object; + mutex_unlock(&item->mutex); + return 0; +out_err: + mutex_unlock(&item->mutex); + item->object = NULL; + return ret; +} +EXPORT_SYMBOL(drm_global_item_ref); + +void drm_global_item_unref(struct drm_global_reference *ref) +{ + struct drm_global_item *item = &glob[ref->global_type]; + + mutex_lock(&item->mutex); + BUG_ON(item->refcount == 0); + BUG_ON(ref->object != item->object); + if (--item->refcount == 0) { + ref->release(ref); + item->object = NULL; + } + mutex_unlock(&item->mutex); +} +EXPORT_SYMBOL(drm_global_item_unref); + diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index d0a35d9ba522..e15db15dca77 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -533,7 +533,7 @@ struct drm_nouveau_private { struct list_head vbl_waiting; struct { - struct ttm_global_reference mem_global_ref; + struct drm_global_reference mem_global_ref; struct ttm_bo_global_ref bo_global_ref; struct ttm_bo_device bdev; spinlock_t bo_list_lock; diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index c385d50f041b..bd35f930568c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c @@ -42,13 +42,13 @@ nouveau_ttm_mmap(struct file *filp, struct vm_area_struct *vma) } static int -nouveau_ttm_mem_global_init(struct ttm_global_reference *ref) +nouveau_ttm_mem_global_init(struct drm_global_reference *ref) { return ttm_mem_global_init(ref->object); } static void -nouveau_ttm_mem_global_release(struct ttm_global_reference *ref) +nouveau_ttm_mem_global_release(struct drm_global_reference *ref) { ttm_mem_global_release(ref->object); } @@ -56,16 +56,16 @@ nouveau_ttm_mem_global_release(struct ttm_global_reference *ref) int nouveau_ttm_global_init(struct drm_nouveau_private *dev_priv) { - struct ttm_global_reference *global_ref; + struct drm_global_reference *global_ref; int ret; global_ref = &dev_priv->ttm.mem_global_ref; - global_ref->global_type = TTM_GLOBAL_TTM_MEM; + global_ref->global_type = DRM_GLOBAL_TTM_MEM; global_ref->size = sizeof(struct ttm_mem_global); global_ref->init = &nouveau_ttm_mem_global_init; global_ref->release = &nouveau_ttm_mem_global_release; - ret = ttm_global_item_ref(global_ref); + ret = drm_global_item_ref(global_ref); if (unlikely(ret != 0)) { DRM_ERROR("Failed setting up TTM memory accounting\n"); dev_priv->ttm.mem_global_ref.release = NULL; @@ -74,15 +74,15 @@ nouveau_ttm_global_init(struct drm_nouveau_private *dev_priv) dev_priv->ttm.bo_global_ref.mem_glob = global_ref->object; global_ref = &dev_priv->ttm.bo_global_ref.ref; - global_ref->global_type = TTM_GLOBAL_TTM_BO; + global_ref->global_type = DRM_GLOBAL_TTM_BO; global_ref->size = sizeof(struct ttm_bo_global); global_ref->init = &ttm_bo_global_init; global_ref->release = &ttm_bo_global_release; - ret = ttm_global_item_ref(global_ref); + ret = drm_global_item_ref(global_ref); if (unlikely(ret != 0)) { DRM_ERROR("Failed setting up TTM BO subsystem\n"); - ttm_global_item_unref(&dev_priv->ttm.mem_global_ref); + drm_global_item_unref(&dev_priv->ttm.mem_global_ref); dev_priv->ttm.mem_global_ref.release = NULL; return ret; } @@ -96,8 +96,8 @@ nouveau_ttm_global_release(struct drm_nouveau_private *dev_priv) if (dev_priv->ttm.mem_global_ref.release == NULL) return; - ttm_global_item_unref(&dev_priv->ttm.bo_global_ref.ref); - ttm_global_item_unref(&dev_priv->ttm.mem_global_ref); + drm_global_item_unref(&dev_priv->ttm.bo_global_ref.ref); + drm_global_item_unref(&dev_priv->ttm.mem_global_ref); dev_priv->ttm.mem_global_ref.release = NULL; } diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 368fecf0c2b7..3cd1c470b777 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -235,7 +235,7 @@ struct radeon_surface_reg { */ struct radeon_mman { struct ttm_bo_global_ref bo_global_ref; - struct ttm_global_reference mem_global_ref; + struct drm_global_reference mem_global_ref; struct ttm_bo_device bdev; bool mem_global_referenced; bool initialized; diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index e9918d88f5b0..84c53e41a88f 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -59,28 +59,28 @@ static struct radeon_device *radeon_get_rdev(struct ttm_bo_device *bdev) /* * Global memory. */ -static int radeon_ttm_mem_global_init(struct ttm_global_reference *ref) +static int radeon_ttm_mem_global_init(struct drm_global_reference *ref) { return ttm_mem_global_init(ref->object); } -static void radeon_ttm_mem_global_release(struct ttm_global_reference *ref) +static void radeon_ttm_mem_global_release(struct drm_global_reference *ref) { ttm_mem_global_release(ref->object); } static int radeon_ttm_global_init(struct radeon_device *rdev) { - struct ttm_global_reference *global_ref; + struct drm_global_reference *global_ref; int r; rdev->mman.mem_global_referenced = false; global_ref = &rdev->mman.mem_global_ref; - global_ref->global_type = TTM_GLOBAL_TTM_MEM; + global_ref->global_type = DRM_GLOBAL_TTM_MEM; global_ref->size = sizeof(struct ttm_mem_global); global_ref->init = &radeon_ttm_mem_global_init; global_ref->release = &radeon_ttm_mem_global_release; - r = ttm_global_item_ref(global_ref); + r = drm_global_item_ref(global_ref); if (r != 0) { DRM_ERROR("Failed setting up TTM memory accounting " "subsystem.\n"); @@ -90,14 +90,14 @@ static int radeon_ttm_global_init(struct radeon_device *rdev) rdev->mman.bo_global_ref.mem_glob = rdev->mman.mem_global_ref.object; global_ref = &rdev->mman.bo_global_ref.ref; - global_ref->global_type = TTM_GLOBAL_TTM_BO; + global_ref->global_type = DRM_GLOBAL_TTM_BO; global_ref->size = sizeof(struct ttm_bo_global); global_ref->init = &ttm_bo_global_init; global_ref->release = &ttm_bo_global_release; - r = ttm_global_item_ref(global_ref); + r = drm_global_item_ref(global_ref); if (r != 0) { DRM_ERROR("Failed setting up TTM BO subsystem.\n"); - ttm_global_item_unref(&rdev->mman.mem_global_ref); + drm_global_item_unref(&rdev->mman.mem_global_ref); return r; } @@ -108,8 +108,8 @@ static int radeon_ttm_global_init(struct radeon_device *rdev) static void radeon_ttm_global_fini(struct radeon_device *rdev) { if (rdev->mman.mem_global_referenced) { - ttm_global_item_unref(&rdev->mman.bo_global_ref.ref); - ttm_global_item_unref(&rdev->mman.mem_global_ref); + drm_global_item_unref(&rdev->mman.bo_global_ref.ref); + drm_global_item_unref(&rdev->mman.mem_global_ref); rdev->mman.mem_global_referenced = false; } } diff --git a/drivers/gpu/drm/ttm/Makefile b/drivers/gpu/drm/ttm/Makefile index 4256e2006476..b256d4adfafe 100644 --- a/drivers/gpu/drm/ttm/Makefile +++ b/drivers/gpu/drm/ttm/Makefile @@ -3,7 +3,7 @@ ccflags-y := -Iinclude/drm ttm-y := ttm_agp_backend.o ttm_memory.o ttm_tt.o ttm_bo.o \ - ttm_bo_util.o ttm_bo_vm.o ttm_module.o ttm_global.o \ + ttm_bo_util.o ttm_bo_vm.o ttm_module.o \ ttm_object.o ttm_lock.o ttm_execbuf_util.o ttm_page_alloc.o obj-$(CONFIG_DRM_TTM) += ttm.o diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 9763288c6b2d..cb4cf7ef4d1e 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1395,7 +1395,7 @@ static void ttm_bo_global_kobj_release(struct kobject *kobj) kfree(glob); } -void ttm_bo_global_release(struct ttm_global_reference *ref) +void ttm_bo_global_release(struct drm_global_reference *ref) { struct ttm_bo_global *glob = ref->object; @@ -1404,7 +1404,7 @@ void ttm_bo_global_release(struct ttm_global_reference *ref) } EXPORT_SYMBOL(ttm_bo_global_release); -int ttm_bo_global_init(struct ttm_global_reference *ref) +int ttm_bo_global_init(struct drm_global_reference *ref) { struct ttm_bo_global_ref *bo_ref = container_of(ref, struct ttm_bo_global_ref, ref); diff --git a/drivers/gpu/drm/ttm/ttm_global.c b/drivers/gpu/drm/ttm/ttm_global.c deleted file mode 100644 index b17007178a36..000000000000 --- a/drivers/gpu/drm/ttm/ttm_global.c +++ /dev/null @@ -1,112 +0,0 @@ -/************************************************************************** - * - * Copyright 2008-2009 VMware, Inc., Palo Alto, CA., USA - * All Rights Reserved. - * - * 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 the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ -/* - * Authors: Thomas Hellstrom - */ - -#include "ttm/ttm_module.h" -#include -#include -#include - -struct ttm_global_item { - struct mutex mutex; - void *object; - int refcount; -}; - -static struct ttm_global_item glob[TTM_GLOBAL_NUM]; - -void ttm_global_init(void) -{ - int i; - - for (i = 0; i < TTM_GLOBAL_NUM; ++i) { - struct ttm_global_item *item = &glob[i]; - mutex_init(&item->mutex); - item->object = NULL; - item->refcount = 0; - } -} - -void ttm_global_release(void) -{ - int i; - for (i = 0; i < TTM_GLOBAL_NUM; ++i) { - struct ttm_global_item *item = &glob[i]; - BUG_ON(item->object != NULL); - BUG_ON(item->refcount != 0); - } -} - -int ttm_global_item_ref(struct ttm_global_reference *ref) -{ - int ret; - struct ttm_global_item *item = &glob[ref->global_type]; - void *object; - - mutex_lock(&item->mutex); - if (item->refcount == 0) { - item->object = kzalloc(ref->size, GFP_KERNEL); - if (unlikely(item->object == NULL)) { - ret = -ENOMEM; - goto out_err; - } - - ref->object = item->object; - ret = ref->init(ref); - if (unlikely(ret != 0)) - goto out_err; - - } - ++item->refcount; - ref->object = item->object; - object = item->object; - mutex_unlock(&item->mutex); - return 0; -out_err: - mutex_unlock(&item->mutex); - item->object = NULL; - return ret; -} -EXPORT_SYMBOL(ttm_global_item_ref); - -void ttm_global_item_unref(struct ttm_global_reference *ref) -{ - struct ttm_global_item *item = &glob[ref->global_type]; - - mutex_lock(&item->mutex); - BUG_ON(item->refcount == 0); - BUG_ON(ref->object != item->object); - if (--item->refcount == 0) { - ref->release(ref); - item->object = NULL; - } - mutex_unlock(&item->mutex); -} -EXPORT_SYMBOL(ttm_global_item_unref); - diff --git a/drivers/gpu/drm/ttm/ttm_module.c b/drivers/gpu/drm/ttm/ttm_module.c index 9a6edbfeaa9e..902d7cf9fb4e 100644 --- a/drivers/gpu/drm/ttm/ttm_module.c +++ b/drivers/gpu/drm/ttm/ttm_module.c @@ -70,8 +70,6 @@ static int __init ttm_init(void) if (unlikely(ret != 0)) return ret; - ttm_global_init(); - atomic_set(&device_released, 0); ret = drm_class_device_register(&ttm_drm_class_device); if (unlikely(ret != 0)) @@ -81,7 +79,6 @@ static int __init ttm_init(void) out_no_dev_reg: atomic_set(&device_released, 1); wake_up_all(&exit_q); - ttm_global_release(); return ret; } @@ -95,7 +92,6 @@ static void __exit ttm_exit(void) */ wait_event(exit_q, atomic_read(&device_released) == 1); - ttm_global_release(); } module_init(ttm_init); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index eaad52095339..429f917b60bf 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -164,7 +164,7 @@ struct vmw_vga_topology_state { struct vmw_private { struct ttm_bo_device bdev; struct ttm_bo_global_ref bo_global_ref; - struct ttm_global_reference mem_global_ref; + struct drm_global_reference mem_global_ref; struct vmw_fifo_state fifo; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c index e3df4adfb4d8..83123287c60c 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c @@ -44,29 +44,29 @@ int vmw_mmap(struct file *filp, struct vm_area_struct *vma) return ttm_bo_mmap(filp, vma, &dev_priv->bdev); } -static int vmw_ttm_mem_global_init(struct ttm_global_reference *ref) +static int vmw_ttm_mem_global_init(struct drm_global_reference *ref) { DRM_INFO("global init.\n"); return ttm_mem_global_init(ref->object); } -static void vmw_ttm_mem_global_release(struct ttm_global_reference *ref) +static void vmw_ttm_mem_global_release(struct drm_global_reference *ref) { ttm_mem_global_release(ref->object); } int vmw_ttm_global_init(struct vmw_private *dev_priv) { - struct ttm_global_reference *global_ref; + struct drm_global_reference *global_ref; int ret; global_ref = &dev_priv->mem_global_ref; - global_ref->global_type = TTM_GLOBAL_TTM_MEM; + global_ref->global_type = DRM_GLOBAL_TTM_MEM; global_ref->size = sizeof(struct ttm_mem_global); global_ref->init = &vmw_ttm_mem_global_init; global_ref->release = &vmw_ttm_mem_global_release; - ret = ttm_global_item_ref(global_ref); + ret = drm_global_item_ref(global_ref); if (unlikely(ret != 0)) { DRM_ERROR("Failed setting up TTM memory accounting.\n"); return ret; @@ -75,11 +75,11 @@ int vmw_ttm_global_init(struct vmw_private *dev_priv) dev_priv->bo_global_ref.mem_glob = dev_priv->mem_global_ref.object; global_ref = &dev_priv->bo_global_ref.ref; - global_ref->global_type = TTM_GLOBAL_TTM_BO; + global_ref->global_type = DRM_GLOBAL_TTM_BO; global_ref->size = sizeof(struct ttm_bo_global); global_ref->init = &ttm_bo_global_init; global_ref->release = &ttm_bo_global_release; - ret = ttm_global_item_ref(global_ref); + ret = drm_global_item_ref(global_ref); if (unlikely(ret != 0)) { DRM_ERROR("Failed setting up TTM buffer objects.\n"); @@ -88,12 +88,12 @@ int vmw_ttm_global_init(struct vmw_private *dev_priv) return 0; out_no_bo: - ttm_global_item_unref(&dev_priv->mem_global_ref); + drm_global_item_unref(&dev_priv->mem_global_ref); return ret; } void vmw_ttm_global_release(struct vmw_private *dev_priv) { - ttm_global_item_unref(&dev_priv->bo_global_ref.ref); - ttm_global_item_unref(&dev_priv->mem_global_ref); + drm_global_item_unref(&dev_priv->bo_global_ref.ref); + drm_global_item_unref(&dev_priv->mem_global_ref); } diff --git a/include/drm/drm.h b/include/drm/drm.h index e3f46e0cb7dc..e5f70617dec5 100644 --- a/include/drm/drm.h +++ b/include/drm/drm.h @@ -663,6 +663,8 @@ struct drm_gem_open { #define DRM_IOCTL_UNLOCK DRM_IOW( 0x2b, struct drm_lock) #define DRM_IOCTL_FINISH DRM_IOW( 0x2c, struct drm_lock) +#define DRM_IOCTL_GEM_PRIME_OPEN DRM_IOWR(0x2e, struct drm_gem_open) + #define DRM_IOCTL_AGP_ACQUIRE DRM_IO( 0x30) #define DRM_IOCTL_AGP_RELEASE DRM_IO( 0x31) #define DRM_IOCTL_AGP_ENABLE DRM_IOW( 0x32, struct drm_agp_mode) diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 04b564bfc4a1..53017ba0ab7b 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1453,6 +1453,8 @@ void drm_gem_vm_open(struct vm_area_struct *vma); void drm_gem_vm_close(struct vm_area_struct *vma); int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma); +#include "drm_global.h" + static inline void drm_gem_object_reference(struct drm_gem_object *obj) { diff --git a/include/drm/drm_global.h b/include/drm/drm_global.h new file mode 100644 index 000000000000..a06805eaf649 --- /dev/null +++ b/include/drm/drm_global.h @@ -0,0 +1,53 @@ +/************************************************************************** + * + * Copyright 2008-2009 VMware, Inc., Palo Alto, CA., USA + * All Rights Reserved. + * + * 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 the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ +/* + * Authors: Thomas Hellstrom + */ + +#ifndef _DRM_GLOBAL_H_ +#define _DRM_GLOBAL_H_ +enum drm_global_types { + DRM_GLOBAL_TTM_MEM = 0, + DRM_GLOBAL_TTM_BO, + DRM_GLOBAL_TTM_OBJECT, + DRM_GLOBAL_NUM +}; + +struct drm_global_reference { + enum drm_global_types global_type; + size_t size; + void *object; + int (*init) (struct drm_global_reference *); + void (*release) (struct drm_global_reference *); +}; + +extern void drm_global_init(void); +extern void drm_global_release(void); +extern int drm_global_item_ref(struct drm_global_reference *ref); +extern void drm_global_item_unref(struct drm_global_reference *ref); + +#endif diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index 0ea602da43e7..b87504235f18 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -34,6 +34,7 @@ #include "ttm/ttm_memory.h" #include "ttm/ttm_module.h" #include "drm_mm.h" +#include "drm_global.h" #include "linux/workqueue.h" #include "linux/fs.h" #include "linux/spinlock.h" @@ -362,7 +363,7 @@ struct ttm_bo_driver { */ struct ttm_bo_global_ref { - struct ttm_global_reference ref; + struct drm_global_reference ref; struct ttm_mem_global *mem_glob; }; @@ -687,8 +688,8 @@ extern int ttm_mem_io_reserve(struct ttm_bo_device *bdev, extern void ttm_mem_io_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem); -extern void ttm_bo_global_release(struct ttm_global_reference *ref); -extern int ttm_bo_global_init(struct ttm_global_reference *ref); +extern void ttm_bo_global_release(struct drm_global_reference *ref); +extern int ttm_bo_global_init(struct drm_global_reference *ref); extern int ttm_bo_device_release(struct ttm_bo_device *bdev); diff --git a/include/drm/ttm/ttm_module.h b/include/drm/ttm/ttm_module.h index cf416aee19af..45fa318c1585 100644 --- a/include/drm/ttm/ttm_module.h +++ b/include/drm/ttm/ttm_module.h @@ -35,26 +35,6 @@ struct kobject; #define TTM_PFX "[TTM] " - -enum ttm_global_types { - TTM_GLOBAL_TTM_MEM = 0, - TTM_GLOBAL_TTM_BO, - TTM_GLOBAL_TTM_OBJECT, - TTM_GLOBAL_NUM -}; - -struct ttm_global_reference { - enum ttm_global_types global_type; - size_t size; - void *object; - int (*init) (struct ttm_global_reference *); - void (*release) (struct ttm_global_reference *); -}; - -extern void ttm_global_init(void); -extern void ttm_global_release(void); -extern int ttm_global_item_ref(struct ttm_global_reference *ref); -extern void ttm_global_item_unref(struct ttm_global_reference *ref); extern struct kobject *ttm_get_kobj(void); #endif /* _TTM_MODULE_H_ */ -- cgit v1.2.3 From 1297c05a8dfb568c689f057d51a65eebe5ddc86f Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 4 Aug 2010 11:40:00 -0400 Subject: drm/radeon: add new pci ids New evergreen and r7xx ids. Signed-off-by: Alex Deucher Cc: stable@kernel.org Signed-off-by: Dave Airlie --- include/drm/drm_pciids.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'include') diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h index 2d428b088cc8..3a9940ef728b 100644 --- a/include/drm/drm_pciids.h +++ b/include/drm/drm_pciids.h @@ -146,6 +146,8 @@ {0x1002, 0x6888, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6889, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x688A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x688C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x688D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6898, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6899, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x689c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HEMLOCK|RADEON_NEW_MEMMAP}, \ @@ -161,6 +163,7 @@ {0x1002, 0x68be, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_NEW_MEMMAP}, \ {0x1002, 0x68c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x68c1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x68c7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x68c8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_NEW_MEMMAP}, \ {0x1002, 0x68c9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_NEW_MEMMAP}, \ {0x1002, 0x68d8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_NEW_MEMMAP}, \ @@ -174,6 +177,7 @@ {0x1002, 0x68e8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \ {0x1002, 0x68e9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \ {0x1002, 0x68f1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x68f2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \ {0x1002, 0x68f8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \ {0x1002, 0x68f9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \ {0x1002, 0x68fe, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \ @@ -314,6 +318,7 @@ {0x1002, 0x9456, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \ {0x1002, 0x945A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x945B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x945E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x9460, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \ {0x1002, 0x9462, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \ {0x1002, 0x946A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ @@ -324,6 +329,7 @@ {0x1002, 0x9487, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV730|RADEON_NEW_MEMMAP}, \ {0x1002, 0x9488, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV730|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x9489, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV730|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x948A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV730|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x948F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV730|RADEON_NEW_MEMMAP}, \ {0x1002, 0x9490, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV730|RADEON_NEW_MEMMAP}, \ {0x1002, 0x9491, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV730|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ @@ -366,6 +372,7 @@ {0x1002, 0x9553, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV710|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x9555, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV710|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x9557, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV710|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x955f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV710|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x9580, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV630|RADEON_NEW_MEMMAP}, \ {0x1002, 0x9581, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV630|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x9583, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV630|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ -- cgit v1.2.3 From fca3ec01e0b40cab82cac7745e154b01969e6219 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 4 Aug 2010 14:34:24 +0100 Subject: drm,io-mapping: Specify slot to use for atomic mappings This is required should we ever attempt to use an io-mapping where KM_USER0 is verboten, such as inside an IRQ context. Signed-off-by: Chris Wilson Cc: Eric Anholt Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/i915_gem.c | 9 +++++---- drivers/gpu/drm/i915/intel_overlay.c | 5 +++-- drivers/gpu/drm/nouveau/nouveau_bios.c | 8 ++++---- include/linux/io-mapping.h | 16 ++++++++++------ 4 files changed, 22 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 4efd4fd3b340..2a4ed7ca8b4e 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -496,10 +496,10 @@ fast_user_write(struct io_mapping *mapping, char *vaddr_atomic; unsigned long unwritten; - vaddr_atomic = io_mapping_map_atomic_wc(mapping, page_base); + vaddr_atomic = io_mapping_map_atomic_wc(mapping, page_base, KM_USER0); unwritten = __copy_from_user_inatomic_nocache(vaddr_atomic + page_offset, user_data, length); - io_mapping_unmap_atomic(vaddr_atomic); + io_mapping_unmap_atomic(vaddr_atomic, KM_USER0); if (unwritten) return -EFAULT; return 0; @@ -3487,7 +3487,8 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, reloc_offset = obj_priv->gtt_offset + reloc->offset; reloc_page = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping, (reloc_offset & - ~(PAGE_SIZE - 1))); + ~(PAGE_SIZE - 1)), + KM_USER0); reloc_entry = (uint32_t __iomem *)(reloc_page + (reloc_offset & (PAGE_SIZE - 1))); reloc_val = target_obj_priv->gtt_offset + reloc->delta; @@ -3498,7 +3499,7 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, readl(reloc_entry), reloc_val); #endif writel(reloc_val, reloc_entry); - io_mapping_unmap_atomic(reloc_page); + io_mapping_unmap_atomic(reloc_page, KM_USER0); /* The updated presumed offset for this entry will be * copied back out to the user. diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index f26ec2f27d36..d39aea24eabe 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -185,7 +185,8 @@ static struct overlay_registers *intel_overlay_map_regs_atomic(struct intel_over if (OVERLAY_NONPHYSICAL(overlay->dev)) { regs = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping, - overlay->reg_bo->gtt_offset); + overlay->reg_bo->gtt_offset, + KM_USER0); if (!regs) { DRM_ERROR("failed to map overlay regs in GTT\n"); @@ -200,7 +201,7 @@ static struct overlay_registers *intel_overlay_map_regs_atomic(struct intel_over static void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay) { if (OVERLAY_NONPHYSICAL(overlay->dev)) - io_mapping_unmap_atomic(overlay->virt_addr); + io_mapping_unmap_atomic(overlay->virt_addr, KM_USER0); overlay->virt_addr = NULL; diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index b59f348f14fc..7369b5e73649 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -2083,11 +2083,11 @@ peek_fb(struct drm_device *dev, struct io_mapping *fb, uint32_t val = 0; if (off < pci_resource_len(dev->pdev, 1)) { - uint32_t __iomem *p = io_mapping_map_atomic_wc(fb, off); + uint32_t __iomem *p = io_mapping_map_atomic_wc(fb, off, KM_USER0); val = ioread32(p); - io_mapping_unmap_atomic(p); + io_mapping_unmap_atomic(p, KM_USER0); } return val; @@ -2098,12 +2098,12 @@ poke_fb(struct drm_device *dev, struct io_mapping *fb, uint32_t off, uint32_t val) { if (off < pci_resource_len(dev->pdev, 1)) { - uint32_t __iomem *p = io_mapping_map_atomic_wc(fb, off); + uint32_t __iomem *p = io_mapping_map_atomic_wc(fb, off, KM_USER0); iowrite32(val, p); wmb(); - io_mapping_unmap_atomic(p); + io_mapping_unmap_atomic(p, KM_USER0); } } diff --git a/include/linux/io-mapping.h b/include/linux/io-mapping.h index 25085ddd955f..e0ea40f6c515 100644 --- a/include/linux/io-mapping.h +++ b/include/linux/io-mapping.h @@ -79,7 +79,9 @@ io_mapping_free(struct io_mapping *mapping) /* Atomic map/unmap */ static inline void * -io_mapping_map_atomic_wc(struct io_mapping *mapping, unsigned long offset) +io_mapping_map_atomic_wc(struct io_mapping *mapping, + unsigned long offset, + int slot) { resource_size_t phys_addr; unsigned long pfn; @@ -87,13 +89,13 @@ io_mapping_map_atomic_wc(struct io_mapping *mapping, unsigned long offset) BUG_ON(offset >= mapping->size); phys_addr = mapping->base + offset; pfn = (unsigned long) (phys_addr >> PAGE_SHIFT); - return iomap_atomic_prot_pfn(pfn, KM_USER0, mapping->prot); + return iomap_atomic_prot_pfn(pfn, slot, mapping->prot); } static inline void -io_mapping_unmap_atomic(void *vaddr) +io_mapping_unmap_atomic(void *vaddr, int slot) { - iounmap_atomic(vaddr, KM_USER0); + iounmap_atomic(vaddr, slot); } static inline void * @@ -133,13 +135,15 @@ io_mapping_free(struct io_mapping *mapping) /* Atomic map/unmap */ static inline void * -io_mapping_map_atomic_wc(struct io_mapping *mapping, unsigned long offset) +io_mapping_map_atomic_wc(struct io_mapping *mapping, + unsigned long offset, + int slot) { return ((char *) mapping) + offset; } static inline void -io_mapping_unmap_atomic(void *vaddr) +io_mapping_unmap_atomic(void *vaddr, int slot) { } -- cgit v1.2.3 From 58374713c9dfb4d231f8c56cac089f6fbdedc2ec Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sat, 10 Jul 2010 23:51:39 +0200 Subject: drm: kill BKL from common code This restricts the use of the big kernel lock to the i830 and i810 device drivers. The three remaining users in common code (open, ioctl and release) get converted to a new mutex, the drm_global_mutex, making the locking stricter than the big kernel lock. This may have a performance impact, but only in those cases that currently don't use DRM_UNLOCKED flag in the ioctl list and would benefit from that anyway. The reason why i810 and i830 cannot use drm_global_mutex in their mmap functions is a lock-order inversion problem between the current use of the BKL and mmap_sem in these drivers. Since the BKL has release-on-sleep semantics, it's harmless but it would cause trouble if we replace the BKL with a mutex. Instead, these drivers get their own ioctl wrappers that take the BKL around every ioctl call and then set their own handlers as DRM_UNLOCKED. Signed-off-by: Arnd Bergmann Cc: David Airlie Cc: dri-devel@lists.freedesktop.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_drv.c | 4 ++-- drivers/gpu/drm/drm_fops.c | 23 +++++++++++---------- drivers/gpu/drm/i810/i810_dma.c | 44 +++++++++++++++++++++++++++-------------- drivers/gpu/drm/i810/i810_drv.c | 2 +- drivers/gpu/drm/i810/i810_drv.h | 1 + drivers/gpu/drm/i830/i830_dma.c | 42 ++++++++++++++++++++++++++------------- drivers/gpu/drm/i830/i830_drv.c | 2 +- drivers/gpu/drm/i830/i830_drv.h | 1 + include/drm/drmP.h | 2 +- 9 files changed, 75 insertions(+), 46 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index d5b349d279f5..90288ec7c284 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -481,9 +481,9 @@ long drm_ioctl(struct file *filp, if (ioctl->flags & DRM_UNLOCKED) retcode = func(dev, kdata, file_priv); else { - lock_kernel(); + mutex_lock(&drm_global_mutex); retcode = func(dev, kdata, file_priv); - unlock_kernel(); + mutex_unlock(&drm_global_mutex); } if (cmd & IOC_OUT) { diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index e7aace20981f..2ca8df8b6102 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -39,6 +39,9 @@ #include #include +/* from BKL pushdown: note that nothing else serializes idr_find() */ +DEFINE_MUTEX(drm_global_mutex); + static int drm_open_helper(struct inode *inode, struct file *filp, struct drm_device * dev); @@ -175,8 +178,7 @@ int drm_stub_open(struct inode *inode, struct file *filp) DRM_DEBUG("\n"); - /* BKL pushdown: note that nothing else serializes idr_find() */ - lock_kernel(); + mutex_lock(&drm_global_mutex); minor = idr_find(&drm_minors_idr, minor_id); if (!minor) goto out; @@ -197,7 +199,7 @@ int drm_stub_open(struct inode *inode, struct file *filp) fops_put(old_fops); out: - unlock_kernel(); + mutex_unlock(&drm_global_mutex); return err; } @@ -472,7 +474,7 @@ int drm_release(struct inode *inode, struct file *filp) struct drm_device *dev = file_priv->minor->dev; int retcode = 0; - lock_kernel(); + mutex_lock(&drm_global_mutex); DRM_DEBUG("open_count = %d\n", dev->open_count); @@ -573,17 +575,14 @@ int drm_release(struct inode *inode, struct file *filp) if (atomic_read(&dev->ioctl_count)) { DRM_ERROR("Device busy: %d\n", atomic_read(&dev->ioctl_count)); - spin_unlock(&dev->count_lock); - unlock_kernel(); - return -EBUSY; + retcode = -EBUSY; + goto out; } - spin_unlock(&dev->count_lock); - unlock_kernel(); - return drm_lastclose(dev); + retcode = drm_lastclose(dev); } +out: spin_unlock(&dev->count_lock); - - unlock_kernel(); + mutex_unlock(&drm_global_mutex); return retcode; } diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c index 09c86ed89927..0e6c131313d9 100644 --- a/drivers/gpu/drm/i810/i810_dma.c +++ b/drivers/gpu/drm/i810/i810_dma.c @@ -37,6 +37,7 @@ #include /* For task queue support */ #include #include +#include #include #define I810_BUF_FREE 2 @@ -1240,22 +1241,35 @@ int i810_driver_dma_quiescent(struct drm_device *dev) return 0; } +/* + * call the drm_ioctl under the big kernel lock because + * to lock against the i810_mmap_buffers function. + */ +long i810_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + int ret; + lock_kernel(); + ret = drm_ioctl(file, cmd, arg); + unlock_kernel(); + return ret; +} + struct drm_ioctl_desc i810_ioctls[] = { - DRM_IOCTL_DEF(DRM_I810_INIT, i810_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_I810_VERTEX, i810_dma_vertex, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I810_CLEAR, i810_clear_bufs, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I810_FLUSH, i810_flush_ioctl, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I810_GETAGE, i810_getage, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I810_GETBUF, i810_getbuf, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I810_SWAP, i810_swap_bufs, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I810_COPY, i810_copybuf, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I810_DOCOPY, i810_docopy, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I810_OV0INFO, i810_ov0_info, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I810_FSTATUS, i810_fstatus, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I810_OV0FLIP, i810_ov0_flip, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I810_MC, i810_dma_mc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_I810_RSTATUS, i810_rstatus, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I810_FLIP, i810_flip_bufs, DRM_AUTH) + DRM_IOCTL_DEF(DRM_I810_INIT, i810_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_I810_VERTEX, i810_dma_vertex, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_I810_CLEAR, i810_clear_bufs, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_I810_FLUSH, i810_flush_ioctl, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_I810_GETAGE, i810_getage, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_I810_GETBUF, i810_getbuf, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_I810_SWAP, i810_swap_bufs, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_I810_COPY, i810_copybuf, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_I810_DOCOPY, i810_docopy, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_I810_OV0INFO, i810_ov0_info, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_I810_FSTATUS, i810_fstatus, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_I810_OV0FLIP, i810_ov0_flip, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_I810_MC, i810_dma_mc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_I810_RSTATUS, i810_rstatus, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_I810_FLIP, i810_flip_bufs, DRM_AUTH|DRM_UNLOCKED), }; int i810_max_ioctl = DRM_ARRAY_SIZE(i810_ioctls); diff --git a/drivers/gpu/drm/i810/i810_drv.c b/drivers/gpu/drm/i810/i810_drv.c index c1e02752e023..b4250b2cac1f 100644 --- a/drivers/gpu/drm/i810/i810_drv.c +++ b/drivers/gpu/drm/i810/i810_drv.c @@ -59,7 +59,7 @@ static struct drm_driver driver = { .owner = THIS_MODULE, .open = drm_open, .release = drm_release, - .unlocked_ioctl = drm_ioctl, + .unlocked_ioctl = i810_ioctl, .mmap = drm_mmap, .poll = drm_poll, .fasync = drm_fasync, diff --git a/drivers/gpu/drm/i810/i810_drv.h b/drivers/gpu/drm/i810/i810_drv.h index 0743fe90f1e3..c9339f481795 100644 --- a/drivers/gpu/drm/i810/i810_drv.h +++ b/drivers/gpu/drm/i810/i810_drv.h @@ -126,6 +126,7 @@ extern void i810_driver_reclaim_buffers_locked(struct drm_device *dev, struct drm_file *file_priv); extern int i810_driver_device_is_agp(struct drm_device *dev); +extern long i810_ioctl(struct file *file, unsigned int cmd, unsigned long arg); extern struct drm_ioctl_desc i810_ioctls[]; extern int i810_max_ioctl; diff --git a/drivers/gpu/drm/i830/i830_dma.c b/drivers/gpu/drm/i830/i830_dma.c index 7ee85ea507ce..5168862c9227 100644 --- a/drivers/gpu/drm/i830/i830_dma.c +++ b/drivers/gpu/drm/i830/i830_dma.c @@ -36,6 +36,7 @@ #include "i830_drm.h" #include "i830_drv.h" #include /* For task queue support */ +#include #include #include #include @@ -1509,21 +1510,34 @@ int i830_driver_dma_quiescent(struct drm_device *dev) return 0; } +/* + * call the drm_ioctl under the big kernel lock because + * to lock against the i830_mmap_buffers function. + */ +long i830_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + int ret; + lock_kernel(); + ret = drm_ioctl(file, cmd, arg); + unlock_kernel(); + return ret; +} + struct drm_ioctl_desc i830_ioctls[] = { - DRM_IOCTL_DEF(DRM_I830_INIT, i830_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_I830_VERTEX, i830_dma_vertex, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I830_CLEAR, i830_clear_bufs, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I830_FLUSH, i830_flush_ioctl, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I830_GETAGE, i830_getage, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I830_GETBUF, i830_getbuf, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I830_SWAP, i830_swap_bufs, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I830_COPY, i830_copybuf, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I830_DOCOPY, i830_docopy, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I830_FLIP, i830_flip_bufs, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I830_IRQ_EMIT, i830_irq_emit, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I830_IRQ_WAIT, i830_irq_wait, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I830_GETPARAM, i830_getparam, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I830_SETPARAM, i830_setparam, DRM_AUTH) + DRM_IOCTL_DEF(DRM_I830_INIT, i830_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_I830_VERTEX, i830_dma_vertex, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_I830_CLEAR, i830_clear_bufs, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_I830_FLUSH, i830_flush_ioctl, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_I830_GETAGE, i830_getage, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_I830_GETBUF, i830_getbuf, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_I830_SWAP, i830_swap_bufs, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_I830_COPY, i830_copybuf, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_I830_DOCOPY, i830_docopy, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_I830_FLIP, i830_flip_bufs, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_I830_IRQ_EMIT, i830_irq_emit, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_I830_IRQ_WAIT, i830_irq_wait, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_I830_GETPARAM, i830_getparam, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_I830_SETPARAM, i830_setparam, DRM_AUTH|DRM_UNLOCKED), }; int i830_max_ioctl = DRM_ARRAY_SIZE(i830_ioctls); diff --git a/drivers/gpu/drm/i830/i830_drv.c b/drivers/gpu/drm/i830/i830_drv.c index 44f990bed8f4..a5c66aa82f0c 100644 --- a/drivers/gpu/drm/i830/i830_drv.c +++ b/drivers/gpu/drm/i830/i830_drv.c @@ -70,7 +70,7 @@ static struct drm_driver driver = { .owner = THIS_MODULE, .open = drm_open, .release = drm_release, - .unlocked_ioctl = drm_ioctl, + .unlocked_ioctl = i830_ioctl, .mmap = drm_mmap, .poll = drm_poll, .fasync = drm_fasync, diff --git a/drivers/gpu/drm/i830/i830_drv.h b/drivers/gpu/drm/i830/i830_drv.h index ecfd25a35da3..0df1c720560b 100644 --- a/drivers/gpu/drm/i830/i830_drv.h +++ b/drivers/gpu/drm/i830/i830_drv.h @@ -122,6 +122,7 @@ typedef struct drm_i830_private { } drm_i830_private_t; +long i830_ioctl(struct file *file, unsigned int cmd, unsigned long arg); extern struct drm_ioctl_desc i830_ioctls[]; extern int i830_max_ioctl; diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 53017ba0ab7b..e2a4da7d7fab 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -52,7 +52,6 @@ #include #include #include -#include /* For (un)lock_kernel */ #include #include #include @@ -1152,6 +1151,7 @@ extern long drm_compat_ioctl(struct file *filp, extern int drm_lastclose(struct drm_device *dev); /* Device support (drm_fops.h) */ +extern struct mutex drm_global_mutex; extern int drm_open(struct inode *inode, struct file *filp); extern int drm_stub_open(struct inode *inode, struct file *filp); extern int drm_fasync(int fd, struct file *filp, int on); -- cgit v1.2.3