2005-04-17 05:20:36 +07:00
|
|
|
/*
|
2014-08-29 17:12:40 +07:00
|
|
|
* Internal Header for the Direct Rendering Manager
|
|
|
|
*
|
2005-04-17 05:20:36 +07:00
|
|
|
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
|
|
|
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
2010-05-28 02:40:25 +07:00
|
|
|
* Copyright (c) 2009-2010, Code Aurora Forum.
|
2005-04-17 05:20:36 +07:00
|
|
|
* All rights reserved.
|
|
|
|
*
|
2014-08-29 17:12:40 +07:00
|
|
|
* Author: Rickard E. (Rik) Faith <faith@valinux.com>
|
|
|
|
* Author: Gareth Hughes <gareth@valinux.com>
|
|
|
|
*
|
2005-04-17 05:20:36 +07:00
|
|
|
* 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
|
|
|
|
* VA LINUX SYSTEMS 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_P_H_
|
|
|
|
#define _DRM_P_H_
|
|
|
|
|
2014-08-29 17:12:37 +07:00
|
|
|
#include <linux/agp_backend.h>
|
|
|
|
#include <linux/cdev.h>
|
|
|
|
#include <linux/dma-mapping.h>
|
|
|
|
#include <linux/file.h>
|
2005-04-17 05:20:36 +07:00
|
|
|
#include <linux/fs.h>
|
2014-08-29 17:12:37 +07:00
|
|
|
#include <linux/highmem.h>
|
|
|
|
#include <linux/idr.h>
|
2005-04-17 05:20:36 +07:00
|
|
|
#include <linux/init.h>
|
2014-08-29 17:12:37 +07:00
|
|
|
#include <linux/io.h>
|
2005-04-17 05:20:36 +07:00
|
|
|
#include <linux/jiffies.h>
|
2014-08-29 17:12:37 +07:00
|
|
|
#include <linux/kernel.h>
|
|
|
|
#include <linux/kref.h>
|
|
|
|
#include <linux/miscdevice.h>
|
2005-04-17 05:20:36 +07:00
|
|
|
#include <linux/mm.h>
|
2006-02-02 15:37:46 +07:00
|
|
|
#include <linux/mutex.h>
|
2014-08-29 17:12:37 +07:00
|
|
|
#include <linux/pci.h>
|
|
|
|
#include <linux/platform_device.h>
|
|
|
|
#include <linux/poll.h>
|
2013-11-22 02:29:51 +07:00
|
|
|
#include <linux/ratelimit.h>
|
2016-09-27 03:44:14 +07:00
|
|
|
#include <linux/rbtree.h>
|
2014-08-29 17:12:37 +07:00
|
|
|
#include <linux/sched.h>
|
|
|
|
#include <linux/slab.h>
|
2005-04-17 05:20:36 +07:00
|
|
|
#include <linux/types.h>
|
2014-08-29 17:12:35 +07:00
|
|
|
#include <linux/vmalloc.h>
|
2014-08-29 17:12:37 +07:00
|
|
|
#include <linux/workqueue.h>
|
2016-10-25 19:00:45 +07:00
|
|
|
#include <linux/dma-fence.h>
|
2014-08-29 17:12:37 +07:00
|
|
|
|
|
|
|
#include <asm/mman.h>
|
2005-04-17 05:20:36 +07:00
|
|
|
#include <asm/pgalloc.h>
|
2014-08-29 17:12:37 +07:00
|
|
|
#include <asm/uaccess.h>
|
|
|
|
|
2014-08-29 17:12:40 +07:00
|
|
|
#include <uapi/drm/drm.h>
|
|
|
|
#include <uapi/drm/drm_mode.h>
|
|
|
|
|
|
|
|
#include <drm/drm_agpsupport.h>
|
|
|
|
#include <drm/drm_crtc.h>
|
2016-06-09 16:54:08 +07:00
|
|
|
#include <drm/drm_fourcc.h>
|
2014-08-29 17:12:40 +07:00
|
|
|
#include <drm/drm_global.h>
|
2014-08-29 17:12:37 +07:00
|
|
|
#include <drm/drm_hashtab.h>
|
2014-08-29 17:12:40 +07:00
|
|
|
#include <drm/drm_mem_util.h>
|
2014-08-29 17:12:37 +07:00
|
|
|
#include <drm/drm_mm.h>
|
|
|
|
#include <drm/drm_os_linux.h>
|
2012-10-03 00:01:03 +07:00
|
|
|
#include <drm/drm_sarea.h>
|
2013-07-25 02:07:52 +07:00
|
|
|
#include <drm/drm_vma_manager.h>
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2011-05-27 00:46:22 +07:00
|
|
|
struct module;
|
|
|
|
|
2007-09-03 09:06:45 +07:00
|
|
|
struct drm_file;
|
|
|
|
struct drm_device;
|
2014-08-29 17:12:32 +07:00
|
|
|
struct drm_agp_head;
|
2014-09-11 12:43:25 +07:00
|
|
|
struct drm_local_map;
|
|
|
|
struct drm_device_dma;
|
|
|
|
struct drm_dma_handle;
|
2014-09-23 20:46:53 +07:00
|
|
|
struct drm_gem_object;
|
2016-06-21 15:54:22 +07:00
|
|
|
struct drm_master;
|
2016-07-16 02:48:01 +07:00
|
|
|
struct drm_vblank_crtc;
|
2007-09-03 09:06:45 +07:00
|
|
|
|
2012-10-29 00:28:06 +07:00
|
|
|
struct device_node;
|
2012-11-14 17:22:52 +07:00
|
|
|
struct videomode;
|
2014-07-01 17:57:26 +07:00
|
|
|
struct reservation_object;
|
2014-01-09 17:03:14 +07:00
|
|
|
struct dma_buf_attachment;
|
2012-11-14 17:22:52 +07:00
|
|
|
|
2009-07-20 12:48:06 +07:00
|
|
|
/*
|
2016-04-14 21:34:16 +07:00
|
|
|
* The following categories are defined:
|
2014-03-24 22:53:08 +07:00
|
|
|
*
|
|
|
|
* CORE: Used in the generic drm code: drm_ioctl.c, drm_mm.c, drm_memory.c, ...
|
|
|
|
* This is the category used by the DRM_DEBUG() macro.
|
|
|
|
*
|
|
|
|
* DRIVER: Used in the vendor specific part of the driver: i915, radeon, ...
|
|
|
|
* This is the category used by the DRM_DEBUG_DRIVER() macro.
|
2009-07-20 12:48:06 +07:00
|
|
|
*
|
2014-03-24 22:53:08 +07:00
|
|
|
* KMS: used in the modesetting code.
|
|
|
|
* This is the category used by the DRM_DEBUG_KMS() macro.
|
2009-07-20 12:48:06 +07:00
|
|
|
*
|
2014-03-24 22:53:08 +07:00
|
|
|
* PRIME: used in the prime code.
|
|
|
|
* This is the category used by the DRM_DEBUG_PRIME() macro.
|
2009-07-20 12:48:06 +07:00
|
|
|
*
|
2015-02-22 18:24:16 +07:00
|
|
|
* ATOMIC: used in the atomic code.
|
|
|
|
* This is the category used by the DRM_DEBUG_ATOMIC() macro.
|
|
|
|
*
|
2015-10-10 02:57:37 +07:00
|
|
|
* VBL: used for verbose debug message in the vblank code
|
|
|
|
* This is the category used by the DRM_DEBUG_VBL() macro.
|
|
|
|
*
|
2014-03-24 22:53:08 +07:00
|
|
|
* Enabling verbose debug messages is done through the drm.debug parameter,
|
|
|
|
* each category being enabled by a bit.
|
|
|
|
*
|
|
|
|
* drm.debug=0x1 will enable CORE messages
|
|
|
|
* drm.debug=0x2 will enable DRIVER messages
|
|
|
|
* drm.debug=0x3 will enable CORE and DRIVER messages
|
|
|
|
* ...
|
2015-10-10 02:57:37 +07:00
|
|
|
* drm.debug=0x3f will enable all messages
|
2014-03-24 22:53:08 +07:00
|
|
|
*
|
|
|
|
* An interesting feature is that it's possible to enable verbose logging at
|
|
|
|
* run-time by echoing the debug value in its sysfs node:
|
|
|
|
* # echo 0xf > /sys/module/drm/parameters/debug
|
2009-07-20 12:48:06 +07:00
|
|
|
*/
|
2016-08-16 06:18:04 +07:00
|
|
|
#define DRM_UT_NONE 0x00
|
2014-03-24 22:53:08 +07:00
|
|
|
#define DRM_UT_CORE 0x01
|
|
|
|
#define DRM_UT_DRIVER 0x02
|
|
|
|
#define DRM_UT_KMS 0x04
|
|
|
|
#define DRM_UT_PRIME 0x08
|
2015-02-22 18:24:16 +07:00
|
|
|
#define DRM_UT_ATOMIC 0x10
|
2015-10-10 02:57:37 +07:00
|
|
|
#define DRM_UT_VBL 0x20
|
drm: add separate drm debugging levels
Now all the DRM debug info will be reported if the boot option of
"drm.debug=1" is added. Sometimes it is inconvenient to get the debug
info in KMS mode. We will get too much unrelated info.
This will separate several DRM debug levels and the debug level can be used
to print the different debug info. And the debug level is controlled by the
module parameter of drm.debug
In this patch it is divided into four debug levels;
drm_core, drm_driver, drm_kms, drm_mode.
At the same time we can get the different debug info by changing the debug
level. This can be done by adding the module parameter. Of course it can
be changed through the /sys/module/drm/parameters/debug after the system is
booted.
Four debug macro definitions are provided.
DRM_DEBUG(fmt, args...)
DRM_DEBUG_DRIVER(prefix, fmt, args...)
DRM_DEBUG_KMS(prefix, fmt, args...)
DRM_DEBUG_MODE(prefix, fmt, args...)
When the boot option of "drm.debug=4" is added, it will print the debug info
using DRM_DEBUG_KMS macro definition.
When the boot option of "drm.debug=6" is added, it will print the debug info
using DRM_DEBUG_KMS/DRM_DEBUG_DRIVER.
Sometimes we expect to print the value of an array.
For example: SDVO command,
In such case the following four DRM debug macro definitions are added:
DRM_LOG(fmt, args...)
DRM_LOG_DRIVER(fmt, args...)
DRM_LOG_KMS(fmt, args...)
DRM_LOG_MODE(fmt, args...)
Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2009-06-02 13:09:47 +07:00
|
|
|
|
2016-08-16 06:18:04 +07:00
|
|
|
extern __printf(6, 7)
|
|
|
|
void drm_dev_printk(const struct device *dev, const char *level,
|
|
|
|
unsigned int category, const char *function_name,
|
|
|
|
const char *prefix, const char *format, ...);
|
|
|
|
|
2016-09-26 09:18:34 +07:00
|
|
|
extern __printf(3, 4)
|
2016-08-16 06:18:04 +07:00
|
|
|
void drm_printk(const char *level, unsigned int category,
|
|
|
|
const char *format, ...);
|
2011-04-18 10:35:51 +07:00
|
|
|
|
2005-04-17 05:20:36 +07:00
|
|
|
/***********************************************************************/
|
|
|
|
/** \name DRM template customization defaults */
|
|
|
|
/*@{*/
|
|
|
|
|
|
|
|
/* driver capabilities and requirements mask */
|
2015-06-23 14:18:49 +07:00
|
|
|
#define DRIVER_USE_AGP 0x1
|
2016-08-04 02:11:09 +07:00
|
|
|
#define DRIVER_LEGACY 0x2
|
2015-06-23 14:18:49 +07:00
|
|
|
#define DRIVER_PCI_DMA 0x8
|
|
|
|
#define DRIVER_SG 0x10
|
|
|
|
#define DRIVER_HAVE_DMA 0x20
|
|
|
|
#define DRIVER_HAVE_IRQ 0x40
|
|
|
|
#define DRIVER_IRQ_SHARED 0x80
|
|
|
|
#define DRIVER_GEM 0x1000
|
|
|
|
#define DRIVER_MODESET 0x2000
|
|
|
|
#define DRIVER_PRIME 0x4000
|
|
|
|
#define DRIVER_RENDER 0x8000
|
|
|
|
#define DRIVER_ATOMIC 0x10000
|
|
|
|
#define DRIVER_KMS_LEGACY_CONTEXT 0x20000
|
2010-12-15 00:16:38 +07:00
|
|
|
|
2005-04-17 05:20:36 +07:00
|
|
|
/***********************************************************************/
|
|
|
|
/** \name Macros to make printk easier */
|
|
|
|
/*@{*/
|
|
|
|
|
2016-08-19 00:17:22 +07:00
|
|
|
#define _DRM_PRINTK(once, level, fmt, ...) \
|
|
|
|
do { \
|
|
|
|
printk##once(KERN_##level "[" DRM_NAME "] " fmt, \
|
|
|
|
##__VA_ARGS__); \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define DRM_INFO(fmt, ...) \
|
|
|
|
_DRM_PRINTK(, INFO, fmt, ##__VA_ARGS__)
|
|
|
|
#define DRM_NOTE(fmt, ...) \
|
|
|
|
_DRM_PRINTK(, NOTICE, fmt, ##__VA_ARGS__)
|
|
|
|
#define DRM_WARN(fmt, ...) \
|
|
|
|
_DRM_PRINTK(, WARNING, fmt, ##__VA_ARGS__)
|
|
|
|
|
|
|
|
#define DRM_INFO_ONCE(fmt, ...) \
|
|
|
|
_DRM_PRINTK(_once, INFO, fmt, ##__VA_ARGS__)
|
|
|
|
#define DRM_NOTE_ONCE(fmt, ...) \
|
|
|
|
_DRM_PRINTK(_once, NOTICE, fmt, ##__VA_ARGS__)
|
|
|
|
#define DRM_WARN_ONCE(fmt, ...) \
|
|
|
|
_DRM_PRINTK(_once, WARNING, fmt, ##__VA_ARGS__)
|
|
|
|
|
2005-04-17 05:20:36 +07:00
|
|
|
/**
|
|
|
|
* Error output.
|
|
|
|
*
|
|
|
|
* \param fmt printf() like format string.
|
|
|
|
* \param arg arguments
|
|
|
|
*/
|
2016-08-16 06:18:04 +07:00
|
|
|
#define DRM_DEV_ERROR(dev, fmt, ...) \
|
|
|
|
drm_dev_printk(dev, KERN_ERR, DRM_UT_NONE, __func__, " *ERROR*",\
|
|
|
|
fmt, ##__VA_ARGS__)
|
|
|
|
#define DRM_ERROR(fmt, ...) \
|
2016-09-26 09:18:34 +07:00
|
|
|
drm_printk(KERN_ERR, DRM_UT_NONE, fmt, ##__VA_ARGS__)
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2013-11-22 02:29:51 +07:00
|
|
|
/**
|
|
|
|
* Rate limited error output. Like DRM_ERROR() but won't flood the log.
|
|
|
|
*
|
|
|
|
* \param fmt printf() like format string.
|
|
|
|
* \param arg arguments
|
|
|
|
*/
|
2016-08-16 06:18:04 +07:00
|
|
|
#define DRM_DEV_ERROR_RATELIMITED(dev, fmt, ...) \
|
2013-11-22 02:29:51 +07:00
|
|
|
({ \
|
|
|
|
static DEFINE_RATELIMIT_STATE(_rs, \
|
|
|
|
DEFAULT_RATELIMIT_INTERVAL, \
|
|
|
|
DEFAULT_RATELIMIT_BURST); \
|
|
|
|
\
|
|
|
|
if (__ratelimit(&_rs)) \
|
2016-08-16 06:18:04 +07:00
|
|
|
DRM_DEV_ERROR(dev, fmt, ##__VA_ARGS__); \
|
2013-11-22 02:29:51 +07:00
|
|
|
})
|
2016-08-16 06:18:04 +07:00
|
|
|
#define DRM_ERROR_RATELIMITED(fmt, ...) \
|
|
|
|
DRM_DEV_ERROR_RATELIMITED(NULL, fmt, ##__VA_ARGS__)
|
2013-11-22 02:29:51 +07:00
|
|
|
|
2016-08-16 06:18:04 +07:00
|
|
|
#define DRM_DEV_INFO(dev, fmt, ...) \
|
|
|
|
drm_dev_printk(dev, KERN_INFO, DRM_UT_NONE, __func__, "", fmt, \
|
|
|
|
##__VA_ARGS__)
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2016-08-16 06:18:04 +07:00
|
|
|
#define DRM_DEV_INFO_ONCE(dev, fmt, ...) \
|
|
|
|
({ \
|
|
|
|
static bool __print_once __read_mostly; \
|
|
|
|
if (!__print_once) { \
|
|
|
|
__print_once = true; \
|
|
|
|
DRM_DEV_INFO(dev, fmt, ##__VA_ARGS__); \
|
|
|
|
} \
|
|
|
|
})
|
2014-01-31 20:49:07 +07:00
|
|
|
|
2005-04-17 05:20:36 +07:00
|
|
|
/**
|
|
|
|
* Debug output.
|
2005-09-25 11:28:13 +07:00
|
|
|
*
|
2005-04-17 05:20:36 +07:00
|
|
|
* \param fmt printf() like format string.
|
|
|
|
* \param arg arguments
|
|
|
|
*/
|
2016-08-16 06:18:04 +07:00
|
|
|
#define DRM_DEV_DEBUG(dev, fmt, args...) \
|
|
|
|
drm_dev_printk(dev, KERN_DEBUG, DRM_UT_CORE, __func__, "", fmt, \
|
|
|
|
##args)
|
2016-09-26 09:18:34 +07:00
|
|
|
#define DRM_DEBUG(fmt, ...) \
|
|
|
|
drm_printk(KERN_DEBUG, DRM_UT_CORE, fmt, ##__VA_ARGS__)
|
drm: add separate drm debugging levels
Now all the DRM debug info will be reported if the boot option of
"drm.debug=1" is added. Sometimes it is inconvenient to get the debug
info in KMS mode. We will get too much unrelated info.
This will separate several DRM debug levels and the debug level can be used
to print the different debug info. And the debug level is controlled by the
module parameter of drm.debug
In this patch it is divided into four debug levels;
drm_core, drm_driver, drm_kms, drm_mode.
At the same time we can get the different debug info by changing the debug
level. This can be done by adding the module parameter. Of course it can
be changed through the /sys/module/drm/parameters/debug after the system is
booted.
Four debug macro definitions are provided.
DRM_DEBUG(fmt, args...)
DRM_DEBUG_DRIVER(prefix, fmt, args...)
DRM_DEBUG_KMS(prefix, fmt, args...)
DRM_DEBUG_MODE(prefix, fmt, args...)
When the boot option of "drm.debug=4" is added, it will print the debug info
using DRM_DEBUG_KMS macro definition.
When the boot option of "drm.debug=6" is added, it will print the debug info
using DRM_DEBUG_KMS/DRM_DEBUG_DRIVER.
Sometimes we expect to print the value of an array.
For example: SDVO command,
In such case the following four DRM debug macro definitions are added:
DRM_LOG(fmt, args...)
DRM_LOG_DRIVER(fmt, args...)
DRM_LOG_KMS(fmt, args...)
DRM_LOG_MODE(fmt, args...)
Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2009-06-02 13:09:47 +07:00
|
|
|
|
2016-08-16 06:18:04 +07:00
|
|
|
#define DRM_DEV_DEBUG_DRIVER(dev, fmt, args...) \
|
|
|
|
drm_dev_printk(dev, KERN_DEBUG, DRM_UT_DRIVER, __func__, "", \
|
|
|
|
fmt, ##args)
|
2016-09-26 09:18:34 +07:00
|
|
|
#define DRM_DEBUG_DRIVER(fmt, ...) \
|
|
|
|
drm_printk(KERN_DEBUG, DRM_UT_DRIVER, fmt, ##__VA_ARGS__)
|
2016-08-16 06:18:04 +07:00
|
|
|
|
|
|
|
#define DRM_DEV_DEBUG_KMS(dev, fmt, args...) \
|
|
|
|
drm_dev_printk(dev, KERN_DEBUG, DRM_UT_KMS, __func__, "", fmt, \
|
|
|
|
##args)
|
2016-09-26 09:18:34 +07:00
|
|
|
#define DRM_DEBUG_KMS(fmt, ...) \
|
|
|
|
drm_printk(KERN_DEBUG, DRM_UT_KMS, fmt, ##__VA_ARGS__)
|
2016-08-16 06:18:04 +07:00
|
|
|
|
|
|
|
#define DRM_DEV_DEBUG_PRIME(dev, fmt, args...) \
|
|
|
|
drm_dev_printk(dev, KERN_DEBUG, DRM_UT_PRIME, __func__, "", \
|
|
|
|
fmt, ##args)
|
2016-09-26 09:18:34 +07:00
|
|
|
#define DRM_DEBUG_PRIME(fmt, ...) \
|
|
|
|
drm_printk(KERN_DEBUG, DRM_UT_PRIME, fmt, ##__VA_ARGS__)
|
2016-08-16 06:18:04 +07:00
|
|
|
|
|
|
|
#define DRM_DEV_DEBUG_ATOMIC(dev, fmt, args...) \
|
|
|
|
drm_dev_printk(dev, KERN_DEBUG, DRM_UT_ATOMIC, __func__, "", \
|
|
|
|
fmt, ##args)
|
2016-09-26 09:18:34 +07:00
|
|
|
#define DRM_DEBUG_ATOMIC(fmt, ...) \
|
|
|
|
drm_printk(KERN_DEBUG, DRM_UT_ATOMIC, fmt, ##__VA_ARGS__)
|
2016-08-16 06:18:04 +07:00
|
|
|
|
|
|
|
#define DRM_DEV_DEBUG_VBL(dev, fmt, args...) \
|
|
|
|
drm_dev_printk(dev, KERN_DEBUG, DRM_UT_VBL, __func__, "", fmt, \
|
|
|
|
##args)
|
2016-09-26 09:18:34 +07:00
|
|
|
#define DRM_DEBUG_VBL(fmt, ...) \
|
|
|
|
drm_printk(KERN_DEBUG, DRM_UT_VBL, fmt, ##__VA_ARGS__)
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2016-08-16 06:18:04 +07:00
|
|
|
#define _DRM_DEV_DEFINE_DEBUG_RATELIMITED(dev, level, fmt, args...) \
|
|
|
|
({ \
|
|
|
|
static DEFINE_RATELIMIT_STATE(_rs, \
|
|
|
|
DEFAULT_RATELIMIT_INTERVAL, \
|
|
|
|
DEFAULT_RATELIMIT_BURST); \
|
|
|
|
if (__ratelimit(&_rs)) \
|
|
|
|
drm_dev_printk(dev, KERN_DEBUG, DRM_UT_ ## level, \
|
|
|
|
__func__, "", fmt, ##args); \
|
|
|
|
})
|
2016-08-06 07:30:38 +07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Rate limited debug output. Like DRM_DEBUG() but won't flood the log.
|
|
|
|
*
|
|
|
|
* \param fmt printf() like format string.
|
|
|
|
* \param arg arguments
|
|
|
|
*/
|
2016-08-16 06:18:04 +07:00
|
|
|
#define DRM_DEV_DEBUG_RATELIMITED(dev, fmt, args...) \
|
|
|
|
DEV__DRM_DEFINE_DEBUG_RATELIMITED(dev, CORE, fmt, ##args)
|
2016-08-06 07:30:38 +07:00
|
|
|
#define DRM_DEBUG_RATELIMITED(fmt, args...) \
|
2016-08-16 06:18:04 +07:00
|
|
|
DRM_DEV_DEBUG_RATELIMITED(NULL, fmt, ##args)
|
|
|
|
#define DRM_DEV_DEBUG_DRIVER_RATELIMITED(dev, fmt, args...) \
|
|
|
|
_DRM_DEV_DEFINE_DEBUG_RATELIMITED(dev, DRIVER, fmt, ##args)
|
2016-08-06 07:30:38 +07:00
|
|
|
#define DRM_DEBUG_DRIVER_RATELIMITED(fmt, args...) \
|
2016-08-16 06:18:04 +07:00
|
|
|
DRM_DEV_DEBUG_DRIVER_RATELIMITED(NULL, fmt, ##args)
|
|
|
|
#define DRM_DEV_DEBUG_KMS_RATELIMITED(dev, fmt, args...) \
|
|
|
|
_DRM_DEV_DEFINE_DEBUG_RATELIMITED(dev, KMS, fmt, ##args)
|
2016-08-06 07:30:38 +07:00
|
|
|
#define DRM_DEBUG_KMS_RATELIMITED(fmt, args...) \
|
2016-08-16 06:18:04 +07:00
|
|
|
DRM_DEV_DEBUG_KMS_RATELIMITED(NULL, fmt, ##args)
|
|
|
|
#define DRM_DEV_DEBUG_PRIME_RATELIMITED(dev, fmt, args...) \
|
|
|
|
_DRM_DEV_DEFINE_DEBUG_RATELIMITED(dev, PRIME, fmt, ##args)
|
2016-08-06 07:30:38 +07:00
|
|
|
#define DRM_DEBUG_PRIME_RATELIMITED(fmt, args...) \
|
2016-08-16 06:18:04 +07:00
|
|
|
DRM_DEV_DEBUG_PRIME_RATELIMITED(NULL, fmt, ##args)
|
2016-08-06 07:30:38 +07:00
|
|
|
|
2005-04-17 05:20:36 +07:00
|
|
|
/*@}*/
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/** \name Internal types and structures */
|
|
|
|
/*@{*/
|
|
|
|
|
|
|
|
#define DRM_IF_VERSION(maj, min) (maj << 16 | min)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Ioctl function type.
|
|
|
|
*
|
|
|
|
* \param inode device inode.
|
2007-08-25 17:23:09 +07:00
|
|
|
* \param file_priv DRM file private pointer.
|
2005-04-17 05:20:36 +07:00
|
|
|
* \param cmd command.
|
|
|
|
* \param arg argument.
|
|
|
|
*/
|
2007-09-03 09:06:45 +07:00
|
|
|
typedef int drm_ioctl_t(struct drm_device *dev, void *data,
|
|
|
|
struct drm_file *file_priv);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
drm: 32/64-bit DRM ioctl compatibility patch
The patch is against a 2.6.11 kernel tree. I am running this with a
32-bit X server (compiled up from X.org CVS as of a couple of weeks
ago) and 32-bit DRI libraries and clients. All the userland stuff is
identical to what I am using under a 32-bit kernel on my G4 powerbook
(which is a 32-bit machine of course). I haven't tried compiling up a
64-bit X server or clients yet.
In the compatibility routines I have assumed that the kernel can
safely access user addresses after set_fs(KERNEL_DS). That is, where
an ioctl argument structure contains pointers to other structures, and
those other structures are already compatible between the 32-bit and
64-bit ABIs (i.e. they only contain things like chars, shorts or
ints), I just check the address with access_ok() and then pass it
through to the 64-bit ioctl code. I believe this approach may not
work on sparc64, but it does work on ppc64 and x86_64 at least.
One tricky area which may need to be revisited is the question of how
to handle the handles which we pass back to userspace to identify
mappings. These handles are generated in the ADDMAP ioctl and then
passed in as the offset value to mmap. However, offset values for
mmap seem to be generated in other ways as well, particularly for AGP
mappings.
The approach I have ended up with is to generate a fake 32-bit handle
only for _DRM_SHM mappings. The handles for other mappings (AGP, REG,
FB) are physical addresses which are already limited to 32 bits, and
generating fake handles for them created all sorts of problems in the
mmap/nopage code.
This patch has been updated to use the new compatibility ioctls.
From: Paul Mackerras <paulus@samba.org>
Signed-off-by: Dave Airlie <airlied@linux.ie>
2005-06-23 18:29:18 +07:00
|
|
|
typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd,
|
|
|
|
unsigned long arg);
|
|
|
|
|
2009-12-03 00:13:48 +07:00
|
|
|
#define DRM_IOCTL_NR(n) _IOC_NR(n)
|
|
|
|
#define DRM_MAJOR 226
|
|
|
|
|
2006-01-02 09:54:04 +07:00
|
|
|
#define DRM_AUTH 0x1
|
|
|
|
#define DRM_MASTER 0x2
|
|
|
|
#define DRM_ROOT_ONLY 0x4
|
2008-11-08 05:05:41 +07:00
|
|
|
#define DRM_CONTROL_ALLOW 0x8
|
2009-12-17 05:17:09 +07:00
|
|
|
#define DRM_UNLOCKED 0x10
|
drm: implement experimental render nodes
Render nodes provide an API for userspace to use non-privileged GPU
commands without any running DRM-Master. It is useful for offscreen
rendering, GPGPU clients, and normal render clients which do not perform
modesetting.
Compared to legacy clients, render clients no longer need any
authentication to perform client ioctls. Instead, user-space controls
render/client access to GPUs via filesystem access-modes on the
render-node. Once a render-node was opened, a client has full access to
the client/render operations on the GPU. However, no modesetting or ioctls
that affect global state are allowed on render nodes.
To prevent privilege-escalation, drivers must explicitly state that they
support render nodes. They must mark their render-only ioctls as
DRM_RENDER_ALLOW so render clients can use them. Furthermore, they must
support clients without any attached master.
If filesystem access-modes are not enough for fine-grained access control
to render nodes (very unlikely, considering the versaitlity of FS-ACLs),
you may still fall-back to fd-passing from server to client (which allows
arbitrary access-control). However, note that revoking access is
currently impossible and unlikely to get implemented.
Note: Render clients no longer have any associated DRM-Master as they are
supposed to be independent of any server state. DRM core highly depends on
file_priv->master to be non-NULL for modesetting/ctx/etc. commands.
Therefore, drivers must be very careful to not require DRM-Master if they
support DRIVER_RENDER.
So far render-nodes are protected by "drm_rnodes". As long as this
module-parameter is not set to 1, a driver will not create render nodes.
This allows us to experiment with the API a bit before we stabilize it.
v2: drop insecure GEM_FLINK to force use of dmabuf
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2013-08-25 23:29:00 +07:00
|
|
|
#define DRM_RENDER_ALLOW 0x20
|
2006-01-02 09:54:04 +07:00
|
|
|
|
2007-09-03 09:06:45 +07:00
|
|
|
struct drm_ioctl_desc {
|
|
|
|
unsigned int cmd;
|
2006-01-02 09:54:04 +07:00
|
|
|
int flags;
|
2009-03-19 00:26:44 +07:00
|
|
|
drm_ioctl_t *func;
|
drm: Use names of ioctls in debug traces
The intention here is to make the output of dmesg with full verbosity a
bit easier for a human to parse. This commit transforms:
[drm:drm_ioctl], pid=699, cmd=0x6458, nr=0x58, dev 0xe200, auth=1
[drm:drm_ioctl], pid=699, cmd=0xc010645b, nr=0x5b, dev 0xe200, auth=1
[drm:drm_ioctl], pid=699, cmd=0xc0106461, nr=0x61, dev 0xe200, auth=1
[drm:drm_ioctl], pid=699, cmd=0xc01c64ae, nr=0xae, dev 0xe200, auth=1
[drm:drm_mode_addfb], [FB:32]
[drm:drm_ioctl], pid=699, cmd=0xc0106464, nr=0x64, dev 0xe200, auth=1
[drm:drm_vm_open_locked], 0x7fd9302fe000,0x00a00000
[drm:drm_ioctl], pid=699, cmd=0x400c645f, nr=0x5f, dev 0xe200, auth=1
[drm:drm_ioctl], pid=699, cmd=0xc00464af, nr=0xaf, dev 0xe200, auth=1
[drm:intel_crtc_set_config], [CRTC:3] [NOFB]
into:
[drm:drm_ioctl], pid=699, dev=0xe200, auth=1, I915_GEM_THROTTLE
[drm:drm_ioctl], pid=699, dev=0xe200, auth=1, I915_GEM_CREATE
[drm:drm_ioctl], pid=699, dev=0xe200, auth=1, I915_GEM_SET_TILING
[drm:drm_ioctl], pid=699, dev=0xe200, auth=1, IOCTL_MODE_ADDFB
[drm:drm_mode_addfb], [FB:32]
[drm:drm_ioctl], pid=699, dev=0xe200, auth=1, I915_GEM_MMAP_GTT
[drm:drm_vm_open_locked], 0x7fd9302fe000,0x00a00000
[drm:drm_ioctl], pid=699, dev=0xe200, auth=1, I915_GEM_SET_DOMAIN
[drm:drm_ioctl], pid=699, dev=0xe200, auth=1, DRM_IOCTL_MODE_RMFB
[drm:intel_crtc_set_config], [CRTC:3] [NOFB]
v2: drm_ioctls is now a constant (Ville Syrjälä)
Signed-off-by: Chris Cummins <christopher.e.cummins@intel.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2013-05-09 20:20:40 +07:00
|
|
|
const char *name;
|
2007-09-03 09:06:45 +07:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates a driver or general drm_ioctl_desc array entry for the given
|
|
|
|
* ioctl, for use by drm_ioctl().
|
|
|
|
*/
|
2010-08-14 17:20:34 +07:00
|
|
|
|
2015-03-31 00:10:36 +07:00
|
|
|
#define DRM_IOCTL_DEF_DRV(ioctl, _func, _flags) \
|
|
|
|
[DRM_IOCTL_NR(DRM_IOCTL_##ioctl) - DRM_COMMAND_BASE] = { \
|
|
|
|
.cmd = DRM_IOCTL_##ioctl, \
|
|
|
|
.func = _func, \
|
|
|
|
.flags = _flags, \
|
|
|
|
.name = #ioctl \
|
|
|
|
}
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2009-09-12 01:33:34 +07:00
|
|
|
/* Event queued up for userspace to read */
|
|
|
|
struct drm_pending_event {
|
2016-06-08 19:19:00 +07:00
|
|
|
struct completion *completion;
|
2009-09-12 01:33:34 +07:00
|
|
|
struct drm_event *event;
|
2016-10-25 19:00:45 +07:00
|
|
|
struct dma_fence *fence;
|
2009-09-12 01:33:34 +07:00
|
|
|
struct list_head link;
|
2016-01-26 04:16:43 +07:00
|
|
|
struct list_head pending_link;
|
2009-09-12 01:33:34 +07:00
|
|
|
struct drm_file *file_priv;
|
2010-07-02 06:48:09 +07:00
|
|
|
pid_t pid; /* pid of requester, no guarantee it's valid by the time
|
|
|
|
we deliver the event, for tracing only */
|
2009-09-12 01:33:34 +07:00
|
|
|
};
|
|
|
|
|
2011-11-25 22:21:02 +07:00
|
|
|
struct drm_prime_file_private {
|
|
|
|
struct mutex lock;
|
2016-09-27 03:44:14 +07:00
|
|
|
struct rb_root dmabufs;
|
|
|
|
struct rb_root handles;
|
2011-11-25 22:21:02 +07:00
|
|
|
};
|
|
|
|
|
2005-04-17 05:20:36 +07:00
|
|
|
/** File private data */
|
2007-07-11 12:53:27 +07:00
|
|
|
struct drm_file {
|
2013-10-29 15:55:58 +07:00
|
|
|
unsigned authenticated :1;
|
|
|
|
/* true when the client has asked us to expose stereo 3D mode flags */
|
|
|
|
unsigned stereo_allowed :1;
|
2014-04-02 05:22:42 +07:00
|
|
|
/*
|
|
|
|
* true if client understands CRTC primary planes and cursor planes
|
|
|
|
* in the plane list
|
|
|
|
*/
|
|
|
|
unsigned universal_planes:1;
|
2014-12-19 04:01:50 +07:00
|
|
|
/* true if client understands atomic properties */
|
|
|
|
unsigned atomic:1;
|
2015-12-03 00:24:46 +07:00
|
|
|
/*
|
2016-06-21 15:54:21 +07:00
|
|
|
* This client is the creator of @master.
|
2015-12-03 00:24:46 +07:00
|
|
|
* Protected by struct drm_device::master_mutex.
|
|
|
|
*/
|
2016-06-21 15:54:21 +07:00
|
|
|
unsigned is_master:1;
|
2013-10-29 15:55:58 +07:00
|
|
|
|
2012-02-08 07:47:26 +07:00
|
|
|
struct pid *pid;
|
2005-09-25 11:28:13 +07:00
|
|
|
drm_magic_t magic;
|
2007-05-26 02:01:51 +07:00
|
|
|
struct list_head lhead;
|
2008-04-21 13:47:32 +07:00
|
|
|
struct drm_minor *minor;
|
2005-09-25 11:28:13 +07:00
|
|
|
unsigned long lock_count;
|
2008-11-28 11:22:24 +07:00
|
|
|
|
2008-07-31 02:06:12 +07:00
|
|
|
/** Mapping of mm object handles to object pointers. */
|
|
|
|
struct idr object_idr;
|
|
|
|
/** Lock for synchronization of access to object_idr. */
|
|
|
|
spinlock_t table_lock;
|
2008-11-28 11:22:24 +07:00
|
|
|
|
2007-08-25 17:23:09 +07:00
|
|
|
struct file *filp;
|
2007-11-05 09:37:41 +07:00
|
|
|
void *driver_priv;
|
2008-11-28 11:22:24 +07:00
|
|
|
|
|
|
|
struct drm_master *master; /* master this node is currently associated with
|
2016-06-21 15:54:12 +07:00
|
|
|
N.B. not always dev->master */
|
drm: revamp locking around fb creation/destruction
Well, at least step 1. The goal here is that framebuffer objects can
survive outside of the mode_config lock, with just a reference held
as protection. The first step to get there is to introduce a special
fb_lock which protects fb lookup, creation and destruction, to make
them appear atomic.
This new fb_lock can nest within the mode_config lock. But the idea is
(once the reference counting part is completed) that we only quickly
take that fb_lock to lookup a framebuffer and grab a reference,
without any other locks involved.
vmwgfx is the only driver which does framebuffer lookups itself, also
wrap those calls to drm_mode_object_find with the new lock.
Also protect the fb_list walking in i915 and omapdrm with the new lock.
As a slight complication there's also the list of user-created fbs
attached to the file private. The problem now is that at fclose() time
we need to walk that list, eventually do a modeset call to remove the
fb from active usage (and are required to be able to take the
mode_config lock), but in the end we need to grab the new fb_lock to
remove the fb from the list. The easiest solution is to add another
mutex to protect this per-file list.
Currently that new fbs_lock nests within the modeset locks and so
appears redudant. But later patches will switch around this sequence
so that taking the modeset locks in the fb destruction path is
optional in the fastpath. Ultimately the goal is that addfb and rmfb
do not require the mode_config lock, since otherwise they have the
potential to introduce stalls in the pageflip sequence of a compositor
(if the compositor e.g. switches to a fullscreen client or if it
enables a plane). But that requires a few more steps and hoops to jump
through.
Note that framebuffer creation/destruction is now double-protected -
once by the fb_lock and in parts by the idr_lock. The later would be
unnecessariy if framebuffers would have their own idr allocator. But
that's material for another patch (series).
v2: Properly initialize the fb->filp_head list in _init, otherwise the
newly added WARN to check whether the fb isn't on a fpriv list any
more will fail for driver-private objects.
v3: Fixup two error-case unlock bugs spotted by Richard Wilbur.
Reviewed-by: Rob Clark <rob@ti.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-12-11 03:19:18 +07:00
|
|
|
/**
|
|
|
|
* fbs - List of framebuffers associated with this file.
|
|
|
|
*
|
|
|
|
* Protected by fbs_lock. Note that the fbs list holds a reference on
|
|
|
|
* the fb object to prevent it from untimely disappearing.
|
|
|
|
*/
|
2008-11-08 05:05:41 +07:00
|
|
|
struct list_head fbs;
|
drm: revamp locking around fb creation/destruction
Well, at least step 1. The goal here is that framebuffer objects can
survive outside of the mode_config lock, with just a reference held
as protection. The first step to get there is to introduce a special
fb_lock which protects fb lookup, creation and destruction, to make
them appear atomic.
This new fb_lock can nest within the mode_config lock. But the idea is
(once the reference counting part is completed) that we only quickly
take that fb_lock to lookup a framebuffer and grab a reference,
without any other locks involved.
vmwgfx is the only driver which does framebuffer lookups itself, also
wrap those calls to drm_mode_object_find with the new lock.
Also protect the fb_list walking in i915 and omapdrm with the new lock.
As a slight complication there's also the list of user-created fbs
attached to the file private. The problem now is that at fclose() time
we need to walk that list, eventually do a modeset call to remove the
fb from active usage (and are required to be able to take the
mode_config lock), but in the end we need to grab the new fb_lock to
remove the fb from the list. The easiest solution is to add another
mutex to protect this per-file list.
Currently that new fbs_lock nests within the modeset locks and so
appears redudant. But later patches will switch around this sequence
so that taking the modeset locks in the fb destruction path is
optional in the fastpath. Ultimately the goal is that addfb and rmfb
do not require the mode_config lock, since otherwise they have the
potential to introduce stalls in the pageflip sequence of a compositor
(if the compositor e.g. switches to a fullscreen client or if it
enables a plane). But that requires a few more steps and hoops to jump
through.
Note that framebuffer creation/destruction is now double-protected -
once by the fb_lock and in parts by the idr_lock. The later would be
unnecessariy if framebuffers would have their own idr allocator. But
that's material for another patch (series).
v2: Properly initialize the fb->filp_head list in _init, otherwise the
newly added WARN to check whether the fb isn't on a fpriv list any
more will fail for driver-private objects.
v3: Fixup two error-case unlock bugs spotted by Richard Wilbur.
Reviewed-by: Rob Clark <rob@ti.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-12-11 03:19:18 +07:00
|
|
|
struct mutex fbs_lock;
|
2009-09-12 01:33:34 +07:00
|
|
|
|
2015-05-22 19:34:51 +07:00
|
|
|
/** User-created blob properties; this retains a reference on the
|
|
|
|
* property. */
|
|
|
|
struct list_head blobs;
|
|
|
|
|
2009-09-12 01:33:34 +07:00
|
|
|
wait_queue_head_t event_wait;
|
2016-01-26 04:16:43 +07:00
|
|
|
struct list_head pending_event_list;
|
2009-09-12 01:33:34 +07:00
|
|
|
struct list_head event_list;
|
|
|
|
int event_space;
|
2011-11-25 22:21:02 +07:00
|
|
|
|
2015-11-25 21:39:03 +07:00
|
|
|
struct mutex event_read_lock;
|
|
|
|
|
2011-11-25 22:21:02 +07:00
|
|
|
struct drm_prime_file_private prime;
|
2007-07-11 12:53:27 +07:00
|
|
|
};
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Lock data.
|
|
|
|
*/
|
2007-07-11 13:53:40 +07:00
|
|
|
struct drm_lock_data {
|
2007-07-11 12:27:12 +07:00
|
|
|
struct drm_hw_lock *hw_lock; /**< Hardware lock */
|
2007-11-05 09:37:41 +07:00
|
|
|
/** Private of lock holder's file (NULL=kernel) */
|
|
|
|
struct drm_file *file_priv;
|
2005-04-17 05:20:36 +07:00
|
|
|
wait_queue_head_t lock_queue; /**< Queue of blocked processes */
|
2005-09-25 11:28:13 +07:00
|
|
|
unsigned long lock_time; /**< Time of last lock in jiffies */
|
2007-03-23 09:28:33 +07:00
|
|
|
spinlock_t spinlock;
|
|
|
|
uint32_t kernel_waiters;
|
|
|
|
uint32_t user_waiters;
|
|
|
|
int idle_has_lock;
|
2007-07-11 13:53:40 +07:00
|
|
|
};
|
2005-04-17 05:20:36 +07:00
|
|
|
|
drm/vblank: Add support for precise vblank timestamping.
The DRI2 swap & sync implementation needs precise
vblank counts and precise timestamps corresponding
to those vblank counts. For conformance to the OpenML
OML_sync_control extension specification the DRM
timestamp associated with a vblank count should
correspond to the start of video scanout of the first
scanline of the video frame following the vblank
interval for that vblank count.
Therefore we need to carry around precise timestamps
for vblanks. Currently the DRM and KMS drivers generate
timestamps ad-hoc via do_gettimeofday() in some
places. The resulting timestamps are sometimes not
very precise due to interrupt handling delays, they
don't conform to OML_sync_control and some are wrong,
as they aren't taken synchronized to the vblank.
This patch implements support inside the drm core
for precise and robust timestamping. It consists
of the following interrelated pieces.
1. Vblank timestamp caching:
A per-crtc ringbuffer stores the most recent vblank
timestamps corresponding to vblank counts.
The ringbuffer can be read out lock-free via the
accessor function:
struct timeval timestamp;
vblankcount = drm_vblank_count_and_time(dev, crtcid, ×tamp).
The function returns the current vblank count and
the corresponding timestamp for start of video
scanout following the vblank interval. It can be
used anywhere between enclosing drm_vblank_get(dev, crtcid)
and drm_vblank_put(dev,crtcid) statements. It is used
inside the drmWaitVblank ioctl and in the vblank event
queueing and handling. It should be used by kms drivers for
timestamping of bufferswap completion.
The timestamp ringbuffer is reinitialized each time
vblank irq's get reenabled in drm_vblank_get()/
drm_update_vblank_count(). It is invalidated when
vblank irq's get disabled.
The ringbuffer is updated inside drm_handle_vblank()
at each vblank irq.
2. Calculation of precise vblank timestamps:
drm_get_last_vbltimestamp() is used to compute the
timestamp for the end of the most recent vblank (if
inside active scanout), or the expected end of the
current vblank interval (if called inside a vblank
interval). The function calls into a new optional kms
driver entry point dev->driver->get_vblank_timestamp()
which is supposed to provide the precise timestamp.
If a kms driver doesn't implement the entry point or
if the call fails, a simple do_gettimeofday() timestamp
is returned as crude approximation of the true vblank time.
A new drm module parameter drm.timestamp_precision_usec
allows to disable high precision timestamps (if set to
zero) or to specify the maximum acceptable error in
the timestamps in microseconds.
Kms drivers could implement their get_vblank_timestamp()
function in a gpu specific way, as long as returned
timestamps conform to OML_sync_control, e.g., by use
of gpu specific hardware timestamps.
Optionally, kms drivers can simply wrap and use the new
utility function drm_calc_vbltimestamp_from_scanoutpos().
This function calls a new optional kms driver function
dev->driver->get_scanout_position() which returns the
current horizontal and vertical video scanout position
of the crtc. The scanout position together with the
drm_display_timing of the current video mode is used
to calculate elapsed time relative to start of active scanout
for the current video frame. This elapsed time is subtracted
from the current do_gettimeofday() time to get the timestamp
corresponding to start of video scanout. Currently
non-interlaced, non-doublescan video modes, with or
without panel scaling are handled correctly. Interlaced/
doublescan modes are tbd in a future patch.
3. Filtering of redundant vblank irq's and removal of
some race-conditions in the vblank irq enable/disable path:
Some gpu's (e.g., Radeon R500/R600) send spurious vblank
irq's outside the vblank if vblank irq's get reenabled.
These get detected by use of the vblank timestamps and
filtered out to avoid miscounting of vblanks.
Some race-conditions between the vblank irq enable/disable
functions, the vblank irq handler and the gpu itself (updating
its hardware vblank counter in the "wrong" moment) are
fixed inside vblank_disable_and_save() and
drm_update_vblank_count() by use of the vblank timestamps and
a new spinlock dev->vblank_time_lock.
The time until vblank irq disable is now configurable via
a new drm module parameter drm.vblankoffdelay to allow
experimentation with timeouts that are much shorter than
the current 5 seconds and should allow longer vblank off
periods for better power savings.
Followup patches will use these new functions to
implement precise timestamping for the intel and radeon
kms drivers.
Signed-off-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2010-10-23 09:20:23 +07:00
|
|
|
/* Flags and return codes for get_vblank_timestamp() driver function. */
|
|
|
|
#define DRM_CALLED_FROM_VBLIRQ 1
|
|
|
|
#define DRM_VBLANKTIME_SCANOUTPOS_METHOD (1 << 0)
|
2014-09-10 22:36:11 +07:00
|
|
|
#define DRM_VBLANKTIME_IN_VBLANK (1 << 1)
|
drm/vblank: Add support for precise vblank timestamping.
The DRI2 swap & sync implementation needs precise
vblank counts and precise timestamps corresponding
to those vblank counts. For conformance to the OpenML
OML_sync_control extension specification the DRM
timestamp associated with a vblank count should
correspond to the start of video scanout of the first
scanline of the video frame following the vblank
interval for that vblank count.
Therefore we need to carry around precise timestamps
for vblanks. Currently the DRM and KMS drivers generate
timestamps ad-hoc via do_gettimeofday() in some
places. The resulting timestamps are sometimes not
very precise due to interrupt handling delays, they
don't conform to OML_sync_control and some are wrong,
as they aren't taken synchronized to the vblank.
This patch implements support inside the drm core
for precise and robust timestamping. It consists
of the following interrelated pieces.
1. Vblank timestamp caching:
A per-crtc ringbuffer stores the most recent vblank
timestamps corresponding to vblank counts.
The ringbuffer can be read out lock-free via the
accessor function:
struct timeval timestamp;
vblankcount = drm_vblank_count_and_time(dev, crtcid, ×tamp).
The function returns the current vblank count and
the corresponding timestamp for start of video
scanout following the vblank interval. It can be
used anywhere between enclosing drm_vblank_get(dev, crtcid)
and drm_vblank_put(dev,crtcid) statements. It is used
inside the drmWaitVblank ioctl and in the vblank event
queueing and handling. It should be used by kms drivers for
timestamping of bufferswap completion.
The timestamp ringbuffer is reinitialized each time
vblank irq's get reenabled in drm_vblank_get()/
drm_update_vblank_count(). It is invalidated when
vblank irq's get disabled.
The ringbuffer is updated inside drm_handle_vblank()
at each vblank irq.
2. Calculation of precise vblank timestamps:
drm_get_last_vbltimestamp() is used to compute the
timestamp for the end of the most recent vblank (if
inside active scanout), or the expected end of the
current vblank interval (if called inside a vblank
interval). The function calls into a new optional kms
driver entry point dev->driver->get_vblank_timestamp()
which is supposed to provide the precise timestamp.
If a kms driver doesn't implement the entry point or
if the call fails, a simple do_gettimeofday() timestamp
is returned as crude approximation of the true vblank time.
A new drm module parameter drm.timestamp_precision_usec
allows to disable high precision timestamps (if set to
zero) or to specify the maximum acceptable error in
the timestamps in microseconds.
Kms drivers could implement their get_vblank_timestamp()
function in a gpu specific way, as long as returned
timestamps conform to OML_sync_control, e.g., by use
of gpu specific hardware timestamps.
Optionally, kms drivers can simply wrap and use the new
utility function drm_calc_vbltimestamp_from_scanoutpos().
This function calls a new optional kms driver function
dev->driver->get_scanout_position() which returns the
current horizontal and vertical video scanout position
of the crtc. The scanout position together with the
drm_display_timing of the current video mode is used
to calculate elapsed time relative to start of active scanout
for the current video frame. This elapsed time is subtracted
from the current do_gettimeofday() time to get the timestamp
corresponding to start of video scanout. Currently
non-interlaced, non-doublescan video modes, with or
without panel scaling are handled correctly. Interlaced/
doublescan modes are tbd in a future patch.
3. Filtering of redundant vblank irq's and removal of
some race-conditions in the vblank irq enable/disable path:
Some gpu's (e.g., Radeon R500/R600) send spurious vblank
irq's outside the vblank if vblank irq's get reenabled.
These get detected by use of the vblank timestamps and
filtered out to avoid miscounting of vblanks.
Some race-conditions between the vblank irq enable/disable
functions, the vblank irq handler and the gpu itself (updating
its hardware vblank counter in the "wrong" moment) are
fixed inside vblank_disable_and_save() and
drm_update_vblank_count() by use of the vblank timestamps and
a new spinlock dev->vblank_time_lock.
The time until vblank irq disable is now configurable via
a new drm module parameter drm.vblankoffdelay to allow
experimentation with timeouts that are much shorter than
the current 5 seconds and should allow longer vblank off
periods for better power savings.
Followup patches will use these new functions to
implement precise timestamping for the intel and radeon
kms drivers.
Signed-off-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2010-10-23 09:20:23 +07:00
|
|
|
|
|
|
|
/* get_scanout_position() return flags */
|
|
|
|
#define DRM_SCANOUTPOS_VALID (1 << 0)
|
2014-09-10 22:36:11 +07:00
|
|
|
#define DRM_SCANOUTPOS_IN_VBLANK (1 << 1)
|
drm/vblank: Add support for precise vblank timestamping.
The DRI2 swap & sync implementation needs precise
vblank counts and precise timestamps corresponding
to those vblank counts. For conformance to the OpenML
OML_sync_control extension specification the DRM
timestamp associated with a vblank count should
correspond to the start of video scanout of the first
scanline of the video frame following the vblank
interval for that vblank count.
Therefore we need to carry around precise timestamps
for vblanks. Currently the DRM and KMS drivers generate
timestamps ad-hoc via do_gettimeofday() in some
places. The resulting timestamps are sometimes not
very precise due to interrupt handling delays, they
don't conform to OML_sync_control and some are wrong,
as they aren't taken synchronized to the vblank.
This patch implements support inside the drm core
for precise and robust timestamping. It consists
of the following interrelated pieces.
1. Vblank timestamp caching:
A per-crtc ringbuffer stores the most recent vblank
timestamps corresponding to vblank counts.
The ringbuffer can be read out lock-free via the
accessor function:
struct timeval timestamp;
vblankcount = drm_vblank_count_and_time(dev, crtcid, ×tamp).
The function returns the current vblank count and
the corresponding timestamp for start of video
scanout following the vblank interval. It can be
used anywhere between enclosing drm_vblank_get(dev, crtcid)
and drm_vblank_put(dev,crtcid) statements. It is used
inside the drmWaitVblank ioctl and in the vblank event
queueing and handling. It should be used by kms drivers for
timestamping of bufferswap completion.
The timestamp ringbuffer is reinitialized each time
vblank irq's get reenabled in drm_vblank_get()/
drm_update_vblank_count(). It is invalidated when
vblank irq's get disabled.
The ringbuffer is updated inside drm_handle_vblank()
at each vblank irq.
2. Calculation of precise vblank timestamps:
drm_get_last_vbltimestamp() is used to compute the
timestamp for the end of the most recent vblank (if
inside active scanout), or the expected end of the
current vblank interval (if called inside a vblank
interval). The function calls into a new optional kms
driver entry point dev->driver->get_vblank_timestamp()
which is supposed to provide the precise timestamp.
If a kms driver doesn't implement the entry point or
if the call fails, a simple do_gettimeofday() timestamp
is returned as crude approximation of the true vblank time.
A new drm module parameter drm.timestamp_precision_usec
allows to disable high precision timestamps (if set to
zero) or to specify the maximum acceptable error in
the timestamps in microseconds.
Kms drivers could implement their get_vblank_timestamp()
function in a gpu specific way, as long as returned
timestamps conform to OML_sync_control, e.g., by use
of gpu specific hardware timestamps.
Optionally, kms drivers can simply wrap and use the new
utility function drm_calc_vbltimestamp_from_scanoutpos().
This function calls a new optional kms driver function
dev->driver->get_scanout_position() which returns the
current horizontal and vertical video scanout position
of the crtc. The scanout position together with the
drm_display_timing of the current video mode is used
to calculate elapsed time relative to start of active scanout
for the current video frame. This elapsed time is subtracted
from the current do_gettimeofday() time to get the timestamp
corresponding to start of video scanout. Currently
non-interlaced, non-doublescan video modes, with or
without panel scaling are handled correctly. Interlaced/
doublescan modes are tbd in a future patch.
3. Filtering of redundant vblank irq's and removal of
some race-conditions in the vblank irq enable/disable path:
Some gpu's (e.g., Radeon R500/R600) send spurious vblank
irq's outside the vblank if vblank irq's get reenabled.
These get detected by use of the vblank timestamps and
filtered out to avoid miscounting of vblanks.
Some race-conditions between the vblank irq enable/disable
functions, the vblank irq handler and the gpu itself (updating
its hardware vblank counter in the "wrong" moment) are
fixed inside vblank_disable_and_save() and
drm_update_vblank_count() by use of the vblank timestamps and
a new spinlock dev->vblank_time_lock.
The time until vblank irq disable is now configurable via
a new drm module parameter drm.vblankoffdelay to allow
experimentation with timeouts that are much shorter than
the current 5 seconds and should allow longer vblank off
periods for better power savings.
Followup patches will use these new functions to
implement precise timestamping for the intel and radeon
kms drivers.
Signed-off-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2010-10-23 09:20:23 +07:00
|
|
|
#define DRM_SCANOUTPOS_ACCURATE (1 << 2)
|
|
|
|
|
2005-04-17 05:20:36 +07:00
|
|
|
/**
|
|
|
|
* DRM driver structure. This structure represent the common code for
|
|
|
|
* a family of cards. There will one drm_device for each card present
|
|
|
|
* in this family
|
|
|
|
*/
|
|
|
|
struct drm_driver {
|
2005-11-10 18:16:34 +07:00
|
|
|
int (*load) (struct drm_device *, unsigned long flags);
|
|
|
|
int (*firstopen) (struct drm_device *);
|
2007-07-11 12:53:27 +07:00
|
|
|
int (*open) (struct drm_device *, struct drm_file *);
|
2007-08-25 17:23:09 +07:00
|
|
|
void (*preclose) (struct drm_device *, struct drm_file *file_priv);
|
2007-07-11 12:53:27 +07:00
|
|
|
void (*postclose) (struct drm_device *, struct drm_file *);
|
2005-11-10 18:16:34 +07:00
|
|
|
void (*lastclose) (struct drm_device *);
|
|
|
|
int (*unload) (struct drm_device *);
|
2007-09-03 09:06:45 +07:00
|
|
|
int (*dma_ioctl) (struct drm_device *dev, void *data, struct drm_file *file_priv);
|
2005-09-25 11:28:13 +07:00
|
|
|
int (*dma_quiescent) (struct drm_device *);
|
2007-07-11 12:53:27 +07:00
|
|
|
int (*context_dtor) (struct drm_device *dev, int context);
|
2014-08-29 17:12:43 +07:00
|
|
|
int (*set_busid)(struct drm_device *dev, struct drm_master *master);
|
2005-09-25 11:28:13 +07:00
|
|
|
|
2008-10-01 02:14:26 +07:00
|
|
|
/**
|
|
|
|
* get_vblank_counter - get raw hardware vblank counter
|
|
|
|
* @dev: DRM device
|
2015-09-24 23:35:31 +07:00
|
|
|
* @pipe: counter to fetch
|
2008-10-01 02:14:26 +07:00
|
|
|
*
|
2012-05-17 18:27:20 +07:00
|
|
|
* Driver callback for fetching a raw hardware vblank counter for @crtc.
|
|
|
|
* If a device doesn't have a hardware counter, the driver can simply
|
2016-06-01 22:35:42 +07:00
|
|
|
* use drm_vblank_no_hw_counter() function. The DRM core will account for
|
2012-05-17 18:27:20 +07:00
|
|
|
* missed vblank events while interrupts where disabled based on system
|
|
|
|
* timestamps.
|
2008-10-01 02:14:26 +07:00
|
|
|
*
|
|
|
|
* Wraparound handling and loss of events due to modesetting is dealt
|
|
|
|
* with in the DRM core code.
|
|
|
|
*
|
|
|
|
* RETURNS
|
|
|
|
* Raw vblank counter value.
|
|
|
|
*/
|
2015-09-24 23:35:31 +07:00
|
|
|
u32 (*get_vblank_counter) (struct drm_device *dev, unsigned int pipe);
|
2008-10-01 02:14:26 +07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* enable_vblank - enable vblank interrupt events
|
|
|
|
* @dev: DRM device
|
2015-09-24 23:35:31 +07:00
|
|
|
* @pipe: which irq to enable
|
2008-10-01 02:14:26 +07:00
|
|
|
*
|
|
|
|
* Enable vblank interrupts for @crtc. If the device doesn't have
|
2016-06-01 22:35:42 +07:00
|
|
|
* a hardware vblank counter, the driver should use the
|
|
|
|
* drm_vblank_no_hw_counter() function that keeps a virtual counter.
|
2008-10-01 02:14:26 +07:00
|
|
|
*
|
|
|
|
* RETURNS
|
|
|
|
* Zero on success, appropriate errno if the given @crtc's vblank
|
|
|
|
* interrupt cannot be enabled.
|
|
|
|
*/
|
2015-09-24 23:35:31 +07:00
|
|
|
int (*enable_vblank) (struct drm_device *dev, unsigned int pipe);
|
2008-10-01 02:14:26 +07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* disable_vblank - disable vblank interrupt events
|
|
|
|
* @dev: DRM device
|
2015-09-24 23:35:31 +07:00
|
|
|
* @pipe: which irq to enable
|
2008-10-01 02:14:26 +07:00
|
|
|
*
|
|
|
|
* Disable vblank interrupts for @crtc. If the device doesn't have
|
2016-06-01 22:35:42 +07:00
|
|
|
* a hardware vblank counter, the driver should use the
|
|
|
|
* drm_vblank_no_hw_counter() function that keeps a virtual counter.
|
2008-10-01 02:14:26 +07:00
|
|
|
*/
|
2015-09-24 23:35:31 +07:00
|
|
|
void (*disable_vblank) (struct drm_device *dev, unsigned int pipe);
|
2008-10-01 02:14:26 +07:00
|
|
|
|
2005-07-10 14:31:26 +07:00
|
|
|
/**
|
|
|
|
* Called by \c drm_device_is_agp. Typically used to determine if a
|
|
|
|
* card is really attached to AGP or not.
|
|
|
|
*
|
|
|
|
* \param dev DRM device handle
|
|
|
|
*
|
|
|
|
* \returns
|
|
|
|
* One of three values is returned depending on whether or not the
|
|
|
|
* card is absolutely \b not AGP (return of 0), absolutely \b is AGP
|
|
|
|
* (return of 1), or may or may not be AGP (return of 2).
|
|
|
|
*/
|
2007-07-11 12:53:27 +07:00
|
|
|
int (*device_is_agp) (struct drm_device *dev);
|
2005-07-10 14:31:26 +07:00
|
|
|
|
drm/vblank: Add support for precise vblank timestamping.
The DRI2 swap & sync implementation needs precise
vblank counts and precise timestamps corresponding
to those vblank counts. For conformance to the OpenML
OML_sync_control extension specification the DRM
timestamp associated with a vblank count should
correspond to the start of video scanout of the first
scanline of the video frame following the vblank
interval for that vblank count.
Therefore we need to carry around precise timestamps
for vblanks. Currently the DRM and KMS drivers generate
timestamps ad-hoc via do_gettimeofday() in some
places. The resulting timestamps are sometimes not
very precise due to interrupt handling delays, they
don't conform to OML_sync_control and some are wrong,
as they aren't taken synchronized to the vblank.
This patch implements support inside the drm core
for precise and robust timestamping. It consists
of the following interrelated pieces.
1. Vblank timestamp caching:
A per-crtc ringbuffer stores the most recent vblank
timestamps corresponding to vblank counts.
The ringbuffer can be read out lock-free via the
accessor function:
struct timeval timestamp;
vblankcount = drm_vblank_count_and_time(dev, crtcid, ×tamp).
The function returns the current vblank count and
the corresponding timestamp for start of video
scanout following the vblank interval. It can be
used anywhere between enclosing drm_vblank_get(dev, crtcid)
and drm_vblank_put(dev,crtcid) statements. It is used
inside the drmWaitVblank ioctl and in the vblank event
queueing and handling. It should be used by kms drivers for
timestamping of bufferswap completion.
The timestamp ringbuffer is reinitialized each time
vblank irq's get reenabled in drm_vblank_get()/
drm_update_vblank_count(). It is invalidated when
vblank irq's get disabled.
The ringbuffer is updated inside drm_handle_vblank()
at each vblank irq.
2. Calculation of precise vblank timestamps:
drm_get_last_vbltimestamp() is used to compute the
timestamp for the end of the most recent vblank (if
inside active scanout), or the expected end of the
current vblank interval (if called inside a vblank
interval). The function calls into a new optional kms
driver entry point dev->driver->get_vblank_timestamp()
which is supposed to provide the precise timestamp.
If a kms driver doesn't implement the entry point or
if the call fails, a simple do_gettimeofday() timestamp
is returned as crude approximation of the true vblank time.
A new drm module parameter drm.timestamp_precision_usec
allows to disable high precision timestamps (if set to
zero) or to specify the maximum acceptable error in
the timestamps in microseconds.
Kms drivers could implement their get_vblank_timestamp()
function in a gpu specific way, as long as returned
timestamps conform to OML_sync_control, e.g., by use
of gpu specific hardware timestamps.
Optionally, kms drivers can simply wrap and use the new
utility function drm_calc_vbltimestamp_from_scanoutpos().
This function calls a new optional kms driver function
dev->driver->get_scanout_position() which returns the
current horizontal and vertical video scanout position
of the crtc. The scanout position together with the
drm_display_timing of the current video mode is used
to calculate elapsed time relative to start of active scanout
for the current video frame. This elapsed time is subtracted
from the current do_gettimeofday() time to get the timestamp
corresponding to start of video scanout. Currently
non-interlaced, non-doublescan video modes, with or
without panel scaling are handled correctly. Interlaced/
doublescan modes are tbd in a future patch.
3. Filtering of redundant vblank irq's and removal of
some race-conditions in the vblank irq enable/disable path:
Some gpu's (e.g., Radeon R500/R600) send spurious vblank
irq's outside the vblank if vblank irq's get reenabled.
These get detected by use of the vblank timestamps and
filtered out to avoid miscounting of vblanks.
Some race-conditions between the vblank irq enable/disable
functions, the vblank irq handler and the gpu itself (updating
its hardware vblank counter in the "wrong" moment) are
fixed inside vblank_disable_and_save() and
drm_update_vblank_count() by use of the vblank timestamps and
a new spinlock dev->vblank_time_lock.
The time until vblank irq disable is now configurable via
a new drm module parameter drm.vblankoffdelay to allow
experimentation with timeouts that are much shorter than
the current 5 seconds and should allow longer vblank off
periods for better power savings.
Followup patches will use these new functions to
implement precise timestamping for the intel and radeon
kms drivers.
Signed-off-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2010-10-23 09:20:23 +07:00
|
|
|
/**
|
|
|
|
* Called by vblank timestamping code.
|
|
|
|
*
|
2013-10-30 11:13:06 +07:00
|
|
|
* Return the current display scanout position from a crtc, and an
|
|
|
|
* optional accurate ktime_get timestamp of when position was measured.
|
drm/vblank: Add support for precise vblank timestamping.
The DRI2 swap & sync implementation needs precise
vblank counts and precise timestamps corresponding
to those vblank counts. For conformance to the OpenML
OML_sync_control extension specification the DRM
timestamp associated with a vblank count should
correspond to the start of video scanout of the first
scanline of the video frame following the vblank
interval for that vblank count.
Therefore we need to carry around precise timestamps
for vblanks. Currently the DRM and KMS drivers generate
timestamps ad-hoc via do_gettimeofday() in some
places. The resulting timestamps are sometimes not
very precise due to interrupt handling delays, they
don't conform to OML_sync_control and some are wrong,
as they aren't taken synchronized to the vblank.
This patch implements support inside the drm core
for precise and robust timestamping. It consists
of the following interrelated pieces.
1. Vblank timestamp caching:
A per-crtc ringbuffer stores the most recent vblank
timestamps corresponding to vblank counts.
The ringbuffer can be read out lock-free via the
accessor function:
struct timeval timestamp;
vblankcount = drm_vblank_count_and_time(dev, crtcid, ×tamp).
The function returns the current vblank count and
the corresponding timestamp for start of video
scanout following the vblank interval. It can be
used anywhere between enclosing drm_vblank_get(dev, crtcid)
and drm_vblank_put(dev,crtcid) statements. It is used
inside the drmWaitVblank ioctl and in the vblank event
queueing and handling. It should be used by kms drivers for
timestamping of bufferswap completion.
The timestamp ringbuffer is reinitialized each time
vblank irq's get reenabled in drm_vblank_get()/
drm_update_vblank_count(). It is invalidated when
vblank irq's get disabled.
The ringbuffer is updated inside drm_handle_vblank()
at each vblank irq.
2. Calculation of precise vblank timestamps:
drm_get_last_vbltimestamp() is used to compute the
timestamp for the end of the most recent vblank (if
inside active scanout), or the expected end of the
current vblank interval (if called inside a vblank
interval). The function calls into a new optional kms
driver entry point dev->driver->get_vblank_timestamp()
which is supposed to provide the precise timestamp.
If a kms driver doesn't implement the entry point or
if the call fails, a simple do_gettimeofday() timestamp
is returned as crude approximation of the true vblank time.
A new drm module parameter drm.timestamp_precision_usec
allows to disable high precision timestamps (if set to
zero) or to specify the maximum acceptable error in
the timestamps in microseconds.
Kms drivers could implement their get_vblank_timestamp()
function in a gpu specific way, as long as returned
timestamps conform to OML_sync_control, e.g., by use
of gpu specific hardware timestamps.
Optionally, kms drivers can simply wrap and use the new
utility function drm_calc_vbltimestamp_from_scanoutpos().
This function calls a new optional kms driver function
dev->driver->get_scanout_position() which returns the
current horizontal and vertical video scanout position
of the crtc. The scanout position together with the
drm_display_timing of the current video mode is used
to calculate elapsed time relative to start of active scanout
for the current video frame. This elapsed time is subtracted
from the current do_gettimeofday() time to get the timestamp
corresponding to start of video scanout. Currently
non-interlaced, non-doublescan video modes, with or
without panel scaling are handled correctly. Interlaced/
doublescan modes are tbd in a future patch.
3. Filtering of redundant vblank irq's and removal of
some race-conditions in the vblank irq enable/disable path:
Some gpu's (e.g., Radeon R500/R600) send spurious vblank
irq's outside the vblank if vblank irq's get reenabled.
These get detected by use of the vblank timestamps and
filtered out to avoid miscounting of vblanks.
Some race-conditions between the vblank irq enable/disable
functions, the vblank irq handler and the gpu itself (updating
its hardware vblank counter in the "wrong" moment) are
fixed inside vblank_disable_and_save() and
drm_update_vblank_count() by use of the vblank timestamps and
a new spinlock dev->vblank_time_lock.
The time until vblank irq disable is now configurable via
a new drm module parameter drm.vblankoffdelay to allow
experimentation with timeouts that are much shorter than
the current 5 seconds and should allow longer vblank off
periods for better power savings.
Followup patches will use these new functions to
implement precise timestamping for the intel and radeon
kms drivers.
Signed-off-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2010-10-23 09:20:23 +07:00
|
|
|
*
|
|
|
|
* \param dev DRM device.
|
2015-09-24 23:35:31 +07:00
|
|
|
* \param pipe Id of the crtc to query.
|
2013-10-29 01:50:48 +07:00
|
|
|
* \param flags Flags from the caller (DRM_CALLED_FROM_VBLIRQ or 0).
|
drm/vblank: Add support for precise vblank timestamping.
The DRI2 swap & sync implementation needs precise
vblank counts and precise timestamps corresponding
to those vblank counts. For conformance to the OpenML
OML_sync_control extension specification the DRM
timestamp associated with a vblank count should
correspond to the start of video scanout of the first
scanline of the video frame following the vblank
interval for that vblank count.
Therefore we need to carry around precise timestamps
for vblanks. Currently the DRM and KMS drivers generate
timestamps ad-hoc via do_gettimeofday() in some
places. The resulting timestamps are sometimes not
very precise due to interrupt handling delays, they
don't conform to OML_sync_control and some are wrong,
as they aren't taken synchronized to the vblank.
This patch implements support inside the drm core
for precise and robust timestamping. It consists
of the following interrelated pieces.
1. Vblank timestamp caching:
A per-crtc ringbuffer stores the most recent vblank
timestamps corresponding to vblank counts.
The ringbuffer can be read out lock-free via the
accessor function:
struct timeval timestamp;
vblankcount = drm_vblank_count_and_time(dev, crtcid, ×tamp).
The function returns the current vblank count and
the corresponding timestamp for start of video
scanout following the vblank interval. It can be
used anywhere between enclosing drm_vblank_get(dev, crtcid)
and drm_vblank_put(dev,crtcid) statements. It is used
inside the drmWaitVblank ioctl and in the vblank event
queueing and handling. It should be used by kms drivers for
timestamping of bufferswap completion.
The timestamp ringbuffer is reinitialized each time
vblank irq's get reenabled in drm_vblank_get()/
drm_update_vblank_count(). It is invalidated when
vblank irq's get disabled.
The ringbuffer is updated inside drm_handle_vblank()
at each vblank irq.
2. Calculation of precise vblank timestamps:
drm_get_last_vbltimestamp() is used to compute the
timestamp for the end of the most recent vblank (if
inside active scanout), or the expected end of the
current vblank interval (if called inside a vblank
interval). The function calls into a new optional kms
driver entry point dev->driver->get_vblank_timestamp()
which is supposed to provide the precise timestamp.
If a kms driver doesn't implement the entry point or
if the call fails, a simple do_gettimeofday() timestamp
is returned as crude approximation of the true vblank time.
A new drm module parameter drm.timestamp_precision_usec
allows to disable high precision timestamps (if set to
zero) or to specify the maximum acceptable error in
the timestamps in microseconds.
Kms drivers could implement their get_vblank_timestamp()
function in a gpu specific way, as long as returned
timestamps conform to OML_sync_control, e.g., by use
of gpu specific hardware timestamps.
Optionally, kms drivers can simply wrap and use the new
utility function drm_calc_vbltimestamp_from_scanoutpos().
This function calls a new optional kms driver function
dev->driver->get_scanout_position() which returns the
current horizontal and vertical video scanout position
of the crtc. The scanout position together with the
drm_display_timing of the current video mode is used
to calculate elapsed time relative to start of active scanout
for the current video frame. This elapsed time is subtracted
from the current do_gettimeofday() time to get the timestamp
corresponding to start of video scanout. Currently
non-interlaced, non-doublescan video modes, with or
without panel scaling are handled correctly. Interlaced/
doublescan modes are tbd in a future patch.
3. Filtering of redundant vblank irq's and removal of
some race-conditions in the vblank irq enable/disable path:
Some gpu's (e.g., Radeon R500/R600) send spurious vblank
irq's outside the vblank if vblank irq's get reenabled.
These get detected by use of the vblank timestamps and
filtered out to avoid miscounting of vblanks.
Some race-conditions between the vblank irq enable/disable
functions, the vblank irq handler and the gpu itself (updating
its hardware vblank counter in the "wrong" moment) are
fixed inside vblank_disable_and_save() and
drm_update_vblank_count() by use of the vblank timestamps and
a new spinlock dev->vblank_time_lock.
The time until vblank irq disable is now configurable via
a new drm module parameter drm.vblankoffdelay to allow
experimentation with timeouts that are much shorter than
the current 5 seconds and should allow longer vblank off
periods for better power savings.
Followup patches will use these new functions to
implement precise timestamping for the intel and radeon
kms drivers.
Signed-off-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2010-10-23 09:20:23 +07:00
|
|
|
* \param *vpos Target location for current vertical scanout position.
|
|
|
|
* \param *hpos Target location for current horizontal scanout position.
|
2013-10-30 11:13:06 +07:00
|
|
|
* \param *stime Target location for timestamp taken immediately before
|
|
|
|
* scanout position query. Can be NULL to skip timestamp.
|
|
|
|
* \param *etime Target location for timestamp taken immediately after
|
|
|
|
* scanout position query. Can be NULL to skip timestamp.
|
2015-09-15 02:43:44 +07:00
|
|
|
* \param mode Current display timings.
|
drm/vblank: Add support for precise vblank timestamping.
The DRI2 swap & sync implementation needs precise
vblank counts and precise timestamps corresponding
to those vblank counts. For conformance to the OpenML
OML_sync_control extension specification the DRM
timestamp associated with a vblank count should
correspond to the start of video scanout of the first
scanline of the video frame following the vblank
interval for that vblank count.
Therefore we need to carry around precise timestamps
for vblanks. Currently the DRM and KMS drivers generate
timestamps ad-hoc via do_gettimeofday() in some
places. The resulting timestamps are sometimes not
very precise due to interrupt handling delays, they
don't conform to OML_sync_control and some are wrong,
as they aren't taken synchronized to the vblank.
This patch implements support inside the drm core
for precise and robust timestamping. It consists
of the following interrelated pieces.
1. Vblank timestamp caching:
A per-crtc ringbuffer stores the most recent vblank
timestamps corresponding to vblank counts.
The ringbuffer can be read out lock-free via the
accessor function:
struct timeval timestamp;
vblankcount = drm_vblank_count_and_time(dev, crtcid, ×tamp).
The function returns the current vblank count and
the corresponding timestamp for start of video
scanout following the vblank interval. It can be
used anywhere between enclosing drm_vblank_get(dev, crtcid)
and drm_vblank_put(dev,crtcid) statements. It is used
inside the drmWaitVblank ioctl and in the vblank event
queueing and handling. It should be used by kms drivers for
timestamping of bufferswap completion.
The timestamp ringbuffer is reinitialized each time
vblank irq's get reenabled in drm_vblank_get()/
drm_update_vblank_count(). It is invalidated when
vblank irq's get disabled.
The ringbuffer is updated inside drm_handle_vblank()
at each vblank irq.
2. Calculation of precise vblank timestamps:
drm_get_last_vbltimestamp() is used to compute the
timestamp for the end of the most recent vblank (if
inside active scanout), or the expected end of the
current vblank interval (if called inside a vblank
interval). The function calls into a new optional kms
driver entry point dev->driver->get_vblank_timestamp()
which is supposed to provide the precise timestamp.
If a kms driver doesn't implement the entry point or
if the call fails, a simple do_gettimeofday() timestamp
is returned as crude approximation of the true vblank time.
A new drm module parameter drm.timestamp_precision_usec
allows to disable high precision timestamps (if set to
zero) or to specify the maximum acceptable error in
the timestamps in microseconds.
Kms drivers could implement their get_vblank_timestamp()
function in a gpu specific way, as long as returned
timestamps conform to OML_sync_control, e.g., by use
of gpu specific hardware timestamps.
Optionally, kms drivers can simply wrap and use the new
utility function drm_calc_vbltimestamp_from_scanoutpos().
This function calls a new optional kms driver function
dev->driver->get_scanout_position() which returns the
current horizontal and vertical video scanout position
of the crtc. The scanout position together with the
drm_display_timing of the current video mode is used
to calculate elapsed time relative to start of active scanout
for the current video frame. This elapsed time is subtracted
from the current do_gettimeofday() time to get the timestamp
corresponding to start of video scanout. Currently
non-interlaced, non-doublescan video modes, with or
without panel scaling are handled correctly. Interlaced/
doublescan modes are tbd in a future patch.
3. Filtering of redundant vblank irq's and removal of
some race-conditions in the vblank irq enable/disable path:
Some gpu's (e.g., Radeon R500/R600) send spurious vblank
irq's outside the vblank if vblank irq's get reenabled.
These get detected by use of the vblank timestamps and
filtered out to avoid miscounting of vblanks.
Some race-conditions between the vblank irq enable/disable
functions, the vblank irq handler and the gpu itself (updating
its hardware vblank counter in the "wrong" moment) are
fixed inside vblank_disable_and_save() and
drm_update_vblank_count() by use of the vblank timestamps and
a new spinlock dev->vblank_time_lock.
The time until vblank irq disable is now configurable via
a new drm module parameter drm.vblankoffdelay to allow
experimentation with timeouts that are much shorter than
the current 5 seconds and should allow longer vblank off
periods for better power savings.
Followup patches will use these new functions to
implement precise timestamping for the intel and radeon
kms drivers.
Signed-off-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2010-10-23 09:20:23 +07:00
|
|
|
*
|
|
|
|
* Returns vpos as a positive number while in active scanout area.
|
|
|
|
* Returns vpos as a negative number inside vblank, counting the number
|
|
|
|
* of scanlines to go until end of vblank, e.g., -1 means "one scanline
|
|
|
|
* until start of active scanout / end of vblank."
|
|
|
|
*
|
|
|
|
* \return Flags, or'ed together as follows:
|
|
|
|
*
|
2011-03-31 08:57:33 +07:00
|
|
|
* DRM_SCANOUTPOS_VALID = Query successful.
|
drm/vblank: Add support for precise vblank timestamping.
The DRI2 swap & sync implementation needs precise
vblank counts and precise timestamps corresponding
to those vblank counts. For conformance to the OpenML
OML_sync_control extension specification the DRM
timestamp associated with a vblank count should
correspond to the start of video scanout of the first
scanline of the video frame following the vblank
interval for that vblank count.
Therefore we need to carry around precise timestamps
for vblanks. Currently the DRM and KMS drivers generate
timestamps ad-hoc via do_gettimeofday() in some
places. The resulting timestamps are sometimes not
very precise due to interrupt handling delays, they
don't conform to OML_sync_control and some are wrong,
as they aren't taken synchronized to the vblank.
This patch implements support inside the drm core
for precise and robust timestamping. It consists
of the following interrelated pieces.
1. Vblank timestamp caching:
A per-crtc ringbuffer stores the most recent vblank
timestamps corresponding to vblank counts.
The ringbuffer can be read out lock-free via the
accessor function:
struct timeval timestamp;
vblankcount = drm_vblank_count_and_time(dev, crtcid, ×tamp).
The function returns the current vblank count and
the corresponding timestamp for start of video
scanout following the vblank interval. It can be
used anywhere between enclosing drm_vblank_get(dev, crtcid)
and drm_vblank_put(dev,crtcid) statements. It is used
inside the drmWaitVblank ioctl and in the vblank event
queueing and handling. It should be used by kms drivers for
timestamping of bufferswap completion.
The timestamp ringbuffer is reinitialized each time
vblank irq's get reenabled in drm_vblank_get()/
drm_update_vblank_count(). It is invalidated when
vblank irq's get disabled.
The ringbuffer is updated inside drm_handle_vblank()
at each vblank irq.
2. Calculation of precise vblank timestamps:
drm_get_last_vbltimestamp() is used to compute the
timestamp for the end of the most recent vblank (if
inside active scanout), or the expected end of the
current vblank interval (if called inside a vblank
interval). The function calls into a new optional kms
driver entry point dev->driver->get_vblank_timestamp()
which is supposed to provide the precise timestamp.
If a kms driver doesn't implement the entry point or
if the call fails, a simple do_gettimeofday() timestamp
is returned as crude approximation of the true vblank time.
A new drm module parameter drm.timestamp_precision_usec
allows to disable high precision timestamps (if set to
zero) or to specify the maximum acceptable error in
the timestamps in microseconds.
Kms drivers could implement their get_vblank_timestamp()
function in a gpu specific way, as long as returned
timestamps conform to OML_sync_control, e.g., by use
of gpu specific hardware timestamps.
Optionally, kms drivers can simply wrap and use the new
utility function drm_calc_vbltimestamp_from_scanoutpos().
This function calls a new optional kms driver function
dev->driver->get_scanout_position() which returns the
current horizontal and vertical video scanout position
of the crtc. The scanout position together with the
drm_display_timing of the current video mode is used
to calculate elapsed time relative to start of active scanout
for the current video frame. This elapsed time is subtracted
from the current do_gettimeofday() time to get the timestamp
corresponding to start of video scanout. Currently
non-interlaced, non-doublescan video modes, with or
without panel scaling are handled correctly. Interlaced/
doublescan modes are tbd in a future patch.
3. Filtering of redundant vblank irq's and removal of
some race-conditions in the vblank irq enable/disable path:
Some gpu's (e.g., Radeon R500/R600) send spurious vblank
irq's outside the vblank if vblank irq's get reenabled.
These get detected by use of the vblank timestamps and
filtered out to avoid miscounting of vblanks.
Some race-conditions between the vblank irq enable/disable
functions, the vblank irq handler and the gpu itself (updating
its hardware vblank counter in the "wrong" moment) are
fixed inside vblank_disable_and_save() and
drm_update_vblank_count() by use of the vblank timestamps and
a new spinlock dev->vblank_time_lock.
The time until vblank irq disable is now configurable via
a new drm module parameter drm.vblankoffdelay to allow
experimentation with timeouts that are much shorter than
the current 5 seconds and should allow longer vblank off
periods for better power savings.
Followup patches will use these new functions to
implement precise timestamping for the intel and radeon
kms drivers.
Signed-off-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2010-10-23 09:20:23 +07:00
|
|
|
* DRM_SCANOUTPOS_INVBL = Inside vblank.
|
|
|
|
* DRM_SCANOUTPOS_ACCURATE = Returned position is accurate. A lack of
|
|
|
|
* this flag means that returned position may be offset by a constant
|
|
|
|
* but unknown small number of scanlines wrt. real scanout position.
|
|
|
|
*
|
|
|
|
*/
|
2015-09-24 23:35:31 +07:00
|
|
|
int (*get_scanout_position) (struct drm_device *dev, unsigned int pipe,
|
|
|
|
unsigned int flags, int *vpos, int *hpos,
|
2015-09-15 02:43:44 +07:00
|
|
|
ktime_t *stime, ktime_t *etime,
|
|
|
|
const struct drm_display_mode *mode);
|
drm/vblank: Add support for precise vblank timestamping.
The DRI2 swap & sync implementation needs precise
vblank counts and precise timestamps corresponding
to those vblank counts. For conformance to the OpenML
OML_sync_control extension specification the DRM
timestamp associated with a vblank count should
correspond to the start of video scanout of the first
scanline of the video frame following the vblank
interval for that vblank count.
Therefore we need to carry around precise timestamps
for vblanks. Currently the DRM and KMS drivers generate
timestamps ad-hoc via do_gettimeofday() in some
places. The resulting timestamps are sometimes not
very precise due to interrupt handling delays, they
don't conform to OML_sync_control and some are wrong,
as they aren't taken synchronized to the vblank.
This patch implements support inside the drm core
for precise and robust timestamping. It consists
of the following interrelated pieces.
1. Vblank timestamp caching:
A per-crtc ringbuffer stores the most recent vblank
timestamps corresponding to vblank counts.
The ringbuffer can be read out lock-free via the
accessor function:
struct timeval timestamp;
vblankcount = drm_vblank_count_and_time(dev, crtcid, ×tamp).
The function returns the current vblank count and
the corresponding timestamp for start of video
scanout following the vblank interval. It can be
used anywhere between enclosing drm_vblank_get(dev, crtcid)
and drm_vblank_put(dev,crtcid) statements. It is used
inside the drmWaitVblank ioctl and in the vblank event
queueing and handling. It should be used by kms drivers for
timestamping of bufferswap completion.
The timestamp ringbuffer is reinitialized each time
vblank irq's get reenabled in drm_vblank_get()/
drm_update_vblank_count(). It is invalidated when
vblank irq's get disabled.
The ringbuffer is updated inside drm_handle_vblank()
at each vblank irq.
2. Calculation of precise vblank timestamps:
drm_get_last_vbltimestamp() is used to compute the
timestamp for the end of the most recent vblank (if
inside active scanout), or the expected end of the
current vblank interval (if called inside a vblank
interval). The function calls into a new optional kms
driver entry point dev->driver->get_vblank_timestamp()
which is supposed to provide the precise timestamp.
If a kms driver doesn't implement the entry point or
if the call fails, a simple do_gettimeofday() timestamp
is returned as crude approximation of the true vblank time.
A new drm module parameter drm.timestamp_precision_usec
allows to disable high precision timestamps (if set to
zero) or to specify the maximum acceptable error in
the timestamps in microseconds.
Kms drivers could implement their get_vblank_timestamp()
function in a gpu specific way, as long as returned
timestamps conform to OML_sync_control, e.g., by use
of gpu specific hardware timestamps.
Optionally, kms drivers can simply wrap and use the new
utility function drm_calc_vbltimestamp_from_scanoutpos().
This function calls a new optional kms driver function
dev->driver->get_scanout_position() which returns the
current horizontal and vertical video scanout position
of the crtc. The scanout position together with the
drm_display_timing of the current video mode is used
to calculate elapsed time relative to start of active scanout
for the current video frame. This elapsed time is subtracted
from the current do_gettimeofday() time to get the timestamp
corresponding to start of video scanout. Currently
non-interlaced, non-doublescan video modes, with or
without panel scaling are handled correctly. Interlaced/
doublescan modes are tbd in a future patch.
3. Filtering of redundant vblank irq's and removal of
some race-conditions in the vblank irq enable/disable path:
Some gpu's (e.g., Radeon R500/R600) send spurious vblank
irq's outside the vblank if vblank irq's get reenabled.
These get detected by use of the vblank timestamps and
filtered out to avoid miscounting of vblanks.
Some race-conditions between the vblank irq enable/disable
functions, the vblank irq handler and the gpu itself (updating
its hardware vblank counter in the "wrong" moment) are
fixed inside vblank_disable_and_save() and
drm_update_vblank_count() by use of the vblank timestamps and
a new spinlock dev->vblank_time_lock.
The time until vblank irq disable is now configurable via
a new drm module parameter drm.vblankoffdelay to allow
experimentation with timeouts that are much shorter than
the current 5 seconds and should allow longer vblank off
periods for better power savings.
Followup patches will use these new functions to
implement precise timestamping for the intel and radeon
kms drivers.
Signed-off-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2010-10-23 09:20:23 +07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Called by \c drm_get_last_vbltimestamp. Should return a precise
|
|
|
|
* timestamp when the most recent VBLANK interval ended or will end.
|
|
|
|
*
|
|
|
|
* Specifically, the timestamp in @vblank_time should correspond as
|
|
|
|
* closely as possible to the time when the first video scanline of
|
|
|
|
* the video frame after the end of VBLANK will start scanning out,
|
2011-11-29 11:31:00 +07:00
|
|
|
* the time immediately after end of the VBLANK interval. If the
|
drm/vblank: Add support for precise vblank timestamping.
The DRI2 swap & sync implementation needs precise
vblank counts and precise timestamps corresponding
to those vblank counts. For conformance to the OpenML
OML_sync_control extension specification the DRM
timestamp associated with a vblank count should
correspond to the start of video scanout of the first
scanline of the video frame following the vblank
interval for that vblank count.
Therefore we need to carry around precise timestamps
for vblanks. Currently the DRM and KMS drivers generate
timestamps ad-hoc via do_gettimeofday() in some
places. The resulting timestamps are sometimes not
very precise due to interrupt handling delays, they
don't conform to OML_sync_control and some are wrong,
as they aren't taken synchronized to the vblank.
This patch implements support inside the drm core
for precise and robust timestamping. It consists
of the following interrelated pieces.
1. Vblank timestamp caching:
A per-crtc ringbuffer stores the most recent vblank
timestamps corresponding to vblank counts.
The ringbuffer can be read out lock-free via the
accessor function:
struct timeval timestamp;
vblankcount = drm_vblank_count_and_time(dev, crtcid, ×tamp).
The function returns the current vblank count and
the corresponding timestamp for start of video
scanout following the vblank interval. It can be
used anywhere between enclosing drm_vblank_get(dev, crtcid)
and drm_vblank_put(dev,crtcid) statements. It is used
inside the drmWaitVblank ioctl and in the vblank event
queueing and handling. It should be used by kms drivers for
timestamping of bufferswap completion.
The timestamp ringbuffer is reinitialized each time
vblank irq's get reenabled in drm_vblank_get()/
drm_update_vblank_count(). It is invalidated when
vblank irq's get disabled.
The ringbuffer is updated inside drm_handle_vblank()
at each vblank irq.
2. Calculation of precise vblank timestamps:
drm_get_last_vbltimestamp() is used to compute the
timestamp for the end of the most recent vblank (if
inside active scanout), or the expected end of the
current vblank interval (if called inside a vblank
interval). The function calls into a new optional kms
driver entry point dev->driver->get_vblank_timestamp()
which is supposed to provide the precise timestamp.
If a kms driver doesn't implement the entry point or
if the call fails, a simple do_gettimeofday() timestamp
is returned as crude approximation of the true vblank time.
A new drm module parameter drm.timestamp_precision_usec
allows to disable high precision timestamps (if set to
zero) or to specify the maximum acceptable error in
the timestamps in microseconds.
Kms drivers could implement their get_vblank_timestamp()
function in a gpu specific way, as long as returned
timestamps conform to OML_sync_control, e.g., by use
of gpu specific hardware timestamps.
Optionally, kms drivers can simply wrap and use the new
utility function drm_calc_vbltimestamp_from_scanoutpos().
This function calls a new optional kms driver function
dev->driver->get_scanout_position() which returns the
current horizontal and vertical video scanout position
of the crtc. The scanout position together with the
drm_display_timing of the current video mode is used
to calculate elapsed time relative to start of active scanout
for the current video frame. This elapsed time is subtracted
from the current do_gettimeofday() time to get the timestamp
corresponding to start of video scanout. Currently
non-interlaced, non-doublescan video modes, with or
without panel scaling are handled correctly. Interlaced/
doublescan modes are tbd in a future patch.
3. Filtering of redundant vblank irq's and removal of
some race-conditions in the vblank irq enable/disable path:
Some gpu's (e.g., Radeon R500/R600) send spurious vblank
irq's outside the vblank if vblank irq's get reenabled.
These get detected by use of the vblank timestamps and
filtered out to avoid miscounting of vblanks.
Some race-conditions between the vblank irq enable/disable
functions, the vblank irq handler and the gpu itself (updating
its hardware vblank counter in the "wrong" moment) are
fixed inside vblank_disable_and_save() and
drm_update_vblank_count() by use of the vblank timestamps and
a new spinlock dev->vblank_time_lock.
The time until vblank irq disable is now configurable via
a new drm module parameter drm.vblankoffdelay to allow
experimentation with timeouts that are much shorter than
the current 5 seconds and should allow longer vblank off
periods for better power savings.
Followup patches will use these new functions to
implement precise timestamping for the intel and radeon
kms drivers.
Signed-off-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2010-10-23 09:20:23 +07:00
|
|
|
* @crtc is currently inside VBLANK, this will be a time in the future.
|
|
|
|
* If the @crtc is currently scanning out a frame, this will be the
|
|
|
|
* past start time of the current scanout. This is meant to adhere
|
|
|
|
* to the OpenML OML_sync_control extension specification.
|
|
|
|
*
|
|
|
|
* \param dev dev DRM device handle.
|
2015-09-24 23:35:31 +07:00
|
|
|
* \param pipe crtc for which timestamp should be returned.
|
drm/vblank: Add support for precise vblank timestamping.
The DRI2 swap & sync implementation needs precise
vblank counts and precise timestamps corresponding
to those vblank counts. For conformance to the OpenML
OML_sync_control extension specification the DRM
timestamp associated with a vblank count should
correspond to the start of video scanout of the first
scanline of the video frame following the vblank
interval for that vblank count.
Therefore we need to carry around precise timestamps
for vblanks. Currently the DRM and KMS drivers generate
timestamps ad-hoc via do_gettimeofday() in some
places. The resulting timestamps are sometimes not
very precise due to interrupt handling delays, they
don't conform to OML_sync_control and some are wrong,
as they aren't taken synchronized to the vblank.
This patch implements support inside the drm core
for precise and robust timestamping. It consists
of the following interrelated pieces.
1. Vblank timestamp caching:
A per-crtc ringbuffer stores the most recent vblank
timestamps corresponding to vblank counts.
The ringbuffer can be read out lock-free via the
accessor function:
struct timeval timestamp;
vblankcount = drm_vblank_count_and_time(dev, crtcid, ×tamp).
The function returns the current vblank count and
the corresponding timestamp for start of video
scanout following the vblank interval. It can be
used anywhere between enclosing drm_vblank_get(dev, crtcid)
and drm_vblank_put(dev,crtcid) statements. It is used
inside the drmWaitVblank ioctl and in the vblank event
queueing and handling. It should be used by kms drivers for
timestamping of bufferswap completion.
The timestamp ringbuffer is reinitialized each time
vblank irq's get reenabled in drm_vblank_get()/
drm_update_vblank_count(). It is invalidated when
vblank irq's get disabled.
The ringbuffer is updated inside drm_handle_vblank()
at each vblank irq.
2. Calculation of precise vblank timestamps:
drm_get_last_vbltimestamp() is used to compute the
timestamp for the end of the most recent vblank (if
inside active scanout), or the expected end of the
current vblank interval (if called inside a vblank
interval). The function calls into a new optional kms
driver entry point dev->driver->get_vblank_timestamp()
which is supposed to provide the precise timestamp.
If a kms driver doesn't implement the entry point or
if the call fails, a simple do_gettimeofday() timestamp
is returned as crude approximation of the true vblank time.
A new drm module parameter drm.timestamp_precision_usec
allows to disable high precision timestamps (if set to
zero) or to specify the maximum acceptable error in
the timestamps in microseconds.
Kms drivers could implement their get_vblank_timestamp()
function in a gpu specific way, as long as returned
timestamps conform to OML_sync_control, e.g., by use
of gpu specific hardware timestamps.
Optionally, kms drivers can simply wrap and use the new
utility function drm_calc_vbltimestamp_from_scanoutpos().
This function calls a new optional kms driver function
dev->driver->get_scanout_position() which returns the
current horizontal and vertical video scanout position
of the crtc. The scanout position together with the
drm_display_timing of the current video mode is used
to calculate elapsed time relative to start of active scanout
for the current video frame. This elapsed time is subtracted
from the current do_gettimeofday() time to get the timestamp
corresponding to start of video scanout. Currently
non-interlaced, non-doublescan video modes, with or
without panel scaling are handled correctly. Interlaced/
doublescan modes are tbd in a future patch.
3. Filtering of redundant vblank irq's and removal of
some race-conditions in the vblank irq enable/disable path:
Some gpu's (e.g., Radeon R500/R600) send spurious vblank
irq's outside the vblank if vblank irq's get reenabled.
These get detected by use of the vblank timestamps and
filtered out to avoid miscounting of vblanks.
Some race-conditions between the vblank irq enable/disable
functions, the vblank irq handler and the gpu itself (updating
its hardware vblank counter in the "wrong" moment) are
fixed inside vblank_disable_and_save() and
drm_update_vblank_count() by use of the vblank timestamps and
a new spinlock dev->vblank_time_lock.
The time until vblank irq disable is now configurable via
a new drm module parameter drm.vblankoffdelay to allow
experimentation with timeouts that are much shorter than
the current 5 seconds and should allow longer vblank off
periods for better power savings.
Followup patches will use these new functions to
implement precise timestamping for the intel and radeon
kms drivers.
Signed-off-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2010-10-23 09:20:23 +07:00
|
|
|
* \param *max_error Maximum allowable timestamp error in nanoseconds.
|
|
|
|
* Implementation should strive to provide timestamp
|
|
|
|
* with an error of at most *max_error nanoseconds.
|
|
|
|
* Returns true upper bound on error for timestamp.
|
|
|
|
* \param *vblank_time Target location for returned vblank timestamp.
|
|
|
|
* \param flags 0 = Defaults, no special treatment needed.
|
|
|
|
* \param DRM_CALLED_FROM_VBLIRQ = Function is called from vblank
|
|
|
|
* irq handler. Some drivers need to apply some workarounds
|
|
|
|
* for gpu-specific vblank irq quirks if flag is set.
|
|
|
|
*
|
|
|
|
* \returns
|
|
|
|
* Zero if timestamping isn't supported in current display mode or a
|
|
|
|
* negative number on failure. A positive status code on success,
|
|
|
|
* which describes how the vblank_time timestamp was computed.
|
|
|
|
*/
|
2015-09-24 23:35:31 +07:00
|
|
|
int (*get_vblank_timestamp) (struct drm_device *dev, unsigned int pipe,
|
drm/vblank: Add support for precise vblank timestamping.
The DRI2 swap & sync implementation needs precise
vblank counts and precise timestamps corresponding
to those vblank counts. For conformance to the OpenML
OML_sync_control extension specification the DRM
timestamp associated with a vblank count should
correspond to the start of video scanout of the first
scanline of the video frame following the vblank
interval for that vblank count.
Therefore we need to carry around precise timestamps
for vblanks. Currently the DRM and KMS drivers generate
timestamps ad-hoc via do_gettimeofday() in some
places. The resulting timestamps are sometimes not
very precise due to interrupt handling delays, they
don't conform to OML_sync_control and some are wrong,
as they aren't taken synchronized to the vblank.
This patch implements support inside the drm core
for precise and robust timestamping. It consists
of the following interrelated pieces.
1. Vblank timestamp caching:
A per-crtc ringbuffer stores the most recent vblank
timestamps corresponding to vblank counts.
The ringbuffer can be read out lock-free via the
accessor function:
struct timeval timestamp;
vblankcount = drm_vblank_count_and_time(dev, crtcid, ×tamp).
The function returns the current vblank count and
the corresponding timestamp for start of video
scanout following the vblank interval. It can be
used anywhere between enclosing drm_vblank_get(dev, crtcid)
and drm_vblank_put(dev,crtcid) statements. It is used
inside the drmWaitVblank ioctl and in the vblank event
queueing and handling. It should be used by kms drivers for
timestamping of bufferswap completion.
The timestamp ringbuffer is reinitialized each time
vblank irq's get reenabled in drm_vblank_get()/
drm_update_vblank_count(). It is invalidated when
vblank irq's get disabled.
The ringbuffer is updated inside drm_handle_vblank()
at each vblank irq.
2. Calculation of precise vblank timestamps:
drm_get_last_vbltimestamp() is used to compute the
timestamp for the end of the most recent vblank (if
inside active scanout), or the expected end of the
current vblank interval (if called inside a vblank
interval). The function calls into a new optional kms
driver entry point dev->driver->get_vblank_timestamp()
which is supposed to provide the precise timestamp.
If a kms driver doesn't implement the entry point or
if the call fails, a simple do_gettimeofday() timestamp
is returned as crude approximation of the true vblank time.
A new drm module parameter drm.timestamp_precision_usec
allows to disable high precision timestamps (if set to
zero) or to specify the maximum acceptable error in
the timestamps in microseconds.
Kms drivers could implement their get_vblank_timestamp()
function in a gpu specific way, as long as returned
timestamps conform to OML_sync_control, e.g., by use
of gpu specific hardware timestamps.
Optionally, kms drivers can simply wrap and use the new
utility function drm_calc_vbltimestamp_from_scanoutpos().
This function calls a new optional kms driver function
dev->driver->get_scanout_position() which returns the
current horizontal and vertical video scanout position
of the crtc. The scanout position together with the
drm_display_timing of the current video mode is used
to calculate elapsed time relative to start of active scanout
for the current video frame. This elapsed time is subtracted
from the current do_gettimeofday() time to get the timestamp
corresponding to start of video scanout. Currently
non-interlaced, non-doublescan video modes, with or
without panel scaling are handled correctly. Interlaced/
doublescan modes are tbd in a future patch.
3. Filtering of redundant vblank irq's and removal of
some race-conditions in the vblank irq enable/disable path:
Some gpu's (e.g., Radeon R500/R600) send spurious vblank
irq's outside the vblank if vblank irq's get reenabled.
These get detected by use of the vblank timestamps and
filtered out to avoid miscounting of vblanks.
Some race-conditions between the vblank irq enable/disable
functions, the vblank irq handler and the gpu itself (updating
its hardware vblank counter in the "wrong" moment) are
fixed inside vblank_disable_and_save() and
drm_update_vblank_count() by use of the vblank timestamps and
a new spinlock dev->vblank_time_lock.
The time until vblank irq disable is now configurable via
a new drm module parameter drm.vblankoffdelay to allow
experimentation with timeouts that are much shorter than
the current 5 seconds and should allow longer vblank off
periods for better power savings.
Followup patches will use these new functions to
implement precise timestamping for the intel and radeon
kms drivers.
Signed-off-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2010-10-23 09:20:23 +07:00
|
|
|
int *max_error,
|
|
|
|
struct timeval *vblank_time,
|
|
|
|
unsigned flags);
|
|
|
|
|
2005-04-17 05:20:36 +07:00
|
|
|
/* these have to be filled in */
|
2005-09-25 11:28:13 +07:00
|
|
|
|
2013-12-11 17:34:42 +07:00
|
|
|
irqreturn_t(*irq_handler) (int irq, void *arg);
|
2007-07-11 12:53:27 +07:00
|
|
|
void (*irq_preinstall) (struct drm_device *dev);
|
2008-10-01 02:14:26 +07:00
|
|
|
int (*irq_postinstall) (struct drm_device *dev);
|
2007-07-11 12:53:27 +07:00
|
|
|
void (*irq_uninstall) (struct drm_device *dev);
|
2005-11-10 18:16:34 +07:00
|
|
|
|
2008-11-28 11:22:24 +07:00
|
|
|
/* Master routines */
|
|
|
|
int (*master_create)(struct drm_device *dev, struct drm_master *master);
|
|
|
|
void (*master_destroy)(struct drm_device *dev, struct drm_master *master);
|
2009-12-03 01:15:25 +07:00
|
|
|
/**
|
|
|
|
* master_set is called whenever the minor master is set.
|
|
|
|
* master_drop is called whenever the minor master is dropped.
|
|
|
|
*/
|
|
|
|
|
|
|
|
int (*master_set)(struct drm_device *dev, struct drm_file *file_priv,
|
|
|
|
bool from_open);
|
2016-06-21 19:20:38 +07:00
|
|
|
void (*master_drop)(struct drm_device *dev, struct drm_file *file_priv);
|
2008-11-28 11:22:24 +07:00
|
|
|
|
2009-02-18 08:08:49 +07:00
|
|
|
int (*debugfs_init)(struct drm_minor *minor);
|
|
|
|
void (*debugfs_cleanup)(struct drm_minor *minor);
|
2008-07-31 02:06:12 +07:00
|
|
|
|
|
|
|
/**
|
2016-05-02 15:40:51 +07:00
|
|
|
* @gem_free_object: deconstructor for drm_gem_objects
|
2008-07-31 02:06:12 +07:00
|
|
|
*
|
2016-05-02 15:40:51 +07:00
|
|
|
* This is deprecated and should not be used by new drivers. Use
|
|
|
|
* @gem_free_object_unlocked instead.
|
2008-07-31 02:06:12 +07:00
|
|
|
*/
|
|
|
|
void (*gem_free_object) (struct drm_gem_object *obj);
|
2016-05-02 15:40:51 +07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @gem_free_object_unlocked: deconstructor for drm_gem_objects
|
|
|
|
*
|
|
|
|
* This is for drivers which are not encumbered with dev->struct_mutex
|
|
|
|
* legacy locking schemes. Use this hook instead of @gem_free_object.
|
|
|
|
*/
|
|
|
|
void (*gem_free_object_unlocked) (struct drm_gem_object *obj);
|
|
|
|
|
2011-06-09 07:24:59 +07:00
|
|
|
int (*gem_open_object) (struct drm_gem_object *, struct drm_file *);
|
|
|
|
void (*gem_close_object) (struct drm_gem_object *, struct drm_file *);
|
2008-07-31 02:06:12 +07:00
|
|
|
|
2015-12-01 01:55:13 +07:00
|
|
|
/**
|
|
|
|
* Hook for allocating the GEM object struct, for use by core
|
|
|
|
* helpers.
|
|
|
|
*/
|
|
|
|
struct drm_gem_object *(*gem_create_object)(struct drm_device *dev,
|
|
|
|
size_t size);
|
|
|
|
|
2011-11-25 22:21:02 +07:00
|
|
|
/* prime: */
|
|
|
|
/* export handle -> fd (see drm_gem_prime_handle_to_fd() helper) */
|
|
|
|
int (*prime_handle_to_fd)(struct drm_device *dev, struct drm_file *file_priv,
|
|
|
|
uint32_t handle, uint32_t flags, int *prime_fd);
|
|
|
|
/* import fd -> handle (see drm_gem_prime_fd_to_handle() helper) */
|
|
|
|
int (*prime_fd_to_handle)(struct drm_device *dev, struct drm_file *file_priv,
|
|
|
|
int prime_fd, uint32_t *handle);
|
|
|
|
/* export GEM -> dmabuf */
|
|
|
|
struct dma_buf * (*gem_prime_export)(struct drm_device *dev,
|
|
|
|
struct drm_gem_object *obj, int flags);
|
|
|
|
/* import dmabuf -> GEM */
|
|
|
|
struct drm_gem_object * (*gem_prime_import)(struct drm_device *dev,
|
|
|
|
struct dma_buf *dma_buf);
|
2013-01-16 03:47:42 +07:00
|
|
|
/* low-level interface used by drm_gem_prime_{import,export} */
|
|
|
|
int (*gem_prime_pin)(struct drm_gem_object *obj);
|
2013-04-09 14:18:44 +07:00
|
|
|
void (*gem_prime_unpin)(struct drm_gem_object *obj);
|
2014-07-01 17:57:26 +07:00
|
|
|
struct reservation_object * (*gem_prime_res_obj)(
|
|
|
|
struct drm_gem_object *obj);
|
2013-01-16 03:47:42 +07:00
|
|
|
struct sg_table *(*gem_prime_get_sg_table)(struct drm_gem_object *obj);
|
|
|
|
struct drm_gem_object *(*gem_prime_import_sg_table)(
|
2014-01-09 17:03:14 +07:00
|
|
|
struct drm_device *dev,
|
|
|
|
struct dma_buf_attachment *attach,
|
2013-01-16 03:47:42 +07:00
|
|
|
struct sg_table *sgt);
|
|
|
|
void *(*gem_prime_vmap)(struct drm_gem_object *obj);
|
|
|
|
void (*gem_prime_vunmap)(struct drm_gem_object *obj, void *vaddr);
|
2013-06-28 12:24:53 +07:00
|
|
|
int (*gem_prime_mmap)(struct drm_gem_object *obj,
|
|
|
|
struct vm_area_struct *vma);
|
2011-11-25 22:21:02 +07:00
|
|
|
|
2009-09-21 11:33:58 +07:00
|
|
|
/* vga arb irq handler */
|
|
|
|
void (*vgaarb_irq)(struct drm_device *dev, bool state);
|
|
|
|
|
2011-02-07 09:16:14 +07:00
|
|
|
/* dumb alloc support */
|
|
|
|
int (*dumb_create)(struct drm_file *file_priv,
|
|
|
|
struct drm_device *dev,
|
|
|
|
struct drm_mode_create_dumb *args);
|
|
|
|
int (*dumb_map_offset)(struct drm_file *file_priv,
|
|
|
|
struct drm_device *dev, uint32_t handle,
|
|
|
|
uint64_t *offset);
|
|
|
|
int (*dumb_destroy)(struct drm_file *file_priv,
|
|
|
|
struct drm_device *dev,
|
|
|
|
uint32_t handle);
|
|
|
|
|
2008-11-06 01:31:53 +07:00
|
|
|
/* Driver private ops for this object */
|
2012-05-17 18:27:22 +07:00
|
|
|
const struct vm_operations_struct *gem_vm_ops;
|
2008-11-06 01:31:53 +07:00
|
|
|
|
2005-11-10 18:16:34 +07:00
|
|
|
int major;
|
|
|
|
int minor;
|
|
|
|
int patchlevel;
|
|
|
|
char *name;
|
|
|
|
char *desc;
|
|
|
|
char *date;
|
|
|
|
|
2005-04-17 05:20:36 +07:00
|
|
|
u32 driver_features;
|
|
|
|
int dev_priv_size;
|
2013-08-03 00:27:49 +07:00
|
|
|
const struct drm_ioctl_desc *ioctls;
|
2005-04-17 05:20:36 +07:00
|
|
|
int num_ioctls;
|
2011-10-31 21:28:57 +07:00
|
|
|
const struct file_operations *fops;
|
2010-12-15 00:16:38 +07:00
|
|
|
|
2013-12-11 17:34:31 +07:00
|
|
|
/* List of devices hanging off this driver with stealth attach. */
|
|
|
|
struct list_head legacy_dev_list;
|
2005-04-17 05:20:36 +07:00
|
|
|
};
|
|
|
|
|
2014-01-29 18:31:40 +07:00
|
|
|
enum drm_minor_type {
|
2016-08-04 01:04:25 +07:00
|
|
|
DRM_MINOR_PRIMARY,
|
2014-01-29 18:31:40 +07:00
|
|
|
DRM_MINOR_CONTROL,
|
|
|
|
DRM_MINOR_RENDER,
|
|
|
|
DRM_MINOR_CNT,
|
|
|
|
};
|
2008-04-21 13:47:32 +07:00
|
|
|
|
2009-02-18 08:08:49 +07:00
|
|
|
/**
|
|
|
|
* Info file list entry. This structure represents a debugfs or proc file to
|
|
|
|
* be created by the drm core
|
|
|
|
*/
|
|
|
|
struct drm_info_list {
|
|
|
|
const char *name; /** file name */
|
|
|
|
int (*show)(struct seq_file*, void*); /** show callback */
|
|
|
|
u32 driver_features; /**< Required driver features for this entry */
|
|
|
|
void *data;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* debugfs node structure. This structure represents a debugfs file.
|
|
|
|
*/
|
|
|
|
struct drm_info_node {
|
|
|
|
struct list_head list;
|
|
|
|
struct drm_minor *minor;
|
2013-04-12 21:23:25 +07:00
|
|
|
const struct drm_info_list *info_ent;
|
2009-02-18 08:08:49 +07:00
|
|
|
struct dentry *dent;
|
|
|
|
};
|
|
|
|
|
2005-04-17 05:20:36 +07:00
|
|
|
/**
|
2008-04-21 13:47:32 +07:00
|
|
|
* DRM minor structure. This structure represents a drm minor number.
|
2005-04-17 05:20:36 +07:00
|
|
|
*/
|
2008-04-21 13:47:32 +07:00
|
|
|
struct drm_minor {
|
|
|
|
int index; /**< Minor device number */
|
|
|
|
int type; /**< Control or render */
|
2013-10-11 11:07:25 +07:00
|
|
|
struct device *kdev; /**< Linux device */
|
2005-04-17 05:20:36 +07:00
|
|
|
struct drm_device *dev;
|
2009-02-18 08:08:49 +07:00
|
|
|
|
|
|
|
struct dentry *debugfs_root;
|
2011-11-10 04:20:35 +07:00
|
|
|
|
|
|
|
struct list_head debugfs_list;
|
|
|
|
struct mutex debugfs_lock; /* Protects debugfs_list. */
|
2007-07-11 12:53:27 +07:00
|
|
|
};
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* DRM device structure. This structure represent a complete card that
|
|
|
|
* may contain multiple heads.
|
|
|
|
*/
|
2007-07-11 12:53:27 +07:00
|
|
|
struct drm_device {
|
2013-12-11 17:34:31 +07:00
|
|
|
struct list_head legacy_dev_list;/**< list of devices per driver for stealth attach cleanup */
|
2005-09-25 11:28:13 +07:00
|
|
|
int if_version; /**< Highest interface version set */
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2014-01-28 22:00:35 +07:00
|
|
|
/** \name Lifetime Management */
|
|
|
|
/*@{ */
|
drm: provide device-refcount
Lets not trick ourselves into thinking "drm_device" objects are not
ref-counted. That's just utterly stupid. We manage "drm_minor" objects on
each drm-device and each minor can have an unlimited number of open
handles. Each of these handles has the drm_minor (and thus the drm_device)
as private-data in the file-handle. Therefore, we may not destroy
"drm_device" until all these handles are closed.
It is *not* possible to reset all these pointers atomically and restrict
access to them, and this is *not* how this is done! Instead, we use
ref-counts to make sure the object is valid and not freed.
Note that we currently use "dev->open_count" for that, which is *exactly*
the same as a reference-count, just open coded. So this patch doesn't
change any semantics on DRM devices (well, this patch just introduces the
ref-count, anyway. Follow-up patches will replace open_count by it).
Also note that generic VFS revoke support could allow us to drop this
ref-count again. We could then just synchronously disable any fops->xy()
calls. However, this is not the case, yet, and no such patches are
in sight (and I seriously question the idea of dropping the ref-cnt
again).
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
2014-01-29 16:21:36 +07:00
|
|
|
struct kref ref; /**< Object ref-count */
|
2014-01-28 22:00:35 +07:00
|
|
|
struct device *dev; /**< Device structure of bus-device */
|
|
|
|
struct drm_driver *driver; /**< DRM driver managing the device */
|
|
|
|
void *dev_private; /**< DRM driver private data */
|
|
|
|
struct drm_minor *control; /**< Control node */
|
|
|
|
struct drm_minor *primary; /**< Primary node */
|
|
|
|
struct drm_minor *render; /**< Render node */
|
2016-06-21 15:54:12 +07:00
|
|
|
|
|
|
|
/* currently active master for this device. Protected by master_mutex */
|
|
|
|
struct drm_master *master;
|
|
|
|
|
2014-01-28 22:00:35 +07:00
|
|
|
atomic_t unplugged; /**< Flag whether dev is dead */
|
2014-03-16 19:13:51 +07:00
|
|
|
struct inode *anon_inode; /**< inode for private address-space */
|
2014-04-11 20:23:00 +07:00
|
|
|
char *unique; /**< unique name of the device */
|
2014-01-28 22:00:35 +07:00
|
|
|
/*@} */
|
|
|
|
|
2005-04-17 05:20:36 +07:00
|
|
|
/** \name Locks */
|
2005-09-25 11:28:13 +07:00
|
|
|
/*@{ */
|
2006-02-02 15:37:46 +07:00
|
|
|
struct mutex struct_mutex; /**< For others */
|
2014-02-26 01:57:44 +07:00
|
|
|
struct mutex master_mutex; /**< For drm_minor::master and drm_file::is_master */
|
2005-09-25 11:28:13 +07:00
|
|
|
/*@} */
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
/** \name Usage Counters */
|
2005-09-25 11:28:13 +07:00
|
|
|
/*@{ */
|
2013-11-04 02:46:34 +07:00
|
|
|
int open_count; /**< Outstanding files open, protected by drm_global_mutex. */
|
2013-12-16 17:21:06 +07:00
|
|
|
spinlock_t buf_lock; /**< For drm_device::buf_use and a few other things. */
|
2005-09-25 11:28:13 +07:00
|
|
|
int buf_use; /**< Buffers in use -- cannot alloc */
|
|
|
|
atomic_t buf_alloc; /**< Buffer allocation in progress */
|
|
|
|
/*@} */
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2016-04-27 00:29:41 +07:00
|
|
|
struct mutex filelist_mutex;
|
2007-05-26 02:01:51 +07:00
|
|
|
struct list_head filelist;
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
/** \name Memory management */
|
2005-09-25 11:28:13 +07:00
|
|
|
/*@{ */
|
2007-05-26 02:01:51 +07:00
|
|
|
struct list_head maplist; /**< Linked list of regions */
|
2007-07-12 07:26:44 +07:00
|
|
|
struct drm_open_hash map_hash; /**< User token hash table for maps */
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
/** \name Context handle management */
|
2005-09-25 11:28:13 +07:00
|
|
|
/*@{ */
|
2007-05-26 02:01:51 +07:00
|
|
|
struct list_head ctxlist; /**< Linked list of context handles */
|
2006-02-02 15:37:46 +07:00
|
|
|
struct mutex ctxlist_mutex; /**< For ctxlist */
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2007-07-17 07:46:52 +07:00
|
|
|
struct idr ctx_idr;
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2007-05-26 02:01:51 +07:00
|
|
|
struct list_head vmalist; /**< List of vmas (for debugging) */
|
2008-11-08 05:05:41 +07:00
|
|
|
|
2005-09-25 11:28:13 +07:00
|
|
|
/*@} */
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2011-10-26 05:54:41 +07:00
|
|
|
/** \name DMA support */
|
2005-09-25 11:28:13 +07:00
|
|
|
/*@{ */
|
2007-07-11 13:32:08 +07:00
|
|
|
struct drm_device_dma *dma; /**< Optional pointer for DMA support */
|
2005-09-25 11:28:13 +07:00
|
|
|
/*@} */
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
/** \name Context support */
|
2005-09-25 11:28:13 +07:00
|
|
|
/*@{ */
|
2013-12-16 17:21:15 +07:00
|
|
|
|
2005-04-17 05:20:36 +07:00
|
|
|
__volatile__ long context_flag; /**< Context swapping flag */
|
2005-09-25 11:28:13 +07:00
|
|
|
int last_context; /**< Last current context */
|
|
|
|
/*@} */
|
|
|
|
|
2005-04-17 05:20:36 +07:00
|
|
|
/** \name VBLANK IRQ support */
|
2005-09-25 11:28:13 +07:00
|
|
|
/*@{ */
|
2014-12-17 22:41:41 +07:00
|
|
|
bool irq_enabled;
|
|
|
|
int irq;
|
2005-09-25 11:28:13 +07:00
|
|
|
|
2014-08-06 18:49:54 +07:00
|
|
|
/*
|
|
|
|
* If true, vblank interrupt will be disabled immediately when the
|
|
|
|
* refcount drops to zero, as opposed to via the vblank disable
|
|
|
|
* timer.
|
|
|
|
* This can be set to true it the hardware has a working vblank
|
|
|
|
* counter and the driver uses drm_vblank_on() and drm_vblank_off()
|
|
|
|
* appropriately.
|
|
|
|
*/
|
|
|
|
bool vblank_disable_immediate;
|
|
|
|
|
2013-10-04 18:53:36 +07:00
|
|
|
/* array of size num_crtcs */
|
|
|
|
struct drm_vblank_crtc *vblank;
|
2008-10-01 02:14:26 +07:00
|
|
|
|
drm/vblank: Add support for precise vblank timestamping.
The DRI2 swap & sync implementation needs precise
vblank counts and precise timestamps corresponding
to those vblank counts. For conformance to the OpenML
OML_sync_control extension specification the DRM
timestamp associated with a vblank count should
correspond to the start of video scanout of the first
scanline of the video frame following the vblank
interval for that vblank count.
Therefore we need to carry around precise timestamps
for vblanks. Currently the DRM and KMS drivers generate
timestamps ad-hoc via do_gettimeofday() in some
places. The resulting timestamps are sometimes not
very precise due to interrupt handling delays, they
don't conform to OML_sync_control and some are wrong,
as they aren't taken synchronized to the vblank.
This patch implements support inside the drm core
for precise and robust timestamping. It consists
of the following interrelated pieces.
1. Vblank timestamp caching:
A per-crtc ringbuffer stores the most recent vblank
timestamps corresponding to vblank counts.
The ringbuffer can be read out lock-free via the
accessor function:
struct timeval timestamp;
vblankcount = drm_vblank_count_and_time(dev, crtcid, ×tamp).
The function returns the current vblank count and
the corresponding timestamp for start of video
scanout following the vblank interval. It can be
used anywhere between enclosing drm_vblank_get(dev, crtcid)
and drm_vblank_put(dev,crtcid) statements. It is used
inside the drmWaitVblank ioctl and in the vblank event
queueing and handling. It should be used by kms drivers for
timestamping of bufferswap completion.
The timestamp ringbuffer is reinitialized each time
vblank irq's get reenabled in drm_vblank_get()/
drm_update_vblank_count(). It is invalidated when
vblank irq's get disabled.
The ringbuffer is updated inside drm_handle_vblank()
at each vblank irq.
2. Calculation of precise vblank timestamps:
drm_get_last_vbltimestamp() is used to compute the
timestamp for the end of the most recent vblank (if
inside active scanout), or the expected end of the
current vblank interval (if called inside a vblank
interval). The function calls into a new optional kms
driver entry point dev->driver->get_vblank_timestamp()
which is supposed to provide the precise timestamp.
If a kms driver doesn't implement the entry point or
if the call fails, a simple do_gettimeofday() timestamp
is returned as crude approximation of the true vblank time.
A new drm module parameter drm.timestamp_precision_usec
allows to disable high precision timestamps (if set to
zero) or to specify the maximum acceptable error in
the timestamps in microseconds.
Kms drivers could implement their get_vblank_timestamp()
function in a gpu specific way, as long as returned
timestamps conform to OML_sync_control, e.g., by use
of gpu specific hardware timestamps.
Optionally, kms drivers can simply wrap and use the new
utility function drm_calc_vbltimestamp_from_scanoutpos().
This function calls a new optional kms driver function
dev->driver->get_scanout_position() which returns the
current horizontal and vertical video scanout position
of the crtc. The scanout position together with the
drm_display_timing of the current video mode is used
to calculate elapsed time relative to start of active scanout
for the current video frame. This elapsed time is subtracted
from the current do_gettimeofday() time to get the timestamp
corresponding to start of video scanout. Currently
non-interlaced, non-doublescan video modes, with or
without panel scaling are handled correctly. Interlaced/
doublescan modes are tbd in a future patch.
3. Filtering of redundant vblank irq's and removal of
some race-conditions in the vblank irq enable/disable path:
Some gpu's (e.g., Radeon R500/R600) send spurious vblank
irq's outside the vblank if vblank irq's get reenabled.
These get detected by use of the vblank timestamps and
filtered out to avoid miscounting of vblanks.
Some race-conditions between the vblank irq enable/disable
functions, the vblank irq handler and the gpu itself (updating
its hardware vblank counter in the "wrong" moment) are
fixed inside vblank_disable_and_save() and
drm_update_vblank_count() by use of the vblank timestamps and
a new spinlock dev->vblank_time_lock.
The time until vblank irq disable is now configurable via
a new drm module parameter drm.vblankoffdelay to allow
experimentation with timeouts that are much shorter than
the current 5 seconds and should allow longer vblank off
periods for better power savings.
Followup patches will use these new functions to
implement precise timestamping for the intel and radeon
kms drivers.
Signed-off-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2010-10-23 09:20:23 +07:00
|
|
|
spinlock_t vblank_time_lock; /**< Protects vblank count and time updates during vblank enable/disable */
|
2005-09-25 11:28:13 +07:00
|
|
|
spinlock_t vbl_lock;
|
2008-10-01 02:14:26 +07:00
|
|
|
|
|
|
|
u32 max_vblank_count; /**< size of vblank counter register */
|
2005-09-25 11:28:13 +07:00
|
|
|
|
2009-09-12 01:33:34 +07:00
|
|
|
/**
|
|
|
|
* List of events
|
|
|
|
*/
|
|
|
|
struct list_head vblank_event_list;
|
|
|
|
spinlock_t event_lock;
|
|
|
|
|
2005-09-25 11:28:13 +07:00
|
|
|
/*@} */
|
|
|
|
|
2007-07-11 13:53:40 +07:00
|
|
|
struct drm_agp_head *agp; /**< AGP data */
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2005-09-25 11:28:13 +07:00
|
|
|
struct pci_dev *pdev; /**< PCI device structure */
|
2005-04-17 05:20:36 +07:00
|
|
|
#ifdef __alpha__
|
|
|
|
struct pci_controller *hose;
|
|
|
|
#endif
|
2010-05-28 02:40:25 +07:00
|
|
|
|
|
|
|
struct platform_device *platformdev; /**< Platform device struture */
|
2013-09-09 07:02:56 +07:00
|
|
|
struct virtio_device *virtdev;
|
2010-05-28 02:40:25 +07:00
|
|
|
|
2007-07-11 13:53:40 +07:00
|
|
|
struct drm_sg_mem *sg; /**< Scatter gather memory */
|
2011-02-24 05:35:06 +07:00
|
|
|
unsigned int num_crtcs; /**< Number of CRTCs on this device */
|
2005-09-25 11:28:13 +07:00
|
|
|
|
2014-08-29 17:12:39 +07:00
|
|
|
struct {
|
|
|
|
int context;
|
|
|
|
struct drm_hw_lock *lock;
|
|
|
|
} sigdata;
|
|
|
|
|
2009-02-02 12:55:46 +07:00
|
|
|
struct drm_local_map *agp_buffer_map;
|
2005-08-05 19:11:22 +07:00
|
|
|
unsigned int agp_buffer_token;
|
2006-10-24 20:04:19 +07:00
|
|
|
|
2014-11-26 08:33:10 +07:00
|
|
|
struct drm_mode_config mode_config; /**< Current mode config */
|
2008-11-08 05:05:41 +07:00
|
|
|
|
2008-07-31 02:06:12 +07:00
|
|
|
/** \name GEM information */
|
|
|
|
/*@{ */
|
2013-08-15 05:02:44 +07:00
|
|
|
struct mutex object_name_lock;
|
2008-07-31 02:06:12 +07:00
|
|
|
struct idr object_name_idr;
|
2013-12-11 20:24:46 +07:00
|
|
|
struct drm_vma_offset_manager *vma_offset_manager;
|
2008-07-31 02:06:12 +07:00
|
|
|
/*@} */
|
2010-12-07 06:20:40 +07:00
|
|
|
int switch_power_state;
|
2007-07-11 12:53:27 +07:00
|
|
|
};
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2016-07-16 02:48:01 +07:00
|
|
|
#include <drm/drm_irq.h>
|
|
|
|
|
2010-12-07 06:20:40 +07:00
|
|
|
#define DRM_SWITCH_POWER_ON 0
|
|
|
|
#define DRM_SWITCH_POWER_OFF 1
|
|
|
|
#define DRM_SWITCH_POWER_CHANGING 2
|
2012-09-12 12:55:05 +07:00
|
|
|
#define DRM_SWITCH_POWER_DYNAMIC_OFF 3
|
2010-12-07 06:20:40 +07:00
|
|
|
|
2005-09-25 11:28:13 +07:00
|
|
|
static __inline__ int drm_core_check_feature(struct drm_device *dev,
|
|
|
|
int feature)
|
2005-04-17 05:20:36 +07:00
|
|
|
{
|
|
|
|
return ((dev->driver->driver_features & feature) ? 1 : 0);
|
|
|
|
}
|
|
|
|
|
2012-02-20 21:18:07 +07:00
|
|
|
static inline void drm_device_set_unplugged(struct drm_device *dev)
|
|
|
|
{
|
|
|
|
smp_wmb();
|
|
|
|
atomic_set(&dev->unplugged, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int drm_device_is_unplugged(struct drm_device *dev)
|
|
|
|
{
|
|
|
|
int ret = atomic_read(&dev->unplugged);
|
|
|
|
smp_rmb();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-03-13 17:07:44 +07:00
|
|
|
static inline bool drm_is_render_client(const struct drm_file *file_priv)
|
drm: implement experimental render nodes
Render nodes provide an API for userspace to use non-privileged GPU
commands without any running DRM-Master. It is useful for offscreen
rendering, GPGPU clients, and normal render clients which do not perform
modesetting.
Compared to legacy clients, render clients no longer need any
authentication to perform client ioctls. Instead, user-space controls
render/client access to GPUs via filesystem access-modes on the
render-node. Once a render-node was opened, a client has full access to
the client/render operations on the GPU. However, no modesetting or ioctls
that affect global state are allowed on render nodes.
To prevent privilege-escalation, drivers must explicitly state that they
support render nodes. They must mark their render-only ioctls as
DRM_RENDER_ALLOW so render clients can use them. Furthermore, they must
support clients without any attached master.
If filesystem access-modes are not enough for fine-grained access control
to render nodes (very unlikely, considering the versaitlity of FS-ACLs),
you may still fall-back to fd-passing from server to client (which allows
arbitrary access-control). However, note that revoking access is
currently impossible and unlikely to get implemented.
Note: Render clients no longer have any associated DRM-Master as they are
supposed to be independent of any server state. DRM core highly depends on
file_priv->master to be non-NULL for modesetting/ctx/etc. commands.
Therefore, drivers must be very careful to not require DRM-Master if they
support DRIVER_RENDER.
So far render-nodes are protected by "drm_rnodes". As long as this
module-parameter is not set to 1, a driver will not create render nodes.
This allows us to experiment with the API a bit before we stabilize it.
v2: drop insecure GEM_FLINK to force use of dmabuf
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2013-08-25 23:29:00 +07:00
|
|
|
{
|
|
|
|
return file_priv->minor->type == DRM_MINOR_RENDER;
|
|
|
|
}
|
|
|
|
|
2014-02-19 20:21:48 +07:00
|
|
|
static inline bool drm_is_control_client(const struct drm_file *file_priv)
|
|
|
|
{
|
|
|
|
return file_priv->minor->type == DRM_MINOR_CONTROL;
|
|
|
|
}
|
|
|
|
|
2014-03-13 17:07:44 +07:00
|
|
|
static inline bool drm_is_primary_client(const struct drm_file *file_priv)
|
|
|
|
{
|
2016-08-04 01:04:25 +07:00
|
|
|
return file_priv->minor->type == DRM_MINOR_PRIMARY;
|
2014-03-13 17:07:44 +07:00
|
|
|
}
|
|
|
|
|
2005-04-17 05:20:36 +07:00
|
|
|
/******************************************************************/
|
|
|
|
/** \name Internal function definitions */
|
|
|
|
/*@{*/
|
|
|
|
|
|
|
|
/* Driver support (drm_drv.h) */
|
2015-07-11 12:31:08 +07:00
|
|
|
extern int drm_ioctl_permit(u32 flags, struct drm_file *file_priv);
|
2009-12-17 05:17:09 +07:00
|
|
|
extern long drm_ioctl(struct file *filp,
|
|
|
|
unsigned int cmd, unsigned long arg);
|
2016-11-01 22:40:44 +07:00
|
|
|
#ifdef CONFIG_COMPAT
|
2005-09-25 11:28:13 +07:00
|
|
|
extern long drm_compat_ioctl(struct file *filp,
|
|
|
|
unsigned int cmd, unsigned long arg);
|
2016-11-01 22:40:44 +07:00
|
|
|
#else
|
|
|
|
/* Let drm_compat_ioctl be assigned to .compat_ioctl unconditionally */
|
|
|
|
#define drm_compat_ioctl NULL
|
|
|
|
#endif
|
2014-02-26 21:51:57 +07:00
|
|
|
extern bool drm_ioctl_flags(unsigned int nr, unsigned int *flags);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2016-01-12 04:40:55 +07:00
|
|
|
/* File Operations (drm_fops.c) */
|
|
|
|
int drm_open(struct inode *inode, struct file *filp);
|
|
|
|
ssize_t drm_read(struct file *filp, char __user *buffer,
|
|
|
|
size_t count, loff_t *offset);
|
|
|
|
int drm_release(struct inode *inode, struct file *filp);
|
|
|
|
unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait);
|
2016-01-28 18:01:04 +07:00
|
|
|
int drm_event_reserve_init_locked(struct drm_device *dev,
|
|
|
|
struct drm_file *file_priv,
|
|
|
|
struct drm_pending_event *p,
|
|
|
|
struct drm_event *e);
|
2016-01-12 04:40:56 +07:00
|
|
|
int drm_event_reserve_init(struct drm_device *dev,
|
|
|
|
struct drm_file *file_priv,
|
|
|
|
struct drm_pending_event *p,
|
|
|
|
struct drm_event *e);
|
|
|
|
void drm_event_cancel_free(struct drm_device *dev,
|
|
|
|
struct drm_pending_event *p);
|
2016-01-12 04:40:59 +07:00
|
|
|
void drm_send_event_locked(struct drm_device *dev, struct drm_pending_event *e);
|
|
|
|
void drm_send_event(struct drm_device *dev, struct drm_pending_event *e);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2014-09-10 17:43:55 +07:00
|
|
|
/* Misc. IOCTL support (drm_ioctl.c) */
|
|
|
|
int drm_noop(struct drm_device *dev, void *data,
|
|
|
|
struct drm_file *file_priv);
|
2015-09-08 18:56:26 +07:00
|
|
|
int drm_invalid_op(struct drm_device *dev, void *data,
|
|
|
|
struct drm_file *file_priv);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2008-07-31 02:06:12 +07:00
|
|
|
/* Cache management (drm_cache.c) */
|
|
|
|
void drm_clflush_pages(struct page *pages[], unsigned long num_pages);
|
2012-06-01 21:20:22 +07:00
|
|
|
void drm_clflush_sg(struct sg_table *st);
|
2014-04-01 16:59:08 +07:00
|
|
|
void drm_clflush_virt_range(void *addr, unsigned long length);
|
2008-07-31 02:06:12 +07:00
|
|
|
|
2007-03-23 09:28:33 +07:00
|
|
|
/*
|
|
|
|
* These are exported to drivers so that they can implement fencing using
|
|
|
|
* DMA quiscent + idle. DMA quiescent usually requires the hardware lock.
|
|
|
|
*/
|
|
|
|
|
2008-10-01 02:14:26 +07:00
|
|
|
/* Modesetting support */
|
2015-08-12 22:00:31 +07:00
|
|
|
extern void drm_vblank_pre_modeset(struct drm_device *dev, unsigned int pipe);
|
|
|
|
extern void drm_vblank_post_modeset(struct drm_device *dev, unsigned int pipe);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2016-06-21 15:54:20 +07:00
|
|
|
/* drm_drv.c */
|
|
|
|
void drm_put_dev(struct drm_device *dev);
|
|
|
|
void drm_unplug_dev(struct drm_device *dev);
|
2005-09-25 11:28:13 +07:00
|
|
|
extern unsigned int drm_debug;
|
2008-04-21 13:47:32 +07:00
|
|
|
|
2009-02-18 08:08:49 +07:00
|
|
|
/* Debugfs support */
|
|
|
|
#if defined(CONFIG_DEBUG_FS)
|
2013-10-18 01:09:53 +07:00
|
|
|
extern int drm_debugfs_create_files(const struct drm_info_list *files,
|
|
|
|
int count, struct dentry *root,
|
|
|
|
struct drm_minor *minor);
|
|
|
|
extern int drm_debugfs_remove_files(const struct drm_info_list *files,
|
|
|
|
int count, struct drm_minor *minor);
|
2013-12-12 21:44:04 +07:00
|
|
|
#else
|
|
|
|
static inline int drm_debugfs_create_files(const struct drm_info_list *files,
|
|
|
|
int count, struct dentry *root,
|
|
|
|
struct drm_minor *minor)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int drm_debugfs_remove_files(const struct drm_info_list *files,
|
|
|
|
int count, struct drm_minor *minor)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
2009-02-18 08:08:49 +07:00
|
|
|
#endif
|
|
|
|
|
2016-10-05 19:21:44 +07:00
|
|
|
struct dma_buf_export_info;
|
|
|
|
|
2013-01-16 03:47:42 +07:00
|
|
|
extern struct dma_buf *drm_gem_prime_export(struct drm_device *dev,
|
2016-10-05 19:21:43 +07:00
|
|
|
struct drm_gem_object *obj,
|
|
|
|
int flags);
|
2011-11-25 22:21:02 +07:00
|
|
|
extern int drm_gem_prime_handle_to_fd(struct drm_device *dev,
|
|
|
|
struct drm_file *file_priv, uint32_t handle, uint32_t flags,
|
|
|
|
int *prime_fd);
|
2013-01-16 03:47:42 +07:00
|
|
|
extern struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev,
|
|
|
|
struct dma_buf *dma_buf);
|
2011-11-25 22:21:02 +07:00
|
|
|
extern int drm_gem_prime_fd_to_handle(struct drm_device *dev,
|
|
|
|
struct drm_file *file_priv, int prime_fd, uint32_t *handle);
|
2016-10-05 19:21:44 +07:00
|
|
|
struct dma_buf *drm_gem_dmabuf_export(struct drm_device *dev,
|
|
|
|
struct dma_buf_export_info *exp_info);
|
2013-08-15 05:02:30 +07:00
|
|
|
extern void drm_gem_dmabuf_release(struct dma_buf *dma_buf);
|
2011-11-25 22:21:02 +07:00
|
|
|
|
2012-05-18 21:40:33 +07:00
|
|
|
extern int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages,
|
|
|
|
dma_addr_t *addrs, int max_pages);
|
2014-06-04 14:18:29 +07:00
|
|
|
extern struct sg_table *drm_prime_pages_to_sg(struct page **pages, unsigned int nr_pages);
|
2011-11-25 22:21:02 +07:00
|
|
|
extern void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg);
|
|
|
|
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2014-09-11 12:43:25 +07:00
|
|
|
extern struct drm_dma_handle *drm_pci_alloc(struct drm_device *dev, size_t size,
|
|
|
|
size_t align);
|
|
|
|
extern void drm_pci_free(struct drm_device *dev, struct drm_dma_handle * dmah);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
/* sysfs support (drm_sysfs.c) */
|
2008-11-08 05:05:41 +07:00
|
|
|
extern void drm_sysfs_hotplug_event(struct drm_device *dev);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2008-07-31 02:06:12 +07:00
|
|
|
|
2013-10-02 16:23:34 +07:00
|
|
|
struct drm_device *drm_dev_alloc(struct drm_driver *driver,
|
|
|
|
struct device *parent);
|
2016-06-15 19:17:46 +07:00
|
|
|
int drm_dev_init(struct drm_device *dev,
|
|
|
|
struct drm_driver *driver,
|
|
|
|
struct device *parent);
|
drm: provide device-refcount
Lets not trick ourselves into thinking "drm_device" objects are not
ref-counted. That's just utterly stupid. We manage "drm_minor" objects on
each drm-device and each minor can have an unlimited number of open
handles. Each of these handles has the drm_minor (and thus the drm_device)
as private-data in the file-handle. Therefore, we may not destroy
"drm_device" until all these handles are closed.
It is *not* possible to reset all these pointers atomically and restrict
access to them, and this is *not* how this is done! Instead, we use
ref-counts to make sure the object is valid and not freed.
Note that we currently use "dev->open_count" for that, which is *exactly*
the same as a reference-count, just open coded. So this patch doesn't
change any semantics on DRM devices (well, this patch just introduces the
ref-count, anyway. Follow-up patches will replace open_count by it).
Also note that generic VFS revoke support could allow us to drop this
ref-count again. We could then just synchronously disable any fops->xy()
calls. However, this is not the case, yet, and no such patches are
in sight (and I seriously question the idea of dropping the ref-cnt
again).
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
2014-01-29 16:21:36 +07:00
|
|
|
void drm_dev_ref(struct drm_device *dev);
|
|
|
|
void drm_dev_unref(struct drm_device *dev);
|
2013-10-02 16:23:35 +07:00
|
|
|
int drm_dev_register(struct drm_device *dev, unsigned long flags);
|
2013-10-02 16:23:38 +07:00
|
|
|
void drm_dev_unregister(struct drm_device *dev);
|
2014-01-29 16:49:19 +07:00
|
|
|
|
|
|
|
struct drm_minor *drm_minor_acquire(unsigned int minor_id);
|
|
|
|
void drm_minor_release(struct drm_minor *minor);
|
|
|
|
|
2010-12-15 00:16:38 +07:00
|
|
|
/*@}*/
|
|
|
|
|
|
|
|
/* PCI section */
|
|
|
|
static __inline__ int drm_pci_device_is_agp(struct drm_device *dev)
|
|
|
|
{
|
2005-09-25 11:28:13 +07:00
|
|
|
if (dev->driver->device_is_agp != NULL) {
|
|
|
|
int err = (*dev->driver->device_is_agp) (dev);
|
|
|
|
|
2005-07-10 14:31:26 +07:00
|
|
|
if (err != 2) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return pci_find_capability(dev->pdev, PCI_CAP_ID_AGP);
|
|
|
|
}
|
2013-12-11 17:34:38 +07:00
|
|
|
void drm_pci_agp_destroy(struct drm_device *dev);
|
2005-07-10 14:31:26 +07:00
|
|
|
|
2010-12-15 00:16:38 +07:00
|
|
|
extern int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver);
|
|
|
|
extern void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver);
|
2014-08-05 18:37:47 +07:00
|
|
|
#ifdef CONFIG_PCI
|
2010-12-15 00:16:38 +07:00
|
|
|
extern int drm_get_pci_dev(struct pci_dev *pdev,
|
2010-05-28 02:40:25 +07:00
|
|
|
const struct pci_device_id *ent,
|
|
|
|
struct drm_driver *driver);
|
2014-08-29 17:12:43 +07:00
|
|
|
extern int drm_pci_set_busid(struct drm_device *dev, struct drm_master *master);
|
2014-08-05 18:37:47 +07:00
|
|
|
#else
|
|
|
|
static inline int drm_get_pci_dev(struct pci_dev *pdev,
|
|
|
|
const struct pci_device_id *ent,
|
|
|
|
struct drm_driver *driver)
|
|
|
|
{
|
|
|
|
return -ENOSYS;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int drm_pci_set_busid(struct drm_device *dev,
|
|
|
|
struct drm_master *master)
|
|
|
|
{
|
|
|
|
return -ENOSYS;
|
|
|
|
}
|
|
|
|
#endif
|
2010-12-15 00:16:38 +07:00
|
|
|
|
2012-06-27 14:35:53 +07:00
|
|
|
#define DRM_PCIE_SPEED_25 1
|
|
|
|
#define DRM_PCIE_SPEED_50 2
|
|
|
|
#define DRM_PCIE_SPEED_80 4
|
|
|
|
|
|
|
|
extern int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *speed_mask);
|
2015-11-12 11:14:39 +07:00
|
|
|
extern int drm_pcie_get_max_link_width(struct drm_device *dev, u32 *mlw);
|
2010-12-15 00:16:38 +07:00
|
|
|
|
|
|
|
/* platform section */
|
|
|
|
extern int drm_platform_init(struct drm_driver *driver, struct platform_device *platform_device);
|
|
|
|
|
2012-01-05 16:55:22 +07:00
|
|
|
/* returns true if currently okay to sleep */
|
|
|
|
static __inline__ bool drm_can_sleep(void)
|
|
|
|
{
|
|
|
|
if (in_atomic() || in_dbg_master() || irqs_disabled())
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
drm: fix potential dangling else problems in for_each_ macros
We have serious dangling else bugs waiting to happen in our for_each_
style macros with ifs. Consider, for example,
#define drm_for_each_plane_mask(plane, dev, plane_mask) \
list_for_each_entry((plane), &(dev)->mode_config.plane_list, head) \
if ((plane_mask) & (1 << drm_plane_index(plane)))
If this is used in context:
if (condition)
drm_for_each_plane_mask(plane, dev, plane_mask);
else
foo();
foo() will be called for each plane *not* in plane_mask, if condition
holds, and not at all if condition doesn't hold.
Fix this by reversing the conditions in the macros, and adding an else
branch for the "for each" block, so that other if/else blocks can't
interfere. Provide a "for_each_if" helper macro to make it easier to get
this right.
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1448392916-2281-1-git-send-email-jani.nikula@intel.com
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-11-25 02:21:55 +07:00
|
|
|
/* helper for handling conditionals in various for_each macros */
|
|
|
|
#define for_each_if(condition) if (!(condition)) {} else
|
|
|
|
|
2005-04-17 05:20:36 +07:00
|
|
|
#endif
|