mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-16 20:36:43 +07:00
3ed4351a83
drm_irq.c contains both the irq helper library (optional) and the vblank support (optional, but part of the modeset uapi, and doesn't require the use of the irq helpers at all. Split this up for more clarity of the scope of the individual bits. v2: Move misplaced hunks to this patch (Stefan). Cc: Stefan Agner <stefan@agner.ch> Reviewed-by: Stefan Agner <stefan@agner.ch> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/20170531092146.12528-1-daniel.vetter@ffwll.ch
502 lines
15 KiB
C
502 lines
15 KiB
C
/*
|
|
* Internal Header for the Direct Rendering Manager
|
|
*
|
|
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
|
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
|
* Copyright (c) 2009-2010, Code Aurora Forum.
|
|
* All rights reserved.
|
|
*
|
|
* Author: Rickard E. (Rik) Faith <faith@valinux.com>
|
|
* Author: Gareth Hughes <gareth@valinux.com>
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation
|
|
* 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_
|
|
|
|
#include <linux/agp_backend.h>
|
|
#include <linux/cdev.h>
|
|
#include <linux/dma-mapping.h>
|
|
#include <linux/file.h>
|
|
#include <linux/fs.h>
|
|
#include <linux/highmem.h>
|
|
#include <linux/idr.h>
|
|
#include <linux/init.h>
|
|
#include <linux/io.h>
|
|
#include <linux/jiffies.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/kref.h>
|
|
#include <linux/miscdevice.h>
|
|
#include <linux/mm.h>
|
|
#include <linux/mutex.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/poll.h>
|
|
#include <linux/ratelimit.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/types.h>
|
|
#include <linux/vmalloc.h>
|
|
#include <linux/workqueue.h>
|
|
#include <linux/dma-fence.h>
|
|
#include <linux/module.h>
|
|
|
|
#include <asm/mman.h>
|
|
#include <asm/pgalloc.h>
|
|
#include <linux/uaccess.h>
|
|
|
|
#include <uapi/drm/drm.h>
|
|
#include <uapi/drm/drm_mode.h>
|
|
|
|
#include <drm/drm_agpsupport.h>
|
|
#include <drm/drm_crtc.h>
|
|
#include <drm/drm_fourcc.h>
|
|
#include <drm/drm_global.h>
|
|
#include <drm/drm_hashtab.h>
|
|
#include <drm/drm_mm.h>
|
|
#include <drm/drm_os_linux.h>
|
|
#include <drm/drm_sarea.h>
|
|
#include <drm/drm_drv.h>
|
|
#include <drm/drm_prime.h>
|
|
#include <drm/drm_pci.h>
|
|
#include <drm/drm_file.h>
|
|
#include <drm/drm_debugfs.h>
|
|
#include <drm/drm_ioctl.h>
|
|
#include <drm/drm_sysfs.h>
|
|
#include <drm/drm_vblank.h>
|
|
#include <drm/drm_irq.h>
|
|
|
|
|
|
struct module;
|
|
|
|
struct drm_device;
|
|
struct drm_agp_head;
|
|
struct drm_local_map;
|
|
struct drm_device_dma;
|
|
struct drm_gem_object;
|
|
struct drm_master;
|
|
struct drm_vblank_crtc;
|
|
struct drm_vma_offset_manager;
|
|
|
|
struct device_node;
|
|
struct videomode;
|
|
struct reservation_object;
|
|
struct dma_buf_attachment;
|
|
|
|
struct pci_dev;
|
|
struct pci_controller;
|
|
|
|
/*
|
|
* The following categories are defined:
|
|
*
|
|
* 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.
|
|
*
|
|
* KMS: used in the modesetting code.
|
|
* This is the category used by the DRM_DEBUG_KMS() macro.
|
|
*
|
|
* PRIME: used in the prime code.
|
|
* This is the category used by the DRM_DEBUG_PRIME() macro.
|
|
*
|
|
* ATOMIC: used in the atomic code.
|
|
* This is the category used by the DRM_DEBUG_ATOMIC() macro.
|
|
*
|
|
* VBL: used for verbose debug message in the vblank code
|
|
* This is the category used by the DRM_DEBUG_VBL() macro.
|
|
*
|
|
* 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
|
|
* ...
|
|
* drm.debug=0x3f will enable all messages
|
|
*
|
|
* 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
|
|
*/
|
|
#define DRM_UT_NONE 0x00
|
|
#define DRM_UT_CORE 0x01
|
|
#define DRM_UT_DRIVER 0x02
|
|
#define DRM_UT_KMS 0x04
|
|
#define DRM_UT_PRIME 0x08
|
|
#define DRM_UT_ATOMIC 0x10
|
|
#define DRM_UT_VBL 0x20
|
|
#define DRM_UT_STATE 0x40
|
|
|
|
/***********************************************************************/
|
|
/** \name DRM template customization defaults */
|
|
/*@{*/
|
|
|
|
/***********************************************************************/
|
|
/** \name Macros to make printk easier */
|
|
/*@{*/
|
|
|
|
#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__)
|
|
|
|
/**
|
|
* Error output.
|
|
*
|
|
* \param fmt printf() like format string.
|
|
* \param arg arguments
|
|
*/
|
|
#define DRM_DEV_ERROR(dev, fmt, ...) \
|
|
drm_dev_printk(dev, KERN_ERR, DRM_UT_NONE, __func__, " *ERROR*",\
|
|
fmt, ##__VA_ARGS__)
|
|
#define DRM_ERROR(fmt, ...) \
|
|
drm_printk(KERN_ERR, DRM_UT_NONE, fmt, ##__VA_ARGS__)
|
|
|
|
/**
|
|
* Rate limited error output. Like DRM_ERROR() but won't flood the log.
|
|
*
|
|
* \param fmt printf() like format string.
|
|
* \param arg arguments
|
|
*/
|
|
#define DRM_DEV_ERROR_RATELIMITED(dev, fmt, ...) \
|
|
({ \
|
|
static DEFINE_RATELIMIT_STATE(_rs, \
|
|
DEFAULT_RATELIMIT_INTERVAL, \
|
|
DEFAULT_RATELIMIT_BURST); \
|
|
\
|
|
if (__ratelimit(&_rs)) \
|
|
DRM_DEV_ERROR(dev, fmt, ##__VA_ARGS__); \
|
|
})
|
|
#define DRM_ERROR_RATELIMITED(fmt, ...) \
|
|
DRM_DEV_ERROR_RATELIMITED(NULL, fmt, ##__VA_ARGS__)
|
|
|
|
#define DRM_DEV_INFO(dev, fmt, ...) \
|
|
drm_dev_printk(dev, KERN_INFO, DRM_UT_NONE, __func__, "", fmt, \
|
|
##__VA_ARGS__)
|
|
|
|
#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__); \
|
|
} \
|
|
})
|
|
|
|
/**
|
|
* Debug output.
|
|
*
|
|
* \param fmt printf() like format string.
|
|
* \param arg arguments
|
|
*/
|
|
#define DRM_DEV_DEBUG(dev, fmt, args...) \
|
|
drm_dev_printk(dev, KERN_DEBUG, DRM_UT_CORE, __func__, "", fmt, \
|
|
##args)
|
|
#define DRM_DEBUG(fmt, ...) \
|
|
drm_printk(KERN_DEBUG, DRM_UT_CORE, fmt, ##__VA_ARGS__)
|
|
|
|
#define DRM_DEV_DEBUG_DRIVER(dev, fmt, args...) \
|
|
drm_dev_printk(dev, KERN_DEBUG, DRM_UT_DRIVER, __func__, "", \
|
|
fmt, ##args)
|
|
#define DRM_DEBUG_DRIVER(fmt, ...) \
|
|
drm_printk(KERN_DEBUG, DRM_UT_DRIVER, fmt, ##__VA_ARGS__)
|
|
|
|
#define DRM_DEV_DEBUG_KMS(dev, fmt, args...) \
|
|
drm_dev_printk(dev, KERN_DEBUG, DRM_UT_KMS, __func__, "", fmt, \
|
|
##args)
|
|
#define DRM_DEBUG_KMS(fmt, ...) \
|
|
drm_printk(KERN_DEBUG, DRM_UT_KMS, fmt, ##__VA_ARGS__)
|
|
|
|
#define DRM_DEV_DEBUG_PRIME(dev, fmt, args...) \
|
|
drm_dev_printk(dev, KERN_DEBUG, DRM_UT_PRIME, __func__, "", \
|
|
fmt, ##args)
|
|
#define DRM_DEBUG_PRIME(fmt, ...) \
|
|
drm_printk(KERN_DEBUG, DRM_UT_PRIME, fmt, ##__VA_ARGS__)
|
|
|
|
#define DRM_DEV_DEBUG_ATOMIC(dev, fmt, args...) \
|
|
drm_dev_printk(dev, KERN_DEBUG, DRM_UT_ATOMIC, __func__, "", \
|
|
fmt, ##args)
|
|
#define DRM_DEBUG_ATOMIC(fmt, ...) \
|
|
drm_printk(KERN_DEBUG, DRM_UT_ATOMIC, fmt, ##__VA_ARGS__)
|
|
|
|
#define DRM_DEV_DEBUG_VBL(dev, fmt, args...) \
|
|
drm_dev_printk(dev, KERN_DEBUG, DRM_UT_VBL, __func__, "", fmt, \
|
|
##args)
|
|
#define DRM_DEBUG_VBL(fmt, ...) \
|
|
drm_printk(KERN_DEBUG, DRM_UT_VBL, fmt, ##__VA_ARGS__)
|
|
|
|
#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); \
|
|
})
|
|
|
|
/**
|
|
* Rate limited debug output. Like DRM_DEBUG() but won't flood the log.
|
|
*
|
|
* \param fmt printf() like format string.
|
|
* \param arg arguments
|
|
*/
|
|
#define DRM_DEV_DEBUG_RATELIMITED(dev, fmt, args...) \
|
|
DEV__DRM_DEFINE_DEBUG_RATELIMITED(dev, CORE, fmt, ##args)
|
|
#define DRM_DEBUG_RATELIMITED(fmt, args...) \
|
|
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)
|
|
#define DRM_DEBUG_DRIVER_RATELIMITED(fmt, args...) \
|
|
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)
|
|
#define DRM_DEBUG_KMS_RATELIMITED(fmt, args...) \
|
|
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)
|
|
#define DRM_DEBUG_PRIME_RATELIMITED(fmt, args...) \
|
|
DRM_DEV_DEBUG_PRIME_RATELIMITED(NULL, fmt, ##args)
|
|
|
|
/* Format strings and argument splitters to simplify printing
|
|
* various "complex" objects
|
|
*/
|
|
|
|
/*@}*/
|
|
|
|
/***********************************************************************/
|
|
/** \name Internal types and structures */
|
|
/*@{*/
|
|
|
|
#define DRM_IF_VERSION(maj, min) (maj << 16 | min)
|
|
|
|
|
|
/**
|
|
* DRM device structure. This structure represent a complete card that
|
|
* may contain multiple heads.
|
|
*/
|
|
struct drm_device {
|
|
struct list_head legacy_dev_list;/**< list of devices per driver for stealth attach cleanup */
|
|
int if_version; /**< Highest interface version set */
|
|
|
|
/** \name Lifetime Management */
|
|
/*@{ */
|
|
struct kref ref; /**< Object ref-count */
|
|
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 */
|
|
bool registered;
|
|
|
|
/* currently active master for this device. Protected by master_mutex */
|
|
struct drm_master *master;
|
|
|
|
atomic_t unplugged; /**< Flag whether dev is dead */
|
|
struct inode *anon_inode; /**< inode for private address-space */
|
|
char *unique; /**< unique name of the device */
|
|
/*@} */
|
|
|
|
/** \name Locks */
|
|
/*@{ */
|
|
struct mutex struct_mutex; /**< For others */
|
|
struct mutex master_mutex; /**< For drm_minor::master and drm_file::is_master */
|
|
/*@} */
|
|
|
|
/** \name Usage Counters */
|
|
/*@{ */
|
|
int open_count; /**< Outstanding files open, protected by drm_global_mutex. */
|
|
spinlock_t buf_lock; /**< For drm_device::buf_use and a few other things. */
|
|
int buf_use; /**< Buffers in use -- cannot alloc */
|
|
atomic_t buf_alloc; /**< Buffer allocation in progress */
|
|
/*@} */
|
|
|
|
struct mutex filelist_mutex;
|
|
struct list_head filelist;
|
|
|
|
/** \name Memory management */
|
|
/*@{ */
|
|
struct list_head maplist; /**< Linked list of regions */
|
|
struct drm_open_hash map_hash; /**< User token hash table for maps */
|
|
|
|
/** \name Context handle management */
|
|
/*@{ */
|
|
struct list_head ctxlist; /**< Linked list of context handles */
|
|
struct mutex ctxlist_mutex; /**< For ctxlist */
|
|
|
|
struct idr ctx_idr;
|
|
|
|
struct list_head vmalist; /**< List of vmas (for debugging) */
|
|
|
|
/*@} */
|
|
|
|
/** \name DMA support */
|
|
/*@{ */
|
|
struct drm_device_dma *dma; /**< Optional pointer for DMA support */
|
|
/*@} */
|
|
|
|
/** \name Context support */
|
|
/*@{ */
|
|
|
|
__volatile__ long context_flag; /**< Context swapping flag */
|
|
int last_context; /**< Last current context */
|
|
/*@} */
|
|
|
|
/** \name VBLANK IRQ support */
|
|
/*@{ */
|
|
bool irq_enabled;
|
|
int irq;
|
|
|
|
/*
|
|
* 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;
|
|
|
|
/* array of size num_crtcs */
|
|
struct drm_vblank_crtc *vblank;
|
|
|
|
spinlock_t vblank_time_lock; /**< Protects vblank count and time updates during vblank enable/disable */
|
|
spinlock_t vbl_lock;
|
|
|
|
u32 max_vblank_count; /**< size of vblank counter register */
|
|
|
|
/**
|
|
* List of events
|
|
*/
|
|
struct list_head vblank_event_list;
|
|
spinlock_t event_lock;
|
|
|
|
/*@} */
|
|
|
|
struct drm_agp_head *agp; /**< AGP data */
|
|
|
|
struct pci_dev *pdev; /**< PCI device structure */
|
|
#ifdef __alpha__
|
|
struct pci_controller *hose;
|
|
#endif
|
|
|
|
struct drm_sg_mem *sg; /**< Scatter gather memory */
|
|
unsigned int num_crtcs; /**< Number of CRTCs on this device */
|
|
|
|
struct {
|
|
int context;
|
|
struct drm_hw_lock *lock;
|
|
} sigdata;
|
|
|
|
struct drm_local_map *agp_buffer_map;
|
|
unsigned int agp_buffer_token;
|
|
|
|
struct drm_mode_config mode_config; /**< Current mode config */
|
|
|
|
/** \name GEM information */
|
|
/*@{ */
|
|
struct mutex object_name_lock;
|
|
struct idr object_name_idr;
|
|
struct drm_vma_offset_manager *vma_offset_manager;
|
|
/*@} */
|
|
int switch_power_state;
|
|
};
|
|
|
|
/**
|
|
* drm_drv_uses_atomic_modeset - check if the driver implements
|
|
* atomic_commit()
|
|
* @dev: DRM device
|
|
*
|
|
* This check is useful if drivers do not have DRIVER_ATOMIC set but
|
|
* have atomic modesetting internally implemented.
|
|
*/
|
|
static inline bool drm_drv_uses_atomic_modeset(struct drm_device *dev)
|
|
{
|
|
return dev->mode_config.funcs->atomic_commit != NULL;
|
|
}
|
|
|
|
#define DRM_SWITCH_POWER_ON 0
|
|
#define DRM_SWITCH_POWER_OFF 1
|
|
#define DRM_SWITCH_POWER_CHANGING 2
|
|
#define DRM_SWITCH_POWER_DYNAMIC_OFF 3
|
|
|
|
static __inline__ int drm_core_check_feature(struct drm_device *dev,
|
|
int feature)
|
|
{
|
|
return ((dev->driver->driver_features & feature) ? 1 : 0);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
/******************************************************************/
|
|
/** \name Internal function definitions */
|
|
/*@{*/
|
|
|
|
/* Driver support (drm_drv.h) */
|
|
|
|
/*
|
|
* These are exported to drivers so that they can implement fencing using
|
|
* DMA quiscent + idle. DMA quiescent usually requires the hardware lock.
|
|
*/
|
|
|
|
/*@}*/
|
|
|
|
/* 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;
|
|
}
|
|
|
|
/* helper for handling conditionals in various for_each macros */
|
|
#define for_each_if(condition) if (!(condition)) {} else
|
|
|
|
#endif
|