summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordumbbell <dumbbell@FreeBSD.org>2015-04-28 19:35:05 +0000
committerdumbbell <dumbbell@FreeBSD.org>2015-04-28 19:35:05 +0000
commitea79a6539f43803c0c31ce2924f403be84b383cb (patch)
tree5f6306edb9b0d44300b67836b2a0b9b018a4aa15
parent616b358cb6cac89dff87e789620e451b9828c6f3 (diff)
downloadFreeBSD-src-ea79a6539f43803c0c31ce2924f403be84b383cb.zip
FreeBSD-src-ea79a6539f43803c0c31ce2924f403be84b383cb.tar.gz
drm: Update the device-independent code to match Linux 3.8.13
This update brings few features: o Support for the setmaster/dropmaster ioctls. For instance, they are used to run multiple X servers simultaneously. o Support for minor devices. The only user-visible change is a new entry in /dev/dri but it is useless at the moment. This is a first step to support render nodes [1]. The main benefit is to greatly reduce the diff with Linux (at the expense of an unreadable commit diff). Hopefully, next upgrades will be easier. No updates were made to the drivers, beside adapting them to API changes. [1] https://en.wikipedia.org/wiki/Direct_Rendering_Manager#Render_nodes r280814 is merged at the same time to avoid a short window where RANDR might be broken: drm: Import Linux commit 9bc3cd5673d84d29272fa7181a4dfca83cbb48c1 Author: Ville Syrjälä <ville.syrjala@linux.intel.com> Date: Fri May 31 12:17:08 2013 +0000 drm: Sort connector modes based on vrefresh Keeping the modes sorted by vrefresh before the pixel clock makes the mode list somehow more pleasing to the eye. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com> PR: 198936 (r280814) Tested by: Many people MFC of: r280183, r280187 (original commit by glebius), r280814 Relnotes: yes
-rw-r--r--sys/dev/drm2/ati_pcigart.c6
-rw-r--r--sys/dev/drm2/drm.h638
-rw-r--r--sys/dev/drm2/drmP.h2041
-rw-r--r--sys/dev/drm2/drm_agpsupport.c562
-rw-r--r--sys/dev/drm2/drm_atomic.h21
-rw-r--r--sys/dev/drm2/drm_auth.c226
-rw-r--r--sys/dev/drm2/drm_buffer.c4
-rw-r--r--sys/dev/drm2/drm_bufs.c1592
-rw-r--r--sys/dev/drm2/drm_context.c292
-rw-r--r--sys/dev/drm2/drm_crtc.c812
-rw-r--r--sys/dev/drm2/drm_crtc.h261
-rw-r--r--sys/dev/drm2/drm_crtc_helper.c305
-rw-r--r--sys/dev/drm2/drm_crtc_helper.h29
-rw-r--r--sys/dev/drm2/drm_dma.c117
-rw-r--r--sys/dev/drm2/drm_dp_helper.c17
-rw-r--r--sys/dev/drm2/drm_dp_iic_helper.c14
-rw-r--r--sys/dev/drm2/drm_drawable.c173
-rw-r--r--sys/dev/drm2/drm_drv.c1204
-rw-r--r--sys/dev/drm2/drm_edid.c468
-rw-r--r--sys/dev/drm2/drm_edid.h9
-rw-r--r--sys/dev/drm2/drm_edid_modes.h52
-rw-r--r--sys/dev/drm2/drm_fb_helper.c518
-rw-r--r--sys/dev/drm2/drm_fb_helper.h12
-rw-r--r--sys/dev/drm2/drm_fops.c501
-rw-r--r--sys/dev/drm2/drm_fourcc.h14
-rw-r--r--sys/dev/drm2/drm_gem.c441
-rw-r--r--sys/dev/drm2/drm_gem_names.c4
-rw-r--r--sys/dev/drm2/drm_global.c8
-rw-r--r--sys/dev/drm2/drm_hashtab.c10
-rw-r--r--sys/dev/drm2/drm_internal.h43
-rw-r--r--sys/dev/drm2/drm_ioc32.c149
-rw-r--r--sys/dev/drm2/drm_ioctl.c367
-rw-r--r--sys/dev/drm2/drm_irq.c690
-rw-r--r--sys/dev/drm2/drm_lock.c339
-rw-r--r--sys/dev/drm2/drm_memory.c167
-rw-r--r--sys/dev/drm2/drm_mm.c358
-rw-r--r--sys/dev/drm2/drm_mm.h146
-rw-r--r--sys/dev/drm2/drm_mode.h253
-rw-r--r--sys/dev/drm2/drm_modes.c84
-rw-r--r--sys/dev/drm2/drm_os_freebsd.c393
-rw-r--r--sys/dev/drm2/drm_os_freebsd.h278
-rw-r--r--sys/dev/drm2/drm_pci.c354
-rw-r--r--sys/dev/drm2/drm_pciids.h24
-rw-r--r--sys/dev/drm2/drm_sarea.h6
-rw-r--r--sys/dev/drm2/drm_scatter.c101
-rw-r--r--sys/dev/drm2/drm_sman.c352
-rw-r--r--sys/dev/drm2/drm_sman.h181
-rw-r--r--sys/dev/drm2/drm_stub.c471
-rw-r--r--sys/dev/drm2/drm_sysctl.c94
-rw-r--r--sys/dev/drm2/drm_vm.c29
-rw-r--r--sys/dev/drm2/i915/i915_debug.c345
-rw-r--r--sys/dev/drm2/i915/i915_dma.c251
-rw-r--r--sys/dev/drm2/i915/i915_drm.h49
-rw-r--r--sys/dev/drm2/i915/i915_drv.c45
-rw-r--r--sys/dev/drm2/i915/i915_drv.h11
-rw-r--r--sys/dev/drm2/i915/i915_gem.c77
-rw-r--r--sys/dev/drm2/i915/i915_gem_context.c4
-rw-r--r--sys/dev/drm2/i915/i915_gem_evict.c4
-rw-r--r--sys/dev/drm2/i915/i915_gem_execbuffer.c7
-rw-r--r--sys/dev/drm2/i915/i915_gem_gtt.c2
-rw-r--r--sys/dev/drm2/i915/i915_gem_tiling.c5
-rw-r--r--sys/dev/drm2/i915/i915_ioc32.c4
-rw-r--r--sys/dev/drm2/i915/i915_irq.c8
-rw-r--r--sys/dev/drm2/i915/i915_suspend.c25
-rw-r--r--sys/dev/drm2/i915/intel_crt.c3
-rw-r--r--sys/dev/drm2/i915/intel_display.c42
-rw-r--r--sys/dev/drm2/i915/intel_dp.c17
-rw-r--r--sys/dev/drm2/i915/intel_fb.c15
-rw-r--r--sys/dev/drm2/i915/intel_hdmi.c6
-rw-r--r--sys/dev/drm2/i915/intel_iic.c36
-rw-r--r--sys/dev/drm2/i915/intel_lvds.c4
-rw-r--r--sys/dev/drm2/i915/intel_modes.c9
-rw-r--r--sys/dev/drm2/i915/intel_opregion.c12
-rw-r--r--sys/dev/drm2/i915/intel_overlay.c4
-rw-r--r--sys/dev/drm2/i915/intel_panel.c4
-rw-r--r--sys/dev/drm2/i915/intel_ringbuffer.c5
-rw-r--r--sys/dev/drm2/i915/intel_sdvo.c51
-rw-r--r--sys/dev/drm2/i915/intel_tv.c26
-rw-r--r--sys/dev/drm2/radeon/atom.c18
-rw-r--r--sys/dev/drm2/radeon/atombios_crtc.c9
-rw-r--r--sys/dev/drm2/radeon/atombios_dp.c14
-rw-r--r--sys/dev/drm2/radeon/atombios_encoders.c20
-rw-r--r--sys/dev/drm2/radeon/atombios_i2c.c19
-rw-r--r--sys/dev/drm2/radeon/cayman_blit_shaders.c6
-rw-r--r--sys/dev/drm2/radeon/evergreen.c159
-rw-r--r--sys/dev/drm2/radeon/evergreen_blit_shaders.c6
-rw-r--r--sys/dev/drm2/radeon/evergreen_cs.c14
-rw-r--r--sys/dev/drm2/radeon/evergreen_reg.h2
-rw-r--r--sys/dev/drm2/radeon/ni.c89
-rw-r--r--sys/dev/drm2/radeon/nid.h4
-rw-r--r--sys/dev/drm2/radeon/r100.c121
-rw-r--r--sys/dev/drm2/radeon/r200.c2
-rw-r--r--sys/dev/drm2/radeon/r300.c12
-rw-r--r--sys/dev/drm2/radeon/r300_cmdbuf.c4
-rw-r--r--sys/dev/drm2/radeon/r420.c2
-rw-r--r--sys/dev/drm2/radeon/r500_reg.h6
-rw-r--r--sys/dev/drm2/radeon/r600.c38
-rw-r--r--sys/dev/drm2/radeon/r600_blit.c2
-rw-r--r--sys/dev/drm2/radeon/r600_blit_shaders.c8
-rw-r--r--sys/dev/drm2/radeon/r600_cp.c47
-rw-r--r--sys/dev/drm2/radeon/r600_cs.c29
-rw-r--r--sys/dev/drm2/radeon/r600_hdmi.c5
-rw-r--r--sys/dev/drm2/radeon/r600d.h6
-rw-r--r--sys/dev/drm2/radeon/radeon.h21
-rw-r--r--sys/dev/drm2/radeon/radeon_acpi.c10
-rw-r--r--sys/dev/drm2/radeon/radeon_agp.c8
-rw-r--r--sys/dev/drm2/radeon/radeon_atombios.c87
-rw-r--r--sys/dev/drm2/radeon/radeon_atpx_handler.c506
-rw-r--r--sys/dev/drm2/radeon/radeon_benchmark.c16
-rw-r--r--sys/dev/drm2/radeon/radeon_bios.c47
-rw-r--r--sys/dev/drm2/radeon/radeon_clocks.c38
-rw-r--r--sys/dev/drm2/radeon/radeon_combios.c74
-rw-r--r--sys/dev/drm2/radeon/radeon_connectors.c105
-rw-r--r--sys/dev/drm2/radeon/radeon_cp.c29
-rw-r--r--sys/dev/drm2/radeon/radeon_cs.c14
-rw-r--r--sys/dev/drm2/radeon/radeon_device.c88
-rw-r--r--sys/dev/drm2/radeon/radeon_display.c36
-rw-r--r--sys/dev/drm2/radeon/radeon_drm.h2
-rw-r--r--sys/dev/drm2/radeon/radeon_drv.c219
-rw-r--r--sys/dev/drm2/radeon/radeon_drv.h11
-rw-r--r--sys/dev/drm2/radeon/radeon_fb.c24
-rw-r--r--sys/dev/drm2/radeon/radeon_fence.c28
-rw-r--r--sys/dev/drm2/radeon/radeon_gart.c21
-rw-r--r--sys/dev/drm2/radeon/radeon_gem.c20
-rw-r--r--sys/dev/drm2/radeon/radeon_i2c.c82
-rw-r--r--sys/dev/drm2/radeon/radeon_ioc32.c6
-rw-r--r--sys/dev/drm2/radeon/radeon_irq_kms.c69
-rw-r--r--sys/dev/drm2/radeon/radeon_irq_kms.h2
-rw-r--r--sys/dev/drm2/radeon/radeon_kms.c24
-rw-r--r--sys/dev/drm2/radeon/radeon_legacy_crtc.c4
-rw-r--r--sys/dev/drm2/radeon/radeon_legacy_encoders.c31
-rw-r--r--sys/dev/drm2/radeon/radeon_legacy_tv.c4
-rw-r--r--sys/dev/drm2/radeon/radeon_mem.c8
-rw-r--r--sys/dev/drm2/radeon/radeon_object.c20
-rw-r--r--sys/dev/drm2/radeon/radeon_object.h4
-rw-r--r--sys/dev/drm2/radeon/radeon_pm.c92
-rw-r--r--sys/dev/drm2/radeon/radeon_ring.c29
-rw-r--r--sys/dev/drm2/radeon/radeon_sa.c2
-rw-r--r--sys/dev/drm2/radeon/radeon_semaphore.c2
-rw-r--r--sys/dev/drm2/radeon/radeon_state.c44
-rw-r--r--sys/dev/drm2/radeon/radeon_test.c12
-rw-r--r--sys/dev/drm2/radeon/radeon_ttm.c42
-rw-r--r--sys/dev/drm2/radeon/rs400.c9
-rw-r--r--sys/dev/drm2/radeon/rs600.c81
-rw-r--r--sys/dev/drm2/radeon/rs690.c2
-rw-r--r--sys/dev/drm2/radeon/rv515.c69
-rw-r--r--sys/dev/drm2/radeon/rv770.c7
-rw-r--r--sys/dev/drm2/radeon/si.c55
-rw-r--r--sys/dev/drm2/radeon/si_blit_shaders.c2
-rw-r--r--sys/dev/drm2/radeon/sid.h2
-rw-r--r--sys/dev/drm2/ttm/ttm_bo.c12
-rw-r--r--sys/dev/drm2/ttm/ttm_bo_util.c2
-rw-r--r--sys/dev/drm2/ttm/ttm_bo_vm.c10
-rw-r--r--sys/dev/drm2/ttm/ttm_lock.c30
-rw-r--r--sys/modules/Makefile2
-rw-r--r--sys/modules/drm2/Makefile7
-rw-r--r--sys/modules/drm2/drm2/Makefile10
-rw-r--r--sys/modules/drm2/radeonkms/Makefile22
158 files changed, 10649 insertions, 8497 deletions
diff --git a/sys/dev/drm2/ati_pcigart.c b/sys/dev/drm2/ati_pcigart.c
index 5d3033f..57fda4d 100644
--- a/sys/dev/drm2/ati_pcigart.c
+++ b/sys/dev/drm2/ati_pcigart.c
@@ -42,7 +42,7 @@ static int drm_ati_alloc_pcigart_table(struct drm_device *dev,
struct drm_ati_pcigart_info *gart_info)
{
gart_info->table_handle = drm_pci_alloc(dev, gart_info->table_size,
- PAGE_SIZE, 0xFFFFFFFFUL);
+ PAGE_SIZE, BUS_SPACE_MAXADDR);
if (gart_info->table_handle == NULL)
return -ENOMEM;
@@ -97,6 +97,7 @@ int drm_ati_pcigart_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info
return 1;
}
+EXPORT_SYMBOL(drm_ati_pcigart_cleanup);
int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *gart_info)
{
@@ -197,7 +198,7 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga
}
ret = 1;
-#if defined(__i386) || defined(__amd64)
+#if defined(__i386__) || defined(__x86_64__)
wbinvd();
#else
mb();
@@ -208,3 +209,4 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga
gart_info->bus_addr = bus_address;
return ret;
}
+EXPORT_SYMBOL(drm_ati_pcigart_init);
diff --git a/sys/dev/drm2/drm.h b/sys/dev/drm2/drm.h
index acb988c..7c40ac0 100644
--- a/sys/dev/drm2/drm.h
+++ b/sys/dev/drm2/drm.h
@@ -36,69 +36,31 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-/**
- * \mainpage
- *
- * The Direct Rendering Manager (DRM) is a device-independent kernel-level
- * device driver that provides support for the XFree86 Direct Rendering
- * Infrastructure (DRI).
- *
- * The DRM supports the Direct Rendering Infrastructure (DRI) in four major
- * ways:
- * -# The DRM provides synchronized access to the graphics hardware via
- * the use of an optimized two-tiered lock.
- * -# The DRM enforces the DRI security policy for access to the graphics
- * hardware by only allowing authenticated X11 clients access to
- * restricted regions of memory.
- * -# The DRM provides a generic DMA engine, complete with multiple
- * queues and the ability to detect the need for an OpenGL context
- * switch.
- * -# The DRM is extensible via the use of small device-specific modules
- * that rely extensively on the API exported by the DRM module.
- *
- */
-
#ifndef _DRM_H_
#define _DRM_H_
-#ifndef __user
-#define __user
-#endif
-#ifndef __iomem
-#define __iomem
-#endif
+#if defined(__linux__)
-#ifdef __GNUC__
-# define DEPRECATED __attribute__ ((deprecated))
-#else
-# define DEPRECATED
-#endif
+#include <linux/types.h>
+#include <asm/ioctl.h>
+typedef unsigned int drm_handle_t;
-#if defined(__linux__)
-#include <asm/ioctl.h> /* For _IO* macros */
-#define DRM_IOCTL_NR(n) _IOC_NR(n)
-#define DRM_IOC_VOID _IOC_NONE
-#define DRM_IOC_READ _IOC_READ
-#define DRM_IOC_WRITE _IOC_WRITE
-#define DRM_IOC_READWRITE _IOC_READ|_IOC_WRITE
-#define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size)
-#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
-#include <sys/ioccom.h>
-#define DRM_IOCTL_NR(n) ((n) & 0xff)
-#define DRM_IOC_VOID IOC_VOID
-#define DRM_IOC_READ IOC_OUT
-#define DRM_IOC_WRITE IOC_IN
-#define DRM_IOC_READWRITE IOC_INOUT
-#define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size)
-#endif
+#else /* One of the BSDs */
-#ifdef __OpenBSD__
-#define DRM_MAJOR 81
-#endif
-#if defined(__linux__) || defined(__NetBSD__)
-#define DRM_MAJOR 226
+#include <sys/ioccom.h>
+#include <sys/types.h>
+typedef int8_t __s8;
+typedef uint8_t __u8;
+typedef int16_t __s16;
+typedef uint16_t __u16;
+typedef int32_t __s32;
+typedef uint32_t __u32;
+typedef int64_t __s64;
+typedef uint64_t __u64;
+typedef unsigned long drm_handle_t;
+
+#include <dev/drm2/drm_os_freebsd.h>
#endif
-#define DRM_MAX_MINOR 15
#define DRM_NAME "drm" /**< Name in kernel, /dev, and /proc */
#define DRM_MIN_ORDER 5 /**< At least 2^5 bytes = 32 bytes */
@@ -111,20 +73,14 @@ __FBSDID("$FreeBSD$");
#define _DRM_LOCK_IS_CONT(lock) ((lock) & _DRM_LOCK_CONT)
#define _DRM_LOCKING_CONTEXT(lock) ((lock) & ~(_DRM_LOCK_HELD|_DRM_LOCK_CONT))
-#if defined(__linux__)
-typedef unsigned int drm_handle_t;
-#else
-#include <sys/types.h>
-typedef unsigned long drm_handle_t; /**< To mapped regions */
-#endif
-typedef unsigned int drm_context_t; /**< GLXContext handle */
+typedef unsigned int drm_context_t;
typedef unsigned int drm_drawable_t;
-typedef unsigned int drm_magic_t; /**< Magic for authentication */
+typedef unsigned int drm_magic_t;
/**
* Cliprect.
*
- * \warning If you change this structure, make sure you change
+ * \warning: If you change this structure, make sure you change
* XF86DRIClipRectRec in the server as well
*
* \note KW: Actually it's illegal to change either for
@@ -138,6 +94,14 @@ struct drm_clip_rect {
};
/**
+ * Drawable information.
+ */
+struct drm_drawable_info {
+ unsigned int num_rects;
+ struct drm_clip_rect *rects;
+};
+
+/**
* Texture region,
*/
struct drm_tex_region {
@@ -160,22 +124,6 @@ struct drm_hw_lock {
char padding[60]; /**< Pad to cache line */
};
-/* This is beyond ugly, and only works on GCC. However, it allows me to use
- * drm.h in places (i.e., in the X-server) where I can't use size_t. The real
- * fix is to use uint32_t instead of size_t, but that fix will break existing
- * LP64 (i.e., PowerPC64, SPARC64, IA-64, Alpha, etc.) systems. That *will*
- * eventually happen, though. I chose 'unsigned long' to be the fallback type
- * because that works on all the platforms I know about. Hopefully, the
- * real fix will happen before that bites us.
- */
-
-#ifdef __SIZE_TYPE__
-# define DRM_SIZE_T __SIZE_TYPE__
-#else
-# warning "__SIZE_TYPE__ not defined. Assuming sizeof(size_t) == sizeof(unsigned long)!"
-# define DRM_SIZE_T unsigned long
-#endif
-
/**
* DRM_IOCTL_VERSION ioctl argument type.
*
@@ -185,12 +133,12 @@ struct drm_version {
int version_major; /**< Major version */
int version_minor; /**< Minor version */
int version_patchlevel; /**< Patch level */
- DRM_SIZE_T name_len; /**< Length of name buffer */
- char __user *name; /**< Name of driver */
- DRM_SIZE_T date_len; /**< Length of date buffer */
- char __user *date; /**< User-space buffer to hold date */
- DRM_SIZE_T desc_len; /**< Length of desc buffer */
- char __user *desc; /**< User-space buffer to hold desc */
+ size_t name_len; /**< Length of name buffer */
+ char __user *name; /**< Name of driver */
+ size_t date_len; /**< Length of date buffer */
+ char __user *date; /**< User-space buffer to hold date */
+ size_t desc_len; /**< Length of desc buffer */
+ char __user *desc; /**< User-space buffer to hold desc */
};
/**
@@ -199,12 +147,10 @@ struct drm_version {
* \sa drmGetBusid() and drmSetBusId().
*/
struct drm_unique {
- DRM_SIZE_T unique_len; /**< Length of unique */
- char __user *unique; /**< Unique name for driver instantiation */
+ size_t unique_len; /**< Length of unique */
+ char __user *unique; /**< Unique name for driver instantiation */
};
-#undef DRM_SIZE_T
-
struct drm_list {
int count; /**< Length of user-space structures */
struct drm_version __user *version;
@@ -239,7 +185,7 @@ enum drm_map_type {
_DRM_AGP = 3, /**< AGP/GART */
_DRM_SCATTER_GATHER = 4, /**< Scatter/gather memory for PCI DMA */
_DRM_CONSISTENT = 5, /**< Consistent memory for PCI DMA */
- _DRM_GEM = 6 /**< GEM */
+ _DRM_GEM = 6, /**< GEM object */
};
/**
@@ -388,8 +334,8 @@ struct drm_buf_desc {
enum {
_DRM_PAGE_ALIGN = 0x01, /**< Align on page boundaries for DMA */
_DRM_AGP_BUFFER = 0x02, /**< Buffer is in AGP space */
- _DRM_SG_BUFFER = 0x04, /**< Scatter/gather memory buffer */
- _DRM_FB_BUFFER = 0x08, /**< Buffer is in frame buffer */
+ _DRM_SG_BUFFER = 0x04, /**< Scatter/gather memory buffer */
+ _DRM_FB_BUFFER = 0x08, /**< Buffer is in frame buffer */
_DRM_PCI_BUFFER_RO = 0x10 /**< Map PCI DMA buffer read-only */
} flags;
unsigned long agp_start; /**<
@@ -402,8 +348,8 @@ struct drm_buf_desc {
* DRM_IOCTL_INFO_BUFS ioctl argument type.
*/
struct drm_buf_info {
- int count; /**< Number of buffers described in list */
- struct drm_buf_desc __user *list; /**< List of buffer descriptions */
+ int count; /**< Entries in list */
+ struct drm_buf_desc __user *list;
};
/**
@@ -431,11 +377,7 @@ struct drm_buf_pub {
*/
struct drm_buf_map {
int count; /**< Length of the buffer list */
-#if defined(__cplusplus)
- void __user *c_virtual;
-#else
void __user *virtual; /**< Mmap'd area in user-virtual */
-#endif
struct drm_buf_pub __user *list; /**< Buffer information */
};
@@ -454,7 +396,7 @@ struct drm_dma {
enum drm_dma_flags flags; /**< Flags */
int request_count; /**< Number of buffers requested */
int request_size; /**< Desired size for buffers */
- int __user *request_indices; /**< Buffer information */
+ int __user *request_indices; /**< Buffer information */
int __user *request_sizes;
int granted_count; /**< Number of buffers granted */
};
@@ -525,12 +467,13 @@ struct drm_irq_busid {
enum drm_vblank_seq_type {
_DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */
_DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */
+ /* bits 1-6 are reserved for high crtcs */
_DRM_VBLANK_HIGH_CRTC_MASK = 0x0000003e,
_DRM_VBLANK_EVENT = 0x4000000, /**< Send event instead of blocking */
- _DRM_VBLANK_FLIP = 0x8000000, /**< Scheduled buffer swap should flip */
+ _DRM_VBLANK_FLIP = 0x8000000, /**< Scheduled buffer swap should flip */
_DRM_VBLANK_NEXTONMISS = 0x10000000, /**< If missed, wait for next vblank */
_DRM_VBLANK_SECONDARY = 0x20000000, /**< Secondary display controller */
- _DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking */
+ _DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking, unsupported */
};
#define _DRM_VBLANK_HIGH_CRTC_SHIFT 1
@@ -561,7 +504,6 @@ union drm_wait_vblank {
struct drm_wait_vblank_reply reply;
};
-
#define _DRM_PRE_MODESET 1
#define _DRM_POST_MODESET 2
@@ -571,8 +513,8 @@ union drm_wait_vblank {
* \sa drmModesetCtl().
*/
struct drm_modeset_ctl {
- uint32_t crtc;
- uint32_t cmd;
+ __u32 crtc;
+ __u32 cmd;
};
/**
@@ -617,16 +559,14 @@ struct drm_agp_info {
int agp_version_major;
int agp_version_minor;
unsigned long mode;
- unsigned long aperture_base; /**< physical address */
- unsigned long aperture_size; /**< bytes */
- unsigned long memory_allowed; /**< bytes */
+ unsigned long aperture_base; /* physical address */
+ unsigned long aperture_size; /* bytes */
+ unsigned long memory_allowed; /* bytes */
unsigned long memory_used;
- /** \name PCI information */
- /*@{ */
+ /* PCI information */
unsigned short id_vendor;
unsigned short id_device;
- /*@} */
};
/**
@@ -647,386 +587,52 @@ struct drm_set_version {
int drm_dd_minor;
};
-#define DRM_FENCE_FLAG_EMIT 0x00000001
-#define DRM_FENCE_FLAG_SHAREABLE 0x00000002
-/**
- * On hardware with no interrupt events for operation completion,
- * indicates that the kernel should sleep while waiting for any blocking
- * operation to complete rather than spinning.
- *
- * Has no effect otherwise.
- */
-#define DRM_FENCE_FLAG_WAIT_LAZY 0x00000004
-#define DRM_FENCE_FLAG_NO_USER 0x00000010
-
-/* Reserved for driver use */
-#define DRM_FENCE_MASK_DRIVER 0xFF000000
-
-#define DRM_FENCE_TYPE_EXE 0x00000001
-
-struct drm_fence_arg {
- unsigned int handle;
- unsigned int fence_class;
- unsigned int type;
- unsigned int flags;
- unsigned int signaled;
- unsigned int error;
- unsigned int sequence;
- unsigned int pad64;
- uint64_t expand_pad[2]; /* Future expansion */
-};
-
-/* Buffer permissions, referring to how the GPU uses the buffers.
- * these translate to fence types used for the buffers.
- * Typically a texture buffer is read, A destination buffer is write and
- * a command (batch-) buffer is exe. Can be or-ed together.
- */
-
-#define DRM_BO_FLAG_READ (1ULL << 0)
-#define DRM_BO_FLAG_WRITE (1ULL << 1)
-#define DRM_BO_FLAG_EXE (1ULL << 2)
-
-/*
- * All of the bits related to access mode
- */
-#define DRM_BO_MASK_ACCESS (DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | DRM_BO_FLAG_EXE)
-/*
- * Status flags. Can be read to determine the actual state of a buffer.
- * Can also be set in the buffer mask before validation.
- */
-
-/*
- * Mask: Never evict this buffer. Not even with force. This type of buffer is only
- * available to root and must be manually removed before buffer manager shutdown
- * or lock.
- * Flags: Acknowledge
- */
-#define DRM_BO_FLAG_NO_EVICT (1ULL << 4)
-
-/*
- * Mask: Require that the buffer is placed in mappable memory when validated.
- * If not set the buffer may or may not be in mappable memory when validated.
- * Flags: If set, the buffer is in mappable memory.
- */
-#define DRM_BO_FLAG_MAPPABLE (1ULL << 5)
-
-/* Mask: The buffer should be shareable with other processes.
- * Flags: The buffer is shareable with other processes.
- */
-#define DRM_BO_FLAG_SHAREABLE (1ULL << 6)
-
-/* Mask: If set, place the buffer in cache-coherent memory if available.
- * If clear, never place the buffer in cache coherent memory if validated.
- * Flags: The buffer is currently in cache-coherent memory.
- */
-#define DRM_BO_FLAG_CACHED (1ULL << 7)
-
-/* Mask: Make sure that every time this buffer is validated,
- * it ends up on the same location provided that the memory mask is the same.
- * The buffer will also not be evicted when claiming space for
- * other buffers. Basically a pinned buffer but it may be thrown out as
- * part of buffer manager shutdown or locking.
- * Flags: Acknowledge.
- */
-#define DRM_BO_FLAG_NO_MOVE (1ULL << 8)
-
-/* Mask: Make sure the buffer is in cached memory when mapped. In conjunction
- * with DRM_BO_FLAG_CACHED it also allows the buffer to be bound into the GART
- * with unsnooped PTEs instead of snooped, by using chipset-specific cache
- * flushing at bind time. A better name might be DRM_BO_FLAG_TT_UNSNOOPED,
- * as the eviction to local memory (TTM unbind) on map is just a side effect
- * to prevent aggressive cache prefetch from the GPU disturbing the cache
- * management that the DRM is doing.
- *
- * Flags: Acknowledge.
- * Buffers allocated with this flag should not be used for suballocators
- * This type may have issues on CPUs with over-aggressive caching
- * http://marc.info/?l=linux-kernel&m=102376926732464&w=2
- */
-#define DRM_BO_FLAG_CACHED_MAPPED (1ULL << 19)
-
-
-/* Mask: Force DRM_BO_FLAG_CACHED flag strictly also if it is set.
- * Flags: Acknowledge.
- */
-#define DRM_BO_FLAG_FORCE_CACHING (1ULL << 13)
-
-/*
- * Mask: Force DRM_BO_FLAG_MAPPABLE flag strictly also if it is clear.
- * Flags: Acknowledge.
- */
-#define DRM_BO_FLAG_FORCE_MAPPABLE (1ULL << 14)
-#define DRM_BO_FLAG_TILE (1ULL << 15)
-
-/*
- * Memory type flags that can be or'ed together in the mask, but only
- * one appears in flags.
- */
-
-/* System memory */
-#define DRM_BO_FLAG_MEM_LOCAL (1ULL << 24)
-/* Translation table memory */
-#define DRM_BO_FLAG_MEM_TT (1ULL << 25)
-/* Vram memory */
-#define DRM_BO_FLAG_MEM_VRAM (1ULL << 26)
-/* Up to the driver to define. */
-#define DRM_BO_FLAG_MEM_PRIV0 (1ULL << 27)
-#define DRM_BO_FLAG_MEM_PRIV1 (1ULL << 28)
-#define DRM_BO_FLAG_MEM_PRIV2 (1ULL << 29)
-#define DRM_BO_FLAG_MEM_PRIV3 (1ULL << 30)
-#define DRM_BO_FLAG_MEM_PRIV4 (1ULL << 31)
-/* We can add more of these now with a 64-bit flag type */
-
-/*
- * This is a mask covering all of the memory type flags; easier to just
- * use a single constant than a bunch of | values. It covers
- * DRM_BO_FLAG_MEM_LOCAL through DRM_BO_FLAG_MEM_PRIV4
- */
-#define DRM_BO_MASK_MEM 0x00000000FF000000ULL
-/*
- * This adds all of the CPU-mapping options in with the memory
- * type to label all bits which change how the page gets mapped
- */
-#define DRM_BO_MASK_MEMTYPE (DRM_BO_MASK_MEM | \
- DRM_BO_FLAG_CACHED_MAPPED | \
- DRM_BO_FLAG_CACHED | \
- DRM_BO_FLAG_MAPPABLE)
-
-/* Driver-private flags */
-#define DRM_BO_MASK_DRIVER 0xFFFF000000000000ULL
-
-/*
- * Don't block on validate and map. Instead, return EBUSY.
- */
-#define DRM_BO_HINT_DONT_BLOCK 0x00000002
-/*
- * Don't place this buffer on the unfenced list. This means
- * that the buffer will not end up having a fence associated
- * with it as a result of this operation
- */
-#define DRM_BO_HINT_DONT_FENCE 0x00000004
-/**
- * On hardware with no interrupt events for operation completion,
- * indicates that the kernel should sleep while waiting for any blocking
- * operation to complete rather than spinning.
- *
- * Has no effect otherwise.
- */
-#define DRM_BO_HINT_WAIT_LAZY 0x00000008
-/*
- * The client has compute relocations refering to this buffer using the
- * offset in the presumed_offset field. If that offset ends up matching
- * where this buffer lands, the kernel is free to skip executing those
- * relocations
- */
-#define DRM_BO_HINT_PRESUMED_OFFSET 0x00000010
-
-#define DRM_BO_INIT_MAGIC 0xfe769812
-#define DRM_BO_INIT_MAJOR 1
-#define DRM_BO_INIT_MINOR 0
-#define DRM_BO_INIT_PATCH 0
-
-
-struct drm_bo_info_req {
- uint64_t mask;
- uint64_t flags;
- unsigned int handle;
- unsigned int hint;
- unsigned int fence_class;
- unsigned int desired_tile_stride;
- unsigned int tile_info;
- unsigned int pad64;
- uint64_t presumed_offset;
-};
-
-struct drm_bo_create_req {
- uint64_t flags;
- uint64_t size;
- uint64_t buffer_start;
- unsigned int hint;
- unsigned int page_alignment;
-};
-
-
-/*
- * Reply flags
- */
-
-#define DRM_BO_REP_BUSY 0x00000001
-
-struct drm_bo_info_rep {
- uint64_t flags;
- uint64_t proposed_flags;
- uint64_t size;
- uint64_t offset;
- uint64_t arg_handle;
- uint64_t buffer_start;
- unsigned int handle;
- unsigned int fence_flags;
- unsigned int rep_flags;
- unsigned int page_alignment;
- unsigned int desired_tile_stride;
- unsigned int hw_tile_stride;
- unsigned int tile_info;
- unsigned int pad64;
- uint64_t expand_pad[4]; /*Future expansion */
-};
-
-struct drm_bo_arg_rep {
- struct drm_bo_info_rep bo_info;
- int ret;
- unsigned int pad64;
-};
-
-struct drm_bo_create_arg {
- union {
- struct drm_bo_create_req req;
- struct drm_bo_info_rep rep;
- } d;
-};
-
-struct drm_bo_handle_arg {
- unsigned int handle;
-};
-
-struct drm_bo_reference_info_arg {
- union {
- struct drm_bo_handle_arg req;
- struct drm_bo_info_rep rep;
- } d;
-};
-
-struct drm_bo_map_wait_idle_arg {
- union {
- struct drm_bo_info_req req;
- struct drm_bo_info_rep rep;
- } d;
-};
-
-struct drm_bo_op_req {
- enum {
- drm_bo_validate,
- drm_bo_fence,
- drm_bo_ref_fence,
- } op;
- unsigned int arg_handle;
- struct drm_bo_info_req bo_req;
-};
-
-
-struct drm_bo_op_arg {
- uint64_t next;
- union {
- struct drm_bo_op_req req;
- struct drm_bo_arg_rep rep;
- } d;
- int handled;
- unsigned int pad64;
-};
-
-
-#define DRM_BO_MEM_LOCAL 0
-#define DRM_BO_MEM_TT 1
-#define DRM_BO_MEM_VRAM 2
-#define DRM_BO_MEM_PRIV0 3
-#define DRM_BO_MEM_PRIV1 4
-#define DRM_BO_MEM_PRIV2 5
-#define DRM_BO_MEM_PRIV3 6
-#define DRM_BO_MEM_PRIV4 7
-
-#define DRM_BO_MEM_TYPES 8 /* For now. */
-
-#define DRM_BO_LOCK_UNLOCK_BM (1 << 0)
-#define DRM_BO_LOCK_IGNORE_NO_EVICT (1 << 1)
-
-struct drm_bo_version_arg {
- uint32_t major;
- uint32_t minor;
- uint32_t patchlevel;
-};
-
-struct drm_mm_type_arg {
- unsigned int mem_type;
- unsigned int lock_flags;
-};
-
-struct drm_mm_init_arg {
- unsigned int magic;
- unsigned int major;
- unsigned int minor;
- unsigned int mem_type;
- uint64_t p_offset;
- uint64_t p_size;
-};
-
-struct drm_mm_info_arg {
- unsigned int mem_type;
- uint64_t p_size;
-};
-
+/** DRM_IOCTL_GEM_CLOSE ioctl argument type */
struct drm_gem_close {
/** Handle of the object to be closed. */
- uint32_t handle;
- uint32_t pad;
+ __u32 handle;
+ __u32 pad;
};
+/** DRM_IOCTL_GEM_FLINK ioctl argument type */
struct drm_gem_flink {
/** Handle for the object being named */
- uint32_t handle;
+ __u32 handle;
/** Returned global name */
- uint32_t name;
+ __u32 name;
};
+/** DRM_IOCTL_GEM_OPEN ioctl argument type */
struct drm_gem_open {
/** Name of object being opened */
- uint32_t name;
+ __u32 name;
/** Returned handle for the object */
- uint32_t handle;
-
+ __u32 handle;
+
/** Returned size of the object */
- uint64_t size;
+ __u64 size;
};
+/** DRM_IOCTL_GET_CAP ioctl argument type */
struct drm_get_cap {
- uint64_t capability;
- uint64_t value;
+ __u64 capability;
+ __u64 value;
};
-struct drm_event {
- uint32_t type;
- uint32_t length;
-};
+#define DRM_CLOEXEC O_CLOEXEC
+struct drm_prime_handle {
+ __u32 handle;
-#define DRM_EVENT_VBLANK 0x01
-#define DRM_EVENT_FLIP_COMPLETE 0x02
+ /** Flags.. only applicable for handle->fd */
+ __u32 flags;
-struct drm_event_vblank {
- struct drm_event base;
- uint64_t user_data;
- uint32_t tv_sec;
- uint32_t tv_usec;
- uint32_t sequence;
- uint32_t reserved;
+ /** Returned dmabuf file descriptor */
+ __s32 fd;
};
-#define DRM_CAP_DUMB_BUFFER 0x1
-#define DRM_CAP_VBLANK_HIGH_CRTC 0x2
-#define DRM_CAP_DUMB_PREFERRED_DEPTH 0x3
-#define DRM_CAP_DUMB_PREFER_SHADOW 0x4
-#define DRM_CAP_PRIME 0x5
-#define DRM_CAP_TIMESTAMP_MONOTONIC 0x6
-
-#define DRM_PRIME_CAP_IMPORT 0x1
-#define DRM_PRIME_CAP_EXPORT 0x2
-
-#include "drm_mode.h"
-
-/**
- * \name Ioctls Definitions
- */
-/*@{*/
+#include <dev/drm2/drm_mode.h>
#define DRM_IOCTL_BASE 'd'
#define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr)
@@ -1042,12 +648,10 @@ struct drm_event_vblank {
#define DRM_IOCTL_GET_CLIENT DRM_IOWR(0x05, struct drm_client)
#define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, struct drm_stats)
#define DRM_IOCTL_SET_VERSION DRM_IOWR(0x07, struct drm_set_version)
-#define DRM_IOCTL_MODESET_CTL DRM_IOW(0x08, struct drm_modeset_ctl)
-
+#define DRM_IOCTL_MODESET_CTL DRM_IOW(0x08, struct drm_modeset_ctl)
#define DRM_IOCTL_GEM_CLOSE DRM_IOW (0x09, struct drm_gem_close)
#define DRM_IOCTL_GEM_FLINK DRM_IOWR(0x0a, struct drm_gem_flink)
#define DRM_IOCTL_GEM_OPEN DRM_IOWR(0x0b, struct drm_gem_open)
-
#define DRM_IOCTL_GET_CAP DRM_IOWR(0x0c, struct drm_get_cap)
#define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, struct drm_unique)
@@ -1065,7 +669,7 @@ struct drm_event_vblank {
#define DRM_IOCTL_RM_MAP DRM_IOW( 0x1b, struct drm_map)
#define DRM_IOCTL_SET_SAREA_CTX DRM_IOW( 0x1c, struct drm_ctx_priv_map)
-#define DRM_IOCTL_GET_SAREA_CTX DRM_IOWR(0x1d, struct drm_ctx_priv_map)
+#define DRM_IOCTL_GET_SAREA_CTX DRM_IOWR(0x1d, struct drm_ctx_priv_map)
#define DRM_IOCTL_SET_MASTER DRM_IO(0x1e)
#define DRM_IOCTL_DROP_MASTER DRM_IO(0x1f)
@@ -1084,7 +688,8 @@ struct drm_event_vblank {
#define DRM_IOCTL_UNLOCK DRM_IOW( 0x2b, struct drm_lock)
#define DRM_IOCTL_FINISH DRM_IOW( 0x2c, struct drm_lock)
-#define DRM_IOCTL_GEM_PRIME_OPEN DRM_IOWR(0x2e, struct drm_gem_open)
+#define DRM_IOCTL_PRIME_HANDLE_TO_FD DRM_IOWR(0x2d, struct drm_prime_handle)
+#define DRM_IOCTL_PRIME_FD_TO_HANDLE DRM_IOWR(0x2e, struct drm_prime_handle)
#define DRM_IOCTL_AGP_ACQUIRE DRM_IO( 0x30)
#define DRM_IOCTL_AGP_RELEASE DRM_IO( 0x31)
@@ -1100,7 +705,7 @@ struct drm_event_vblank {
#define DRM_IOCTL_WAIT_VBLANK DRM_IOWR(0x3a, union drm_wait_vblank)
-#define DRM_IOCTL_UPDATE_DRAW DRM_IOW(0x3f, struct drm_update_draw)
+#define DRM_IOCTL_UPDATE_DRAW DRM_IOW(0x3f, struct drm_update_draw)
#define DRM_IOCTL_MODE_GETRESOURCES DRM_IOWR(0xA0, struct drm_mode_card_res)
#define DRM_IOCTL_MODE_GETCRTC DRM_IOWR(0xA1, struct drm_mode_crtc)
@@ -1122,43 +727,16 @@ struct drm_event_vblank {
#define DRM_IOCTL_MODE_PAGE_FLIP DRM_IOWR(0xB0, struct drm_mode_crtc_page_flip)
#define DRM_IOCTL_MODE_DIRTYFB DRM_IOWR(0xB1, struct drm_mode_fb_dirty_cmd)
-#define DRM_IOCTL_MODE_CREATE_DUMB DRM_IOWR(0xB2, struct drm_mode_create_dumb)
-#define DRM_IOCTL_MODE_MAP_DUMB DRM_IOWR(0xB3, struct drm_mode_map_dumb)
-#define DRM_IOCTL_MODE_DESTROY_DUMB DRM_IOWR(0xB4, struct drm_mode_destroy_dumb)
+#define DRM_IOCTL_MODE_CREATE_DUMB DRM_IOWR(0xB2, struct drm_mode_create_dumb)
+#define DRM_IOCTL_MODE_MAP_DUMB DRM_IOWR(0xB3, struct drm_mode_map_dumb)
+#define DRM_IOCTL_MODE_DESTROY_DUMB DRM_IOWR(0xB4, struct drm_mode_destroy_dumb)
#define DRM_IOCTL_MODE_GETPLANERESOURCES DRM_IOWR(0xB5, struct drm_mode_get_plane_res)
-#define DRM_IOCTL_MODE_GETPLANE DRM_IOWR(0xB6, struct drm_mode_get_plane)
-#define DRM_IOCTL_MODE_SETPLANE DRM_IOWR(0xB7, struct drm_mode_set_plane)
+#define DRM_IOCTL_MODE_GETPLANE DRM_IOWR(0xB6, struct drm_mode_get_plane)
+#define DRM_IOCTL_MODE_SETPLANE DRM_IOWR(0xB7, struct drm_mode_set_plane)
#define DRM_IOCTL_MODE_ADDFB2 DRM_IOWR(0xB8, struct drm_mode_fb_cmd2)
#define DRM_IOCTL_MODE_OBJ_GETPROPERTIES DRM_IOWR(0xB9, struct drm_mode_obj_get_properties)
#define DRM_IOCTL_MODE_OBJ_SETPROPERTY DRM_IOWR(0xBA, struct drm_mode_obj_set_property)
-#define DRM_IOCTL_MM_INIT DRM_IOWR(0xc0, struct drm_mm_init_arg)
-#define DRM_IOCTL_MM_TAKEDOWN DRM_IOWR(0xc1, struct drm_mm_type_arg)
-#define DRM_IOCTL_MM_LOCK DRM_IOWR(0xc2, struct drm_mm_type_arg)
-#define DRM_IOCTL_MM_UNLOCK DRM_IOWR(0xc3, struct drm_mm_type_arg)
-
-#define DRM_IOCTL_FENCE_CREATE DRM_IOWR(0xc4, struct drm_fence_arg)
-#define DRM_IOCTL_FENCE_REFERENCE DRM_IOWR(0xc6, struct drm_fence_arg)
-#define DRM_IOCTL_FENCE_UNREFERENCE DRM_IOWR(0xc7, struct drm_fence_arg)
-#define DRM_IOCTL_FENCE_SIGNALED DRM_IOWR(0xc8, struct drm_fence_arg)
-#define DRM_IOCTL_FENCE_FLUSH DRM_IOWR(0xc9, struct drm_fence_arg)
-#define DRM_IOCTL_FENCE_WAIT DRM_IOWR(0xca, struct drm_fence_arg)
-#define DRM_IOCTL_FENCE_EMIT DRM_IOWR(0xcb, struct drm_fence_arg)
-#define DRM_IOCTL_FENCE_BUFFERS DRM_IOWR(0xcc, struct drm_fence_arg)
-
-#define DRM_IOCTL_BO_CREATE DRM_IOWR(0xcd, struct drm_bo_create_arg)
-#define DRM_IOCTL_BO_MAP DRM_IOWR(0xcf, struct drm_bo_map_wait_idle_arg)
-#define DRM_IOCTL_BO_UNMAP DRM_IOWR(0xd0, struct drm_bo_handle_arg)
-#define DRM_IOCTL_BO_REFERENCE DRM_IOWR(0xd1, struct drm_bo_reference_info_arg)
-#define DRM_IOCTL_BO_UNREFERENCE DRM_IOWR(0xd2, struct drm_bo_handle_arg)
-#define DRM_IOCTL_BO_SETSTATUS DRM_IOWR(0xd3, struct drm_bo_map_wait_idle_arg)
-#define DRM_IOCTL_BO_INFO DRM_IOWR(0xd4, struct drm_bo_reference_info_arg)
-#define DRM_IOCTL_BO_WAIT_IDLE DRM_IOWR(0xd5, struct drm_bo_map_wait_idle_arg)
-#define DRM_IOCTL_BO_VERSION DRM_IOR(0xd6, struct drm_bo_version_arg)
-#define DRM_IOCTL_MM_INFO DRM_IOWR(0xd7, struct drm_mm_info_arg)
-
-/*@}*/
-
/**
* Device specific ioctls should only be in their respective headers
* The device specific ioctl range is from 0x40 to 0x99.
@@ -1168,11 +746,51 @@ struct drm_event_vblank {
* drmCommandReadWrite().
*/
#define DRM_COMMAND_BASE 0x40
-#define DRM_COMMAND_END 0xA0
+#define DRM_COMMAND_END 0xA0
+
+/**
+ * Header for events written back to userspace on the drm fd. The
+ * type defines the type of event, the length specifies the total
+ * length of the event (including the header), and user_data is
+ * typically a 64 bit value passed with the ioctl that triggered the
+ * event. A read on the drm fd will always only return complete
+ * events, that is, if for example the read buffer is 100 bytes, and
+ * there are two 64 byte events pending, only one will be returned.
+ *
+ * Event types 0 - 0x7fffffff are generic drm events, 0x80000000 and
+ * up are chipset specific.
+ */
+struct drm_event {
+ __u32 type;
+ __u32 length;
+};
+
+#define DRM_EVENT_VBLANK 0x01
+#define DRM_EVENT_FLIP_COMPLETE 0x02
+
+struct drm_event_vblank {
+ struct drm_event base;
+ __u64 user_data;
+ __u32 tv_sec;
+ __u32 tv_usec;
+ __u32 sequence;
+ __u32 reserved;
+};
+
+#define DRM_CAP_DUMB_BUFFER 0x1
+#define DRM_CAP_VBLANK_HIGH_CRTC 0x2
+#define DRM_CAP_DUMB_PREFERRED_DEPTH 0x3
+#define DRM_CAP_DUMB_PREFER_SHADOW 0x4
+#define DRM_CAP_PRIME 0x5
+#define DRM_CAP_TIMESTAMP_MONOTONIC 0x6
+
+#define DRM_PRIME_CAP_IMPORT 0x1
+#define DRM_PRIME_CAP_EXPORT 0x2
/* typedef area */
#ifndef __KERNEL__
typedef struct drm_clip_rect drm_clip_rect_t;
+typedef struct drm_drawable_info drm_drawable_info_t;
typedef struct drm_tex_region drm_tex_region_t;
typedef struct drm_hw_lock drm_hw_lock_t;
typedef struct drm_version drm_version_t;
@@ -1206,16 +824,12 @@ typedef struct drm_update_draw drm_update_draw_t;
typedef struct drm_auth drm_auth_t;
typedef struct drm_irq_busid drm_irq_busid_t;
typedef enum drm_vblank_seq_type drm_vblank_seq_type_t;
+
typedef struct drm_agp_buffer drm_agp_buffer_t;
typedef struct drm_agp_binding drm_agp_binding_t;
typedef struct drm_agp_info drm_agp_info_t;
typedef struct drm_scatter_gather drm_scatter_gather_t;
typedef struct drm_set_version drm_set_version_t;
-
-typedef struct drm_fence_arg drm_fence_arg_t;
-typedef struct drm_mm_type_arg drm_mm_type_arg_t;
-typedef struct drm_mm_init_arg drm_mm_init_arg_t;
-typedef enum drm_bo_type drm_bo_type_t;
#endif
#endif
diff --git a/sys/dev/drm2/drmP.h b/sys/dev/drm2/drmP.h
index e33ab88..f028d81 100644
--- a/sys/dev/drm2/drmP.h
+++ b/sys/dev/drm2/drmP.h
@@ -100,14 +100,17 @@ __FBSDID("$FreeBSD$");
#include <dev/drm2/drm_sarea.h>
#include <dev/drm2/drm_atomic.h>
-#include <dev/drm2/drm_internal.h>
#include <dev/drm2/drm_linux_list.h>
#include <dev/drm2/drm_gem_names.h>
+#include <dev/drm2/drm_os_freebsd.h>
+
+#define __OS_HAS_AGP (defined(CONFIG_AGP) || (defined(CONFIG_AGP_MODULE) && defined(MODULE)))
+#define __OS_HAS_MTRR (defined(CONFIG_MTRR))
+
struct drm_file;
struct drm_device;
-#include <dev/drm2/drm_os_freebsd.h>
#include <dev/drm2/drm_hashtab.h>
#include <dev/drm2/drm_mm.h>
@@ -146,244 +149,116 @@ struct drm_device;
#define DRIVER_GEM 0x1000
#define DRIVER_MODESET 0x2000
#define DRIVER_PRIME 0x4000
-#define DRIVER_LOCKLESS_IRQ 0x8000
-
-
-#define DRM_HASH_SIZE 16 /* Size of key hash table */
-#define DRM_KERNEL_CONTEXT 0 /* Change drm_resctx if changed */
-#define DRM_RESERVED_CONTEXTS 1 /* Change drm_resctx if changed */
-
-#define DRM_GEM_MAPPING_MASK (3ULL << 62)
-#define DRM_GEM_MAPPING_KEY (2ULL << 62) /* Non-canonical address form */
-#define DRM_GEM_MAX_IDX 0x3fffff
-#define DRM_GEM_MAPPING_IDX(o) (((o) >> 40) & DRM_GEM_MAX_IDX)
-#define DRM_GEM_MAPPING_OFF(i) (((uint64_t)(i)) << 40)
-#define DRM_GEM_MAPPING_MAPOFF(o) \
- ((o) & ~(DRM_GEM_MAPPING_OFF(DRM_GEM_MAX_IDX) | DRM_GEM_MAPPING_KEY))
-
-MALLOC_DECLARE(DRM_MEM_DMA);
-MALLOC_DECLARE(DRM_MEM_SAREA);
-MALLOC_DECLARE(DRM_MEM_DRIVER);
-MALLOC_DECLARE(DRM_MEM_MAGIC);
-MALLOC_DECLARE(DRM_MEM_IOCTLS);
-MALLOC_DECLARE(DRM_MEM_MAPS);
-MALLOC_DECLARE(DRM_MEM_BUFS);
-MALLOC_DECLARE(DRM_MEM_SEGS);
-MALLOC_DECLARE(DRM_MEM_PAGES);
-MALLOC_DECLARE(DRM_MEM_FILES);
-MALLOC_DECLARE(DRM_MEM_QUEUES);
-MALLOC_DECLARE(DRM_MEM_CMDS);
-MALLOC_DECLARE(DRM_MEM_MAPPINGS);
-MALLOC_DECLARE(DRM_MEM_BUFLISTS);
-MALLOC_DECLARE(DRM_MEM_AGPLISTS);
-MALLOC_DECLARE(DRM_MEM_CTXBITMAP);
-MALLOC_DECLARE(DRM_MEM_SGLISTS);
-MALLOC_DECLARE(DRM_MEM_DRAWABLE);
-MALLOC_DECLARE(DRM_MEM_MM);
-MALLOC_DECLARE(DRM_MEM_HASHTAB);
-MALLOC_DECLARE(DRM_MEM_KMS);
-SYSCTL_DECL(_hw_drm);
-
-#define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8)
+#define DRIVER_BUS_PCI 0x1
+#define DRIVER_BUS_PLATFORM 0x2
+#define DRIVER_BUS_USB 0x3
/***********************************************************************/
-/** \name Internal types and structures */
+/** \name Begin the DRM... */
/*@{*/
-#define DRM_ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
-#define DRM_MIN(a,b) ((a)<(b)?(a):(b))
-#define DRM_MAX(a,b) ((a)>(b)?(a):(b))
-
-#define DRM_IF_VERSION(maj, min) (maj << 16 | min)
-
-#define __OS_HAS_AGP 1
-
-#define DRM_DEV_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP)
-#define DRM_DEV_UID 0
-#define DRM_DEV_GID 0
+#define DRM_DEBUG_CODE 2 /**< Include debugging code if > 1, then
+ also include looping detection. */
-#define wait_queue_head_t atomic_t
-#define DRM_WAKEUP(w) wakeup((void *)w)
-#define DRM_WAKEUP_INT(w) wakeup(w)
-#define DRM_INIT_WAITQUEUE(queue) do {(void)(queue);} while (0)
+#define DRM_MAGIC_HASH_ORDER 4 /**< Size of key hash table. Must be power of 2. */
+#define DRM_KERNEL_CONTEXT 0 /**< Change drm_resctx if changed */
+#define DRM_RESERVED_CONTEXTS 1 /**< Change drm_resctx if changed */
+#define DRM_LOOPING_LIMIT 5000000
+#define DRM_TIME_SLICE (HZ/20) /**< Time slice for GLXContexts */
+#define DRM_LOCK_SLICE 1 /**< Time slice for lock, in jiffies */
-#define DRM_CURPROC curthread
-#define DRM_STRUCTPROC struct thread
-#define DRM_SPINTYPE struct mtx
-#define DRM_SPININIT(l,name) mtx_init(l, name, NULL, MTX_DEF)
-#define DRM_SPINUNINIT(l) mtx_destroy(l)
-#define DRM_SPINLOCK(l) mtx_lock(l)
-#define DRM_SPINUNLOCK(u) mtx_unlock(u)
-#define DRM_SPINLOCK_IRQSAVE(l, irqflags) do { \
- mtx_lock(l); \
- (void)irqflags; \
-} while (0)
-#define DRM_SPINUNLOCK_IRQRESTORE(u, irqflags) mtx_unlock(u)
-#define DRM_SPINLOCK_ASSERT(l) mtx_assert(l, MA_OWNED)
-#define DRM_CURRENTPID curthread->td_proc->p_pid
-#define DRM_LOCK(dev) sx_xlock(&(dev)->dev_struct_lock)
-#define DRM_UNLOCK(dev) sx_xunlock(&(dev)->dev_struct_lock)
-#define DRM_LOCK_SLEEP(dev, chan, flags, msg, timeout) \
- (sx_sleep((chan), &(dev)->dev_struct_lock, (flags), (msg), (timeout)))
-#if defined(INVARIANTS)
-#define DRM_LOCK_ASSERT(dev) sx_assert(&(dev)->dev_struct_lock, SA_XLOCKED)
-#define DRM_UNLOCK_ASSERT(dev) sx_assert(&(dev)->dev_struct_lock, SA_UNLOCKED)
-#else
-#define DRM_LOCK_ASSERT(d)
-#define DRM_UNLOCK_ASSERT(d)
-#endif
+#define DRM_FLAG_DEBUG 0x01
-#define DRM_SYSCTL_HANDLER_ARGS (SYSCTL_HANDLER_ARGS)
-
-#define DRM_IRQ_ARGS void *arg
-typedef void irqreturn_t;
-#define IRQ_HANDLED /* nothing */
-#define IRQ_NONE /* nothing */
+#define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8)
+#define DRM_MAP_HASH_OFFSET 0x10000000
-enum {
- DRM_IS_NOT_AGP,
- DRM_IS_AGP,
- DRM_MIGHT_BE_AGP
-};
-#define DRM_AGP_MEM struct agp_memory_info
+/*@}*/
-#define drm_get_device_from_kdev(_kdev) (_kdev->si_drv1)
+/***********************************************************************/
+/** \name Macros to make printk easier */
+/*@{*/
-#define PAGE_ALIGN(addr) round_page(addr)
-/* DRM_SUSER returns true if the user is superuser */
-#define DRM_SUSER(p) (priv_check(p, PRIV_DRIVER) == 0)
-#define DRM_AGP_FIND_DEVICE() agp_find_device()
-#define DRM_MTRR_WC MDF_WRITECOMBINE
-#define jiffies ticks
-#define jiffies_to_msecs(x) (((int64_t)(x)) * 1000 / hz)
-#define msecs_to_jiffies(x) (((int64_t)(x)) * hz / 1000)
-#define time_after(a,b) ((long)(b) - (long)(a) < 0)
-#define time_after_eq(a,b) ((long)(b) - (long)(a) <= 0)
-#define drm_msleep(x, msg) pause((msg), ((int64_t)(x)) * hz / 1000)
-
-/* DRM_READMEMORYBARRIER() prevents reordering of reads.
- * DRM_WRITEMEMORYBARRIER() prevents reordering of writes.
- * DRM_MEMORYBARRIER() prevents reordering of reads and writes.
+/**
+ * Error output.
+ *
+ * \param fmt printf() like format string.
+ * \param arg arguments
*/
-#define DRM_READMEMORYBARRIER() rmb()
-#define DRM_WRITEMEMORYBARRIER() wmb()
-#define DRM_MEMORYBARRIER() mb()
-
-#define DRM_READ8(map, offset) \
- *(volatile u_int8_t *)(((vm_offset_t)(map)->virtual) + \
- (vm_offset_t)(offset))
-#define DRM_READ16(map, offset) \
- le16toh(*(volatile u_int16_t *)(((vm_offset_t)(map)->virtual) + \
- (vm_offset_t)(offset)))
-#define DRM_READ32(map, offset) \
- le32toh(*(volatile u_int32_t *)(((vm_offset_t)(map)->virtual) + \
- (vm_offset_t)(offset)))
-#define DRM_READ64(map, offset) \
- le64toh(*(volatile u_int64_t *)(((vm_offset_t)(map)->virtual) + \
- (vm_offset_t)(offset)))
-#define DRM_WRITE8(map, offset, val) \
- *(volatile u_int8_t *)(((vm_offset_t)(map)->virtual) + \
- (vm_offset_t)(offset)) = val
-#define DRM_WRITE16(map, offset, val) \
- *(volatile u_int16_t *)(((vm_offset_t)(map)->virtual) + \
- (vm_offset_t)(offset)) = htole16(val)
-#define DRM_WRITE32(map, offset, val) \
- *(volatile u_int32_t *)(((vm_offset_t)(map)->virtual) + \
- (vm_offset_t)(offset)) = htole32(val)
-#define DRM_WRITE64(map, offset, val) \
- *(volatile u_int64_t *)(((vm_offset_t)(map)->virtual) + \
- (vm_offset_t)(offset)) = htole64(val)
-
-#define DRM_VERIFYAREA_READ( uaddr, size ) \
- (!useracc(__DECONST(caddr_t, uaddr), size, VM_PROT_READ))
-
-#define DRM_COPY_TO_USER(user, kern, size) \
- copyout(kern, user, size)
-#define DRM_COPY_FROM_USER(kern, user, size) \
- copyin(user, kern, size)
-#define DRM_COPY_FROM_USER_UNCHECKED(arg1, arg2, arg3) \
- copyin(arg2, arg1, arg3)
-#define DRM_COPY_TO_USER_UNCHECKED(arg1, arg2, arg3) \
- copyout(arg2, arg1, arg3)
-#define DRM_GET_USER_UNCHECKED(val, uaddr) \
- ((val) = fuword32(uaddr), 0)
-
-#define DRM_GET_PRIV_SAREA(_dev, _ctx, _map) do { \
- (_map) = (_dev)->context_sareas[_ctx]; \
-} while(0)
-
-#define LOCK_TEST_WITH_RETURN(dev, file_priv) \
-do { \
- if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) || \
- dev->lock.file_priv != file_priv) { \
- DRM_ERROR("%s called without lock held\n", \
- __FUNCTION__); \
- return EINVAL; \
- } \
-} while (0)
-
-/* Returns -errno to shared code */
-#define DRM_WAIT_ON( ret, queue, timeout, condition ) \
-for ( ret = 0 ; !ret && !(condition) ; ) { \
- DRM_UNLOCK(dev); \
- mtx_lock(&dev->irq_lock); \
- if (!(condition)) \
- ret = -mtx_sleep(&(queue), &dev->irq_lock, \
- PCATCH, "drmwtq", (timeout)); \
- mtx_unlock(&dev->irq_lock); \
- DRM_LOCK(dev); \
-}
-
#define DRM_ERROR(fmt, ...) \
printf("error: [" DRM_NAME ":pid%d:%s] *ERROR* " fmt, \
DRM_CURRENTPID, __func__ , ##__VA_ARGS__)
+#define DRM_WARNING(fmt, ...) printf("warning: [" DRM_NAME "] " fmt , ##__VA_ARGS__)
#define DRM_INFO(fmt, ...) printf("info: [" DRM_NAME "] " fmt , ##__VA_ARGS__)
+/**
+ * Debug output.
+ *
+ * \param fmt printf() like format string.
+ * \param arg arguments
+ */
#define DRM_DEBUG(fmt, ...) do { \
- if ((drm_debug_flag & DRM_DEBUGBITS_DEBUG) != 0) \
+ if ((drm_debug & DRM_DEBUGBITS_DEBUG) != 0) \
printf("[" DRM_NAME ":pid%d:%s] " fmt, DRM_CURRENTPID, \
__func__ , ##__VA_ARGS__); \
} while (0)
#define DRM_DEBUG_KMS(fmt, ...) do { \
- if ((drm_debug_flag & DRM_DEBUGBITS_KMS) != 0) \
+ if ((drm_debug & DRM_DEBUGBITS_KMS) != 0) \
printf("[" DRM_NAME ":KMS:pid%d:%s] " fmt, DRM_CURRENTPID,\
__func__ , ##__VA_ARGS__); \
} while (0)
#define DRM_DEBUG_DRIVER(fmt, ...) do { \
- if ((drm_debug_flag & DRM_DEBUGBITS_KMS) != 0) \
+ if ((drm_debug & DRM_DEBUGBITS_KMS) != 0) \
printf("[" DRM_NAME ":KMS:pid%d:%s] " fmt, DRM_CURRENTPID,\
__func__ , ##__VA_ARGS__); \
} while (0)
-#define dev_err(dev, fmt, ...) \
- device_printf((dev), "error: " fmt, ## __VA_ARGS__)
-#define dev_warn(dev, fmt, ...) \
- device_printf((dev), "warning: " fmt, ## __VA_ARGS__)
-#define dev_info(dev, fmt, ...) \
- device_printf((dev), "info: " fmt, ## __VA_ARGS__)
-#define dev_dbg(dev, fmt, ...) do { \
- if ((drm_debug_flag& DRM_DEBUGBITS_KMS) != 0) { \
- device_printf((dev), "debug: " fmt, ## __VA_ARGS__); \
- } \
+/*@}*/
+
+/***********************************************************************/
+/** \name Internal types and structures */
+/*@{*/
+
+#define DRM_ARRAY_SIZE(x) ARRAY_SIZE(x)
+
+#define DRM_LEFTCOUNT(x) (((x)->rp + (x)->count - (x)->wp) % ((x)->count + 1))
+#define DRM_BUFCOUNT(x) ((x)->count - DRM_LEFTCOUNT(x))
+
+#define DRM_IF_VERSION(maj, min) (maj << 16 | min)
+
+/**
+ * Test that the hardware lock is held by the caller, returning otherwise.
+ *
+ * \param dev DRM device.
+ * \param filp file pointer of the caller.
+ */
+#define LOCK_TEST_WITH_RETURN( dev, _file_priv ) \
+do { \
+ if (!_DRM_LOCK_IS_HELD(_file_priv->master->lock.hw_lock->lock) || \
+ _file_priv->master->lock.file_priv != _file_priv) { \
+ DRM_ERROR( "%s called without lock held, held %d owner %p %p\n",\
+ __func__, _DRM_LOCK_IS_HELD(_file_priv->master->lock.hw_lock->lock),\
+ _file_priv->master->lock.file_priv, _file_priv); \
+ return -EINVAL; \
+ } \
} while (0)
-typedef struct drm_pci_id_list
-{
- int vendor;
- int device;
- long driver_private;
- char *name;
-} drm_pci_id_list_t;
+/**
+ * Ioctl function type.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private pointer.
+ * \param cmd command.
+ * \param arg argument.
+ */
+typedef int drm_ioctl_t(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
-struct drm_msi_blacklist_entry
-{
- int vendor;
- int device;
-};
+#define DRM_IOCTL_NR(n) ((n) & 0xff)
+#define DRM_MAJOR 226
#define DRM_AUTH 0x1
#define DRM_MASTER 0x2
@@ -391,36 +266,34 @@ struct drm_msi_blacklist_entry
#define DRM_CONTROL_ALLOW 0x8
#define DRM_UNLOCKED 0x10
-typedef struct drm_ioctl_desc {
+struct drm_ioctl_desc {
unsigned long cmd;
- int (*func)(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
int flags;
+ drm_ioctl_t *func;
unsigned int cmd_drv;
-} drm_ioctl_desc_t;
+};
/**
* Creates a driver or general drm_ioctl_desc array entry for the given
* ioctl, for use by drm_ioctl().
*/
-#define DRM_IOCTL_DEF(ioctl, func, flags) \
- [DRM_IOCTL_NR(ioctl)] = {ioctl, func, flags}
+
+#define DRM_IOCTL_DEF(ioctl, _func, _flags) \
+ [DRM_IOCTL_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, .cmd_drv = 0}
#define DRM_IOCTL_DEF_DRV(ioctl, _func, _flags) \
[DRM_IOCTL_NR(DRM_##ioctl)] = {.cmd = DRM_##ioctl, .func = _func, .flags = _flags, .cmd_drv = DRM_IOCTL_##ioctl}
-typedef struct drm_magic_entry {
- drm_magic_t magic;
- struct drm_file *priv;
- struct drm_magic_entry *next;
-} drm_magic_entry_t;
-
-typedef struct drm_magic_head {
- struct drm_magic_entry *head;
- struct drm_magic_entry *tail;
-} drm_magic_head_t;
+struct drm_magic_entry {
+ struct list_head head;
+ struct drm_hash_item hash_item;
+ struct drm_file *priv;
+};
-typedef struct drm_buf {
+/**
+ * DMA buffer.
+ */
+struct drm_buf {
int idx; /**< Index into master buflist */
int total; /**< Buffer size */
int order; /**< log-base-2(total) */
@@ -445,16 +318,23 @@ typedef struct drm_buf {
int dev_priv_size; /**< Size of buffer private storage */
void *dev_private; /**< Per-buffer private storage */
-} drm_buf_t;
-
-typedef struct drm_freelist {
- int initialized; /* Freelist in use */
- atomic_t count; /* Number of free buffers */
- drm_buf_t *next; /* End pointer */
+};
- int low_mark; /* Low water mark */
- int high_mark; /* High water mark */
-} drm_freelist_t;
+struct drm_freelist {
+ int initialized; /**< Freelist in use */
+ atomic_t count; /**< Number of free buffers */
+ struct drm_buf *next; /**< End pointer */
+
+#ifdef FREEBSD_NOTYET
+ wait_queue_head_t waiting; /**< Processes waiting on free bufs */
+#endif /* defined(FREEBSD_NOTYET) */
+ int low_mark; /**< Low water mark */
+ int high_mark; /**< High water mark */
+#ifdef FREEBSD_NOTYET
+ atomic_t wfh; /**< If waiting for high mark */
+ spinlock_t lock;
+#endif /* defined(FREEBSD_NOTYET) */
+};
typedef struct drm_dma_handle {
void *vaddr;
@@ -463,16 +343,19 @@ typedef struct drm_dma_handle {
bus_dmamap_t map;
} drm_dma_handle_t;
-typedef struct drm_buf_entry {
- int buf_size;
- int buf_count;
- drm_buf_t *buflist;
- int seg_count;
- drm_dma_handle_t **seglist;
- int page_order;
+/**
+ * Buffer entry. There is one of this for each buffer size order.
+ */
+struct drm_buf_entry {
+ int buf_size; /**< size */
+ int buf_count; /**< number of buffers */
+ struct drm_buf *buflist; /**< buffer list */
+ int seg_count;
+ int page_order;
+ struct drm_dma_handle **seglist;
- drm_freelist_t freelist;
-} drm_buf_entry_t;
+ struct drm_freelist freelist;
+};
/* Event queued up for userspace to read */
struct drm_pending_event {
@@ -487,53 +370,53 @@ struct drm_pending_event {
/* initial implementaton using a linked list - todo hashtab */
struct drm_prime_file_private {
struct list_head head;
-#ifdef DUMBBELL_WIP
- struct mutex lock;
-#endif /* DUMBBELL_WIP */
+ struct mtx lock;
};
-typedef TAILQ_HEAD(drm_file_list, drm_file) drm_file_list_t;
struct drm_file {
- TAILQ_ENTRY(drm_file) link;
- struct drm_device *dev;
- int authenticated;
- int master;
- pid_t pid;
- uid_t uid;
- drm_magic_t magic;
- unsigned long ioctl_count;
-
- void *driver_priv;
+ int authenticated;
+ pid_t pid;
+ uid_t uid;
+ drm_magic_t magic;
+ unsigned long ioctl_count;
+ struct list_head lhead;
+ struct drm_minor *minor;
+ unsigned long lock_count;
+
+ void *driver_priv;
struct drm_gem_names object_names;
- int is_master;
- struct drm_master *masterp;
-
- struct list_head fbs;
+ int is_master; /* this file private is a master for a minor */
+ struct drm_master *master; /* master this node is currently associated with
+ N.B. not always minor->master */
+ struct list_head fbs;
- struct list_head event_list;
- int event_space;
- struct selinfo event_poll;
+ struct selinfo event_poll;
+ struct list_head event_list;
+ int event_space;
struct drm_prime_file_private prime;
};
-typedef struct drm_lock_data {
- struct drm_hw_lock *hw_lock; /* Hardware lock */
- struct drm_file *file_priv; /* Unique identifier of holding process (NULL is kernel)*/
- int lock_queue; /* Queue of blocked processes */
- unsigned long lock_time; /* Time of last lock in jiffies */
-} drm_lock_data_t;
-
-/* This structure, in the struct drm_device, is always initialized while the
- * device
- * is open. dev->dma_lock protects the incrementing of dev->buf_use, which
- * when set marks that no further bufs may be allocated until device teardown
- * occurs (when the last open of the device has closed). The high/low
- * watermarks of bufs are only touched by the X Server, and thus not
- * concurrently accessed, so no locking is needed.
+/**
+ * Lock data.
+ */
+struct drm_lock_data {
+ struct drm_hw_lock *hw_lock; /**< Hardware lock */
+ /** Private of lock holder's file (NULL=kernel) */
+ struct drm_file *file_priv;
+ wait_queue_head_t lock_queue; /**< Queue of blocked processes */
+ unsigned long lock_time; /**< Time of last lock in jiffies */
+ struct mtx spinlock;
+ uint32_t kernel_waiters;
+ uint32_t user_waiters;
+ int idle_has_lock;
+};
+
+/**
+ * DMA data.
*/
-typedef struct drm_device_dma {
+struct drm_device_dma {
struct drm_buf_entry bufs[DRM_MAX_ORDER + 1]; /**< buffers, grouped by their size order */
int buf_count; /**< total number of buffers */
@@ -549,68 +432,90 @@ typedef struct drm_device_dma {
_DRM_DMA_USE_PCI_RO = 0x08
} flags;
-} drm_device_dma_t;
-
-typedef struct drm_agp_mem {
- void *handle;
- unsigned long bound; /* address */
- int pages;
- struct drm_agp_mem *prev;
- struct drm_agp_mem *next;
-} drm_agp_mem_t;
-
-typedef struct drm_agp_head {
- device_t agpdev;
- struct agp_info info;
- const char *chipset;
- drm_agp_mem_t *memory;
- unsigned long mode;
- int enabled;
- int acquired;
- unsigned long base;
- int mtrr;
- int cant_use_aperture;
- unsigned long page_mask;
-} drm_agp_head_t;
-
-typedef struct drm_sg_mem {
+};
+
+/**
+ * AGP memory entry. Stored as a doubly linked list.
+ */
+struct drm_agp_mem {
+ unsigned long handle; /**< handle */
+ DRM_AGP_MEM *memory;
+ unsigned long bound; /**< address */
+ int pages;
+ struct list_head head;
+};
+
+/**
+ * AGP data.
+ *
+ * \sa drm_agp_init() and drm_device::agp.
+ */
+struct drm_agp_head {
+ DRM_AGP_KERN agp_info; /**< AGP device information */
+ struct list_head memory;
+ unsigned long mode; /**< AGP mode */
+ device_t bridge;
+ int enabled; /**< whether the AGP bus as been enabled */
+ int acquired; /**< whether the AGP device has been acquired */
+ unsigned long base;
+ int agp_mtrr;
+ int cant_use_aperture;
+};
+
+/**
+ * Scatter-gather memory.
+ */
+struct drm_sg_mem {
vm_offset_t vaddr;
vm_paddr_t *busaddr;
vm_pindex_t pages;
-} drm_sg_mem_t;
+};
+
+struct drm_sigdata {
+ int context;
+ struct drm_hw_lock *lock;
+};
+/**
+ * Kernel side of a mapping
+ */
#define DRM_MAP_HANDLE_BITS (sizeof(void *) == 4 ? 4 : 24)
#define DRM_MAP_HANDLE_SHIFT (sizeof(void *) * 8 - DRM_MAP_HANDLE_BITS)
-typedef TAILQ_HEAD(drm_map_list, drm_local_map) drm_map_list_t;
-
-typedef struct drm_local_map {
- unsigned long offset; /* Physical address (0 for SAREA) */
- unsigned long size; /* Physical size (bytes) */
- enum drm_map_type type; /* Type of memory mapped */
- enum drm_map_flags flags; /* Flags */
- void *handle; /* User-space: "Handle" to pass to mmap */
- /* Kernel-space: kernel-virtual address */
- int mtrr; /* Boolean: MTRR used */
+
+struct drm_local_map {
+ resource_size_t offset; /**< Requested physical address (0 for SAREA)*/
+ unsigned long size; /**< Requested physical size (bytes) */
+ enum drm_map_type type; /**< Type of memory to map */
+ enum drm_map_flags flags; /**< Flags */
+ void *handle; /**< User-space: "Handle" to pass to mmap() */
+ /**< Kernel-space: kernel-virtual address */
+ int mtrr; /**< MTRR slot used */
+
/* Private data */
- int rid; /* PCI resource ID for bus_space */
- void *virtual; /* Kernel-space: kernel-virtual address */
- struct resource *bsr;
- bus_space_tag_t bst;
- bus_space_handle_t bsh;
drm_dma_handle_t *dmah;
- TAILQ_ENTRY(drm_local_map) link;
-} drm_local_map_t;
+};
-struct drm_vblank_info {
- wait_queue_head_t queue; /* vblank wait queue */
- atomic_t count; /* number of VBLANK interrupts */
- /* (driver must alloc the right number of counters) */
- atomic_t refcount; /* number of users of vblank interrupts */
- u32 last; /* protected by dev->vbl_lock, used */
- /* for wraparound handling */
- int enabled; /* so we don't call enable more than */
- /* once per disable */
- int inmodeset; /* Display driver is setting mode */
+typedef struct drm_local_map drm_local_map_t;
+
+/**
+ * Mappings list
+ */
+struct drm_map_list {
+ struct list_head head; /**< list head */
+ struct drm_hash_item hash;
+ struct drm_local_map *map; /**< mapping */
+ uint64_t user_token;
+ struct drm_master *master;
+ struct drm_mm_node *file_offset_node; /**< fake offset */
+};
+
+/**
+ * Context handle list
+ */
+struct drm_ctx_list {
+ struct list_head head; /**< list head */
+ drm_context_t handle; /**< context handle */
+ struct drm_file *tag; /**< associated fd private data */
};
/* location of GART table */
@@ -627,29 +532,30 @@ struct drm_ati_pcigart_info {
void *addr;
dma_addr_t bus_addr;
dma_addr_t table_mask;
- dma_addr_t member_mask;
struct drm_dma_handle *table_handle;
- drm_local_map_t mapping;
+ struct drm_local_map mapping;
int table_size;
- struct drm_dma_handle *dmah; /* handle for ATI PCIGART table */
+ struct drm_dma_handle *dmah; /* handle for ATI PCIGART table FIXME */
};
-typedef vm_paddr_t resource_size_t;
-
/**
* GEM specific mm private for tracking GEM objects
*/
struct drm_gem_mm {
- struct drm_open_hash offset_hash; /**< User token hash table for maps */
struct unrhdr *idxunr;
+ struct drm_open_hash offset_hash; /**< User token hash table for maps */
};
+/**
+ * This structure defines the drm_mm memory object, which will be used by the
+ * DRM for its buffer objects.
+ */
struct drm_gem_object {
/** Reference count of this object */
u_int refcount;
/** Handle count of this object. Each handle also holds a reference */
- u_int handle_count; /* number of handles on this object */
+ atomic_t handle_count; /* number of handles on this object */
/** Related drm device */
struct drm_device *dev;
@@ -657,6 +563,7 @@ struct drm_gem_object {
/** File representing the shmem storage: filp in Linux parlance */
vm_object_t vm_obj;
+ /* Mapping info for this object */
bool on_map;
struct drm_hash_item map_list;
@@ -692,16 +599,16 @@ struct drm_gem_object {
void *driver_private;
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_NOTYET
/* dma buf exported from this GEM object */
struct dma_buf *export_dma_buf;
/* dma buf attachment backing this object */
struct dma_buf_attachment *import_attach;
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_NOTYET */
};
-#include "drm_crtc.h"
+#include <dev/drm2/drm_crtc.h>
/* per-master structure */
struct drm_master {
@@ -743,70 +650,81 @@ struct drm_master {
#define DRM_SCANOUTPOS_INVBL (1 << 1)
#define DRM_SCANOUTPOS_ACCURATE (1 << 2)
-#ifndef DMA_BIT_MASK
-#define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : (1ULL<<(n)) - 1)
-#endif
+struct drm_bus {
+ int bus_type;
+ int (*get_irq)(struct drm_device *dev);
+ void (*free_irq)(struct drm_device *dev);
+ const char *(*get_name)(struct drm_device *dev);
+ int (*set_busid)(struct drm_device *dev, struct drm_master *master);
+ int (*set_unique)(struct drm_device *dev, struct drm_master *master,
+ struct drm_unique *unique);
+ int (*irq_by_busid)(struct drm_device *dev, struct drm_irq_busid *p);
+ /* hooks that are for PCI */
+ int (*agp_init)(struct drm_device *dev);
-#define upper_32_bits(n) ((u32)(((n) >> 16) >> 16))
-
-struct drm_driver_info {
- int (*load)(struct drm_device *, unsigned long flags);
- int (*use_msi)(struct drm_device *, unsigned long flags);
- int (*firstopen)(struct drm_device *);
- int (*open)(struct drm_device *, struct drm_file *);
- void (*preclose)(struct drm_device *, struct drm_file *file_priv);
- void (*postclose)(struct drm_device *, struct drm_file *);
- void (*lastclose)(struct drm_device *);
- int (*unload)(struct drm_device *);
- void (*reclaim_buffers_locked)(struct drm_device *,
- struct drm_file *file_priv);
- int (*dma_ioctl)(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
- void (*dma_ready)(struct drm_device *);
- int (*dma_quiescent)(struct drm_device *);
- int (*dma_flush_block_and_flush)(struct drm_device *, int context,
- enum drm_lock_flags flags);
- int (*dma_flush_unblock)(struct drm_device *, int context,
- enum drm_lock_flags flags);
- int (*context_ctor)(struct drm_device *dev, int context);
- int (*context_dtor)(struct drm_device *dev, int context);
- int (*kernel_context_switch)(struct drm_device *dev, int old,
- int new);
- int (*kernel_context_switch_unlock)(struct drm_device *dev);
- void (*irq_preinstall)(struct drm_device *dev);
- int (*irq_postinstall)(struct drm_device *dev);
- void (*irq_uninstall)(struct drm_device *dev);
- void (*irq_handler)(DRM_IRQ_ARGS);
-
- u32 (*get_vblank_counter)(struct drm_device *dev, int crtc);
- int (*enable_vblank)(struct drm_device *dev, int crtc);
- void (*disable_vblank)(struct drm_device *dev, int crtc);
- int (*get_scanout_position)(struct drm_device *dev, int crtc,
- int *vpos, int *hpos);
-
- int (*get_vblank_timestamp)(struct drm_device *dev, int crtc,
- int *max_error, struct timeval *vblank_time,
- unsigned flags);
-
- int (*gem_init_object)(struct drm_gem_object *obj);
- void (*gem_free_object)(struct drm_gem_object *obj);
- int (*gem_open_object)(struct drm_gem_object *, struct drm_file *);
- void (*gem_close_object)(struct drm_gem_object *, struct drm_file *);
+};
- struct cdev_pager_ops *gem_pager_ops;
+/**
+ * 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 {
+ int (*load) (struct drm_device *, unsigned long flags);
+ int (*firstopen) (struct drm_device *);
+ int (*open) (struct drm_device *, struct drm_file *);
+ void (*preclose) (struct drm_device *, struct drm_file *file_priv);
+ void (*postclose) (struct drm_device *, struct drm_file *);
+ void (*lastclose) (struct drm_device *);
+ int (*unload) (struct drm_device *);
+ int (*dma_ioctl) (struct drm_device *dev, void *data, struct drm_file *file_priv);
+ int (*dma_quiescent) (struct drm_device *);
+ int (*context_dtor) (struct drm_device *dev, int context);
- 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);
+ /**
+ * get_vblank_counter - get raw hardware vblank counter
+ * @dev: DRM device
+ * @crtc: counter to fetch
+ *
+ * Driver callback for fetching a raw hardware vblank counter for @crtc.
+ * If a device doesn't have a hardware counter, the driver can simply
+ * return the value of drm_vblank_count. The DRM core will account for
+ * missed vblank events while interrupts where disabled based on system
+ * timestamps.
+ *
+ * Wraparound handling and loss of events due to modesetting is dealt
+ * with in the DRM core code.
+ *
+ * RETURNS
+ * Raw vblank counter value.
+ */
+ u32 (*get_vblank_counter) (struct drm_device *dev, int crtc);
- int (*sysctl_init)(struct drm_device *dev,
- struct sysctl_ctx_list *ctx, struct sysctl_oid *top);
- void (*sysctl_cleanup)(struct drm_device *dev);
+ /**
+ * enable_vblank - enable vblank interrupt events
+ * @dev: DRM device
+ * @crtc: which irq to enable
+ *
+ * Enable vblank interrupts for @crtc. If the device doesn't have
+ * a hardware vblank counter, this routine should be a no-op, since
+ * interrupts will have to stay on to keep the count accurate.
+ *
+ * RETURNS
+ * Zero on success, appropriate errno if the given @crtc's vblank
+ * interrupt cannot be enabled.
+ */
+ int (*enable_vblank) (struct drm_device *dev, int crtc);
- drm_pci_id_list_t *id_entry; /* PCI ID, name, and chipset private */
+ /**
+ * disable_vblank - disable vblank interrupt events
+ * @dev: DRM device
+ * @crtc: which irq to enable
+ *
+ * Disable vblank interrupts for @crtc. If the device doesn't have
+ * a hardware vblank counter, this routine should be a no-op, since
+ * interrupts will have to stay on to keep the count accurate.
+ */
+ void (*disable_vblank) (struct drm_device *dev, int crtc);
/**
* Called by \c drm_device_is_agp. Typically used to determine if a
@@ -819,39 +737,177 @@ struct drm_driver_info {
* 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).
*/
- int (*device_is_agp) (struct drm_device * dev);
+ int (*device_is_agp) (struct drm_device *dev);
- drm_ioctl_desc_t *ioctls;
-#ifdef COMPAT_FREEBSD32
- drm_ioctl_desc_t *compat_ioctls;
- int *compat_ioctls_nr;
-#endif
- int max_ioctl;
+ /**
+ * Called by vblank timestamping code.
+ *
+ * Return the current display scanout position from a crtc.
+ *
+ * \param dev DRM device.
+ * \param crtc Id of the crtc to query.
+ * \param *vpos Target location for current vertical scanout position.
+ * \param *hpos Target location for current horizontal scanout position.
+ *
+ * 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:
+ *
+ * DRM_SCANOUTPOS_VALID = Query successful.
+ * 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.
+ *
+ */
+ int (*get_scanout_position) (struct drm_device *dev, int crtc,
+ int *vpos, int *hpos);
- int buf_priv_size;
+ /**
+ * 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,
+ * the time immediately after end of the VBLANK interval. If the
+ * @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.
+ * \param crtc crtc for which timestamp should be returned.
+ * \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.
+ */
+ int (*get_vblank_timestamp) (struct drm_device *dev, int crtc,
+ int *max_error,
+ struct timeval *vblank_time,
+ unsigned flags);
+
+ /* these have to be filled in */
+
+ irqreturn_t(*irq_handler) (DRM_IRQ_ARGS);
+ void (*irq_preinstall) (struct drm_device *dev);
+ int (*irq_postinstall) (struct drm_device *dev);
+ void (*irq_uninstall) (struct drm_device *dev);
+ void (*set_version) (struct drm_device *dev,
+ struct drm_set_version *sv);
+
+ /* Master routines */
+ int (*master_create)(struct drm_device *dev, struct drm_master *master);
+ void (*master_destroy)(struct drm_device *dev, struct drm_master *master);
+ /**
+ * 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);
+ void (*master_drop)(struct drm_device *dev, struct drm_file *file_priv,
+ bool from_release);
+
+ /**
+ * Driver-specific constructor for drm_gem_objects, to set up
+ * obj->driver_private.
+ *
+ * Returns 0 on success.
+ */
+ int (*gem_init_object) (struct drm_gem_object *obj);
+ void (*gem_free_object) (struct drm_gem_object *obj);
+ int (*gem_open_object) (struct drm_gem_object *, struct drm_file *);
+ void (*gem_close_object) (struct drm_gem_object *, struct drm_file *);
+
+#ifdef FREEBSD_NOTYET
+ /* 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);
+#endif /* defined(FREEBSD_NOTYET) */
+
+ /* 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);
+
+ /* Driver private ops for this object */
+ struct cdev_pager_ops *gem_pager_ops;
+
+ int (*sysctl_init)(struct drm_device *dev,
+ struct sysctl_ctx_list *ctx, struct sysctl_oid *top);
+ void (*sysctl_cleanup)(struct drm_device *dev);
- int major;
- int minor;
- int patchlevel;
- const char *name; /* Simple driver name */
- const char *desc; /* Longer driver name */
- const char *date; /* Date of last major changes. */
+ int major;
+ int minor;
+ int patchlevel;
+ char *name;
+ char *desc;
+ char *date;
u32 driver_features;
+ int dev_priv_size;
+ struct drm_ioctl_desc *ioctls;
+ int num_ioctls;
+ struct drm_bus *bus;
+#ifdef COMPAT_FREEBSD32
+ struct drm_ioctl_desc *compat_ioctls;
+ int *num_compat_ioctls;
+#endif
+
+ int buf_priv_size;
};
+#define DRM_MINOR_UNASSIGNED 0
+#define DRM_MINOR_LEGACY 1
+#define DRM_MINOR_CONTROL 2
+#define DRM_MINOR_RENDER 3
+
/**
* DRM minor structure. This structure represents a drm minor number.
*/
struct drm_minor {
int index; /**< Minor device number */
int type; /**< Control or render */
+ struct cdev *device; /**< Device number for mknod */
device_t kdev; /**< OS device */
struct drm_device *dev;
struct drm_master *master; /* currently active master for this node */
struct list_head master_list;
struct drm_mode_group mode_group;
+
+ struct sigio *buf_sigio; /* Processes waiting for SIGIO */
};
/* mode specified on the command line */
@@ -876,105 +932,80 @@ struct drm_pending_vblank_event {
struct drm_event_vblank event;
};
-/* Length for the array of resource pointers for drm_get_resource_*. */
-#define DRM_MAX_PCI_RESOURCE 6
-
/**
* DRM device structure. This structure represent a complete card that
* may contain multiple heads.
*/
struct drm_device {
- struct drm_driver_info *driver;
- drm_pci_id_list_t *id_entry; /* PCI ID, name, and chipset private */
-
- uint16_t pci_device; /* PCI device id */
- uint16_t pci_vendor; /* PCI vendor id */
- uint16_t pci_subdevice; /* PCI subsystem device id */
- uint16_t pci_subvendor; /* PCI subsystem vendor id */
-
- char *unique; /* Unique identifier: e.g., busid */
- int unique_len; /* Length of unique field */
- device_t device; /* Device instance from newbus */
- struct cdev *devnode; /* Device number for mknod */
- int if_version; /* Highest interface version set */
-
- int flags; /* Flags to open(2) */
-
- /* Locks */
- struct mtx dma_lock; /* protects dev->dma */
- struct mtx irq_lock; /* protects irq condition checks */
- struct mtx dev_lock; /* protects everything else */
- struct sx dev_struct_lock;
- DRM_SPINTYPE drw_lock;
-
- /* Usage Counters */
- int open_count; /* Outstanding files open */
- int buf_use; /* Buffers in use -- cannot alloc */
-
- /* Performance counters */
- unsigned long counters;
- enum drm_stat_type types[15];
- atomic_t counts[15];
-
- /* Authentication */
- drm_file_list_t files;
- drm_magic_head_t magiclist[DRM_HASH_SIZE];
-
- /* Linked list of mappable regions. Protected by dev_lock */
- drm_map_list_t maplist;
- struct unrhdr *map_unrhdr;
-
- drm_local_map_t **context_sareas;
- int max_context;
-
- drm_lock_data_t lock; /* Information on hardware lock */
-
- /* DMA queues (contexts) */
- drm_device_dma_t *dma; /* Optional pointer for DMA support */
+ int if_version; /**< Highest interface version set */
- /* Context support */
- int irq; /* Interrupt used by board */
- int irq_enabled; /* True if the irq handler is enabled */
- int msi_enabled; /* MSI enabled */
- int irqrid; /* Interrupt used by board */
- struct resource *irqr; /* Resource for interrupt used by board */
- void *irqh; /* Handle from bus_setup_intr */
+ /** \name Locks */
+ /*@{ */
+ struct mtx count_lock; /**< For inuse, drm_device::open_count, drm_device::buf_use */
+ struct sx dev_struct_lock; /**< For others */
+ /*@} */
- /* Storage of resource pointers for drm_get_resource_* */
- struct resource *pcir[DRM_MAX_PCI_RESOURCE];
- int pcirid[DRM_MAX_PCI_RESOURCE];
+ /** \name Usage Counters */
+ /*@{ */
+ int open_count; /**< Outstanding files open */
+ atomic_t ioctl_count; /**< Outstanding IOCTLs pending */
+ atomic_t vma_count; /**< Outstanding vma areas open */
+ int buf_use; /**< Buffers in use -- cannot alloc */
+ atomic_t buf_alloc; /**< Buffer allocation in progress */
+ /*@} */
- int pci_domain;
- int pci_bus;
- int pci_slot;
- int pci_func;
+ /** \name Performance counters */
+ /*@{ */
+ unsigned long counters;
+ enum drm_stat_type types[15];
+ atomic_t counts[15];
+ /*@} */
- atomic_t context_flag; /* Context swapping flag */
- int last_context; /* Last current context */
+ struct list_head filelist;
- int num_crtcs;
+ /** \name Memory management */
+ /*@{ */
+ struct list_head maplist; /**< Linked list of regions */
+ int map_count; /**< Number of mappable regions */
+ struct drm_open_hash map_hash; /**< User token hash table for maps */
- struct sigio *buf_sigio; /* Processes waiting for SIGIO */
+ /** \name Context handle management */
+ /*@{ */
+ struct list_head ctxlist; /**< Linked list of context handles */
+ int ctx_count; /**< Number of context handles */
+ struct mtx ctxlist_mutex; /**< For ctxlist */
+ drm_local_map_t **context_sareas;
+ int max_context;
+ unsigned long *ctx_bitmap;
- /* Sysctl support */
- struct drm_sysctl_info *sysctl;
- int sysctl_node_idx;
+ /*@} */
- drm_agp_head_t *agp;
- drm_sg_mem_t *sg; /* Scatter gather memory */
- unsigned long *ctx_bitmap;
- void *dev_private;
- unsigned int agp_buffer_token;
- drm_local_map_t *agp_buffer_map;
+ /** \name DMA support */
+ /*@{ */
+ struct drm_device_dma *dma; /**< Optional pointer for DMA support */
+ /*@} */
- struct drm_minor *control; /**< Control node for card */
- struct drm_minor *primary; /**< render type primary screen head */
+ /** \name Context support */
+ /*@{ */
+ int irq_enabled; /**< True if irq handler is enabled */
+ atomic_t context_flag; /**< Context swapping flag */
+ atomic_t interrupt_flag; /**< Interruption handler flag */
+ atomic_t dma_flag; /**< DMA dispatch flag */
+ wait_queue_head_t context_wait; /**< Processes waiting on ctx switch */
+ int last_checked; /**< Last context checked for DMA */
+ int last_context; /**< Last current context */
+ unsigned long last_switch; /**< jiffies at last context switch */
+ /*@} */
- void *drm_ttm_bdev;
- struct unrhdr *drw_unrhdr;
- /* RB tree of drawable infos */
- RB_HEAD(drawable_tree, bsd_drm_drawable_info) drw_head;
+ /** \name VBLANK IRQ support */
+ /*@{ */
+ /*
+ * At load time, disabling the vblank interrupt won't be allowed since
+ * old clients may not call the modeset ioctl and therefore misbehave.
+ * Once the modeset ioctl *has* been called though, we can safely
+ * disable them when unused.
+ */
int vblank_disable_allowed;
atomic_t *_vblank_count; /**< number of VBLANK interrupts (driver must alloc the right number of counters) */
@@ -992,21 +1023,79 @@ struct drm_device {
u32 max_vblank_count; /**< size of vblank counter register */
+ /**
+ * List of events
+ */
struct list_head vblank_event_list;
- struct mtx event_lock;
+ struct mtx event_lock;
+
+ /*@} */
+
+ struct drm_agp_head *agp; /**< AGP data */
+
+ device_t dev; /* Device instance from newbus */
+ uint16_t pci_device; /* PCI device id */
+ uint16_t pci_vendor; /* PCI vendor id */
+ uint16_t pci_subdevice; /* PCI subsystem device id */
+ uint16_t pci_subvendor; /* PCI subsystem vendor id */
+
+ struct drm_sg_mem *sg; /**< Scatter gather memory */
+ unsigned int num_crtcs; /**< Number of CRTCs on this device */
+ void *dev_private; /**< device private data */
+ void *mm_private;
+ struct drm_sigdata sigdata; /**< For block_all_signals */
+ sigset_t sigmask;
+
+ struct drm_driver *driver;
+ struct drm_local_map *agp_buffer_map;
+ unsigned int agp_buffer_token;
+ struct drm_minor *control; /**< Control node for card */
+ struct drm_minor *primary; /**< render type primary screen head */
struct drm_mode_config mode_config; /**< Current mode config */
- /* GEM part */
- struct sx object_name_lock;
+ /** \name GEM information */
+ /*@{ */
+ struct sx object_name_lock;
struct drm_gem_names object_names;
- void *mm_private;
+ /*@} */
+ int switch_power_state;
+
+ atomic_t unplugged; /* device has been unplugged or gone away */
+
+ /* Locks */
+ struct mtx dma_lock; /* protects dev->dma */
+ struct mtx irq_lock; /* protects irq condition checks */
+
+ /* Context support */
+ int irq; /* Interrupt used by board */
+ int msi_enabled; /* MSI enabled */
+ int irqrid; /* Interrupt used by board */
+ struct resource *irqr; /* Resource for interrupt used by board */
+ void *irqh; /* Handle from bus_setup_intr */
+
+ /* Storage of resource pointers for drm_get_resource_* */
+#define DRM_MAX_PCI_RESOURCE 6
+ struct resource *pcir[DRM_MAX_PCI_RESOURCE];
+ int pcirid[DRM_MAX_PCI_RESOURCE];
+ struct mtx pcir_lock;
+
+ int pci_domain;
+ int pci_bus;
+ int pci_slot;
+ int pci_func;
+
+ /* Sysctl support */
+ struct drm_sysctl_info *sysctl;
+ int sysctl_node_idx;
+
+ void *drm_ttm_bdev;
void *sysctl_private;
char busid_str[128];
int modesetting;
- int switch_power_state;
+ drm_pci_id_list_t *id_entry; /* PCI ID, name, and chipset private */
};
#define DRM_SWITCH_POWER_ON 0
@@ -1019,6 +1108,12 @@ static __inline__ int drm_core_check_feature(struct drm_device *dev,
return ((dev->driver->driver_features & feature) ? 1 : 0);
}
+static inline int drm_dev_to_irq(struct drm_device *dev)
+{
+ return dev->driver->bus->get_irq(dev);
+}
+
+
#if __OS_HAS_AGP
static inline int drm_core_has_AGP(struct drm_device *dev)
{
@@ -1028,165 +1123,175 @@ static inline int drm_core_has_AGP(struct drm_device *dev)
#define drm_core_has_AGP(dev) (0)
#endif
-enum dmi_field {
- DMI_NONE,
- DMI_BIOS_VENDOR,
- DMI_BIOS_VERSION,
- DMI_BIOS_DATE,
- DMI_SYS_VENDOR,
- DMI_PRODUCT_NAME,
- DMI_PRODUCT_VERSION,
- DMI_PRODUCT_SERIAL,
- DMI_PRODUCT_UUID,
- DMI_BOARD_VENDOR,
- DMI_BOARD_NAME,
- DMI_BOARD_VERSION,
- DMI_BOARD_SERIAL,
- DMI_BOARD_ASSET_TAG,
- DMI_CHASSIS_VENDOR,
- DMI_CHASSIS_TYPE,
- DMI_CHASSIS_VERSION,
- DMI_CHASSIS_SERIAL,
- DMI_CHASSIS_ASSET_TAG,
- DMI_STRING_MAX,
-};
+#if __OS_HAS_MTRR
+static inline int drm_core_has_MTRR(struct drm_device *dev)
+{
+ return drm_core_check_feature(dev, DRIVER_USE_MTRR);
+}
-struct dmi_strmatch {
- unsigned char slot;
- char substr[79];
-};
+#define DRM_MTRR_WC MDF_WRITECOMBINE
-struct dmi_system_id {
- int (*callback)(const struct dmi_system_id *);
- const char *ident;
- struct dmi_strmatch matches[4];
-};
-#define DMI_MATCH(a, b) {(a), (b)}
-bool dmi_check_system(const struct dmi_system_id *);
+int drm_mtrr_add(unsigned long offset, unsigned long size, unsigned int flags);
+int drm_mtrr_del(int handle, unsigned long offset, unsigned long size, unsigned int flags);
-extern int drm_debug_flag;
-extern int drm_notyet_flag;
-extern unsigned int drm_vblank_offdelay;
-extern unsigned int drm_timestamp_precision;
-extern unsigned int drm_timestamp_monotonic;
+#else
+#define drm_core_has_MTRR(dev) (0)
-/* Device setup support (drm_drv.c) */
-int drm_probe(device_t kdev, drm_pci_id_list_t *idlist);
-int drm_attach(device_t kdev, drm_pci_id_list_t *idlist);
-int drm_create_cdevs(device_t kdev);
-void drm_close(void *data);
-int drm_detach(device_t kdev);
+#define DRM_MTRR_WC 0
+
+static inline int drm_mtrr_add(unsigned long offset, unsigned long size,
+ unsigned int flags)
+{
+ return 0;
+}
+
+static inline int drm_mtrr_del(int handle, unsigned long offset,
+ unsigned long size, unsigned int flags)
+{
+ return 0;
+}
+#endif
+
+/******************************************************************/
+/** \name Internal function definitions */
+/*@{*/
+
+ /* Driver support (drm_drv.h) */
d_ioctl_t drm_ioctl;
+extern int drm_lastclose(struct drm_device *dev);
+
+ /* Device support (drm_fops.h) */
+extern struct sx drm_global_mutex;
d_open_t drm_open;
d_read_t drm_read;
-d_poll_t drm_poll;
+extern void drm_release(void *data);
+
+ /* Mapping support (drm_vm.h) */
d_mmap_t drm_mmap;
-extern drm_local_map_t *drm_getsarea(struct drm_device *dev);
+int drm_mmap_single(struct cdev *kdev, vm_ooffset_t *offset,
+ vm_size_t size, struct vm_object **obj_res, int nprot);
+d_poll_t drm_poll;
-void drm_event_wakeup(struct drm_pending_event *e);
+ /* Memory management support (drm_memory.h) */
+extern void drm_free_agp(DRM_AGP_MEM * handle, int pages);
+extern int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start);
+#ifdef FREEBSD_NOTYET
+extern DRM_AGP_MEM *drm_agp_bind_pages(struct drm_device *dev,
+ struct page **pages,
+ unsigned long num_pages,
+ uint32_t gtt_offset,
+ uint32_t type);
+#endif /* FREEBSD_NOTYET */
+extern int drm_unbind_agp(DRM_AGP_MEM * handle);
+
+ /* Misc. IOCTL support (drm_ioctl.h) */
+extern int drm_irq_by_busid(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_getunique(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_setunique(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_getmap(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_getclient(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_getstats(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_getcap(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_setversion(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_noop(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
-int drm_add_busid_modesetting(struct drm_device *dev,
- struct sysctl_ctx_list *ctx, struct sysctl_oid *top);
+ /* Context IOCTL support (drm_context.h) */
+extern int drm_resctx(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_addctx(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_modctx(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_getctx(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_switchctx(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_newctx(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_rmctx(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
-/* File operations helpers (drm_fops.c) */
-extern int drm_open_helper(struct cdev *kdev, int flags, int fmt,
- DRM_STRUCTPROC *p,
- struct drm_device *dev);
+extern int drm_ctxbitmap_init(struct drm_device *dev);
+extern void drm_ctxbitmap_cleanup(struct drm_device *dev);
+extern void drm_ctxbitmap_free(struct drm_device *dev, int ctx_handle);
-#ifdef DUMBBELL_WIP
-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);
-extern int drm_gem_prime_fd_to_handle(struct drm_device *dev,
- struct drm_file *file_priv, int prime_fd, uint32_t *handle);
+extern int drm_setsareactx(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_getsareactx(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
-extern int drm_prime_handle_to_fd_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-extern int drm_prime_fd_to_handle_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
+ /* Authentication IOCTL support (drm_auth.h) */
+extern int drm_getmagic(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_authmagic(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_remove_magic(struct drm_master *master, drm_magic_t magic);
-#ifdef DUMBBELL_WIP
-/*
- * See drm_prime.c
- * -- dumbbell@
- */
-extern int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, vm_page_t *pages,
- dma_addr_t *addrs, int max_pages);
-#endif /* DUMBBELL_WIP */
-extern struct sg_table *drm_prime_pages_to_sg(vm_page_t *pages, int nr_pages);
-extern void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg);
+/* Cache management (drm_cache.c) */
+void drm_clflush_pages(vm_page_t *pages, unsigned long num_pages);
+void drm_clflush_virt_range(char *addr, unsigned long length);
+ /* Locking IOCTL support (drm_lock.h) */
+extern int drm_lock(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_unlock(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_lock_free(struct drm_lock_data *lock_data, unsigned int context);
+extern void drm_idlelock_take(struct drm_lock_data *lock_data);
+extern void drm_idlelock_release(struct drm_lock_data *lock_data);
-void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv);
-void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv);
-int drm_prime_add_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle);
-int drm_prime_lookup_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t *handle);
-void drm_prime_remove_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf);
+/*
+ * These are exported to drivers so that they can implement fencing using
+ * DMA quiscent + idle. DMA quiescent usually requires the hardware lock.
+ */
-int drm_prime_add_dma_buf(struct drm_device *dev, struct drm_gem_object *obj);
-int drm_prime_lookup_obj(struct drm_device *dev, struct dma_buf *buf,
- struct drm_gem_object **obj);
-#endif /* DUMBBELL_WIP */
-
-/* Memory management support (drm_memory.c) */
-void drm_mem_init(void);
-void drm_mem_uninit(void);
-void *drm_ioremap_wc(struct drm_device *dev, drm_local_map_t *map);
-void *drm_ioremap(struct drm_device *dev, drm_local_map_t *map);
-void drm_ioremapfree(drm_local_map_t *map);
-int drm_mtrr_add(unsigned long offset, size_t size, int flags);
-int drm_mtrr_del(int handle, unsigned long offset, size_t size, int flags);
-
-int drm_context_switch(struct drm_device *dev, int old, int new);
-int drm_context_switch_complete(struct drm_device *dev, int new);
-
-int drm_ctxbitmap_init(struct drm_device *dev);
-void drm_ctxbitmap_cleanup(struct drm_device *dev);
-void drm_ctxbitmap_free(struct drm_device *dev, int ctx_handle);
-int drm_ctxbitmap_next(struct drm_device *dev);
-
-/* Locking IOCTL support (drm_lock.c) */
-int drm_lock_take(struct drm_lock_data *lock_data,
- unsigned int context);
-int drm_lock_transfer(struct drm_lock_data *lock_data,
- unsigned int context);
-int drm_lock_free(struct drm_lock_data *lock_data,
- unsigned int context);
+extern int drm_i_have_hw_lock(struct drm_device *dev, struct drm_file *file_priv);
-/* Buffer management support (drm_bufs.c) */
-unsigned long drm_get_resource_start(struct drm_device *dev,
- unsigned int resource);
-unsigned long drm_get_resource_len(struct drm_device *dev,
- unsigned int resource);
-void drm_rmmap(struct drm_device *dev, drm_local_map_t *map);
-int drm_order(unsigned long size);
-int drm_addmap(struct drm_device *dev, unsigned long offset,
- unsigned long size,
- enum drm_map_type type, enum drm_map_flags flags,
- drm_local_map_t **map_ptr);
-int drm_addbufs_pci(struct drm_device *dev, struct drm_buf_desc *request);
-int drm_addbufs_sg(struct drm_device *dev, struct drm_buf_desc *request);
-int drm_addbufs_agp(struct drm_device *dev, struct drm_buf_desc *request);
-
-/* DMA support (drm_dma.c) */
-int drm_dma_setup(struct drm_device *dev);
-void drm_dma_takedown(struct drm_device *dev);
-void drm_free_buffer(struct drm_device *dev, drm_buf_t *buf);
-void drm_reclaim_buffers(struct drm_device *dev, struct drm_file *file_priv);
-#define drm_core_reclaim_buffers drm_reclaim_buffers
+ /* Buffer management support (drm_bufs.h) */
+extern int drm_addbufs_agp(struct drm_device *dev, struct drm_buf_desc * request);
+extern int drm_addbufs_pci(struct drm_device *dev, struct drm_buf_desc * request);
+extern int drm_addmap(struct drm_device *dev, resource_size_t offset,
+ unsigned int size, enum drm_map_type type,
+ enum drm_map_flags flags, struct drm_local_map **map_ptr);
+extern int drm_addmap_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_rmmap(struct drm_device *dev, struct drm_local_map *map);
+extern int drm_rmmap_locked(struct drm_device *dev, struct drm_local_map *map);
+extern int drm_rmmap_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_addbufs(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_infobufs(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_markbufs(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_freebufs(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_mapbufs(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_order(unsigned long size);
-/* IRQ support (drm_irq.c) */
-int drm_irq_install(struct drm_device *dev);
-int drm_irq_uninstall(struct drm_device *dev);
-irqreturn_t drm_irq_handler(DRM_IRQ_ARGS);
-void drm_driver_irq_preinstall(struct drm_device *dev);
-void drm_driver_irq_postinstall(struct drm_device *dev);
-void drm_driver_irq_uninstall(struct drm_device *dev);
+ /* DMA support (drm_dma.h) */
+extern int drm_dma_setup(struct drm_device *dev);
+extern void drm_dma_takedown(struct drm_device *dev);
+extern void drm_free_buffer(struct drm_device *dev, struct drm_buf * buf);
+extern void drm_core_reclaim_buffers(struct drm_device *dev,
+ struct drm_file *filp);
-void drm_vblank_pre_modeset(struct drm_device *dev, int crtc);
-void drm_vblank_post_modeset(struct drm_device *dev, int crtc);
-int drm_modeset_ctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
+ /* IRQ support (drm_irq.h) */
+extern int drm_control(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_irq_install(struct drm_device *dev);
+extern int drm_irq_uninstall(struct drm_device *dev);
extern int drm_vblank_init(struct drm_device *dev, int num_crtcs);
extern int drm_wait_vblank(struct drm_device *dev, void *data,
@@ -1195,8 +1300,9 @@ extern int drm_vblank_wait(struct drm_device *dev, unsigned int *vbl_seq);
extern u32 drm_vblank_count(struct drm_device *dev, int crtc);
extern u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc,
struct timeval *vblanktime);
+extern void drm_send_vblank_event(struct drm_device *dev, int crtc,
+ struct drm_pending_vblank_event *e);
extern bool drm_handle_vblank(struct drm_device *dev, int crtc);
-void drm_handle_vblank_events(struct drm_device *dev, int crtc);
extern int drm_vblank_get(struct drm_device *dev, int crtc);
extern void drm_vblank_put(struct drm_device *dev, int crtc);
extern void drm_vblank_off(struct drm_device *dev, int crtc);
@@ -1210,303 +1316,261 @@ extern int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
struct drm_crtc *refcrtc);
extern void drm_calc_timestamping_constants(struct drm_crtc *crtc);
-struct timeval ns_to_timeval(const int64_t nsec);
-int64_t timeval_to_ns(const struct timeval *tv);
+extern bool
+drm_mode_parse_command_line_for_connector(const char *mode_option,
+ struct drm_connector *connector,
+ struct drm_cmdline_mode *mode);
-/* AGP/PCI Express/GART support (drm_agpsupport.c) */
-int drm_device_is_agp(struct drm_device *dev);
-int drm_device_is_pcie(struct drm_device *dev);
-drm_agp_head_t *drm_agp_init(void);
-int drm_agp_acquire(struct drm_device *dev);
-int drm_agp_release(struct drm_device *dev);
-int drm_agp_info(struct drm_device * dev, struct drm_agp_info *info);
-int drm_agp_enable(struct drm_device *dev, struct drm_agp_mode mode);
-void *drm_agp_allocate_memory(size_t pages, u32 type);
-int drm_agp_free_memory(void *handle);
-int drm_agp_bind_memory(void *handle, off_t start);
-int drm_agp_unbind_memory(void *handle);
-int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request);
-int drm_agp_free(struct drm_device *dev, struct drm_agp_buffer *request);
-int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request);
-int drm_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request);
+extern struct drm_display_mode *
+drm_mode_create_from_cmdline_mode(struct drm_device *dev,
+ struct drm_cmdline_mode *cmd);
-/* Scatter Gather Support (drm_scatter.c) */
-void drm_sg_cleanup(drm_sg_mem_t *entry);
-int drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather * request);
-
-/* sysctl support (drm_sysctl.h) */
-extern int drm_sysctl_init(struct drm_device *dev);
-extern int drm_sysctl_cleanup(struct drm_device *dev);
-
-/* ATI PCIGART support (ati_pcigart.c) */
-int drm_ati_pcigart_init(struct drm_device *dev,
- struct drm_ati_pcigart_info *gart_info);
-int drm_ati_pcigart_cleanup(struct drm_device *dev,
- struct drm_ati_pcigart_info *gart_info);
-
-/* Cache management (drm_memory.c) */
-void drm_clflush_pages(vm_page_t *pages, unsigned long num_pages);
-void drm_clflush_virt_range(char *addr, unsigned long length);
-
-/* Locking IOCTL support (drm_drv.c) */
-int drm_lock(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-int drm_unlock(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-int drm_version(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-int drm_setversion(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
+/* Modesetting support */
+extern void drm_vblank_pre_modeset(struct drm_device *dev, int crtc);
+extern void drm_vblank_post_modeset(struct drm_device *dev, int crtc);
+extern int drm_modeset_ctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
-/* Misc. IOCTL support (drm_ioctl.c) */
-int drm_irq_by_busid(struct drm_device *dev, void *data,
+ /* AGP/GART support (drm_agpsupport.h) */
+extern struct drm_agp_head *drm_agp_init(struct drm_device *dev);
+extern int drm_agp_acquire(struct drm_device *dev);
+extern int drm_agp_acquire_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_agp_release(struct drm_device *dev);
+extern int drm_agp_release_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_agp_enable(struct drm_device *dev, struct drm_agp_mode mode);
+extern int drm_agp_enable_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_agp_info(struct drm_device *dev, struct drm_agp_info *info);
+extern int drm_agp_info_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request);
+extern int drm_agp_alloc_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
-int drm_getunique(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-int drm_setunique(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-int drm_getmap(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-int drm_getclient(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-int drm_getstats(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-int drm_getcap(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-int drm_noop(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-
-/* Context IOCTL support (drm_context.c) */
-int drm_resctx(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-int drm_addctx(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-int drm_modctx(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-int drm_getctx(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-int drm_switchctx(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-int drm_newctx(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-int drm_rmctx(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-int drm_setsareactx(struct drm_device *dev, void *data,
+extern int drm_agp_free(struct drm_device *dev, struct drm_agp_buffer *request);
+extern int drm_agp_free_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
-int drm_getsareactx(struct drm_device *dev, void *data,
+extern int drm_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request);
+extern int drm_agp_unbind_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request);
+extern int drm_agp_bind_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
-/* Drawable IOCTL support (drm_drawable.c) */
-int drm_adddraw(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-int drm_rmdraw(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-int drm_update_draw(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-struct drm_drawable_info *drm_get_drawable_info(struct drm_device *dev,
- int handle);
+ /* Stub support (drm_stub.h) */
+extern int drm_setmaster_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+struct drm_master *drm_master_create(struct drm_minor *minor);
+extern struct drm_master *drm_master_get(struct drm_master *master);
+extern void drm_master_put(struct drm_master **master);
-/* Drawable support (drm_drawable.c) */
-void drm_drawable_free_all(struct drm_device *dev);
+extern void drm_put_dev(struct drm_device *dev);
+extern int drm_put_minor(struct drm_minor **minor);
+extern void drm_unplug_dev(struct drm_device *dev);
+extern unsigned int drm_debug;
+extern unsigned int drm_notyet;
-/* Authentication IOCTL support (drm_auth.c) */
-int drm_getmagic(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-int drm_authmagic(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
+extern unsigned int drm_vblank_offdelay;
+extern unsigned int drm_timestamp_precision;
+extern unsigned int drm_timestamp_monotonic;
-/* Buffer management support (drm_bufs.c) */
-int drm_addmap_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-int drm_rmmap_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-int drm_addbufs(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-int drm_infobufs(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-int drm_markbufs(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-int drm_freebufs(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-int drm_mapbufs(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
+extern struct drm_local_map *drm_getsarea(struct drm_device *dev);
-/* DMA support (drm_dma.c) */
-int drm_dma(struct drm_device *dev, void *data, struct drm_file *file_priv);
-/* IRQ support (drm_irq.c) */
-int drm_control(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
+#ifdef FREEBSD_NOTYET
+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);
+extern int drm_gem_prime_fd_to_handle(struct drm_device *dev,
+ struct drm_file *file_priv, int prime_fd, uint32_t *handle);
-/* AGP/GART support (drm_agpsupport.c) */
-int drm_agp_acquire_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-int drm_agp_release_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-int drm_agp_enable_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-int drm_agp_info_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-int drm_agp_alloc_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-int drm_agp_free_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-int drm_agp_unbind_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-int drm_agp_bind_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
+extern int drm_prime_handle_to_fd_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_prime_fd_to_handle_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
- /* Stub support (drm_stub.h) */
-extern int drm_setmaster_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-extern int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
+extern int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, vm_page_t *pages,
+ dma_addr_t *addrs, int max_pages);
+extern struct sg_table *drm_prime_pages_to_sg(vm_page_t *pages, int nr_pages);
+extern void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg);
-/* Scatter Gather Support (drm_scatter.c) */
-int drm_sg_alloc_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-int drm_sg_free(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-/* consistent PCI memory functions (drm_pci.c) */
-drm_dma_handle_t *drm_pci_alloc(struct drm_device *dev, size_t size,
- size_t align, dma_addr_t maxaddr);
-void drm_pci_free(struct drm_device *dev, drm_dma_handle_t *dmah);
+void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv);
+void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv);
+int drm_prime_add_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle);
+int drm_prime_lookup_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t *handle);
+void drm_prime_remove_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf);
-/* Graphics Execution Manager library functions (drm_gem.c) */
-int drm_gem_init(struct drm_device *dev);
-void drm_gem_destroy(struct drm_device *dev);
+int drm_prime_add_dma_buf(struct drm_device *dev, struct drm_gem_object *obj);
+int drm_prime_lookup_obj(struct drm_device *dev, struct dma_buf *buf,
+ struct drm_gem_object **obj);
+#endif /* FREEBSD_NOTYET */
-int drm_gem_close_ioctl(struct drm_device *dev, void *data,
+ /* Scatter Gather Support (drm_scatter.h) */
+extern void drm_sg_cleanup(struct drm_sg_mem * entry);
+extern int drm_sg_alloc_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
-int drm_gem_flink_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-int drm_gem_open_ioctl(struct drm_device *dev, void *data,
+extern int drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather * request);
+extern int drm_sg_free(struct drm_device *dev, void *data,
struct drm_file *file_priv);
-int drm_gem_handle_create(struct drm_file *file_priv,
- struct drm_gem_object *obj,
- u32 *handlep);
-int drm_gem_handle_delete(struct drm_file *file_priv, uint32_t handle);
-void drm_gem_object_handle_reference(struct drm_gem_object *obj);
-void drm_gem_object_handle_unreference(struct drm_gem_object *obj);
-void drm_gem_object_handle_unreference_unlocked(struct drm_gem_object *obj);
-void drm_gem_object_handle_free(struct drm_gem_object *obj);
-void drm_gem_object_reference(struct drm_gem_object *obj);
-void drm_gem_object_unreference(struct drm_gem_object *obj);
-void drm_gem_object_unreference_unlocked(struct drm_gem_object *obj);
+
+ /* ATI PCIGART support (ati_pcigart.h) */
+extern int drm_ati_pcigart_init(struct drm_device *dev,
+ struct drm_ati_pcigart_info * gart_info);
+extern int drm_ati_pcigart_cleanup(struct drm_device *dev,
+ struct drm_ati_pcigart_info * gart_info);
+
+extern drm_dma_handle_t *drm_pci_alloc(struct drm_device *dev, size_t size,
+ size_t align, dma_addr_t maxaddr);
+extern void __drm_pci_free(struct drm_device *dev, drm_dma_handle_t * dmah);
+extern void drm_pci_free(struct drm_device *dev, drm_dma_handle_t * dmah);
+
+/* Graphics Execution Manager library functions (drm_gem.c) */
+int drm_gem_init(struct drm_device *dev);
+void drm_gem_destroy(struct drm_device *dev);
void drm_gem_object_release(struct drm_gem_object *obj);
void drm_gem_object_free(struct drm_gem_object *obj);
-int drm_gem_object_init(struct drm_device *dev, struct drm_gem_object *obj,
- size_t size);
-int drm_gem_private_object_init(struct drm_device *dev,
- struct drm_gem_object *obj, size_t size);
struct drm_gem_object *drm_gem_object_alloc(struct drm_device *dev,
- size_t size);
-struct drm_gem_object *drm_gem_object_lookup(struct drm_device *dev,
- struct drm_file *file_priv, uint32_t handle);
-
-void drm_gem_open(struct drm_device *dev, struct drm_file *file_priv);
-void drm_gem_release(struct drm_device *dev, struct drm_file *file_priv);
-
-int drm_gem_create_mmap_offset(struct drm_gem_object *obj);
-void drm_gem_free_mmap_offset(struct drm_gem_object *obj);
+ size_t size);
+int drm_gem_object_init(struct drm_device *dev,
+ struct drm_gem_object *obj, size_t size);
+int drm_gem_private_object_init(struct drm_device *dev,
+ struct drm_gem_object *obj, size_t size);
+void drm_gem_object_handle_free(struct drm_gem_object *obj);
int drm_gem_mmap_single(struct drm_device *dev, vm_ooffset_t *offset,
vm_size_t size, struct vm_object **obj_res, int nprot);
void drm_gem_pager_dtr(void *obj);
-struct ttm_bo_device;
-int ttm_bo_mmap_single(struct ttm_bo_device *bdev, vm_ooffset_t *offset,
- vm_size_t size, struct vm_object **obj_res, int nprot);
-struct ttm_buffer_object;
-void ttm_bo_release_mmap(struct ttm_buffer_object *bo);
+#include <dev/drm2/drm_global.h>
-void drm_device_lock_mtx(struct drm_device *dev);
-void drm_device_unlock_mtx(struct drm_device *dev);
-int drm_device_sleep_mtx(struct drm_device *dev, void *chan, int flags,
- const char *msg, int timeout);
-void drm_device_assert_mtx_locked(struct drm_device *dev);
-void drm_device_assert_mtx_unlocked(struct drm_device *dev);
-
-void drm_device_lock_struct(struct drm_device *dev);
-void drm_device_unlock_struct(struct drm_device *dev);
-int drm_device_sleep_struct(struct drm_device *dev, void *chan, int flags,
- const char *msg, int timeout);
-void drm_device_assert_struct_locked(struct drm_device *dev);
-void drm_device_assert_struct_unlocked(struct drm_device *dev);
-
-void drm_compat_locking_init(struct drm_device *dev);
-void drm_sleep_locking_init(struct drm_device *dev);
-
-/* drm_modes.c */
-bool drm_mode_parse_command_line_for_connector(const char *mode_option,
- struct drm_connector *connector, struct drm_cmdline_mode *mode);
-struct drm_display_mode *drm_mode_create_from_cmdline_mode(
- struct drm_device *dev, struct drm_cmdline_mode *cmd);
-
-/* drm_edid.c */
-u8 *drm_find_cea_extension(struct edid *edid);
-
-/* Inline replacements for drm_alloc and friends */
-static __inline__ void *
-drm_alloc(size_t size, struct malloc_type *area)
+static inline void
+drm_gem_object_reference(struct drm_gem_object *obj)
{
- return malloc(size, area, M_NOWAIT);
-}
-static __inline__ void *
-drm_calloc(size_t nmemb, size_t size, struct malloc_type *area)
-{
- return malloc(size * nmemb, area, M_NOWAIT | M_ZERO);
+ KASSERT(obj->refcount > 0, ("Dangling obj %p", obj));
+ refcount_acquire(&obj->refcount);
}
-static __inline__ void *
-drm_realloc(void *oldpt, size_t oldsize, size_t size,
- struct malloc_type *area)
+static inline void
+drm_gem_object_unreference(struct drm_gem_object *obj)
{
- return reallocf(oldpt, size, area, M_NOWAIT);
+
+ if (obj == NULL)
+ return;
+ if (refcount_release(&obj->refcount))
+ drm_gem_object_free(obj);
}
-static __inline__ void
-drm_free(void *pt, size_t size, struct malloc_type *area)
+static inline void
+drm_gem_object_unreference_unlocked(struct drm_gem_object *obj)
{
- free(pt, area);
+ if (obj != NULL) {
+ struct drm_device *dev = obj->dev;
+ DRM_LOCK(dev);
+ drm_gem_object_unreference(obj);
+ DRM_UNLOCK(dev);
+ }
}
-/* Inline replacements for DRM_IOREMAP macros */
-static __inline__ void
-drm_core_ioremap_wc(struct drm_local_map *map, struct drm_device *dev)
+int drm_gem_handle_create(struct drm_file *file_priv,
+ struct drm_gem_object *obj,
+ u32 *handlep);
+int drm_gem_handle_delete(struct drm_file *filp, u32 handle);
+
+static inline void
+drm_gem_object_handle_reference(struct drm_gem_object *obj)
{
- map->virtual = drm_ioremap_wc(dev, map);
+ drm_gem_object_reference(obj);
+ atomic_inc(&obj->handle_count);
}
-static __inline__ void
-drm_core_ioremap(struct drm_local_map *map, struct drm_device *dev)
+
+static inline void
+drm_gem_object_handle_unreference(struct drm_gem_object *obj)
{
- map->virtual = drm_ioremap(dev, map);
+ if (obj == NULL)
+ return;
+
+ if (atomic_read(&obj->handle_count) == 0)
+ return;
+ /*
+ * Must bump handle count first as this may be the last
+ * ref, in which case the object would disappear before we
+ * checked for a name
+ */
+ if (atomic_dec_and_test(&obj->handle_count))
+ drm_gem_object_handle_free(obj);
+ drm_gem_object_unreference(obj);
}
-static __inline__ void
-drm_core_ioremapfree(struct drm_local_map *map, struct drm_device *dev)
+
+static inline void
+drm_gem_object_handle_unreference_unlocked(struct drm_gem_object *obj)
{
- if ( map->virtual && map->size )
- drm_ioremapfree(map);
+ if (obj == NULL)
+ return;
+
+ if (atomic_read(&obj->handle_count) == 0)
+ return;
+
+ /*
+ * Must bump handle count first as this may be the last
+ * ref, in which case the object would disappear before we
+ * checked for a name
+ */
+
+ if (atomic_dec_and_test(&obj->handle_count))
+ drm_gem_object_handle_free(obj);
+ drm_gem_object_unreference_unlocked(obj);
}
-static __inline__ struct drm_local_map *
-drm_core_findmap(struct drm_device *dev, unsigned long offset)
-{
- drm_local_map_t *map;
+void drm_gem_free_mmap_offset(struct drm_gem_object *obj);
+int drm_gem_create_mmap_offset(struct drm_gem_object *obj);
- DRM_LOCK_ASSERT(dev);
- TAILQ_FOREACH(map, &dev->maplist, link) {
- if (offset == (unsigned long)map->handle)
- return map;
- }
+struct drm_gem_object *drm_gem_object_lookup(struct drm_device *dev,
+ struct drm_file *filp,
+ u32 handle);
+int drm_gem_close_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+int drm_gem_flink_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+int drm_gem_open_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+void drm_gem_open(struct drm_device *dev, struct drm_file *file_private);
+void drm_gem_release(struct drm_device *dev, struct drm_file *file_private);
+
+extern void drm_core_ioremap(struct drm_local_map *map, struct drm_device *dev);
+extern void drm_core_ioremap_wc(struct drm_local_map *map, struct drm_device *dev);
+extern void drm_core_ioremapfree(struct drm_local_map *map, struct drm_device *dev);
+
+static __inline__ struct drm_local_map *drm_core_findmap(struct drm_device *dev,
+ unsigned int token)
+{
+ struct drm_map_list *_entry;
+ list_for_each_entry(_entry, &dev->maplist, head)
+ if (_entry->user_token == token)
+ return _entry->map;
return NULL;
}
-static __inline__ void drm_core_dropmap(struct drm_map *map)
+static __inline__ void drm_core_dropmap(struct drm_local_map *map)
{
}
+extern int drm_fill_in_dev(struct drm_device *dev,
+ struct drm_driver *driver);
+extern void drm_cancel_fill_in_dev(struct drm_device *dev);
+int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int type);
+/*@}*/
+
+/* PCI section */
+int drm_pci_device_is_agp(struct drm_device *dev);
+int drm_pci_device_is_pcie(struct drm_device *dev);
+
+extern int drm_get_pci_dev(device_t kdev, struct drm_device *dev,
+ struct drm_driver *driver);
+
#define DRM_PCIE_SPEED_25 1
#define DRM_PCIE_SPEED_50 2
#define DRM_PCIE_SPEED_80 4
@@ -1515,5 +1579,210 @@ extern int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *speed_mask);
#define drm_can_sleep() (DRM_HZ & 1)
-#endif /* __KERNEL__ */
-#endif /* _DRM_P_H_ */
+/* FreeBSD specific -- should be moved to drm_os_freebsd.h */
+
+#define DRM_GEM_MAPPING_MASK (3ULL << 62)
+#define DRM_GEM_MAPPING_KEY (2ULL << 62) /* Non-canonical address form */
+#define DRM_GEM_MAX_IDX 0x3fffff
+#define DRM_GEM_MAPPING_IDX(o) (((o) >> 40) & DRM_GEM_MAX_IDX)
+#define DRM_GEM_MAPPING_OFF(i) (((uint64_t)(i)) << 40)
+#define DRM_GEM_MAPPING_MAPOFF(o) \
+ ((o) & ~(DRM_GEM_MAPPING_OFF(DRM_GEM_MAX_IDX) | DRM_GEM_MAPPING_KEY))
+
+SYSCTL_DECL(_hw_drm);
+
+#define DRM_DEV_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP)
+#define DRM_DEV_UID 0
+#define DRM_DEV_GID 0
+
+#define DRM_WAKEUP(w) wakeup((void *)w)
+#define DRM_WAKEUP_INT(w) wakeup(w)
+#define DRM_INIT_WAITQUEUE(queue) do {(void)(queue);} while (0)
+
+#define DRM_CURPROC curthread
+#define DRM_STRUCTPROC struct thread
+#define DRM_SPINTYPE struct mtx
+#define DRM_SPININIT(l,name) mtx_init(l, name, NULL, MTX_DEF)
+#define DRM_SPINUNINIT(l) mtx_destroy(l)
+#define DRM_SPINLOCK(l) mtx_lock(l)
+#define DRM_SPINUNLOCK(u) mtx_unlock(u)
+#define DRM_SPINLOCK_IRQSAVE(l, irqflags) do { \
+ mtx_lock(l); \
+ (void)irqflags; \
+} while (0)
+#define DRM_SPINUNLOCK_IRQRESTORE(u, irqflags) mtx_unlock(u)
+#define DRM_SPINLOCK_ASSERT(l) mtx_assert(l, MA_OWNED)
+#define DRM_LOCK_SLEEP(dev, chan, flags, msg, timeout) \
+ (sx_sleep((chan), &(dev)->dev_struct_lock, (flags), (msg), (timeout)))
+#if defined(INVARIANTS)
+#define DRM_LOCK_ASSERT(dev) sx_assert(&(dev)->dev_struct_lock, SA_XLOCKED)
+#define DRM_UNLOCK_ASSERT(dev) sx_assert(&(dev)->dev_struct_lock, SA_UNLOCKED)
+#else
+#define DRM_LOCK_ASSERT(d)
+#define DRM_UNLOCK_ASSERT(d)
+#endif
+
+#define DRM_SYSCTL_HANDLER_ARGS (SYSCTL_HANDLER_ARGS)
+
+enum {
+ DRM_IS_NOT_AGP,
+ DRM_IS_AGP,
+ DRM_MIGHT_BE_AGP
+};
+
+#define DRM_VERIFYAREA_READ( uaddr, size ) \
+ (!useracc(__DECONST(caddr_t, uaddr), size, VM_PROT_READ))
+
+#define DRM_COPY_TO_USER(user, kern, size) \
+ copyout(kern, user, size)
+#define DRM_COPY_FROM_USER(kern, user, size) \
+ copyin(user, kern, size)
+#define DRM_COPY_FROM_USER_UNCHECKED(arg1, arg2, arg3) \
+ copyin(arg2, arg1, arg3)
+#define DRM_COPY_TO_USER_UNCHECKED(arg1, arg2, arg3) \
+ copyout(arg2, arg1, arg3)
+#define DRM_GET_USER_UNCHECKED(val, uaddr) \
+ ((val) = fuword32(uaddr), 0)
+
+#define DRM_GET_PRIV_SAREA(_dev, _ctx, _map) do { \
+ (_map) = (_dev)->context_sareas[_ctx]; \
+} while(0)
+
+/* Returns -errno to shared code */
+#define DRM_WAIT_ON( ret, queue, timeout, condition ) \
+for ( ret = 0 ; !ret && !(condition) ; ) { \
+ DRM_UNLOCK(dev); \
+ mtx_lock(&dev->irq_lock); \
+ if (!(condition)) \
+ ret = -mtx_sleep(&(queue), &dev->irq_lock, \
+ PCATCH, "drmwtq", (timeout)); \
+ if (ret == -ERESTART) \
+ ret = -ERESTARTSYS; \
+ mtx_unlock(&dev->irq_lock); \
+ DRM_LOCK(dev); \
+}
+
+#define dev_err(dev, fmt, ...) \
+ device_printf((dev), "error: " fmt, ## __VA_ARGS__)
+#define dev_warn(dev, fmt, ...) \
+ device_printf((dev), "warning: " fmt, ## __VA_ARGS__)
+#define dev_info(dev, fmt, ...) \
+ device_printf((dev), "info: " fmt, ## __VA_ARGS__)
+#define dev_dbg(dev, fmt, ...) do { \
+ if ((drm_debug& DRM_DEBUGBITS_KMS) != 0) { \
+ device_printf((dev), "debug: " fmt, ## __VA_ARGS__); \
+ } \
+} while (0)
+
+struct drm_msi_blacklist_entry
+{
+ int vendor;
+ int device;
+};
+
+struct drm_vblank_info {
+ wait_queue_head_t queue; /* vblank wait queue */
+ atomic_t count; /* number of VBLANK interrupts */
+ /* (driver must alloc the right number of counters) */
+ atomic_t refcount; /* number of users of vblank interrupts */
+ u32 last; /* protected by dev->vbl_lock, used */
+ /* for wraparound handling */
+ int enabled; /* so we don't call enable more than */
+ /* once per disable */
+ int inmodeset; /* Display driver is setting mode */
+};
+
+#ifndef DMA_BIT_MASK
+#define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : (1ULL<<(n)) - 1)
+#endif
+
+#define upper_32_bits(n) ((u32)(((n) >> 16) >> 16))
+
+enum dmi_field {
+ DMI_NONE,
+ DMI_BIOS_VENDOR,
+ DMI_BIOS_VERSION,
+ DMI_BIOS_DATE,
+ DMI_SYS_VENDOR,
+ DMI_PRODUCT_NAME,
+ DMI_PRODUCT_VERSION,
+ DMI_PRODUCT_SERIAL,
+ DMI_PRODUCT_UUID,
+ DMI_BOARD_VENDOR,
+ DMI_BOARD_NAME,
+ DMI_BOARD_VERSION,
+ DMI_BOARD_SERIAL,
+ DMI_BOARD_ASSET_TAG,
+ DMI_CHASSIS_VENDOR,
+ DMI_CHASSIS_TYPE,
+ DMI_CHASSIS_VERSION,
+ DMI_CHASSIS_SERIAL,
+ DMI_CHASSIS_ASSET_TAG,
+ DMI_STRING_MAX,
+};
+
+struct dmi_strmatch {
+ unsigned char slot;
+ char substr[79];
+};
+
+struct dmi_system_id {
+ int (*callback)(const struct dmi_system_id *);
+ const char *ident;
+ struct dmi_strmatch matches[4];
+};
+#define DMI_MATCH(a, b) {(a), (b)}
+bool dmi_check_system(const struct dmi_system_id *);
+
+/* Device setup support (drm_drv.c) */
+int drm_probe_helper(device_t kdev, drm_pci_id_list_t *idlist);
+int drm_attach_helper(device_t kdev, drm_pci_id_list_t *idlist,
+ struct drm_driver *driver);
+int drm_generic_detach(device_t kdev);
+
+void drm_event_wakeup(struct drm_pending_event *e);
+
+int drm_add_busid_modesetting(struct drm_device *dev,
+ struct sysctl_ctx_list *ctx, struct sysctl_oid *top);
+
+/* Buffer management support (drm_bufs.c) */
+unsigned long drm_get_resource_start(struct drm_device *dev,
+ unsigned int resource);
+unsigned long drm_get_resource_len(struct drm_device *dev,
+ unsigned int resource);
+
+/* IRQ support (drm_irq.c) */
+irqreturn_t drm_irq_handler(DRM_IRQ_ARGS);
+void drm_driver_irq_preinstall(struct drm_device *dev);
+void drm_driver_irq_postinstall(struct drm_device *dev);
+void drm_driver_irq_uninstall(struct drm_device *dev);
+
+/* AGP/PCI Express/GART support (drm_agpsupport.c) */
+void *drm_agp_allocate_memory(size_t pages, u32 type);
+int drm_agp_free_memory(void *handle);
+int drm_agp_bind_memory(void *handle, off_t start);
+int drm_agp_unbind_memory(void *handle);
+
+/* sysctl support (drm_sysctl.h) */
+extern int drm_sysctl_init(struct drm_device *dev);
+extern int drm_sysctl_cleanup(struct drm_device *dev);
+
+int drm_version(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+
+/* consistent PCI memory functions (drm_pci.c) */
+int drm_pci_set_busid(struct drm_device *dev, struct drm_master *master);
+int drm_pci_set_unique(struct drm_device *dev, struct drm_master *master,
+ struct drm_unique *u);
+int drm_pci_agp_init(struct drm_device *dev);
+int drm_pci_enable_msi(struct drm_device *dev);
+void drm_pci_disable_msi(struct drm_device *dev);
+
+struct ttm_bo_device;
+int ttm_bo_mmap_single(struct ttm_bo_device *bdev, vm_ooffset_t *offset,
+ vm_size_t size, struct vm_object **obj_res, int nprot);
+struct ttm_buffer_object;
+void ttm_bo_release_mmap(struct ttm_buffer_object *bo);
+
+#endif /* __KERNEL__ */
+#endif
diff --git a/sys/dev/drm2/drm_agpsupport.c b/sys/dev/drm2/drm_agpsupport.c
index 1f487e3..131a9ad 100644
--- a/sys/dev/drm2/drm_agpsupport.c
+++ b/sys/dev/drm2/drm_agpsupport.c
@@ -1,4 +1,12 @@
-/*-
+/**
+ * \file drm_agpsupport.c
+ * DRM support for AGP/GART backend
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
* All Rights Reserved.
@@ -21,64 +29,36 @@
* 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.
- *
- * Author:
- * Rickard E. (Rik) Faith <faith@valinux.com>
- * Gareth Hughes <gareth@valinux.com>
- *
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-/** @file drm_agpsupport.c
- * Support code for tying the kernel AGP support to DRM drivers and
- * the DRM's AGP ioctls.
- */
-
#include <dev/drm2/drmP.h>
-#include <dev/agp/agpreg.h>
-#include <dev/pci/pcireg.h>
-
-/* Returns 1 if AGP or 0 if not. */
-static int
-drm_device_find_capability(struct drm_device *dev, int cap)
-{
-
- return (pci_find_cap(dev->device, cap, NULL) == 0);
-}
-
-int drm_device_is_agp(struct drm_device *dev)
-{
- if (dev->driver->device_is_agp != NULL) {
- int ret;
-
- /* device_is_agp returns a tristate, 0 = not AGP, 1 = definitely
- * AGP, 2 = fall back to PCI capability
- */
- ret = (*dev->driver->device_is_agp)(dev);
- if (ret != DRM_MIGHT_BE_AGP)
- return ret;
- }
-
- return (drm_device_find_capability(dev, PCIY_AGP));
-}
-
-int drm_device_is_pcie(struct drm_device *dev)
-{
- return (drm_device_find_capability(dev, PCIY_EXPRESS));
-}
+#if __OS_HAS_AGP
-int drm_agp_info(struct drm_device * dev, struct drm_agp_info *info)
+/**
+ * Get AGP information.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg pointer to a (output) drm_agp_info structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies the AGP device has been initialized and acquired and fills in the
+ * drm_agp_info structure with the information in drm_agp_head::agp_info.
+ */
+int drm_agp_info(struct drm_device *dev, struct drm_agp_info *info)
{
- struct agp_info *kern;
+ DRM_AGP_KERN *kern;
if (!dev->agp || !dev->agp->acquired)
- return EINVAL;
+ return -EINVAL;
- kern = &dev->agp->info;
- agp_get_info(dev->agp->agpdev, kern);
+ kern = &dev->agp->agp_info;
+ agp_get_info(dev->agp->bridge, kern);
info->agp_version_major = 1;
info->agp_version_minor = 0;
info->mode = kern->ai_mode;
@@ -92,343 +72,397 @@ int drm_agp_info(struct drm_device * dev, struct drm_agp_info *info)
return 0;
}
+EXPORT_SYMBOL(drm_agp_info);
+
int drm_agp_info_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
+ struct drm_agp_info *info = data;
int err;
- struct drm_agp_info info;
- err = drm_agp_info(dev, &info);
- if (err != 0)
+ err = drm_agp_info(dev, info);
+ if (err)
return err;
- *(struct drm_agp_info *) data = info;
return 0;
}
-int drm_agp_acquire_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
-
- return drm_agp_acquire(dev);
-}
-
-int drm_agp_acquire(struct drm_device *dev)
+/**
+ * Acquire the AGP device.
+ *
+ * \param dev DRM device that is to acquire AGP.
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies the AGP device hasn't been acquired before and calls
+ * \c agp_backend_acquire.
+ */
+int drm_agp_acquire(struct drm_device * dev)
{
int retcode;
- if (!dev->agp || dev->agp->acquired)
- return EINVAL;
-
- retcode = agp_acquire(dev->agp->agpdev);
+ if (!dev->agp)
+ return -ENODEV;
+ if (dev->agp->acquired)
+ return -EBUSY;
+ retcode = agp_acquire(dev->agp->bridge);
if (retcode)
- return retcode;
-
+ return -retcode;
dev->agp->acquired = 1;
return 0;
}
-int drm_agp_release_ioctl(struct drm_device *dev, void *data,
+EXPORT_SYMBOL(drm_agp_acquire);
+
+/**
+ * Acquire the AGP device (ioctl).
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument.
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies the AGP device hasn't been acquired before and calls
+ * \c agp_backend_acquire.
+ */
+int drm_agp_acquire_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
-
- return drm_agp_release(dev);
+ return drm_agp_acquire((struct drm_device *) file_priv->minor->dev);
}
+/**
+ * Release the AGP device.
+ *
+ * \param dev DRM device that is to release AGP.
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies the AGP device has been acquired and calls \c agp_backend_release.
+ */
int drm_agp_release(struct drm_device * dev)
{
if (!dev->agp || !dev->agp->acquired)
- return EINVAL;
- agp_release(dev->agp->agpdev);
+ return -EINVAL;
+ agp_release(dev->agp->bridge);
dev->agp->acquired = 0;
return 0;
}
+EXPORT_SYMBOL(drm_agp_release);
-int drm_agp_enable(struct drm_device *dev, struct drm_agp_mode mode)
+int drm_agp_release_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
+ return drm_agp_release(dev);
+}
+/**
+ * Enable the AGP bus.
+ *
+ * \param dev DRM device that has previously acquired AGP.
+ * \param mode Requested AGP mode.
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies the AGP device has been acquired but not enabled, and calls
+ * \c agp_enable.
+ */
+int drm_agp_enable(struct drm_device * dev, struct drm_agp_mode mode)
+{
if (!dev->agp || !dev->agp->acquired)
- return EINVAL;
-
- dev->agp->mode = mode.mode;
- agp_enable(dev->agp->agpdev, mode.mode);
+ return -EINVAL;
+
+ dev->agp->mode = mode.mode;
+ agp_enable(dev->agp->bridge, mode.mode);
dev->agp->enabled = 1;
return 0;
}
+EXPORT_SYMBOL(drm_agp_enable);
+
int drm_agp_enable_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
- struct drm_agp_mode mode;
+ struct drm_agp_mode *mode = data;
- mode = *(struct drm_agp_mode *) data;
-
- return drm_agp_enable(dev, mode);
+ return drm_agp_enable(dev, *mode);
}
+/**
+ * Allocate AGP memory.
+ *
+ * \param inode device inode.
+ * \param file_priv file private pointer.
+ * \param cmd command.
+ * \param arg pointer to a drm_agp_buffer structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies the AGP device is present and has been acquired, allocates the
+ * memory via agp_allocate_memory() and creates a drm_agp_mem entry for it.
+ */
int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request)
{
- drm_agp_mem_t *entry;
- void *handle;
- unsigned long pages;
- u_int32_t type;
+ struct drm_agp_mem *entry;
+ DRM_AGP_MEM *memory;
+ unsigned long pages;
+ u32 type;
struct agp_memory_info info;
if (!dev->agp || !dev->agp->acquired)
- return EINVAL;
+ return -EINVAL;
+ if (!(entry = malloc(sizeof(*entry), DRM_MEM_AGPLISTS, M_NOWAIT)))
+ return -ENOMEM;
- entry = malloc(sizeof(*entry), DRM_MEM_AGPLISTS, M_NOWAIT | M_ZERO);
- if (entry == NULL)
- return ENOMEM;
+ memset(entry, 0, sizeof(*entry));
pages = (request->size + PAGE_SIZE - 1) / PAGE_SIZE;
- type = (u_int32_t) request->type;
-
- DRM_UNLOCK(dev);
- handle = drm_agp_allocate_memory(pages, type);
- DRM_LOCK(dev);
- if (handle == NULL) {
+ type = (u32) request->type;
+ if (!(memory = agp_alloc_memory(dev->agp->bridge, type, pages << PAGE_SHIFT))) {
free(entry, DRM_MEM_AGPLISTS);
- return ENOMEM;
+ return -ENOMEM;
}
-
- entry->handle = handle;
- entry->bound = 0;
- entry->pages = pages;
- entry->prev = NULL;
- entry->next = dev->agp->memory;
- if (dev->agp->memory)
- dev->agp->memory->prev = entry;
- dev->agp->memory = entry;
- agp_memory_info(dev->agp->agpdev, entry->handle, &info);
+ entry->handle = (unsigned long)memory;
+ entry->memory = memory;
+ entry->bound = 0;
+ entry->pages = pages;
+ list_add(&entry->head, &dev->agp->memory);
+
+ agp_memory_info(dev->agp->bridge, entry->memory, &info);
- request->handle = (unsigned long) entry->handle;
- request->physical = info.ami_physical;
+ request->handle = entry->handle;
+ request->physical = info.ami_physical;
return 0;
}
+EXPORT_SYMBOL(drm_agp_alloc);
+
int drm_agp_alloc_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
- struct drm_agp_buffer request;
- int retcode;
+ struct drm_agp_buffer *request = data;
- request = *(struct drm_agp_buffer *) data;
-
- DRM_LOCK(dev);
- retcode = drm_agp_alloc(dev, &request);
- DRM_UNLOCK(dev);
-
- *(struct drm_agp_buffer *) data = request;
-
- return retcode;
+ return drm_agp_alloc(dev, request);
}
-static drm_agp_mem_t * drm_agp_lookup_entry(struct drm_device *dev,
- void *handle)
+/**
+ * Search for the AGP memory entry associated with a handle.
+ *
+ * \param dev DRM device structure.
+ * \param handle AGP memory handle.
+ * \return pointer to the drm_agp_mem structure associated with \p handle.
+ *
+ * Walks through drm_agp_head::memory until finding a matching handle.
+ */
+static struct drm_agp_mem *drm_agp_lookup_entry(struct drm_device * dev,
+ unsigned long handle)
{
- drm_agp_mem_t *entry;
+ struct drm_agp_mem *entry;
- for (entry = dev->agp->memory; entry; entry = entry->next) {
- if (entry->handle == handle) return entry;
+ list_for_each_entry(entry, &dev->agp->memory, head) {
+ if (entry->handle == handle)
+ return entry;
}
return NULL;
}
+/**
+ * Unbind AGP memory from the GATT (ioctl).
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg pointer to a drm_agp_binding structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies the AGP device is present and acquired, looks-up the AGP memory
+ * entry and passes it to the unbind_agp() function.
+ */
int drm_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request)
{
- drm_agp_mem_t *entry;
- int retcode;
+ struct drm_agp_mem *entry;
+ int ret;
if (!dev->agp || !dev->agp->acquired)
- return EINVAL;
-
- entry = drm_agp_lookup_entry(dev, (void *)request->handle);
- if (entry == NULL || !entry->bound)
- return EINVAL;
-
- DRM_UNLOCK(dev);
- retcode = drm_agp_unbind_memory(entry->handle);
- DRM_LOCK(dev);
-
- if (retcode == 0)
+ return -EINVAL;
+ if (!(entry = drm_agp_lookup_entry(dev, request->handle)))
+ return -EINVAL;
+ if (!entry->bound)
+ return -EINVAL;
+ ret = drm_unbind_agp(entry->memory);
+ if (ret == 0)
entry->bound = 0;
-
- return retcode;
+ return ret;
}
+EXPORT_SYMBOL(drm_agp_unbind);
+
int drm_agp_unbind_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
- struct drm_agp_binding request;
- int retcode;
-
- request = *(struct drm_agp_binding *) data;
+ struct drm_agp_binding *request = data;
- DRM_LOCK(dev);
- retcode = drm_agp_unbind(dev, &request);
- DRM_UNLOCK(dev);
-
- return retcode;
+ return drm_agp_unbind(dev, request);
}
+/**
+ * Bind AGP memory into the GATT (ioctl)
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg pointer to a drm_agp_binding structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies the AGP device is present and has been acquired and that no memory
+ * is currently bound into the GATT. Looks-up the AGP memory entry and passes
+ * it to bind_agp() function.
+ */
int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request)
{
- drm_agp_mem_t *entry;
- int retcode;
- int page;
-
- if (!dev->agp || !dev->agp->acquired)
- return EINVAL;
-
- DRM_DEBUG("agp_bind, page_size=%x\n", (int)PAGE_SIZE);
-
- entry = drm_agp_lookup_entry(dev, (void *)request->handle);
- if (entry == NULL || entry->bound)
- return EINVAL;
+ struct drm_agp_mem *entry;
+ int retcode;
+ int page;
+ if (!dev->agp || !dev->agp->acquired)
+ return -EINVAL;
+ if (!(entry = drm_agp_lookup_entry(dev, request->handle)))
+ return -EINVAL;
+ if (entry->bound)
+ return -EINVAL;
page = (request->offset + PAGE_SIZE - 1) / PAGE_SIZE;
-
- DRM_UNLOCK(dev);
- retcode = drm_agp_bind_memory(entry->handle, page);
- DRM_LOCK(dev);
- if (retcode == 0)
- entry->bound = dev->agp->base + (page << PAGE_SHIFT);
-
- return retcode;
+ if ((retcode = drm_bind_agp(entry->memory, page)))
+ return retcode;
+ entry->bound = dev->agp->base + (page << PAGE_SHIFT);
+ DRM_DEBUG("base = 0x%lx entry->bound = 0x%lx\n",
+ dev->agp->base, entry->bound);
+ return 0;
}
+EXPORT_SYMBOL(drm_agp_bind);
+
int drm_agp_bind_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
- struct drm_agp_binding request;
- int retcode;
-
- request = *(struct drm_agp_binding *) data;
+ struct drm_agp_binding *request = data;
- DRM_LOCK(dev);
- retcode = drm_agp_bind(dev, &request);
- DRM_UNLOCK(dev);
-
- return retcode;
+ return drm_agp_bind(dev, request);
}
+/**
+ * Free AGP memory (ioctl).
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg pointer to a drm_agp_buffer structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies the AGP device is present and has been acquired and looks up the
+ * AGP memory entry. If the memory it's currently bound, unbind it via
+ * unbind_agp(). Frees it via free_agp() as well as the entry itself
+ * and unlinks from the doubly linked list it's inserted in.
+ */
int drm_agp_free(struct drm_device *dev, struct drm_agp_buffer *request)
{
- drm_agp_mem_t *entry;
-
+ struct drm_agp_mem *entry;
+
if (!dev->agp || !dev->agp->acquired)
- return EINVAL;
-
- entry = drm_agp_lookup_entry(dev, (void*)request->handle);
- if (entry == NULL)
- return EINVAL;
-
- if (entry->prev)
- entry->prev->next = entry->next;
- else
- dev->agp->memory = entry->next;
- if (entry->next)
- entry->next->prev = entry->prev;
-
- DRM_UNLOCK(dev);
+ return -EINVAL;
+ if (!(entry = drm_agp_lookup_entry(dev, request->handle)))
+ return -EINVAL;
if (entry->bound)
- drm_agp_unbind_memory(entry->handle);
- drm_agp_free_memory(entry->handle);
- DRM_LOCK(dev);
+ drm_unbind_agp(entry->memory);
- free(entry, DRM_MEM_AGPLISTS);
+ list_del(&entry->head);
+ drm_free_agp(entry->memory, entry->pages);
+ free(entry, DRM_MEM_AGPLISTS);
return 0;
-
}
+EXPORT_SYMBOL(drm_agp_free);
+
+
int drm_agp_free_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
- struct drm_agp_buffer request;
- int retcode;
-
- request = *(struct drm_agp_buffer *) data;
-
- DRM_LOCK(dev);
- retcode = drm_agp_free(dev, &request);
- DRM_UNLOCK(dev);
+ struct drm_agp_buffer *request = data;
- return retcode;
+ return drm_agp_free(dev, request);
}
-drm_agp_head_t *drm_agp_init(void)
-{
- device_t agpdev;
- drm_agp_head_t *head = NULL;
- int agp_available = 1;
-
- agpdev = DRM_AGP_FIND_DEVICE();
- if (!agpdev)
- agp_available = 0;
-
- DRM_DEBUG("agp_available = %d\n", agp_available);
-
- if (agp_available) {
- head = malloc(sizeof(*head), DRM_MEM_AGPLISTS,
- M_NOWAIT | M_ZERO);
- if (head == NULL)
- return NULL;
- head->agpdev = agpdev;
- agp_get_info(agpdev, &head->info);
- head->base = head->info.ai_aperture_base;
- head->memory = NULL;
- DRM_INFO("AGP at 0x%08lx %dMB\n",
- (long)head->info.ai_aperture_base,
- (int)(head->info.ai_aperture_size >> 20));
- }
- return head;
-}
-
-void *drm_agp_allocate_memory(size_t pages, u32 type)
+/**
+ * Initialize the AGP resources.
+ *
+ * \return pointer to a drm_agp_head structure.
+ *
+ * Gets the drm_agp_t structure which is made available by the agpgart module
+ * via the inter_module_* functions. Creates and initializes a drm_agp_head
+ * structure.
+ */
+struct drm_agp_head *drm_agp_init(struct drm_device *dev)
{
- device_t agpdev;
+ struct drm_agp_head *head = NULL;
- agpdev = DRM_AGP_FIND_DEVICE();
- if (!agpdev)
+ if (!(head = malloc(sizeof(*head), DRM_MEM_AGPLISTS, M_NOWAIT)))
return NULL;
-
- return agp_alloc_memory(agpdev, type, pages << PAGE_SHIFT);
+ memset((void *)head, 0, sizeof(*head));
+ head->bridge = agp_find_device();
+ if (!head->bridge) {
+ free(head, DRM_MEM_AGPLISTS);
+ return NULL;
+ } else {
+ agp_get_info(head->bridge, &head->agp_info);
+ }
+ INIT_LIST_HEAD(&head->memory);
+ head->cant_use_aperture = 0;
+ head->base = head->agp_info.ai_aperture_base;
+ return head;
}
-int drm_agp_free_memory(void *handle)
+#ifdef FREEBSD_NOTYET
+/**
+ * Binds a collection of pages into AGP memory at the given offset, returning
+ * the AGP memory structure containing them.
+ *
+ * No reference is held on the pages during this time -- it is up to the
+ * caller to handle that.
+ */
+DRM_AGP_MEM *
+drm_agp_bind_pages(struct drm_device *dev,
+ struct page **pages,
+ unsigned long num_pages,
+ uint32_t gtt_offset,
+ u32 type)
{
- device_t agpdev;
+ DRM_AGP_MEM *mem;
+ int ret, i;
- agpdev = DRM_AGP_FIND_DEVICE();
- if (!agpdev || !handle)
- return 0;
+ DRM_DEBUG("\n");
- agp_free_memory(agpdev, handle);
- return 1;
-}
+ mem = agp_allocate_memory(dev->agp->bridge, num_pages,
+ type);
+ if (mem == NULL) {
+ DRM_ERROR("Failed to allocate memory for %ld pages\n",
+ num_pages);
+ return NULL;
+ }
-int drm_agp_bind_memory(void *handle, off_t start)
-{
- device_t agpdev;
+ for (i = 0; i < num_pages; i++)
+ mem->pages[i] = pages[i];
+ mem->page_count = num_pages;
- agpdev = DRM_AGP_FIND_DEVICE();
- if (!agpdev || !handle)
- return EINVAL;
+ mem->is_flushed = true;
+ ret = agp_bind_memory(mem, gtt_offset / PAGE_SIZE);
+ if (ret != 0) {
+ DRM_ERROR("Failed to bind AGP memory: %d\n", ret);
+ agp_free_memory(mem);
+ return NULL;
+ }
- return agp_bind_memory(agpdev, handle, start * PAGE_SIZE);
+ return mem;
}
+EXPORT_SYMBOL(drm_agp_bind_pages);
+#endif /* FREEBSD_NOTYET */
-int drm_agp_unbind_memory(void *handle)
-{
- device_t agpdev;
-
- agpdev = DRM_AGP_FIND_DEVICE();
- if (!agpdev || !handle)
- return EINVAL;
-
- return agp_unbind_memory(agpdev, handle);
-}
+#endif /* __OS_HAS_AGP */
diff --git a/sys/dev/drm2/drm_atomic.h b/sys/dev/drm2/drm_atomic.h
index eb86373..fd84922 100644
--- a/sys/dev/drm2/drm_atomic.h
+++ b/sys/dev/drm2/drm_atomic.h
@@ -36,12 +36,15 @@ __FBSDID("$FreeBSD$");
typedef u_int atomic_t;
typedef uint64_t atomic64_t;
-#define BITS_PER_LONG (sizeof(long) * NBBY)
-#define BITS_TO_LONGS(x) howmany(x, BITS_PER_LONG)
+#define NB_BITS_PER_LONG (sizeof(long) * NBBY)
+#define BITS_TO_LONGS(x) howmany(x, NB_BITS_PER_LONG)
#define atomic_read(p) (*(volatile u_int *)(p))
#define atomic_set(p, v) do { *(u_int *)(p) = (v); } while (0)
+#define atomic64_read(p) atomic_load_acq_64(p)
+#define atomic64_set(p, v) atomic_store_rel_64(p, v)
+
#define atomic_add(v, p) atomic_add_int(p, v)
#define atomic_sub(v, p) atomic_subtract_int(p, v)
#define atomic_inc(p) atomic_add(1, p)
@@ -60,8 +63,8 @@ typedef uint64_t atomic64_t;
#define atomic_xchg(p, v) atomic_swap_int(p, v)
#define atomic64_xchg(p, v) atomic_swap_64(p, v)
-#define __bit_word(b) ((b) / BITS_PER_LONG)
-#define __bit_mask(b) (1UL << (b) % BITS_PER_LONG)
+#define __bit_word(b) ((b) / NB_BITS_PER_LONG)
+#define __bit_mask(b) (1UL << (b) % NB_BITS_PER_LONG)
#define __bit_addr(p, b) ((volatile u_long *)(p) + __bit_word(b))
#define clear_bit(b, p) \
@@ -70,17 +73,21 @@ typedef uint64_t atomic64_t;
atomic_set_long(__bit_addr(p, b), __bit_mask(b))
#define test_bit(b, p) \
((*__bit_addr(p, b) & __bit_mask(b)) != 0)
+#define test_and_set_bit(b, p) \
+ (atomic_xchg((p), 1) != b)
+#define cmpxchg(ptr, old, new) \
+ (atomic_cmpset_int((volatile u_int *)(ptr),(old),(new)) ? (old) : (0))
static __inline u_long
find_first_zero_bit(const u_long *p, u_long max)
{
u_long i, n;
- KASSERT(max % BITS_PER_LONG == 0, ("invalid bitmap size %lu", max));
- for (i = 0; i < max / BITS_PER_LONG; i++) {
+ KASSERT(max % NB_BITS_PER_LONG == 0, ("invalid bitmap size %lu", max));
+ for (i = 0; i < max / NB_BITS_PER_LONG; i++) {
n = ~p[i];
if (n != 0)
- return (i * BITS_PER_LONG + ffsl(n) - 1);
+ return (i * NB_BITS_PER_LONG + ffsl(n) - 1);
}
return (max);
}
diff --git a/sys/dev/drm2/drm_auth.c b/sys/dev/drm2/drm_auth.c
index 69acff9..f377c00 100644
--- a/sys/dev/drm2/drm_auth.c
+++ b/sys/dev/drm2/drm_auth.c
@@ -1,4 +1,14 @@
-/*-
+/**
+ * \file drm_auth.c
+ * IOCTLs for authentication
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
+ * Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com
+ *
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
* All Rights Reserved.
@@ -21,121 +31,118 @@
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Rickard E. (Rik) Faith <faith@valinux.com>
- * Gareth Hughes <gareth@valinux.com>
- *
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-/** @file drm_auth.c
- * Implementation of the get/authmagic ioctls implementing the authentication
- * scheme between the master and clients.
- */
-
#include <dev/drm2/drmP.h>
-static int drm_hash_magic(drm_magic_t magic)
-{
- return magic & (DRM_HASH_SIZE-1);
-}
+static struct mtx drm_magic_lock;
/**
- * Returns the file private associated with the given magic number.
+ * Find the file with the given magic number.
+ *
+ * \param dev DRM device.
+ * \param magic magic number.
+ *
+ * Searches in drm_device::magiclist within all files with the same hash key
+ * the one with matching magic number, while holding the drm_device::struct_mutex
+ * lock.
*/
-static struct drm_file *drm_find_file(struct drm_device *dev, drm_magic_t magic)
+static struct drm_file *drm_find_file(struct drm_master *master, drm_magic_t magic)
{
- drm_magic_entry_t *pt;
- int hash = drm_hash_magic(magic);
+ struct drm_file *retval = NULL;
+ struct drm_magic_entry *pt;
+ struct drm_hash_item *hash;
+ struct drm_device *dev = master->minor->dev;
- DRM_LOCK_ASSERT(dev);
-
- for (pt = dev->magiclist[hash].head; pt; pt = pt->next) {
- if (pt->magic == magic) {
- return pt->priv;
- }
+ DRM_LOCK(dev);
+ if (!drm_ht_find_item(&master->magiclist, (unsigned long)magic, &hash)) {
+ pt = drm_hash_entry(hash, struct drm_magic_entry, hash_item);
+ retval = pt->priv;
}
-
- return NULL;
+ DRM_UNLOCK(dev);
+ return retval;
}
/**
- * Inserts the given magic number into the hash table of used magic number
- * lists.
+ * Adds a magic number.
+ *
+ * \param dev DRM device.
+ * \param priv file private data.
+ * \param magic magic number.
+ *
+ * Creates a drm_magic_entry structure and appends to the linked list
+ * associated the magic number hash key in drm_device::magiclist, while holding
+ * the drm_device::struct_mutex lock.
*/
-static int drm_add_magic(struct drm_device *dev, struct drm_file *priv,
+static int drm_add_magic(struct drm_master *master, struct drm_file *priv,
drm_magic_t magic)
{
- int hash;
- drm_magic_entry_t *entry;
-
+ struct drm_magic_entry *entry;
+ struct drm_device *dev = master->minor->dev;
DRM_DEBUG("%d\n", magic);
- DRM_LOCK_ASSERT(dev);
-
- hash = drm_hash_magic(magic);
entry = malloc(sizeof(*entry), DRM_MEM_MAGIC, M_ZERO | M_NOWAIT);
if (!entry)
- return ENOMEM;
- entry->magic = magic;
- entry->priv = priv;
- entry->next = NULL;
-
- if (dev->magiclist[hash].tail) {
- dev->magiclist[hash].tail->next = entry;
- dev->magiclist[hash].tail = entry;
- } else {
- dev->magiclist[hash].head = entry;
- dev->magiclist[hash].tail = entry;
- }
+ return -ENOMEM;
+ entry->priv = priv;
+ entry->hash_item.key = (unsigned long)magic;
+ DRM_LOCK(dev);
+ drm_ht_insert_item(&master->magiclist, &entry->hash_item);
+ list_add_tail(&entry->head, &master->magicfree);
+ DRM_UNLOCK(dev);
return 0;
}
/**
- * Removes the given magic number from the hash table of used magic number
- * lists.
+ * Remove a magic number.
+ *
+ * \param dev DRM device.
+ * \param magic magic number.
+ *
+ * Searches and unlinks the entry in drm_device::magiclist with the magic
+ * number hash key, while holding the drm_device::struct_mutex lock.
*/
-static int drm_remove_magic(struct drm_device *dev, drm_magic_t magic)
+int drm_remove_magic(struct drm_master *master, drm_magic_t magic)
{
- drm_magic_entry_t *prev = NULL;
- drm_magic_entry_t *pt;
- int hash;
-
- DRM_LOCK_ASSERT(dev);
+ struct drm_magic_entry *pt;
+ struct drm_hash_item *hash;
+ struct drm_device *dev = master->minor->dev;
DRM_DEBUG("%d\n", magic);
- hash = drm_hash_magic(magic);
-
- for (pt = dev->magiclist[hash].head; pt; prev = pt, pt = pt->next) {
- if (pt->magic == magic) {
- if (dev->magiclist[hash].head == pt) {
- dev->magiclist[hash].head = pt->next;
- }
- if (dev->magiclist[hash].tail == pt) {
- dev->magiclist[hash].tail = prev;
- }
- if (prev) {
- prev->next = pt->next;
- }
- free(pt, DRM_MEM_MAGIC);
- return 0;
- }
+
+ DRM_LOCK(dev);
+ if (drm_ht_find_item(&master->magiclist, (unsigned long)magic, &hash)) {
+ DRM_UNLOCK(dev);
+ return -EINVAL;
}
+ pt = drm_hash_entry(hash, struct drm_magic_entry, hash_item);
+ drm_ht_remove_item(&master->magiclist, hash);
+ list_del(&pt->head);
+ DRM_UNLOCK(dev);
+
+ free(pt, DRM_MEM_MAGIC);
- return EINVAL;
+ return 0;
}
/**
- * Called by the client, this returns a unique magic number to be authorized
- * by the master.
+ * Get a unique magic number (ioctl).
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg pointer to a resulting drm_auth structure.
+ * \return zero on success, or a negative number on failure.
*
- * The master may use its own knowledge of the client (such as the X
- * connection that the magic is passed over) to determine if the magic number
- * should be authenticated.
+ * If there is a magic number in drm_file::magic then use it, otherwise
+ * searches an unique non-zero magic number and add it associating it with \p
+ * file_priv.
+ * This ioctl needs protection by the drm_global_mutex, which protects
+ * struct drm_file::magic and struct drm_magic_entry::priv.
*/
int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
@@ -146,18 +153,15 @@ int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv)
if (file_priv->magic) {
auth->magic = file_priv->magic;
} else {
- DRM_LOCK(dev);
do {
- int old = sequence;
-
- auth->magic = old+1;
-
- if (!atomic_cmpset_int(&sequence, old, auth->magic))
- continue;
- } while (drm_find_file(dev, auth->magic));
+ mtx_lock(&drm_magic_lock);
+ if (!sequence)
+ ++sequence; /* reserve 0 */
+ auth->magic = sequence++;
+ mtx_unlock(&drm_magic_lock);
+ } while (drm_find_file(file_priv->master, auth->magic));
file_priv->magic = auth->magic;
- drm_add_magic(dev, file_priv, auth->magic);
- DRM_UNLOCK(dev);
+ drm_add_magic(file_priv->master, file_priv, auth->magic);
}
DRM_DEBUG("%u\n", auth->magic);
@@ -166,25 +170,47 @@ int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv)
}
/**
- * Marks the client associated with the given magic number as authenticated.
+ * Authenticate with a magic.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg pointer to a drm_auth structure.
+ * \return zero if authentication successed, or a negative number otherwise.
+ *
+ * Checks if \p file_priv is associated with the magic number passed in \arg.
+ * This ioctl needs protection by the drm_global_mutex, which protects
+ * struct drm_file::magic and struct drm_magic_entry::priv.
*/
int drm_authmagic(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_auth *auth = data;
- struct drm_file *priv;
+ struct drm_file *file;
DRM_DEBUG("%u\n", auth->magic);
-
- DRM_LOCK(dev);
- priv = drm_find_file(dev, auth->magic);
- if (priv != NULL) {
- priv->authenticated = 1;
- drm_remove_magic(dev, auth->magic);
- DRM_UNLOCK(dev);
+ if ((file = drm_find_file(file_priv->master, auth->magic))) {
+ file->authenticated = 1;
+ drm_remove_magic(file_priv->master, auth->magic);
return 0;
- } else {
- DRM_UNLOCK(dev);
- return EINVAL;
}
+ return -EINVAL;
+}
+
+static int
+drm_magic_init(void *arg)
+{
+
+ mtx_init(&drm_magic_lock, "drm_getmagic__lock", NULL, MTX_DEF);
+ return (0);
+}
+
+static void
+drm_magic_fini(void *arg)
+{
+
+ mtx_destroy(&drm_magic_lock);
}
+
+SYSINIT(drm_magic_init, SI_SUB_KLD, SI_ORDER_MIDDLE, drm_magic_init, NULL);
+SYSUNINIT(drm_magic_fini, SI_SUB_KLD, SI_ORDER_MIDDLE, drm_magic_fini, NULL);
diff --git a/sys/dev/drm2/drm_buffer.c b/sys/dev/drm2/drm_buffer.c
index cdc91a4..f151a61 100644
--- a/sys/dev/drm2/drm_buffer.c
+++ b/sys/dev/drm2/drm_buffer.c
@@ -92,6 +92,7 @@ error_out:
free(*buf, DRM_MEM_DRIVER);
return -ENOMEM;
}
+EXPORT_SYMBOL(drm_buffer_alloc);
/**
* Copy the user data to the begin of the buffer and reset the processing
@@ -128,6 +129,7 @@ int drm_buffer_copy_from_user(struct drm_buffer *buf,
buf->iterator = 0;
return 0;
}
+EXPORT_SYMBOL(drm_buffer_copy_from_user);
/**
* Free the drm buffer object
@@ -145,6 +147,7 @@ void drm_buffer_free(struct drm_buffer *buf)
free(buf, DRM_MEM_DRIVER);
}
}
+EXPORT_SYMBOL(drm_buffer_free);
/**
* Read an object from buffer that may be split to multiple parts. If object
@@ -181,3 +184,4 @@ void *drm_buffer_read_object(struct drm_buffer *buf,
drm_buffer_advance(buf, objsize);
return obj;
}
+EXPORT_SYMBOL(drm_buffer_read_object);
diff --git a/sys/dev/drm2/drm_bufs.c b/sys/dev/drm2/drm_bufs.c
index 410c88f..1359466 100644
--- a/sys/dev/drm2/drm_bufs.c
+++ b/sys/dev/drm2/drm_bufs.c
@@ -1,4 +1,14 @@
-/*-
+/**
+ * \file drm_bufs.c
+ * Generic buffer template
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
+ * Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com
+ *
* Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
* All Rights Reserved.
@@ -21,19 +31,13 @@
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Rickard E. (Rik) Faith <faith@valinux.com>
- * Gareth Hughes <gareth@valinux.com>
- *
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-/** @file drm_bufs.c
- * Implementation of the ioctls for setup of DRM mappings and DMA buffers.
- */
+#include <sys/param.h>
+#include <sys/shm.h>
#include <dev/pci/pcireg.h>
@@ -48,8 +52,6 @@ static int drm_alloc_resource(struct drm_device *dev, int resource)
struct resource *res;
int rid;
- DRM_LOCK_ASSERT(dev);
-
if (resource >= DRM_MAX_PCI_RESOURCE) {
DRM_ERROR("Resource %d too large\n", resource);
return 1;
@@ -59,11 +61,9 @@ static int drm_alloc_resource(struct drm_device *dev, int resource)
return 0;
}
- DRM_UNLOCK(dev);
rid = PCIR_BAR(resource);
- res = bus_alloc_resource_any(dev->device, SYS_RES_MEMORY, &rid,
+ res = bus_alloc_resource_any(dev->dev, SYS_RES_MEMORY, &rid,
RF_SHAREABLE);
- DRM_LOCK(dev);
if (res == NULL) {
DRM_ERROR("Couldn't find resource 0x%x\n", resource);
return 1;
@@ -80,120 +80,275 @@ static int drm_alloc_resource(struct drm_device *dev, int resource)
unsigned long drm_get_resource_start(struct drm_device *dev,
unsigned int resource)
{
+ unsigned long start;
+
+ mtx_lock(&dev->pcir_lock);
+
if (drm_alloc_resource(dev, resource) != 0)
return 0;
- return rman_get_start(dev->pcir[resource]);
+ start = rman_get_start(dev->pcir[resource]);
+
+ mtx_unlock(&dev->pcir_lock);
+
+ return (start);
}
unsigned long drm_get_resource_len(struct drm_device *dev,
unsigned int resource)
{
+ unsigned long len;
+
+ mtx_lock(&dev->pcir_lock);
+
if (drm_alloc_resource(dev, resource) != 0)
return 0;
- return rman_get_size(dev->pcir[resource]);
+ len = rman_get_size(dev->pcir[resource]);
+
+ mtx_unlock(&dev->pcir_lock);
+
+ return (len);
+}
+
+static struct drm_map_list *drm_find_matching_map(struct drm_device *dev,
+ struct drm_local_map *map)
+{
+ struct drm_map_list *entry;
+ list_for_each_entry(entry, &dev->maplist, head) {
+ /*
+ * Because the kernel-userspace ABI is fixed at a 32-bit offset
+ * while PCI resources may live above that, we only compare the
+ * lower 32 bits of the map offset for maps of type
+ * _DRM_FRAMEBUFFER or _DRM_REGISTERS.
+ * It is assumed that if a driver have more than one resource
+ * of each type, the lower 32 bits are different.
+ */
+ if (!entry->map ||
+ map->type != entry->map->type ||
+ entry->master != dev->primary->master)
+ continue;
+ switch (map->type) {
+ case _DRM_SHM:
+ if (map->flags != _DRM_CONTAINS_LOCK)
+ break;
+ return entry;
+ case _DRM_REGISTERS:
+ case _DRM_FRAME_BUFFER:
+ if ((entry->map->offset & 0xffffffff) ==
+ (map->offset & 0xffffffff))
+ return entry;
+ default: /* Make gcc happy */
+ ;
+ }
+ if (entry->map->offset == map->offset)
+ return entry;
+ }
+
+ return NULL;
+}
+
+static int drm_map_handle(struct drm_device *dev, struct drm_hash_item *hash,
+ unsigned long user_token, int hashed_handle, int shm)
+{
+ int use_hashed_handle, shift;
+ unsigned long add;
+
+#if (BITS_PER_LONG == 64)
+ use_hashed_handle = ((user_token & 0xFFFFFFFF00000000UL) || hashed_handle);
+#elif (BITS_PER_LONG == 32)
+ use_hashed_handle = hashed_handle;
+#else
+#error Unsupported long size. Neither 64 nor 32 bits.
+#endif
+
+ if (!use_hashed_handle) {
+ int ret;
+ hash->key = user_token >> PAGE_SHIFT;
+ ret = drm_ht_insert_item(&dev->map_hash, hash);
+ if (ret != -EINVAL)
+ return ret;
+ }
+
+ shift = 0;
+ add = DRM_MAP_HASH_OFFSET >> PAGE_SHIFT;
+ if (shm && (SHMLBA > PAGE_SIZE)) {
+ int bits = ilog2(SHMLBA >> PAGE_SHIFT) + 1;
+
+ /* For shared memory, we have to preserve the SHMLBA
+ * bits of the eventual vma->vm_pgoff value during
+ * mmap(). Otherwise we run into cache aliasing problems
+ * on some platforms. On these platforms, the pgoff of
+ * a mmap() request is used to pick a suitable virtual
+ * address for the mmap() region such that it will not
+ * cause cache aliasing problems.
+ *
+ * Therefore, make sure the SHMLBA relevant bits of the
+ * hash value we use are equal to those in the original
+ * kernel virtual address.
+ */
+ shift = bits;
+ add |= ((user_token >> PAGE_SHIFT) & ((1UL << bits) - 1UL));
+ }
+
+ return drm_ht_just_insert_please(&dev->map_hash, hash,
+ user_token, 32 - PAGE_SHIFT - 3,
+ shift, add);
}
-int drm_addmap(struct drm_device * dev, unsigned long offset,
- unsigned long size,
- enum drm_map_type type, enum drm_map_flags flags, drm_local_map_t **map_ptr)
+/**
+ * Core function to create a range of memory available for mapping by a
+ * non-root process.
+ *
+ * Adjusts the memory offset to its absolute value according to the mapping
+ * type. Adds the map to the map list drm_device::maplist. Adds MTRR's where
+ * applicable and if supported by the kernel.
+ */
+static int drm_addmap_core(struct drm_device * dev, resource_size_t offset,
+ unsigned int size, enum drm_map_type type,
+ enum drm_map_flags flags,
+ struct drm_map_list ** maplist)
{
- drm_local_map_t *map;
+ struct drm_local_map *map;
+ struct drm_map_list *list;
+ drm_dma_handle_t *dmah;
+ unsigned long user_token;
+ int ret;
int align;
- /*drm_agp_mem_t *entry;
- int valid;*/
+
+ map = malloc(sizeof(*map), DRM_MEM_MAPS, M_NOWAIT);
+ if (!map)
+ return -ENOMEM;
+
+ map->offset = offset;
+ map->size = size;
+ map->flags = flags;
+ map->type = type;
/* Only allow shared memory to be removable since we only keep enough
* book keeping information about shared memory to allow for removal
* when processes fork.
*/
- if ((flags & _DRM_REMOVABLE) && type != _DRM_SHM) {
- DRM_ERROR("Requested removable map for non-DRM_SHM\n");
- return EINVAL;
- }
- if ((offset & PAGE_MASK) || (size & PAGE_MASK)) {
- DRM_ERROR("offset/size not page aligned: 0x%lx/0x%lx\n",
- offset, size);
- return EINVAL;
- }
- if (offset + size < offset) {
- DRM_ERROR("offset and size wrap around: 0x%lx/0x%lx\n",
- offset, size);
- return EINVAL;
+ if ((map->flags & _DRM_REMOVABLE) && map->type != _DRM_SHM) {
+ free(map, DRM_MEM_MAPS);
+ return -EINVAL;
}
+ DRM_DEBUG("offset = 0x%08llx, size = 0x%08lx, type = %d\n",
+ (unsigned long long)map->offset, map->size, map->type);
- DRM_DEBUG("offset = 0x%08lx, size = 0x%08lx, type = %d\n", offset,
- size, type);
-
- /* Check if this is just another version of a kernel-allocated map, and
- * just hand that back if so.
+ /* page-align _DRM_SHM maps. They are allocated here so there is no security
+ * hole created by that and it works around various broken drivers that use
+ * a non-aligned quantity to map the SAREA. --BenH
*/
- if (type == _DRM_REGISTERS || type == _DRM_FRAME_BUFFER ||
- type == _DRM_SHM) {
- TAILQ_FOREACH(map, &dev->maplist, link) {
- if (map->type == type && (map->offset == offset ||
- (map->type == _DRM_SHM &&
- map->flags == _DRM_CONTAINS_LOCK))) {
- map->size = size;
- DRM_DEBUG("Found kernel map %d\n", type);
- goto done;
- }
- }
- }
- DRM_UNLOCK(dev);
+ if (map->type == _DRM_SHM)
+ map->size = PAGE_ALIGN(map->size);
- /* Allocate a new map structure, fill it in, and do any type-specific
- * initialization necessary.
+ /*
+ * FreeBSD port note: FreeBSD's PAGE_MASK is the inverse of
+ * Linux's one. That's why the test below doesn't inverse the
+ * constant.
*/
- map = malloc(sizeof(*map), DRM_MEM_MAPS, M_ZERO | M_NOWAIT);
- if (!map) {
- DRM_LOCK(dev);
- return ENOMEM;
+ if ((map->offset & ((resource_size_t)PAGE_MASK)) || (map->size & (PAGE_MASK))) {
+ free(map, DRM_MEM_MAPS);
+ return -EINVAL;
}
-
- map->offset = offset;
- map->size = size;
- map->type = type;
- map->flags = flags;
- map->handle = (void *)((unsigned long)alloc_unr(dev->map_unrhdr) <<
- DRM_MAP_HANDLE_SHIFT);
+ map->mtrr = -1;
+ map->handle = NULL;
switch (map->type) {
case _DRM_REGISTERS:
- map->virtual = drm_ioremap(dev, map);
- if (!(map->flags & _DRM_WRITE_COMBINING))
- break;
- /* FALLTHROUGH */
case _DRM_FRAME_BUFFER:
- if (drm_mtrr_add(map->offset, map->size, DRM_MTRR_WC) == 0)
- map->mtrr = 1;
+#ifdef __linux__
+#if !defined(__sparc__) && !defined(__alpha__) && !defined(__ia64__) && !defined(__powerpc64__) && !defined(__x86_64__) && !defined(__arm__)
+ if (map->offset + (map->size-1) < map->offset ||
+ map->offset < virt_to_phys(high_memory)) {
+ kfree(map);
+ return -EINVAL;
+ }
+#endif
+#endif
+ /* Some drivers preinitialize some maps, without the X Server
+ * needing to be aware of it. Therefore, we just return success
+ * when the server tries to create a duplicate map.
+ */
+ list = drm_find_matching_map(dev, map);
+ if (list != NULL) {
+ if (list->map->size != map->size) {
+ DRM_DEBUG("Matching maps of type %d with "
+ "mismatched sizes, (%ld vs %ld)\n",
+ map->type, map->size,
+ list->map->size);
+ list->map->size = map->size;
+ }
+
+ free(map, DRM_MEM_MAPS);
+ *maplist = list;
+ return 0;
+ }
+
+ if (drm_core_has_MTRR(dev)) {
+ if (map->type == _DRM_FRAME_BUFFER ||
+ (map->flags & _DRM_WRITE_COMBINING)) {
+ if (drm_mtrr_add(
+ map->offset, map->size,
+ DRM_MTRR_WC) == 0)
+ map->mtrr = 1;
+ }
+ }
+ if (map->type == _DRM_REGISTERS) {
+ drm_core_ioremap(map, dev);
+ if (!map->handle) {
+ free(map, DRM_MEM_MAPS);
+ return -ENOMEM;
+ }
+ }
+
break;
case _DRM_SHM:
- map->virtual = malloc(map->size, DRM_MEM_MAPS, M_NOWAIT);
+ list = drm_find_matching_map(dev, map);
+ if (list != NULL) {
+ if(list->map->size != map->size) {
+ DRM_DEBUG("Matching maps of type %d with "
+ "mismatched sizes, (%ld vs %ld)\n",
+ map->type, map->size, list->map->size);
+ list->map->size = map->size;
+ }
+
+ free(map, DRM_MEM_MAPS);
+ *maplist = list;
+ return 0;
+ }
+ map->handle = malloc(map->size, DRM_MEM_MAPS, M_NOWAIT);
DRM_DEBUG("%lu %d %p\n",
- map->size, drm_order(map->size), map->virtual);
- if (!map->virtual) {
+ map->size, drm_order(map->size), map->handle);
+ if (!map->handle) {
free(map, DRM_MEM_MAPS);
- DRM_LOCK(dev);
- return ENOMEM;
+ return -ENOMEM;
}
- map->offset = (unsigned long)map->virtual;
+ map->offset = (unsigned long)map->handle;
if (map->flags & _DRM_CONTAINS_LOCK) {
/* Prevent a 2nd X Server from creating a 2nd lock */
- DRM_LOCK(dev);
- if (dev->lock.hw_lock != NULL) {
- DRM_UNLOCK(dev);
- free(map->virtual, DRM_MEM_MAPS);
+ if (dev->primary->master->lock.hw_lock != NULL) {
+ free(map->handle, DRM_MEM_MAPS);
free(map, DRM_MEM_MAPS);
- return EBUSY;
+ return -EBUSY;
}
- dev->lock.hw_lock = map->virtual; /* Pointer to lock */
- DRM_UNLOCK(dev);
+ dev->sigdata.lock = dev->primary->master->lock.hw_lock = map->handle; /* Pointer to lock */
}
break;
- case _DRM_AGP:
- /*valid = 0;*/
+ case _DRM_AGP: {
+ struct drm_agp_mem *entry;
+ int valid = 0;
+
+ if (!drm_core_has_AGP(dev)) {
+ free(map, DRM_MEM_MAPS);
+ return -EINVAL;
+ }
+#ifdef __linux__
+#ifdef __alpha__
+ map->offset += dev->hose->mem_space->start;
+#endif
+#endif
/* In some cases (i810 driver), user space may have already
* added the AGP base itself, because dev->agp->base previously
* only got set during AGP enable. So, only add the base
@@ -202,128 +357,202 @@ int drm_addmap(struct drm_device * dev, unsigned long offset,
*/
if (map->offset < dev->agp->base ||
map->offset > dev->agp->base +
- dev->agp->info.ai_aperture_size - 1) {
+ dev->agp->agp_info.ai_aperture_size * 1024 * 1024 - 1) {
map->offset += dev->agp->base;
}
- map->mtrr = dev->agp->mtrr; /* for getmap */
- /*for (entry = dev->agp->memory; entry; entry = entry->next) {
+ map->mtrr = dev->agp->agp_mtrr; /* for getmap */
+
+ /* This assumes the DRM is in total control of AGP space.
+ * It's not always the case as AGP can be in the control
+ * of user space (i.e. i810 driver). So this loop will get
+ * skipped and we double check that dev->agp->memory is
+ * actually set as well as being invalid before EPERM'ing
+ */
+ list_for_each_entry(entry, &dev->agp->memory, head) {
if ((map->offset >= entry->bound) &&
- (map->offset + map->size <=
- entry->bound + entry->pages * PAGE_SIZE)) {
+ (map->offset + map->size <= entry->bound + entry->pages * PAGE_SIZE)) {
valid = 1;
break;
}
}
- if (!valid) {
+ if (!list_empty(&dev->agp->memory) && !valid) {
free(map, DRM_MEM_MAPS);
- DRM_LOCK(dev);
- return EACCES;
- }*/
+ return -EPERM;
+ }
+ DRM_DEBUG("AGP offset = 0x%08llx, size = 0x%08lx\n",
+ (unsigned long long)map->offset, map->size);
+
+ break;
+ }
+ case _DRM_GEM:
+ DRM_ERROR("tried to addmap GEM object\n");
break;
case _DRM_SCATTER_GATHER:
if (!dev->sg) {
free(map, DRM_MEM_MAPS);
- DRM_LOCK(dev);
- return EINVAL;
+ return -EINVAL;
}
- map->virtual = (void *)(dev->sg->vaddr + offset);
- map->offset = dev->sg->vaddr + offset;
+ map->handle = (void *)(dev->sg->vaddr + offset);
+ map->offset += dev->sg->vaddr;
break;
case _DRM_CONSISTENT:
- /* Unfortunately, we don't get any alignment specification from
- * the caller, so we have to guess. drm_pci_alloc requires
- * a power-of-two alignment, so try to align the bus address of
- * the map to it size if possible, otherwise just assume
- * PAGE_SIZE alignment.
- */
+ /* dma_addr_t is 64bit on i386 with CONFIG_HIGHMEM64G,
+ * As we're limiting the address to 2^32-1 (or less),
+ * casting it down to 32 bits is no problem, but we
+ * need to point to a 64bit variable first. */
align = map->size;
if ((align & (align - 1)) != 0)
align = PAGE_SIZE;
- map->dmah = drm_pci_alloc(dev, map->size, align, 0xfffffffful);
- if (map->dmah == NULL) {
+ dmah = drm_pci_alloc(dev, map->size, align, BUS_SPACE_MAXADDR);
+ if (!dmah) {
free(map, DRM_MEM_MAPS);
- DRM_LOCK(dev);
- return ENOMEM;
+ return -ENOMEM;
}
- map->virtual = map->dmah->vaddr;
- map->offset = map->dmah->busaddr;
+ map->handle = dmah->vaddr;
+ map->offset = dmah->busaddr;
+ map->dmah = dmah;
break;
default:
- DRM_ERROR("Bad map type %d\n", map->type);
free(map, DRM_MEM_MAPS);
- DRM_LOCK(dev);
- return EINVAL;
+ return -EINVAL;
+ }
+
+ list = malloc(sizeof(*list), DRM_MEM_MAPS, M_ZERO | M_NOWAIT);
+ if (!list) {
+ if (map->type == _DRM_REGISTERS)
+ drm_core_ioremapfree(map, dev);
+ free(map, DRM_MEM_MAPS);
+ return -EINVAL;
}
+ list->map = map;
DRM_LOCK(dev);
- TAILQ_INSERT_TAIL(&dev->maplist, map, link);
+ list_add(&list->head, &dev->maplist);
+
+ /* Assign a 32-bit handle */
+ /* We do it here so that dev->struct_mutex protects the increment */
+ user_token = (map->type == _DRM_SHM) ? (unsigned long)map->handle :
+ map->offset;
+ ret = drm_map_handle(dev, &list->hash, user_token, 0,
+ (map->type == _DRM_SHM));
+ if (ret) {
+ if (map->type == _DRM_REGISTERS)
+ drm_core_ioremapfree(map, dev);
+ free(map, DRM_MEM_MAPS);
+ free(list, DRM_MEM_MAPS);
+ DRM_UNLOCK(dev);
+ return ret;
+ }
-done:
- /* Jumped to, with lock held, when a kernel map is found. */
+ list->user_token = list->hash.key << PAGE_SHIFT;
+ DRM_UNLOCK(dev);
- DRM_DEBUG("Added map %d 0x%lx/0x%lx\n", map->type, map->offset,
- map->size);
+ if (!(map->flags & _DRM_DRIVER))
+ list->master = dev->primary->master;
+ *maplist = list;
+ return 0;
+ }
- *map_ptr = map;
+int drm_addmap(struct drm_device * dev, resource_size_t offset,
+ unsigned int size, enum drm_map_type type,
+ enum drm_map_flags flags, struct drm_local_map ** map_ptr)
+{
+ struct drm_map_list *list;
+ int rc;
- return 0;
+ rc = drm_addmap_core(dev, offset, size, type, flags, &list);
+ if (!rc)
+ *map_ptr = list->map;
+ return rc;
}
+EXPORT_SYMBOL(drm_addmap);
+
+/**
+ * Ioctl to specify a range of memory that is available for mapping by a
+ * non-root process.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg pointer to a drm_map structure.
+ * \return zero on success or a negative value on error.
+ *
+ */
int drm_addmap_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
- struct drm_map *request = data;
- drm_local_map_t *map;
+ struct drm_map *map = data;
+ struct drm_map_list *maplist;
int err;
- if (!(dev->flags & (FREAD|FWRITE)))
- return EACCES; /* Require read/write */
+ if (!(DRM_SUSER(DRM_CURPROC) || map->type == _DRM_AGP || map->type == _DRM_SHM))
+ return -EPERM;
- if (!DRM_SUSER(DRM_CURPROC) && request->type != _DRM_AGP)
- return EACCES;
+ err = drm_addmap_core(dev, map->offset, map->size, map->type,
+ map->flags, &maplist);
- DRM_LOCK(dev);
- err = drm_addmap(dev, request->offset, request->size, request->type,
- request->flags, &map);
- DRM_UNLOCK(dev);
- if (err != 0)
+ if (err)
return err;
- request->offset = map->offset;
- request->size = map->size;
- request->type = map->type;
- request->flags = map->flags;
- request->mtrr = map->mtrr;
- request->handle = (void *)map->handle;
-
+ /* avoid a warning on 64-bit, this casting isn't very nice, but the API is set so too late */
+ map->handle = (void *)(unsigned long)maplist->user_token;
return 0;
}
-void drm_rmmap(struct drm_device *dev, drm_local_map_t *map)
+/**
+ * Remove a map private from list and deallocate resources if the mapping
+ * isn't in use.
+ *
+ * Searches the map on drm_device::maplist, removes it from the list, see if
+ * its being used, and free any associate resource (such as MTRR's) if it's not
+ * being on use.
+ *
+ * \sa drm_addmap
+ */
+int drm_rmmap_locked(struct drm_device *dev, struct drm_local_map *map)
{
- DRM_LOCK_ASSERT(dev);
-
- if (map == NULL)
- return;
+ struct drm_map_list *r_list = NULL, *list_t;
+ int found = 0;
+ struct drm_master *master;
+
+ /* Find the list entry for the map and remove it */
+ list_for_each_entry_safe(r_list, list_t, &dev->maplist, head) {
+ if (r_list->map == map) {
+ master = r_list->master;
+ list_del(&r_list->head);
+ drm_ht_remove_key(&dev->map_hash,
+ r_list->user_token >> PAGE_SHIFT);
+ free(r_list, DRM_MEM_MAPS);
+ found = 1;
+ break;
+ }
+ }
- TAILQ_REMOVE(&dev->maplist, map, link);
+ if (!found)
+ return -EINVAL;
switch (map->type) {
case _DRM_REGISTERS:
- if (map->bsr == NULL)
- drm_ioremapfree(map);
+ drm_core_ioremapfree(map, dev);
/* FALLTHROUGH */
case _DRM_FRAME_BUFFER:
- if (map->mtrr) {
- int __unused retcode;
-
- retcode = drm_mtrr_del(0, map->offset, map->size,
- DRM_MTRR_WC);
- DRM_DEBUG("mtrr_del = %d\n", retcode);
+ if (drm_core_has_MTRR(dev) && map->mtrr >= 0) {
+ int retcode;
+ retcode = drm_mtrr_del(map->mtrr, map->offset,
+ map->size, DRM_MTRR_WC);
+ DRM_DEBUG("mtrr_del=%d\n", retcode);
}
break;
case _DRM_SHM:
- free(map->virtual, DRM_MEM_MAPS);
+ free(map->handle, DRM_MEM_MAPS);
+ if (master) {
+ if (dev->sigdata.lock == master->lock.hw_lock)
+ dev->sigdata.lock = NULL;
+ master->lock.hw_lock = NULL; /* SHM removed */
+ master->lock.file_priv = NULL;
+ DRM_WAKEUP_INT((void *)&master->lock.lock_queue);
+ }
break;
case _DRM_AGP:
case _DRM_SCATTER_GATHER:
@@ -331,72 +560,108 @@ void drm_rmmap(struct drm_device *dev, drm_local_map_t *map)
case _DRM_CONSISTENT:
drm_pci_free(dev, map->dmah);
break;
- default:
- DRM_ERROR("Bad map type %d\n", map->type);
+ case _DRM_GEM:
+ DRM_ERROR("tried to rmmap GEM object\n");
break;
}
+ free(map, DRM_MEM_MAPS);
- if (map->bsr != NULL) {
- bus_release_resource(dev->device, SYS_RES_MEMORY, map->rid,
- map->bsr);
- }
+ return 0;
+}
+EXPORT_SYMBOL(drm_rmmap_locked);
+
+int drm_rmmap(struct drm_device *dev, struct drm_local_map *map)
+{
+ int ret;
- DRM_UNLOCK(dev);
- if (map->handle)
- free_unr(dev->map_unrhdr, (unsigned long)map->handle >>
- DRM_MAP_HANDLE_SHIFT);
DRM_LOCK(dev);
+ ret = drm_rmmap_locked(dev, map);
+ DRM_UNLOCK(dev);
- free(map, DRM_MEM_MAPS);
+ return ret;
}
+EXPORT_SYMBOL(drm_rmmap);
-/* Remove a map private from list and deallocate resources if the mapping
- * isn't in use.
+/* The rmmap ioctl appears to be unnecessary. All mappings are torn down on
+ * the last close of the device, and this is necessary for cleanup when things
+ * exit uncleanly. Therefore, having userland manually remove mappings seems
+ * like a pointless exercise since they're going away anyway.
+ *
+ * One use case might be after addmap is allowed for normal users for SHM and
+ * gets used by drivers that the server doesn't need to care about. This seems
+ * unlikely.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg pointer to a struct drm_map structure.
+ * \return zero on success or a negative value on error.
*/
-
int drm_rmmap_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
- drm_local_map_t *map;
struct drm_map *request = data;
+ struct drm_local_map *map = NULL;
+ struct drm_map_list *r_list;
+ int ret;
DRM_LOCK(dev);
- TAILQ_FOREACH(map, &dev->maplist, link) {
- if (map->handle == request->handle &&
- map->flags & _DRM_REMOVABLE)
+ list_for_each_entry(r_list, &dev->maplist, head) {
+ if (r_list->map &&
+ r_list->user_token == (unsigned long)request->handle &&
+ r_list->map->flags & _DRM_REMOVABLE) {
+ map = r_list->map;
break;
+ }
}
- /* No match found. */
- if (map == NULL) {
+ /* List has wrapped around to the head pointer, or its empty we didn't
+ * find anything.
+ */
+ if (list_empty(&dev->maplist) || !map) {
DRM_UNLOCK(dev);
- return EINVAL;
+ return -EINVAL;
}
- drm_rmmap(dev, map);
+ /* Register and framebuffer maps are permanent */
+ if ((map->type == _DRM_REGISTERS) || (map->type == _DRM_FRAME_BUFFER)) {
+ DRM_UNLOCK(dev);
+ return 0;
+ }
+
+ ret = drm_rmmap_locked(dev, map);
DRM_UNLOCK(dev);
- return 0;
+ return ret;
}
-
-static void drm_cleanup_buf_error(struct drm_device *dev,
- drm_buf_entry_t *entry)
+/**
+ * Cleanup after an error on one of the addbufs() functions.
+ *
+ * \param dev DRM device.
+ * \param entry buffer entry where the error occurred.
+ *
+ * Frees any pages and buffers associated with the given entry.
+ */
+static void drm_cleanup_buf_error(struct drm_device * dev,
+ struct drm_buf_entry * entry)
{
int i;
if (entry->seg_count) {
for (i = 0; i < entry->seg_count; i++) {
- drm_pci_free(dev, entry->seglist[i]);
+ if (entry->seglist[i]) {
+ drm_pci_free(dev, entry->seglist[i]);
+ }
}
free(entry->seglist, DRM_MEM_SEGS);
entry->seg_count = 0;
}
- if (entry->buf_count) {
- for (i = 0; i < entry->buf_count; i++) {
+ if (entry->buf_count) {
+ for (i = 0; i < entry->buf_count; i++) {
free(entry->buflist[i].dev_private, DRM_MEM_BUFS);
}
free(entry->buflist, DRM_MEM_BUFS);
@@ -405,13 +670,24 @@ static void drm_cleanup_buf_error(struct drm_device *dev,
}
}
-static int drm_do_addbufs_agp(struct drm_device *dev, struct drm_buf_desc *request)
+#if __OS_HAS_AGP
+/**
+ * Add AGP buffers for DMA transfers.
+ *
+ * \param dev struct drm_device to which the buffers are to be added.
+ * \param request pointer to a struct drm_buf_desc describing the request.
+ * \return zero on success or a negative number on failure.
+ *
+ * After some sanity checks creates a drm_buf structure for each buffer and
+ * reallocates the buffer list of the same size order to accommodate the new
+ * buffers.
+ */
+int drm_addbufs_agp(struct drm_device * dev, struct drm_buf_desc * request)
{
- drm_device_dma_t *dma = dev->dma;
- drm_buf_entry_t *entry;
- /*drm_agp_mem_t *agp_entry;
- int valid*/
- drm_buf_t *buf;
+ struct drm_device_dma *dma = dev->dma;
+ struct drm_buf_entry *entry;
+ struct drm_agp_mem *agp_entry;
+ struct drm_buf *buf;
unsigned long offset;
unsigned long agp_offset;
int count;
@@ -421,55 +697,76 @@ static int drm_do_addbufs_agp(struct drm_device *dev, struct drm_buf_desc *reque
int page_order;
int total;
int byte_count;
- int i;
- drm_buf_t **temp_buflist;
+ int i, valid;
+ struct drm_buf **temp_buflist;
+
+ if (!dma)
+ return -EINVAL;
count = request->count;
order = drm_order(request->size);
size = 1 << order;
- alignment = (request->flags & _DRM_PAGE_ALIGN)
- ? round_page(size) : size;
+ alignment = (request->flags & _DRM_PAGE_ALIGN)
+ ? PAGE_ALIGN(size) : size;
page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
total = PAGE_SIZE << page_order;
byte_count = 0;
agp_offset = dev->agp->base + request->agp_start;
- DRM_DEBUG("count: %d\n", count);
- DRM_DEBUG("order: %d\n", order);
- DRM_DEBUG("size: %d\n", size);
- DRM_DEBUG("agp_offset: 0x%lx\n", agp_offset);
- DRM_DEBUG("alignment: %d\n", alignment);
- DRM_DEBUG("page_order: %d\n", page_order);
- DRM_DEBUG("total: %d\n", total);
+ DRM_DEBUG("count: %d\n", count);
+ DRM_DEBUG("order: %d\n", order);
+ DRM_DEBUG("size: %d\n", size);
+ DRM_DEBUG("agp_offset: %lx\n", agp_offset);
+ DRM_DEBUG("alignment: %d\n", alignment);
+ DRM_DEBUG("page_order: %d\n", page_order);
+ DRM_DEBUG("total: %d\n", total);
+
+ if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
+ return -EINVAL;
/* Make sure buffers are located in AGP memory that we own */
- /* Breaks MGA due to drm_alloc_agp not setting up entries for the
- * memory. Safe to ignore for now because these ioctls are still
- * root-only.
- */
- /*valid = 0;
- for (agp_entry = dev->agp->memory; agp_entry;
- agp_entry = agp_entry->next) {
+ valid = 0;
+ list_for_each_entry(agp_entry, &dev->agp->memory, head) {
if ((agp_offset >= agp_entry->bound) &&
- (agp_offset + total * count <=
- agp_entry->bound + agp_entry->pages * PAGE_SIZE)) {
+ (agp_offset + total * count <= agp_entry->bound + agp_entry->pages * PAGE_SIZE)) {
valid = 1;
break;
}
}
- if (!valid) {
+ if (!list_empty(&dev->agp->memory) && !valid) {
DRM_DEBUG("zone invalid\n");
- return EINVAL;
- }*/
+ return -EINVAL;
+ }
+ mtx_lock(&dev->count_lock);
+ if (dev->buf_use) {
+ mtx_unlock(&dev->count_lock);
+ return -EBUSY;
+ }
+ atomic_inc(&dev->buf_alloc);
+ mtx_unlock(&dev->count_lock);
+ DRM_LOCK(dev);
entry = &dma->bufs[order];
+ if (entry->buf_count) {
+ DRM_UNLOCK(dev);
+ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM; /* May only call once for each order */
+ }
+
+ if (count < 0 || count > 4096) {
+ DRM_UNLOCK(dev);
+ atomic_dec(&dev->buf_alloc);
+ return -EINVAL;
+ }
entry->buflist = malloc(count * sizeof(*entry->buflist), DRM_MEM_BUFS,
M_NOWAIT | M_ZERO);
if (!entry->buflist) {
- return ENOMEM;
+ DRM_UNLOCK(dev);
+ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM;
}
entry->buf_size = size;
@@ -478,29 +775,34 @@ static int drm_do_addbufs_agp(struct drm_device *dev, struct drm_buf_desc *reque
offset = 0;
while (entry->buf_count < count) {
- buf = &entry->buflist[entry->buf_count];
- buf->idx = dma->buf_count + entry->buf_count;
- buf->total = alignment;
- buf->order = order;
- buf->used = 0;
+ buf = &entry->buflist[entry->buf_count];
+ buf->idx = dma->buf_count + entry->buf_count;
+ buf->total = alignment;
+ buf->order = order;
+ buf->used = 0;
- buf->offset = (dma->byte_count + offset);
+ buf->offset = (dma->byte_count + offset);
buf->bus_address = agp_offset + offset;
buf->address = (void *)(agp_offset + offset);
- buf->next = NULL;
+ buf->next = NULL;
+ buf->waiting = 0;
buf->pending = 0;
buf->file_priv = NULL;
- buf->dev_priv_size = dev->driver->buf_priv_size;
+ buf->dev_priv_size = dev->driver->dev_priv_size;
buf->dev_private = malloc(buf->dev_priv_size, DRM_MEM_BUFS,
M_NOWAIT | M_ZERO);
- if (buf->dev_private == NULL) {
+ if (!buf->dev_private) {
/* Set count correctly so we free the proper amount. */
entry->buf_count = count;
drm_cleanup_buf_error(dev, entry);
- return ENOMEM;
+ DRM_UNLOCK(dev);
+ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM;
}
+ DRM_DEBUG("buffer %d @ %p\n", entry->buf_count, buf->address);
+
offset += alignment;
entry->buf_count++;
byte_count += PAGE_SIZE << page_order;
@@ -511,10 +813,12 @@ static int drm_do_addbufs_agp(struct drm_device *dev, struct drm_buf_desc *reque
temp_buflist = realloc(dma->buflist,
(dma->buf_count + entry->buf_count) * sizeof(*dma->buflist),
DRM_MEM_BUFS, M_NOWAIT);
- if (temp_buflist == NULL) {
+ if (!temp_buflist) {
/* Free the entry because it isn't valid */
drm_cleanup_buf_error(dev, entry);
- return ENOMEM;
+ DRM_UNLOCK(dev);
+ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM;
}
dma->buflist = temp_buflist;
@@ -523,132 +827,184 @@ static int drm_do_addbufs_agp(struct drm_device *dev, struct drm_buf_desc *reque
}
dma->buf_count += entry->buf_count;
+ dma->seg_count += entry->seg_count;
+ dma->page_count += byte_count >> PAGE_SHIFT;
dma->byte_count += byte_count;
DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count);
+ DRM_UNLOCK(dev);
+
request->count = entry->buf_count;
request->size = size;
dma->flags = _DRM_DMA_USE_AGP;
+ atomic_dec(&dev->buf_alloc);
return 0;
}
+EXPORT_SYMBOL(drm_addbufs_agp);
+#endif /* __OS_HAS_AGP */
-static int drm_do_addbufs_pci(struct drm_device *dev, struct drm_buf_desc *request)
+int drm_addbufs_pci(struct drm_device * dev, struct drm_buf_desc * request)
{
- drm_device_dma_t *dma = dev->dma;
+ struct drm_device_dma *dma = dev->dma;
int count;
int order;
int size;
int total;
int page_order;
- drm_buf_entry_t *entry;
- drm_buf_t *buf;
+ struct drm_buf_entry *entry;
+ drm_dma_handle_t *dmah;
+ struct drm_buf *buf;
int alignment;
unsigned long offset;
int i;
int byte_count;
int page_count;
unsigned long *temp_pagelist;
- drm_buf_t **temp_buflist;
+ struct drm_buf **temp_buflist;
+
+ if (!drm_core_check_feature(dev, DRIVER_PCI_DMA))
+ return -EINVAL;
+
+ if (!dma)
+ return -EINVAL;
+
+ if (!DRM_SUSER(DRM_CURPROC))
+ return -EPERM;
count = request->count;
order = drm_order(request->size);
size = 1 << order;
DRM_DEBUG("count=%d, size=%d (%d), order=%d\n",
- request->count, request->size, size, order);
+ request->count, request->size, size, order);
+
+ if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
+ return -EINVAL;
alignment = (request->flags & _DRM_PAGE_ALIGN)
- ? round_page(size) : size;
+ ? PAGE_ALIGN(size) : size;
page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
total = PAGE_SIZE << page_order;
+ mtx_lock(&dev->count_lock);
+ if (dev->buf_use) {
+ mtx_unlock(&dev->count_lock);
+ return -EBUSY;
+ }
+ atomic_inc(&dev->buf_alloc);
+ mtx_unlock(&dev->count_lock);
+
+ DRM_LOCK(dev);
entry = &dma->bufs[order];
+ if (entry->buf_count) {
+ DRM_UNLOCK(dev);
+ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM; /* May only call once for each order */
+ }
+
+ if (count < 0 || count > 4096) {
+ DRM_UNLOCK(dev);
+ atomic_dec(&dev->buf_alloc);
+ return -EINVAL;
+ }
entry->buflist = malloc(count * sizeof(*entry->buflist), DRM_MEM_BUFS,
M_NOWAIT | M_ZERO);
+ if (!entry->buflist) {
+ DRM_UNLOCK(dev);
+ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM;
+ }
+
entry->seglist = malloc(count * sizeof(*entry->seglist), DRM_MEM_SEGS,
M_NOWAIT | M_ZERO);
+ if (!entry->seglist) {
+ free(entry->buflist, DRM_MEM_BUFS);
+ DRM_UNLOCK(dev);
+ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM;
+ }
/* Keep the original pagelist until we know all the allocations
* have succeeded
*/
temp_pagelist = malloc((dma->page_count + (count << page_order)) *
sizeof(*dma->pagelist), DRM_MEM_PAGES, M_NOWAIT);
-
- if (entry->buflist == NULL || entry->seglist == NULL ||
- temp_pagelist == NULL) {
- free(temp_pagelist, DRM_MEM_PAGES);
- free(entry->seglist, DRM_MEM_SEGS);
+ if (!temp_pagelist) {
free(entry->buflist, DRM_MEM_BUFS);
- return ENOMEM;
+ free(entry->seglist, DRM_MEM_SEGS);
+ DRM_UNLOCK(dev);
+ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM;
}
-
- memcpy(temp_pagelist, dma->pagelist, dma->page_count *
- sizeof(*dma->pagelist));
-
+ memcpy(temp_pagelist,
+ dma->pagelist, dma->page_count * sizeof(*dma->pagelist));
DRM_DEBUG("pagelist: %d entries\n",
- dma->page_count + (count << page_order));
+ dma->page_count + (count << page_order));
- entry->buf_size = size;
+ entry->buf_size = size;
entry->page_order = page_order;
byte_count = 0;
page_count = 0;
while (entry->buf_count < count) {
- DRM_SPINUNLOCK(&dev->dma_lock);
- drm_dma_handle_t *dmah = drm_pci_alloc(dev, size, alignment,
- 0xfffffffful);
- DRM_SPINLOCK(&dev->dma_lock);
- if (dmah == NULL) {
+
+ dmah = drm_pci_alloc(dev, PAGE_SIZE << page_order, 0x1000, BUS_SPACE_MAXADDR);
+
+ if (!dmah) {
/* Set count correctly so we free the proper amount. */
entry->buf_count = count;
entry->seg_count = count;
drm_cleanup_buf_error(dev, entry);
free(temp_pagelist, DRM_MEM_PAGES);
- return ENOMEM;
+ DRM_UNLOCK(dev);
+ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM;
}
-
entry->seglist[entry->seg_count++] = dmah;
for (i = 0; i < (1 << page_order); i++) {
- DRM_DEBUG("page %d @ %p\n",
- dma->page_count + page_count,
- (char *)dmah->vaddr + PAGE_SIZE * i);
- temp_pagelist[dma->page_count + page_count++] =
- (long)dmah->vaddr + PAGE_SIZE * i;
+ DRM_DEBUG("page %d @ 0x%08lx\n",
+ dma->page_count + page_count,
+ (unsigned long)dmah->vaddr + PAGE_SIZE * i);
+ temp_pagelist[dma->page_count + page_count++]
+ = (unsigned long)dmah->vaddr + PAGE_SIZE * i;
}
for (offset = 0;
- offset + size <= total && entry->buf_count < count;
- offset += alignment, ++entry->buf_count) {
- buf = &entry->buflist[entry->buf_count];
- buf->idx = dma->buf_count + entry->buf_count;
- buf->total = alignment;
- buf->order = order;
- buf->used = 0;
- buf->offset = (dma->byte_count + byte_count + offset);
- buf->address = ((char *)dmah->vaddr + offset);
+ offset + size <= total && entry->buf_count < count;
+ offset += alignment, ++entry->buf_count) {
+ buf = &entry->buflist[entry->buf_count];
+ buf->idx = dma->buf_count + entry->buf_count;
+ buf->total = alignment;
+ buf->order = order;
+ buf->used = 0;
+ buf->offset = (dma->byte_count + byte_count + offset);
+ buf->address = (void *)((char *)dmah->vaddr + offset);
buf->bus_address = dmah->busaddr + offset;
- buf->next = NULL;
+ buf->next = NULL;
+ buf->waiting = 0;
buf->pending = 0;
buf->file_priv = NULL;
- buf->dev_priv_size = dev->driver->buf_priv_size;
+ buf->dev_priv_size = dev->driver->dev_priv_size;
buf->dev_private = malloc(buf->dev_priv_size,
DRM_MEM_BUFS, M_NOWAIT | M_ZERO);
- if (buf->dev_private == NULL) {
+ if (!buf->dev_private) {
/* Set count correctly so we free the proper amount. */
entry->buf_count = count;
entry->seg_count = count;
drm_cleanup_buf_error(dev, entry);
free(temp_pagelist, DRM_MEM_PAGES);
- return ENOMEM;
+ DRM_UNLOCK(dev);
+ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM;
}
DRM_DEBUG("buffer %d @ %p\n",
- entry->buf_count, buf->address);
+ entry->buf_count, buf->address);
}
byte_count += PAGE_SIZE << page_order;
}
@@ -656,11 +1012,13 @@ static int drm_do_addbufs_pci(struct drm_device *dev, struct drm_buf_desc *reque
temp_buflist = realloc(dma->buflist,
(dma->buf_count + entry->buf_count) * sizeof(*dma->buflist),
DRM_MEM_BUFS, M_NOWAIT);
- if (temp_buflist == NULL) {
+ if (!temp_buflist) {
/* Free the entry because it isn't valid */
drm_cleanup_buf_error(dev, entry);
free(temp_pagelist, DRM_MEM_PAGES);
- return ENOMEM;
+ DRM_UNLOCK(dev);
+ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM;
}
dma->buflist = temp_buflist;
@@ -668,10 +1026,12 @@ static int drm_do_addbufs_pci(struct drm_device *dev, struct drm_buf_desc *reque
dma->buflist[i + dma->buf_count] = &entry->buflist[i];
}
- /* No allocations failed, so now we can replace the orginal pagelist
+ /* No allocations failed, so now we can replace the original pagelist
* with the new one.
*/
- free(dma->pagelist, DRM_MEM_PAGES);
+ if (dma->page_count) {
+ free(dma->pagelist, DRM_MEM_PAGES);
+ }
dma->pagelist = temp_pagelist;
dma->buf_count += entry->buf_count;
@@ -679,18 +1039,25 @@ static int drm_do_addbufs_pci(struct drm_device *dev, struct drm_buf_desc *reque
dma->page_count += entry->seg_count << page_order;
dma->byte_count += PAGE_SIZE * (entry->seg_count << page_order);
+ DRM_UNLOCK(dev);
+
request->count = entry->buf_count;
request->size = size;
+ if (request->flags & _DRM_PCI_BUFFER_RO)
+ dma->flags = _DRM_DMA_USE_PCI_RO;
+
+ atomic_dec(&dev->buf_alloc);
return 0;
}
+EXPORT_SYMBOL(drm_addbufs_pci);
-static int drm_do_addbufs_sg(struct drm_device *dev, struct drm_buf_desc *request)
+static int drm_addbufs_sg(struct drm_device * dev, struct drm_buf_desc * request)
{
- drm_device_dma_t *dma = dev->dma;
- drm_buf_entry_t *entry;
- drm_buf_t *buf;
+ struct drm_device_dma *dma = dev->dma;
+ struct drm_buf_entry *entry;
+ struct drm_buf *buf;
unsigned long offset;
unsigned long agp_offset;
int count;
@@ -701,34 +1068,69 @@ static int drm_do_addbufs_sg(struct drm_device *dev, struct drm_buf_desc *reques
int total;
int byte_count;
int i;
- drm_buf_t **temp_buflist;
+ struct drm_buf **temp_buflist;
+
+ if (!drm_core_check_feature(dev, DRIVER_SG))
+ return -EINVAL;
+
+ if (!dma)
+ return -EINVAL;
+
+ if (!DRM_SUSER(DRM_CURPROC))
+ return -EPERM;
count = request->count;
order = drm_order(request->size);
size = 1 << order;
- alignment = (request->flags & _DRM_PAGE_ALIGN)
- ? round_page(size) : size;
+ alignment = (request->flags & _DRM_PAGE_ALIGN)
+ ? PAGE_ALIGN(size) : size;
page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
total = PAGE_SIZE << page_order;
byte_count = 0;
agp_offset = request->agp_start;
- DRM_DEBUG("count: %d\n", count);
- DRM_DEBUG("order: %d\n", order);
- DRM_DEBUG("size: %d\n", size);
- DRM_DEBUG("agp_offset: %ld\n", agp_offset);
- DRM_DEBUG("alignment: %d\n", alignment);
- DRM_DEBUG("page_order: %d\n", page_order);
- DRM_DEBUG("total: %d\n", total);
+ DRM_DEBUG("count: %d\n", count);
+ DRM_DEBUG("order: %d\n", order);
+ DRM_DEBUG("size: %d\n", size);
+ DRM_DEBUG("agp_offset: %lu\n", agp_offset);
+ DRM_DEBUG("alignment: %d\n", alignment);
+ DRM_DEBUG("page_order: %d\n", page_order);
+ DRM_DEBUG("total: %d\n", total);
+
+ if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
+ return -EINVAL;
+
+ mtx_lock(&dev->count_lock);
+ if (dev->buf_use) {
+ mtx_unlock(&dev->count_lock);
+ return -EBUSY;
+ }
+ atomic_inc(&dev->buf_alloc);
+ mtx_unlock(&dev->count_lock);
+ DRM_LOCK(dev);
entry = &dma->bufs[order];
+ if (entry->buf_count) {
+ DRM_UNLOCK(dev);
+ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM; /* May only call once for each order */
+ }
+
+ if (count < 0 || count > 4096) {
+ DRM_UNLOCK(dev);
+ atomic_dec(&dev->buf_alloc);
+ return -EINVAL;
+ }
entry->buflist = malloc(count * sizeof(*entry->buflist), DRM_MEM_BUFS,
M_NOWAIT | M_ZERO);
- if (entry->buflist == NULL)
- return ENOMEM;
+ if (!entry->buflist) {
+ DRM_UNLOCK(dev);
+ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM;
+ }
entry->buf_size = size;
entry->page_order = page_order;
@@ -736,31 +1138,34 @@ static int drm_do_addbufs_sg(struct drm_device *dev, struct drm_buf_desc *reques
offset = 0;
while (entry->buf_count < count) {
- buf = &entry->buflist[entry->buf_count];
- buf->idx = dma->buf_count + entry->buf_count;
- buf->total = alignment;
- buf->order = order;
- buf->used = 0;
+ buf = &entry->buflist[entry->buf_count];
+ buf->idx = dma->buf_count + entry->buf_count;
+ buf->total = alignment;
+ buf->order = order;
+ buf->used = 0;
- buf->offset = (dma->byte_count + offset);
+ buf->offset = (dma->byte_count + offset);
buf->bus_address = agp_offset + offset;
- buf->address = (void *)(agp_offset + offset + dev->sg->vaddr);
- buf->next = NULL;
+ buf->address = (void *)(agp_offset + offset
+ + (unsigned long)dev->sg->vaddr);
+ buf->next = NULL;
+ buf->waiting = 0;
buf->pending = 0;
buf->file_priv = NULL;
- buf->dev_priv_size = dev->driver->buf_priv_size;
+ buf->dev_priv_size = dev->driver->dev_priv_size;
buf->dev_private = malloc(buf->dev_priv_size, DRM_MEM_BUFS,
M_NOWAIT | M_ZERO);
- if (buf->dev_private == NULL) {
+ if (!buf->dev_private) {
/* Set count correctly so we free the proper amount. */
entry->buf_count = count;
drm_cleanup_buf_error(dev, entry);
- return ENOMEM;
+ DRM_UNLOCK(dev);
+ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM;
}
- DRM_DEBUG("buffer %d @ %p\n",
- entry->buf_count, buf->address);
+ DRM_DEBUG("buffer %d @ %p\n", entry->buf_count, buf->address);
offset += alignment;
entry->buf_count++;
@@ -772,10 +1177,12 @@ static int drm_do_addbufs_sg(struct drm_device *dev, struct drm_buf_desc *reques
temp_buflist = realloc(dma->buflist,
(dma->buf_count + entry->buf_count) * sizeof(*dma->buflist),
DRM_MEM_BUFS, M_NOWAIT);
- if (temp_buflist == NULL) {
+ if (!temp_buflist) {
/* Free the entry because it isn't valid */
drm_cleanup_buf_error(dev, entry);
- return ENOMEM;
+ DRM_UNLOCK(dev);
+ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM;
}
dma->buflist = temp_buflist;
@@ -784,144 +1191,256 @@ static int drm_do_addbufs_sg(struct drm_device *dev, struct drm_buf_desc *reques
}
dma->buf_count += entry->buf_count;
+ dma->seg_count += entry->seg_count;
+ dma->page_count += byte_count >> PAGE_SHIFT;
dma->byte_count += byte_count;
DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count);
+ DRM_UNLOCK(dev);
+
request->count = entry->buf_count;
request->size = size;
dma->flags = _DRM_DMA_USE_SG;
+ atomic_dec(&dev->buf_alloc);
return 0;
}
-int drm_addbufs_agp(struct drm_device *dev, struct drm_buf_desc *request)
+static int drm_addbufs_fb(struct drm_device * dev, struct drm_buf_desc * request)
{
- int order, ret;
-
- if (request->count < 0 || request->count > 4096)
- return EINVAL;
-
- order = drm_order(request->size);
- if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
- return EINVAL;
-
- DRM_SPINLOCK(&dev->dma_lock);
+ struct drm_device_dma *dma = dev->dma;
+ struct drm_buf_entry *entry;
+ struct drm_buf *buf;
+ unsigned long offset;
+ unsigned long agp_offset;
+ int count;
+ int order;
+ int size;
+ int alignment;
+ int page_order;
+ int total;
+ int byte_count;
+ int i;
+ struct drm_buf **temp_buflist;
- /* No more allocations after first buffer-using ioctl. */
- if (dev->buf_use != 0) {
- DRM_SPINUNLOCK(&dev->dma_lock);
- return EBUSY;
- }
- /* No more than one allocation per order */
- if (dev->dma->bufs[order].buf_count != 0) {
- DRM_SPINUNLOCK(&dev->dma_lock);
- return ENOMEM;
- }
+ if (!drm_core_check_feature(dev, DRIVER_FB_DMA))
+ return -EINVAL;
- ret = drm_do_addbufs_agp(dev, request);
+ if (!dma)
+ return -EINVAL;
- DRM_SPINUNLOCK(&dev->dma_lock);
+ if (!DRM_SUSER(DRM_CURPROC))
+ return -EPERM;
- return ret;
-}
+ count = request->count;
+ order = drm_order(request->size);
+ size = 1 << order;
-int drm_addbufs_sg(struct drm_device *dev, struct drm_buf_desc *request)
-{
- int order, ret;
+ alignment = (request->flags & _DRM_PAGE_ALIGN)
+ ? PAGE_ALIGN(size) : size;
+ page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
+ total = PAGE_SIZE << page_order;
- if (!DRM_SUSER(DRM_CURPROC))
- return EACCES;
+ byte_count = 0;
+ agp_offset = request->agp_start;
- if (request->count < 0 || request->count > 4096)
- return EINVAL;
+ DRM_DEBUG("count: %d\n", count);
+ DRM_DEBUG("order: %d\n", order);
+ DRM_DEBUG("size: %d\n", size);
+ DRM_DEBUG("agp_offset: %lu\n", agp_offset);
+ DRM_DEBUG("alignment: %d\n", alignment);
+ DRM_DEBUG("page_order: %d\n", page_order);
+ DRM_DEBUG("total: %d\n", total);
- order = drm_order(request->size);
if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
- return EINVAL;
+ return -EINVAL;
- DRM_SPINLOCK(&dev->dma_lock);
+ mtx_lock(&dev->count_lock);
+ if (dev->buf_use) {
+ mtx_unlock(&dev->count_lock);
+ return -EBUSY;
+ }
+ atomic_inc(&dev->buf_alloc);
+ mtx_unlock(&dev->count_lock);
- /* No more allocations after first buffer-using ioctl. */
- if (dev->buf_use != 0) {
- DRM_SPINUNLOCK(&dev->dma_lock);
- return EBUSY;
+ DRM_LOCK(dev);
+ entry = &dma->bufs[order];
+ if (entry->buf_count) {
+ DRM_UNLOCK(dev);
+ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM; /* May only call once for each order */
}
- /* No more than one allocation per order */
- if (dev->dma->bufs[order].buf_count != 0) {
- DRM_SPINUNLOCK(&dev->dma_lock);
- return ENOMEM;
+
+ if (count < 0 || count > 4096) {
+ DRM_UNLOCK(dev);
+ atomic_dec(&dev->buf_alloc);
+ return -EINVAL;
}
- ret = drm_do_addbufs_sg(dev, request);
+ entry->buflist = malloc(count * sizeof(*entry->buflist), DRM_MEM_BUFS,
+ M_NOWAIT | M_ZERO);
+ if (!entry->buflist) {
+ DRM_UNLOCK(dev);
+ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM;
+ }
- DRM_SPINUNLOCK(&dev->dma_lock);
+ entry->buf_size = size;
+ entry->page_order = page_order;
- return ret;
-}
+ offset = 0;
-int drm_addbufs_pci(struct drm_device *dev, struct drm_buf_desc *request)
-{
- int order, ret;
+ while (entry->buf_count < count) {
+ buf = &entry->buflist[entry->buf_count];
+ buf->idx = dma->buf_count + entry->buf_count;
+ buf->total = alignment;
+ buf->order = order;
+ buf->used = 0;
- if (!DRM_SUSER(DRM_CURPROC))
- return EACCES;
+ buf->offset = (dma->byte_count + offset);
+ buf->bus_address = agp_offset + offset;
+ buf->address = (void *)(agp_offset + offset);
+ buf->next = NULL;
+ buf->waiting = 0;
+ buf->pending = 0;
+ buf->file_priv = NULL;
- if (request->count < 0 || request->count > 4096)
- return EINVAL;
+ buf->dev_priv_size = dev->driver->dev_priv_size;
+ buf->dev_private = malloc(buf->dev_priv_size, DRM_MEM_BUFS,
+ M_NOWAIT | M_ZERO);
+ if (!buf->dev_private) {
+ /* Set count correctly so we free the proper amount. */
+ entry->buf_count = count;
+ drm_cleanup_buf_error(dev, entry);
+ DRM_UNLOCK(dev);
+ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM;
+ }
- order = drm_order(request->size);
- if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
- return EINVAL;
+ DRM_DEBUG("buffer %d @ %p\n", entry->buf_count, buf->address);
+
+ offset += alignment;
+ entry->buf_count++;
+ byte_count += PAGE_SIZE << page_order;
+ }
- DRM_SPINLOCK(&dev->dma_lock);
+ DRM_DEBUG("byte_count: %d\n", byte_count);
- /* No more allocations after first buffer-using ioctl. */
- if (dev->buf_use != 0) {
- DRM_SPINUNLOCK(&dev->dma_lock);
- return EBUSY;
+ temp_buflist = realloc(dma->buflist,
+ (dma->buf_count + entry->buf_count) * sizeof(*dma->buflist),
+ DRM_MEM_BUFS, M_NOWAIT);
+ if (!temp_buflist) {
+ /* Free the entry because it isn't valid */
+ drm_cleanup_buf_error(dev, entry);
+ DRM_UNLOCK(dev);
+ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM;
}
- /* No more than one allocation per order */
- if (dev->dma->bufs[order].buf_count != 0) {
- DRM_SPINUNLOCK(&dev->dma_lock);
- return ENOMEM;
+ dma->buflist = temp_buflist;
+
+ for (i = 0; i < entry->buf_count; i++) {
+ dma->buflist[i + dma->buf_count] = &entry->buflist[i];
}
- ret = drm_do_addbufs_pci(dev, request);
+ dma->buf_count += entry->buf_count;
+ dma->seg_count += entry->seg_count;
+ dma->page_count += byte_count >> PAGE_SHIFT;
+ dma->byte_count += byte_count;
+
+ DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
+ DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count);
- DRM_SPINUNLOCK(&dev->dma_lock);
+ DRM_UNLOCK(dev);
- return ret;
+ request->count = entry->buf_count;
+ request->size = size;
+
+ dma->flags = _DRM_DMA_USE_FB;
+
+ atomic_dec(&dev->buf_alloc);
+ return 0;
}
-int drm_addbufs(struct drm_device *dev, void *data, struct drm_file *file_priv)
+
+/**
+ * Add buffers for DMA transfers (ioctl).
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg pointer to a struct drm_buf_desc request.
+ * \return zero on success or a negative number on failure.
+ *
+ * According with the memory type specified in drm_buf_desc::flags and the
+ * build options, it dispatches the call either to addbufs_agp(),
+ * addbufs_sg() or addbufs_pci() for AGP, scatter-gather or consistent
+ * PCI memory respectively.
+ */
+int drm_addbufs(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
struct drm_buf_desc *request = data;
- int err;
+ int ret;
+
+ if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+ return -EINVAL;
+#if __OS_HAS_AGP
if (request->flags & _DRM_AGP_BUFFER)
- err = drm_addbufs_agp(dev, request);
- else if (request->flags & _DRM_SG_BUFFER)
- err = drm_addbufs_sg(dev, request);
+ ret = drm_addbufs_agp(dev, request);
+ else
+#endif
+ if (request->flags & _DRM_SG_BUFFER)
+ ret = drm_addbufs_sg(dev, request);
+ else if (request->flags & _DRM_FB_BUFFER)
+ ret = drm_addbufs_fb(dev, request);
else
- err = drm_addbufs_pci(dev, request);
+ ret = drm_addbufs_pci(dev, request);
- return err;
+ return ret;
}
-int drm_infobufs(struct drm_device *dev, void *data, struct drm_file *file_priv)
+/**
+ * Get information about the buffer mappings.
+ *
+ * This was originally mean for debugging purposes, or by a sophisticated
+ * client library to determine how best to use the available buffers (e.g.,
+ * large buffers can be used for image transfer).
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg pointer to a drm_buf_info structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Increments drm_device::buf_use while holding the drm_device::count_lock
+ * lock, preventing of allocating more buffers after this call. Information
+ * about each requested buffer is then copied into user space.
+ */
+int drm_infobufs(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
- drm_device_dma_t *dma = dev->dma;
+ struct drm_device_dma *dma = dev->dma;
struct drm_buf_info *request = data;
int i;
int count;
- int retcode = 0;
- DRM_SPINLOCK(&dev->dma_lock);
+ if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+ return -EINVAL;
+
+ if (!dma)
+ return -EINVAL;
+
+ mtx_lock(&dev->count_lock);
+ if (atomic_read(&dev->buf_alloc)) {
+ mtx_unlock(&dev->count_lock);
+ return -EBUSY;
+ }
++dev->buf_use; /* Can't allocate more after this call */
- DRM_SPINUNLOCK(&dev->dma_lock);
+ mtx_unlock(&dev->count_lock);
for (i = 0, count = 0; i < DRM_MAX_ORDER + 1; i++) {
if (dma->bufs[i].buf_count)
@@ -933,198 +1452,257 @@ int drm_infobufs(struct drm_device *dev, void *data, struct drm_file *file_priv)
if (request->count >= count) {
for (i = 0, count = 0; i < DRM_MAX_ORDER + 1; i++) {
if (dma->bufs[i].buf_count) {
- struct drm_buf_desc from;
-
- from.count = dma->bufs[i].buf_count;
- from.size = dma->bufs[i].buf_size;
- from.low_mark = dma->bufs[i].freelist.low_mark;
- from.high_mark = dma->bufs[i].freelist.high_mark;
-
- if (DRM_COPY_TO_USER(&request->list[count], &from,
- sizeof(struct drm_buf_desc)) != 0) {
- retcode = EFAULT;
- break;
- }
+ struct drm_buf_desc __user *to =
+ &request->list[count];
+ struct drm_buf_entry *from = &dma->bufs[i];
+ struct drm_freelist *list = &dma->bufs[i].freelist;
+ if (copy_to_user(&to->count,
+ &from->buf_count,
+ sizeof(from->buf_count)) ||
+ copy_to_user(&to->size,
+ &from->buf_size,
+ sizeof(from->buf_size)) ||
+ copy_to_user(&to->low_mark,
+ &list->low_mark,
+ sizeof(list->low_mark)) ||
+ copy_to_user(&to->high_mark,
+ &list->high_mark,
+ sizeof(list->high_mark)))
+ return -EFAULT;
DRM_DEBUG("%d %d %d %d %d\n",
- i, dma->bufs[i].buf_count,
- dma->bufs[i].buf_size,
- dma->bufs[i].freelist.low_mark,
- dma->bufs[i].freelist.high_mark);
+ i,
+ dma->bufs[i].buf_count,
+ dma->bufs[i].buf_size,
+ dma->bufs[i].freelist.low_mark,
+ dma->bufs[i].freelist.high_mark);
++count;
}
}
}
request->count = count;
- return retcode;
+ return 0;
}
-int drm_markbufs(struct drm_device *dev, void *data, struct drm_file *file_priv)
+/**
+ * Specifies a low and high water mark for buffer allocation
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg a pointer to a drm_buf_desc structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies that the size order is bounded between the admissible orders and
+ * updates the respective drm_device_dma::bufs entry low and high water mark.
+ *
+ * \note This ioctl is deprecated and mostly never used.
+ */
+int drm_markbufs(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
- drm_device_dma_t *dma = dev->dma;
+ struct drm_device_dma *dma = dev->dma;
struct drm_buf_desc *request = data;
int order;
+ struct drm_buf_entry *entry;
+
+ if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+ return -EINVAL;
+
+ if (!dma)
+ return -EINVAL;
DRM_DEBUG("%d, %d, %d\n",
request->size, request->low_mark, request->high_mark);
-
-
- order = drm_order(request->size);
- if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER ||
- request->low_mark < 0 || request->high_mark < 0) {
- return EINVAL;
- }
+ order = drm_order(request->size);
+ if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
+ return -EINVAL;
+ entry = &dma->bufs[order];
- DRM_SPINLOCK(&dev->dma_lock);
- if (request->low_mark > dma->bufs[order].buf_count ||
- request->high_mark > dma->bufs[order].buf_count) {
- DRM_SPINUNLOCK(&dev->dma_lock);
- return EINVAL;
- }
+ if (request->low_mark < 0 || request->low_mark > entry->buf_count)
+ return -EINVAL;
+ if (request->high_mark < 0 || request->high_mark > entry->buf_count)
+ return -EINVAL;
- dma->bufs[order].freelist.low_mark = request->low_mark;
- dma->bufs[order].freelist.high_mark = request->high_mark;
- DRM_SPINUNLOCK(&dev->dma_lock);
+ entry->freelist.low_mark = request->low_mark;
+ entry->freelist.high_mark = request->high_mark;
return 0;
}
-int drm_freebufs(struct drm_device *dev, void *data, struct drm_file *file_priv)
+/**
+ * Unreserve the buffers in list, previously reserved using drmDMA.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg pointer to a drm_buf_free structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Calls free_buffer() for each used buffer.
+ * This function is primarily used for debugging.
+ */
+int drm_freebufs(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
- drm_device_dma_t *dma = dev->dma;
+ struct drm_device_dma *dma = dev->dma;
struct drm_buf_free *request = data;
int i;
int idx;
- drm_buf_t *buf;
- int retcode = 0;
+ struct drm_buf *buf;
+
+ if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+ return -EINVAL;
+
+ if (!dma)
+ return -EINVAL;
DRM_DEBUG("%d\n", request->count);
-
- DRM_SPINLOCK(&dev->dma_lock);
for (i = 0; i < request->count; i++) {
- if (DRM_COPY_FROM_USER(&idx, &request->list[i], sizeof(idx))) {
- retcode = EFAULT;
- break;
- }
+ if (copy_from_user(&idx, &request->list[i], sizeof(idx)))
+ return -EFAULT;
if (idx < 0 || idx >= dma->buf_count) {
DRM_ERROR("Index %d (of %d max)\n",
- idx, dma->buf_count - 1);
- retcode = EINVAL;
- break;
+ idx, dma->buf_count - 1);
+ return -EINVAL;
}
buf = dma->buflist[idx];
if (buf->file_priv != file_priv) {
DRM_ERROR("Process %d freeing buffer not owned\n",
- DRM_CURRENTPID);
- retcode = EINVAL;
- break;
+ DRM_CURRENTPID);
+ return -EINVAL;
}
drm_free_buffer(dev, buf);
}
- DRM_SPINUNLOCK(&dev->dma_lock);
- return retcode;
+ return 0;
}
-int drm_mapbufs(struct drm_device *dev, void *data, struct drm_file *file_priv)
+/**
+ * Maps all of the DMA buffers into client-virtual space (ioctl).
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg pointer to a drm_buf_map structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Maps the AGP, SG or PCI buffer region with vm_mmap(), and copies information
+ * about each buffer into user space. For PCI buffers, it calls vm_mmap() with
+ * offset equal to 0, which drm_mmap() interpretes as PCI buffers and calls
+ * drm_mmap_dma().
+ */
+int drm_mapbufs(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
- drm_device_dma_t *dma = dev->dma;
+ struct drm_device_dma *dma = dev->dma;
int retcode = 0;
const int zero = 0;
+ vm_offset_t virtual;
vm_offset_t address;
struct vmspace *vms;
- vm_ooffset_t foff;
- vm_size_t size;
- vm_offset_t vaddr;
struct drm_buf_map *request = data;
int i;
- vms = DRM_CURPROC->td_proc->p_vmspace;
+ if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+ return -EINVAL;
- DRM_SPINLOCK(&dev->dma_lock);
- dev->buf_use++; /* Can't allocate more after this call */
- DRM_SPINUNLOCK(&dev->dma_lock);
-
- if (request->count < dma->buf_count)
- goto done;
-
- if ((drm_core_has_AGP(dev) && (dma->flags & _DRM_DMA_USE_AGP)) ||
- (drm_core_check_feature(dev, DRIVER_SG) &&
- (dma->flags & _DRM_DMA_USE_SG))) {
- drm_local_map_t *map = dev->agp_buffer_map;
+ if (!dma)
+ return -EINVAL;
- if (map == NULL) {
- retcode = EINVAL;
- goto done;
- }
- size = round_page(map->size);
- foff = (unsigned long)map->handle;
- } else {
- size = round_page(dma->byte_count),
- foff = 0;
+ mtx_lock(&dev->count_lock);
+ if (atomic_read(&dev->buf_alloc)) {
+ mtx_unlock(&dev->count_lock);
+ return -EBUSY;
}
+ dev->buf_use++; /* Can't allocate more after this call */
+ mtx_unlock(&dev->count_lock);
- vaddr = round_page((vm_offset_t)vms->vm_daddr + MAXDSIZ);
-#if __FreeBSD_version >= 600023
- retcode = vm_mmap(&vms->vm_map, &vaddr, size, PROT_READ | PROT_WRITE,
- VM_PROT_ALL, MAP_SHARED | MAP_NOSYNC, OBJT_DEVICE,
- dev->devnode, foff);
-#else
- retcode = vm_mmap(&vms->vm_map, &vaddr, size, PROT_READ | PROT_WRITE,
- VM_PROT_ALL, MAP_SHARED | MAP_NOSYNC,
- SLIST_FIRST(&dev->devnode->si_hlist), foff);
-#endif
- if (retcode)
- goto done;
-
- request->virtual = (void *)vaddr;
+ vms = DRM_CURPROC->td_proc->p_vmspace;
- for (i = 0; i < dma->buf_count; i++) {
- if (DRM_COPY_TO_USER(&request->list[i].idx,
- &dma->buflist[i]->idx, sizeof(request->list[0].idx))) {
- retcode = EFAULT;
- goto done;
- }
- if (DRM_COPY_TO_USER(&request->list[i].total,
- &dma->buflist[i]->total, sizeof(request->list[0].total))) {
- retcode = EFAULT;
- goto done;
+ if (request->count >= dma->buf_count) {
+ if ((drm_core_has_AGP(dev) && (dma->flags & _DRM_DMA_USE_AGP))
+ || (drm_core_check_feature(dev, DRIVER_SG)
+ && (dma->flags & _DRM_DMA_USE_SG))
+ || (drm_core_check_feature(dev, DRIVER_FB_DMA)
+ && (dma->flags & _DRM_DMA_USE_FB))) {
+ struct drm_local_map *map = dev->agp_buffer_map;
+ vm_ooffset_t token = dev->agp_buffer_token;
+
+ if (!map) {
+ retcode = -EINVAL;
+ goto done;
+ }
+ retcode = vm_mmap(&vms->vm_map, &virtual, map->size,
+ PROT_READ | PROT_WRITE, VM_PROT_ALL,
+ MAP_SHARED | MAP_NOSYNC, OBJT_DEVICE,
+ file_priv->minor->device, token);
+ } else {
+ retcode = vm_mmap(&vms->vm_map, &virtual, dma->byte_count,
+ PROT_READ | PROT_WRITE, VM_PROT_ALL,
+ MAP_SHARED | MAP_NOSYNC, OBJT_DEVICE,
+ file_priv->minor->device, 0);
}
- if (DRM_COPY_TO_USER(&request->list[i].used, &zero,
- sizeof(zero))) {
- retcode = EFAULT;
+ if (retcode) {
+ /* Real error */
+ retcode = -retcode;
goto done;
}
- address = vaddr + dma->buflist[i]->offset; /* *** */
- if (DRM_COPY_TO_USER(&request->list[i].address, &address,
- sizeof(address))) {
- retcode = EFAULT;
- goto done;
+ request->virtual = (void __user *)virtual;
+
+ for (i = 0; i < dma->buf_count; i++) {
+ if (copy_to_user(&request->list[i].idx,
+ &dma->buflist[i]->idx,
+ sizeof(request->list[0].idx))) {
+ retcode = -EFAULT;
+ goto done;
+ }
+ if (copy_to_user(&request->list[i].total,
+ &dma->buflist[i]->total,
+ sizeof(request->list[0].total))) {
+ retcode = -EFAULT;
+ goto done;
+ }
+ if (copy_to_user(&request->list[i].used,
+ &zero, sizeof(zero))) {
+ retcode = -EFAULT;
+ goto done;
+ }
+ address = virtual + dma->buflist[i]->offset; /* *** */
+ if (copy_to_user(&request->list[i].address,
+ &address, sizeof(address))) {
+ retcode = -EFAULT;
+ goto done;
+ }
}
}
-
- done:
+ done:
request->count = dma->buf_count;
-
DRM_DEBUG("%d buffers, retcode = %d\n", request->count, retcode);
return retcode;
}
-/*
- * Compute order. Can be made faster.
+/**
+ * Compute size order. Returns the exponent of the smaller power of two which
+ * is greater or equal to given number.
+ *
+ * \param size size.
+ * \return order.
+ *
+ * \todo Can be made faster.
*/
int drm_order(unsigned long size)
{
int order;
+ unsigned long tmp;
- if (size == 0)
- return 0;
+ for (order = 0, tmp = size >> 1; tmp; tmp >>= 1, order++) ;
- order = flsl(size) - 1;
- if (size & ~(1ul << order))
+ if (size & (size - 1))
++order;
return order;
}
+EXPORT_SYMBOL(drm_order);
diff --git a/sys/dev/drm2/drm_context.c b/sys/dev/drm2/drm_context.c
index 9ca941e..90e08e9 100644
--- a/sys/dev/drm2/drm_context.c
+++ b/sys/dev/drm2/drm_context.c
@@ -1,4 +1,14 @@
-/*-
+/**
+ * \file drm_context.c
+ * IOCTLs for generic contexts
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
+ * Created: Fri Nov 24 18:31:37 2000 by gareth@valinux.com
+ *
* Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
* All Rights Reserved.
@@ -21,29 +31,37 @@
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Rickard E. (Rik) Faith <faith@valinux.com>
- * Gareth Hughes <gareth@valinux.com>
- *
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-/** @file drm_context.c
- * Implementation of the context management ioctls.
+/*
+ * ChangeLog:
+ * 2001-11-16 Torsten Duwe <duwe@caldera.de>
+ * added context constructor/destructor hooks,
+ * needed by SiS driver's memory management.
*/
#include <dev/drm2/drmP.h>
-/* ================================================================
- * Context bitmap support
- */
+/******************************************************************/
+/** \name Context bitmap support */
+/*@{*/
-void drm_ctxbitmap_free(struct drm_device *dev, int ctx_handle)
+/**
+ * Free a handle from the context bitmap.
+ *
+ * \param dev DRM device.
+ * \param ctx_handle context handle.
+ *
+ * Clears the bit specified by \p ctx_handle in drm_device::ctx_bitmap and the entry
+ * in drm_device::ctx_idr, while holding the drm_device::struct_mutex
+ * lock.
+ */
+void drm_ctxbitmap_free(struct drm_device * dev, int ctx_handle)
{
- if (ctx_handle < 0 || ctx_handle >= DRM_MAX_CTXBITMAP ||
+ if (ctx_handle < 0 || ctx_handle >= DRM_MAX_CTXBITMAP ||
dev->ctx_bitmap == NULL) {
DRM_ERROR("Attempt to free invalid context handle: %d\n",
ctx_handle);
@@ -54,10 +72,18 @@ void drm_ctxbitmap_free(struct drm_device *dev, int ctx_handle)
clear_bit(ctx_handle, dev->ctx_bitmap);
dev->context_sareas[ctx_handle] = NULL;
DRM_UNLOCK(dev);
- return;
}
-int drm_ctxbitmap_next(struct drm_device *dev)
+/**
+ * Context bitmap allocation.
+ *
+ * \param dev DRM device.
+ * \return (non-negative) context handle on success or a negative number on failure.
+ *
+ * Allocate a new idr from drm_device::ctx_idr while holding the
+ * drm_device::struct_mutex lock.
+ */
+static int drm_ctxbitmap_next(struct drm_device * dev)
{
int bit;
@@ -74,7 +100,7 @@ int drm_ctxbitmap_next(struct drm_device *dev)
set_bit(bit, dev->ctx_bitmap);
DRM_DEBUG("bit : %d\n", bit);
if ((bit+1) > dev->max_context) {
- drm_local_map_t **ctx_sareas;
+ struct drm_local_map **ctx_sareas;
int max_ctx = (bit+1);
ctx_sareas = realloc(dev->context_sareas,
@@ -94,7 +120,14 @@ int drm_ctxbitmap_next(struct drm_device *dev)
return bit;
}
-int drm_ctxbitmap_init(struct drm_device *dev)
+/**
+ * Context bitmap initialization.
+ *
+ * \param dev DRM device.
+ *
+ * Initialise the drm_device::ctx_idr
+ */
+int drm_ctxbitmap_init(struct drm_device * dev)
{
int i;
int temp;
@@ -118,7 +151,15 @@ int drm_ctxbitmap_init(struct drm_device *dev)
return 0;
}
-void drm_ctxbitmap_cleanup(struct drm_device *dev)
+/**
+ * Context bitmap cleanup.
+ *
+ * \param dev DRM device.
+ *
+ * Free all idr members using drm_ctx_sarea_free helper function
+ * while holding the drm_device::struct_mutex lock.
+ */
+void drm_ctxbitmap_cleanup(struct drm_device * dev)
{
DRM_LOCK(dev);
if (dev->context_sareas != NULL)
@@ -127,15 +168,29 @@ void drm_ctxbitmap_cleanup(struct drm_device *dev)
DRM_UNLOCK(dev);
}
-/* ================================================================
- * Per Context SAREA Support
- */
+/*@}*/
+
+/******************************************************************/
+/** \name Per Context SAREA Support */
+/*@{*/
+/**
+ * Get per-context SAREA.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument pointing to a drm_ctx_priv_map structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Gets the map from drm_device::ctx_idr with the handle specified and
+ * returns its handle.
+ */
int drm_getsareactx(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_ctx_priv_map *request = data;
- drm_local_map_t *map;
+ struct drm_local_map *map;
DRM_LOCK(dev);
if (dev->max_context < 0 ||
@@ -152,15 +207,29 @@ int drm_getsareactx(struct drm_device *dev, void *data,
return 0;
}
+/**
+ * Set per-context SAREA.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument pointing to a drm_ctx_priv_map structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Searches the mapping specified in \p arg and update the entry in
+ * drm_device::ctx_idr with it.
+ */
int drm_setsareactx(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_ctx_priv_map *request = data;
- drm_local_map_t *map = NULL;
+ struct drm_local_map *map = NULL;
+ struct drm_map_list *r_list = NULL;
DRM_LOCK(dev);
- TAILQ_FOREACH(map, &dev->maplist, link) {
- if (map->handle == request->handle) {
+ list_for_each_entry(r_list, &dev->maplist, head) {
+ if (r_list->map
+ && r_list->user_token == (unsigned long) request->handle) {
if (dev->max_context < 0)
goto bad;
if (request->ctx_id >= (unsigned) dev->max_context)
@@ -176,56 +245,91 @@ bad:
return EINVAL;
}
-/* ================================================================
- * The actual DRM context handling routines
- */
+/*@}*/
+
+/******************************************************************/
+/** \name The actual DRM context handling routines */
+/*@{*/
-int drm_context_switch(struct drm_device *dev, int old, int new)
+/**
+ * Switch context.
+ *
+ * \param dev DRM device.
+ * \param old old context handle.
+ * \param new new context handle.
+ * \return zero on success or a negative number on failure.
+ *
+ * Attempt to set drm_device::context_flag.
+ */
+static int drm_context_switch(struct drm_device * dev, int old, int new)
{
- if (atomic_xchg(&dev->context_flag, 1) != 0) {
+ if (test_and_set_bit(0, &dev->context_flag)) {
DRM_ERROR("Reentering -- FIXME\n");
- return EBUSY;
+ return -EBUSY;
}
DRM_DEBUG("Context switch from %d to %d\n", old, new);
if (new == dev->last_context) {
- atomic_xchg(&dev->context_flag, 0);
+ clear_bit(0, &dev->context_flag);
return 0;
}
return 0;
}
-int drm_context_switch_complete(struct drm_device *dev, int new)
+/**
+ * Complete context switch.
+ *
+ * \param dev DRM device.
+ * \param new new context handle.
+ * \return zero on success or a negative number on failure.
+ *
+ * Updates drm_device::last_context and drm_device::last_switch. Verifies the
+ * hardware lock is held, clears the drm_device::context_flag and wakes up
+ * drm_device::context_wait.
+ */
+static int drm_context_switch_complete(struct drm_device *dev,
+ struct drm_file *file_priv, int new)
{
- dev->last_context = new; /* PRE/POST: This is the _only_ writer. */
+ dev->last_context = new; /* PRE/POST: This is the _only_ writer. */
+ dev->last_switch = jiffies;
- if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+ if (!_DRM_LOCK_IS_HELD(file_priv->master->lock.hw_lock->lock)) {
DRM_ERROR("Lock isn't held after context switch\n");
}
/* If a context switch is ever initiated
when the kernel holds the lock, release
that lock here. */
- atomic_xchg(&dev->context_flag, 0);
+ clear_bit(0, &dev->context_flag);
+ wakeup(&dev->context_wait);
return 0;
}
-int drm_resctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
+/**
+ * Reserve contexts.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument pointing to a drm_ctx_res structure.
+ * \return zero on success or a negative number on failure.
+ */
+int drm_resctx(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
struct drm_ctx_res *res = data;
struct drm_ctx ctx;
int i;
if (res->count >= DRM_RESERVED_CONTEXTS) {
- bzero(&ctx, sizeof(ctx));
+ memset(&ctx, 0, sizeof(ctx));
for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
ctx.handle = i;
- if (DRM_COPY_TO_USER(&res->contexts[i],
- &ctx, sizeof(ctx)))
- return EFAULT;
+ if (copy_to_user(&res->contexts[i], &ctx, sizeof(ctx)))
+ return -EFAULT;
}
}
res->count = DRM_RESERVED_CONTEXTS;
@@ -233,8 +337,21 @@ int drm_resctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
return 0;
}
-int drm_addctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
+/**
+ * Add context.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument pointing to a drm_ctx structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Get a new handle for the context and copy to userspace.
+ */
+int drm_addctx(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
+ struct drm_ctx_list *ctx_entry;
struct drm_ctx *ctx = data;
ctx->handle = drm_ctxbitmap_next(dev);
@@ -246,15 +363,24 @@ int drm_addctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
if (ctx->handle == -1) {
DRM_DEBUG("Not enough free contexts.\n");
/* Should this return -EBUSY instead? */
- return ENOMEM;
+ return -ENOMEM;
}
- if (dev->driver->context_ctor && ctx->handle != DRM_KERNEL_CONTEXT) {
- DRM_LOCK(dev);
- dev->driver->context_ctor(dev, ctx->handle);
- DRM_UNLOCK(dev);
+ ctx_entry = malloc(sizeof(*ctx_entry), DRM_MEM_CTXBITMAP, M_NOWAIT);
+ if (!ctx_entry) {
+ DRM_DEBUG("out of memory\n");
+ return -ENOMEM;
}
+ INIT_LIST_HEAD(&ctx_entry->head);
+ ctx_entry->handle = ctx->handle;
+ ctx_entry->tag = file_priv;
+
+ DRM_LOCK(dev);
+ list_add(&ctx_entry->head, &dev->ctxlist);
+ ++dev->ctx_count;
+ DRM_UNLOCK(dev);
+
return 0;
}
@@ -264,6 +390,15 @@ int drm_modctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
return 0;
}
+/**
+ * Get context.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument pointing to a drm_ctx structure.
+ * \return zero on success or a negative number on failure.
+ */
int drm_getctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
struct drm_ctx *ctx = data;
@@ -274,6 +409,17 @@ int drm_getctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
return 0;
}
+/**
+ * Switch context.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument pointing to a drm_ctx structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Calls context_switch().
+ */
int drm_switchctx(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
@@ -283,30 +429,66 @@ int drm_switchctx(struct drm_device *dev, void *data,
return drm_context_switch(dev, dev->last_context, ctx->handle);
}
-int drm_newctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
+/**
+ * New context.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument pointing to a drm_ctx structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Calls context_switch_complete().
+ */
+int drm_newctx(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
struct drm_ctx *ctx = data;
DRM_DEBUG("%d\n", ctx->handle);
- drm_context_switch_complete(dev, ctx->handle);
+ drm_context_switch_complete(dev, file_priv, ctx->handle);
return 0;
}
-int drm_rmctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
+/**
+ * Remove context.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument pointing to a drm_ctx structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * If not the special kernel context, calls ctxbitmap_free() to free the specified context.
+ */
+int drm_rmctx(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
struct drm_ctx *ctx = data;
DRM_DEBUG("%d\n", ctx->handle);
if (ctx->handle != DRM_KERNEL_CONTEXT) {
- if (dev->driver->context_dtor) {
- DRM_LOCK(dev);
+ if (dev->driver->context_dtor)
dev->driver->context_dtor(dev, ctx->handle);
- DRM_UNLOCK(dev);
- }
-
drm_ctxbitmap_free(dev, ctx->handle);
}
+ DRM_LOCK(dev);
+ if (!list_empty(&dev->ctxlist)) {
+ struct drm_ctx_list *pos, *n;
+
+ list_for_each_entry_safe(pos, n, &dev->ctxlist, head) {
+ if (pos->handle == ctx->handle) {
+ list_del(&pos->head);
+ free(pos, DRM_MEM_CTXBITMAP);
+ --dev->ctx_count;
+ }
+ }
+ }
+ DRM_UNLOCK(dev);
+
return 0;
}
+
+/*@}*/
diff --git a/sys/dev/drm2/drm_crtc.c b/sys/dev/drm2/drm_crtc.c
index e044ec2..318a764 100644
--- a/sys/dev/drm2/drm_crtc.c
+++ b/sys/dev/drm2/drm_crtc.c
@@ -32,19 +32,20 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include <dev/drm2/drm.h>
#include <dev/drm2/drmP.h>
#include <dev/drm2/drm_crtc.h>
#include <dev/drm2/drm_edid.h>
#include <dev/drm2/drm_fourcc.h>
-#include <sys/limits.h>
+
+static void drm_property_destroy_blob(struct drm_device *dev,
+ struct drm_property_blob *blob);
/* Avoid boilerplate. I'm tired of typing. */
#define DRM_ENUM_NAME_FN(fnname, list) \
char *fnname(int val) \
{ \
int i; \
- for (i = 0; i < DRM_ARRAY_SIZE(list); i++) { \
+ for (i = 0; i < ARRAY_SIZE(list); i++) { \
if (list[i].type == val) \
return list[i].name; \
} \
@@ -160,6 +161,7 @@ static struct drm_conn_prop_enum_list drm_connector_enum_list[] =
{ DRM_MODE_CONNECTOR_HDMIB, "HDMI-B", 0 },
{ DRM_MODE_CONNECTOR_TV, "TV", 0 },
{ DRM_MODE_CONNECTOR_eDP, "eDP", 0 },
+ { DRM_MODE_CONNECTOR_VIRTUAL, "Virtual", 0},
};
static struct drm_prop_enum_list drm_encoder_enum_list[] =
@@ -168,11 +170,9 @@ static struct drm_prop_enum_list drm_encoder_enum_list[] =
{ DRM_MODE_ENCODER_TMDS, "TMDS" },
{ DRM_MODE_ENCODER_LVDS, "LVDS" },
{ DRM_MODE_ENCODER_TVDAC, "TV" },
+ { DRM_MODE_ENCODER_VIRTUAL, "Virtual" },
};
-static void drm_property_destroy_blob(struct drm_device *dev,
- struct drm_property_blob *blob);
-
char *drm_get_encoder_name(struct drm_encoder *encoder)
{
static char buf[32];
@@ -182,6 +182,7 @@ char *drm_get_encoder_name(struct drm_encoder *encoder)
encoder->base.id);
return buf;
}
+EXPORT_SYMBOL(drm_get_encoder_name);
char *drm_get_connector_name(struct drm_connector *connector)
{
@@ -192,6 +193,7 @@ char *drm_get_connector_name(struct drm_connector *connector)
connector->connector_type_id);
return buf;
}
+EXPORT_SYMBOL(drm_get_connector_name);
char *drm_get_connector_status_name(enum drm_connector_status status)
{
@@ -221,13 +223,12 @@ char *drm_get_connector_status_name(enum drm_connector_status status)
static int drm_mode_object_get(struct drm_device *dev,
struct drm_mode_object *obj, uint32_t obj_type)
{
- int new_id;
+ int new_id = 0;
int ret;
- new_id = 0;
ret = drm_gem_name_create(&dev->mode_config.crtc_names, obj, &new_id);
- if (ret != 0)
- return (ret);
+ if (ret)
+ return ret;
obj->id = new_id;
obj->type = obj_type;
@@ -254,7 +255,7 @@ static void drm_mode_object_put(struct drm_device *dev,
struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
uint32_t id, uint32_t type)
{
- struct drm_mode_object *obj;
+ struct drm_mode_object *obj = NULL;
obj = drm_gem_name_ref(&dev->mode_config.crtc_names, id, NULL);
if (!obj || (obj->type != type) || (obj->id != id))
@@ -262,6 +263,7 @@ struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
return obj;
}
+EXPORT_SYMBOL(drm_mode_object_find);
/**
* drm_framebuffer_init - initialize a framebuffer
@@ -281,7 +283,7 @@ int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb,
{
int ret;
- DRM_MODE_CONFIG_ASSERT_LOCKED(dev);
+ refcount_init(&fb->refcount, 1);
ret = drm_mode_object_get(dev, &fb->base, DRM_MODE_OBJECT_FB);
if (ret)
@@ -294,6 +296,39 @@ int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb,
return 0;
}
+EXPORT_SYMBOL(drm_framebuffer_init);
+
+static void drm_framebuffer_free(struct drm_framebuffer *fb)
+{
+ fb->funcs->destroy(fb);
+}
+
+/**
+ * drm_framebuffer_unreference - unref a framebuffer
+ *
+ * LOCKING:
+ * Caller must hold mode config lock.
+ */
+void drm_framebuffer_unreference(struct drm_framebuffer *fb)
+{
+ struct drm_device *dev = fb->dev;
+ DRM_DEBUG("FB ID: %d\n", fb->base.id);
+ if (!sx_xlocked(&dev->mode_config.mutex))
+ DRM_WARNING("%s: dev->mode_config.mutex not locked\n", __func__);
+ if (refcount_release(&fb->refcount))
+ drm_framebuffer_free(fb);
+}
+EXPORT_SYMBOL(drm_framebuffer_unreference);
+
+/**
+ * drm_framebuffer_reference - incr the fb refcnt
+ */
+void drm_framebuffer_reference(struct drm_framebuffer *fb)
+{
+ DRM_DEBUG("FB ID: %d\n", fb->base.id);
+ refcount_acquire(&fb->refcount);
+}
+EXPORT_SYMBOL(drm_framebuffer_reference);
/**
* drm_framebuffer_cleanup - remove a framebuffer object
@@ -308,13 +343,37 @@ int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb,
void drm_framebuffer_cleanup(struct drm_framebuffer *fb)
{
struct drm_device *dev = fb->dev;
+ /*
+ * This could be moved to drm_framebuffer_remove(), but for
+ * debugging is nice to keep around the list of fb's that are
+ * no longer associated w/ a drm_file but are not unreferenced
+ * yet. (i915 and omapdrm have debugfs files which will show
+ * this.)
+ */
+ drm_mode_object_put(dev, &fb->base);
+ list_del(&fb->head);
+ dev->mode_config.num_fb--;
+}
+EXPORT_SYMBOL(drm_framebuffer_cleanup);
+
+/**
+ * drm_framebuffer_remove - remove and unreference a framebuffer object
+ * @fb: framebuffer to remove
+ *
+ * LOCKING:
+ * Caller must hold mode config lock.
+ *
+ * Scans all the CRTCs and planes in @dev's mode_config. If they're
+ * using @fb, removes it, setting it to NULL.
+ */
+void drm_framebuffer_remove(struct drm_framebuffer *fb)
+{
+ struct drm_device *dev = fb->dev;
struct drm_crtc *crtc;
struct drm_plane *plane;
struct drm_mode_set set;
int ret;
- DRM_MODE_CONFIG_ASSERT_LOCKED(dev);
-
/* remove from any CRTC */
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
if (crtc->fb == fb) {
@@ -340,10 +399,11 @@ void drm_framebuffer_cleanup(struct drm_framebuffer *fb)
}
}
- drm_mode_object_put(dev, &fb->base);
- list_del(&fb->head);
- dev->mode_config.num_fb--;
+ list_del(&fb->filp_head);
+
+ drm_framebuffer_unreference(fb);
}
+EXPORT_SYMBOL(drm_framebuffer_remove);
/**
* drm_crtc_init - Initialise a new CRTC object
@@ -366,8 +426,10 @@ int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
crtc->dev = dev;
crtc->funcs = funcs;
+ crtc->invert_dimensions = false;
sx_xlock(&dev->mode_config.mutex);
+
ret = drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC);
if (ret)
goto out;
@@ -377,11 +439,12 @@ int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
list_add_tail(&crtc->head, &dev->mode_config.crtc_list);
dev->mode_config.num_crtc++;
-out:
+ out:
sx_xunlock(&dev->mode_config.mutex);
return ret;
}
+EXPORT_SYMBOL(drm_crtc_init);
/**
* drm_crtc_cleanup - Cleans up the core crtc usage.
@@ -397,17 +460,14 @@ void drm_crtc_cleanup(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
- DRM_MODE_CONFIG_ASSERT_LOCKED(dev);
-
- if (crtc->gamma_store) {
- free(crtc->gamma_store, DRM_MEM_KMS);
- crtc->gamma_store = NULL;
- }
+ free(crtc->gamma_store, DRM_MEM_KMS);
+ crtc->gamma_store = NULL;
drm_mode_object_put(dev, &crtc->base);
list_del(&crtc->head);
dev->mode_config.num_crtc--;
}
+EXPORT_SYMBOL(drm_crtc_cleanup);
/**
* drm_mode_probed_add - add a mode to a connector's probed mode list
@@ -422,11 +482,9 @@ void drm_crtc_cleanup(struct drm_crtc *crtc)
void drm_mode_probed_add(struct drm_connector *connector,
struct drm_display_mode *mode)
{
-
- DRM_MODE_CONFIG_ASSERT_LOCKED(connector->dev);
-
list_add(&mode->head, &connector->probed_modes);
}
+EXPORT_SYMBOL(drm_mode_probed_add);
/**
* drm_mode_remove - remove and free a mode
@@ -441,12 +499,10 @@ void drm_mode_probed_add(struct drm_connector *connector,
void drm_mode_remove(struct drm_connector *connector,
struct drm_display_mode *mode)
{
-
- DRM_MODE_CONFIG_ASSERT_LOCKED(connector->dev);
-
list_del(&mode->head);
drm_mode_destroy(connector->dev, mode);
}
+EXPORT_SYMBOL(drm_mode_remove);
/**
* drm_connector_init - Init a preallocated connector
@@ -487,21 +543,25 @@ int drm_connector_init(struct drm_device *dev,
INIT_LIST_HEAD(&connector->probed_modes);
INIT_LIST_HEAD(&connector->modes);
connector->edid_blob_ptr = NULL;
+ connector->status = connector_status_unknown;
list_add_tail(&connector->head, &dev->mode_config.connector_list);
dev->mode_config.num_connector++;
- drm_connector_attach_property(connector,
- dev->mode_config.edid_property, 0);
+ if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL)
+ drm_object_attach_property(&connector->base,
+ dev->mode_config.edid_property,
+ 0);
- drm_connector_attach_property(connector,
+ drm_object_attach_property(&connector->base,
dev->mode_config.dpms_property, 0);
-out:
+ out:
sx_xunlock(&dev->mode_config.mutex);
return ret;
}
+EXPORT_SYMBOL(drm_connector_init);
/**
* drm_connector_cleanup - cleans up an initialised connector
@@ -527,18 +587,30 @@ void drm_connector_cleanup(struct drm_connector *connector)
drm_mode_remove(connector, mode);
sx_xlock(&dev->mode_config.mutex);
- if (connector->edid_blob_ptr)
- drm_property_destroy_blob(dev, connector->edid_blob_ptr);
drm_mode_object_put(dev, &connector->base);
list_del(&connector->head);
dev->mode_config.num_connector--;
sx_xunlock(&dev->mode_config.mutex);
}
+EXPORT_SYMBOL(drm_connector_cleanup);
+
+void drm_connector_unplug_all(struct drm_device *dev)
+{
+#ifdef FREEBSD_NOTYET
+ struct drm_connector *connector;
+
+ /* taking the mode config mutex ends up in a clash with sysfs */
+ list_for_each_entry(connector, &dev->mode_config.connector_list, head)
+ drm_sysfs_connector_remove(connector);
+#endif /* FREEBSD_NOTYET */
+
+}
+EXPORT_SYMBOL(drm_connector_unplug_all);
int drm_encoder_init(struct drm_device *dev,
- struct drm_encoder *encoder,
- const struct drm_encoder_funcs *funcs,
- int encoder_type)
+ struct drm_encoder *encoder,
+ const struct drm_encoder_funcs *funcs,
+ int encoder_type)
{
int ret;
@@ -555,22 +627,23 @@ int drm_encoder_init(struct drm_device *dev,
list_add_tail(&encoder->head, &dev->mode_config.encoder_list);
dev->mode_config.num_encoder++;
-out:
+ out:
sx_xunlock(&dev->mode_config.mutex);
return ret;
}
+EXPORT_SYMBOL(drm_encoder_init);
void drm_encoder_cleanup(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
-
sx_xlock(&dev->mode_config.mutex);
drm_mode_object_put(dev, &encoder->base);
list_del(&encoder->head);
dev->mode_config.num_encoder--;
sx_xunlock(&dev->mode_config.mutex);
}
+EXPORT_SYMBOL(drm_encoder_cleanup);
int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
unsigned long possible_crtcs,
@@ -591,6 +664,12 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
plane->funcs = funcs;
plane->format_types = malloc(sizeof(uint32_t) * format_count,
DRM_MEM_KMS, M_WAITOK);
+ if (!plane->format_types) {
+ DRM_DEBUG_KMS("out of memory when allocating plane\n");
+ drm_mode_object_put(dev, &plane->base);
+ ret = -ENOMEM;
+ goto out;
+ }
memcpy(plane->format_types, formats, format_count * sizeof(uint32_t));
plane->format_count = format_count;
@@ -607,11 +686,12 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
INIT_LIST_HEAD(&plane->head);
}
-out:
+ out:
sx_xunlock(&dev->mode_config.mutex);
return ret;
}
+EXPORT_SYMBOL(drm_plane_init);
void drm_plane_cleanup(struct drm_plane *plane)
{
@@ -627,6 +707,7 @@ void drm_plane_cleanup(struct drm_plane *plane)
}
sx_xunlock(&dev->mode_config.mutex);
}
+EXPORT_SYMBOL(drm_plane_cleanup);
/**
* drm_mode_create - create a new display mode
@@ -646,13 +727,17 @@ struct drm_display_mode *drm_mode_create(struct drm_device *dev)
nmode = malloc(sizeof(struct drm_display_mode), DRM_MEM_KMS,
M_WAITOK | M_ZERO);
+ if (!nmode)
+ return NULL;
if (drm_mode_object_get(dev, &nmode->base, DRM_MODE_OBJECT_MODE)) {
free(nmode, DRM_MEM_KMS);
- return (NULL);
+ return NULL;
}
+
return nmode;
}
+EXPORT_SYMBOL(drm_mode_create);
/**
* drm_mode_destroy - remove a mode
@@ -673,6 +758,7 @@ void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode)
free(mode, DRM_MEM_KMS);
}
+EXPORT_SYMBOL(drm_mode_destroy);
static int drm_mode_create_standard_connector_properties(struct drm_device *dev)
{
@@ -689,7 +775,7 @@ static int drm_mode_create_standard_connector_properties(struct drm_device *dev)
dpms = drm_property_create_enum(dev, 0,
"DPMS", drm_dpms_enum_list,
- DRM_ARRAY_SIZE(drm_dpms_enum_list));
+ ARRAY_SIZE(drm_dpms_enum_list));
dev->mode_config.dpms_property = dpms;
return 0;
@@ -713,17 +799,18 @@ int drm_mode_create_dvi_i_properties(struct drm_device *dev)
drm_property_create_enum(dev, 0,
"select subconnector",
drm_dvi_i_select_enum_list,
- DRM_ARRAY_SIZE(drm_dvi_i_select_enum_list));
+ ARRAY_SIZE(drm_dvi_i_select_enum_list));
dev->mode_config.dvi_i_select_subconnector_property = dvi_i_selector;
dvi_i_subconnector = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
"subconnector",
drm_dvi_i_subconnector_enum_list,
- DRM_ARRAY_SIZE(drm_dvi_i_subconnector_enum_list));
+ ARRAY_SIZE(drm_dvi_i_subconnector_enum_list));
dev->mode_config.dvi_i_subconnector_property = dvi_i_subconnector;
return 0;
}
+EXPORT_SYMBOL(drm_mode_create_dvi_i_properties);
/**
* drm_create_tv_properties - create TV specific connector properties
@@ -752,14 +839,14 @@ int drm_mode_create_tv_properties(struct drm_device *dev, int num_modes,
tv_selector = drm_property_create_enum(dev, 0,
"select subconnector",
drm_tv_select_enum_list,
- DRM_ARRAY_SIZE(drm_tv_select_enum_list));
+ ARRAY_SIZE(drm_tv_select_enum_list));
dev->mode_config.tv_select_subconnector_property = tv_selector;
tv_subconnector =
drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
"subconnector",
drm_tv_subconnector_enum_list,
- DRM_ARRAY_SIZE(drm_tv_subconnector_enum_list));
+ ARRAY_SIZE(drm_tv_subconnector_enum_list));
dev->mode_config.tv_subconnector_property = tv_subconnector;
/*
@@ -804,6 +891,7 @@ int drm_mode_create_tv_properties(struct drm_device *dev, int num_modes,
return 0;
}
+EXPORT_SYMBOL(drm_mode_create_tv_properties);
/**
* drm_mode_create_scaling_mode_property - create scaling mode property
@@ -822,12 +910,13 @@ int drm_mode_create_scaling_mode_property(struct drm_device *dev)
scaling_mode =
drm_property_create_enum(dev, 0, "scaling mode",
drm_scaling_mode_enum_list,
- DRM_ARRAY_SIZE(drm_scaling_mode_enum_list));
+ ARRAY_SIZE(drm_scaling_mode_enum_list));
dev->mode_config.scaling_mode_property = scaling_mode;
return 0;
}
+EXPORT_SYMBOL(drm_mode_create_scaling_mode_property);
/**
* drm_mode_create_dithering_property - create dithering property
@@ -846,11 +935,12 @@ int drm_mode_create_dithering_property(struct drm_device *dev)
dithering_mode =
drm_property_create_enum(dev, 0, "dithering",
drm_dithering_mode_enum_list,
- DRM_ARRAY_SIZE(drm_dithering_mode_enum_list));
+ ARRAY_SIZE(drm_dithering_mode_enum_list));
dev->mode_config.dithering_mode_property = dithering_mode;
return 0;
}
+EXPORT_SYMBOL(drm_mode_create_dithering_property);
/**
* drm_mode_create_dirty_property - create dirty property
@@ -870,11 +960,12 @@ int drm_mode_create_dirty_info_property(struct drm_device *dev)
drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
"dirty",
drm_dirty_info_enum_list,
- DRM_ARRAY_SIZE(drm_dirty_info_enum_list));
+ ARRAY_SIZE(drm_dirty_info_enum_list));
dev->mode_config.dirty_info_property = dirty_info;
return 0;
}
+EXPORT_SYMBOL(drm_mode_create_dirty_info_property);
/**
* drm_mode_config_init - initialize DRM mode_configuration structure
@@ -908,9 +999,9 @@ void drm_mode_config_init(struct drm_device *dev)
dev->mode_config.num_crtc = 0;
dev->mode_config.num_encoder = 0;
}
+EXPORT_SYMBOL(drm_mode_config_init);
-static int
-drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *group)
+int drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *group)
{
uint32_t total_objects = 0;
@@ -920,6 +1011,8 @@ drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *group)
group->id_list = malloc(total_objects * sizeof(uint32_t),
DRM_MEM_KMS, M_WAITOK | M_ZERO);
+ if (!group->id_list)
+ return -ENOMEM;
group->num_crtcs = 0;
group->num_connectors = 0;
@@ -927,6 +1020,12 @@ drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *group)
return 0;
}
+void drm_mode_group_free(struct drm_mode_group *group)
+{
+ free(group->id_list, DRM_MEM_KMS);
+ group->id_list = NULL;
+}
+
int drm_mode_group_init_legacy_group(struct drm_device *dev,
struct drm_mode_group *group)
{
@@ -951,6 +1050,7 @@ int drm_mode_group_init_legacy_group(struct drm_device *dev,
return 0;
}
+EXPORT_SYMBOL(drm_mode_group_init_legacy_group);
/**
* drm_mode_config_cleanup - free up DRM mode_config info
@@ -971,6 +1071,7 @@ void drm_mode_config_cleanup(struct drm_device *dev)
struct drm_encoder *encoder, *enct;
struct drm_framebuffer *fb, *fbt;
struct drm_property *property, *pt;
+ struct drm_property_blob *blob, *bt;
struct drm_plane *plane, *plt;
list_for_each_entry_safe(encoder, enct, &dev->mode_config.encoder_list,
@@ -988,20 +1089,27 @@ void drm_mode_config_cleanup(struct drm_device *dev)
drm_property_destroy(dev, property);
}
- list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) {
- fb->funcs->destroy(fb);
+ list_for_each_entry_safe(blob, bt, &dev->mode_config.property_blob_list,
+ head) {
+ drm_property_destroy_blob(dev, blob);
}
- list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) {
- crtc->funcs->destroy(crtc);
+ list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) {
+ drm_framebuffer_remove(fb);
}
list_for_each_entry_safe(plane, plt, &dev->mode_config.plane_list,
head) {
plane->funcs->destroy(plane);
}
+
+ list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) {
+ crtc->funcs->destroy(crtc);
+ }
+
drm_gem_names_fini(&dev->mode_config.crtc_names);
}
+EXPORT_SYMBOL(drm_mode_config_cleanup);
/**
* drm_crtc_convert_to_umode - convert a drm_display_mode into a modeinfo
@@ -1018,11 +1126,11 @@ static void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out,
const struct drm_display_mode *in)
{
if (in->hdisplay > USHRT_MAX || in->hsync_start > USHRT_MAX ||
- in->hsync_end > USHRT_MAX || in->htotal > USHRT_MAX ||
- in->hskew > USHRT_MAX || in->vdisplay > USHRT_MAX ||
- in->vsync_start > USHRT_MAX || in->vsync_end > USHRT_MAX ||
- in->vtotal > USHRT_MAX || in->vscan > USHRT_MAX)
- printf("timing values too large for mode info\n");
+ in->hsync_end > USHRT_MAX || in->htotal > USHRT_MAX ||
+ in->hskew > USHRT_MAX || in->vdisplay > USHRT_MAX ||
+ in->vsync_start > USHRT_MAX || in->vsync_end > USHRT_MAX ||
+ in->vtotal > USHRT_MAX || in->vscan > USHRT_MAX)
+ DRM_WARNING("timing values too large for mode info\n");
out->clock = in->clock;
out->hdisplay = in->hdisplay;
@@ -1060,7 +1168,7 @@ static int drm_crtc_convert_umode(struct drm_display_mode *out,
const struct drm_mode_modeinfo *in)
{
if (in->clock > INT_MAX || in->vrefresh > INT_MAX)
- return ERANGE;
+ return -ERANGE;
out->clock = in->clock;
out->hdisplay = in->hdisplay;
@@ -1122,7 +1230,7 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
struct drm_mode_group *mode_group;
if (!drm_core_check_feature(dev, DRIVER_MODESET))
- return (EINVAL);
+ return -EINVAL;
sx_xlock(&dev->mode_config.mutex);
@@ -1133,13 +1241,8 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
list_for_each(lh, &file_priv->fbs)
fb_count++;
-#if 1
- mode_group = NULL; /* XXXKIB */
- if (1 || file_priv->master) {
-#else
- mode_group = &file_priv->masterp->minor->mode_group;
- if (file_priv->masterp->minor->type == DRM_MINOR_CONTROL) {
-#endif
+ mode_group = &file_priv->master->minor->mode_group;
+ if (file_priv->master->minor->type == DRM_MINOR_CONTROL) {
list_for_each(lh, &dev->mode_config.crtc_list)
crtc_count++;
@@ -1165,11 +1268,10 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
/* FBs */
if (card_res->count_fbs >= fb_count) {
copied = 0;
- fb_id = (uint32_t *)(uintptr_t)card_res->fb_id_ptr;
+ fb_id = (uint32_t __user *)(unsigned long)card_res->fb_id_ptr;
list_for_each_entry(fb, &file_priv->fbs, filp_head) {
- if (copyout(&fb->base.id, fb_id + copied,
- sizeof(uint32_t))) {
- ret = EFAULT;
+ if (put_user(fb->base.id, fb_id + copied)) {
+ ret = -EFAULT;
goto out;
}
copied++;
@@ -1180,27 +1282,22 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
/* CRTCs */
if (card_res->count_crtcs >= crtc_count) {
copied = 0;
- crtc_id = (uint32_t *)(uintptr_t)card_res->crtc_id_ptr;
-#if 1
- if (1 || file_priv->master) {
-#else
- if (file_priv->masterp->minor->type == DRM_MINOR_CONTROL) {
-#endif
+ crtc_id = (uint32_t __user *)(unsigned long)card_res->crtc_id_ptr;
+ if (file_priv->master->minor->type == DRM_MINOR_CONTROL) {
list_for_each_entry(crtc, &dev->mode_config.crtc_list,
head) {
DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
- if (copyout(&crtc->base.id, crtc_id +
- copied, sizeof(uint32_t))) {
- ret = EFAULT;
+ if (put_user(crtc->base.id, crtc_id + copied)) {
+ ret = -EFAULT;
goto out;
}
copied++;
}
} else {
for (i = 0; i < mode_group->num_crtcs; i++) {
- if (copyout(&mode_group->id_list[i],
- crtc_id + copied, sizeof(uint32_t))) {
- ret = EFAULT;
+ if (put_user(mode_group->id_list[i],
+ crtc_id + copied)) {
+ ret = -EFAULT;
goto out;
}
copied++;
@@ -1212,31 +1309,25 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
/* Encoders */
if (card_res->count_encoders >= encoder_count) {
copied = 0;
- encoder_id = (uint32_t *)(uintptr_t)card_res->encoder_id_ptr;
-#if 1
- if (file_priv->master) {
-#else
- if (file_priv->masterp->minor->type == DRM_MINOR_CONTROL) {
-#endif
+ encoder_id = (uint32_t __user *)(unsigned long)card_res->encoder_id_ptr;
+ if (file_priv->master->minor->type == DRM_MINOR_CONTROL) {
list_for_each_entry(encoder,
&dev->mode_config.encoder_list,
head) {
DRM_DEBUG_KMS("[ENCODER:%d:%s]\n", encoder->base.id,
drm_get_encoder_name(encoder));
- if (copyout(&encoder->base.id, encoder_id +
- copied, sizeof(uint32_t))) {
- ret = EFAULT;
+ if (put_user(encoder->base.id, encoder_id +
+ copied)) {
+ ret = -EFAULT;
goto out;
}
copied++;
}
} else {
- for (i = mode_group->num_crtcs;
- i < mode_group->num_crtcs + mode_group->num_encoders;
- i++) {
- if (copyout(&mode_group->id_list[i],
- encoder_id + copied, sizeof(uint32_t))) {
- ret = EFAULT;
+ for (i = mode_group->num_crtcs; i < mode_group->num_crtcs + mode_group->num_encoders; i++) {
+ if (put_user(mode_group->id_list[i],
+ encoder_id + copied)) {
+ ret = -EFAULT;
goto out;
}
copied++;
@@ -1249,21 +1340,17 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
/* Connectors */
if (card_res->count_connectors >= connector_count) {
copied = 0;
- connector_id = (uint32_t *)(uintptr_t)card_res->connector_id_ptr;
-#if 1
- if (file_priv->master) {
-#else
- if (file_priv->masterp->minor->type == DRM_MINOR_CONTROL) {
-#endif
+ connector_id = (uint32_t __user *)(unsigned long)card_res->connector_id_ptr;
+ if (file_priv->master->minor->type == DRM_MINOR_CONTROL) {
list_for_each_entry(connector,
&dev->mode_config.connector_list,
head) {
DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
connector->base.id,
drm_get_connector_name(connector));
- if (copyout(&connector->base.id,
- connector_id + copied, sizeof(uint32_t))) {
- ret = EFAULT;
+ if (put_user(connector->base.id,
+ connector_id + copied)) {
+ ret = -EFAULT;
goto out;
}
copied++;
@@ -1272,9 +1359,9 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
int start = mode_group->num_crtcs +
mode_group->num_encoders;
for (i = start; i < start + mode_group->num_connectors; i++) {
- if (copyout(&mode_group->id_list[i],
- connector_id + copied, sizeof(uint32_t))) {
- ret = EFAULT;
+ if (put_user(mode_group->id_list[i],
+ connector_id + copied)) {
+ ret = -EFAULT;
goto out;
}
copied++;
@@ -1317,14 +1404,14 @@ int drm_mode_getcrtc(struct drm_device *dev,
int ret = 0;
if (!drm_core_check_feature(dev, DRIVER_MODESET))
- return (EINVAL);
+ return -EINVAL;
sx_xlock(&dev->mode_config.mutex);
obj = drm_mode_object_find(dev, crtc_resp->crtc_id,
DRM_MODE_OBJECT_CRTC);
if (!obj) {
- ret = (EINVAL);
+ ret = -EINVAL;
goto out;
}
crtc = obj_to_crtc(obj);
@@ -1383,12 +1470,12 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
int i;
struct drm_mode_modeinfo u_mode;
struct drm_mode_modeinfo __user *mode_ptr;
- uint32_t *prop_ptr;
- uint64_t *prop_values;
- uint32_t *encoder_ptr;
+ uint32_t __user *prop_ptr;
+ uint64_t __user *prop_values;
+ uint32_t __user *encoder_ptr;
if (!drm_core_check_feature(dev, DRIVER_MODESET))
- return (EINVAL);
+ return -EINVAL;
memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo));
@@ -1399,7 +1486,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
obj = drm_mode_object_find(dev, out_resp->connector_id,
DRM_MODE_OBJECT_CONNECTOR);
if (!obj) {
- ret = EINVAL;
+ ret = -EINVAL;
goto out;
}
connector = obj_to_connector(obj);
@@ -1440,12 +1527,12 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
*/
if ((out_resp->count_modes >= mode_count) && mode_count) {
copied = 0;
- mode_ptr = (struct drm_mode_modeinfo *)(uintptr_t)out_resp->modes_ptr;
+ mode_ptr = (struct drm_mode_modeinfo __user *)(unsigned long)out_resp->modes_ptr;
list_for_each_entry(mode, &connector->modes, head) {
drm_crtc_convert_to_umode(&u_mode, mode);
- if (copyout(&u_mode, mode_ptr + copied,
- sizeof(u_mode))) {
- ret = EFAULT;
+ if (copy_to_user(mode_ptr + copied,
+ &u_mode, sizeof(u_mode))) {
+ ret = -EFAULT;
goto out;
}
copied++;
@@ -1455,18 +1542,18 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
if ((out_resp->count_props >= props_count) && props_count) {
copied = 0;
- prop_ptr = (uint32_t *)(uintptr_t)(out_resp->props_ptr);
- prop_values = (uint64_t *)(uintptr_t)(out_resp->prop_values_ptr);
+ prop_ptr = (uint32_t __user *)(unsigned long)(out_resp->props_ptr);
+ prop_values = (uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr);
for (i = 0; i < connector->properties.count; i++) {
- if (copyout(&connector->properties.ids[i],
- prop_ptr + copied, sizeof(uint32_t))) {
- ret = EFAULT;
+ if (put_user(connector->properties.ids[i],
+ prop_ptr + copied)) {
+ ret = -EFAULT;
goto out;
}
- if (copyout(&connector->properties.values[i],
- prop_values + copied, sizeof(uint64_t))) {
- ret = EFAULT;
+ if (put_user(connector->properties.values[i],
+ prop_values + copied)) {
+ ret = -EFAULT;
goto out;
}
copied++;
@@ -1476,12 +1563,12 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
if ((out_resp->count_encoders >= encoders_count) && encoders_count) {
copied = 0;
- encoder_ptr = (uint32_t *)(uintptr_t)(out_resp->encoders_ptr);
+ encoder_ptr = (uint32_t __user *)(unsigned long)(out_resp->encoders_ptr);
for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
if (connector->encoder_ids[i] != 0) {
- if (copyout(&connector->encoder_ids[i],
- encoder_ptr + copied, sizeof(uint32_t))) {
- ret = EFAULT;
+ if (put_user(connector->encoder_ids[i],
+ encoder_ptr + copied)) {
+ ret = -EFAULT;
goto out;
}
copied++;
@@ -1504,13 +1591,13 @@ int drm_mode_getencoder(struct drm_device *dev, void *data,
int ret = 0;
if (!drm_core_check_feature(dev, DRIVER_MODESET))
- return (EINVAL);
+ return -EINVAL;
sx_xlock(&dev->mode_config.mutex);
obj = drm_mode_object_find(dev, enc_resp->encoder_id,
DRM_MODE_OBJECT_ENCODER);
if (!obj) {
- ret = EINVAL;
+ ret = -EINVAL;
goto out;
}
encoder = obj_to_encoder(obj);
@@ -1546,11 +1633,11 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data,
struct drm_mode_get_plane_res *plane_resp = data;
struct drm_mode_config *config;
struct drm_plane *plane;
- uint32_t *plane_ptr;
+ uint32_t __user *plane_ptr;
int copied = 0, ret = 0;
if (!drm_core_check_feature(dev, DRIVER_MODESET))
- return (EINVAL);
+ return -EINVAL;
sx_xlock(&dev->mode_config.mutex);
config = &dev->mode_config;
@@ -1561,12 +1648,11 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data,
*/
if (config->num_plane &&
(plane_resp->count_planes >= config->num_plane)) {
- plane_ptr = (uint32_t *)(unsigned long)plane_resp->plane_id_ptr;
+ plane_ptr = (uint32_t __user *)(unsigned long)plane_resp->plane_id_ptr;
list_for_each_entry(plane, &config->plane_list, head) {
- if (copyout(&plane->base.id, plane_ptr + copied,
- sizeof(uint32_t))) {
- ret = EFAULT;
+ if (put_user(plane->base.id, plane_ptr + copied)) {
+ ret = -EFAULT;
goto out;
}
copied++;
@@ -1597,17 +1683,17 @@ int drm_mode_getplane(struct drm_device *dev, void *data,
struct drm_mode_get_plane *plane_resp = data;
struct drm_mode_object *obj;
struct drm_plane *plane;
- uint32_t *format_ptr;
+ uint32_t __user *format_ptr;
int ret = 0;
if (!drm_core_check_feature(dev, DRIVER_MODESET))
- return (EINVAL);
+ return -EINVAL;
sx_xlock(&dev->mode_config.mutex);
obj = drm_mode_object_find(dev, plane_resp->plane_id,
DRM_MODE_OBJECT_PLANE);
if (!obj) {
- ret = ENOENT;
+ ret = -ENOENT;
goto out;
}
plane = obj_to_plane(obj);
@@ -1632,11 +1718,11 @@ int drm_mode_getplane(struct drm_device *dev, void *data,
*/
if (plane->format_count &&
(plane_resp->count_format_types >= plane->format_count)) {
- format_ptr = (uint32_t *)(unsigned long)plane_resp->format_type_ptr;
- if (copyout(format_ptr,
+ format_ptr = (uint32_t __user *)(unsigned long)plane_resp->format_type_ptr;
+ if (copy_to_user(format_ptr,
plane->format_types,
sizeof(uint32_t) * plane->format_count)) {
- ret = EFAULT;
+ ret = -EFAULT;
goto out;
}
}
@@ -1672,7 +1758,7 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
int i;
if (!drm_core_check_feature(dev, DRIVER_MODESET))
- return (EINVAL);
+ return -EINVAL;
sx_xlock(&dev->mode_config.mutex);
@@ -1685,7 +1771,7 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
if (!obj) {
DRM_DEBUG_KMS("Unknown plane ID %d\n",
plane_req->plane_id);
- ret = ENOENT;
+ ret = -ENOENT;
goto out;
}
plane = obj_to_plane(obj);
@@ -1703,7 +1789,7 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
if (!obj) {
DRM_DEBUG_KMS("Unknown crtc ID %d\n",
plane_req->crtc_id);
- ret = ENOENT;
+ ret = -ENOENT;
goto out;
}
crtc = obj_to_crtc(obj);
@@ -1713,7 +1799,7 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
if (!obj) {
DRM_DEBUG_KMS("Unknown framebuffer ID %d\n",
plane_req->fb_id);
- ret = ENOENT;
+ ret = -ENOENT;
goto out;
}
fb = obj_to_fb(obj);
@@ -1724,7 +1810,7 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
break;
if (i == plane->format_count) {
DRM_DEBUG_KMS("Invalid pixel format 0x%08x\n", fb->pixel_format);
- ret = EINVAL;
+ ret = -EINVAL;
goto out;
}
@@ -1746,7 +1832,7 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
((plane_req->src_x & 0xffff) * 15625) >> 10,
plane_req->src_y >> 16,
((plane_req->src_y & 0xffff) * 15625) >> 10);
- ret = ENOSPC;
+ ret = -ENOSPC;
goto out;
}
@@ -1758,11 +1844,11 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n",
plane_req->crtc_w, plane_req->crtc_h,
plane_req->crtc_x, plane_req->crtc_y);
- ret = ERANGE;
+ ret = -ERANGE;
goto out;
}
- ret = -plane->funcs->update_plane(plane, crtc, fb,
+ ret = plane->funcs->update_plane(plane, crtc, fb,
plane_req->crtc_x, plane_req->crtc_y,
plane_req->crtc_w, plane_req->crtc_h,
plane_req->src_x, plane_req->src_y,
@@ -1806,29 +1892,30 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
struct drm_framebuffer *fb = NULL;
struct drm_display_mode *mode = NULL;
struct drm_mode_set set;
- uint32_t *set_connectors_ptr;
+ uint32_t __user *set_connectors_ptr;
int ret;
int i;
if (!drm_core_check_feature(dev, DRIVER_MODESET))
- return (EINVAL);
+ return -EINVAL;
/* For some reason crtc x/y offsets are signed internally. */
if (crtc_req->x > INT_MAX || crtc_req->y > INT_MAX)
- return (ERANGE);
+ return -ERANGE;
sx_xlock(&dev->mode_config.mutex);
obj = drm_mode_object_find(dev, crtc_req->crtc_id,
DRM_MODE_OBJECT_CRTC);
if (!obj) {
DRM_DEBUG_KMS("Unknown CRTC ID %d\n", crtc_req->crtc_id);
- ret = EINVAL;
+ ret = -EINVAL;
goto out;
}
crtc = obj_to_crtc(obj);
DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
if (crtc_req->mode_valid) {
+ int hdisplay, vdisplay;
/* If we have a mode we need a framebuffer. */
/* If we pass -1, set the mode with the currently bound fb */
if (crtc_req->fb_id == -1) {
@@ -1844,7 +1931,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
if (!obj) {
DRM_DEBUG_KMS("Unknown FB ID%d\n",
crtc_req->fb_id);
- ret = EINVAL;
+ ret = -EINVAL;
goto out;
}
fb = obj_to_fb(obj);
@@ -1852,7 +1939,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
mode = drm_mode_create(dev);
if (!mode) {
- ret = ENOMEM;
+ ret = -ENOMEM;
goto out;
}
@@ -1864,29 +1951,39 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
- if (mode->hdisplay > fb->width ||
- mode->vdisplay > fb->height ||
- crtc_req->x > fb->width - mode->hdisplay ||
- crtc_req->y > fb->height - mode->vdisplay) {
- DRM_DEBUG_KMS("Invalid CRTC viewport %ux%u+%u+%u for fb size %ux%u.\n",
- mode->hdisplay, mode->vdisplay,
- crtc_req->x, crtc_req->y,
- fb->width, fb->height);
- ret = ENOSPC;
+ hdisplay = mode->hdisplay;
+ vdisplay = mode->vdisplay;
+
+ if (crtc->invert_dimensions) {
+ int tmp;
+ tmp = vdisplay;
+ vdisplay = hdisplay;
+ hdisplay = tmp;
+ }
+
+ if (hdisplay > fb->width ||
+ vdisplay > fb->height ||
+ crtc_req->x > fb->width - hdisplay ||
+ crtc_req->y > fb->height - vdisplay) {
+ DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d%s.\n",
+ fb->width, fb->height,
+ hdisplay, vdisplay, crtc_req->x, crtc_req->y,
+ crtc->invert_dimensions ? " (inverted)" : "");
+ ret = -ENOSPC;
goto out;
}
}
if (crtc_req->count_connectors == 0 && mode) {
DRM_DEBUG_KMS("Count connectors is 0 but mode set\n");
- ret = EINVAL;
+ ret = -EINVAL;
goto out;
}
if (crtc_req->count_connectors > 0 && (!mode || !fb)) {
DRM_DEBUG_KMS("Count connectors is %d but no mode or fb set\n",
crtc_req->count_connectors);
- ret = EINVAL;
+ ret = -EINVAL;
goto out;
}
@@ -1895,17 +1992,22 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
/* Avoid unbounded kernel memory allocation */
if (crtc_req->count_connectors > config->num_connector) {
- ret = EINVAL;
+ ret = -EINVAL;
goto out;
}
connector_set = malloc(crtc_req->count_connectors *
- sizeof(struct drm_connector *), DRM_MEM_KMS, M_WAITOK);
+ sizeof(struct drm_connector *),
+ DRM_MEM_KMS, M_WAITOK);
+ if (!connector_set) {
+ ret = -ENOMEM;
+ goto out;
+ }
for (i = 0; i < crtc_req->count_connectors; i++) {
- set_connectors_ptr = (uint32_t *)(uintptr_t)crtc_req->set_connectors_ptr;
- if (copyin(&set_connectors_ptr[i], &out_id, sizeof(uint32_t))) {
- ret = EFAULT;
+ set_connectors_ptr = (uint32_t __user *)(unsigned long)crtc_req->set_connectors_ptr;
+ if (get_user(out_id, &set_connectors_ptr[i])) {
+ ret = -EFAULT;
goto out;
}
@@ -1914,7 +2016,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
if (!obj) {
DRM_DEBUG_KMS("Connector id %d unknown\n",
out_id);
- ret = EINVAL;
+ ret = -EINVAL;
goto out;
}
connector = obj_to_connector(obj);
@@ -1951,27 +2053,27 @@ int drm_mode_cursor_ioctl(struct drm_device *dev,
int ret = 0;
if (!drm_core_check_feature(dev, DRIVER_MODESET))
- return (EINVAL);
+ return -EINVAL;
- if (!req->flags)
- return (EINVAL);
+ if (!req->flags || (~DRM_MODE_CURSOR_FLAGS & req->flags))
+ return -EINVAL;
sx_xlock(&dev->mode_config.mutex);
obj = drm_mode_object_find(dev, req->crtc_id, DRM_MODE_OBJECT_CRTC);
if (!obj) {
DRM_DEBUG_KMS("Unknown CRTC ID %d\n", req->crtc_id);
- ret = EINVAL;
+ ret = -EINVAL;
goto out;
}
crtc = obj_to_crtc(obj);
if (req->flags & DRM_MODE_CURSOR_BO) {
if (!crtc->funcs->cursor_set) {
- ret = ENXIO;
+ ret = -ENXIO;
goto out;
}
/* Turns off the cursor if handle is 0 */
- ret = -crtc->funcs->cursor_set(crtc, file_priv, req->handle,
+ ret = crtc->funcs->cursor_set(crtc, file_priv, req->handle,
req->width, req->height);
}
@@ -1979,7 +2081,7 @@ int drm_mode_cursor_ioctl(struct drm_device *dev,
if (crtc->funcs->cursor_move) {
ret = crtc->funcs->cursor_move(crtc, req->x, req->y);
} else {
- ret = EFAULT;
+ ret = -EFAULT;
goto out;
}
}
@@ -1995,7 +2097,7 @@ uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth)
switch (bpp) {
case 8:
- fmt = DRM_FORMAT_RGB332;
+ fmt = DRM_FORMAT_C8;
break;
case 16:
if (depth == 15)
@@ -2015,13 +2117,14 @@ uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth)
fmt = DRM_FORMAT_ARGB8888;
break;
default:
- DRM_ERROR("bad bpp, assuming RGB24 pixel format\n");
+ DRM_ERROR("bad bpp, assuming x8r8g8b8 pixel format\n");
fmt = DRM_FORMAT_XRGB8888;
break;
}
return fmt;
}
+EXPORT_SYMBOL(drm_mode_legacy_fb_format);
/**
* drm_mode_addfb - add an FB to the graphics configuration
@@ -2058,18 +2161,22 @@ int drm_mode_addfb(struct drm_device *dev,
r.handles[0] = or->handle;
if (!drm_core_check_feature(dev, DRIVER_MODESET))
- return (EINVAL);
+ return -EINVAL;
if ((config->min_width > r.width) || (r.width > config->max_width))
- return (EINVAL);
+ return -EINVAL;
+
if ((config->min_height > r.height) || (r.height > config->max_height))
- return (EINVAL);
+ return -EINVAL;
sx_xlock(&dev->mode_config.mutex);
- ret = -dev->mode_config.funcs->fb_create(dev, file_priv, &r, &fb);
+ /* TODO check buffer is sufficiently large */
+ /* TODO setup destructor callback */
+
+ ret = dev->mode_config.funcs->fb_create(dev, file_priv, &r, &fb);
if (ret != 0) {
- DRM_DEBUG_KMS("could not create framebuffer, error %d\n", ret);
+ DRM_DEBUG_KMS("could not create framebuffer\n");
goto out;
}
@@ -2082,7 +2189,7 @@ out:
return ret;
}
-static int format_check(struct drm_mode_fb_cmd2 *r)
+static int format_check(const struct drm_mode_fb_cmd2 *r)
{
uint32_t format = r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN;
@@ -2135,6 +2242,8 @@ static int format_check(struct drm_mode_fb_cmd2 *r)
case DRM_FORMAT_NV21:
case DRM_FORMAT_NV16:
case DRM_FORMAT_NV61:
+ case DRM_FORMAT_NV24:
+ case DRM_FORMAT_NV42:
case DRM_FORMAT_YUV410:
case DRM_FORMAT_YVU410:
case DRM_FORMAT_YUV411:
@@ -2147,11 +2256,11 @@ static int format_check(struct drm_mode_fb_cmd2 *r)
case DRM_FORMAT_YVU444:
return 0;
default:
- return (EINVAL);
+ return -EINVAL;
}
}
-static int framebuffer_check(struct drm_mode_fb_cmd2 *r)
+static int framebuffer_check(const struct drm_mode_fb_cmd2 *r)
{
int ret, hsub, vsub, num_planes, i;
@@ -2177,13 +2286,21 @@ static int framebuffer_check(struct drm_mode_fb_cmd2 *r)
for (i = 0; i < num_planes; i++) {
unsigned int width = r->width / (i != 0 ? hsub : 1);
+ unsigned int height = r->height / (i != 0 ? vsub : 1);
+ unsigned int cpp = drm_format_plane_cpp(r->pixel_format, i);
if (!r->handles[i]) {
DRM_DEBUG_KMS("no buffer object handle for plane %d\n", i);
return -EINVAL;
}
- if (r->pitches[i] < drm_format_plane_cpp(r->pixel_format, i) * width) {
+ if ((uint64_t) width * cpp > UINT_MAX)
+ return -ERANGE;
+
+ if ((uint64_t) height * r->pitches[i] + r->offsets[i] > UINT_MAX)
+ return -ERANGE;
+
+ if (r->pitches[i] < width * cpp) {
DRM_DEBUG_KMS("bad pitch %u for plane %d\n", r->pitches[i], i);
return -EINVAL;
}
@@ -2215,34 +2332,36 @@ int drm_mode_addfb2(struct drm_device *dev,
struct drm_mode_fb_cmd2 *r = data;
struct drm_mode_config *config = &dev->mode_config;
struct drm_framebuffer *fb;
- int ret = 0;
+ int ret;
if (!drm_core_check_feature(dev, DRIVER_MODESET))
- return (EINVAL);
+ return -EINVAL;
+
+ if (r->flags & ~DRM_MODE_FB_INTERLACED) {
+ DRM_DEBUG_KMS("bad framebuffer flags 0x%08x\n", r->flags);
+ return -EINVAL;
+ }
if ((config->min_width > r->width) || (r->width > config->max_width)) {
DRM_DEBUG_KMS("bad framebuffer width %d, should be >= %d && <= %d\n",
r->width, config->min_width, config->max_width);
- return (EINVAL);
+ return -EINVAL;
}
if ((config->min_height > r->height) || (r->height > config->max_height)) {
DRM_DEBUG_KMS("bad framebuffer height %d, should be >= %d && <= %d\n",
r->height, config->min_height, config->max_height);
- return (EINVAL);
+ return -EINVAL;
}
ret = framebuffer_check(r);
if (ret)
- return -ret;
+ return ret;
sx_xlock(&dev->mode_config.mutex);
- /* TODO check buffer is sufficiently large */
- /* TODO setup destructor callback */
-
- ret = -dev->mode_config.funcs->fb_create(dev, file_priv, r, &fb);
+ ret = dev->mode_config.funcs->fb_create(dev, file_priv, r, &fb);
if (ret != 0) {
- DRM_DEBUG_KMS("could not create framebuffer, error %d\n", ret);
+ DRM_DEBUG_KMS("could not create framebuffer\n");
goto out;
}
@@ -2252,7 +2371,7 @@ int drm_mode_addfb2(struct drm_device *dev,
out:
sx_xunlock(&dev->mode_config.mutex);
- return (ret);
+ return ret;
}
/**
@@ -2283,13 +2402,13 @@ int drm_mode_rmfb(struct drm_device *dev,
int found = 0;
if (!drm_core_check_feature(dev, DRIVER_MODESET))
- return (EINVAL);
+ return -EINVAL;
sx_xlock(&dev->mode_config.mutex);
obj = drm_mode_object_find(dev, *id, DRM_MODE_OBJECT_FB);
/* TODO check that we really get a framebuffer back. */
if (!obj) {
- ret = EINVAL;
+ ret = -EINVAL;
goto out;
}
fb = obj_to_fb(obj);
@@ -2299,15 +2418,11 @@ int drm_mode_rmfb(struct drm_device *dev,
found = 1;
if (!found) {
- ret = EINVAL;
+ ret = -EINVAL;
goto out;
}
- /* TODO release all crtc connected to the framebuffer */
- /* TODO unhock the destructor from the buffer object */
-
- list_del(&fb->filp_head);
- fb->funcs->destroy(fb);
+ drm_framebuffer_remove(fb);
out:
sx_xunlock(&dev->mode_config.mutex);
@@ -2340,12 +2455,12 @@ int drm_mode_getfb(struct drm_device *dev,
int ret = 0;
if (!drm_core_check_feature(dev, DRIVER_MODESET))
- return (EINVAL);
+ return -EINVAL;
sx_xlock(&dev->mode_config.mutex);
obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB);
if (!obj) {
- ret = EINVAL;
+ ret = -EINVAL;
goto out;
}
fb = obj_to_fb(obj);
@@ -2376,21 +2491,21 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
int ret;
if (!drm_core_check_feature(dev, DRIVER_MODESET))
- return (EINVAL);
+ return -EINVAL;
sx_xlock(&dev->mode_config.mutex);
obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB);
if (!obj) {
- ret = EINVAL;
+ ret = -EINVAL;
goto out_err1;
}
fb = obj_to_fb(obj);
num_clips = r->num_clips;
- clips_ptr = (struct drm_clip_rect *)(unsigned long)r->clips_ptr;
+ clips_ptr = (struct drm_clip_rect __user *)(unsigned long)r->clips_ptr;
if (!num_clips != !clips_ptr) {
- ret = EINVAL;
+ ret = -EINVAL;
goto out_err1;
}
@@ -2398,28 +2513,35 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
/* If userspace annotates copy, clips must come in pairs */
if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY && (num_clips % 2)) {
- ret = EINVAL;
+ ret = -EINVAL;
goto out_err1;
}
if (num_clips && clips_ptr) {
if (num_clips < 0 || num_clips > DRM_MODE_FB_DIRTY_MAX_CLIPS) {
- ret = EINVAL;
+ ret = -EINVAL;
goto out_err1;
}
clips = malloc(num_clips * sizeof(*clips), DRM_MEM_KMS,
M_WAITOK | M_ZERO);
+ if (!clips) {
+ ret = -ENOMEM;
+ goto out_err1;
+ }
- ret = copyin(clips_ptr, clips, num_clips * sizeof(*clips));
- if (ret)
+ ret = copy_from_user(clips, clips_ptr,
+ num_clips * sizeof(*clips));
+ if (ret) {
+ ret = -EFAULT;
goto out_err2;
+ }
}
if (fb->funcs->dirty) {
- ret = -fb->funcs->dirty(fb, file_priv, flags, r->color,
+ ret = fb->funcs->dirty(fb, file_priv, flags, r->color,
clips, num_clips);
} else {
- ret = ENOSYS;
+ ret = -ENOSYS;
goto out_err2;
}
@@ -2447,17 +2569,12 @@ out_err1:
*/
void drm_fb_release(struct drm_file *priv)
{
-#if 1
- struct drm_device *dev = priv->dev;
-#else
struct drm_device *dev = priv->minor->dev;
-#endif
struct drm_framebuffer *fb, *tfb;
sx_xlock(&dev->mode_config.mutex);
list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) {
- list_del(&fb->filp_head);
- fb->funcs->destroy(fb);
+ drm_framebuffer_remove(fb);
}
sx_xunlock(&dev->mode_config.mutex);
}
@@ -2491,7 +2608,7 @@ int drm_mode_attachmode_crtc(struct drm_device *dev, struct drm_crtc *crtc,
if (connector->encoder->crtc == crtc) {
dup_mode = drm_mode_duplicate(dev, mode);
if (!dup_mode) {
- ret = ENOMEM;
+ ret = -ENOMEM;
goto out;
}
list_add_tail(&dup_mode->head, &list);
@@ -2513,6 +2630,7 @@ int drm_mode_attachmode_crtc(struct drm_device *dev, struct drm_crtc *crtc,
return ret;
}
+EXPORT_SYMBOL(drm_mode_attachmode_crtc);
static int drm_mode_detachmode(struct drm_device *dev,
struct drm_connector *connector,
@@ -2546,6 +2664,7 @@ int drm_mode_detachmode_crtc(struct drm_device *dev, struct drm_display_mode *mo
}
return 0;
}
+EXPORT_SYMBOL(drm_mode_detachmode_crtc);
/**
* drm_fb_attachmode - Attach a user mode to an connector
@@ -2656,15 +2775,20 @@ struct drm_property *drm_property_create(struct drm_device *dev, int flags,
property = malloc(sizeof(struct drm_property), DRM_MEM_KMS,
M_WAITOK | M_ZERO);
+ if (!property)
+ return NULL;
if (num_values) {
property->values = malloc(sizeof(uint64_t)*num_values, DRM_MEM_KMS,
M_WAITOK | M_ZERO);
+ if (!property->values)
+ goto fail;
}
ret = drm_mode_object_get(dev, &property->base, DRM_MODE_OBJECT_PROPERTY);
if (ret)
goto fail;
+
property->flags = flags;
property->num_values = num_values;
INIT_LIST_HEAD(&property->enum_blob_list);
@@ -2676,12 +2800,12 @@ struct drm_property *drm_property_create(struct drm_device *dev, int flags,
list_add_tail(&property->head, &dev->mode_config.property_list);
return property;
-
fail:
free(property->values, DRM_MEM_KMS);
free(property, DRM_MEM_KMS);
- return (NULL);
+ return NULL;
}
+EXPORT_SYMBOL(drm_property_create);
struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags,
const char *name,
@@ -2709,6 +2833,7 @@ struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags,
return property;
}
+EXPORT_SYMBOL(drm_property_create_enum);
struct drm_property *drm_property_create_bitmask(struct drm_device *dev,
int flags, const char *name,
@@ -2736,6 +2861,7 @@ struct drm_property *drm_property_create_bitmask(struct drm_device *dev,
return property;
}
+EXPORT_SYMBOL(drm_property_create_bitmask);
struct drm_property *drm_property_create_range(struct drm_device *dev, int flags,
const char *name,
@@ -2754,6 +2880,7 @@ struct drm_property *drm_property_create_range(struct drm_device *dev, int flags
return property;
}
+EXPORT_SYMBOL(drm_property_create_range);
int drm_property_add_enum(struct drm_property *property, int index,
uint64_t value, const char *name)
@@ -2782,6 +2909,8 @@ int drm_property_add_enum(struct drm_property *property, int index,
prop_enum = malloc(sizeof(struct drm_property_enum), DRM_MEM_KMS,
M_WAITOK | M_ZERO);
+ if (!prop_enum)
+ return -ENOMEM;
strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN);
prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0';
@@ -2791,6 +2920,7 @@ int drm_property_add_enum(struct drm_property *property, int index,
list_add_tail(&prop_enum->head, &property->enum_blob_list);
return 0;
}
+EXPORT_SYMBOL(drm_property_add_enum);
void drm_property_destroy(struct drm_device *dev, struct drm_property *property)
{
@@ -2807,24 +2937,7 @@ void drm_property_destroy(struct drm_device *dev, struct drm_property *property)
list_del(&property->head);
free(property, DRM_MEM_KMS);
}
-
-void drm_connector_attach_property(struct drm_connector *connector,
- struct drm_property *property, uint64_t init_val)
-{
- drm_object_attach_property(&connector->base, property, init_val);
-}
-
-int drm_connector_property_set_value(struct drm_connector *connector,
- struct drm_property *property, uint64_t value)
-{
- return drm_object_property_set_value(&connector->base, property, value);
-}
-
-int drm_connector_property_get_value(struct drm_connector *connector,
- struct drm_property *property, uint64_t *val)
-{
- return drm_object_property_get_value(&connector->base, property, val);
-}
+EXPORT_SYMBOL(drm_property_destroy);
void drm_object_attach_property(struct drm_mode_object *obj,
struct drm_property *property,
@@ -2833,17 +2946,18 @@ void drm_object_attach_property(struct drm_mode_object *obj,
int count = obj->properties->count;
if (count == DRM_OBJECT_MAX_PROPERTY) {
- printf("Failed to attach object property (type: 0x%x). Please "
+ DRM_WARNING("Failed to attach object property (type: 0x%x). Please "
"increase DRM_OBJECT_MAX_PROPERTY by 1 for each time "
"you see this message on the same object type.\n",
obj->type);
return;
- }
+ }
obj->properties->ids[count] = property->base.id;
obj->properties->values[count] = init_val;
obj->properties->count++;
}
+EXPORT_SYMBOL(drm_object_attach_property);
int drm_object_property_set_value(struct drm_mode_object *obj,
struct drm_property *property, uint64_t val)
@@ -2859,6 +2973,7 @@ int drm_object_property_set_value(struct drm_mode_object *obj,
return -EINVAL;
}
+EXPORT_SYMBOL(drm_object_property_set_value);
int drm_object_property_get_value(struct drm_mode_object *obj,
struct drm_property *property, uint64_t *val)
@@ -2874,6 +2989,7 @@ int drm_object_property_get_value(struct drm_mode_object *obj,
return -EINVAL;
}
+EXPORT_SYMBOL(drm_object_property_get_value);
int drm_mode_getproperty_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv)
@@ -2889,9 +3005,9 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev,
struct drm_property_enum *prop_enum;
struct drm_mode_property_enum __user *enum_ptr;
struct drm_property_blob *prop_blob;
- uint32_t *blob_id_ptr;
- uint64_t *values_ptr;
- uint32_t *blob_length_ptr;
+ uint32_t __user *blob_id_ptr;
+ uint64_t __user *values_ptr;
+ uint32_t __user *blob_length_ptr;
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EINVAL;
@@ -2919,9 +3035,9 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev,
out_resp->flags = property->flags;
if ((out_resp->count_values >= value_count) && value_count) {
- values_ptr = (uint64_t *)(uintptr_t)out_resp->values_ptr;
+ values_ptr = (uint64_t __user *)(unsigned long)out_resp->values_ptr;
for (i = 0; i < value_count; i++) {
- if (copyout(&property->values[i], values_ptr + i, sizeof(uint64_t))) {
+ if (copy_to_user(values_ptr + i, &property->values[i], sizeof(uint64_t))) {
ret = -EFAULT;
goto done;
}
@@ -2932,16 +3048,16 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev,
if (property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)) {
if ((out_resp->count_enum_blobs >= enum_count) && enum_count) {
copied = 0;
- enum_ptr = (struct drm_mode_property_enum *)(uintptr_t)out_resp->enum_blob_ptr;
+ enum_ptr = (struct drm_mode_property_enum __user *)(unsigned long)out_resp->enum_blob_ptr;
list_for_each_entry(prop_enum, &property->enum_blob_list, head) {
- if (copyout(&prop_enum->value, &enum_ptr[copied].value, sizeof(uint64_t))) {
+ if (copy_to_user(&enum_ptr[copied].value, &prop_enum->value, sizeof(uint64_t))) {
ret = -EFAULT;
goto done;
}
- if (copyout(&prop_enum->name,
- &enum_ptr[copied].name,DRM_PROP_NAME_LEN)) {
+ if (copy_to_user(&enum_ptr[copied].name,
+ &prop_enum->name, DRM_PROP_NAME_LEN)) {
ret = -EFAULT;
goto done;
}
@@ -2954,18 +3070,16 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev,
if (property->flags & DRM_MODE_PROP_BLOB) {
if ((out_resp->count_enum_blobs >= blob_count) && blob_count) {
copied = 0;
- blob_id_ptr = (uint32_t *)(uintptr_t)out_resp->enum_blob_ptr;
- blob_length_ptr = (uint32_t *)(uintptr_t)out_resp->values_ptr;
+ blob_id_ptr = (uint32_t __user *)(unsigned long)out_resp->enum_blob_ptr;
+ blob_length_ptr = (uint32_t __user *)(unsigned long)out_resp->values_ptr;
list_for_each_entry(prop_blob, &property->enum_blob_list, head) {
- if (copyout(&prop_blob->base.id,
- blob_id_ptr + copied, sizeof(uint32_t))) {
+ if (put_user(prop_blob->base.id, blob_id_ptr + copied)) {
ret = -EFAULT;
goto done;
}
- if (copyout(&prop_blob->length,
- blob_length_ptr + copied, sizeof(uint32_t))) {
+ if (put_user(prop_blob->length, blob_length_ptr + copied)) {
ret = -EFAULT;
goto done;
}
@@ -2989,13 +3103,15 @@ static struct drm_property_blob *drm_property_create_blob(struct drm_device *dev
if (!length || !data)
return NULL;
- blob = malloc(sizeof(struct drm_property_blob) + length, DRM_MEM_KMS,
+ blob = malloc(sizeof(struct drm_property_blob)+length, DRM_MEM_KMS,
M_WAITOK | M_ZERO);
+ if (!blob)
+ return NULL;
ret = drm_mode_object_get(dev, &blob->base, DRM_MODE_OBJECT_BLOB);
if (ret) {
free(blob, DRM_MEM_KMS);
- return (NULL);
+ return NULL;
}
blob->length = length;
@@ -3021,7 +3137,7 @@ int drm_mode_getblob_ioctl(struct drm_device *dev,
struct drm_mode_get_blob *out_resp = data;
struct drm_property_blob *blob;
int ret = 0;
- void *blob_ptr;
+ void __user *blob_ptr;
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EINVAL;
@@ -3035,8 +3151,8 @@ int drm_mode_getblob_ioctl(struct drm_device *dev,
blob = obj_to_blob(obj);
if (out_resp->length == blob->length) {
- blob_ptr = (void *)(unsigned long)out_resp->data;
- if (copyout(blob->data, blob_ptr, blob->length)){
+ blob_ptr = (void __user *)(unsigned long)out_resp->data;
+ if (copy_to_user(blob_ptr, blob->data, blob->length)){
ret = -EFAULT;
goto done;
}
@@ -3060,23 +3176,26 @@ int drm_mode_connector_update_edid_property(struct drm_connector *connector,
/* Delete edid, when there is none. */
if (!edid) {
connector->edid_blob_ptr = NULL;
- ret = drm_connector_property_set_value(connector, dev->mode_config.edid_property, 0);
+ ret = drm_object_property_set_value(&connector->base, dev->mode_config.edid_property, 0);
return ret;
}
size = EDID_LENGTH * (1 + edid->extensions);
connector->edid_blob_ptr = drm_property_create_blob(connector->dev,
size, edid);
+ if (!connector->edid_blob_ptr)
+ return -EINVAL;
- ret = drm_connector_property_set_value(connector,
+ ret = drm_object_property_set_value(&connector->base,
dev->mode_config.edid_property,
connector->edid_blob_ptr->base.id);
return ret;
}
+EXPORT_SYMBOL(drm_mode_connector_update_edid_property);
static bool drm_property_change_is_valid(struct drm_property *property,
- u64 value)
+ uint64_t value)
{
if (property->flags & DRM_MODE_PROP_IMMUTABLE)
return false;
@@ -3086,10 +3205,13 @@ static bool drm_property_change_is_valid(struct drm_property *property,
return true;
} else if (property->flags & DRM_MODE_PROP_BITMASK) {
int i;
- u64 valid_mask = 0;
+ uint64_t valid_mask = 0;
for (i = 0; i < property->num_values; i++)
valid_mask |= (1ULL << property->values[i]);
return !(value & ~valid_mask);
+ } else if (property->flags & DRM_MODE_PROP_BLOB) {
+ /* Only the driver knows */
+ return true;
} else {
int i;
for (i = 0; i < property->num_values; i++)
@@ -3131,7 +3253,7 @@ static int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj,
/* store the property value if successful */
if (!ret)
- drm_connector_property_set_value(connector, property, value);
+ drm_object_property_set_value(&connector->base, property, value);
return ret;
}
@@ -3202,13 +3324,13 @@ int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data,
prop_values_ptr = (uint64_t __user *)(unsigned long)
(arg->prop_values_ptr);
for (i = 0; i < props_count; i++) {
- if (copyout(props_ptr + copied,
- &obj->properties->ids[i], sizeof(uint32_t))) {
+ if (put_user(obj->properties->ids[i],
+ props_ptr + copied)) {
ret = -EFAULT;
goto out;
}
- if (copyout(prop_values_ptr + copied,
- &obj->properties->values[i], sizeof(uint64_t))) {
+ if (put_user(obj->properties->values[i],
+ prop_values_ptr + copied)) {
ret = -EFAULT;
goto out;
}
@@ -3289,6 +3411,7 @@ int drm_mode_connector_attach_encoder(struct drm_connector *connector,
}
return -ENOMEM;
}
+EXPORT_SYMBOL(drm_mode_connector_attach_encoder);
void drm_mode_connector_detach_encoder(struct drm_connector *connector,
struct drm_encoder *encoder)
@@ -3303,6 +3426,7 @@ void drm_mode_connector_detach_encoder(struct drm_connector *connector,
}
}
}
+EXPORT_SYMBOL(drm_mode_connector_detach_encoder);
int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc,
int gamma_size)
@@ -3311,9 +3435,14 @@ int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc,
crtc->gamma_store = malloc(gamma_size * sizeof(uint16_t) * 3,
DRM_MEM_KMS, M_WAITOK | M_ZERO);
+ if (!crtc->gamma_store) {
+ crtc->gamma_size = 0;
+ return -ENOMEM;
+ }
return 0;
}
+EXPORT_SYMBOL(drm_mode_crtc_set_gamma_size);
int drm_mode_gamma_set_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv)
@@ -3336,6 +3465,11 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev,
}
crtc = obj_to_crtc(obj);
+ if (crtc->funcs->gamma_set == NULL) {
+ ret = -ENOSYS;
+ goto out;
+ }
+
/* memcpy into gamma store */
if (crtc_lut->gamma_size != crtc->gamma_size) {
ret = -EINVAL;
@@ -3344,19 +3478,19 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev,
size = crtc_lut->gamma_size * (sizeof(uint16_t));
r_base = crtc->gamma_store;
- if (copyin((void *)(uintptr_t)crtc_lut->red, r_base, size)) {
+ if (copy_from_user(r_base, (void __user *)(unsigned long)crtc_lut->red, size)) {
ret = -EFAULT;
goto out;
}
g_base = (char *)r_base + size;
- if (copyin((void *)(uintptr_t)crtc_lut->green, g_base, size)) {
+ if (copy_from_user(g_base, (void __user *)(unsigned long)crtc_lut->green, size)) {
ret = -EFAULT;
goto out;
}
b_base = (char *)g_base + size;
- if (copyin((void *)(uintptr_t)crtc_lut->blue, b_base, size)) {
+ if (copy_from_user(b_base, (void __user *)(unsigned long)crtc_lut->blue, size)) {
ret = -EFAULT;
goto out;
}
@@ -3390,11 +3524,6 @@ int drm_mode_gamma_get_ioctl(struct drm_device *dev,
}
crtc = obj_to_crtc(obj);
- if (crtc->funcs->gamma_set == NULL) {
- ret = -ENOSYS;
- goto out;
- }
-
/* memcpy into gamma store */
if (crtc_lut->gamma_size != crtc->gamma_size) {
ret = -EINVAL;
@@ -3403,19 +3532,19 @@ int drm_mode_gamma_get_ioctl(struct drm_device *dev,
size = crtc_lut->gamma_size * (sizeof(uint16_t));
r_base = crtc->gamma_store;
- if (copyout(r_base, (void *)(uintptr_t)crtc_lut->red, size)) {
+ if (copy_to_user((void __user *)(unsigned long)crtc_lut->red, r_base, size)) {
ret = -EFAULT;
goto out;
}
g_base = (char *)r_base + size;
- if (copyout(g_base, (void *)(uintptr_t)crtc_lut->green, size)) {
+ if (copy_to_user((void __user *)(unsigned long)crtc_lut->green, g_base, size)) {
ret = -EFAULT;
goto out;
}
b_base = (char *)g_base + size;
- if (copyout(b_base, (void *)(uintptr_t)crtc_lut->blue, size)) {
+ if (copy_to_user((void __user *)(unsigned long)crtc_lut->blue, b_base, size)) {
ret = -EFAULT;
goto out;
}
@@ -3425,25 +3554,29 @@ out:
}
static void
-drm_kms_free(void *arg)
+free_vblank_event(void *arg)
{
free(arg, DRM_MEM_KMS);
}
-int drm_mode_page_flip_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
+int drm_mode_page_flip_ioctl(struct drm_device *dev,
+ void *data, struct drm_file *file_priv)
{
struct drm_mode_crtc_page_flip *page_flip = data;
struct drm_mode_object *obj;
struct drm_crtc *crtc;
struct drm_framebuffer *fb;
struct drm_pending_vblank_event *e = NULL;
- int ret = EINVAL;
+#ifdef __linux__
+ unsigned long flags;
+#endif
+ int hdisplay, vdisplay;
+ int ret = -EINVAL;
if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS ||
page_flip->reserved != 0)
- return (EINVAL);
+ return -EINVAL;
sx_xlock(&dev->mode_config.mutex);
obj = drm_mode_object_find(dev, page_flip->crtc_id, DRM_MODE_OBJECT_CRTC);
@@ -3456,7 +3589,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, void *data,
* due to a hotplug event, that userspace has not
* yet discovered.
*/
- ret = EBUSY;
+ ret = -EBUSY;
goto out;
}
@@ -3468,20 +3601,29 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, void *data,
goto out;
fb = obj_to_fb(obj);
- if (crtc->mode.hdisplay > fb->width ||
- crtc->mode.vdisplay > fb->height ||
- crtc->x > fb->width - crtc->mode.hdisplay ||
- crtc->y > fb->height - crtc->mode.vdisplay) {
- DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d.\n",
- fb->width, fb->height,
- crtc->mode.hdisplay, crtc->mode.vdisplay,
- crtc->x, crtc->y);
- ret = ENOSPC;
+ hdisplay = crtc->mode.hdisplay;
+ vdisplay = crtc->mode.vdisplay;
+
+ if (crtc->invert_dimensions) {
+ int tmp;
+ tmp = vdisplay;
+ vdisplay = hdisplay;
+ hdisplay = tmp;
+ }
+
+ if (hdisplay > fb->width ||
+ vdisplay > fb->height ||
+ crtc->x > fb->width - hdisplay ||
+ crtc->y > fb->height - vdisplay) {
+ DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d%s.\n",
+ fb->width, fb->height, hdisplay, vdisplay, crtc->x, crtc->y,
+ crtc->invert_dimensions ? " (inverted)" : "");
+ ret = -ENOSPC;
goto out;
}
if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
- ret = ENOMEM;
+ ret = -ENOMEM;
mtx_lock(&dev->event_lock);
if (file_priv->event_space < sizeof e->event) {
mtx_unlock(&dev->event_lock);
@@ -3491,6 +3633,12 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, void *data,
mtx_unlock(&dev->event_lock);
e = malloc(sizeof *e, DRM_MEM_KMS, M_WAITOK | M_ZERO);
+ if (e == NULL) {
+ mtx_lock(&dev->event_lock);
+ file_priv->event_space += sizeof e->event;
+ mtx_unlock(&dev->event_lock);
+ goto out;
+ }
e->event.base.type = DRM_EVENT_FLIP_COMPLETE;
e->event.base.length = sizeof e->event;
@@ -3498,11 +3646,11 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, void *data,
e->base.event = &e->event.base;
e->base.file_priv = file_priv;
e->base.destroy =
- (void (*) (struct drm_pending_event *))drm_kms_free;
+ (void (*) (struct drm_pending_event *)) free_vblank_event;
}
- ret = -crtc->funcs->page_flip(crtc, fb, e);
- if (ret != 0) {
+ ret = crtc->funcs->page_flip(crtc, fb, e);
+ if (ret) {
if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
mtx_lock(&dev->event_lock);
file_priv->event_space += sizeof e->event;
@@ -3513,9 +3661,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, void *data,
out:
sx_xunlock(&dev->mode_config.mutex);
- CTR3(KTR_DRM, "page_flip_ioctl %d %d %d", curproc->p_pid,
- page_flip->crtc_id, ret);
- return (ret);
+ return ret;
}
void drm_mode_config_reset(struct drm_device *dev)
@@ -3532,10 +3678,14 @@ void drm_mode_config_reset(struct drm_device *dev)
if (encoder->funcs->reset)
encoder->funcs->reset(encoder);
- list_for_each_entry(connector, &dev->mode_config.connector_list, head)
+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+ connector->status = connector_status_unknown;
+
if (connector->funcs->reset)
connector->funcs->reset(connector);
+ }
}
+EXPORT_SYMBOL(drm_mode_config_reset);
int drm_mode_create_dumb_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv)
@@ -3543,7 +3693,7 @@ int drm_mode_create_dumb_ioctl(struct drm_device *dev,
struct drm_mode_create_dumb *args = data;
if (!dev->driver->dumb_create)
- return -ENOTSUP;
+ return -ENOSYS;
return dev->driver->dumb_create(file_priv, dev, args);
}
@@ -3554,7 +3704,7 @@ int drm_mode_mmap_dumb_ioctl(struct drm_device *dev,
/* call driver ioctl to get mmap offset */
if (!dev->driver->dumb_map_offset)
- return -ENOTSUP;
+ return -ENOSYS;
return dev->driver->dumb_map_offset(file_priv, dev, args->handle, &args->offset);
}
@@ -3565,7 +3715,7 @@ int drm_mode_destroy_dumb_ioctl(struct drm_device *dev,
struct drm_mode_destroy_dumb *args = data;
if (!dev->driver->dumb_destroy)
- return -ENOTSUP;
+ return -ENOSYS;
return dev->driver->dumb_destroy(file_priv, dev, args->handle);
}
@@ -3578,6 +3728,7 @@ void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth,
int *bpp)
{
switch (format) {
+ case DRM_FORMAT_C8:
case DRM_FORMAT_RGB332:
case DRM_FORMAT_BGR233:
*depth = 8;
@@ -3636,6 +3787,7 @@ void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth,
break;
}
}
+EXPORT_SYMBOL(drm_fb_get_bpp_depth);
/**
* drm_format_num_planes - get the number of planes for format
@@ -3662,11 +3814,14 @@ int drm_format_num_planes(uint32_t format)
case DRM_FORMAT_NV21:
case DRM_FORMAT_NV16:
case DRM_FORMAT_NV61:
+ case DRM_FORMAT_NV24:
+ case DRM_FORMAT_NV42:
return 2;
default:
return 1;
}
}
+EXPORT_SYMBOL(drm_format_num_planes);
/**
* drm_format_plane_cpp - determine the bytes per pixel value
@@ -3694,6 +3849,8 @@ int drm_format_plane_cpp(uint32_t format, int plane)
case DRM_FORMAT_NV21:
case DRM_FORMAT_NV16:
case DRM_FORMAT_NV61:
+ case DRM_FORMAT_NV24:
+ case DRM_FORMAT_NV42:
return plane ? 2 : 1;
case DRM_FORMAT_YUV410:
case DRM_FORMAT_YVU410:
@@ -3711,6 +3868,7 @@ int drm_format_plane_cpp(uint32_t format, int plane)
return bpp >> 3;
}
}
+EXPORT_SYMBOL(drm_format_plane_cpp);
/**
* drm_format_horz_chroma_subsampling - get the horizontal chroma subsampling factor
@@ -3745,6 +3903,7 @@ int drm_format_horz_chroma_subsampling(uint32_t format)
return 1;
}
}
+EXPORT_SYMBOL(drm_format_horz_chroma_subsampling);
/**
* drm_format_vert_chroma_subsampling - get the vertical chroma subsampling factor
@@ -3769,3 +3928,4 @@ int drm_format_vert_chroma_subsampling(uint32_t format)
return 1;
}
}
+EXPORT_SYMBOL(drm_format_vert_chroma_subsampling);
diff --git a/sys/dev/drm2/drm_crtc.h b/sys/dev/drm2/drm_crtc.h
index 36708c6..0ab60c8 100644
--- a/sys/dev/drm2/drm_crtc.h
+++ b/sys/dev/drm2/drm_crtc.h
@@ -27,13 +27,15 @@
#ifndef __DRM_CRTC_H__
#define __DRM_CRTC_H__
-#include <dev/drm2/drm_gem_names.h>
+#include <dev/drm2/drm_mode.h>
+
#include <dev/drm2/drm_fourcc.h>
struct drm_device;
struct drm_mode_set;
struct drm_framebuffer;
-struct i2c_adapter;
+struct drm_object_properties;
+
#define DRM_MODE_OBJECT_CRTC 0xcccccccc
#define DRM_MODE_OBJECT_CONNECTOR 0xc0c0c0c0
@@ -50,7 +52,7 @@ struct drm_mode_object {
struct drm_object_properties *properties;
};
-#define DRM_OBJECT_MAX_PROPERTY 16
+#define DRM_OBJECT_MAX_PROPERTY 24
struct drm_object_properties {
int count;
uint32_t ids[DRM_OBJECT_MAX_PROPERTY];
@@ -72,7 +74,7 @@ enum drm_mode_status {
MODE_H_ILLEGAL, /* mode has illegal horizontal timings */
MODE_V_ILLEGAL, /* mode has illegal horizontal timings */
MODE_BAD_WIDTH, /* requires an unsupported linepitch */
- MODE_NOMODE, /* no mode with a maching name */
+ MODE_NOMODE, /* no mode with a matching name */
MODE_NO_INTERLACE, /* interlaced mode not supported */
MODE_NO_DBLESCAN, /* doublescan mode not supported */
MODE_NO_VSCAN, /* multiscan mode not supported */
@@ -114,7 +116,8 @@ enum drm_mode_status {
.hdisplay = (hd), .hsync_start = (hss), .hsync_end = (hse), \
.htotal = (ht), .hskew = (hsk), .vdisplay = (vd), \
.vsync_start = (vss), .vsync_end = (vse), .vtotal = (vt), \
- .vscan = (vs), .flags = (f), .vrefresh = 0
+ .vscan = (vs), .flags = (f), .vrefresh = 0, \
+ .base.type = DRM_MODE_OBJECT_MODE
#define CRTC_INTERLACE_HALVE_V 0x1 /* halve V values for interlacing */
@@ -125,9 +128,8 @@ struct drm_display_mode {
char name[DRM_DISPLAY_MODE_LEN];
- int connector_count;
enum drm_mode_status status;
- int type;
+ unsigned int type;
/* Proposed mode values */
int clock; /* in kHz */
@@ -163,8 +165,6 @@ struct drm_display_mode {
int crtc_vsync_start;
int crtc_vsync_end;
int crtc_vtotal;
- int crtc_hadjusted;
- int crtc_vadjusted;
/* Driver private mode info */
int private_size;
@@ -213,11 +213,10 @@ struct drm_display_info {
u32 color_formats;
u8 cea_rev;
-
- char *raw_edid; /* if any */
};
struct drm_framebuffer_funcs {
+ /* note: use drm_framebuffer_remove() */
void (*destroy)(struct drm_framebuffer *framebuffer);
int (*create_handle)(struct drm_framebuffer *fb,
struct drm_file *file_priv,
@@ -242,6 +241,16 @@ struct drm_framebuffer_funcs {
struct drm_framebuffer {
struct drm_device *dev;
+ /*
+ * Note that the fb is refcounted for the benefit of driver internals,
+ * for example some hw, disabling a CRTC/plane is asynchronous, and
+ * scanout does not actually complete until the next vblank. So some
+ * cleanup (like releasing the reference(s) on the backing GEM bo(s))
+ * should be deferred. In cases like this, the driver would like to
+ * hold a ref to the fb even though it has already been removed from
+ * userspace perspective.
+ */
+ unsigned int refcount;
struct list_head head;
struct drm_mode_object base;
const struct drm_framebuffer_funcs *funcs;
@@ -291,20 +300,16 @@ struct drm_plane;
/**
* drm_crtc_funcs - control CRTCs for a given device
- * @reset: reset CRTC after state has been invalidate (e.g. resume)
- * @dpms: control display power levels
* @save: save CRTC state
- * @resore: restore CRTC state
- * @lock: lock the CRTC
- * @unlock: unlock the CRTC
- * @shadow_allocate: allocate shadow pixmap
- * @shadow_create: create shadow pixmap for rotation support
- * @shadow_destroy: free shadow pixmap
- * @mode_fixup: fixup proposed mode
- * @mode_set: set the desired mode on the CRTC
+ * @restore: restore CRTC state
+ * @reset: reset CRTC after state has been invalidate (e.g. resume)
+ * @cursor_set: setup the cursor
+ * @cursor_move: move the cursor
* @gamma_set: specify color ramp for CRTC
* @destroy: deinit and free object
* @set_property: called when a property is changed
+ * @set_config: apply a new CRTC configuration
+ * @page_flip: initiate a page flip
*
* The drm_crtc_funcs structure is the central CRTC management structure
* in the DRM. Each CRTC controls one or more connectors (note that the name
@@ -338,7 +343,7 @@ struct drm_crtc_funcs {
/*
* Flip to the given framebuffer. This implements the page
- * flip ioctl descibed in drm_mode.h, specifically, the
+ * flip ioctl described in drm_mode.h, specifically, the
* implementation must return immediately and block all
* rendering to the current fb until the flip has completed.
* If userspace set the event flag in the ioctl, the event
@@ -348,16 +353,31 @@ struct drm_crtc_funcs {
int (*page_flip)(struct drm_crtc *crtc,
struct drm_framebuffer *fb,
struct drm_pending_vblank_event *event);
+
int (*set_property)(struct drm_crtc *crtc,
struct drm_property *property, uint64_t val);
};
/**
* drm_crtc - central CRTC control structure
+ * @dev: parent DRM device
+ * @head: list management
+ * @base: base KMS object for ID tracking etc.
* @enabled: is this CRTC enabled?
+ * @mode: current mode timings
+ * @hwmode: mode timings as programmed to hw regs
+ * @invert_dimensions: for purposes of error checking crtc vs fb sizes,
+ * invert the width/height of the crtc. This is used if the driver
+ * is performing 90 or 270 degree rotated scanout
* @x: x position on screen
* @y: y position on screen
* @funcs: CRTC control functions
+ * @gamma_size: size of gamma ramp
+ * @gamma_store: gamma ramp values
+ * @framedur_ns: precise frame timing
+ * @framedur_ns: precise line timing
+ * @pixeldur_ns: precise pixel timing
+ * @helper_private: mid-layer private data
* @properties: property tracking for this CRTC
*
* Each CRTC may have one or more connectors associated with it. This structure
@@ -382,6 +402,8 @@ struct drm_crtc {
*/
struct drm_display_mode hwmode;
+ bool invert_dimensions;
+
int x, y;
const struct drm_crtc_funcs *funcs;
@@ -390,7 +412,7 @@ struct drm_crtc {
uint16_t *gamma_store;
/* Constants needed for precise vblank and swap timestamping. */
- int64_t framedur_ns, linedur_ns, pixeldur_ns;
+ s64 framedur_ns, linedur_ns, pixeldur_ns;
/* if you are using the helper */
void *helper_private;
@@ -405,11 +427,8 @@ struct drm_crtc {
* @save: save connector state
* @restore: restore connector state
* @reset: reset connector after state has been invalidate (e.g. resume)
- * @mode_valid: is this mode valid on the given connector?
- * @mode_fixup: try to fixup proposed mode for this connector
- * @mode_set: set this mode
* @detect: is this connector active?
- * @get_modes: get mode list for this connector
+ * @fill_modes: fill mode list for this connector
* @set_property: property for this connector may need update
* @destroy: make object go away
* @force: notify the driver the connector is forced on
@@ -439,6 +458,13 @@ struct drm_connector_funcs {
void (*force)(struct drm_connector *connector);
};
+/**
+ * drm_encoder_funcs - encoder controls
+ * @reset: reset state (e.g. at init or resume time)
+ * @destroy: cleanup and free associated data
+ *
+ * Encoders sit between CRTCs and connectors.
+ */
struct drm_encoder_funcs {
void (*reset)(struct drm_encoder *encoder);
void (*destroy)(struct drm_encoder *encoder);
@@ -446,10 +472,22 @@ struct drm_encoder_funcs {
#define DRM_CONNECTOR_MAX_UMODES 16
#define DRM_CONNECTOR_LEN 32
-#define DRM_CONNECTOR_MAX_ENCODER 2
+#define DRM_CONNECTOR_MAX_ENCODER 3
/**
* drm_encoder - central DRM encoder structure
+ * @dev: parent DRM device
+ * @head: list management
+ * @base: base KMS object
+ * @encoder_type: one of the %DRM_MODE_ENCODER_<foo> types in drm_mode.h
+ * @possible_crtcs: bitmask of potential CRTC bindings
+ * @possible_clones: bitmask of potential sibling encoders for cloning
+ * @crtc: currently bound CRTC
+ * @funcs: control functions
+ * @helper_private: mid-layer private data
+ *
+ * CRTCs drive pixels to encoders, which convert them into signals
+ * appropriate for a given connector or set of connectors.
*/
struct drm_encoder {
struct drm_device *dev;
@@ -485,14 +523,36 @@ enum drm_connector_force {
/**
* drm_connector - central DRM connector control structure
- * @crtc: CRTC this connector is currently connected to, NULL if none
+ * @dev: parent DRM device
+ * @kdev: kernel device for sysfs attributes
+ * @attr: sysfs attributes
+ * @head: list management
+ * @base: base KMS object
+ * @connector_type: one of the %DRM_MODE_CONNECTOR_<foo> types from drm_mode.h
+ * @connector_type_id: index into connector type enum
* @interlace_allowed: can this connector handle interlaced modes?
* @doublescan_allowed: can this connector handle doublescan?
- * @available_modes: modes available on this connector (from get_modes() + user)
- * @initial_x: initial x position for this connector
- * @initial_y: initial y position for this connector
- * @status: connector connected?
+ * @modes: modes available on this connector (from fill_modes() + user)
+ * @status: one of the drm_connector_status enums (connected, not, or unknown)
+ * @probed_modes: list of modes derived directly from the display
+ * @display_info: information about attached display (e.g. from EDID)
* @funcs: connector control functions
+ * @user_modes: user added mode list
+ * @edid_blob_ptr: DRM property containing EDID if present
+ * @properties: property tracking for this connector
+ * @polled: a %DRM_CONNECTOR_POLL_<foo> value for core driven polling
+ * @dpms: current dpms state
+ * @helper_private: mid-layer private data
+ * @force: a %DRM_FORCE_<foo> state for forced mode sets
+ * @encoder_ids: valid encoders for this connector
+ * @encoder: encoder driving this connector, if any
+ * @eld: EDID-like data, if present
+ * @dvi_dual: dual link DVI, if found
+ * @max_tmds_clock: max clock rate, if found
+ * @latency_present: AV delay info from ELD, if found
+ * @video_latency: video latency info from ELD, if found
+ * @audio_latency: audio latency info from ELD, if found
+ * @null_edid_counter: track sinks that give us all zeros for the EDID
*
* Each connector may be connected to one or more CRTCs, or may be clonable by
* another connector if they can share a CRTC. Each connector also has a specific
@@ -501,7 +561,9 @@ enum drm_connector_force {
*/
struct drm_connector {
struct drm_device *dev;
- /* struct device kdev; XXXKIB */
+#ifdef FREEBSD_NOTYET
+ struct device kdev;
+#endif /* FREEBSD_NOTYET */
struct device_attribute *attr;
struct list_head head;
@@ -513,7 +575,6 @@ struct drm_connector {
bool doublescan_allowed;
struct list_head modes; /* list of modes on this connector */
- int initial_x, initial_y;
enum drm_connector_status status;
/* these are modes added by probing with DDC or the BIOS */
@@ -536,7 +597,6 @@ struct drm_connector {
/* forced on connector */
enum drm_connector_force force;
uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER];
- uint32_t force_encoder_id;
struct drm_encoder *encoder; /* currently active encoder */
/* EDID bits */
@@ -546,8 +606,8 @@ struct drm_connector {
bool latency_present[2];
int video_latency[2]; /* [0]: progressive, [1]: interlaced */
int audio_latency[2];
-
int null_edid_counter; /* needed to workaround some HW bugs where we get all 0s */
+ unsigned bad_edid_counter;
};
/**
@@ -566,6 +626,7 @@ struct drm_plane_funcs {
uint32_t src_w, uint32_t src_h);
int (*disable_plane)(struct drm_plane *plane);
void (*destroy)(struct drm_plane *plane);
+
int (*set_property)(struct drm_plane *plane,
struct drm_property *property, uint64_t val);
};
@@ -585,7 +646,7 @@ struct drm_plane_funcs {
* @enabled: enabled flag
* @funcs: helper functions
* @helper_private: storage for drver layer
- @properties: property tracking for this plane
+ * @properties: property tracking for this plane
*/
struct drm_plane {
struct drm_device *dev;
@@ -613,7 +674,15 @@ struct drm_plane {
};
/**
- * struct drm_mode_set
+ * drm_mode_set - new values for a CRTC config change
+ * @head: list management
+ * @fb: framebuffer to use for new config
+ * @crtc: CRTC whose configuration we're about to change
+ * @mode: mode timings to use
+ * @x: position of this CRTC relative to @fb
+ * @y: position of this CRTC relative to @fb
+ * @connectors: array of connectors to drive with this CRTC if possible
+ * @num_connectors: size of @connectors array
*
* Represents a single crtc the connectors that it drives with what mode
* and from which framebuffer it scans out from.
@@ -621,8 +690,6 @@ struct drm_plane {
* This is used to set modes.
*/
struct drm_mode_set {
- struct list_head head;
-
struct drm_framebuffer *fb;
struct drm_crtc *crtc;
struct drm_display_mode *mode;
@@ -635,15 +702,34 @@ struct drm_mode_set {
};
/**
- * struct drm_mode_config_funcs - configure CRTCs for a given screen layout
+ * struct drm_mode_config_funcs - basic driver provided mode setting functions
+ * @fb_create: create a new framebuffer object
+ * @output_poll_changed: function to handle output configuration changes
+ *
+ * Some global (i.e. not per-CRTC, connector, etc) mode setting functions that
+ * involve drivers.
*/
struct drm_mode_config_funcs {
int (*fb_create)(struct drm_device *dev,
- struct drm_file *file_priv, struct drm_mode_fb_cmd2 *mode_cmd,
- struct drm_framebuffer **res);
+ struct drm_file *file_priv,
+ struct drm_mode_fb_cmd2 *mode_cmd,
+ struct drm_framebuffer **fb);
void (*output_poll_changed)(struct drm_device *dev);
};
+/**
+ * drm_mode_group - group of mode setting resources for potential sub-grouping
+ * @num_crtcs: CRTC count
+ * @num_encoders: encoder count
+ * @num_connectors: connector count
+ * @id_list: list of KMS object IDs in this group
+ *
+ * Currently this simply tracks the global mode setting state. But in the
+ * future it could allow groups of objects to be set aside into independent
+ * control groups for use by different user level processes (e.g. two X servers
+ * running simultaneously on different heads, each with their own mode
+ * configuration and freedom of mode setting).
+ */
struct drm_mode_group {
uint32_t num_crtcs;
uint32_t num_encoders;
@@ -655,11 +741,34 @@ struct drm_mode_group {
/**
* drm_mode_config - Mode configuration control structure
+ * @mutex: mutex protecting KMS related lists and structures
+ * @idr_mutex: mutex for KMS ID allocation and management
+ * @crtc_idr: main KMS ID tracking object
+ * @num_fb: number of fbs available
+ * @fb_list: list of framebuffers available
+ * @num_connector: number of connectors on this device
+ * @connector_list: list of connector objects
+ * @num_encoder: number of encoders on this device
+ * @encoder_list: list of encoder objects
+ * @num_crtc: number of CRTCs on this device
+ * @crtc_list: list of CRTC objects
+ * @min_width: minimum pixel width on this device
+ * @min_height: minimum pixel height on this device
+ * @max_width: maximum pixel width on this device
+ * @max_height: maximum pixel height on this device
+ * @funcs: core driver provided mode setting functions
+ * @fb_base: base address of the framebuffer
+ * @poll_enabled: track polling status for this device
+ * @output_poll_work: delayed work for polling in process context
+ * @*_property: core property tracking
*
+ * Core mode resource tracking structure. All CRTC, encoders, and connectors
+ * enumerated by the driver are added here, as are global properties. Some
+ * global restrictions are also here, e.g. dimension restrictions.
*/
struct drm_mode_config {
struct sx mutex; /* protects configuration (mode lists etc.) */
- struct drm_gem_names crtc_names; /* use this idr for all IDs, fb, crtc, connector, modes */
+ struct drm_gem_names crtc_names; /* use this idr for all IDs, fb, crtc, connector, modes - just makes life easier */
/* this is limited to one for now */
int num_fb;
struct list_head fb_list;
@@ -682,7 +791,8 @@ struct drm_mode_config {
/* output poll support */
bool poll_enabled;
- struct timeout_task output_poll_task;
+ bool poll_running;
+ struct timeout_task output_poll_work;
/* pointers to standard properties */
struct list_head property_blob_list;
@@ -731,16 +841,6 @@ struct drm_prop_enum_list {
char *name;
};
-#if defined(MODE_SETTING_LOCKING_IS_NOT_BROKEN)
-#define DRM_MODE_CONFIG_ASSERT_LOCKED(dev) \
- sx_assert(&dev->mode_config.mutex, SA_XLOCKED)
-#else
-#define DRM_MODE_CONFIG_ASSERT_LOCKED(dev)
-#endif
-
-extern char *drm_get_dirty_info_name(int val);
-extern char *drm_get_connector_status_name(enum drm_connector_status status);
-
extern int drm_crtc_init(struct drm_device *dev,
struct drm_crtc *crtc,
const struct drm_crtc_funcs *funcs);
@@ -752,6 +852,8 @@ extern int drm_connector_init(struct drm_device *dev,
int connector_type);
extern void drm_connector_cleanup(struct drm_connector *connector);
+/* helper to unplug all connectors from sysfs for device */
+extern void drm_connector_unplug_all(struct drm_device *dev);
extern int drm_encoder_init(struct drm_device *dev,
struct drm_encoder *encoder,
@@ -769,28 +871,34 @@ extern void drm_plane_cleanup(struct drm_plane *plane);
extern void drm_encoder_cleanup(struct drm_encoder *encoder);
extern char *drm_get_connector_name(struct drm_connector *connector);
+extern char *drm_get_connector_status_name(enum drm_connector_status status);
extern char *drm_get_dpms_name(int val);
extern char *drm_get_dvi_i_subconnector_name(int val);
extern char *drm_get_dvi_i_select_name(int val);
extern char *drm_get_tv_subconnector_name(int val);
+extern char *drm_get_dirty_info_name(int val);
extern char *drm_get_tv_select_name(int val);
extern void drm_fb_release(struct drm_file *file_priv);
+extern int drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *group);
+extern void drm_mode_group_free(struct drm_mode_group *group);
extern int drm_mode_group_init_legacy_group(struct drm_device *dev, struct drm_mode_group *group);
+extern bool drm_probe_ddc(device_t adapter);
extern struct edid *drm_get_edid(struct drm_connector *connector,
device_t adapter);
extern int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid);
extern void drm_mode_probed_add(struct drm_connector *connector, struct drm_display_mode *mode);
extern void drm_mode_remove(struct drm_connector *connector, struct drm_display_mode *mode);
+extern void drm_mode_copy(struct drm_display_mode *dst, const struct drm_display_mode *src);
extern struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev,
- const struct drm_display_mode *mode);
-extern void drm_mode_debug_printmodeline(struct drm_display_mode *mode);
+ const struct drm_display_mode *mode);
+extern void drm_mode_debug_printmodeline(const struct drm_display_mode *mode);
extern void drm_mode_config_init(struct drm_device *dev);
extern void drm_mode_config_reset(struct drm_device *dev);
extern void drm_mode_config_cleanup(struct drm_device *dev);
extern void drm_mode_set_name(struct drm_display_mode *mode);
-extern bool drm_mode_equal(struct drm_display_mode *mode1, struct drm_display_mode *mode2);
-extern int drm_mode_width(struct drm_display_mode *mode);
-extern int drm_mode_height(struct drm_display_mode *mode);
+extern bool drm_mode_equal(const struct drm_display_mode *mode1, const struct drm_display_mode *mode2);
+extern int drm_mode_width(const struct drm_display_mode *mode);
+extern int drm_mode_height(const struct drm_display_mode *mode);
/* for us by fb module */
extern int drm_mode_attachmode_crtc(struct drm_device *dev,
@@ -806,8 +914,8 @@ extern void drm_mode_validate_size(struct drm_device *dev,
struct list_head *mode_list,
int maxX, int maxY, int maxPitch);
extern void drm_mode_validate_clocks(struct drm_device *dev,
- struct list_head *mode_list,
- int *min, int *max, int n_ranges);
+ struct list_head *mode_list,
+ int *min, int *max, int n_ranges);
extern void drm_mode_prune_invalid(struct drm_device *dev,
struct list_head *mode_list, bool verbose);
extern void drm_mode_sort(struct list_head *mode_list);
@@ -818,15 +926,6 @@ extern void drm_mode_set_crtcinfo(struct drm_display_mode *p,
extern void drm_mode_connector_list_update(struct drm_connector *connector);
extern int drm_mode_connector_update_edid_property(struct drm_connector *connector,
struct edid *edid);
-extern int drm_connector_property_set_value(struct drm_connector *connector,
- struct drm_property *property,
- uint64_t value);
-extern int drm_connector_property_get_value(struct drm_connector *connector,
- struct drm_property *property,
- uint64_t *value);
-void drm_object_attach_property(struct drm_mode_object *obj,
- struct drm_property *property,
- uint64_t init_val);
extern int drm_object_property_set_value(struct drm_mode_object *obj,
struct drm_property *property,
uint64_t val);
@@ -839,14 +938,18 @@ extern void drm_framebuffer_set_object(struct drm_device *dev,
extern int drm_framebuffer_init(struct drm_device *dev,
struct drm_framebuffer *fb,
const struct drm_framebuffer_funcs *funcs);
+extern void drm_framebuffer_unreference(struct drm_framebuffer *fb);
+extern void drm_framebuffer_reference(struct drm_framebuffer *fb);
+extern void drm_framebuffer_remove(struct drm_framebuffer *fb);
extern void drm_framebuffer_cleanup(struct drm_framebuffer *fb);
extern int drmfb_probe(struct drm_device *dev, struct drm_crtc *crtc);
extern int drmfb_remove(struct drm_device *dev, struct drm_framebuffer *fb);
extern void drm_crtc_probe_connector_modes(struct drm_device *dev, int maxX, int maxY);
extern bool drm_crtc_in_use(struct drm_crtc *crtc);
-extern void drm_connector_attach_property(struct drm_connector *connector,
- struct drm_property *property, uint64_t init_val);
+extern void drm_object_attach_property(struct drm_mode_object *obj,
+ struct drm_property *property,
+ uint64_t init_val);
extern struct drm_property *drm_property_create(struct drm_device *dev, int flags,
const char *name, int num_values);
extern struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags,
@@ -854,9 +957,9 @@ extern struct drm_property *drm_property_create_enum(struct drm_device *dev, int
const struct drm_prop_enum_list *props,
int num_values);
struct drm_property *drm_property_create_bitmask(struct drm_device *dev,
- int flags, const char *name,
- const struct drm_prop_enum_list *props,
- int num_values);
+ int flags, const char *name,
+ const struct drm_prop_enum_list *props,
+ int num_values);
struct drm_property *drm_property_create_range(struct drm_device *dev, int flags,
const char *name,
uint64_t min, uint64_t max);
@@ -932,6 +1035,8 @@ extern int drm_mode_gamma_get_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv);
extern int drm_mode_gamma_set_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv);
+extern u8 *drm_find_cea_extension(struct edid *edid);
+extern u8 drm_match_cea_mode(struct drm_display_mode *to_match);
extern bool drm_detect_hdmi_monitor(struct edid *edid);
extern bool drm_detect_monitor_audio(struct edid *edid);
extern int drm_mode_page_flip_ioctl(struct drm_device *dev,
@@ -948,8 +1053,10 @@ extern struct drm_display_mode *drm_gtf_mode_complex(struct drm_device *dev,
int GTF_2C, int GTF_K, int GTF_2J);
extern int drm_add_modes_noedid(struct drm_connector *connector,
int hdisplay, int vdisplay);
+extern uint8_t drm_mode_cea_vic(const struct drm_display_mode *mode);
extern int drm_edid_header_is_valid(const u8 *raw_edid);
+extern bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid);
extern bool drm_edid_is_valid(struct edid *edid);
struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
int hsize, int vsize, int fresh,
diff --git a/sys/dev/drm2/drm_crtc_helper.c b/sys/dev/drm2/drm_crtc_helper.c
index 4d35e7f..411a1f6 100644
--- a/sys/dev/drm2/drm_crtc_helper.c
+++ b/sys/dev/drm2/drm_crtc_helper.c
@@ -32,48 +32,54 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include <sys/param.h>
-#include <sys/systm.h>
#include <dev/drm2/drmP.h>
#include <dev/drm2/drm_crtc.h>
#include <dev/drm2/drm_fourcc.h>
#include <dev/drm2/drm_crtc_helper.h>
#include <dev/drm2/drm_fb_helper.h>
+#include <dev/drm2/drm_edid.h>
-bool
-drm_fetch_cmdline_mode_from_kenv(struct drm_connector *connector,
- struct drm_cmdline_mode *cmdline_mode)
+/**
+ * drm_helper_move_panel_connectors_to_head() - move panels to the front in the
+ * connector list
+ * @dev: drm device to operate on
+ *
+ * Some userspace presumes that the first connected connector is the main
+ * display, where it's supposed to display e.g. the login screen. For
+ * laptops, this should be the main panel. Use this function to sort all
+ * (eDP/LVDS) panels to the front of the connector list, instead of
+ * painstakingly trying to initialize them in the right order.
+ */
+void drm_helper_move_panel_connectors_to_head(struct drm_device *dev)
{
- char *tun_var_name, *tun_mode;
- static const char tun_prefix[] = "drm_mode.";
- bool res;
-
- res = false;
- tun_var_name = malloc(sizeof(tun_prefix) +
- strlen(drm_get_connector_name(connector)), M_TEMP, M_WAITOK);
- strcpy(tun_var_name, tun_prefix);
- strcat(tun_var_name, drm_get_connector_name(connector));
- tun_mode = getenv(tun_var_name);
- if (tun_mode != NULL) {
- res = drm_mode_parse_command_line_for_connector(tun_mode,
- connector, cmdline_mode);
- freeenv(tun_mode);
+ struct drm_connector *connector, *tmp;
+ struct list_head panel_list;
+
+ INIT_LIST_HEAD(&panel_list);
+
+ list_for_each_entry_safe(connector, tmp,
+ &dev->mode_config.connector_list, head) {
+ if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
+ connector->connector_type == DRM_MODE_CONNECTOR_eDP)
+ list_move_tail(&connector->head, &panel_list);
}
- free(tun_var_name, M_TEMP);
- return (res);
+
+ list_splice(&panel_list, &dev->mode_config.connector_list);
}
+EXPORT_SYMBOL(drm_helper_move_panel_connectors_to_head);
static bool drm_kms_helper_poll = true;
+module_param_named(poll, drm_kms_helper_poll, bool, 0600);
static void drm_mode_validate_flag(struct drm_connector *connector,
int flags)
{
- struct drm_display_mode *mode, *t;
+ struct drm_display_mode *mode;
if (flags == (DRM_MODE_FLAG_DBLSCAN | DRM_MODE_FLAG_INTERLACE))
return;
- list_for_each_entry_safe(mode, t, &connector->modes, head) {
+ list_for_each_entry(mode, &connector->modes, head) {
if ((mode->flags & DRM_MODE_FLAG_INTERLACE) &&
!(flags & DRM_MODE_FLAG_INTERLACE))
mode->status = MODE_NO_INTERLACE;
@@ -87,22 +93,21 @@ static void drm_mode_validate_flag(struct drm_connector *connector,
/**
* drm_helper_probe_single_connector_modes - get complete set of display modes
- * @dev: DRM device
+ * @connector: connector to probe
* @maxX: max width for modes
* @maxY: max height for modes
*
* LOCKING:
* Caller must hold mode config lock.
*
- * Based on @dev's mode_config layout, scan all the connectors and try to detect
- * modes on them. Modes will first be added to the connector's probed_modes
- * list, then culled (based on validity and the @maxX, @maxY parameters) and
- * put into the normal modes list.
+ * Based on the helper callbacks implemented by @connector try to detect all
+ * valid modes. Modes will first be added to the connector's probed_modes list,
+ * then culled (based on validity and the @maxX, @maxY parameters) and put into
+ * the normal modes list.
*
- * Intended to be used either at bootup time or when major configuration
- * changes have occurred.
- *
- * FIXME: take into account monitor limits
+ * Intended to be use as a generic implementation of the ->probe() @connector
+ * callback for drivers that use the crtc helpers for output mode filtering and
+ * detection.
*
* RETURNS:
* Number of modes found on @connector.
@@ -111,17 +116,16 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
uint32_t maxX, uint32_t maxY)
{
struct drm_device *dev = connector->dev;
- struct drm_display_mode *mode, *t;
+ struct drm_display_mode *mode;
struct drm_connector_helper_funcs *connector_funcs =
connector->helper_private;
- struct drm_cmdline_mode cmdline_mode;
int count = 0;
int mode_flags = 0;
DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id,
drm_get_connector_name(connector));
/* set all modes to the unverified state */
- list_for_each_entry_safe(mode, t, &connector->modes, head)
+ list_for_each_entry(mode, &connector->modes, head)
mode->status = MODE_UNVERIFIED;
if (connector->force) {
@@ -133,9 +137,14 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
connector->funcs->force(connector);
} else {
connector->status = connector->funcs->detect(connector, true);
- drm_kms_helper_poll_enable(dev);
}
+ /* Re-enable polling in case the global poll config changed. */
+ if (drm_kms_helper_poll != dev->mode_config.poll_running)
+ drm_kms_helper_poll_enable(dev);
+
+ dev->mode_config.poll_running = drm_kms_helper_poll;
+
if (connector->status == connector_status_disconnected) {
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] disconnected\n",
connector->base.id, drm_get_connector_name(connector));
@@ -143,26 +152,14 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
goto prune;
}
- count = (*connector_funcs->get_modes)(connector);
- if (count == 0 && drm_fetch_cmdline_mode_from_kenv(connector,
- &cmdline_mode)) {
- mode = drm_mode_create_from_cmdline_mode(dev,
- &cmdline_mode);
- if (mode != NULL) {
- DRM_DEBUG_KMS(
- "[CONNECTOR:%d:%s] found manual override ",
- connector->base.id,
- drm_get_connector_name(connector));
- drm_mode_debug_printmodeline(mode);
- drm_mode_probed_add(connector, mode);
- count++;
- } else {
- DRM_ERROR(
- "[CONNECTOR:%d:%s] manual override mode: parse error\n",
- connector->base.id,
- drm_get_connector_name(connector));
- }
- }
+#ifdef FREEBSD_NOTYET
+#ifdef CONFIG_DRM_LOAD_EDID_FIRMWARE
+ count = drm_load_edid_firmware(connector);
+ if (count == 0)
+#endif
+#endif /* FREEBSD_NOTYET */
+ count = (*connector_funcs->get_modes)(connector);
+
if (count == 0 && connector->status == connector_status_connected)
count = drm_add_modes_noedid(connector, 1024, 768);
if (count == 0)
@@ -180,7 +177,7 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
mode_flags |= DRM_MODE_FLAG_DBLSCAN;
drm_mode_validate_flag(connector, mode_flags);
- list_for_each_entry_safe(mode, t, &connector->modes, head) {
+ list_for_each_entry(mode, &connector->modes, head) {
if (mode->status == MODE_OK)
mode->status = connector_funcs->mode_valid(connector,
mode);
@@ -192,19 +189,21 @@ prune:
if (list_empty(&connector->modes))
return 0;
+ list_for_each_entry(mode, &connector->modes, head)
+ mode->vrefresh = drm_mode_vrefresh(mode);
+
drm_mode_sort(&connector->modes);
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] probed modes :\n", connector->base.id,
drm_get_connector_name(connector));
- list_for_each_entry_safe(mode, t, &connector->modes, head) {
- mode->vrefresh = drm_mode_vrefresh(mode);
-
+ list_for_each_entry(mode, &connector->modes, head) {
drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
drm_mode_debug_printmodeline(mode);
}
return count;
}
+EXPORT_SYMBOL(drm_helper_probe_single_connector_modes);
/**
* drm_helper_encoder_in_use - check if a given encoder is in use
@@ -227,6 +226,7 @@ bool drm_helper_encoder_in_use(struct drm_encoder *encoder)
return true;
return false;
}
+EXPORT_SYMBOL(drm_helper_encoder_in_use);
/**
* drm_helper_crtc_in_use - check if a given CRTC is in a mode_config
@@ -250,6 +250,7 @@ bool drm_helper_crtc_in_use(struct drm_crtc *crtc)
return true;
return false;
}
+EXPORT_SYMBOL(drm_helper_crtc_in_use);
static void
drm_encoder_disable(struct drm_encoder *encoder)
@@ -305,6 +306,7 @@ void drm_helper_disable_unused_functions(struct drm_device *dev)
}
}
}
+EXPORT_SYMBOL(drm_helper_disable_unused_functions);
/**
* drm_encoder_crtc_ok - can a given crtc drive a given encoder?
@@ -360,17 +362,24 @@ drm_crtc_prepare_encoders(struct drm_device *dev)
}
/**
- * drm_crtc_set_mode - set a mode
+ * drm_crtc_helper_set_mode - internal helper to set a mode
* @crtc: CRTC to program
* @mode: mode to use
- * @x: width of mode
- * @y: height of mode
+ * @x: horizontal offset into the surface
+ * @y: vertical offset into the surface
+ * @old_fb: old framebuffer, for cleanup
*
* LOCKING:
* Caller must hold mode config lock.
*
* Try to set @mode on @crtc. Give @crtc and its associated connectors a chance
- * to fixup or reject the mode prior to trying to set it.
+ * to fixup or reject the mode prior to trying to set it. This is an internal
+ * helper that drivers could e.g. use to update properties that require the
+ * entire output pipe to be disabled and re-enabled in a new configuration. For
+ * example for changing whether audio is enabled on a hdmi link or for changing
+ * panel fitter or dither attributes. It is also called by the
+ * drm_crtc_helper_set_config() helper function to drive the mode setting
+ * sequence.
*
* RETURNS:
* True if the mode was set successfully, or false otherwise.
@@ -419,11 +428,13 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
encoder_funcs = encoder->helper_private;
if (!(ret = encoder_funcs->mode_fixup(encoder, mode,
adjusted_mode))) {
+ DRM_DEBUG_KMS("Encoder fixup failed\n");
goto done;
}
}
if (!(ret = crtc_funcs->mode_fixup(crtc, mode, adjusted_mode))) {
+ DRM_DEBUG_KMS("CRTC fixup failed\n");
goto done;
}
DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
@@ -495,6 +506,8 @@ done:
return ret;
}
+EXPORT_SYMBOL(drm_crtc_helper_set_mode);
+
static int
drm_crtc_helper_disable(struct drm_crtc *crtc)
@@ -522,20 +535,19 @@ drm_crtc_helper_disable(struct drm_crtc *crtc)
/**
* drm_crtc_helper_set_config - set a new config from userspace
- * @crtc: CRTC to setup
- * @crtc_info: user provided configuration
- * @new_mode: new mode to set
- * @connector_set: set of connectors for the new config
- * @fb: new framebuffer
+ * @set: mode set configuration
*
* LOCKING:
* Caller must hold mode config lock.
*
- * Setup a new configuration, provided by the user in @crtc_info, and enable
- * it.
+ * Setup a new configuration, provided by the upper layers (either an ioctl call
+ * from userspace or internally e.g. from the fbdev suppport code) in @set, and
+ * enable it. This is the main helper functions for drivers that implement
+ * kernel mode setting with the crtc helper functions and the assorted
+ * ->prepare(), ->modeset() and ->commit() helper callbacks.
*
* RETURNS:
- * Zero. (FIXME)
+ * Returns 0 on success, -ERRNO on failure.
*/
int drm_crtc_helper_set_config(struct drm_mode_set *set)
{
@@ -581,12 +593,25 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
/* Allocate space for the backup of all (non-pointer) crtc, encoder and
* connector data. */
- save_crtcs = malloc(dev->mode_config.num_crtc * sizeof(struct drm_crtc),
- DRM_MEM_KMS, M_WAITOK | M_ZERO);
+ save_crtcs = malloc(dev->mode_config.num_crtc *
+ sizeof(struct drm_crtc), DRM_MEM_KMS, M_NOWAIT | M_ZERO);
+ if (!save_crtcs)
+ return -ENOMEM;
+
save_encoders = malloc(dev->mode_config.num_encoder *
- sizeof(struct drm_encoder), DRM_MEM_KMS, M_WAITOK | M_ZERO);
+ sizeof(struct drm_encoder), DRM_MEM_KMS, M_NOWAIT | M_ZERO);
+ if (!save_encoders) {
+ free(save_crtcs, DRM_MEM_KMS);
+ return -ENOMEM;
+ }
+
save_connectors = malloc(dev->mode_config.num_connector *
- sizeof(struct drm_connector), DRM_MEM_KMS, M_WAITOK | M_ZERO);
+ sizeof(struct drm_connector), DRM_MEM_KMS, M_NOWAIT | M_ZERO);
+ if (!save_connectors) {
+ free(save_crtcs, DRM_MEM_KMS);
+ free(save_encoders, DRM_MEM_KMS);
+ return -ENOMEM;
+ }
/* Copy data. Note that driver private data is not affected.
* Should anything bad happen only the expected state is
@@ -622,6 +647,11 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
mode_changed = true;
} else if (set->fb == NULL) {
mode_changed = true;
+ } else if (set->fb->depth != set->crtc->fb->depth) {
+ mode_changed = true;
+ } else if (set->fb->bits_per_pixel !=
+ set->crtc->fb->bits_per_pixel) {
+ mode_changed = true;
} else
fb_changed = true;
}
@@ -732,7 +762,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
for (i = 0; i < set->num_connectors; i++) {
DRM_DEBUG_KMS("\t[CONNECTOR:%d:%s] set DPMS on\n", set->connectors[i]->base.id,
drm_get_connector_name(set->connectors[i]));
- set->connectors[i]->dpms = DRM_MODE_DPMS_ON;
+ set->connectors[i]->funcs->dpms(set->connectors[i], DRM_MODE_DPMS_ON);
}
}
drm_helper_disable_unused_functions(dev);
@@ -784,6 +814,7 @@ fail:
free(save_crtcs, DRM_MEM_KMS);
return ret;
}
+EXPORT_SYMBOL(drm_crtc_helper_set_config);
static int drm_helper_choose_encoder_dpms(struct drm_encoder *encoder)
{
@@ -812,12 +843,14 @@ static int drm_helper_choose_crtc_dpms(struct drm_crtc *crtc)
}
/**
- * drm_helper_connector_dpms
- * @connector affected connector
- * @mode DPMS mode
+ * drm_helper_connector_dpms() - connector dpms helper implementation
+ * @connector: affected connector
+ * @mode: DPMS mode
*
- * Calls the low-level connector DPMS function, then
- * calls appropriate encoder and crtc DPMS functions as well
+ * This is the main helper function provided by the crtc helper framework for
+ * implementing the DPMS connector attribute. It computes the new desired DPMS
+ * state for all encoders and crtcs in the output mesh and calls the ->dpms()
+ * callback provided by the driver appropriately.
*/
void drm_helper_connector_dpms(struct drm_connector *connector, int mode)
{
@@ -865,6 +898,7 @@ void drm_helper_connector_dpms(struct drm_connector *connector, int mode)
return;
}
+EXPORT_SYMBOL(drm_helper_connector_dpms);
int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
struct drm_mode_fb_cmd2 *mode_cmd)
@@ -883,6 +917,7 @@ int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
return 0;
}
+EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct);
int drm_helper_resume_force_mode(struct drm_device *dev)
{
@@ -900,7 +935,7 @@ int drm_helper_resume_force_mode(struct drm_device *dev)
ret = drm_crtc_helper_set_mode(crtc, &crtc->mode,
crtc->x, crtc->y, crtc->fb);
- if (!ret)
+ if (ret == false)
DRM_ERROR("failed to set mode on crtc %p\n", crtc);
/* Turn off outputs that were already powered off */
@@ -913,24 +948,36 @@ int drm_helper_resume_force_mode(struct drm_device *dev)
encoder_funcs = encoder->helper_private;
if (encoder_funcs->dpms)
(*encoder_funcs->dpms) (encoder,
- drm_helper_choose_encoder_dpms(encoder));
+ drm_helper_choose_encoder_dpms(encoder));
}
crtc_funcs = crtc->helper_private;
if (crtc_funcs->dpms)
(*crtc_funcs->dpms) (crtc,
- drm_helper_choose_crtc_dpms(crtc));
+ drm_helper_choose_crtc_dpms(crtc));
}
}
/* disable the unused connectors while restoring the modesetting */
drm_helper_disable_unused_functions(dev);
return 0;
}
+EXPORT_SYMBOL(drm_helper_resume_force_mode);
+
+void drm_kms_helper_hotplug_event(struct drm_device *dev)
+{
+ /* send a uevent + call fbdev */
+#ifdef FREEBSD_NOTYET
+ drm_sysfs_hotplug_event(dev);
+#endif /* FREEBSD_NOTYET */
+ if (dev->mode_config.funcs->output_poll_changed)
+ dev->mode_config.funcs->output_poll_changed(dev);
+}
+EXPORT_SYMBOL(drm_kms_helper_hotplug_event);
-#define DRM_OUTPUT_POLL_PERIOD (10 * hz)
+#define DRM_OUTPUT_POLL_PERIOD (10*HZ)
static void output_poll_execute(void *ctx, int pending)
{
- struct drm_device *dev;
+ struct drm_device *dev = ctx;
struct drm_connector *connector;
enum drm_connector_status old_status;
bool repoll = false, changed = false;
@@ -938,26 +985,25 @@ static void output_poll_execute(void *ctx, int pending)
if (!drm_kms_helper_poll)
return;
- dev = ctx;
-
sx_xlock(&dev->mode_config.mutex);
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
- /* if this is HPD or polled don't check it -
- TV out for instance */
- if (!connector->polled)
+ /* Ignore forced connectors. */
+ if (connector->force)
+ continue;
+
+ /* Ignore HPD capable connectors and connectors where we don't
+ * want any hotplug detection at all for polling. */
+ if (!connector->polled || connector->polled == DRM_CONNECTOR_POLL_HPD)
continue;
- else if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT |
- DRM_CONNECTOR_POLL_DISCONNECT))
- repoll = true;
+ repoll = true;
old_status = connector->status;
/* if we are connected and don't want to poll for disconnect
skip it */
if (old_status == connector_status_connected &&
- !(connector->polled & DRM_CONNECTOR_POLL_DISCONNECT) &&
- !(connector->polled & DRM_CONNECTOR_POLL_HPD))
+ !(connector->polled & DRM_CONNECTOR_POLL_DISCONNECT))
continue;
connector->status = connector->funcs->detect(connector, false);
@@ -971,20 +1017,13 @@ static void output_poll_execute(void *ctx, int pending)
sx_xunlock(&dev->mode_config.mutex);
- if (changed) {
-#if 0
- /* send a uevent + call fbdev */
- drm_sysfs_hotplug_event(dev);
-#endif
- if (dev->mode_config.funcs->output_poll_changed)
- dev->mode_config.funcs->output_poll_changed(dev);
- }
+ if (changed)
+ drm_kms_helper_hotplug_event(dev);
- if (repoll) {
+ if (repoll)
taskqueue_enqueue_timeout(taskqueue_thread,
- &dev->mode_config.output_poll_task,
+ &dev->mode_config.output_poll_work,
DRM_OUTPUT_POLL_PERIOD);
- }
}
void drm_kms_helper_poll_disable(struct drm_device *dev)
@@ -992,8 +1031,9 @@ void drm_kms_helper_poll_disable(struct drm_device *dev)
if (!dev->mode_config.poll_enabled)
return;
taskqueue_cancel_timeout(taskqueue_thread,
- &dev->mode_config.output_poll_task, NULL);
+ &dev->mode_config.output_poll_work, NULL);
}
+EXPORT_SYMBOL(drm_kms_helper_poll_disable);
void drm_kms_helper_poll_enable(struct drm_device *dev)
{
@@ -1004,40 +1044,63 @@ void drm_kms_helper_poll_enable(struct drm_device *dev)
return;
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
- if (connector->polled)
+ if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT |
+ DRM_CONNECTOR_POLL_DISCONNECT))
poll = true;
}
- if (poll) {
+ if (poll)
taskqueue_enqueue_timeout(taskqueue_thread,
- &dev->mode_config.output_poll_task, DRM_OUTPUT_POLL_PERIOD);
- }
+ &dev->mode_config.output_poll_work, DRM_OUTPUT_POLL_PERIOD);
}
+EXPORT_SYMBOL(drm_kms_helper_poll_enable);
void drm_kms_helper_poll_init(struct drm_device *dev)
{
-
- TIMEOUT_TASK_INIT(taskqueue_thread, &dev->mode_config.output_poll_task,
+ TIMEOUT_TASK_INIT(taskqueue_thread, &dev->mode_config.output_poll_work,
0, output_poll_execute, dev);
dev->mode_config.poll_enabled = true;
drm_kms_helper_poll_enable(dev);
}
+EXPORT_SYMBOL(drm_kms_helper_poll_init);
void drm_kms_helper_poll_fini(struct drm_device *dev)
{
drm_kms_helper_poll_disable(dev);
}
+EXPORT_SYMBOL(drm_kms_helper_poll_fini);
void drm_helper_hpd_irq_event(struct drm_device *dev)
{
+ struct drm_connector *connector;
+ enum drm_connector_status old_status;
+ bool changed = false;
+
if (!dev->mode_config.poll_enabled)
return;
- /* kill timer and schedule immediate execution, this doesn't block */
- taskqueue_cancel_timeout(taskqueue_thread,
- &dev->mode_config.output_poll_task, NULL);
- if (drm_kms_helper_poll)
- taskqueue_enqueue_timeout(taskqueue_thread,
- &dev->mode_config.output_poll_task, 0);
+ sx_xlock(&dev->mode_config.mutex);
+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+
+ /* Only handle HPD capable connectors. */
+ if (!(connector->polled & DRM_CONNECTOR_POLL_HPD))
+ continue;
+
+ old_status = connector->status;
+
+ connector->status = connector->funcs->detect(connector, false);
+ DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %d to %d\n",
+ connector->base.id,
+ drm_get_connector_name(connector),
+ old_status, connector->status);
+ if (old_status != connector->status)
+ changed = true;
+ }
+
+ sx_xunlock(&dev->mode_config.mutex);
+
+ if (changed)
+ drm_kms_helper_hotplug_event(dev);
}
+EXPORT_SYMBOL(drm_helper_hpd_irq_event);
diff --git a/sys/dev/drm2/drm_crtc_helper.h b/sys/dev/drm2/drm_crtc_helper.h
index 0f36b1f..e5961dc 100644
--- a/sys/dev/drm2/drm_crtc_helper.h
+++ b/sys/dev/drm2/drm_crtc_helper.h
@@ -40,6 +40,13 @@ enum mode_set_atomic {
ENTER_ATOMIC_MODE_SET,
};
+/**
+ * drm_crtc_helper_funcs - helper operations for CRTCs
+ * @mode_fixup: try to fixup proposed mode for this connector
+ * @mode_set: set this mode
+ *
+ * The helper operations are called by the mid-layer CRTC helper.
+ */
struct drm_crtc_helper_funcs {
/*
* Control power levels on the CRTC. If the mode passed in is
@@ -72,13 +79,20 @@ struct drm_crtc_helper_funcs {
void (*disable)(struct drm_crtc *crtc);
};
+/**
+ * drm_encoder_helper_funcs - helper operations for encoders
+ * @mode_fixup: try to fixup proposed mode for this connector
+ * @mode_set: set this mode
+ *
+ * The helper operations are called by the mid-layer CRTC helper.
+ */
struct drm_encoder_helper_funcs {
void (*dpms)(struct drm_encoder *encoder, int mode);
void (*save)(struct drm_encoder *encoder);
void (*restore)(struct drm_encoder *encoder);
bool (*mode_fixup)(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
+ const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode);
void (*prepare)(struct drm_encoder *encoder);
void (*commit)(struct drm_encoder *encoder);
@@ -93,6 +107,13 @@ struct drm_encoder_helper_funcs {
void (*disable)(struct drm_encoder *encoder);
};
+/**
+ * drm_connector_helper_funcs - helper operations for connectors
+ * @get_modes: get mode list for this connector
+ * @mode_valid: is this mode valid on the given connector?
+ *
+ * The helper operations are called by the mid-layer CRTC helper.
+ */
struct drm_connector_helper_funcs {
int (*get_modes)(struct drm_connector *connector);
int (*mode_valid)(struct drm_connector *connector,
@@ -112,6 +133,8 @@ extern bool drm_helper_encoder_in_use(struct drm_encoder *encoder);
extern void drm_helper_connector_dpms(struct drm_connector *connector, int mode);
+extern void drm_helper_move_panel_connectors_to_head(struct drm_device *);
+
extern int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
struct drm_mode_fb_cmd2 *mode_cmd);
@@ -137,10 +160,8 @@ extern int drm_helper_resume_force_mode(struct drm_device *dev);
extern void drm_kms_helper_poll_init(struct drm_device *dev);
extern void drm_kms_helper_poll_fini(struct drm_device *dev);
extern void drm_helper_hpd_irq_event(struct drm_device *dev);
+extern void drm_kms_helper_hotplug_event(struct drm_device *dev);
extern void drm_kms_helper_poll_disable(struct drm_device *dev);
extern void drm_kms_helper_poll_enable(struct drm_device *dev);
-
-extern bool drm_fetch_cmdline_mode_from_kenv(struct drm_connector *connector,
- struct drm_cmdline_mode *cmdline_mode);
#endif
diff --git a/sys/dev/drm2/drm_dma.c b/sys/dev/drm2/drm_dma.c
index c0a1c80..380be2b 100644
--- a/sys/dev/drm2/drm_dma.c
+++ b/sys/dev/drm2/drm_dma.c
@@ -1,4 +1,14 @@
+/**
+ * \file drm_dma.c
+ * DMA IOCTL and function support
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
/*-
+ * Created: Fri Mar 19 14:30:16 1999 by faith@valinux.com
+ *
* Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
* All Rights Reserved.
@@ -21,64 +31,72 @@
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Rickard E. (Rik) Faith <faith@valinux.com>
- * Gareth Hughes <gareth@valinux.com>
- *
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-/** @file drm_dma.c
- * Support code for DMA buffer management.
- *
- * The implementation used to be significantly more complicated, but the
- * complexity has been moved into the drivers as different buffer management
- * schemes evolved.
- */
-
#include <dev/drm2/drmP.h>
+/**
+ * Initialize the DMA data.
+ *
+ * \param dev DRM device.
+ * \return zero on success or a negative value on failure.
+ *
+ * Allocate and initialize a drm_device_dma structure.
+ */
int drm_dma_setup(struct drm_device *dev)
{
+ int i;
dev->dma = malloc(sizeof(*dev->dma), DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
- if (dev->dma == NULL)
- return ENOMEM;
+ if (!dev->dma)
+ return -ENOMEM;
- DRM_SPININIT(&dev->dma_lock, "drmdma");
+ for (i = 0; i <= DRM_MAX_ORDER; i++)
+ memset(&dev->dma->bufs[i], 0, sizeof(dev->dma->bufs[0]));
return 0;
}
+/**
+ * Cleanup the DMA resources.
+ *
+ * \param dev DRM device.
+ *
+ * Free all pages associated with DMA buffers, the buffers and pages lists, and
+ * finally the drm_device::dma structure itself.
+ */
void drm_dma_takedown(struct drm_device *dev)
{
- drm_device_dma_t *dma = dev->dma;
- int i, j;
+ struct drm_device_dma *dma = dev->dma;
+ int i, j;
- if (dma == NULL)
+ if (!dma)
return;
/* Clear dma buffers */
for (i = 0; i <= DRM_MAX_ORDER; i++) {
if (dma->bufs[i].seg_count) {
DRM_DEBUG("order %d: buf_count = %d,"
- " seg_count = %d\n", i, dma->bufs[i].buf_count,
- dma->bufs[i].seg_count);
+ " seg_count = %d\n",
+ i,
+ dma->bufs[i].buf_count,
+ dma->bufs[i].seg_count);
for (j = 0; j < dma->bufs[i].seg_count; j++) {
- drm_pci_free(dev, dma->bufs[i].seglist[j]);
+ if (dma->bufs[i].seglist[j]) {
+ drm_pci_free(dev, dma->bufs[i].seglist[j]);
+ }
}
free(dma->bufs[i].seglist, DRM_MEM_SEGS);
}
-
- if (dma->bufs[i].buf_count) {
- for (j = 0; j < dma->bufs[i].buf_count; j++) {
+ if (dma->bufs[i].buf_count) {
+ for (j = 0; j < dma->bufs[i].buf_count; j++) {
free(dma->bufs[i].buflist[j].dev_private,
DRM_MEM_BUFS);
}
- free(dma->bufs[i].buflist, DRM_MEM_BUFS);
+ free(dma->bufs[i].buflist, DRM_MEM_BUFS);
}
}
@@ -86,28 +104,42 @@ void drm_dma_takedown(struct drm_device *dev)
free(dma->pagelist, DRM_MEM_PAGES);
free(dev->dma, DRM_MEM_DRIVER);
dev->dma = NULL;
- DRM_SPINUNINIT(&dev->dma_lock);
}
-
-void drm_free_buffer(struct drm_device *dev, drm_buf_t *buf)
+/**
+ * Free a buffer.
+ *
+ * \param dev DRM device.
+ * \param buf buffer to free.
+ *
+ * Resets the fields of \p buf.
+ */
+void drm_free_buffer(struct drm_device *dev, struct drm_buf * buf)
{
if (!buf)
return;
- buf->pending = 0;
- buf->file_priv= NULL;
- buf->used = 0;
+ buf->waiting = 0;
+ buf->pending = 0;
+ buf->file_priv = NULL;
+ buf->used = 0;
}
-void drm_reclaim_buffers(struct drm_device *dev, struct drm_file *file_priv)
+/**
+ * Reclaim the buffers.
+ *
+ * \param file_priv DRM file private.
+ *
+ * Frees each buffer associated with \p file_priv not already on the hardware.
+ */
+void drm_core_reclaim_buffers(struct drm_device *dev,
+ struct drm_file *file_priv)
{
- drm_device_dma_t *dma = dev->dma;
- int i;
+ struct drm_device_dma *dma = dev->dma;
+ int i;
if (!dma)
return;
-
for (i = 0; i < dma->buf_count; i++) {
if (dma->buflist[i]->file_priv == file_priv) {
switch (dma->buflist[i]->list) {
@@ -125,15 +157,4 @@ void drm_reclaim_buffers(struct drm_device *dev, struct drm_file *file_priv)
}
}
-/* Call into the driver-specific DMA handler */
-int drm_dma(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-
- if (dev->driver->dma_ioctl) {
- /* shared code returns -errno */
- return -dev->driver->dma_ioctl(dev, data, file_priv);
- } else {
- DRM_DEBUG("DMA ioctl on driver with no dma handler\n");
- return EINVAL;
- }
-}
+EXPORT_SYMBOL(drm_core_reclaim_buffers);
diff --git a/sys/dev/drm2/drm_dp_helper.c b/sys/dev/drm2/drm_dp_helper.c
index d4a0360..5b53e89 100644
--- a/sys/dev/drm2/drm_dp_helper.c
+++ b/sys/dev/drm2/drm_dp_helper.c
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
* blocks, ...
*/
+/* Helpers for DP link training */
static u8 dp_link_status(u8 link_status[DP_LINK_STATUS_SIZE], int r)
{
return link_status[r - DP_LANE0_1_STATUS];
@@ -67,6 +68,7 @@ bool drm_dp_channel_eq_ok(u8 link_status[DP_LINK_STATUS_SIZE],
}
return true;
}
+EXPORT_SYMBOL(drm_dp_channel_eq_ok);
bool drm_dp_clock_recovery_ok(u8 link_status[DP_LINK_STATUS_SIZE],
int lane_count)
@@ -81,6 +83,7 @@ bool drm_dp_clock_recovery_ok(u8 link_status[DP_LINK_STATUS_SIZE],
}
return true;
}
+EXPORT_SYMBOL(drm_dp_clock_recovery_ok);
u8 drm_dp_get_adjust_request_voltage(u8 link_status[DP_LINK_STATUS_SIZE],
int lane)
@@ -93,6 +96,7 @@ u8 drm_dp_get_adjust_request_voltage(u8 link_status[DP_LINK_STATUS_SIZE],
return ((l >> s) & 0x3) << DP_TRAIN_VOLTAGE_SWING_SHIFT;
}
+EXPORT_SYMBOL(drm_dp_get_adjust_request_voltage);
u8 drm_dp_get_adjust_request_pre_emphasis(u8 link_status[DP_LINK_STATUS_SIZE],
int lane)
@@ -105,20 +109,23 @@ u8 drm_dp_get_adjust_request_pre_emphasis(u8 link_status[DP_LINK_STATUS_SIZE],
return ((l >> s) & 0x3) << DP_TRAIN_PRE_EMPHASIS_SHIFT;
}
+EXPORT_SYMBOL(drm_dp_get_adjust_request_pre_emphasis);
void drm_dp_link_train_clock_recovery_delay(u8 dpcd[DP_RECEIVER_CAP_SIZE]) {
if (dpcd[DP_TRAINING_AUX_RD_INTERVAL] == 0)
- DRM_UDELAY(100);
+ udelay(100);
else
- DRM_MDELAY(dpcd[DP_TRAINING_AUX_RD_INTERVAL] * 4);
+ mdelay(dpcd[DP_TRAINING_AUX_RD_INTERVAL] * 4);
}
+EXPORT_SYMBOL(drm_dp_link_train_clock_recovery_delay);
void drm_dp_link_train_channel_eq_delay(u8 dpcd[DP_RECEIVER_CAP_SIZE]) {
if (dpcd[DP_TRAINING_AUX_RD_INTERVAL] == 0)
- DRM_UDELAY(400);
+ udelay(400);
else
- DRM_MDELAY(dpcd[DP_TRAINING_AUX_RD_INTERVAL] * 4);
+ mdelay(dpcd[DP_TRAINING_AUX_RD_INTERVAL] * 4);
}
+EXPORT_SYMBOL(drm_dp_link_train_channel_eq_delay);
u8 drm_dp_link_rate_to_bw_code(int link_rate)
{
@@ -132,6 +139,7 @@ u8 drm_dp_link_rate_to_bw_code(int link_rate)
return DP_LINK_BW_5_4;
}
}
+EXPORT_SYMBOL(drm_dp_link_rate_to_bw_code);
int drm_dp_bw_code_to_link_rate(u8 link_bw)
{
@@ -145,3 +153,4 @@ int drm_dp_bw_code_to_link_rate(u8 link_bw)
return 540000;
}
}
+EXPORT_SYMBOL(drm_dp_bw_code_to_link_rate);
diff --git a/sys/dev/drm2/drm_dp_iic_helper.c b/sys/dev/drm2/drm_dp_iic_helper.c
index c4e5803..492e2f9 100644
--- a/sys/dev/drm2/drm_dp_iic_helper.c
+++ b/sys/dev/drm2/drm_dp_iic_helper.c
@@ -41,7 +41,9 @@ iic_dp_aux_transaction(device_t idev, int mode, uint8_t write_byte,
aux_data = device_get_softc(idev);
ret = (*aux_data->aux_ch)(idev, mode, write_byte, read_byte);
- return (ret);
+ if (ret < 0)
+ return (ret);
+ return (0);
}
/*
@@ -106,7 +108,7 @@ iic_dp_aux_put_byte(device_t idev, u8 byte)
aux_data = device_get_softc(idev);
if (!aux_data->running)
- return (EIO);
+ return (-EIO);
ret = iic_dp_aux_transaction(idev, MODE_I2C_WRITE, byte, NULL);
return (ret);
@@ -125,7 +127,7 @@ iic_dp_aux_get_byte(device_t idev, u8 *byte_ret)
aux_data = device_get_softc(idev);
if (!aux_data->running)
- return (EIO);
+ return (-EIO);
ret = iic_dp_aux_transaction(idev, MODE_I2C_READ, 0, byte_ret);
return (ret);
@@ -167,7 +169,7 @@ iic_dp_aux_xfer(device_t idev, struct iic_msg *msgs, uint32_t num)
}
iic_dp_aux_stop(idev, reading);
DRM_DEBUG_KMS("dp_aux_xfer return %d\n", ret);
- return (ret);
+ return (-ret);
}
static void
@@ -183,7 +185,7 @@ iic_dp_aux_reset(device_t idev, u_char speed, u_char addr, u_char *oldaddr)
{
iic_dp_aux_reset_bus(idev);
- return (0);
+ return (0);
}
static int
@@ -255,7 +257,7 @@ iic_dp_aux_add_bus(device_t dev, const char *name,
*adapter = data->port;
}
mtx_unlock(&Giant);
- return (error);
+ return (-error);
}
static device_method_t drm_iic_dp_aux_methods[] = {
diff --git a/sys/dev/drm2/drm_drawable.c b/sys/dev/drm2/drm_drawable.c
deleted file mode 100644
index e8c4e02..0000000
--- a/sys/dev/drm2/drm_drawable.c
+++ /dev/null
@@ -1,173 +0,0 @@
-/*-
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * 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.
- *
- * Authors:
- * Rickard E. (Rik) Faith <faith@valinux.com>
- * Gareth Hughes <gareth@valinux.com>
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-/** @file drm_drawable.c
- * This file implements ioctls to store information along with DRM drawables,
- * such as the current set of cliprects for vblank-synced buffer swaps.
- */
-
-#include <dev/drm2/drmP.h>
-
-struct bsd_drm_drawable_info {
- struct drm_drawable_info info;
- int handle;
- RB_ENTRY(bsd_drm_drawable_info) tree;
-};
-
-static int
-drm_drawable_compare(struct bsd_drm_drawable_info *a,
- struct bsd_drm_drawable_info *b)
-{
- if (a->handle > b->handle)
- return 1;
- if (a->handle < b->handle)
- return -1;
- return 0;
-}
-
-RB_GENERATE_STATIC(drawable_tree, bsd_drm_drawable_info, tree,
- drm_drawable_compare);
-
-struct drm_drawable_info *
-drm_get_drawable_info(struct drm_device *dev, int handle)
-{
- struct bsd_drm_drawable_info find, *result;
-
- find.handle = handle;
- result = RB_FIND(drawable_tree, &dev->drw_head, &find);
-
- return &result->info;
-}
-
-int drm_adddraw(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
- struct drm_draw *draw = data;
- struct bsd_drm_drawable_info *info;
-
- info = malloc(sizeof(struct bsd_drm_drawable_info), DRM_MEM_DRAWABLE,
- M_NOWAIT | M_ZERO);
- if (info == NULL)
- return ENOMEM;
-
- info->handle = alloc_unr(dev->drw_unrhdr);
- DRM_SPINLOCK(&dev->drw_lock);
- RB_INSERT(drawable_tree, &dev->drw_head, info);
- draw->handle = info->handle;
- DRM_SPINUNLOCK(&dev->drw_lock);
-
- DRM_DEBUG("%d\n", draw->handle);
-
- return 0;
-}
-
-int drm_rmdraw(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
- struct drm_draw *draw = (struct drm_draw *)data;
- struct drm_drawable_info *info;
-
- DRM_SPINLOCK(&dev->drw_lock);
- info = drm_get_drawable_info(dev, draw->handle);
- if (info != NULL) {
- RB_REMOVE(drawable_tree, &dev->drw_head,
- (struct bsd_drm_drawable_info *)info);
- DRM_SPINUNLOCK(&dev->drw_lock);
- free_unr(dev->drw_unrhdr, draw->handle);
- free(info->rects, DRM_MEM_DRAWABLE);
- free(info, DRM_MEM_DRAWABLE);
- return 0;
- } else {
- DRM_SPINUNLOCK(&dev->drw_lock);
- return EINVAL;
- }
-}
-
-int drm_update_draw(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_drawable_info *info;
- struct drm_update_draw *update = (struct drm_update_draw *)data;
- int ret;
-
- info = drm_get_drawable_info(dev, update->handle);
- if (info == NULL)
- return EINVAL;
-
- switch (update->type) {
- case DRM_DRAWABLE_CLIPRECTS:
- DRM_SPINLOCK(&dev->drw_lock);
- if (update->num != info->num_rects) {
- free(info->rects, DRM_MEM_DRAWABLE);
- info->rects = NULL;
- info->num_rects = 0;
- }
- if (update->num == 0) {
- DRM_SPINUNLOCK(&dev->drw_lock);
- return 0;
- }
- if (info->rects == NULL) {
- info->rects = malloc(sizeof(*info->rects) *
- update->num, DRM_MEM_DRAWABLE, M_NOWAIT);
- if (info->rects == NULL) {
- DRM_SPINUNLOCK(&dev->drw_lock);
- return ENOMEM;
- }
- info->num_rects = update->num;
- }
- /* For some reason the pointer arg is unsigned long long. */
- ret = copyin((void *)(intptr_t)update->data, info->rects,
- sizeof(*info->rects) * info->num_rects);
- DRM_SPINUNLOCK(&dev->drw_lock);
- return ret;
- default:
- return EINVAL;
- }
-}
-
-void drm_drawable_free_all(struct drm_device *dev)
-{
- struct bsd_drm_drawable_info *info, *next;
-
- DRM_SPINLOCK(&dev->drw_lock);
- for (info = RB_MIN(drawable_tree, &dev->drw_head);
- info != NULL ; info = next) {
- next = RB_NEXT(drawable_tree, &dev->drw_head, info);
- RB_REMOVE(drawable_tree, &dev->drw_head,
- (struct bsd_drm_drawable_info *)info);
- DRM_SPINUNLOCK(&dev->drw_lock);
- free_unr(dev->drw_unrhdr, info->handle);
- free(info->info.rects, DRM_MEM_DRAWABLE);
- free(info, DRM_MEM_DRAWABLE);
- DRM_SPINLOCK(&dev->drw_lock);
- }
- DRM_SPINUNLOCK(&dev->drw_lock);
-}
diff --git a/sys/dev/drm2/drm_drv.c b/sys/dev/drm2/drm_drv.c
index 1e6626f..f4431a7 100644
--- a/sys/dev/drm2/drm_drv.c
+++ b/sys/dev/drm2/drm_drv.c
@@ -1,4 +1,27 @@
-/*-
+/**
+ * \file drm_drv.c
+ * Generic driver template
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ *
+ * To use this template, you must at least define the following (samples
+ * given for the MGA driver):
+ *
+ * \code
+ * #define DRIVER_AUTHOR "VA Linux Systems, Inc."
+ *
+ * #define DRIVER_NAME "mga"
+ * #define DRIVER_DESC "Matrox G200/G400"
+ * #define DRIVER_DATE "20001127"
+ *
+ * #define drm_x mga_##x
+ * \endcode
+ */
+
+/*
+ * Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com
+ *
* Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
* All Rights Reserved.
@@ -21,94 +44,35 @@
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Rickard E. (Rik) Faith <faith@valinux.com>
- * Gareth Hughes <gareth@valinux.com>
- *
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-/** @file drm_drv.c
- * The catch-all file for DRM device support, including module setup/teardown,
- * open/close, and ioctl dispatch.
- */
-
-#include <sys/limits.h>
#include <sys/sysent.h>
+
#include <dev/drm2/drmP.h>
-#include <dev/drm2/drm.h>
#include <dev/drm2/drm_core.h>
#include <dev/drm2/drm_global.h>
-#include <dev/drm2/drm_sarea.h>
-#include <dev/drm2/drm_mode.h>
-
-#ifdef DRM_DEBUG_DEFAULT_ON
-int drm_debug_flag = (DRM_DEBUGBITS_DEBUG | DRM_DEBUGBITS_KMS |
- DRM_DEBUGBITS_FAILED_IOCTL);
-#else
-int drm_debug_flag = 0;
-#endif
-int drm_notyet_flag = 0;
-
-unsigned int drm_vblank_offdelay = 5000; /* Default to 5000 msecs. */
-unsigned int drm_timestamp_precision = 20; /* Default to 20 usecs. */
-
-/*
- * Default to use monotonic timestamps for wait-for-vblank and page-flip
- * complete events.
- */
-unsigned int drm_timestamp_monotonic = 1;
-static int drm_load(struct drm_device *dev);
-static void drm_unload(struct drm_device *dev);
-static drm_pci_id_list_t *drm_find_description(int vendor, int device,
- drm_pci_id_list_t *idlist);
-static int drm_mmap_single(struct cdev *kdev, vm_ooffset_t *offset,
- vm_size_t size, struct vm_object **obj_res, int nprot);
+struct sx drm_global_mutex;
-static int
-drm_modevent(module_t mod, int type, void *data)
-{
-
- switch (type) {
- case MOD_LOAD:
- TUNABLE_INT_FETCH("drm.debug", &drm_debug_flag);
- TUNABLE_INT_FETCH("drm.notyet", &drm_notyet_flag);
- break;
- }
- return (0);
-}
-
-static moduledata_t drm_mod = {
- "drmn",
- drm_modevent,
- 0
-};
-DECLARE_MODULE(drmn, drm_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);
-MODULE_VERSION(drmn, 1);
-MODULE_DEPEND(drmn, agp, 1, 1, 1);
-MODULE_DEPEND(drmn, pci, 1, 1, 1);
-MODULE_DEPEND(drmn, mem, 1, 1, 1);
-MODULE_DEPEND(drmn, iicbus, 1, 1, 1);
-
-static drm_ioctl_desc_t drm_ioctls[256] = {
- DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, 0),
+/** Ioctl table */
+static struct drm_ioctl_desc drm_ioctls[] = {
+ DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0),
DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0),
DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, 0),
- DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, 0),
- DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, 0),
+ DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_GET_CAP, drm_getcap, DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER),
DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_UNBLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_AUTH|DRM_MASTER),
DRM_IOCTL_DEF(DRM_IOCTL_ADD_MAP, drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_RM_MAP, drm_rmmap_ioctl, DRM_AUTH),
@@ -127,8 +91,8 @@ static drm_ioctl_desc_t drm_ioctls[256] = {
DRM_IOCTL_DEF(DRM_IOCTL_NEW_CTX, drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_RES_CTX, drm_resctx, DRM_AUTH),
- DRM_IOCTL_DEF(DRM_IOCTL_ADD_DRAW, drm_adddraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_RM_DRAW, drm_rmdraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF(DRM_IOCTL_ADD_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF(DRM_IOCTL_RM_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_LOCK, drm_lock, DRM_AUTH),
DRM_IOCTL_DEF(DRM_IOCTL_UNLOCK, drm_unlock, DRM_AUTH),
@@ -140,10 +104,12 @@ static drm_ioctl_desc_t drm_ioctls[256] = {
DRM_IOCTL_DEF(DRM_IOCTL_INFO_BUFS, drm_infobufs, DRM_AUTH),
DRM_IOCTL_DEF(DRM_IOCTL_MAP_BUFS, drm_mapbufs, DRM_AUTH),
DRM_IOCTL_DEF(DRM_IOCTL_FREE_BUFS, drm_freebufs, DRM_AUTH),
- DRM_IOCTL_DEF(DRM_IOCTL_DMA, drm_dma, DRM_AUTH),
+ /* The DRM_IOCTL_DMA ioctl should be defined by the driver. */
+ DRM_IOCTL_DEF(DRM_IOCTL_DMA, NULL, DRM_AUTH),
DRM_IOCTL_DEF(DRM_IOCTL_CONTROL, drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+#if __OS_HAS_AGP
DRM_IOCTL_DEF(DRM_IOCTL_AGP_ACQUIRE, drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_AGP_RELEASE, drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_AGP_ENABLE, drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
@@ -152,711 +118,253 @@ static drm_ioctl_desc_t drm_ioctls[256] = {
DRM_IOCTL_DEF(DRM_IOCTL_AGP_FREE, drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_AGP_BIND, drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_AGP_UNBIND, drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+#endif
DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_sg_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+
DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, DRM_UNLOCKED),
+
DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_modeset_ctl, 0),
- DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_update_draw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+
+ DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+
+#ifdef FREEBSD_NOTYET
+ DRM_IOCTL_DEF(DRM_IOCTL_PRIME_HANDLE_TO_FD, drm_prime_handle_to_fd_ioctl, DRM_AUTH|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_PRIME_FD_TO_HANDLE, drm_prime_fd_to_handle_ioctl, DRM_AUTH|DRM_UNLOCKED),
+#endif /* FREEBSD_NOTYET */
+
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE, drm_mode_getplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE, drm_mode_getplane, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPLANE, drm_mode_setplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_MASTER|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_mode_attachmode_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_mode_detachmode_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_MASTER | DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_mode_connector_property_set_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB2, drm_mode_addfb2, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB2, drm_mode_addfb2, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
};
-static struct cdevsw drm_cdevsw = {
- .d_version = D_VERSION,
- .d_open = drm_open,
- .d_read = drm_read,
- .d_ioctl = drm_ioctl,
- .d_poll = drm_poll,
- .d_mmap = drm_mmap,
- .d_mmap_single = drm_mmap_single,
- .d_name = "drm",
- .d_flags = D_TRACKCLOSE
-};
-
-static int drm_msi = 1; /* Enable by default. */
-TUNABLE_INT("hw.drm.msi", &drm_msi);
-SYSCTL_NODE(_hw, OID_AUTO, drm, CTLFLAG_RW, NULL, "DRM device");
-SYSCTL_INT(_hw_drm, OID_AUTO, msi, CTLFLAG_RDTUN, &drm_msi, 1,
- "Enable MSI interrupts for drm devices");
-
-static struct drm_msi_blacklist_entry drm_msi_blacklist[] = {
- {0x8086, 0x2772}, /* Intel i945G */ \
- {0x8086, 0x27A2}, /* Intel i945GM */ \
- {0x8086, 0x27AE}, /* Intel i945GME */ \
- {0, 0}
-};
-
-static int drm_msi_is_blacklisted(struct drm_device *dev, unsigned long flags)
-{
- int i = 0;
-
- if (dev->driver->use_msi != NULL) {
- int use_msi;
-
- use_msi = dev->driver->use_msi(dev, flags);
-
- return (!use_msi);
- }
-
- /* TODO: Maybe move this to a callback in i915? */
- for (i = 0; drm_msi_blacklist[i].vendor != 0; i++) {
- if ((drm_msi_blacklist[i].vendor == dev->pci_vendor) &&
- (drm_msi_blacklist[i].device == dev->pci_device)) {
- return 1;
- }
- }
-
- return 0;
-}
-
-int drm_probe(device_t kdev, drm_pci_id_list_t *idlist)
-{
- drm_pci_id_list_t *id_entry;
- int vendor, device;
-
- vendor = pci_get_vendor(kdev);
- device = pci_get_device(kdev);
-
- if (pci_get_class(kdev) != PCIC_DISPLAY
- || (pci_get_subclass(kdev) != PCIS_DISPLAY_VGA &&
- pci_get_subclass(kdev) != PCIS_DISPLAY_OTHER))
- return ENXIO;
-
- id_entry = drm_find_description(vendor, device, idlist);
- if (id_entry != NULL) {
- if (!device_get_desc(kdev)) {
- DRM_DEBUG("desc : %s\n", device_get_desc(kdev));
- device_set_desc(kdev, id_entry->name);
- }
- return 0;
- }
-
- return ENXIO;
-}
-
-int drm_attach(device_t kdev, drm_pci_id_list_t *idlist)
-{
- struct drm_device *dev;
- drm_pci_id_list_t *id_entry;
- int error, msicount;
-
- dev = device_get_softc(kdev);
-
- dev->device = kdev;
-
- dev->pci_domain = pci_get_domain(dev->device);
- dev->pci_bus = pci_get_bus(dev->device);
- dev->pci_slot = pci_get_slot(dev->device);
- dev->pci_func = pci_get_function(dev->device);
-
- dev->pci_vendor = pci_get_vendor(dev->device);
- dev->pci_device = pci_get_device(dev->device);
- dev->pci_subvendor = pci_get_subvendor(dev->device);
- dev->pci_subdevice = pci_get_subdevice(dev->device);
-
- id_entry = drm_find_description(dev->pci_vendor,
- dev->pci_device, idlist);
- dev->id_entry = id_entry;
-
- if (drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) {
- if (drm_msi &&
- !drm_msi_is_blacklisted(dev, dev->id_entry->driver_private)) {
- msicount = pci_msi_count(dev->device);
- DRM_DEBUG("MSI count = %d\n", msicount);
- if (msicount > 1)
- msicount = 1;
-
- if (pci_alloc_msi(dev->device, &msicount) == 0) {
- DRM_INFO("MSI enabled %d message(s)\n",
- msicount);
- dev->msi_enabled = 1;
- dev->irqrid = 1;
- }
- }
-
- dev->irqr = bus_alloc_resource_any(dev->device, SYS_RES_IRQ,
- &dev->irqrid, RF_SHAREABLE);
- if (!dev->irqr) {
- return (ENOENT);
- }
-
- dev->irq = (int) rman_get_start(dev->irqr);
- }
-
- mtx_init(&dev->dev_lock, "drmdev", NULL, MTX_DEF);
- mtx_init(&dev->irq_lock, "drmirq", NULL, MTX_DEF);
- mtx_init(&dev->vbl_lock, "drmvbl", NULL, MTX_DEF);
- mtx_init(&dev->drw_lock, "drmdrw", NULL, MTX_DEF);
- mtx_init(&dev->event_lock, "drmev", NULL, MTX_DEF);
- sx_init(&dev->dev_struct_lock, "drmslk");
-
- error = drm_load(dev);
- if (error)
- goto error;
-
- error = drm_create_cdevs(kdev);
- if (error)
- goto error;
-
- return (error);
-error:
- if (dev->irqr) {
- bus_release_resource(dev->device, SYS_RES_IRQ,
- dev->irqrid, dev->irqr);
- }
- if (dev->msi_enabled) {
- pci_release_msi(dev->device);
- }
- return (error);
-}
-
-int
-drm_create_cdevs(device_t kdev)
-{
- struct drm_device *dev;
- int error, unit;
-
- unit = device_get_unit(kdev);
- dev = device_get_softc(kdev);
-
- error = make_dev_p(MAKEDEV_WAITOK | MAKEDEV_CHECKNAME, &dev->devnode,
- &drm_cdevsw, 0, DRM_DEV_UID, DRM_DEV_GID,
- DRM_DEV_MODE, "dri/card%d", unit);
- if (error == 0)
- dev->devnode->si_drv1 = dev;
- return (error);
-}
-
-int drm_detach(device_t kdev)
-{
- struct drm_device *dev;
-
- dev = device_get_softc(kdev);
- drm_unload(dev);
- if (dev->irqr) {
- bus_release_resource(dev->device, SYS_RES_IRQ, dev->irqrid,
- dev->irqr);
- if (dev->msi_enabled) {
- pci_release_msi(dev->device);
- DRM_INFO("MSI released\n");
- }
- }
- return (0);
-}
-
-#ifndef DRM_DEV_NAME
-#define DRM_DEV_NAME "drm"
+#ifdef COMPAT_FREEBSD32
+extern struct drm_ioctl_desc drm_compat_ioctls[];
#endif
-devclass_t drm_devclass;
-
-drm_pci_id_list_t *drm_find_description(int vendor, int device,
- drm_pci_id_list_t *idlist)
-{
- int i = 0;
-
- for (i = 0; idlist[i].vendor != 0; i++) {
- if ((idlist[i].vendor == vendor) &&
- ((idlist[i].device == device) ||
- (idlist[i].device == 0))) {
- return &idlist[i];
- }
- }
- return NULL;
-}
-
-static int drm_firstopen(struct drm_device *dev)
-{
- drm_local_map_t *map;
- int i;
-
- DRM_LOCK_ASSERT(dev);
-
- /* prebuild the SAREA */
- i = drm_addmap(dev, 0, SAREA_MAX, _DRM_SHM,
- _DRM_CONTAINS_LOCK, &map);
- if (i != 0)
- return i;
-
- if (dev->driver->firstopen)
- dev->driver->firstopen(dev);
-
- dev->buf_use = 0;
-
- if (drm_core_check_feature(dev, DRIVER_HAVE_DMA)) {
- i = drm_dma_setup(dev);
- if (i != 0)
- return i;
- }
-
- for (i = 0; i < DRM_HASH_SIZE; i++) {
- dev->magiclist[i].head = NULL;
- dev->magiclist[i].tail = NULL;
- }
-
- dev->lock.lock_queue = 0;
- if (!drm_core_check_feature(dev, DRIVER_MODESET))
- dev->irq_enabled = 0;
- dev->context_flag = 0;
- dev->last_context = 0;
- dev->if_version = 0;
-
- dev->buf_sigio = NULL;
-
- DRM_DEBUG("\n");
+#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
- return 0;
-}
-
-static int drm_lastclose(struct drm_device *dev)
+/**
+ * Take down the DRM device.
+ *
+ * \param dev DRM device structure.
+ *
+ * Frees every resource in \p dev.
+ *
+ * \sa drm_device
+ */
+int drm_lastclose(struct drm_device * dev)
{
- drm_magic_entry_t *pt, *next;
- drm_local_map_t *map, *mapsave;
- int i;
-
- DRM_LOCK_ASSERT(dev);
+#ifdef __linux__
+ struct drm_vma_entry *vma, *vma_temp;
+#endif
DRM_DEBUG("\n");
- if (dev->driver->lastclose != NULL)
+ if (dev->driver->lastclose)
dev->driver->lastclose(dev);
+ DRM_DEBUG("driver lastclose completed\n");
- if (!drm_core_check_feature(dev, DRIVER_MODESET) && dev->irq_enabled)
+ if (dev->irq_enabled && !drm_core_check_feature(dev, DRIVER_MODESET))
drm_irq_uninstall(dev);
- if (dev->unique) {
- free(dev->unique, DRM_MEM_DRIVER);
- dev->unique = NULL;
- dev->unique_len = 0;
- }
- /* Clear pid list */
- for (i = 0; i < DRM_HASH_SIZE; i++) {
- for (pt = dev->magiclist[i].head; pt; pt = next) {
- next = pt->next;
- free(pt, DRM_MEM_MAGIC);
- }
- dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
- }
-
- DRM_UNLOCK(dev);
- drm_drawable_free_all(dev);
DRM_LOCK(dev);
/* Clear AGP information */
- if (dev->agp) {
- drm_agp_mem_t *entry;
- drm_agp_mem_t *nexte;
+ if (drm_core_has_AGP(dev) && dev->agp &&
+ !drm_core_check_feature(dev, DRIVER_MODESET)) {
+ struct drm_agp_mem *entry, *tempe;
- /* Remove AGP resources, but leave dev->agp intact until
- * drm_unload is called.
- */
- for (entry = dev->agp->memory; entry; entry = nexte) {
- nexte = entry->next;
+ /* Remove AGP resources, but leave dev->agp
+ intact until drv_cleanup is called. */
+ list_for_each_entry_safe(entry, tempe, &dev->agp->memory, head) {
if (entry->bound)
- drm_agp_unbind_memory(entry->handle);
- drm_agp_free_memory(entry->handle);
+ drm_unbind_agp(entry->memory);
+ drm_free_agp(entry->memory, entry->pages);
free(entry, DRM_MEM_AGPLISTS);
}
- dev->agp->memory = NULL;
+ INIT_LIST_HEAD(&dev->agp->memory);
if (dev->agp->acquired)
drm_agp_release(dev);
dev->agp->acquired = 0;
- dev->agp->enabled = 0;
+ dev->agp->enabled = 0;
}
- if (dev->sg != NULL) {
+ if (drm_core_check_feature(dev, DRIVER_SG) && dev->sg &&
+ !drm_core_check_feature(dev, DRIVER_MODESET)) {
drm_sg_cleanup(dev->sg);
dev->sg = NULL;
}
- TAILQ_FOREACH_SAFE(map, &dev->maplist, link, mapsave) {
- if (!(map->flags & _DRM_DRIVER))
- drm_rmmap(dev, map);
+#ifdef __linux__
+ /* Clear vma list (only built for debugging) */
+ list_for_each_entry_safe(vma, vma_temp, &dev->vmalist, head) {
+ list_del(&vma->head);
+ kfree(vma);
}
+#endif
- drm_dma_takedown(dev);
- if (dev->lock.hw_lock) {
- dev->lock.hw_lock = NULL; /* SHM removed */
- dev->lock.file_priv = NULL;
- DRM_WAKEUP_INT((void *)&dev->lock.lock_queue);
- }
+ if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) &&
+ !drm_core_check_feature(dev, DRIVER_MODESET))
+ drm_dma_takedown(dev);
+ DRM_UNLOCK(dev);
+
+ DRM_DEBUG("lastclose completed\n");
return 0;
}
-static int drm_load(struct drm_device *dev)
-{
- int i, retcode;
-
- DRM_DEBUG("\n");
-
- TAILQ_INIT(&dev->maplist);
- dev->map_unrhdr = new_unrhdr(1, ((1 << DRM_MAP_HANDLE_BITS) - 1), NULL);
- if (dev->map_unrhdr == NULL) {
- DRM_ERROR("Couldn't allocate map number allocator\n");
- return EINVAL;
- }
-
-
- drm_mem_init();
- drm_sysctl_init(dev);
- TAILQ_INIT(&dev->files);
-
- dev->counters = 6;
- dev->types[0] = _DRM_STAT_LOCK;
- dev->types[1] = _DRM_STAT_OPENS;
- dev->types[2] = _DRM_STAT_CLOSES;
- dev->types[3] = _DRM_STAT_IOCTLS;
- dev->types[4] = _DRM_STAT_LOCKS;
- dev->types[5] = _DRM_STAT_UNLOCKS;
-
- for (i = 0; i < DRM_ARRAY_SIZE(dev->counts); i++)
- atomic_set(&dev->counts[i], 0);
-
- INIT_LIST_HEAD(&dev->vblank_event_list);
-
- if (drm_core_has_AGP(dev)) {
- if (drm_device_is_agp(dev))
- dev->agp = drm_agp_init();
- if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP) &&
- dev->agp == NULL) {
- DRM_ERROR("Card isn't AGP, or couldn't initialize "
- "AGP.\n");
- retcode = ENOMEM;
- goto error;
- }
- if (dev->agp != NULL && dev->agp->info.ai_aperture_base != 0) {
- if (drm_mtrr_add(dev->agp->info.ai_aperture_base,
- dev->agp->info.ai_aperture_size, DRM_MTRR_WC) == 0)
- dev->agp->mtrr = 1;
- }
- }
+#ifdef __linux__
+/** File operations structure */
+static const struct file_operations drm_stub_fops = {
+ .owner = THIS_MODULE,
+ .open = drm_stub_open,
+ .llseek = noop_llseek,
+};
+#endif
- retcode = drm_ctxbitmap_init(dev);
- if (retcode != 0) {
- DRM_ERROR("Cannot allocate memory for context bitmap.\n");
- goto error;
- }
+static int __init drm_core_init(void)
+{
- dev->drw_unrhdr = new_unrhdr(1, INT_MAX, NULL);
- if (dev->drw_unrhdr == NULL) {
- DRM_ERROR("Couldn't allocate drawable number allocator\n");
- retcode = ENOMEM;
- goto error;
- }
+ sx_init(&drm_global_mutex, "drm_global_mutex");
- if (dev->driver->driver_features & DRIVER_GEM) {
- retcode = drm_gem_init(dev);
- if (retcode != 0) {
- DRM_ERROR("Cannot initialize graphics execution "
- "manager (GEM)\n");
- goto error1;
- }
- }
+ drm_global_init();
- if (dev->driver->load != NULL) {
- DRM_LOCK(dev);
- /* Shared code returns -errno. */
- retcode = -dev->driver->load(dev,
- dev->id_entry->driver_private);
- if (pci_enable_busmaster(dev->device))
- DRM_ERROR("Request to enable bus-master failed.\n");
- DRM_UNLOCK(dev);
- if (retcode != 0)
- goto error1;
- }
+#if DRM_LINUX
+ linux_ioctl_register_handler(&drm_handler);
+#endif /* DRM_LINUX */
DRM_INFO("Initialized %s %d.%d.%d %s\n",
- dev->driver->name,
- dev->driver->major,
- dev->driver->minor,
- dev->driver->patchlevel,
- dev->driver->date);
-
+ CORE_NAME, CORE_MAJOR, CORE_MINOR, CORE_PATCHLEVEL, CORE_DATE);
return 0;
-
-error1:
- delete_unrhdr(dev->drw_unrhdr);
- drm_gem_destroy(dev);
-error:
- drm_ctxbitmap_cleanup(dev);
- drm_sysctl_cleanup(dev);
- DRM_LOCK(dev);
- drm_lastclose(dev);
- DRM_UNLOCK(dev);
- if (dev->devnode != NULL)
- destroy_dev(dev->devnode);
-
- mtx_destroy(&dev->drw_lock);
- mtx_destroy(&dev->vbl_lock);
- mtx_destroy(&dev->irq_lock);
- mtx_destroy(&dev->dev_lock);
- mtx_destroy(&dev->event_lock);
- sx_destroy(&dev->dev_struct_lock);
-
- return retcode;
}
-static void drm_unload(struct drm_device *dev)
+static void __exit drm_core_exit(void)
{
- int i;
-
- DRM_DEBUG("\n");
-
- drm_sysctl_cleanup(dev);
- if (dev->devnode != NULL)
- destroy_dev(dev->devnode);
-
- drm_ctxbitmap_cleanup(dev);
-
- if (dev->driver->driver_features & DRIVER_GEM)
- drm_gem_destroy(dev);
-
- if (dev->agp && dev->agp->mtrr) {
- int __unused retcode;
-
- retcode = drm_mtrr_del(0, dev->agp->info.ai_aperture_base,
- dev->agp->info.ai_aperture_size, DRM_MTRR_WC);
- DRM_DEBUG("mtrr_del = %d", retcode);
- }
-
- drm_vblank_cleanup(dev);
-
- DRM_LOCK(dev);
- drm_lastclose(dev);
- DRM_UNLOCK(dev);
-
- /* Clean up PCI resources allocated by drm_bufs.c. We're not really
- * worried about resource consumption while the DRM is inactive (between
- * lastclose and firstopen or unload) because these aren't actually
- * taking up KVA, just keeping the PCI resource allocated.
- */
- for (i = 0; i < DRM_MAX_PCI_RESOURCE; i++) {
- if (dev->pcir[i] == NULL)
- continue;
- bus_release_resource(dev->device, SYS_RES_MEMORY,
- dev->pcirid[i], dev->pcir[i]);
- dev->pcir[i] = NULL;
- }
-
- if (dev->agp) {
- free(dev->agp, DRM_MEM_AGPLISTS);
- dev->agp = NULL;
- }
-
- if (dev->driver->unload != NULL) {
- DRM_LOCK(dev);
- dev->driver->unload(dev);
- DRM_UNLOCK(dev);
- }
- delete_unrhdr(dev->drw_unrhdr);
- delete_unrhdr(dev->map_unrhdr);
-
- drm_mem_uninit();
+#if DRM_LINUX
+ linux_ioctl_unregister_handler(&drm_handler);
+#endif /* DRM_LINUX */
- if (pci_disable_busmaster(dev->device))
- DRM_ERROR("Request to disable bus-master failed.\n");
+ drm_global_release();
- mtx_destroy(&dev->drw_lock);
- mtx_destroy(&dev->vbl_lock);
- mtx_destroy(&dev->irq_lock);
- mtx_destroy(&dev->dev_lock);
- mtx_destroy(&dev->event_lock);
- sx_destroy(&dev->dev_struct_lock);
+ sx_destroy(&drm_global_mutex);
}
-int drm_version(struct drm_device *dev, void *data, struct drm_file *file_priv)
+SYSINIT(drm_register, SI_SUB_KLD, SI_ORDER_MIDDLE,
+ drm_core_init, NULL);
+SYSUNINIT(drm_unregister, SI_SUB_KLD, SI_ORDER_MIDDLE,
+ drm_core_exit, NULL);
+
+/**
+ * Copy and IOCTL return string to user space
+ */
+static int drm_copy_field(char *buf, size_t *buf_len, const char *value)
{
- struct drm_version *version = data;
int len;
-#define DRM_COPY( name, value ) \
- len = strlen( value ); \
- if ( len > name##_len ) len = name##_len; \
- name##_len = strlen( value ); \
- if ( len && name ) { \
- if ( DRM_COPY_TO_USER( name, value, len ) ) \
- return EFAULT; \
- }
+ /* don't overflow userbuf */
+ len = strlen(value);
+ if (len > *buf_len)
+ len = *buf_len;
- version->version_major = dev->driver->major;
- version->version_minor = dev->driver->minor;
- version->version_patchlevel = dev->driver->patchlevel;
-
- DRM_COPY(version->name, dev->driver->name);
- DRM_COPY(version->date, dev->driver->date);
- DRM_COPY(version->desc, dev->driver->desc);
+ /* let userspace know exact length of driver value (which could be
+ * larger than the userspace-supplied buffer) */
+ *buf_len = strlen(value);
+ /* finally, try filling in the userbuf */
+ if (len && buf)
+ if (copy_to_user(buf, value, len))
+ return -EFAULT;
return 0;
}
-int
-drm_open(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p)
-{
- struct drm_device *dev;
- int retcode;
-
- dev = kdev->si_drv1;
- if (dev == NULL)
- return (ENXIO);
-
- DRM_DEBUG("open_count = %d\n", dev->open_count);
-
- retcode = drm_open_helper(kdev, flags, fmt, p, dev);
-
- if (retcode == 0) {
- atomic_inc(&dev->counts[_DRM_STAT_OPENS]);
- DRM_LOCK(dev);
- mtx_lock(&Giant);
- device_busy(dev->device);
- mtx_unlock(&Giant);
- if (!dev->open_count++)
- retcode = drm_firstopen(dev);
- DRM_UNLOCK(dev);
- }
-
- return (retcode);
-}
-
-void drm_close(void *data)
+/**
+ * Get version information
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_version structure.
+ * \return zero on success or negative number on failure.
+ *
+ * Fills in the version information in \p arg.
+ */
+int drm_version(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
- struct drm_file *file_priv = data;
- struct drm_device *dev = file_priv->dev;
- int retcode = 0;
-
- DRM_DEBUG("open_count = %d\n", dev->open_count);
-
- DRM_LOCK(dev);
-
- if (dev->driver->preclose != NULL)
- dev->driver->preclose(dev, file_priv);
-
- /* ========================================================
- * Begin inline drm_release
- */
-
- DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
- DRM_CURRENTPID, (long)dev->device, dev->open_count);
-
- if (dev->driver->driver_features & DRIVER_GEM)
- drm_gem_release(dev, file_priv);
-
- if (dev->lock.hw_lock && _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)
- && dev->lock.file_priv == file_priv) {
- DRM_DEBUG("Process %d dead, freeing lock for context %d\n",
- DRM_CURRENTPID,
- _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
- if (dev->driver->reclaim_buffers_locked != NULL)
- dev->driver->reclaim_buffers_locked(dev, file_priv);
-
- drm_lock_free(&dev->lock,
- _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
-
- /* FIXME: may require heavy-handed reset of
- hardware at this point, possibly
- processed via a callback to the X
- server. */
- } else if (dev->driver->reclaim_buffers_locked != NULL &&
- dev->lock.hw_lock != NULL) {
- /* The lock is required to reclaim buffers */
- for (;;) {
- if (!dev->lock.hw_lock) {
- /* Device has been unregistered */
- retcode = EINTR;
- break;
- }
- if (drm_lock_take(&dev->lock, DRM_KERNEL_CONTEXT)) {
- dev->lock.file_priv = file_priv;
- dev->lock.lock_time = jiffies;
- atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
- break; /* Got lock */
- }
- /* Contention */
- retcode = DRM_LOCK_SLEEP(dev, &dev->lock.lock_queue,
- PCATCH, "drmlk2", 0);
- if (retcode)
- break;
- }
- if (retcode == 0) {
- dev->driver->reclaim_buffers_locked(dev, file_priv);
- drm_lock_free(&dev->lock, DRM_KERNEL_CONTEXT);
- }
- }
-
- if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) &&
- !dev->driver->reclaim_buffers_locked)
- drm_reclaim_buffers(dev, file_priv);
-
- funsetown(&dev->buf_sigio);
- seldrain(&file_priv->event_poll);
-
- if (dev->driver->postclose != NULL)
- dev->driver->postclose(dev, file_priv);
- TAILQ_REMOVE(&dev->files, file_priv, link);
- free(file_priv, DRM_MEM_FILES);
-
- /* ========================================================
- * End inline drm_release
- */
-
- atomic_inc(&dev->counts[_DRM_STAT_CLOSES]);
- mtx_lock(&Giant);
- device_unbusy(dev->device);
- mtx_unlock(&Giant);
- if (--dev->open_count == 0) {
- retcode = drm_lastclose(dev);
- }
-
- DRM_UNLOCK(dev);
+ struct drm_version *version = data;
+ int err;
+
+ version->version_major = dev->driver->major;
+ version->version_minor = dev->driver->minor;
+ version->version_patchlevel = dev->driver->patchlevel;
+ err = drm_copy_field(version->name, &version->name_len,
+ dev->driver->name);
+ if (!err)
+ err = drm_copy_field(version->date, &version->date_len,
+ dev->driver->date);
+ if (!err)
+ err = drm_copy_field(version->desc, &version->desc_len,
+ dev->driver->desc);
+
+ return err;
}
-extern drm_ioctl_desc_t drm_compat_ioctls[];
-
-/* drm_ioctl is called whenever a process performs an ioctl on /dev/drm.
+/**
+ * Called whenever a process performs an ioctl on /dev/drm.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument.
+ * \return zero on success or negative number on failure.
+ *
+ * Looks up the ioctl function in the ::ioctls table, checking for root
+ * previleges if so required, and dispatches to the respective function.
*/
int drm_ioctl(struct cdev *kdev, u_long cmd, caddr_t data, int flags,
DRM_STRUCTPROC *p)
{
- struct drm_device *dev = drm_get_device_from_kdev(kdev);
- int retcode = 0;
- drm_ioctl_desc_t *ioctl;
- int (*func)(struct drm_device *dev, void *data, struct drm_file *file_priv);
- int nr = DRM_IOCTL_NR(cmd);
- int is_driver_ioctl = 0;
struct drm_file *file_priv;
+ struct drm_device *dev;
+ struct drm_ioctl_desc *ioctl;
+ drm_ioctl_t *func;
+ unsigned int nr = DRM_IOCTL_NR(cmd);
+ int retcode;
+
+ dev = drm_get_device_from_kdev(kdev);
retcode = devfs_get_cdevpriv((void **)&file_priv);
if (retcode != 0) {
@@ -864,12 +372,16 @@ int drm_ioctl(struct cdev *kdev, u_long cmd, caddr_t data, int flags,
return EINVAL;
}
+ retcode = -EINVAL;
+
+ atomic_inc(&dev->ioctl_count);
atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]);
++file_priv->ioctl_count;
DRM_DEBUG("pid=%d, cmd=0x%02lx, nr=0x%02x, dev 0x%lx, auth=%d\n",
- DRM_CURRENTPID, cmd, nr, (long)dev->device,
- file_priv->authenticated);
+ DRM_CURRENTPID, cmd, nr,
+ (long)file_priv->minor->device,
+ file_priv->authenticated);
switch (cmd) {
case FIONBIO:
@@ -877,10 +389,10 @@ int drm_ioctl(struct cdev *kdev, u_long cmd, caddr_t data, int flags,
return 0;
case FIOSETOWN:
- return fsetown(*(int *)data, &dev->buf_sigio);
+ return fsetown(*(int *)data, &file_priv->minor->buf_sigio);
case FIOGETOWN:
- *(int *) data = fgetown(&dev->buf_sigio);
+ *(int *) data = fgetown(&file_priv->minor->buf_sigio);
return 0;
}
@@ -889,253 +401,99 @@ int drm_ioctl(struct cdev *kdev, u_long cmd, caddr_t data, int flags,
return EINVAL;
}
+ if ((nr >= DRM_CORE_IOCTL_COUNT) &&
+ ((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END)))
+ goto err_i1;
#ifdef COMPAT_FREEBSD32
- /*
- * Called whenever a 32-bit process running under a 64-bit
- * kernel performs an ioctl on /dev/drm.
- */
- if (SV_CURPROC_FLAG(SV_ILP32) && drm_compat_ioctls[nr].func != NULL)
- /*
- * Assume that ioctls without an explicit compat
- * routine will just work. This may not always be a
- * good assumption, but it's better than always
- * failing.
- */
- ioctl = &drm_compat_ioctls[nr];
- else
+ if (SV_CURPROC_FLAG(SV_ILP32) &&
+ (nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END) &&
+ (nr < DRM_COMMAND_BASE + *dev->driver->num_compat_ioctls) &&
+ (dev->driver->compat_ioctls[nr - DRM_COMMAND_BASE].func != NULL)) {
+ ioctl = &dev->driver->compat_ioctls[nr - DRM_COMMAND_BASE];
+ } else
#endif
- ioctl = &drm_ioctls[nr];
- /* It's not a core DRM ioctl, try driver-specific. */
- if (ioctl->func == NULL && nr >= DRM_COMMAND_BASE) {
- /* The array entries begin at DRM_COMMAND_BASE ioctl nr */
- nr -= DRM_COMMAND_BASE;
- if (nr >= dev->driver->max_ioctl) {
- DRM_DEBUG("Bad driver ioctl number, 0x%x (of 0x%x)\n",
- nr, dev->driver->max_ioctl);
- return EINVAL;
- }
+ if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END) &&
+ (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) {
+ ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
+ }
+ else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE)) {
#ifdef COMPAT_FREEBSD32
- if (SV_CURPROC_FLAG(SV_ILP32) &&
- nr < *dev->driver->compat_ioctls_nr &&
- dev->driver->compat_ioctls[nr].func != NULL)
- ioctl = &dev->driver->compat_ioctls[nr];
+ /*
+ * Called whenever a 32-bit process running under a 64-bit
+ * kernel performs an ioctl on /dev/drm.
+ */
+ if (SV_CURPROC_FLAG(SV_ILP32) && drm_compat_ioctls[nr].func != NULL)
+ /*
+ * Assume that ioctls without an explicit compat
+ * routine will just work. This may not always be a
+ * good assumption, but it's better than always
+ * failing.
+ */
+ ioctl = &drm_compat_ioctls[nr];
else
#endif
- ioctl = &dev->driver->ioctls[nr];
- is_driver_ioctl = 1;
- }
+ ioctl = &drm_ioctls[nr];
+ } else
+ goto err_i1;
+
+ /* Do not trust userspace, use our own definition */
func = ioctl->func;
+ /* is there a local override? */
+#ifdef FREEBSD_NOTYET
+#ifdef COMPAT_FREEBSD32
+ if (SV_CURPROC_FLAG(SV_ILP32) &&
+ (nr == DRM_IOCTL_NR(DRM_IOCTL_DMA)) && dev->driver->dma_compat_ioctl)
+ func = dev->driver->dma_compat_ioctl;
+ else
+#endif
+#endif /* FREEBSD_NOTYET */
+ if ((nr == DRM_IOCTL_NR(DRM_IOCTL_DMA)) && dev->driver->dma_ioctl)
+ func = dev->driver->dma_ioctl;
- if (func == NULL) {
+ if (!func) {
DRM_DEBUG("no function\n");
- return EINVAL;
- }
-
- if (((ioctl->flags & DRM_ROOT_ONLY) && !DRM_SUSER(p)) ||
- ((ioctl->flags & DRM_AUTH) && !file_priv->authenticated) ||
- ((ioctl->flags & DRM_MASTER) && !file_priv->master))
- return EACCES;
-
- if (is_driver_ioctl) {
- if ((ioctl->flags & DRM_UNLOCKED) == 0)
- DRM_LOCK(dev);
- /* shared code returns -errno */
- retcode = -func(dev, data, file_priv);
- if ((ioctl->flags & DRM_UNLOCKED) == 0)
- DRM_UNLOCK(dev);
+ retcode = -EINVAL;
+ } else if (((ioctl->flags & DRM_ROOT_ONLY) && !DRM_SUSER(p)) ||
+ ((ioctl->flags & DRM_AUTH) && !file_priv->authenticated) ||
+ ((ioctl->flags & DRM_MASTER) && !file_priv->is_master) ||
+ (!(ioctl->flags & DRM_CONTROL_ALLOW) && (file_priv->minor->type == DRM_MINOR_CONTROL))) {
+ retcode = -EACCES;
} else {
- retcode = func(dev, data, file_priv);
+ if (ioctl->flags & DRM_UNLOCKED)
+ retcode = func(dev, data, file_priv);
+ else {
+ sx_xlock(&drm_global_mutex);
+ retcode = func(dev, data, file_priv);
+ sx_xunlock(&drm_global_mutex);
+ }
}
- if (retcode != 0)
- DRM_DEBUG(" returning %d\n", retcode);
+ err_i1:
+ atomic_dec(&dev->ioctl_count);
+ if (retcode)
+ DRM_DEBUG("ret = %d\n", retcode);
if (retcode != 0 &&
- (drm_debug_flag & DRM_DEBUGBITS_FAILED_IOCTL) != 0) {
+ (drm_debug & DRM_DEBUGBITS_FAILED_IOCTL) != 0) {
printf(
-"pid %d, cmd 0x%02lx, nr 0x%02x/%1d, dev 0x%lx, auth %d, res %d\n",
- DRM_CURRENTPID, cmd, nr, is_driver_ioctl, (long)dev->device,
- file_priv->authenticated, retcode);
+"pid %d, cmd 0x%02lx, nr 0x%02x, dev 0x%lx, auth %d, res %d\n",
+ DRM_CURRENTPID, cmd, nr, (long)file_priv->minor->device,
+ file_priv->authenticated, -retcode);
}
- return retcode;
-}
-
-drm_local_map_t *drm_getsarea(struct drm_device *dev)
-{
- drm_local_map_t *map;
-
- DRM_LOCK_ASSERT(dev);
- TAILQ_FOREACH(map, &dev->maplist, link) {
- if (map->type == _DRM_SHM && (map->flags & _DRM_CONTAINS_LOCK))
- return map;
- }
-
- return NULL;
-}
-
-int
-drm_add_busid_modesetting(struct drm_device *dev, struct sysctl_ctx_list *ctx,
- struct sysctl_oid *top)
-{
- struct sysctl_oid *oid;
-
- snprintf(dev->busid_str, sizeof(dev->busid_str),
- "pci:%04x:%02x:%02x.%d", dev->pci_domain, dev->pci_bus,
- dev->pci_slot, dev->pci_func);
- oid = SYSCTL_ADD_STRING(ctx, SYSCTL_CHILDREN(top), OID_AUTO, "busid",
- CTLFLAG_RD, dev->busid_str, 0, NULL);
- if (oid == NULL)
- return (ENOMEM);
- dev->modesetting = (dev->driver->driver_features & DRIVER_MODESET) != 0;
- oid = SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(top), OID_AUTO,
- "modesetting", CTLFLAG_RD, &dev->modesetting, 0, NULL);
- if (oid == NULL)
- return (ENOMEM);
-
- return (0);
-}
-
-static int
-drm_mmap_single(struct cdev *kdev, vm_ooffset_t *offset, vm_size_t size,
- struct vm_object **obj_res, int nprot)
-{
- struct drm_device *dev;
-
- dev = drm_get_device_from_kdev(kdev);
- if (dev->drm_ttm_bdev != NULL) {
- return (ttm_bo_mmap_single(dev->drm_ttm_bdev, offset, size,
- obj_res, nprot));
- } else if ((dev->driver->driver_features & DRIVER_GEM) != 0) {
- return (drm_gem_mmap_single(dev, offset, size, obj_res, nprot));
- } else {
- return (ENODEV);
- }
+ return -retcode;
}
+EXPORT_SYMBOL(drm_ioctl);
-#if DRM_LINUX
-
-#include <sys/sysproto.h>
-
-MODULE_DEPEND(DRIVER_NAME, linux, 1, 1, 1);
-
-#define LINUX_IOCTL_DRM_MIN 0x6400
-#define LINUX_IOCTL_DRM_MAX 0x64ff
-
-static linux_ioctl_function_t drm_linux_ioctl;
-static struct linux_ioctl_handler drm_handler = {drm_linux_ioctl,
- LINUX_IOCTL_DRM_MIN, LINUX_IOCTL_DRM_MAX};
-
-/* The bits for in/out are switched on Linux */
-#define LINUX_IOC_IN IOC_OUT
-#define LINUX_IOC_OUT IOC_IN
-
-static int
-drm_linux_ioctl(DRM_STRUCTPROC *p, struct linux_ioctl_args* args)
+struct drm_local_map *drm_getsarea(struct drm_device *dev)
{
- int error;
- int cmd = args->cmd;
+ struct drm_map_list *entry;
- args->cmd &= ~(LINUX_IOC_IN | LINUX_IOC_OUT);
- if (cmd & LINUX_IOC_IN)
- args->cmd |= IOC_IN;
- if (cmd & LINUX_IOC_OUT)
- args->cmd |= IOC_OUT;
-
- error = ioctl(p, (struct ioctl_args *)args);
-
- return error;
-}
-#endif /* DRM_LINUX */
-
-
-static int
-drm_core_init(void *arg)
-{
-
- drm_global_init();
-
-#if DRM_LINUX
- linux_ioctl_register_handler(&drm_handler);
-#endif /* DRM_LINUX */
-
- DRM_INFO("Initialized %s %d.%d.%d %s\n",
- CORE_NAME, CORE_MAJOR, CORE_MINOR, CORE_PATCHLEVEL, CORE_DATE);
- return 0;
-}
-
-static void
-drm_core_exit(void *arg)
-{
-
-#if DRM_LINUX
- linux_ioctl_unregister_handler(&drm_handler);
-#endif /* DRM_LINUX */
-
- drm_global_release();
-}
-
-SYSINIT(drm_register, SI_SUB_KLD, SI_ORDER_MIDDLE,
- drm_core_init, NULL);
-SYSUNINIT(drm_unregister, SI_SUB_KLD, SI_ORDER_MIDDLE,
- drm_core_exit, NULL);
-
-static bool
-dmi_found(const struct dmi_system_id *dsi)
-{
- char *hw_vendor, *hw_prod;
- int i, slot;
- bool res;
-
- hw_vendor = getenv("smbios.planar.maker");
- hw_prod = getenv("smbios.planar.product");
- res = true;
- for (i = 0; i < nitems(dsi->matches); i++) {
- slot = dsi->matches[i].slot;
- switch (slot) {
- case DMI_NONE:
- break;
- case DMI_SYS_VENDOR:
- case DMI_BOARD_VENDOR:
- if (hw_vendor != NULL &&
- !strcmp(hw_vendor, dsi->matches[i].substr)) {
- break;
- } else {
- res = false;
- goto out;
- }
- case DMI_PRODUCT_NAME:
- case DMI_BOARD_NAME:
- if (hw_prod != NULL &&
- !strcmp(hw_prod, dsi->matches[i].substr)) {
- break;
- } else {
- res = false;
- goto out;
- }
- default:
- res = false;
- goto out;
+ list_for_each_entry(entry, &dev->maplist, head) {
+ if (entry->map && entry->map->type == _DRM_SHM &&
+ (entry->map->flags & _DRM_CONTAINS_LOCK)) {
+ return entry->map;
}
}
-out:
- freeenv(hw_vendor);
- freeenv(hw_prod);
-
- return (res);
-}
-
-bool
-dmi_check_system(const struct dmi_system_id *sysid)
-{
- const struct dmi_system_id *dsi;
- bool res;
-
- for (res = false, dsi = sysid; dsi->matches[0].slot != 0 ; dsi++) {
- if (dmi_found(dsi)) {
- res = true;
- if (dsi->callback != NULL && dsi->callback(dsi))
- break;
- }
- }
- return (res);
+ return NULL;
}
+EXPORT_SYMBOL(drm_getsarea);
diff --git a/sys/dev/drm2/drm_edid.c b/sys/dev/drm2/drm_edid.c
index bf4cc9f..6fad736 100644
--- a/sys/dev/drm2/drm_edid.c
+++ b/sys/dev/drm2/drm_edid.c
@@ -33,7 +33,7 @@ __FBSDID("$FreeBSD$");
#include <dev/drm2/drmP.h>
#include <dev/drm2/drm_edid.h>
-#include <dev/drm2/drm_edid_modes.h>
+#include "drm_edid_modes.h"
#include <dev/iicbus/iic.h>
#include <dev/iicbus/iiconf.h>
#include "iicbus_if.h"
@@ -69,6 +69,8 @@ __FBSDID("$FreeBSD$");
#define EDID_QUIRK_FIRST_DETAILED_PREFERRED (1 << 5)
/* use +hsync +vsync for detailed mode */
#define EDID_QUIRK_DETAILED_SYNC_PP (1 << 6)
+/* Force reduced-blanking timings for detailed modes */
+#define EDID_QUIRK_FORCE_REDUCED_BLANKING (1 << 7)
struct detailed_mode_closure {
struct drm_connector *connector;
@@ -123,6 +125,9 @@ static struct edid_quirk {
/* Samsung SyncMaster 22[5-6]BW */
{ "SAM", 596, EDID_QUIRK_PREFER_LARGE_60 },
{ "SAM", 638, EDID_QUIRK_PREFER_LARGE_60 },
+
+ /* ViewSonic VA2026w */
+ { "VSC", 5020, EDID_QUIRK_FORCE_REDUCED_BLANKING },
};
/*** DDC fetch and block validation ***/
@@ -145,22 +150,30 @@ int drm_edid_header_is_valid(const u8 *raw_edid)
return score;
}
+EXPORT_SYMBOL(drm_edid_header_is_valid);
+
+static int edid_fixup __read_mostly = 6;
+module_param_named(edid_fixup, edid_fixup, int, 0400);
+MODULE_PARM_DESC(edid_fixup,
+ "Minimum number of valid EDID header bytes (0-8, default 6)");
/*
* Sanity check the EDID block (base or extension). Return 0 if the block
* doesn't check out, or 1 if it's valid.
*/
-static bool
-drm_edid_block_valid(u8 *raw_edid, int block)
+bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid)
{
int i;
u8 csum = 0;
struct edid *edid = (struct edid *)raw_edid;
+ if (edid_fixup > 8 || edid_fixup < 0)
+ edid_fixup = 6;
+
if (block == 0) {
int score = drm_edid_header_is_valid(raw_edid);
if (score == 8) ;
- else if (score >= 6) {
+ else if (score >= edid_fixup) {
DRM_DEBUG("Fixing EDID header, your hardware may be failing\n");
memcpy(raw_edid, edid_header, sizeof(edid_header));
} else {
@@ -171,7 +184,9 @@ drm_edid_block_valid(u8 *raw_edid, int block)
for (i = 0; i < EDID_LENGTH; i++)
csum += raw_edid[i];
if (csum) {
- DRM_DEBUG_KMS("EDID checksum is invalid, remainder is %d\n", csum);
+ if (print_bad_edid) {
+ DRM_ERROR("EDID checksum is invalid, remainder is %d\n", csum);
+ }
/* allow CEA to slide through, switches mangle this */
if (raw_edid[0] != 0x02)
@@ -197,23 +212,22 @@ drm_edid_block_valid(u8 *raw_edid, int block)
return 1;
bad:
- if (raw_edid) {
+ if (raw_edid && print_bad_edid) {
DRM_DEBUG_KMS("Raw EDID:\n");
- if ((drm_debug_flag & DRM_DEBUGBITS_KMS) != 0) {
- for (i = 0; i < EDID_LENGTH; ) {
- printf("%02x", raw_edid[i]);
- i++;
- if (i % 16 == 0 || i == EDID_LENGTH)
- printf("\n");
- else if (i % 8 == 0)
- printf(" ");
- else
- printf(" ");
- }
+ for (i = 0; i < EDID_LENGTH; ) {
+ printf("%02x", raw_edid[i]);
+ i++;
+ if (i % 16 == 0 || i == EDID_LENGTH)
+ printf("\n");
+ else if (i % 8 == 0)
+ printf(" ");
+ else
+ printf(" ");
}
}
return 0;
}
+EXPORT_SYMBOL(drm_edid_block_valid);
/**
* drm_edid_is_valid - sanity check EDID data
@@ -230,13 +244,13 @@ bool drm_edid_is_valid(struct edid *edid)
return false;
for (i = 0; i <= edid->extensions; i++)
- if (!drm_edid_block_valid(raw + i * EDID_LENGTH, i))
+ if (!drm_edid_block_valid(raw + i * EDID_LENGTH, i, true))
return false;
return true;
}
+EXPORT_SYMBOL(drm_edid_is_valid);
-#define DDC_ADDR 0x50
#define DDC_SEGMENT_ADDR 0x30
/**
* Get EDID information via I2C.
@@ -266,13 +280,13 @@ drm_do_probe_ddc_edid(device_t adapter, unsigned char *buf,
do {
struct iic_msg msgs[] = {
{
- .slave = DDC_SEGMENT_ADDR << 1,
- .flags = 0,
- .len = 1,
- .buf = &segment,
+ .slave = DDC_SEGMENT_ADDR << 1,
+ .flags = 0,
+ .len = 1,
+ .buf = &segment,
}, {
.slave = DDC_ADDR << 1,
- .flags = IIC_M_WR,
+ .flags = 0,
.len = 1,
.buf = &start,
}, {
@@ -294,7 +308,7 @@ drm_do_probe_ddc_edid(device_t adapter, unsigned char *buf,
retries, ret);
} while (ret != 0 && --retries);
- return (ret == 0 ? 0 : -1);
+ return ret == 0 ? 0 : -1;
}
static bool drm_edid_is_zero(u8 *in_edid, int length)
@@ -305,6 +319,7 @@ static bool drm_edid_is_zero(u8 *in_edid, int length)
for (i = 0; i < length / 4; i++)
if (*(raw_edid + i) != 0)
return false;
+
return true;
}
@@ -313,14 +328,16 @@ drm_do_get_edid(struct drm_connector *connector, device_t adapter)
{
int i, j = 0, valid_extensions = 0;
u8 *block, *new;
+ bool print_bad_edid = !connector->bad_edid_counter || (drm_debug & DRM_DEBUGBITS_KMS);
- block = malloc(EDID_LENGTH, DRM_MEM_KMS, M_WAITOK | M_ZERO);
+ if ((block = malloc(EDID_LENGTH, DRM_MEM_KMS, M_NOWAIT)) == NULL)
+ return NULL;
/* base block fetch */
for (i = 0; i < 4; i++) {
if (drm_do_probe_ddc_edid(adapter, block, 0, EDID_LENGTH))
goto out;
- if (drm_edid_block_valid(block, 0))
+ if (drm_edid_block_valid(block, 0, print_bad_edid))
break;
if (i == 0 && drm_edid_is_zero(block, EDID_LENGTH)) {
connector->null_edid_counter++;
@@ -335,7 +352,9 @@ drm_do_get_edid(struct drm_connector *connector, device_t adapter)
return block;
new = reallocf(block, (block[0x7e] + 1) * EDID_LENGTH, DRM_MEM_KMS,
- M_WAITOK);
+ M_NOWAIT);
+ if (!new)
+ goto out;
block = new;
for (j = 1; j <= block[0x7e]; j++) {
@@ -344,30 +363,39 @@ drm_do_get_edid(struct drm_connector *connector, device_t adapter)
block + (valid_extensions + 1) * EDID_LENGTH,
j, EDID_LENGTH))
goto out;
- if (drm_edid_block_valid(block + (valid_extensions + 1) * EDID_LENGTH, j)) {
+ if (drm_edid_block_valid(block + (valid_extensions + 1) * EDID_LENGTH, j, print_bad_edid)) {
valid_extensions++;
break;
}
}
- if (i == 4)
- DRM_DEBUG_KMS("%s: Ignoring invalid EDID block %d.\n",
- drm_get_connector_name(connector), j);
+
+ if (i == 4 && print_bad_edid) {
+ dev_warn(connector->dev->dev,
+ "%s: Ignoring invalid EDID block %d.\n",
+ drm_get_connector_name(connector), j);
+
+ connector->bad_edid_counter++;
+ }
}
if (valid_extensions != block[0x7e]) {
block[EDID_LENGTH-1] += block[0x7e] - valid_extensions;
block[0x7e] = valid_extensions;
new = reallocf(block, (valid_extensions + 1) * EDID_LENGTH,
- DRM_MEM_KMS, M_WAITOK);
+ DRM_MEM_KMS, M_NOWAIT);
+ if (!new)
+ goto out;
block = new;
}
- DRM_DEBUG_KMS("got EDID from %s\n", drm_get_connector_name(connector));
return block;
carp:
- DRM_DEBUG_KMS("%s: EDID block %d invalid.\n",
- drm_get_connector_name(connector), j);
+ if (print_bad_edid) {
+ dev_warn(connector->dev->dev, "%s: EDID block %d invalid.\n",
+ drm_get_connector_name(connector), j);
+ }
+ connector->bad_edid_counter++;
out:
free(block, DRM_MEM_KMS);
@@ -380,13 +408,14 @@ out:
* \param adapter : i2c device adaptor
* \return 1 on success
*/
-static bool
+bool
drm_probe_ddc(device_t adapter)
{
unsigned char out;
return (drm_do_probe_ddc_edid(adapter, &out, 0, 1) == 0);
}
+EXPORT_SYMBOL(drm_probe_ddc);
/**
* drm_get_edid - get EDID data, if available
@@ -406,11 +435,9 @@ struct edid *drm_get_edid(struct drm_connector *connector,
if (drm_probe_ddc(adapter))
edid = (struct edid *)drm_do_get_edid(connector, adapter);
- connector->display_info.raw_edid = (char *)edid;
-
return edid;
-
}
+EXPORT_SYMBOL(drm_get_edid);
/*** EDID parsing ***/
@@ -444,7 +471,7 @@ static u32 edid_get_quirks(struct edid *edid)
struct edid_quirk *quirk;
int i;
- for (i = 0; i < DRM_ARRAY_SIZE(edid_quirk_list); i++) {
+ for (i = 0; i < ARRAY_SIZE(edid_quirk_list); i++) {
quirk = &edid_quirk_list[i];
if (edid_vendor(edid, quirk->vendor) &&
@@ -531,7 +558,7 @@ struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
int i;
for (i = 0; i < drm_num_dmt_modes; i++) {
- struct drm_display_mode *ptr = &drm_dmt_modes[i];
+ const struct drm_display_mode *ptr = &drm_dmt_modes[i];
if (hsize != ptr->hdisplay)
continue;
if (vsize != ptr->vdisplay)
@@ -546,6 +573,7 @@ struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
return NULL;
}
+EXPORT_SYMBOL(drm_mode_find_dmt);
typedef void detailed_cb(struct detailed_timing *timing, void *closure);
@@ -553,25 +581,10 @@ static void
cea_for_each_detailed_block(u8 *ext, detailed_cb *cb, void *closure)
{
int i, n = 0;
- u8 rev = ext[0x01], d = ext[0x02];
+ u8 d = ext[0x02];
u8 *det_base = ext + d;
- switch (rev) {
- case 0:
- /* can't happen */
- return;
- case 1:
- /* have to infer how many blocks we have, check pixel clock */
- for (i = 0; i < 6; i++)
- if (det_base[18*i] || det_base[18*i+1])
- n++;
- break;
- default:
- /* explicit count */
- n = min(ext[0x03] & 0x0f, 6);
- break;
- }
-
+ n = (127 - d) / 18;
for (i = 0; i < n; i++)
cb((struct detailed_timing *)(det_base + 18 * i), closure);
}
@@ -630,7 +643,7 @@ static bool
drm_monitor_supports_rb(struct edid *edid)
{
if (edid->revision >= 4) {
- bool ret;
+ bool ret = false;
drm_for_each_detailed_block((u8 *)edid, is_rb, &ret);
return ret;
}
@@ -814,7 +827,7 @@ drm_mode_std(struct drm_connector *connector, struct edid *edid,
if (!mode)
return NULL;
if (drm_mode_hsync(mode) > drm_gtf2_hbreak(edid)) {
- free(mode, DRM_MEM_KMS);
+ drm_mode_destroy(dev, mode);
mode = drm_gtf_mode_complex(dev, hsize, vsize,
vrefresh_rate, 0, 0,
drm_gtf2_m(edid),
@@ -859,7 +872,7 @@ drm_mode_do_interlace_quirk(struct drm_display_mode *mode,
if (!(pt->misc & DRM_EDID_PT_INTERLACED))
return;
- for (i = 0; i < DRM_ARRAY_SIZE(cea_interlaced); i++) {
+ for (i = 0; i < ARRAY_SIZE(cea_interlaced); i++) {
if ((mode->hdisplay == cea_interlaced[i].w) &&
(mode->vdisplay == cea_interlaced[i].h / 2)) {
mode->vdisplay *= 2;
@@ -896,7 +909,7 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
unsigned vblank = (pt->vactive_vblank_hi & 0xf) << 8 | pt->vblank_lo;
unsigned hsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc0) << 2 | pt->hsync_offset_lo;
unsigned hsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0x30) << 4 | pt->hsync_pulse_width_lo;
- unsigned vsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc) >> 2 | pt->vsync_offset_pulse_width_lo >> 4;
+ unsigned vsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc) << 2 | pt->vsync_offset_pulse_width_lo >> 4;
unsigned vsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0x3) << 4 | (pt->vsync_offset_pulse_width_lo & 0xf);
/* ignore tiny modes */
@@ -917,16 +930,23 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
"Wrong Hsync/Vsync pulse width\n");
return NULL;
}
+
+ if (quirks & EDID_QUIRK_FORCE_REDUCED_BLANKING) {
+ mode = drm_cvt_mode(dev, hactive, vactive, 60, true, false, false);
+ if (!mode)
+ return NULL;
+
+ goto set_size;
+ }
+
mode = drm_mode_create(dev);
if (!mode)
return NULL;
- mode->type = DRM_MODE_TYPE_DRIVER;
-
if (quirks & EDID_QUIRK_135_CLOCK_TOO_HIGH)
- timing->pixel_clock = htole16(1088);
+ timing->pixel_clock = cpu_to_le16(1088);
- mode->clock = le16toh(timing->pixel_clock) * 10;
+ mode->clock = le16_to_cpu(timing->pixel_clock) * 10;
mode->hdisplay = hactive;
mode->hsync_start = mode->hdisplay + hsync_offset;
@@ -946,8 +966,6 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
drm_mode_do_interlace_quirk(mode, pt);
- drm_mode_set_name(mode);
-
if (quirks & EDID_QUIRK_DETAILED_SYNC_PP) {
pt->misc |= DRM_EDID_PT_HSYNC_POSITIVE | DRM_EDID_PT_VSYNC_POSITIVE;
}
@@ -957,6 +975,7 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ?
DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
+set_size:
mode->width_mm = pt->width_mm_lo | (pt->width_height_mm_hi & 0xf0) << 4;
mode->height_mm = pt->height_mm_lo | (pt->width_height_mm_hi & 0xf) << 8;
@@ -970,11 +989,15 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
mode->height_mm = edid->height_cm * 10;
}
+ mode->type = DRM_MODE_TYPE_DRIVER;
+ mode->vrefresh = drm_mode_vrefresh(mode);
+ drm_mode_set_name(mode);
+
return mode;
}
static bool
-mode_in_hsync_range(struct drm_display_mode *mode,
+mode_in_hsync_range(const struct drm_display_mode *mode,
struct edid *edid, u8 *t)
{
int hsync, hmin, hmax;
@@ -991,7 +1014,7 @@ mode_in_hsync_range(struct drm_display_mode *mode,
}
static bool
-mode_in_vsync_range(struct drm_display_mode *mode,
+mode_in_vsync_range(const struct drm_display_mode *mode,
struct edid *edid, u8 *t)
{
int vsync, vmin, vmax;
@@ -1023,7 +1046,7 @@ range_pixel_clock(struct edid *edid, u8 *t)
}
static bool
-mode_in_range(struct drm_display_mode *mode, struct edid *edid,
+mode_in_range(const struct drm_display_mode *mode, struct edid *edid,
struct detailed_timing *timing)
{
u32 max_clock;
@@ -1050,6 +1073,24 @@ mode_in_range(struct drm_display_mode *mode, struct edid *edid,
return true;
}
+static bool valid_inferred_mode(const struct drm_connector *connector,
+ const struct drm_display_mode *mode)
+{
+ struct drm_display_mode *m;
+ bool ok = false;
+
+ list_for_each_entry(m, &connector->probed_modes, head) {
+ if (mode->hdisplay == m->hdisplay &&
+ mode->vdisplay == m->vdisplay &&
+ drm_mode_vrefresh(mode) == drm_mode_vrefresh(m))
+ return false; /* duplicated */
+ if (mode->hdisplay <= m->hdisplay &&
+ mode->vdisplay <= m->vdisplay)
+ ok = true;
+ }
+ return ok;
+}
+
static int
drm_dmt_modes_for_range(struct drm_connector *connector, struct edid *edid,
struct detailed_timing *timing)
@@ -1059,7 +1100,8 @@ drm_dmt_modes_for_range(struct drm_connector *connector, struct edid *edid,
struct drm_device *dev = connector->dev;
for (i = 0; i < drm_num_dmt_modes; i++) {
- if (mode_in_range(drm_dmt_modes + i, edid, timing)) {
+ if (mode_in_range(drm_dmt_modes + i, edid, timing) &&
+ valid_inferred_mode(connector, drm_dmt_modes + i)) {
newmode = drm_mode_duplicate(dev, &drm_dmt_modes[i]);
if (newmode) {
drm_mode_probed_add(connector, newmode);
@@ -1099,7 +1141,8 @@ drm_gtf_modes_for_range(struct drm_connector *connector, struct edid *edid,
return modes;
fixup_mode_1366x768(newmode);
- if (!mode_in_range(newmode, edid, timing)) {
+ if (!mode_in_range(newmode, edid, timing) ||
+ !valid_inferred_mode(connector, newmode)) {
drm_mode_destroy(dev, newmode);
continue;
}
@@ -1127,7 +1170,8 @@ drm_cvt_modes_for_range(struct drm_connector *connector, struct edid *edid,
return modes;
fixup_mode_1366x768(newmode);
- if (!mode_in_range(newmode, edid, timing)) {
+ if (!mode_in_range(newmode, edid, timing) ||
+ !valid_inferred_mode(connector, newmode)) {
drm_mode_destroy(dev, newmode);
continue;
}
@@ -1201,7 +1245,7 @@ drm_est3_modes(struct drm_connector *connector, struct detailed_timing *timing)
for (i = 0; i < 6; i++) {
for (j = 7; j > 0; j--) {
m = (i * 8) + (7 - j);
- if (m >= DRM_ARRAY_SIZE(est3_modes))
+ if (m >= ARRAY_SIZE(est3_modes))
break;
if (est[i] & (1 << j)) {
mode = drm_mode_find_dmt(connector->dev,
@@ -1453,6 +1497,7 @@ add_detailed_modes(struct drm_connector *connector, struct edid *edid,
#define HDMI_IDENTIFIER 0x000C03
#define AUDIO_BLOCK 0x01
+#define VIDEO_BLOCK 0x02
#define VENDOR_BLOCK 0x03
#define SPEAKER_BLOCK 0x04
#define EDID_BASIC_AUDIO (1 << 6)
@@ -1483,21 +1528,133 @@ u8 *drm_find_cea_extension(struct edid *edid)
return edid_ext;
}
+EXPORT_SYMBOL(drm_find_cea_extension);
-static void
-parse_hdmi_vsdb(struct drm_connector *connector, uint8_t *db)
+/*
+ * Looks for a CEA mode matching given drm_display_mode.
+ * Returns its CEA Video ID code, or 0 if not found.
+ */
+u8 drm_match_cea_mode(struct drm_display_mode *to_match)
+{
+ const struct drm_display_mode *cea_mode;
+ u8 mode;
+
+ for (mode = 0; mode < drm_num_cea_modes; mode++) {
+ cea_mode = (const struct drm_display_mode *)&edid_cea_modes[mode];
+
+ if (drm_mode_equal(to_match, cea_mode))
+ return mode + 1;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(drm_match_cea_mode);
+
+
+static int
+do_cea_modes (struct drm_connector *connector, u8 *db, u8 len)
+{
+ struct drm_device *dev = connector->dev;
+ u8 * mode, cea_mode;
+ int modes = 0;
+
+ for (mode = db; mode < db + len; mode++) {
+ cea_mode = (*mode & 127) - 1; /* CEA modes are numbered 1..127 */
+ if (cea_mode < drm_num_cea_modes) {
+ struct drm_display_mode *newmode;
+ newmode = drm_mode_duplicate(dev,
+ &edid_cea_modes[cea_mode]);
+ if (newmode) {
+ drm_mode_probed_add(connector, newmode);
+ modes++;
+ }
+ }
+ }
+
+ return modes;
+}
+
+static int
+cea_db_payload_len(const u8 *db)
+{
+ return db[0] & 0x1f;
+}
+
+static int
+cea_db_tag(const u8 *db)
+{
+ return db[0] >> 5;
+}
+
+static int
+cea_revision(const u8 *cea)
+{
+ return cea[1];
+}
+
+static int
+cea_db_offsets(const u8 *cea, int *start, int *end)
{
- connector->eld[5] |= (db[6] >> 7) << 1; /* Supports_AI */
+ /* Data block offset in CEA extension block */
+ *start = 4;
+ *end = cea[2];
+ if (*end == 0)
+ *end = 127;
+ if (*end < 4 || *end > 127)
+ return -ERANGE;
+ return 0;
+}
- connector->dvi_dual = db[6] & 1;
- connector->max_tmds_clock = db[7] * 5;
+#define for_each_cea_db(cea, i, start, end) \
+ for ((i) = (start); (i) < (end) && (i) + cea_db_payload_len(&(cea)[(i)]) < (end); (i) += cea_db_payload_len(&(cea)[(i)]) + 1)
- connector->latency_present[0] = db[8] >> 7;
- connector->latency_present[1] = (db[8] >> 6) & 1;
- connector->video_latency[0] = db[9];
- connector->audio_latency[0] = db[10];
- connector->video_latency[1] = db[11];
- connector->audio_latency[1] = db[12];
+static int
+add_cea_modes(struct drm_connector *connector, struct edid *edid)
+{
+ u8 * cea = drm_find_cea_extension(edid);
+ u8 * db, dbl;
+ int modes = 0;
+
+ if (cea && cea_revision(cea) >= 3) {
+ int i, start, end;
+
+ if (cea_db_offsets(cea, &start, &end))
+ return 0;
+
+ for_each_cea_db(cea, i, start, end) {
+ db = &cea[i];
+ dbl = cea_db_payload_len(db);
+
+ if (cea_db_tag(db) == VIDEO_BLOCK)
+ modes += do_cea_modes (connector, db+1, dbl);
+ }
+ }
+
+ return modes;
+}
+
+static void
+parse_hdmi_vsdb(struct drm_connector *connector, const u8 *db)
+{
+ u8 len = cea_db_payload_len(db);
+
+ if (len >= 6) {
+ connector->eld[5] |= (db[6] >> 7) << 1; /* Supports_AI */
+ connector->dvi_dual = db[6] & 1;
+ }
+ if (len >= 7)
+ connector->max_tmds_clock = db[7] * 5;
+ if (len >= 8) {
+ connector->latency_present[0] = db[8] >> 7;
+ connector->latency_present[1] = (db[8] >> 6) & 1;
+ }
+ if (len >= 9)
+ connector->video_latency[0] = db[9];
+ if (len >= 10)
+ connector->audio_latency[0] = db[10];
+ if (len >= 11)
+ connector->video_latency[1] = db[11];
+ if (len >= 12)
+ connector->audio_latency[1] = db[12];
DRM_DEBUG_KMS("HDMI: DVI dual %d, "
"max TMDS clock %d, "
@@ -1521,6 +1678,21 @@ monitor_name(struct detailed_timing *t, void *data)
*(u8 **)data = t->data.other_data.data.str.str;
}
+static bool cea_db_is_hdmi_vsdb(const u8 *db)
+{
+ int hdmi_id;
+
+ if (cea_db_tag(db) != VENDOR_BLOCK)
+ return false;
+
+ if (cea_db_payload_len(db) < 5)
+ return false;
+
+ hdmi_id = db[1] | (db[2] << 8) | (db[3] << 16);
+
+ return hdmi_id == HDMI_IDENTIFIER;
+}
+
/**
* drm_edid_to_eld - build ELD from EDID
* @connector: connector corresponding to the HDMI/DP sink
@@ -1567,24 +1739,38 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
eld[18] = edid->prod_code[0];
eld[19] = edid->prod_code[1];
- for (db = cea + 4; db < cea + cea[2]; db += dbl + 1) {
- dbl = db[0] & 0x1f;
+ if (cea_revision(cea) >= 3) {
+ int i, start, end;
- switch ((db[0] & 0xe0) >> 5) {
- case AUDIO_BLOCK: /* Audio Data Block, contains SADs */
- sad_count = dbl / 3;
- memcpy(eld + 20 + mnl, &db[1], dbl);
- break;
- case SPEAKER_BLOCK: /* Speaker Allocation Data Block */
- eld[7] = db[1];
- break;
- case VENDOR_BLOCK:
- /* HDMI Vendor-Specific Data Block */
- if (db[1] == 0x03 && db[2] == 0x0c && db[3] == 0)
- parse_hdmi_vsdb(connector, db);
- break;
- default:
- break;
+ if (cea_db_offsets(cea, &start, &end)) {
+ start = 0;
+ end = 0;
+ }
+
+ for_each_cea_db(cea, i, start, end) {
+ db = &cea[i];
+ dbl = cea_db_payload_len(db);
+
+ switch (cea_db_tag(db)) {
+ case AUDIO_BLOCK:
+ /* Audio Data Block, contains SADs */
+ sad_count = dbl / 3;
+ if (dbl >= 1)
+ memcpy(eld + 20 + mnl, &db[1], dbl);
+ break;
+ case SPEAKER_BLOCK:
+ /* Speaker Allocation Data Block */
+ if (dbl >= 1)
+ eld[7] = db[1];
+ break;
+ case VENDOR_BLOCK:
+ /* HDMI Vendor-Specific Data Block */
+ if (cea_db_is_hdmi_vsdb(db))
+ parse_hdmi_vsdb(connector, db);
+ break;
+ default:
+ break;
+ }
}
}
eld[5] |= sad_count << 4;
@@ -1592,6 +1778,7 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
DRM_DEBUG_KMS("ELD size %d, SAD count %d\n", (int)eld[2], sad_count);
}
+EXPORT_SYMBOL(drm_edid_to_eld);
/**
* drm_av_sync_delay - HDMI/DP sink audio-video sync delay in millisecond
@@ -1629,6 +1816,7 @@ int drm_av_sync_delay(struct drm_connector *connector,
return max(v - a, 0);
}
+EXPORT_SYMBOL(drm_av_sync_delay);
/**
* drm_select_eld - select one ELD from multiple HDMI/DP sinks
@@ -1650,6 +1838,7 @@ struct drm_connector *drm_select_eld(struct drm_encoder *encoder,
return NULL;
}
+EXPORT_SYMBOL(drm_select_eld);
/**
* drm_detect_hdmi_monitor - detect whether monitor is hdmi.
@@ -1661,39 +1850,28 @@ struct drm_connector *drm_select_eld(struct drm_encoder *encoder,
bool drm_detect_hdmi_monitor(struct edid *edid)
{
u8 *edid_ext;
- int i, hdmi_id;
+ int i;
int start_offset, end_offset;
- bool is_hdmi = false;
edid_ext = drm_find_cea_extension(edid);
if (!edid_ext)
- goto end;
+ return false;
- /* Data block offset in CEA extension block */
- start_offset = 4;
- end_offset = edid_ext[2];
+ if (cea_db_offsets(edid_ext, &start_offset, &end_offset))
+ return false;
/*
* Because HDMI identifier is in Vendor Specific Block,
* search it from all data blocks of CEA extension.
*/
- for (i = start_offset; i < end_offset;
- /* Increased by data block len */
- i += ((edid_ext[i] & 0x1f) + 1)) {
- /* Find vendor specific block */
- if ((edid_ext[i] >> 5) == VENDOR_BLOCK) {
- hdmi_id = edid_ext[i + 1] | (edid_ext[i + 2] << 8) |
- edid_ext[i + 3] << 16;
- /* Find HDMI identifier */
- if (hdmi_id == HDMI_IDENTIFIER)
- is_hdmi = true;
- break;
- }
+ for_each_cea_db(edid_ext, i, start_offset, end_offset) {
+ if (cea_db_is_hdmi_vsdb(&edid_ext[i]))
+ return true;
}
-end:
- return is_hdmi;
+ return false;
}
+EXPORT_SYMBOL(drm_detect_hdmi_monitor);
/**
* drm_detect_monitor_audio - check monitor audio capability
@@ -1723,15 +1901,13 @@ bool drm_detect_monitor_audio(struct edid *edid)
goto end;
}
- /* Data block offset in CEA extension block */
- start_offset = 4;
- end_offset = edid_ext[2];
+ if (cea_db_offsets(edid_ext, &start_offset, &end_offset))
+ goto end;
- for (i = start_offset; i < end_offset;
- i += ((edid_ext[i] & 0x1f) + 1)) {
- if ((edid_ext[i] >> 5) == AUDIO_BLOCK) {
+ for_each_cea_db(edid_ext, i, start_offset, end_offset) {
+ if (cea_db_tag(&edid_ext[i]) == AUDIO_BLOCK) {
has_audio = true;
- for (j = 1; j < (edid_ext[i] & 0x1f); j += 3)
+ for (j = 1; j < cea_db_payload_len(&edid_ext[i]) + 1; j += 3)
DRM_DEBUG_KMS("CEA audio format %d\n",
(edid_ext[i + j] >> 3) & 0xf);
goto end;
@@ -1740,6 +1916,7 @@ bool drm_detect_monitor_audio(struct edid *edid)
end:
return has_audio;
}
+EXPORT_SYMBOL(drm_detect_monitor_audio);
/**
* drm_add_display_info - pull display info out if present
@@ -1835,7 +2012,7 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
return 0;
}
if (!drm_edid_is_valid(edid)) {
- device_printf(connector->dev->device, "%s: EDID invalid.\n",
+ dev_warn(connector->dev->dev, "%s: EDID invalid.\n",
drm_get_connector_name(connector));
return 0;
}
@@ -1860,7 +2037,9 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
num_modes += add_cvt_modes(connector, edid);
num_modes += add_standard_modes(connector, edid);
num_modes += add_established_modes(connector, edid);
- num_modes += add_inferred_modes(connector, edid);
+ if (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF)
+ num_modes += add_inferred_modes(connector, edid);
+ num_modes += add_cea_modes(connector, edid);
if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75))
edid_fixup_preferred(connector, quirks);
@@ -1869,6 +2048,7 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
return num_modes;
}
+EXPORT_SYMBOL(drm_add_edid_modes);
/**
* drm_add_modes_noedid - add modes for the connectors without EDID
@@ -1895,7 +2075,7 @@ int drm_add_modes_noedid(struct drm_connector *connector,
vdisplay = 0;
for (i = 0; i < count; i++) {
- struct drm_display_mode *ptr = &drm_dmt_modes[i];
+ const struct drm_display_mode *ptr = &drm_dmt_modes[i];
if (hdisplay && vdisplay) {
/*
* Only when two are valid, they will be used to check
@@ -1916,3 +2096,23 @@ int drm_add_modes_noedid(struct drm_connector *connector,
}
return num_modes;
}
+EXPORT_SYMBOL(drm_add_modes_noedid);
+
+/**
+ * drm_mode_cea_vic - return the CEA-861 VIC of a given mode
+ * @mode: mode
+ *
+ * RETURNS:
+ * The VIC number, 0 in case it's not a CEA-861 mode.
+ */
+uint8_t drm_mode_cea_vic(const struct drm_display_mode *mode)
+{
+ uint8_t i;
+
+ for (i = 0; i < drm_num_cea_modes; i++)
+ if (drm_mode_equal(mode, &edid_cea_modes[i]))
+ return i + 1;
+
+ return 0;
+}
+EXPORT_SYMBOL(drm_mode_cea_vic);
diff --git a/sys/dev/drm2/drm_edid.h b/sys/dev/drm2/drm_edid.h
index 3dfe6e3..0132b6f 100644
--- a/sys/dev/drm2/drm_edid.h
+++ b/sys/dev/drm2/drm_edid.h
@@ -25,9 +25,6 @@
#ifndef __DRM_EDID_H__
#define __DRM_EDID_H__
-#include <sys/types.h>
-#include <dev/drm2/drmP.h>
-
#define EDID_LENGTH 128
#define DDC_ADDR 0x50
@@ -99,7 +96,7 @@ struct detailed_data_monitor_range {
u8 reserved;
u8 hfreq_start_khz; /* need to multiply by 2 */
u8 c; /* need to divide by 2 */
- u16 m;
+ __le16 m;
u8 k;
u8 j; /* need to divide by 2 */
} __attribute__((packed)) gtf2;
@@ -159,7 +156,7 @@ struct detailed_non_pixel {
#define EDID_DETAIL_MONITOR_SERIAL 0xff
struct detailed_timing {
- u16 pixel_clock; /* need to multiply by 10 KHz */
+ __le16 pixel_clock; /* need to multiply by 10 KHz */
union {
struct detailed_pixel_timing pixel_data;
struct detailed_non_pixel other_data;
@@ -192,6 +189,7 @@ struct detailed_timing {
#define DRM_EDID_FEATURE_DEFAULT_GTF (1 << 0)
#define DRM_EDID_FEATURE_PREFERRED_TIMING (1 << 1)
#define DRM_EDID_FEATURE_STANDARD_COLOR (1 << 2)
+/* If analog */
#define DRM_EDID_FEATURE_DISPLAY_TYPE (3 << 3) /* 00=mono, 01=rgb, 10=non-rgb, 11=unknown */
/* If digital */
#define DRM_EDID_FEATURE_COLOR_MASK (3 << 3)
@@ -254,5 +252,6 @@ int drm_av_sync_delay(struct drm_connector *connector,
struct drm_display_mode *mode);
struct drm_connector *drm_select_eld(struct drm_encoder *encoder,
struct drm_display_mode *mode);
+int drm_load_edid_firmware(struct drm_connector *connector);
#endif /* __DRM_EDID_H__ */
diff --git a/sys/dev/drm2/drm_edid_modes.h b/sys/dev/drm2/drm_edid_modes.h
index b6431d3..27fe555 100644
--- a/sys/dev/drm2/drm_edid_modes.h
+++ b/sys/dev/drm2/drm_edid_modes.h
@@ -32,7 +32,7 @@
* Autogenerated from the DMT spec.
* This table is copied from xfree86/modes/xf86EdidModes.c.
*/
-static struct drm_display_mode drm_dmt_modes[] = {
+static const struct drm_display_mode drm_dmt_modes[] = {
/* 640x350@85Hz */
{ DRM_MODE("640x350", DRM_MODE_TYPE_DRIVER, 31500, 640, 672,
736, 832, 0, 350, 382, 385, 445, 0,
@@ -90,7 +90,7 @@ static struct drm_display_mode drm_dmt_modes[] = {
976, 1088, 0, 480, 486, 494, 517, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
/* 1024x768@43Hz, interlace */
- { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 44900, 1024, 1032,
+ { DRM_MODE("1024x768i", DRM_MODE_TYPE_DRIVER, 44900, 1024, 1032,
1208, 1264, 0, 768, 768, 772, 817, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
DRM_MODE_FLAG_INTERLACE) },
@@ -359,7 +359,7 @@ static struct drm_display_mode drm_dmt_modes[] = {
static const int drm_num_dmt_modes =
sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode);
-static struct drm_display_mode edid_est_modes[] = {
+static const struct drm_display_mode edid_est_modes[] = {
{ DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840,
968, 1056, 0, 600, 601, 605, 628, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@60Hz */
@@ -396,7 +396,7 @@ static struct drm_display_mode edid_est_modes[] = {
{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048,
1184, 1344, 0, 768, 771, 777, 806, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 1024x768@60Hz */
- { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER,44900, 1024, 1032,
+ { DRM_MODE("1024x768i", DRM_MODE_TYPE_DRIVER,44900, 1024, 1032,
1208, 1264, 0, 768, 768, 776, 817, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_INTERLACE) }, /* 1024x768@43Hz */
{ DRM_MODE("832x624", DRM_MODE_TYPE_DRIVER, 57284, 832, 864,
@@ -472,7 +472,7 @@ static const struct minimode est3_modes[] = {
{ 1920, 1440, 60, 0 },
{ 1920, 1440, 75, 0 },
};
-static const int num_est3_modes = DRM_ARRAY_SIZE(est3_modes);
+static const int num_est3_modes = ARRAY_SIZE(est3_modes);
static const struct minimode extra_modes[] = {
{ 1024, 576, 60, 0 },
@@ -483,7 +483,7 @@ static const struct minimode extra_modes[] = {
{ 2048, 1152, 60, 0 },
{ 2048, 1536, 60, 0 },
};
-static const int num_extra_modes = DRM_ARRAY_SIZE(extra_modes);
+static const int num_extra_modes = ARRAY_SIZE(extra_modes);
/*
* Probably taken from CEA-861 spec.
@@ -507,17 +507,17 @@ static const struct drm_display_mode edid_cea_modes[] = {
1430, 1650, 0, 720, 725, 730, 750, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
/* 5 - 1920x1080i@60Hz */
- { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2008,
+ { DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2008,
2052, 2200, 0, 1080, 1084, 1094, 1125, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
DRM_MODE_FLAG_INTERLACE) },
/* 6 - 1440x480i@60Hz */
- { DRM_MODE("1440x480", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1478,
+ { DRM_MODE("1440x480i", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1478,
1602, 1716, 0, 480, 488, 494, 525, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK) },
/* 7 - 1440x480i@60Hz */
- { DRM_MODE("1440x480", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1478,
+ { DRM_MODE("1440x480i", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1478,
1602, 1716, 0, 480, 488, 494, 525, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK) },
@@ -532,12 +532,12 @@ static const struct drm_display_mode edid_cea_modes[] = {
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
DRM_MODE_FLAG_DBLCLK) },
/* 10 - 2880x480i@60Hz */
- { DRM_MODE("2880x480", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2956,
+ { DRM_MODE("2880x480i", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2956,
3204, 3432, 0, 480, 488, 494, 525, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
DRM_MODE_FLAG_INTERLACE) },
/* 11 - 2880x480i@60Hz */
- { DRM_MODE("2880x480", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2956,
+ { DRM_MODE("2880x480i", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2956,
3204, 3432, 0, 480, 488, 494, 525, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
DRM_MODE_FLAG_INTERLACE) },
@@ -574,17 +574,17 @@ static const struct drm_display_mode edid_cea_modes[] = {
1760, 1980, 0, 720, 725, 730, 750, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
/* 20 - 1920x1080i@50Hz */
- { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2448,
+ { DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2448,
2492, 2640, 0, 1080, 1084, 1094, 1125, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
DRM_MODE_FLAG_INTERLACE) },
/* 21 - 1440x576i@50Hz */
- { DRM_MODE("1440x576", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1464,
+ { DRM_MODE("1440x576i", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1464,
1590, 1728, 0, 576, 580, 586, 625, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK) },
/* 22 - 1440x576i@50Hz */
- { DRM_MODE("1440x576", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1464,
+ { DRM_MODE("1440x576i", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1464,
1590, 1728, 0, 576, 580, 586, 625, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK) },
@@ -599,12 +599,12 @@ static const struct drm_display_mode edid_cea_modes[] = {
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
DRM_MODE_FLAG_DBLCLK) },
/* 25 - 2880x576i@50Hz */
- { DRM_MODE("2880x576", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2928,
+ { DRM_MODE("2880x576i", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2928,
3180, 3456, 0, 576, 580, 586, 625, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
DRM_MODE_FLAG_INTERLACE) },
/* 26 - 2880x576i@50Hz */
- { DRM_MODE("2880x576", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2928,
+ { DRM_MODE("2880x576i", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2928,
3180, 3456, 0, 576, 580, 586, 625, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
DRM_MODE_FLAG_INTERLACE) },
@@ -657,12 +657,12 @@ static const struct drm_display_mode edid_cea_modes[] = {
3184, 3456, 0, 576, 581, 586, 625, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
/* 39 - 1920x1080i@50Hz */
- { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 72000, 1920, 1952,
+ { DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 72000, 1920, 1952,
2120, 2304, 0, 1080, 1126, 1136, 1250, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC |
DRM_MODE_FLAG_INTERLACE) },
/* 40 - 1920x1080i@100Hz */
- { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2448,
+ { DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2448,
2492, 2640, 0, 1080, 1084, 1094, 1125, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
DRM_MODE_FLAG_INTERLACE) },
@@ -689,7 +689,7 @@ static const struct drm_display_mode edid_cea_modes[] = {
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
DRM_MODE_FLAG_DBLCLK) },
/* 46 - 1920x1080i@120Hz */
- { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2008,
+ { DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2008,
2052, 2200, 0, 1080, 1084, 1094, 1125, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
DRM_MODE_FLAG_INTERLACE) },
@@ -706,12 +706,12 @@ static const struct drm_display_mode edid_cea_modes[] = {
798, 858, 0, 480, 489, 495, 525, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
/* 50 - 1440x480i@120Hz */
- { DRM_MODE("1440x480", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1478,
+ { DRM_MODE("1440x480i", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1478,
1602, 1716, 0, 480, 488, 494, 525, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK) },
/* 51 - 1440x480i@120Hz */
- { DRM_MODE("1440x480", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1478,
+ { DRM_MODE("1440x480i", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1478,
1602, 1716, 0, 480, 488, 494, 525, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK) },
@@ -724,12 +724,12 @@ static const struct drm_display_mode edid_cea_modes[] = {
796, 864, 0, 576, 581, 586, 625, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
/* 54 - 1440x576i@200Hz */
- { DRM_MODE("1440x576", DRM_MODE_TYPE_DRIVER, 108000, 1440, 1464,
+ { DRM_MODE("1440x576i", DRM_MODE_TYPE_DRIVER, 108000, 1440, 1464,
1590, 1728, 0, 576, 580, 586, 625, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK) },
/* 55 - 1440x576i@200Hz */
- { DRM_MODE("1440x576", DRM_MODE_TYPE_DRIVER, 108000, 1440, 1464,
+ { DRM_MODE("1440x576i", DRM_MODE_TYPE_DRIVER, 108000, 1440, 1464,
1590, 1728, 0, 576, 580, 586, 625, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK) },
@@ -742,12 +742,12 @@ static const struct drm_display_mode edid_cea_modes[] = {
798, 858, 0, 480, 489, 495, 525, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
/* 58 - 1440x480i@240 */
- { DRM_MODE("1440x480", DRM_MODE_TYPE_DRIVER, 108000, 1440, 1478,
+ { DRM_MODE("1440x480i", DRM_MODE_TYPE_DRIVER, 108000, 1440, 1478,
1602, 1716, 0, 480, 488, 494, 525, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK) },
/* 59 - 1440x480i@240 */
- { DRM_MODE("1440x480", DRM_MODE_TYPE_DRIVER, 108000, 1440, 1478,
+ { DRM_MODE("1440x480i", DRM_MODE_TYPE_DRIVER, 108000, 1440, 1478,
1602, 1716, 0, 480, 488, 494, 525, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK) },
@@ -772,4 +772,4 @@ static const struct drm_display_mode edid_cea_modes[] = {
2492, 2640, 0, 1080, 1084, 1094, 1125, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
};
-static const int drm_num_cea_modes = DRM_ARRAY_SIZE(edid_cea_modes);
+static const int drm_num_cea_modes = ARRAY_SIZE(edid_cea_modes);
diff --git a/sys/dev/drm2/drm_fb_helper.c b/sys/dev/drm2/drm_fb_helper.c
index 473c3a5..2fd1ebb 100644
--- a/sys/dev/drm2/drm_fb_helper.c
+++ b/sys/dev/drm2/drm_fb_helper.c
@@ -31,24 +31,28 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <dev/drm2/drmP.h>
#include <dev/drm2/drm_crtc.h>
#include <dev/drm2/drm_fb_helper.h>
#include <dev/drm2/drm_crtc_helper.h>
+MODULE_AUTHOR("David Airlie, Jesse Barnes");
+MODULE_DESCRIPTION("DRM KMS helper");
+MODULE_LICENSE("GPL and additional rights");
+
+static DRM_LIST_HEAD(kernel_fb_helper_list);
#include <sys/kdb.h>
#include <sys/param.h>
#include <sys/systm.h>
struct vt_kms_softc {
- struct drm_fb_helper *fb_helper;
- struct task fb_mode_task;
+ struct drm_fb_helper *fb_helper;
+ struct task fb_mode_task;
};
-static fb_enter_t vt_kms_postswitch;
-static void vt_restore_fbdev_mode(void *, int);
-
/* Call restore out of vt(9) locks. */
static void
vt_restore_fbdev_mode(void *arg, int pending)
@@ -78,25 +82,29 @@ vt_kms_postswitch(void *arg)
return (0);
}
-static DRM_LIST_HEAD(kernel_fb_helper_list);
-
-/* simple single crtc case helper function */
-int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper)
+struct fb_info *
+framebuffer_alloc()
{
- struct drm_device *dev = fb_helper->dev;
- struct drm_connector *connector;
+ struct fb_info *info;
+ struct vt_kms_softc *sc;
- list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
- struct drm_fb_helper_connector *fb_helper_connector;
+ info = malloc(sizeof(*info), DRM_MEM_KMS, M_WAITOK | M_ZERO);
- fb_helper_connector = malloc(
- sizeof(struct drm_fb_helper_connector), DRM_MEM_KMS,
- M_WAITOK | M_ZERO);
+ sc = malloc(sizeof(*sc), DRM_MEM_KMS, M_WAITOK | M_ZERO);
+ TASK_INIT(&sc->fb_mode_task, 0, vt_restore_fbdev_mode, sc);
- fb_helper_connector->connector = connector;
- fb_helper->connector_info[fb_helper->connector_count++] = fb_helper_connector;
- }
- return 0;
+ info->fb_priv = sc;
+ info->enter = &vt_kms_postswitch;
+
+ return (info);
+}
+
+void
+framebuffer_release(struct fb_info *info)
+{
+
+ free(info->fb_priv, DRM_MEM_KMS);
+ free(info, DRM_MEM_KMS);
}
static int
@@ -126,8 +134,46 @@ fb_get_options(const char *connector_name, char **option)
if (*option == NULL)
*option = getenv("kern.vt.fb.default_mode");
- return (*option != NULL ? 0 : 1);
+ return (*option != NULL ? 0 : -ENOENT);
+}
+
+/**
+ * DOC: fbdev helpers
+ *
+ * The fb helper functions are useful to provide an fbdev on top of a drm kernel
+ * mode setting driver. They can be used mostly independantely from the crtc
+ * helper functions used by many drivers to implement the kernel mode setting
+ * interfaces.
+ */
+
+/* simple single crtc case helper function */
+int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper)
+{
+ struct drm_device *dev = fb_helper->dev;
+ struct drm_connector *connector;
+ int i;
+
+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+ struct drm_fb_helper_connector *fb_helper_connector;
+
+ fb_helper_connector = malloc(sizeof(struct drm_fb_helper_connector),
+ DRM_MEM_KMS, M_NOWAIT | M_ZERO);
+ if (!fb_helper_connector)
+ goto fail;
+
+ fb_helper_connector->connector = connector;
+ fb_helper->connector_info[fb_helper->connector_count++] = fb_helper_connector;
+ }
+ return 0;
+fail:
+ for (i = 0; i < fb_helper->connector_count; i++) {
+ free(fb_helper->connector_info[i], DRM_MEM_KMS);
+ fb_helper->connector_info[i] = NULL;
+ }
+ fb_helper->connector_count = 0;
+ return -ENOMEM;
}
+EXPORT_SYMBOL(drm_fb_helper_single_add_all_connectors);
static int drm_fb_helper_parse_command_line(struct drm_fb_helper *fb_helper)
{
@@ -170,7 +216,7 @@ static int drm_fb_helper_parse_command_line(struct drm_fb_helper *fb_helper)
connector->force = mode->force;
}
- DRM_INFO("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n",
+ DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n",
drm_get_connector_name(connector),
mode->xres, mode->yres,
mode->refresh_specified ? mode->refresh : 60,
@@ -180,12 +226,11 @@ static int drm_fb_helper_parse_command_line(struct drm_fb_helper *fb_helper)
}
freeenv(option);
-
}
return 0;
}
-#if 0
+#if 0 && defined(FREEBSD_NOTYET)
static void drm_fb_helper_save_lut_atomic(struct drm_crtc *crtc, struct drm_fb_helper *helper)
{
uint16_t *r_base, *g_base, *b_base;
@@ -212,9 +257,7 @@ static void drm_fb_helper_restore_lut_atomic(struct drm_crtc *crtc)
crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, 0, crtc->gamma_size);
}
-#endif
-#if 0
int drm_fb_helper_debug_enter(struct fb_info *info)
{
struct drm_fb_helper *helper = info->par;
@@ -244,9 +287,8 @@ int drm_fb_helper_debug_enter(struct fb_info *info)
return 0;
}
-#endif
+EXPORT_SYMBOL(drm_fb_helper_debug_enter);
-#if 0
/* Find the real fb for a given fb helper CRTC */
static struct drm_framebuffer *drm_mode_config_fb(struct drm_crtc *crtc)
{
@@ -260,9 +302,7 @@ static struct drm_framebuffer *drm_mode_config_fb(struct drm_crtc *crtc)
return NULL;
}
-#endif
-#if 0
int drm_fb_helper_debug_leave(struct fb_info *info)
{
struct drm_fb_helper *helper = info->par;
@@ -292,7 +332,8 @@ int drm_fb_helper_debug_leave(struct fb_info *info)
return 0;
}
-#endif
+EXPORT_SYMBOL(drm_fb_helper_debug_leave);
+#endif /* FREEBSD_NOTYET */
bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper)
{
@@ -300,15 +341,15 @@ bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper)
int i, ret;
for (i = 0; i < fb_helper->crtc_count; i++) {
struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;
- ret = drm_crtc_helper_set_config(mode_set);
+ ret = mode_set->crtc->funcs->set_config(mode_set);
if (ret)
error = true;
}
return error;
}
+EXPORT_SYMBOL(drm_fb_helper_restore_fbdev_mode);
-#if 0
-bool drm_fb_helper_force_kernel_mode(void)
+static bool drm_fb_helper_force_kernel_mode(void)
{
bool ret, error = false;
struct drm_fb_helper *helper;
@@ -326,20 +367,27 @@ bool drm_fb_helper_force_kernel_mode(void)
}
return error;
}
-#endif
-#if 0
+#if 0 && defined(FREEBSD_NOTYET)
int drm_fb_helper_panic(struct notifier_block *n, unsigned long ununsed,
void *panic_str)
{
- printf("panic occurred, switching back to text console\n");
+ /*
+ * It's a waste of time and effort to switch back to text console
+ * if the kernel should reboot before panic messages can be seen.
+ */
+ if (panic_timeout < 0)
+ return 0;
+
+ pr_err("panic occurred, switching back to text console\n");
return drm_fb_helper_force_kernel_mode();
- return 0;
}
+EXPORT_SYMBOL(drm_fb_helper_panic);
static struct notifier_block paniced = {
.notifier_call = drm_fb_helper_panic,
};
+#endif /* FREEBSD_NOTYET */
/**
* drm_fb_helper_restore - restore the framebuffer console (kernel) config
@@ -353,7 +401,9 @@ void drm_fb_helper_restore(void)
if (ret == true)
DRM_ERROR("Failed to restore crtc configuration\n");
}
+EXPORT_SYMBOL(drm_fb_helper_restore);
+#ifdef __linux__
#ifdef CONFIG_MAGIC_SYSRQ
static void drm_fb_helper_restore_work_fn(struct work_struct *ignored)
{
@@ -376,127 +426,64 @@ static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = { };
#endif
#endif
-#if 0
-static void drm_fb_helper_on(struct fb_info *info)
-{
- struct drm_fb_helper *fb_helper = info->par;
- struct drm_device *dev = fb_helper->dev;
- struct drm_crtc *crtc;
- struct drm_crtc_helper_funcs *crtc_funcs;
- struct drm_connector *connector;
- struct drm_encoder *encoder;
- int i, j;
-
- /*
- * For each CRTC in this fb, turn the crtc on then,
- * find all associated encoders and turn them on.
- */
- sx_xlock(&dev->mode_config.mutex);
- for (i = 0; i < fb_helper->crtc_count; i++) {
- crtc = fb_helper->crtc_info[i].mode_set.crtc;
- crtc_funcs = crtc->helper_private;
-
- if (!crtc->enabled)
- continue;
-
- crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
-
- /* Walk the connectors & encoders on this fb turning them on */
- for (j = 0; j < fb_helper->connector_count; j++) {
- connector = fb_helper->connector_info[j]->connector;
- connector->dpms = DRM_MODE_DPMS_ON;
- drm_connector_property_set_value(connector,
- dev->mode_config.dpms_property,
- DRM_MODE_DPMS_ON);
- }
- /* Found a CRTC on this fb, now find encoders */
- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
- if (encoder->crtc == crtc) {
- struct drm_encoder_helper_funcs *encoder_funcs;
-
- encoder_funcs = encoder->helper_private;
- encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
- }
- }
- }
- sx_xunlock(&dev->mode_config.mutex);
-}
-#endif
-
-#if 0
-static void drm_fb_helper_off(struct fb_info *info, int dpms_mode)
+#if 0 && defined(FREEBSD_NOTYET)
+static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode)
{
struct drm_fb_helper *fb_helper = info->par;
struct drm_device *dev = fb_helper->dev;
struct drm_crtc *crtc;
- struct drm_crtc_helper_funcs *crtc_funcs;
struct drm_connector *connector;
- struct drm_encoder *encoder;
int i, j;
/*
- * For each CRTC in this fb, find all associated encoders
- * and turn them off, then turn off the CRTC.
+ * For each CRTC in this fb, turn the connectors on/off.
*/
sx_xlock(&dev->mode_config.mutex);
for (i = 0; i < fb_helper->crtc_count; i++) {
crtc = fb_helper->crtc_info[i].mode_set.crtc;
- crtc_funcs = crtc->helper_private;
if (!crtc->enabled)
continue;
- /* Walk the connectors on this fb and mark them off */
+ /* Walk the connectors & encoders on this fb turning them on/off */
for (j = 0; j < fb_helper->connector_count; j++) {
connector = fb_helper->connector_info[j]->connector;
- connector->dpms = dpms_mode;
- drm_connector_property_set_value(connector,
- dev->mode_config.dpms_property,
- dpms_mode);
+ connector->funcs->dpms(connector, dpms_mode);
+ drm_object_property_set_value(&connector->base,
+ dev->mode_config.dpms_property, dpms_mode);
}
- /* Found a CRTC on this fb, now find encoders */
- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
- if (encoder->crtc == crtc) {
- struct drm_encoder_helper_funcs *encoder_funcs;
-
- encoder_funcs = encoder->helper_private;
- encoder_funcs->dpms(encoder, dpms_mode);
- }
- }
- crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
}
sx_xunlock(&dev->mode_config.mutex);
}
-#endif
-#if 0
int drm_fb_helper_blank(int blank, struct fb_info *info)
{
switch (blank) {
/* Display: On; HSync: On, VSync: On */
case FB_BLANK_UNBLANK:
- drm_fb_helper_on(info);
+ drm_fb_helper_dpms(info, DRM_MODE_DPMS_ON);
break;
/* Display: Off; HSync: On, VSync: On */
case FB_BLANK_NORMAL:
- drm_fb_helper_off(info, DRM_MODE_DPMS_STANDBY);
+ drm_fb_helper_dpms(info, DRM_MODE_DPMS_STANDBY);
break;
/* Display: Off; HSync: Off, VSync: On */
case FB_BLANK_HSYNC_SUSPEND:
- drm_fb_helper_off(info, DRM_MODE_DPMS_STANDBY);
+ drm_fb_helper_dpms(info, DRM_MODE_DPMS_STANDBY);
break;
/* Display: Off; HSync: On, VSync: Off */
case FB_BLANK_VSYNC_SUSPEND:
- drm_fb_helper_off(info, DRM_MODE_DPMS_SUSPEND);
+ drm_fb_helper_dpms(info, DRM_MODE_DPMS_SUSPEND);
break;
/* Display: Off; HSync: Off, VSync: Off */
case FB_BLANK_POWERDOWN:
- drm_fb_helper_off(info, DRM_MODE_DPMS_OFF);
+ drm_fb_helper_dpms(info, DRM_MODE_DPMS_OFF);
break;
}
return 0;
}
-#endif
+EXPORT_SYMBOL(drm_fb_helper_blank);
+#endif /* FREEBSD_NOTYET */
static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper)
{
@@ -524,52 +511,64 @@ int drm_fb_helper_init(struct drm_device *dev,
INIT_LIST_HEAD(&fb_helper->kernel_fb_list);
- fb_helper->crtc_info = malloc(crtc_count *
- sizeof(struct drm_fb_helper_crtc), DRM_MEM_KMS, M_WAITOK | M_ZERO);
+ fb_helper->crtc_info = malloc(crtc_count * sizeof(struct drm_fb_helper_crtc),
+ DRM_MEM_KMS, M_NOWAIT | M_ZERO);
+ if (!fb_helper->crtc_info)
+ return -ENOMEM;
fb_helper->crtc_count = crtc_count;
- fb_helper->connector_info = malloc(dev->mode_config.num_connector *
- sizeof(struct drm_fb_helper_connector *), DRM_MEM_KMS,
- M_WAITOK | M_ZERO);
+ fb_helper->connector_info = malloc(dev->mode_config.num_connector * sizeof(struct drm_fb_helper_connector *),
+ DRM_MEM_KMS, M_NOWAIT | M_ZERO);
+ if (!fb_helper->connector_info) {
+ free(fb_helper->crtc_info, DRM_MEM_KMS);
+ return -ENOMEM;
+ }
fb_helper->connector_count = 0;
for (i = 0; i < crtc_count; i++) {
fb_helper->crtc_info[i].mode_set.connectors =
- malloc(max_conn_count * sizeof(struct drm_connector *),
- DRM_MEM_KMS, M_WAITOK | M_ZERO);
+ malloc(max_conn_count *
+ sizeof(struct drm_connector *),
+ DRM_MEM_KMS, M_NOWAIT | M_ZERO);
+ if (!fb_helper->crtc_info[i].mode_set.connectors)
+ goto out_free;
fb_helper->crtc_info[i].mode_set.num_connectors = 0;
}
i = 0;
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
- fb_helper->crtc_info[i].crtc_id = crtc->base.id;
fb_helper->crtc_info[i].mode_set.crtc = crtc;
i++;
}
- fb_helper->conn_limit = max_conn_count;
+
return 0;
+out_free:
+ drm_fb_helper_crtc_free(fb_helper);
+ return -ENOMEM;
}
+EXPORT_SYMBOL(drm_fb_helper_init);
void drm_fb_helper_fini(struct drm_fb_helper *fb_helper)
{
if (!list_empty(&fb_helper->kernel_fb_list)) {
list_del(&fb_helper->kernel_fb_list);
+#if 0 && defined(FREEBSD_NOTYET)
if (list_empty(&kernel_fb_helper_list)) {
-#if 0
- printk(KERN_INFO "drm: unregistered panic notifier\n");
+ pr_info("drm: unregistered panic notifier\n");
atomic_notifier_chain_unregister(&panic_notifier_list,
&paniced);
unregister_sysrq_key('v', &sysrq_drm_fb_helper_restore_op);
-#endif
}
+#endif /* FREEBSD_NOTYET */
}
drm_fb_helper_crtc_free(fb_helper);
}
+EXPORT_SYMBOL(drm_fb_helper_fini);
-#if 0
+#if 0 && defined(FREEBSD_NOTYET)
static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green,
u16 blue, u16 regno, struct fb_info *info)
{
@@ -577,7 +576,7 @@ static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green,
struct drm_framebuffer *fb = fb_helper->fb;
int pindex;
- if (info->fix.visual == FB_VISUAL_trueCOLOR) {
+ if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
u32 *palette;
u32 value;
/* place color in psuedopalette */
@@ -633,9 +632,7 @@ static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green,
fb_helper->funcs->gamma_set(crtc, red, green, blue, pindex);
return 0;
}
-#endif
-#if 0
int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info)
{
struct drm_fb_helper *fb_helper = info->par;
@@ -673,9 +670,8 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info)
}
return rc;
}
-#endif
+EXPORT_SYMBOL(drm_fb_helper_setcmap);
-#if 0
int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
struct fb_info *info)
{
@@ -766,9 +762,8 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
}
return 0;
}
-#endif
+EXPORT_SYMBOL(drm_fb_helper_check_var);
-#if 0
/* this will let fbcon do the mode init */
int drm_fb_helper_set_par(struct fb_info *info)
{
@@ -784,16 +779,16 @@ int drm_fb_helper_set_par(struct fb_info *info)
return -EINVAL;
}
- mutex_lock(&dev->mode_config.mutex);
+ sx_xlock(&dev->mode_config.mutex);
for (i = 0; i < fb_helper->crtc_count; i++) {
crtc = fb_helper->crtc_info[i].mode_set.crtc;
ret = crtc->funcs->set_config(&fb_helper->crtc_info[i].mode_set);
if (ret) {
- mutex_unlock(&dev->mode_config.mutex);
+ sx_xunlock(&dev->mode_config.mutex);
return ret;
}
}
- mutex_unlock(&dev->mode_config.mutex);
+ sx_xunlock(&dev->mode_config.mutex);
if (fb_helper->delayed_hotplug) {
fb_helper->delayed_hotplug = false;
@@ -801,9 +796,8 @@ int drm_fb_helper_set_par(struct fb_info *info)
}
return 0;
}
-#endif
+EXPORT_SYMBOL(drm_fb_helper_set_par);
-#if 0
int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
@@ -814,7 +808,7 @@ int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
int ret = 0;
int i;
- mutex_lock(&dev->mode_config.mutex);
+ sx_xlock(&dev->mode_config.mutex);
for (i = 0; i < fb_helper->crtc_count; i++) {
crtc = fb_helper->crtc_info[i].mode_set.crtc;
@@ -831,10 +825,11 @@ int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
}
}
}
- mutex_unlock(&dev->mode_config.mutex);
+ sx_xunlock(&dev->mode_config.mutex);
return ret;
}
-#endif
+EXPORT_SYMBOL(drm_fb_helper_pan_display);
+#endif /* FREEBSD_NOTYET */
int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
int preferred_bpp)
@@ -845,8 +840,9 @@ int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
struct fb_info *info;
struct drm_fb_helper_surface_size sizes;
int gamma_size = 0;
- struct vt_kms_softc *sc;
+#if defined(__FreeBSD__)
device_t kdev;
+#endif
memset(&sizes, 0, sizeof(struct drm_fb_helper_surface_size));
sizes.surface_depth = 24;
@@ -856,9 +852,9 @@ int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
/* if driver picks 8 or 16 by default use that
for both depth/bpp */
- if (preferred_bpp != sizes.surface_bpp) {
+ if (preferred_bpp != sizes.surface_bpp)
sizes.surface_depth = sizes.surface_bpp = preferred_bpp;
- }
+
/* first up get a count of crtcs now in use and new min/maxes width/heights */
for (i = 0; i < fb_helper->connector_count; i++) {
struct drm_fb_helper_connector *fb_helper_conn = fb_helper->connector_info[i];
@@ -923,31 +919,18 @@ int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
if (new_fb < 0)
return new_fb;
- sc = malloc(sizeof(struct vt_kms_softc), DRM_MEM_KMS,
- M_WAITOK | M_ZERO);
- sc->fb_helper = fb_helper;
- TASK_INIT(&sc->fb_mode_task, 0, vt_restore_fbdev_mode, sc);
-
info = fb_helper->fbdev;
- info->fb_name = device_get_nameunit(fb_helper->dev->device);
- info->fb_depth = fb_helper->fb->bits_per_pixel;
- info->fb_height = fb_helper->fb->height;
- info->fb_width = fb_helper->fb->width;
- info->fb_stride = fb_helper->fb->pitches[0];
- info->fb_priv = sc;
- info->enter = &vt_kms_postswitch;
-
/* set the fb pointer */
- for (i = 0; i < fb_helper->crtc_count; i++) {
+ for (i = 0; i < fb_helper->crtc_count; i++)
fb_helper->crtc_info[i].mode_set.fb = fb_helper->fb;
- }
+#if defined(__FreeBSD__)
if (new_fb) {
device_t fbd;
int ret;
- kdev = fb_helper->dev->device;
+ kdev = fb_helper->dev->dev;
fbd = device_add_child(kdev, "fbd", device_get_unit(kdev));
if (fbd != NULL)
ret = device_probe_and_attach(fbd);
@@ -958,102 +941,61 @@ int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
DRM_ERROR("Failed to attach fbd device: %d\n", ret);
#endif
}
+#else
+ if (new_fb) {
+ info->var.pixclock = 0;
+ if (register_framebuffer(info) < 0)
+ return -EINVAL;
+
+ dev_info(fb_helper->dev->dev, "fb%d: %s frame buffer device\n",
+ info->node, info->fix.id);
+
+ } else {
+ drm_fb_helper_set_par(info);
+ }
+#endif
+
+#if 0 && defined(FREEBSD_NOTYET)
+ /* Switch back to kernel console on panic */
+ /* multi card linked list maybe */
+ if (list_empty(&kernel_fb_helper_list)) {
+ dev_info(fb_helper->dev->dev, "registered panic notifier\n");
+ atomic_notifier_chain_register(&panic_notifier_list,
+ &paniced);
+ register_sysrq_key('v', &sysrq_drm_fb_helper_restore_op);
+ }
+#endif /* FREEBSD_NOTYET */
+ if (new_fb)
+ list_add(&fb_helper->kernel_fb_list, &kernel_fb_helper_list);
+
return 0;
}
+EXPORT_SYMBOL(drm_fb_helper_single_fb_probe);
-#if 0
void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
uint32_t depth)
{
- info->fix.type = FB_TYPE_PACKED_PIXELS;
- info->fix.visual = depth == 8 ? FB_VISUAL_PSEUDOCOLOR :
- FB_VISUAL_trueCOLOR;
- info->fix.mmio_start = 0;
- info->fix.mmio_len = 0;
- info->fix.type_aux = 0;
- info->fix.xpanstep = 1; /* doing it in hw */
- info->fix.ypanstep = 1; /* doing it in hw */
- info->fix.ywrapstep = 0;
- info->fix.accel = FB_ACCEL_NONE;
- info->fix.type_aux = 0;
-
- info->fix.line_length = pitch;
+ info->fb_stride = pitch;
+
return;
}
+EXPORT_SYMBOL(drm_fb_helper_fill_fix);
void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helper,
uint32_t fb_width, uint32_t fb_height)
{
struct drm_framebuffer *fb = fb_helper->fb;
- info->pseudo_palette = fb_helper->pseudo_palette;
- info->var.xres_virtual = fb->width;
- info->var.yres_virtual = fb->height;
- info->var.bits_per_pixel = fb->bits_per_pixel;
- info->var.accel_flags = FB_ACCELF_TEXT;
- info->var.xoffset = 0;
- info->var.yoffset = 0;
- info->var.activate = FB_ACTIVATE_NOW;
- info->var.height = -1;
- info->var.width = -1;
-
- switch (fb->depth) {
- case 8:
- info->var.red.offset = 0;
- info->var.green.offset = 0;
- info->var.blue.offset = 0;
- info->var.red.length = 8; /* 8bit DAC */
- info->var.green.length = 8;
- info->var.blue.length = 8;
- info->var.transp.offset = 0;
- info->var.transp.length = 0;
- break;
- case 15:
- info->var.red.offset = 10;
- info->var.green.offset = 5;
- info->var.blue.offset = 0;
- info->var.red.length = 5;
- info->var.green.length = 5;
- info->var.blue.length = 5;
- info->var.transp.offset = 15;
- info->var.transp.length = 1;
- break;
- case 16:
- info->var.red.offset = 11;
- info->var.green.offset = 5;
- info->var.blue.offset = 0;
- info->var.red.length = 5;
- info->var.green.length = 6;
- info->var.blue.length = 5;
- info->var.transp.offset = 0;
- break;
- case 24:
- info->var.red.offset = 16;
- info->var.green.offset = 8;
- info->var.blue.offset = 0;
- info->var.red.length = 8;
- info->var.green.length = 8;
- info->var.blue.length = 8;
- info->var.transp.offset = 0;
- info->var.transp.length = 0;
- break;
- case 32:
- info->var.red.offset = 16;
- info->var.green.offset = 8;
- info->var.blue.offset = 0;
- info->var.red.length = 8;
- info->var.green.length = 8;
- info->var.blue.length = 8;
- info->var.transp.offset = 24;
- info->var.transp.length = 8;
- break;
- default:
- break;
- }
+ struct vt_kms_softc *sc;
+
+ info->fb_name = device_get_nameunit(fb_helper->dev->dev);
+ info->fb_width = fb->width;
+ info->fb_height = fb->height;
+ info->fb_depth = fb->bits_per_pixel;
- info->var.xres = fb_width;
- info->var.yres = fb_height;
+ sc = (struct vt_kms_softc *)info->fb_priv;
+ sc->fb_helper = fb_helper;
}
-#endif
+EXPORT_SYMBOL(drm_fb_helper_fill_var);
static int drm_fb_helper_probe_connector_modes(struct drm_fb_helper *fb_helper,
uint32_t maxX,
@@ -1100,7 +1042,7 @@ static struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_conne
cmdline_mode = &fb_helper_conn->cmdline_mode;
if (cmdline_mode->specified == false)
- return (NULL);
+ return mode;
/* attempt to find a matching mode in the list of modes
* we have gotten so far, if not add a CVT mode that conforms
@@ -1127,19 +1069,8 @@ static struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_conne
}
create_mode:
- if (cmdline_mode->cvt)
- mode = drm_cvt_mode(fb_helper_conn->connector->dev,
- cmdline_mode->xres, cmdline_mode->yres,
- cmdline_mode->refresh_specified ? cmdline_mode->refresh : 60,
- cmdline_mode->rb, cmdline_mode->interlace,
- cmdline_mode->margins);
- else
- mode = drm_gtf_mode(fb_helper_conn->connector->dev,
- cmdline_mode->xres, cmdline_mode->yres,
- cmdline_mode->refresh_specified ? cmdline_mode->refresh : 60,
- cmdline_mode->interlace,
- cmdline_mode->margins);
- drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
+ mode = drm_mode_create_from_cmdline_mode(fb_helper_conn->connector->dev,
+ cmdline_mode);
list_add(&mode->head, &fb_helper_conn->connector->modes);
return mode;
}
@@ -1148,11 +1079,11 @@ static bool drm_connector_enabled(struct drm_connector *connector, bool strict)
{
bool enable;
- if (strict) {
+ if (strict)
enable = connector->status == connector_status_connected;
- } else {
+ else
enable = connector->status != connector_status_disconnected;
- }
+
return enable;
}
@@ -1315,8 +1246,9 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
return best_score;
crtcs = malloc(dev->mode_config.num_connector *
- sizeof(struct drm_fb_helper_crtc *), DRM_MEM_KMS,
- M_WAITOK | M_ZERO);
+ sizeof(struct drm_fb_helper_crtc *), DRM_MEM_KMS, M_NOWAIT | M_ZERO);
+ if (!crtcs)
+ return best_score;
my_score = 1;
if (connector->status == connector_status_connected)
@@ -1336,9 +1268,8 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
for (c = 0; c < fb_helper->crtc_count; c++) {
crtc = &fb_helper->crtc_info[c];
- if ((encoder->possible_crtcs & (1 << c)) == 0) {
+ if ((encoder->possible_crtcs & (1 << c)) == 0)
continue;
- }
for (o = 0; o < n; o++)
if (best_crtcs[o] == crtc)
@@ -1375,7 +1306,6 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
struct drm_device *dev = fb_helper->dev;
struct drm_fb_helper_crtc **crtcs;
struct drm_display_mode **modes;
- struct drm_encoder *encoder;
struct drm_mode_set *modeset;
bool *enabled;
int width, height;
@@ -1386,19 +1316,17 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
width = dev->mode_config.max_width;
height = dev->mode_config.max_height;
- /* clean out all the encoder/crtc combos */
- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
- encoder->crtc = NULL;
- }
-
crtcs = malloc(dev->mode_config.num_connector *
- sizeof(struct drm_fb_helper_crtc *), DRM_MEM_KMS,
- M_WAITOK | M_ZERO);
+ sizeof(struct drm_fb_helper_crtc *), DRM_MEM_KMS, M_NOWAIT | M_ZERO);
modes = malloc(dev->mode_config.num_connector *
- sizeof(struct drm_display_mode *), DRM_MEM_KMS,
- M_WAITOK | M_ZERO);
+ sizeof(struct drm_display_mode *), DRM_MEM_KMS, M_NOWAIT | M_ZERO);
enabled = malloc(dev->mode_config.num_connector *
- sizeof(bool), DRM_MEM_KMS, M_WAITOK | M_ZERO);
+ sizeof(bool), DRM_MEM_KMS, M_NOWAIT | M_ZERO);
+ if (!crtcs || !modes || !enabled) {
+ DRM_ERROR("Memory allocation failed\n");
+ goto out;
+ }
+
drm_enable_connectors(fb_helper, enabled);
@@ -1437,6 +1365,7 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
}
}
+out:
free(crtcs, DRM_MEM_KMS);
free(modes, DRM_MEM_KMS);
free(enabled, DRM_MEM_KMS);
@@ -1444,12 +1373,14 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
/**
* drm_helper_initial_config - setup a sane initial connector configuration
- * @dev: DRM device
+ * @fb_helper: fb_helper device struct
+ * @bpp_sel: bpp value to use for the framebuffer configuration
*
* LOCKING:
- * Called at init time, must take mode config lock.
+ * Called at init time by the driver to set up the @fb_helper initial
+ * configuration, must take the mode config lock.
*
- * Scan the CRTCs and connectors and try to put together an initial setup.
+ * Scans the CRTCs and connectors and tries to put together an initial setup.
* At the moment, this is a cloned configuration across all heads with
* a new framebuffer object as the backing store.
*
@@ -1472,20 +1403,35 @@ bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel)
/*
* we shouldn't end up with no modes here.
*/
- if (count == 0) {
- printf("No connectors reported connected with modes\n");
- }
+ if (count == 0)
+ dev_info(fb_helper->dev->dev, "No connectors reported connected with modes\n");
+
drm_setup_crtcs(fb_helper);
return drm_fb_helper_single_fb_probe(fb_helper, bpp_sel);
}
+EXPORT_SYMBOL(drm_fb_helper_initial_config);
+/**
+ * drm_fb_helper_hotplug_event - respond to a hotplug notification by
+ * probing all the outputs attached to the fb
+ * @fb_helper: the drm_fb_helper
+ *
+ * LOCKING:
+ * Called at runtime, must take mode config lock.
+ *
+ * Scan the connectors attached to the fb_helper and try to put together a
+ * setup after *notification of a change in output configuration.
+ *
+ * RETURNS:
+ * 0 on success and a non-zero error code otherwise.
+ */
int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
{
struct drm_device *dev = fb_helper->dev;
int count = 0;
u32 max_width, max_height, bpp_sel;
- bool bound = false, crtcs_bound = false;
+ int bound = 0, crtcs_bound = 0;
struct drm_crtc *crtc;
if (!fb_helper->fb)
@@ -1494,12 +1440,12 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
sx_xlock(&dev->mode_config.mutex);
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
if (crtc->fb)
- crtcs_bound = true;
+ crtcs_bound++;
if (crtc->fb == fb_helper->fb)
- bound = true;
+ bound++;
}
- if (!bound && crtcs_bound) {
+ if (bound < crtcs_bound) {
fb_helper->delayed_hotplug = true;
sx_xunlock(&dev->mode_config.mutex);
return 0;
@@ -1517,4 +1463,4 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
return drm_fb_helper_single_fb_probe(fb_helper, bpp_sel);
}
-
+EXPORT_SYMBOL(drm_fb_helper_hotplug_event);
diff --git a/sys/dev/drm2/drm_fb_helper.h b/sys/dev/drm2/drm_fb_helper.h
index 16ef7ee..c292752 100644
--- a/sys/dev/drm2/drm_fb_helper.h
+++ b/sys/dev/drm2/drm_fb_helper.h
@@ -35,7 +35,6 @@
struct drm_fb_helper;
struct drm_fb_helper_crtc {
- uint32_t crtc_id;
struct drm_mode_set mode_set;
struct drm_display_mode *desired_mode;
};
@@ -74,7 +73,6 @@ struct drm_fb_helper {
int connector_count;
struct drm_fb_helper_connector **connector_info;
struct drm_fb_helper_funcs *funcs;
- int conn_limit;
struct fb_info *fbdev;
u32 pseudo_palette[17];
struct list_head kernel_fb_list;
@@ -84,9 +82,6 @@ struct drm_fb_helper {
bool delayed_hotplug;
};
-struct fb_var_screeninfo;
-struct fb_cmap;
-
int drm_fb_helper_single_fb_probe(struct drm_fb_helper *helper,
int preferred_bpp);
@@ -95,11 +90,15 @@ int drm_fb_helper_init(struct drm_device *dev,
int max_conn);
void drm_fb_helper_fini(struct drm_fb_helper *helper);
int drm_fb_helper_blank(int blank, struct fb_info *info);
+#ifdef FREEBSD_NOTYET
int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info);
+#endif /* FREEBSD_NOTYET */
int drm_fb_helper_set_par(struct fb_info *info);
+#ifdef FREEBSD_NOTYET
int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
struct fb_info *info);
+#endif /* FREEBSD_NOTYET */
int drm_fb_helper_setcolreg(unsigned regno,
unsigned red,
unsigned green,
@@ -114,13 +113,14 @@ void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helpe
void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
uint32_t depth);
+#ifdef FREEBSD_NOTYET
int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info);
+#endif /* FREEBSD_NOTYET */
int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper);
bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel);
int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper);
int drm_fb_helper_debug_enter(struct fb_info *info);
int drm_fb_helper_debug_leave(struct fb_info *info);
-bool drm_fb_helper_force_kernel_mode(void);
#endif
diff --git a/sys/dev/drm2/drm_fops.c b/sys/dev/drm2/drm_fops.c
index 2685ff7..b73cec6 100644
--- a/sys/dev/drm2/drm_fops.c
+++ b/sys/dev/drm2/drm_fops.c
@@ -1,4 +1,15 @@
-/*-
+/**
+ * \file drm_fops.c
+ * File operations for DRM
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Daryll Strauss <daryll@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
+ * Created: Mon Jan 4 08:58:31 1999 by faith@valinux.com
+ *
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
* All Rights Reserved.
@@ -21,51 +32,177 @@
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Rickard E. (Rik) Faith <faith@valinux.com>
- * Daryll Strauss <daryll@valinux.com>
- * Gareth Hughes <gareth@valinux.com>
- *
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-/** @file drm_fops.c
- * Support code for dealing with the file privates associated with each
- * open of the DRM device.
+#include <dev/drm2/drmP.h>
+
+static int drm_open_helper(struct cdev *kdev, int flags, int fmt,
+ DRM_STRUCTPROC *p, struct drm_device *dev);
+
+static int drm_setup(struct drm_device * dev)
+{
+ int i;
+ int ret;
+
+ if (dev->driver->firstopen) {
+ ret = dev->driver->firstopen(dev);
+ if (ret != 0)
+ return ret;
+ }
+
+ atomic_set(&dev->ioctl_count, 0);
+ atomic_set(&dev->vma_count, 0);
+
+ if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) &&
+ !drm_core_check_feature(dev, DRIVER_MODESET)) {
+ dev->buf_use = 0;
+ atomic_set(&dev->buf_alloc, 0);
+
+ i = drm_dma_setup(dev);
+ if (i < 0)
+ return i;
+ }
+
+ /*
+ * FIXME Linux<->FreeBSD: counter incremented in drm_open() and
+ * reset to 0 here.
+ */
+#if 0
+ for (i = 0; i < ARRAY_SIZE(dev->counts); i++)
+ atomic_set(&dev->counts[i], 0);
+#endif
+
+ dev->sigdata.lock = NULL;
+
+ dev->context_flag = 0;
+ dev->interrupt_flag = 0;
+ dev->dma_flag = 0;
+ dev->last_context = 0;
+ dev->last_switch = 0;
+ dev->last_checked = 0;
+ DRM_INIT_WAITQUEUE(&dev->context_wait);
+ dev->if_version = 0;
+
+#ifdef FREEBSD_NOTYET
+ dev->ctx_start = 0;
+ dev->lck_start = 0;
+
+ dev->buf_async = NULL;
+ DRM_INIT_WAITQUEUE(&dev->buf_readers);
+ DRM_INIT_WAITQUEUE(&dev->buf_writers);
+#endif /* FREEBSD_NOTYET */
+
+ DRM_DEBUG("\n");
+
+ /*
+ * The kernel's context could be created here, but is now created
+ * in drm_dma_enqueue. This is more resource-efficient for
+ * hardware that does not do DMA, but may mean that
+ * drm_select_queue fails between the time the interrupt is
+ * initialized and the time the queues are initialized.
+ */
+
+ return 0;
+}
+
+/**
+ * Open file.
+ *
+ * \param inode device inode
+ * \param filp file pointer.
+ * \return zero on success or a negative number on failure.
+ *
+ * Searches the DRM device with the same minor number, calls open_helper(), and
+ * increments the device open count. If the open count was previous at zero,
+ * i.e., it's the first that the device is open, then calls setup().
*/
+int drm_open(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p)
+{
+ struct drm_device *dev = NULL;
+ struct drm_minor *minor;
+ int retcode = 0;
+ int need_setup = 0;
-#include <dev/drm2/drmP.h>
+ minor = kdev->si_drv1;
+ if (!minor)
+ return ENODEV;
+
+ if (!(dev = minor->dev))
+ return ENODEV;
+
+ sx_xlock(&drm_global_mutex);
-/* drm_open_helper is called whenever a process opens /dev/drm. */
-int drm_open_helper(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p,
- struct drm_device *dev)
+ /*
+ * FIXME Linux<->FreeBSD: On Linux, counter updated outisde
+ * global mutex.
+ */
+ if (!dev->open_count++)
+ need_setup = 1;
+
+ retcode = drm_open_helper(kdev, flags, fmt, p, dev);
+ if (retcode) {
+ sx_xunlock(&drm_global_mutex);
+ return (-retcode);
+ }
+ atomic_inc(&dev->counts[_DRM_STAT_OPENS]);
+ if (need_setup) {
+ retcode = drm_setup(dev);
+ if (retcode)
+ goto err_undo;
+ }
+ sx_xunlock(&drm_global_mutex);
+ return 0;
+
+err_undo:
+ mtx_lock(&Giant); /* FIXME: Giant required? */
+ device_unbusy(dev->dev);
+ mtx_unlock(&Giant);
+ dev->open_count--;
+ sx_xunlock(&drm_global_mutex);
+ return -retcode;
+}
+EXPORT_SYMBOL(drm_open);
+
+/**
+ * Called whenever a process opens /dev/drm.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param dev device.
+ * \return zero on success or a negative number on failure.
+ *
+ * Creates and initializes a drm_file structure for the file private data in \p
+ * filp and add it into the double linked list in \p dev.
+ */
+static int drm_open_helper(struct cdev *kdev, int flags, int fmt,
+ DRM_STRUCTPROC *p, struct drm_device *dev)
{
struct drm_file *priv;
- int retcode;
+ int ret;
if (flags & O_EXCL)
- return EBUSY; /* No exclusive opens */
- dev->flags = flags;
+ return -EBUSY; /* No exclusive opens */
+ if (dev->switch_power_state != DRM_SWITCH_POWER_ON)
+ return -EINVAL;
DRM_DEBUG("pid = %d, device = %s\n", DRM_CURRENTPID, devtoname(kdev));
priv = malloc(sizeof(*priv), DRM_MEM_FILES, M_NOWAIT | M_ZERO);
- if (priv == NULL) {
- return ENOMEM;
- }
-
- DRM_LOCK(dev);
- priv->dev = dev;
- priv->uid = p->td_ucred->cr_svuid;
- priv->pid = p->td_proc->p_pid;
- priv->ioctl_count = 0;
+ if (!priv)
+ return -ENOMEM;
+ priv->uid = p->td_ucred->cr_svuid;
+ priv->pid = p->td_proc->p_pid;
+ priv->minor = kdev->si_drv1;
+ priv->ioctl_count = 0;
/* for compatibility root is always authenticated */
- priv->authenticated = DRM_SUSER(p);
+ priv->authenticated = DRM_SUSER(p);
+ priv->lock_count = 0;
+ INIT_LIST_HEAD(&priv->lhead);
INIT_LIST_HEAD(&priv->fbs);
INIT_LIST_HEAD(&priv->event_list);
priv->event_space = 4096; /* set aside 4k for event buffer */
@@ -73,47 +210,289 @@ int drm_open_helper(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p,
if (dev->driver->driver_features & DRIVER_GEM)
drm_gem_open(dev, priv);
+#ifdef FREEBSD_NOTYET
+ if (drm_core_check_feature(dev, DRIVER_PRIME))
+ drm_prime_init_file_private(&priv->prime);
+#endif /* FREEBSD_NOTYET */
+
if (dev->driver->open) {
- /* shared code returns -errno */
- retcode = -dev->driver->open(dev, priv);
- if (retcode != 0) {
- free(priv, DRM_MEM_FILES);
+ ret = dev->driver->open(dev, priv);
+ if (ret < 0)
+ goto out_free;
+ }
+
+
+ /* if there is no current master make this fd it */
+ DRM_LOCK(dev);
+ if (!priv->minor->master) {
+ /* create a new master */
+ priv->minor->master = drm_master_create(priv->minor);
+ if (!priv->minor->master) {
DRM_UNLOCK(dev);
- return retcode;
+ ret = -ENOMEM;
+ goto out_free;
+ }
+
+ priv->is_master = 1;
+ /* take another reference for the copy in the local file priv */
+ priv->master = drm_master_get(priv->minor->master);
+
+ priv->authenticated = 1;
+
+ DRM_UNLOCK(dev);
+ if (dev->driver->master_create) {
+ ret = dev->driver->master_create(dev, priv->master);
+ if (ret) {
+ DRM_LOCK(dev);
+ /* drop both references if this fails */
+ drm_master_put(&priv->minor->master);
+ drm_master_put(&priv->master);
+ DRM_UNLOCK(dev);
+ goto out_free;
+ }
+ }
+ DRM_LOCK(dev);
+ if (dev->driver->master_set) {
+ ret = dev->driver->master_set(dev, priv, true);
+ if (ret) {
+ /* drop both references if this fails */
+ drm_master_put(&priv->minor->master);
+ drm_master_put(&priv->master);
+ DRM_UNLOCK(dev);
+ goto out_free;
+ }
+ }
+ DRM_UNLOCK(dev);
+ } else {
+ /* get a reference to the master */
+ priv->master = drm_master_get(priv->minor->master);
+ DRM_UNLOCK(dev);
+ }
+
+ DRM_LOCK(dev);
+ list_add(&priv->lhead, &dev->filelist);
+ DRM_UNLOCK(dev);
+
+ mtx_lock(&Giant); /* FIXME: Giant required? */
+ device_busy(dev->dev);
+ mtx_unlock(&Giant);
+
+ ret = devfs_set_cdevpriv(priv, drm_release);
+ if (ret != 0)
+ drm_release(priv);
+
+ return ret;
+ out_free:
+ free(priv, DRM_MEM_FILES);
+ return ret;
+}
+
+static void drm_master_release(struct drm_device *dev, struct drm_file *file_priv)
+{
+
+ if (drm_i_have_hw_lock(dev, file_priv)) {
+ DRM_DEBUG("File %p released, freeing lock for context %d\n",
+ file_priv, _DRM_LOCKING_CONTEXT(file_priv->master->lock.hw_lock->lock));
+ drm_lock_free(&file_priv->master->lock,
+ _DRM_LOCKING_CONTEXT(file_priv->master->lock.hw_lock->lock));
+ }
+}
+
+static void drm_events_release(struct drm_file *file_priv)
+{
+ struct drm_device *dev = file_priv->minor->dev;
+ struct drm_pending_event *e, *et;
+ struct drm_pending_vblank_event *v, *vt;
+ unsigned long flags;
+
+ DRM_SPINLOCK_IRQSAVE(&dev->event_lock, flags);
+
+ /* Remove pending flips */
+ list_for_each_entry_safe(v, vt, &dev->vblank_event_list, base.link)
+ if (v->base.file_priv == file_priv) {
+ list_del(&v->base.link);
+ drm_vblank_put(dev, v->pipe);
+ v->base.destroy(&v->base);
+ }
+
+ /* Remove unconsumed events */
+ list_for_each_entry_safe(e, et, &file_priv->event_list, link)
+ e->destroy(e);
+
+ DRM_SPINUNLOCK_IRQRESTORE(&dev->event_lock, flags);
+}
+
+/**
+ * Release file.
+ *
+ * \param inode device inode
+ * \param file_priv DRM file private.
+ * \return zero on success or a negative number on failure.
+ *
+ * If the hardware lock is held then free it, and take it again for the kernel
+ * context since it's necessary to reclaim buffers. Unlink the file private
+ * data from its list and free it. Decreases the open count and if it reaches
+ * zero calls drm_lastclose().
+ */
+void drm_release(void *data)
+{
+ struct drm_file *file_priv = data;
+ struct drm_device *dev = file_priv->minor->dev;
+
+ sx_xlock(&drm_global_mutex);
+
+ DRM_DEBUG("open_count = %d\n", dev->open_count);
+
+ if (dev->driver->preclose)
+ dev->driver->preclose(dev, file_priv);
+
+ /* ========================================================
+ * Begin inline drm_release
+ */
+
+ DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
+ DRM_CURRENTPID,
+ (long)file_priv->minor->device,
+ dev->open_count);
+
+ /* Release any auth tokens that might point to this file_priv,
+ (do that under the drm_global_mutex) */
+ if (file_priv->magic)
+ (void) drm_remove_magic(file_priv->master, file_priv->magic);
+
+ /* if the master has gone away we can't do anything with the lock */
+ if (file_priv->minor->master)
+ drm_master_release(dev, file_priv);
+
+ if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+ drm_core_reclaim_buffers(dev, file_priv);
+
+ drm_events_release(file_priv);
+
+ seldrain(&file_priv->event_poll);
+
+ if (dev->driver->driver_features & DRIVER_MODESET)
+ drm_fb_release(file_priv);
+
+ if (dev->driver->driver_features & DRIVER_GEM)
+ drm_gem_release(dev, file_priv);
+
+#ifdef FREEBSD_NOTYET
+ mutex_lock(&dev->ctxlist_mutex);
+ if (!list_empty(&dev->ctxlist)) {
+ struct drm_ctx_list *pos, *n;
+
+ list_for_each_entry_safe(pos, n, &dev->ctxlist, head) {
+ if (pos->tag == file_priv &&
+ pos->handle != DRM_KERNEL_CONTEXT) {
+ if (dev->driver->context_dtor)
+ dev->driver->context_dtor(dev,
+ pos->handle);
+
+ drm_ctxbitmap_free(dev, pos->handle);
+
+ list_del(&pos->head);
+ kfree(pos);
+ --dev->ctx_count;
+ }
}
}
+ mutex_unlock(&dev->ctxlist_mutex);
+#endif /* FREEBSD_NOTYET */
+
+ DRM_LOCK(dev);
+
+ if (file_priv->is_master) {
+ struct drm_master *master = file_priv->master;
+ struct drm_file *temp;
+ list_for_each_entry(temp, &dev->filelist, lhead) {
+ if ((temp->master == file_priv->master) &&
+ (temp != file_priv))
+ temp->authenticated = 0;
+ }
+
+ /**
+ * Since the master is disappearing, so is the
+ * possibility to lock.
+ */
- /* first opener automatically becomes master */
- priv->master = TAILQ_EMPTY(&dev->files);
+ if (master->lock.hw_lock) {
+ if (dev->sigdata.lock == master->lock.hw_lock)
+ dev->sigdata.lock = NULL;
+ master->lock.hw_lock = NULL;
+ master->lock.file_priv = NULL;
+ DRM_WAKEUP_INT(&master->lock.lock_queue);
+ }
+
+ if (file_priv->minor->master == file_priv->master) {
+ /* drop the reference held my the minor */
+ if (dev->driver->master_drop)
+ dev->driver->master_drop(dev, file_priv, true);
+ drm_master_put(&file_priv->minor->master);
+ }
+ }
- TAILQ_INSERT_TAIL(&dev->files, priv, link);
+ /* drop the reference held my the file priv */
+ drm_master_put(&file_priv->master);
+ file_priv->is_master = 0;
+ list_del(&file_priv->lhead);
DRM_UNLOCK(dev);
- kdev->si_drv1 = dev;
- retcode = devfs_set_cdevpriv(priv, drm_close);
- if (retcode != 0)
- drm_close(priv);
+ if (dev->driver->postclose)
+ dev->driver->postclose(dev, file_priv);
- return (retcode);
+#ifdef FREEBSD_NOTYET
+ if (drm_core_check_feature(dev, DRIVER_PRIME))
+ drm_prime_destroy_file_private(&file_priv->prime);
+#endif /* FREEBSD_NOTYET */
+
+ free(file_priv, DRM_MEM_FILES);
+
+ /* ========================================================
+ * End inline drm_release
+ */
+
+ atomic_inc(&dev->counts[_DRM_STAT_CLOSES]);
+ mtx_lock(&Giant);
+ device_unbusy(dev->dev);
+ mtx_unlock(&Giant);
+ if (!--dev->open_count) {
+ if (atomic_read(&dev->ioctl_count)) {
+ DRM_ERROR("Device busy: %d\n",
+ atomic_read(&dev->ioctl_count));
+ } else
+ drm_lastclose(dev);
+ }
+ sx_xunlock(&drm_global_mutex);
}
+EXPORT_SYMBOL(drm_release);
static bool
-drm_dequeue_event(struct drm_device *dev, struct drm_file *file_priv,
- struct uio *uio, struct drm_pending_event **out)
+drm_dequeue_event(struct drm_file *file_priv, struct uio *uio,
+ struct drm_pending_event **out)
{
struct drm_pending_event *e;
+ bool ret = false;
+ /* Already locked in drm_read(). */
+ /* DRM_SPINLOCK_IRQSAVE(&dev->event_lock, flags); */
+
+ *out = NULL;
if (list_empty(&file_priv->event_list))
- return (false);
+ goto out;
e = list_first_entry(&file_priv->event_list,
- struct drm_pending_event, link);
+ struct drm_pending_event, link);
if (e->event->length > uio->uio_resid)
- return (false);
+ goto out;
file_priv->event_space += e->event->length;
list_del(&e->link);
*out = e;
- return (true);
+ ret = true;
+
+out:
+ /* DRM_SPINUNLOCK_IRQRESTORE(&dev->event_lock, flags); */
+ return ret;
}
int
@@ -122,13 +501,14 @@ drm_read(struct cdev *kdev, struct uio *uio, int ioflag)
struct drm_file *file_priv;
struct drm_device *dev;
struct drm_pending_event *e;
- int error;
+ ssize_t error;
error = devfs_get_cdevpriv((void **)&file_priv);
if (error != 0) {
DRM_ERROR("can't find authenticator\n");
return (EINVAL);
}
+
dev = drm_get_device_from_kdev(kdev);
mtx_lock(&dev->event_lock);
while (list_empty(&file_priv->event_list)) {
@@ -141,20 +521,24 @@ drm_read(struct cdev *kdev, struct uio *uio, int ioflag)
if (error != 0)
goto out;
}
- while (drm_dequeue_event(dev, file_priv, uio, &e)) {
+
+ while (drm_dequeue_event(file_priv, uio, &e)) {
mtx_unlock(&dev->event_lock);
error = uiomove(e->event, e->event->length, uio);
CTR3(KTR_DRM, "drm_event_dequeued %d %d %d", curproc->p_pid,
e->event->type, e->event->length);
+
e->destroy(e);
if (error != 0)
return (error);
mtx_lock(&dev->event_lock);
}
+
out:
mtx_unlock(&dev->event_lock);
return (error);
}
+EXPORT_SYMBOL(drm_read);
void
drm_event_wakeup(struct drm_pending_event *e)
@@ -163,7 +547,7 @@ drm_event_wakeup(struct drm_pending_event *e)
struct drm_device *dev;
file_priv = e->file_priv;
- dev = file_priv->dev;
+ dev = file_priv->minor->dev;
mtx_assert(&dev->event_lock, MA_OWNED);
wakeup(&file_priv->event_space);
@@ -182,6 +566,7 @@ drm_poll(struct cdev *kdev, int events, struct thread *td)
DRM_ERROR("can't find authenticator\n");
return (EINVAL);
}
+
dev = drm_get_device_from_kdev(kdev);
revents = 0;
@@ -198,3 +583,21 @@ drm_poll(struct cdev *kdev, int events, struct thread *td)
mtx_unlock(&dev->event_lock);
return (revents);
}
+EXPORT_SYMBOL(drm_poll);
+
+int
+drm_mmap_single(struct cdev *kdev, vm_ooffset_t *offset, vm_size_t size,
+ struct vm_object **obj_res, int nprot)
+{
+ struct drm_device *dev;
+
+ dev = drm_get_device_from_kdev(kdev);
+ if (dev->drm_ttm_bdev != NULL) {
+ return (-ttm_bo_mmap_single(dev->drm_ttm_bdev, offset, size,
+ obj_res, nprot));
+ } else if ((dev->driver->driver_features & DRIVER_GEM) != 0) {
+ return (-drm_gem_mmap_single(dev, offset, size, obj_res, nprot));
+ } else {
+ return (ENODEV);
+ }
+}
diff --git a/sys/dev/drm2/drm_fourcc.h b/sys/dev/drm2/drm_fourcc.h
index 0e871df..bb35a6e 100644
--- a/sys/dev/drm2/drm_fourcc.h
+++ b/sys/dev/drm2/drm_fourcc.h
@@ -26,10 +26,8 @@
#ifndef DRM_FOURCC_H
#define DRM_FOURCC_H
-#include <sys/types.h>
-
-#define fourcc_code(a, b, c, d) ((uint32_t)(a) | ((uint32_t)(b) << 8) | \
- ((uint32_t)(c) << 16) | ((uint32_t)(d) << 24))
+#define fourcc_code(a, b, c, d) ((__u32)(a) | ((__u32)(b) << 8) | \
+ ((__u32)(c) << 16) | ((__u32)(d) << 24))
#define DRM_FORMAT_BIG_ENDIAN (1<<31) /* format is big endian instead of little endian */
@@ -108,9 +106,10 @@
#define DRM_FORMAT_NV21 fourcc_code('N', 'V', '2', '1') /* 2x2 subsampled Cb:Cr plane */
#define DRM_FORMAT_NV16 fourcc_code('N', 'V', '1', '6') /* 2x1 subsampled Cr:Cb plane */
#define DRM_FORMAT_NV61 fourcc_code('N', 'V', '6', '1') /* 2x1 subsampled Cb:Cr plane */
+#define DRM_FORMAT_NV24 fourcc_code('N', 'V', '2', '4') /* non-subsampled Cr:Cb plane */
+#define DRM_FORMAT_NV42 fourcc_code('N', 'V', '4', '2') /* non-subsampled Cb:Cr plane */
-/* 2 non contiguous plane YCbCr */
-#define DRM_FORMAT_NV12M fourcc_code('N', 'M', '1', '2') /* 2x2 subsampled Cr:Cb plane */
+/* special NV12 tiled format */
#define DRM_FORMAT_NV12MT fourcc_code('T', 'M', '1', '2') /* 2x2 subsampled Cr:Cb plane 64x32 macroblocks */
/*
@@ -133,7 +132,4 @@
#define DRM_FORMAT_YUV444 fourcc_code('Y', 'U', '2', '4') /* non-subsampled Cb (1) and Cr (2) planes */
#define DRM_FORMAT_YVU444 fourcc_code('Y', 'V', '2', '4') /* non-subsampled Cr (1) and Cb (2) planes */
-/* 3 non contiguous plane YCbCr */
-#define DRM_FORMAT_YUV420M fourcc_code('Y', 'M', '1', '2') /* 2x2 subsampled Cb (1) and Cr (2) planes */
-
#endif /* DRM_FOURCC_H */
diff --git a/sys/dev/drm2/drm_gem.c b/sys/dev/drm2/drm_gem.c
index 04b7659..aaf9962 100644
--- a/sys/dev/drm2/drm_gem.c
+++ b/sys/dev/drm2/drm_gem.c
@@ -54,7 +54,7 @@ __FBSDID("$FreeBSD$");
* the faked up offset will fit
*/
-#if ULONG_MAX == UINT64_MAX
+#if BITS_PER_LONG == 64
#define DRM_FILE_PAGE_OFFSET_START ((0xFFFFFFFFUL >> PAGE_SHIFT) + 1)
#define DRM_FILE_PAGE_OFFSET_SIZE ((0xFFFFFFFFUL >> PAGE_SHIFT) * 16)
#else
@@ -62,28 +62,40 @@ __FBSDID("$FreeBSD$");
#define DRM_FILE_PAGE_OFFSET_SIZE ((0xFFFFFFFUL >> PAGE_SHIFT) * 16)
#endif
+/**
+ * Initialize the GEM device fields
+ */
+
int
drm_gem_init(struct drm_device *dev)
{
struct drm_gem_mm *mm;
drm_gem_names_init(&dev->object_names);
- mm = malloc(sizeof(*mm), DRM_MEM_DRIVER, M_WAITOK);
+
+ mm = malloc(sizeof(*mm), DRM_MEM_DRIVER, M_NOWAIT);
+ if (!mm) {
+ DRM_ERROR("out of memory\n");
+ return -ENOMEM;
+ }
+
dev->mm_private = mm;
- if (drm_ht_create(&mm->offset_hash, 19) != 0) {
+
+ if (drm_ht_create(&mm->offset_hash, 19)) {
free(mm, DRM_MEM_DRIVER);
- return (ENOMEM);
+ return -ENOMEM;
}
+
mm->idxunr = new_unrhdr(0, DRM_GEM_MAX_IDX, NULL);
- return (0);
+
+ return 0;
}
void
drm_gem_destroy(struct drm_device *dev)
{
- struct drm_gem_mm *mm;
+ struct drm_gem_mm *mm = dev->mm_private;
- mm = dev->mm_private;
dev->mm_private = NULL;
drm_ht_remove(&mm->offset_hash);
delete_unrhdr(mm->idxunr);
@@ -91,11 +103,9 @@ drm_gem_destroy(struct drm_device *dev)
drm_gem_names_fini(&dev->object_names);
}
-int
-drm_gem_object_init(struct drm_device *dev, struct drm_gem_object *obj,
- size_t size)
+int drm_gem_object_init(struct drm_device *dev,
+ struct drm_gem_object *obj, size_t size)
{
-
KASSERT((size & (PAGE_SIZE - 1)) == 0,
("Bad size %ju", (uintmax_t)size));
@@ -107,14 +117,18 @@ drm_gem_object_init(struct drm_device *dev, struct drm_gem_object *obj,
obj->handle_count = 0;
obj->size = size;
- return (0);
+ return 0;
}
+EXPORT_SYMBOL(drm_gem_object_init);
-int
-drm_gem_private_object_init(struct drm_device *dev, struct drm_gem_object *obj,
- size_t size)
+/**
+ * Initialize an already allocated GEM object of the specified size with
+ * no GEM provided backing store. Instead the caller is responsible for
+ * backing the object and handling it.
+ */
+int drm_gem_private_object_init(struct drm_device *dev,
+ struct drm_gem_object *obj, size_t size)
{
-
MPASS((size & (PAGE_SIZE - 1)) == 0);
obj->dev = dev;
@@ -124,283 +138,298 @@ drm_gem_private_object_init(struct drm_device *dev, struct drm_gem_object *obj,
atomic_store_rel_int(&obj->handle_count, 0);
obj->size = size;
- return (0);
+ return 0;
}
-
+EXPORT_SYMBOL(drm_gem_private_object_init);
struct drm_gem_object *
drm_gem_object_alloc(struct drm_device *dev, size_t size)
{
struct drm_gem_object *obj;
- obj = malloc(sizeof(*obj), DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
+ obj = malloc(sizeof(*obj), DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
+ if (!obj)
+ goto free;
+
if (drm_gem_object_init(dev, obj, size) != 0)
goto free;
if (dev->driver->gem_init_object != NULL &&
- dev->driver->gem_init_object(obj) != 0)
+ dev->driver->gem_init_object(obj) != 0) {
goto dealloc;
- return (obj);
+ }
+ return obj;
dealloc:
vm_object_deallocate(obj->vm_obj);
free:
free(obj, DRM_MEM_DRIVER);
- return (NULL);
+ return NULL;
}
+EXPORT_SYMBOL(drm_gem_object_alloc);
-void
-drm_gem_object_free(struct drm_gem_object *obj)
+#if defined(FREEBSD_NOTYET)
+static void
+drm_gem_remove_prime_handles(struct drm_gem_object *obj, struct drm_file *filp)
{
- struct drm_device *dev;
-
- dev = obj->dev;
- DRM_LOCK_ASSERT(dev);
- if (dev->driver->gem_free_object != NULL)
- dev->driver->gem_free_object(obj);
-}
-
-void
-drm_gem_object_reference(struct drm_gem_object *obj)
-{
-
- KASSERT(obj->refcount > 0, ("Dangling obj %p", obj));
- refcount_acquire(&obj->refcount);
-}
-
-void
-drm_gem_object_unreference(struct drm_gem_object *obj)
-{
-
- if (obj == NULL)
- return;
- if (refcount_release(&obj->refcount))
- drm_gem_object_free(obj);
+ if (obj->import_attach) {
+ drm_prime_remove_buf_handle(&filp->prime,
+ obj->import_attach->dmabuf);
+ }
+ if (obj->export_dma_buf) {
+ drm_prime_remove_buf_handle(&filp->prime,
+ obj->export_dma_buf);
+ }
}
+#endif
-void
-drm_gem_object_unreference_unlocked(struct drm_gem_object *obj)
+/**
+ * Removes the mapping from handle to filp for this object.
+ */
+int
+drm_gem_handle_delete(struct drm_file *filp, u32 handle)
{
struct drm_device *dev;
+ struct drm_gem_object *obj;
- if (obj == NULL)
- return;
+ obj = drm_gem_names_remove(&filp->object_names, handle);
+ if (obj == NULL) {
+ return -EINVAL;
+ }
dev = obj->dev;
- DRM_LOCK(dev);
- drm_gem_object_unreference(obj);
- DRM_UNLOCK(dev);
-}
-void
-drm_gem_object_handle_reference(struct drm_gem_object *obj)
-{
+#if defined(FREEBSD_NOTYET)
+ drm_gem_remove_prime_handles(obj, filp);
+#endif
- drm_gem_object_reference(obj);
- atomic_add_rel_int(&obj->handle_count, 1);
+ if (dev->driver->gem_close_object)
+ dev->driver->gem_close_object(obj, filp);
+ drm_gem_object_handle_unreference_unlocked(obj);
+
+ return 0;
}
+EXPORT_SYMBOL(drm_gem_handle_delete);
-void
-drm_gem_object_handle_free(struct drm_gem_object *obj)
+/**
+ * Create a handle for this object. This adds a handle reference
+ * to the object, which includes a regular reference count. Callers
+ * will likely want to dereference the object afterwards.
+ */
+int
+drm_gem_handle_create(struct drm_file *file_priv,
+ struct drm_gem_object *obj,
+ u32 *handlep)
{
- struct drm_device *dev;
- struct drm_gem_object *obj1;
+ struct drm_device *dev = obj->dev;
+ int ret;
- dev = obj->dev;
- if (obj->name != 0) {
- obj1 = drm_gem_names_remove(&dev->object_names, obj->name);
- obj->name = 0;
- drm_gem_object_unreference(obj1);
- }
-}
+ *handlep = 0;
+ ret = drm_gem_name_create(&file_priv->object_names, obj, handlep);
+ if (ret != 0)
+ return ret;
-void
-drm_gem_object_handle_unreference(struct drm_gem_object *obj)
-{
+ drm_gem_object_handle_reference(obj);
- if (obj == NULL ||
- atomic_load_acq_int(&obj->handle_count) == 0)
- return;
+ if (dev->driver->gem_open_object) {
+ ret = dev->driver->gem_open_object(obj, file_priv);
+ if (ret) {
+ drm_gem_handle_delete(file_priv, *handlep);
+ return ret;
+ }
+ }
- if (atomic_fetchadd_int(&obj->handle_count, -1) == 1)
- drm_gem_object_handle_free(obj);
- drm_gem_object_unreference(obj);
+ return 0;
}
+EXPORT_SYMBOL(drm_gem_handle_create);
void
-drm_gem_object_handle_unreference_unlocked(struct drm_gem_object *obj)
+drm_gem_free_mmap_offset(struct drm_gem_object *obj)
{
+ struct drm_device *dev = obj->dev;
+ struct drm_gem_mm *mm = dev->mm_private;
+ struct drm_hash_item *list = &obj->map_list;
- if (obj == NULL ||
- atomic_load_acq_int(&obj->handle_count) == 0)
+ if (!obj->on_map)
return;
- if (atomic_fetchadd_int(&obj->handle_count, -1) == 1)
- drm_gem_object_handle_free(obj);
- drm_gem_object_unreference_unlocked(obj);
+ drm_ht_remove_item(&mm->offset_hash, list);
+ free_unr(mm->idxunr, list->key);
+ obj->on_map = false;
}
+EXPORT_SYMBOL(drm_gem_free_mmap_offset);
int
-drm_gem_handle_create(struct drm_file *file_priv, struct drm_gem_object *obj,
- uint32_t *handle)
+drm_gem_create_mmap_offset(struct drm_gem_object *obj)
{
struct drm_device *dev = obj->dev;
+ struct drm_gem_mm *mm = dev->mm_private;
int ret;
- ret = drm_gem_name_create(&file_priv->object_names, obj, handle);
- if (ret != 0)
- return (ret);
- drm_gem_object_handle_reference(obj);
+ if (obj->on_map)
+ return 0;
- if (dev->driver->gem_open_object) {
- ret = dev->driver->gem_open_object(obj, file_priv);
- if (ret) {
- drm_gem_handle_delete(file_priv, *handle);
- return ret;
- }
+ obj->map_list.key = alloc_unr(mm->idxunr);
+ ret = drm_ht_insert_item(&mm->offset_hash, &obj->map_list);
+ if (ret) {
+ DRM_ERROR("failed to add to map hash\n");
+ free_unr(mm->idxunr, obj->map_list.key);
+ return ret;
}
+ obj->on_map = true;
- return (0);
+ return 0;
}
+EXPORT_SYMBOL(drm_gem_create_mmap_offset);
-int
-drm_gem_handle_delete(struct drm_file *file_priv, uint32_t handle)
+/** Returns a reference to the object named by the handle. */
+struct drm_gem_object *
+drm_gem_object_lookup(struct drm_device *dev, struct drm_file *filp,
+ u32 handle)
{
- struct drm_device *dev;
struct drm_gem_object *obj;
- obj = drm_gem_names_remove(&file_priv->object_names, handle);
- if (obj == NULL)
- return (EINVAL);
+ obj = drm_gem_name_ref(&filp->object_names, handle,
+ (void (*)(void *))drm_gem_object_reference);
- dev = obj->dev;
- if (dev->driver->gem_close_object)
- dev->driver->gem_close_object(obj, file_priv);
- drm_gem_object_handle_unreference_unlocked(obj);
+ return obj;
+}
+EXPORT_SYMBOL(drm_gem_object_lookup);
- return (0);
+int
+drm_gem_close_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_gem_close *args = data;
+ int ret;
+
+ if (!(dev->driver->driver_features & DRIVER_GEM))
+ return -ENODEV;
+
+ ret = drm_gem_handle_delete(file_priv, args->handle);
+
+ return ret;
}
-void
-drm_gem_object_release(struct drm_gem_object *obj)
+int
+drm_gem_flink_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
+ struct drm_gem_flink *args = data;
+ struct drm_gem_object *obj;
+ int ret;
- /*
- * obj->vm_obj can be NULL for private gem objects.
- */
- vm_object_deallocate(obj->vm_obj);
+ if (!(dev->driver->driver_features & DRIVER_GEM))
+ return -ENODEV;
+
+ obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+ if (obj == NULL)
+ return -ENOENT;
+
+ ret = drm_gem_name_create(&dev->object_names, obj, &obj->name);
+ if (ret != 0) {
+ if (ret == -EALREADY)
+ ret = 0;
+ drm_gem_object_unreference_unlocked(obj);
+ }
+ if (ret == 0)
+ args->name = obj->name;
+ return ret;
}
int
drm_gem_open_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
+ struct drm_file *file_priv)
{
- struct drm_gem_open *args;
+ struct drm_gem_open *args = data;
struct drm_gem_object *obj;
int ret;
- uint32_t handle;
+ u32 handle;
- if (!drm_core_check_feature(dev, DRIVER_GEM))
- return (ENODEV);
- args = data;
+ if (!(dev->driver->driver_features & DRIVER_GEM))
+ return -ENODEV;
obj = drm_gem_name_ref(&dev->object_names, args->name,
(void (*)(void *))drm_gem_object_reference);
- if (obj == NULL)
- return (ENOENT);
- handle = 0;
+ if (!obj)
+ return -ENOENT;
+
ret = drm_gem_handle_create(file_priv, obj, &handle);
drm_gem_object_unreference_unlocked(obj);
- if (ret != 0)
- return (ret);
-
+ if (ret)
+ return ret;
+
args->handle = handle;
args->size = obj->size;
- return (0);
+ return 0;
}
void
-drm_gem_open(struct drm_device *dev, struct drm_file *file_priv)
+drm_gem_open(struct drm_device *dev, struct drm_file *file_private)
{
- drm_gem_names_init(&file_priv->object_names);
+ drm_gem_names_init(&file_private->object_names);
}
static int
-drm_gem_object_release_handle(uint32_t name, void *ptr, void *arg)
+drm_gem_object_release_handle(uint32_t name, void *ptr, void *data)
{
- struct drm_file *file_priv;
- struct drm_gem_object *obj;
- struct drm_device *dev;
+ struct drm_file *file_priv = data;
+ struct drm_gem_object *obj = ptr;
+ struct drm_device *dev = obj->dev;
- file_priv = arg;
- obj = ptr;
- dev = obj->dev;
+#if defined(FREEBSD_NOTYET)
+ drm_gem_remove_prime_handles(obj, file_priv);
+#endif
if (dev->driver->gem_close_object)
dev->driver->gem_close_object(obj, file_priv);
- drm_gem_object_handle_unreference(obj);
- return (0);
+ drm_gem_object_handle_unreference_unlocked(obj);
+
+ return 0;
}
void
-drm_gem_release(struct drm_device *dev, struct drm_file *file_priv)
+drm_gem_release(struct drm_device *dev, struct drm_file *file_private)
{
+ drm_gem_names_foreach(&file_private->object_names,
+ drm_gem_object_release_handle, file_private);
- drm_gem_names_foreach(&file_priv->object_names,
- drm_gem_object_release_handle, file_priv);
- drm_gem_names_fini(&file_priv->object_names);
+ drm_gem_names_fini(&file_private->object_names);
}
-int
-drm_gem_close_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
+void
+drm_gem_object_release(struct drm_gem_object *obj)
{
- struct drm_gem_close *args;
-
- if (!drm_core_check_feature(dev, DRIVER_GEM))
- return (ENODEV);
- args = data;
- return (drm_gem_handle_delete(file_priv, args->handle));
+ /*
+ * obj->vm_obj can be NULL for private gem objects.
+ */
+ vm_object_deallocate(obj->vm_obj);
}
+EXPORT_SYMBOL(drm_gem_object_release);
-int
-drm_gem_flink_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
+void
+drm_gem_object_free(struct drm_gem_object *obj)
{
- struct drm_gem_flink *args;
- struct drm_gem_object *obj;
- int error;
-
- if (!drm_core_check_feature(dev, DRIVER_GEM))
- return (ENODEV);
- args = data;
+ struct drm_device *dev = obj->dev;
- obj = drm_gem_name_ref(&file_priv->object_names, args->handle,
- (void (*)(void *))drm_gem_object_reference);
- if (obj == NULL)
- return (ENOENT);
- error = drm_gem_name_create(&dev->object_names, obj, &obj->name);
- if (error != 0) {
- if (error == EALREADY)
- error = 0;
- drm_gem_object_unreference_unlocked(obj);
- }
- if (error == 0)
- args->name = obj->name;
- return (error);
+ DRM_LOCK_ASSERT(dev);
+ if (dev->driver->gem_free_object != NULL)
+ dev->driver->gem_free_object(obj);
}
+EXPORT_SYMBOL(drm_gem_object_free);
-struct drm_gem_object *
-drm_gem_object_lookup(struct drm_device *dev, struct drm_file *file_priv,
- uint32_t handle)
+void drm_gem_object_handle_free(struct drm_gem_object *obj)
{
- struct drm_gem_object *obj;
+ struct drm_device *dev = obj->dev;
+ struct drm_gem_object *obj1;
- obj = drm_gem_name_ref(&file_priv->object_names, handle,
- (void (*)(void *))drm_gem_object_reference);
- return (obj);
+ if (obj->name) {
+ obj1 = drm_gem_names_remove(&dev->object_names, obj->name);
+ obj->name = 0;
+ drm_gem_object_unreference(obj1);
+ }
}
static struct drm_gem_object *
@@ -425,46 +454,6 @@ drm_gem_object_from_offset(struct drm_device *dev, vm_ooffset_t offset)
}
int
-drm_gem_create_mmap_offset(struct drm_gem_object *obj)
-{
- struct drm_device *dev;
- struct drm_gem_mm *mm;
- int ret;
-
- if (obj->on_map)
- return (0);
- dev = obj->dev;
- mm = dev->mm_private;
- ret = 0;
-
- obj->map_list.key = alloc_unr(mm->idxunr);
- ret = drm_ht_insert_item(&mm->offset_hash, &obj->map_list);
- if (ret != 0) {
- DRM_ERROR("failed to add to map hash\n");
- free_unr(mm->idxunr, obj->map_list.key);
- return (ret);
- }
- obj->on_map = true;
- return (0);
-}
-
-void
-drm_gem_free_mmap_offset(struct drm_gem_object *obj)
-{
- struct drm_hash_item *list;
- struct drm_gem_mm *mm;
-
- if (!obj->on_map)
- return;
- mm = obj->dev->mm_private;
- list = &obj->map_list;
-
- drm_ht_remove_item(&mm->offset_hash, list);
- free_unr(mm->idxunr, list->key);
- obj->on_map = false;
-}
-
-int
drm_gem_mmap_single(struct drm_device *dev, vm_ooffset_t *offset, vm_size_t size,
struct vm_object **obj_res, int nprot)
{
@@ -475,7 +464,7 @@ drm_gem_mmap_single(struct drm_device *dev, vm_ooffset_t *offset, vm_size_t size
gem_obj = drm_gem_object_from_offset(dev, *offset);
if (gem_obj == NULL) {
DRM_UNLOCK(dev);
- return (ENODEV);
+ return (-ENODEV);
}
drm_gem_object_reference(gem_obj);
DRM_UNLOCK(dev);
@@ -484,7 +473,7 @@ drm_gem_mmap_single(struct drm_device *dev, vm_ooffset_t *offset, vm_size_t size
DRM_GEM_MAPPING_MAPOFF(*offset), curthread->td_ucred);
if (vm_obj == NULL) {
drm_gem_object_unreference_unlocked(gem_obj);
- return (EINVAL);
+ return (-EINVAL);
}
*offset = DRM_GEM_MAPPING_MAPOFF(*offset);
*obj_res = vm_obj;
diff --git a/sys/dev/drm2/drm_gem_names.c b/sys/dev/drm2/drm_gem_names.c
index 03ef2c8..8e47531 100644
--- a/sys/dev/drm2/drm_gem_names.c
+++ b/sys/dev/drm2/drm_gem_names.c
@@ -151,7 +151,7 @@ drm_gem_name_create(struct drm_gem_names *names, void *p, uint32_t *name)
struct drm_gem_name *np;
if (*name != 0) {
- return (EALREADY);
+ return (-EALREADY);
}
np = malloc(sizeof(struct drm_gem_name), M_GEM_NAMES, M_WAITOK);
@@ -160,7 +160,7 @@ drm_gem_name_create(struct drm_gem_names *names, void *p, uint32_t *name)
if (np->name == -1) {
mtx_unlock(&names->lock);
free(np, M_GEM_NAMES);
- return (ENOMEM);
+ return (-ENOMEM);
}
*name = np->name;
np->ptr = p;
diff --git a/sys/dev/drm2/drm_global.c b/sys/dev/drm2/drm_global.c
index 6372044..2778aac 100644
--- a/sys/dev/drm2/drm_global.c
+++ b/sys/dev/drm2/drm_global.c
@@ -76,7 +76,11 @@ int drm_global_item_ref(struct drm_global_reference *ref)
sx_xlock(&item->mutex);
if (item->refcount == 0) {
item->object = malloc(ref->size, M_DRM_GLOBAL,
- M_WAITOK | M_ZERO);
+ M_NOWAIT | M_ZERO);
+ if (unlikely(item->object == NULL)) {
+ ret = -ENOMEM;
+ goto out_err;
+ }
ref->object = item->object;
ret = ref->init(ref);
@@ -94,6 +98,7 @@ out_err:
item->object = NULL;
return ret;
}
+EXPORT_SYMBOL(drm_global_item_ref);
void drm_global_item_unref(struct drm_global_reference *ref)
{
@@ -109,3 +114,4 @@ void drm_global_item_unref(struct drm_global_reference *ref)
}
sx_xunlock(&item->mutex);
}
+EXPORT_SYMBOL(drm_global_item_unref);
diff --git a/sys/dev/drm2/drm_hashtab.c b/sys/dev/drm2/drm_hashtab.c
index 8536fb8..f49d59f 100644
--- a/sys/dev/drm2/drm_hashtab.c
+++ b/sys/dev/drm2/drm_hashtab.c
@@ -54,6 +54,7 @@ int drm_ht_create(struct drm_open_hash *ht, unsigned int order)
}
return 0;
}
+EXPORT_SYMBOL(drm_ht_create);
void drm_ht_verbose_list(struct drm_open_hash *ht, unsigned long key)
{
@@ -69,8 +70,8 @@ void drm_ht_verbose_list(struct drm_open_hash *ht, unsigned long key)
DRM_DEBUG("count %d, key: 0x%08lx\n", count++, entry->key);
}
-static struct drm_hash_item *
-drm_ht_find_key(struct drm_open_hash *ht, unsigned long key)
+static struct drm_hash_item *drm_ht_find_key(struct drm_open_hash *ht,
+ unsigned long key)
{
struct drm_hash_item *entry;
struct drm_hash_item_list *h_list;
@@ -112,6 +113,7 @@ int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item)
}
return 0;
}
+EXPORT_SYMBOL(drm_ht_insert_item);
/*
* Just insert an item and return any "bits" bit key that hasn't been
@@ -140,6 +142,7 @@ int drm_ht_just_insert_please(struct drm_open_hash *ht, struct drm_hash_item *it
}
return 0;
}
+EXPORT_SYMBOL(drm_ht_just_insert_please);
int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key,
struct drm_hash_item **item)
@@ -153,6 +156,7 @@ int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key,
*item = entry;
return 0;
}
+EXPORT_SYMBOL(drm_ht_find_item);
int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key)
{
@@ -171,6 +175,7 @@ int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item)
LIST_REMOVE(item, head);
return 0;
}
+EXPORT_SYMBOL(drm_ht_remove_item);
void drm_ht_remove(struct drm_open_hash *ht)
{
@@ -179,3 +184,4 @@ void drm_ht_remove(struct drm_open_hash *ht)
ht->table = NULL;
}
}
+EXPORT_SYMBOL(drm_ht_remove);
diff --git a/sys/dev/drm2/drm_internal.h b/sys/dev/drm2/drm_internal.h
deleted file mode 100644
index 0ed1b6f..0000000
--- a/sys/dev/drm2/drm_internal.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*-
- * Copyright 2007 Red Hat, Inc
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * 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.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-/* This header file holds function prototypes and data types that are
- * internal to the drm (not exported to user space) but shared across
- * drivers and platforms */
-
-#ifndef __DRM_INTERNAL_H__
-#define __DRM_INTERNAL_H__
-
-/**
- * Drawable information.
- */
-struct drm_drawable_info {
- unsigned int num_rects;
- struct drm_clip_rect *rects;
-};
-
-#endif
diff --git a/sys/dev/drm2/drm_ioc32.c b/sys/dev/drm2/drm_ioc32.c
index e051967..7bbcd43 100644
--- a/sys/dev/drm2/drm_ioc32.c
+++ b/sys/dev/drm2/drm_ioc32.c
@@ -20,9 +20,6 @@
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
- *
- * Authors:
- * Paul Mackerras <paulus@samba.org>
*/
#include <sys/cdefs.h>
@@ -35,10 +32,6 @@ __FBSDID("$FreeBSD$");
#include <dev/drm2/drmP.h>
#include <dev/drm2/drm.h>
-/** @file drm_ioc32.c
- * 32-bit ioctl compatibility routines for the DRM.
- */
-
#define DRM_IOCTL_VERSION32 DRM_IOWR(0x00, drm_version32_t)
#define DRM_IOCTL_GET_UNIQUE32 DRM_IOWR(0x01, drm_unique32_t)
#define DRM_IOCTL_GET_MAP32 DRM_IOWR(0x04, drm_map32_t)
@@ -87,7 +80,8 @@ typedef struct drm_version_32 {
u32 desc; /**< User-space buffer to hold desc */
} drm_version32_t;
-static int compat_drm_version(struct drm_device *dev, void *data, struct drm_file *file_priv)
+static int compat_drm_version(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
drm_version32_t *v32 = data;
struct drm_version version;
@@ -99,7 +93,7 @@ static int compat_drm_version(struct drm_device *dev, void *data, struct drm_fil
version.date = (void *)(unsigned long)v32->date;
version.desc_len = v32->desc_len;
version.desc = (void *)(unsigned long)v32->desc;
-
+
err = drm_version(dev, (void *)&version, file_priv);
if (err)
return err;
@@ -119,7 +113,8 @@ typedef struct drm_unique32 {
u32 unique; /**< Unique name for driver instantiation */
} drm_unique32_t;
-static int compat_drm_getunique(struct drm_device *dev, void *data, struct drm_file *file_priv)
+static int compat_drm_getunique(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
drm_unique32_t *uq32 = data;
struct drm_unique u;
@@ -137,7 +132,8 @@ static int compat_drm_getunique(struct drm_device *dev, void *data, struct drm_f
return 0;
}
-static int compat_drm_setunique(struct drm_device *dev, void *data, struct drm_file *file_priv)
+static int compat_drm_setunique(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
drm_unique32_t *uq32 = data;
struct drm_unique u;
@@ -157,7 +153,8 @@ typedef struct drm_map32 {
int mtrr; /**< MTRR slot used */
} drm_map32_t;
-static int compat_drm_getmap(struct drm_device *dev, void *data, struct drm_file *file_priv)
+static int compat_drm_getmap(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
drm_map32_t *m32 = data;
struct drm_map map;
@@ -183,13 +180,14 @@ static int compat_drm_getmap(struct drm_device *dev, void *data, struct drm_file
}
-static int compat_drm_addmap(struct drm_device *dev, void *data, struct drm_file *file_priv)
+static int compat_drm_addmap(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
drm_map32_t *m32 = data;
struct drm_map map;
int err;
void *handle;
-
+
map.offset = (unsigned long)m32->offset;
map.size = (unsigned long)m32->size;
map.type = m32->type;
@@ -202,7 +200,7 @@ static int compat_drm_addmap(struct drm_device *dev, void *data, struct drm_file
m32->offset = map.offset;
m32->mtrr = map.mtrr;
handle = map.handle;
-
+
m32->handle = (unsigned long)handle;
if (m32->handle != (unsigned long)handle)
DRM_DEBUG("compat_drm_addmap truncated handle"
@@ -212,7 +210,8 @@ static int compat_drm_addmap(struct drm_device *dev, void *data, struct drm_file
return 0;
}
-static int compat_drm_rmmap(struct drm_device *dev, void *data, struct drm_file *file_priv)
+static int compat_drm_rmmap(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
drm_map32_t *m32 = data;
struct drm_map map;
@@ -231,7 +230,8 @@ typedef struct drm_client32 {
u32 iocs; /**< Ioctl count */
} drm_client32_t;
-static int compat_drm_getclient(struct drm_device *dev, void *data, struct drm_file *file_priv)
+static int compat_drm_getclient(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
drm_client32_t *c32 = data;
struct drm_client client;
@@ -261,7 +261,8 @@ typedef struct drm_stats32 {
} data[15];
} drm_stats32_t;
-static int compat_drm_getstats(struct drm_device *dev, void *data, struct drm_file *file_priv)
+static int compat_drm_getstats(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
drm_stats32_t *s32 = data;
struct drm_stats stats;
@@ -289,7 +290,8 @@ typedef struct drm_buf_desc32 {
u32 agp_start; /**< Start address in the AGP aperture */
} drm_buf_desc32_t;
-static int compat_drm_addbufs(struct drm_device *dev, void *data, struct drm_file *file_priv)
+static int compat_drm_addbufs(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
drm_buf_desc32_t *b32 = data;
struct drm_buf_desc buf;
@@ -312,11 +314,12 @@ static int compat_drm_addbufs(struct drm_device *dev, void *data, struct drm_fil
b32->high_mark = buf.high_mark;
b32->flags = buf.flags;
b32->agp_start = buf.agp_start;
-
+
return 0;
}
-static int compat_drm_markbufs(struct drm_device *dev, void *data, struct drm_file *file_priv)
+static int compat_drm_markbufs(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
drm_buf_desc32_t *b32 = data;
struct drm_buf_desc buf;
@@ -324,7 +327,7 @@ static int compat_drm_markbufs(struct drm_device *dev, void *data, struct drm_fi
buf.size = b32->size;
buf.low_mark = b32->low_mark;
buf.high_mark = b32->high_mark;
-
+
return drm_markbufs(dev, (void *)&buf, file_priv);
}
@@ -333,7 +336,8 @@ typedef struct drm_buf_info32 {
u32 list;
} drm_buf_info32_t;
-static int compat_drm_infobufs(struct drm_device *dev, void *data, struct drm_file *file_priv)
+static int compat_drm_infobufs(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
drm_buf_info32_t *req32 = data;
drm_buf_desc32_t *to;
@@ -351,7 +355,7 @@ static int compat_drm_infobufs(struct drm_device *dev, void *data, struct drm_fi
nbytes = sizeof(*request) + count * sizeof(struct drm_buf_desc);
request = malloc(nbytes, DRM_MEM_BUFLISTS, M_ZERO | M_NOWAIT);
if (!request)
- return -EFAULT;
+ return -ENOMEM;
list = (struct drm_buf_desc *) (request + 1);
request->count = count;
@@ -389,7 +393,8 @@ typedef struct drm_buf_map32 {
u32 list; /**< Buffer information */
} drm_buf_map32_t;
-static int compat_drm_mapbufs(struct drm_device *dev, void *data, struct drm_file *file_priv)
+static int compat_drm_mapbufs(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
drm_buf_map32_t *req32 = data;
drm_buf_pub32_t *list32;
@@ -407,7 +412,7 @@ static int compat_drm_mapbufs(struct drm_device *dev, void *data, struct drm_fil
nbytes = sizeof(*request) + count * sizeof(struct drm_buf_pub);
request = malloc(nbytes, DRM_MEM_BUFLISTS, M_ZERO | M_NOWAIT);
if (!request)
- return -EFAULT;
+ return -ENOMEM;
list = (struct drm_buf_pub *) (request + 1);
request->count = count;
@@ -437,7 +442,8 @@ typedef struct drm_buf_free32 {
u32 list;
} drm_buf_free32_t;
-static int compat_drm_freebufs(struct drm_device *dev, void *data, struct drm_file *file_priv)
+static int compat_drm_freebufs(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
drm_buf_free32_t *req32 = data;
struct drm_buf_free request;
@@ -453,7 +459,8 @@ typedef struct drm_ctx_priv_map32 {
u32 handle; /**< Handle of map */
} drm_ctx_priv_map32_t;
-static int compat_drm_setsareactx(struct drm_device *dev, void *data, struct drm_file *file_priv)
+static int compat_drm_setsareactx(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
drm_ctx_priv_map32_t *req32 = data;
struct drm_ctx_priv_map request;
@@ -464,7 +471,8 @@ static int compat_drm_setsareactx(struct drm_device *dev, void *data, struct drm
return drm_setsareactx(dev, (void *)&request, file_priv);
}
-static int compat_drm_getsareactx(struct drm_device *dev, void *data, struct drm_file *file_priv)
+static int compat_drm_getsareactx(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
drm_ctx_priv_map32_t *req32 = data;
struct drm_ctx_priv_map request;
@@ -486,7 +494,8 @@ typedef struct drm_ctx_res32 {
u32 contexts;
} drm_ctx_res32_t;
-static int compat_drm_resctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
+static int compat_drm_resctx(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
drm_ctx_res32_t *res32 = data;
struct drm_ctx_res res;
@@ -517,12 +526,18 @@ typedef struct drm_dma32 {
int granted_count; /**< Number of buffers granted */
} drm_dma32_t;
-static int compat_drm_dma(struct drm_device *dev, void *data, struct drm_file *file_priv)
+static int compat_drm_dma(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
drm_dma32_t *d32 = data;
struct drm_dma d;
int err;
+ if (!dev->driver->dma_ioctl) {
+ DRM_DEBUG("DMA ioctl on driver with no dma handler\n");
+ return -EINVAL;
+ }
+
d.context = d32->context;
d.send_count = d32->send_count;
d.send_indices = (int *)(unsigned long)d32->send_indices;
@@ -532,7 +547,7 @@ static int compat_drm_dma(struct drm_device *dev, void *data, struct drm_file *f
d.request_indices = (int *)(unsigned long)d32->request_indices;
d.request_sizes = (int *)(unsigned long)d32->request_sizes;
- err = drm_dma(dev, (void *)&d, file_priv);
+ err = dev->driver->dma_ioctl(dev, (void *)&d, file_priv);
if (err)
return err;
@@ -542,11 +557,13 @@ static int compat_drm_dma(struct drm_device *dev, void *data, struct drm_file *f
return 0;
}
+#if __OS_HAS_AGP
typedef struct drm_agp_mode32 {
u32 mode; /**< AGP mode */
} drm_agp_mode32_t;
-static int compat_drm_agp_enable(struct drm_device *dev, void *data, struct drm_file *file_priv)
+static int compat_drm_agp_enable(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
drm_agp_mode32_t *m32 = data;
struct drm_agp_mode mode;
@@ -570,7 +587,8 @@ typedef struct drm_agp_info32 {
unsigned short id_device;
} drm_agp_info32_t;
-static int compat_drm_agp_info(struct drm_device *dev, void *data, struct drm_file *file_priv)
+static int compat_drm_agp_info(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
drm_agp_info32_t *i32 = data;
struct drm_agp_info info;
@@ -600,7 +618,8 @@ typedef struct drm_agp_buffer32 {
u32 physical; /**< Physical used by i810 */
} drm_agp_buffer32_t;
-static int compat_drm_agp_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv)
+static int compat_drm_agp_alloc(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
drm_agp_buffer32_t *req32 = data;
struct drm_agp_buffer request;
@@ -619,7 +638,8 @@ static int compat_drm_agp_alloc(struct drm_device *dev, void *data, struct drm_f
return 0;
}
-static int compat_drm_agp_free(struct drm_device *dev, void *data, struct drm_file *file_priv)
+static int compat_drm_agp_free(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
drm_agp_buffer32_t *req32 = data;
struct drm_agp_buffer request;
@@ -634,7 +654,8 @@ typedef struct drm_agp_binding32 {
u32 offset; /**< In bytes -- will round to page boundary */
} drm_agp_binding32_t;
-static int compat_drm_agp_bind(struct drm_device *dev, void *data, struct drm_file *file_priv)
+static int compat_drm_agp_bind(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
drm_agp_binding32_t *req32 = data;
struct drm_agp_binding request;
@@ -645,22 +666,25 @@ static int compat_drm_agp_bind(struct drm_device *dev, void *data, struct drm_fi
return drm_agp_bind_ioctl(dev, (void *)&request, file_priv);
}
-static int compat_drm_agp_unbind(struct drm_device *dev, void *data, struct drm_file *file_priv)
+static int compat_drm_agp_unbind(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
drm_agp_binding32_t *req32 = data;
struct drm_agp_binding request;
-
+
request.handle = req32->handle;
-
+
return drm_agp_unbind_ioctl(dev, (void *)&request, file_priv);
}
+#endif /* __OS_HAS_AGP */
typedef struct drm_scatter_gather32 {
u32 size; /**< In bytes -- will round to page boundary */
u32 handle; /**< Used for mapping / unmapping */
} drm_scatter_gather32_t;
-static int compat_drm_sg_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv)
+static int compat_drm_sg_alloc(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
drm_scatter_gather32_t *req32 = data;
struct drm_scatter_gather request;
@@ -678,7 +702,8 @@ static int compat_drm_sg_alloc(struct drm_device *dev, void *data, struct drm_fi
return 0;
}
-static int compat_drm_sg_free(struct drm_device *dev, void *data, struct drm_file *file_priv)
+static int compat_drm_sg_free(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
drm_scatter_gather32_t *req32 = data;
struct drm_scatter_gather request;
@@ -688,6 +713,7 @@ static int compat_drm_sg_free(struct drm_device *dev, void *data, struct drm_fil
return drm_sg_free(dev, (void *)&request, file_priv);
}
+#if defined(CONFIG_X86) || defined(CONFIG_IA64)
typedef struct drm_update_draw32 {
drm_drawable_t handle;
unsigned int type;
@@ -695,21 +721,7 @@ typedef struct drm_update_draw32 {
/* 64-bit version has a 32-bit pad here */
u64 data; /**< Pointer */
} __attribute__((packed)) drm_update_draw32_t;
-
-static int compat_drm_update_draw(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
- drm_update_draw32_t *update32 = data;
- struct drm_update_draw request;
- int err;
-
- request.handle = update32->handle;
- request.type = update32->type;
- request.num = update32->num;
- request.data = update32->data;
-
- err = drm_update_draw(dev, (void *)&request, file_priv);
- return err;
-}
+#endif
struct drm_wait_vblank_request32 {
enum drm_vblank_seq_type type;
@@ -729,7 +741,8 @@ typedef union drm_wait_vblank32 {
struct drm_wait_vblank_reply32 reply;
} drm_wait_vblank32_t;
-static int compat_drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_priv)
+static int compat_drm_wait_vblank(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
drm_wait_vblank32_t *req32 = data;
union drm_wait_vblank request;
@@ -751,12 +764,12 @@ static int compat_drm_wait_vblank(struct drm_device *dev, void *data, struct drm
return 0;
}
-drm_ioctl_desc_t drm_compat_ioctls[256] = {
- DRM_IOCTL_DEF(DRM_IOCTL_VERSION32, compat_drm_version, 0),
+struct drm_ioctl_desc drm_compat_ioctls[256] = {
+ DRM_IOCTL_DEF(DRM_IOCTL_VERSION32, compat_drm_version, DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE32, compat_drm_getunique, 0),
- DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP32, compat_drm_getmap, 0),
- DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT32, compat_drm_getclient, 0),
- DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS32, compat_drm_getstats, 0),
+ DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP32, compat_drm_getmap, DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT32, compat_drm_getclient, DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS32, compat_drm_getstats, DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE32, compat_drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_ADD_MAP32, compat_drm_addmap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_ADD_BUFS32, compat_drm_addbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
@@ -769,19 +782,19 @@ drm_ioctl_desc_t drm_compat_ioctls[256] = {
DRM_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX32, compat_drm_getsareactx, DRM_AUTH),
DRM_IOCTL_DEF(DRM_IOCTL_RES_CTX32, compat_drm_resctx, DRM_AUTH),
DRM_IOCTL_DEF(DRM_IOCTL_DMA32, compat_drm_dma, DRM_AUTH),
-
+#if __OS_HAS_AGP
DRM_IOCTL_DEF(DRM_IOCTL_AGP_ENABLE32, compat_drm_agp_enable, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_AGP_INFO32, compat_drm_agp_info, DRM_AUTH),
DRM_IOCTL_DEF(DRM_IOCTL_AGP_ALLOC32, compat_drm_agp_alloc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_AGP_FREE32, compat_drm_agp_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_AGP_BIND32, compat_drm_agp_bind, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_AGP_UNBIND32, compat_drm_agp_unbind, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-
+#endif
DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC32, compat_drm_sg_alloc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE32, compat_drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-
- DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW32, compat_drm_update_draw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-
+#if defined(CONFIG_X86) || defined(CONFIG_IA64)
+ DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW32, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+#endif
DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK32, compat_drm_wait_vblank, DRM_UNLOCKED),
};
diff --git a/sys/dev/drm2/drm_ioctl.c b/sys/dev/drm2/drm_ioctl.c
index e13eec7..a6c508a 100644
--- a/sys/dev/drm2/drm_ioctl.c
+++ b/sys/dev/drm2/drm_ioctl.c
@@ -1,4 +1,14 @@
-/*-
+/**
+ * \file drm_ioctl.c
+ * IOCTL processing for DRM
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
+ * Created: Fri Jan 8 09:01:26 1999 by faith@valinux.com
+ *
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
* All Rights Reserved.
@@ -21,216 +31,237 @@
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Rickard E. (Rik) Faith <faith@valinux.com>
- * Gareth Hughes <gareth@valinux.com>
- *
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-/** @file drm_ioctl.c
- * Varios minor DRM ioctls not applicable to other files, such as versioning
- * information and reporting DRM information to userland.
- */
-
#include <dev/drm2/drmP.h>
#include <dev/drm2/drm_core.h>
-/*
- * Beginning in revision 1.1 of the DRM interface, getunique will return
- * a unique in the form pci:oooo:bb:dd.f (o=domain, b=bus, d=device, f=function)
- * before setunique has been called. The format for the bus-specific part of
- * the unique is not defined for any other bus.
+/**
+ * Get the bus id.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_unique structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Copies the bus id from drm_device::unique into user space.
*/
int drm_getunique(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_unique *u = data;
+ struct drm_master *master = file_priv->master;
- if (u->unique_len >= dev->unique_len) {
- if (DRM_COPY_TO_USER(u->unique, dev->unique, dev->unique_len))
- return EFAULT;
+ if (u->unique_len >= master->unique_len) {
+ if (copy_to_user(u->unique, master->unique, master->unique_len))
+ return -EFAULT;
}
- u->unique_len = dev->unique_len;
+ u->unique_len = master->unique_len;
return 0;
}
-/* Deprecated in DRM version 1.1, and will return EBUSY when setversion has
- * requested version 1.1 or greater.
+static void
+drm_unset_busid(struct drm_device *dev,
+ struct drm_master *master)
+{
+
+ free(master->unique, DRM_MEM_DRIVER);
+ master->unique = NULL;
+ master->unique_len = 0;
+ master->unique_size = 0;
+}
+
+/**
+ * Set the bus id.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_unique structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Copies the bus id from userspace into drm_device::unique, and verifies that
+ * it matches the device this DRM is attached to (EINVAL otherwise). Deprecated
+ * in interface version 1.1 and will return EBUSY when setversion has requested
+ * version 1.1 or greater.
*/
int drm_setunique(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_unique *u = data;
- int domain, bus, slot, func, ret;
- char *busid;
+ struct drm_master *master = file_priv->master;
+ int ret;
- /* Check and copy in the submitted Bus ID */
- if (!u->unique_len || u->unique_len > 1024)
- return EINVAL;
+ if (master->unique_len || master->unique)
+ return -EBUSY;
- busid = malloc(u->unique_len + 1, DRM_MEM_DRIVER, M_WAITOK);
- if (busid == NULL)
- return ENOMEM;
-
- if (DRM_COPY_FROM_USER(busid, u->unique, u->unique_len)) {
- free(busid, DRM_MEM_DRIVER);
- return EFAULT;
- }
- busid[u->unique_len] = '\0';
-
- /* Return error if the busid submitted doesn't match the device's actual
- * busid.
- */
- ret = sscanf(busid, "PCI:%d:%d:%d", &bus, &slot, &func);
- if (ret != 3) {
- free(busid, DRM_MEM_DRIVER);
- return EINVAL;
- }
- domain = bus >> 8;
- bus &= 0xff;
-
- if ((domain != dev->pci_domain) ||
- (bus != dev->pci_bus) ||
- (slot != dev->pci_slot) ||
- (func != dev->pci_func)) {
- free(busid, DRM_MEM_DRIVER);
- return EINVAL;
- }
+ if (!u->unique_len || u->unique_len > 1024)
+ return -EINVAL;
- /* Actually set the device's busid now. */
- DRM_LOCK(dev);
- if (dev->unique_len || dev->unique) {
- DRM_UNLOCK(dev);
- return EBUSY;
- }
+ if (!dev->driver->bus->set_unique)
+ return -EINVAL;
- dev->unique_len = u->unique_len;
- dev->unique = busid;
- DRM_UNLOCK(dev);
+ ret = dev->driver->bus->set_unique(dev, master, u);
+ if (ret)
+ goto err;
return 0;
-}
+err:
+ drm_unset_busid(dev, master);
+ return ret;
+}
-static int
-drm_set_busid(struct drm_device *dev)
+static int drm_set_busid(struct drm_device *dev, struct drm_file *file_priv)
{
+ struct drm_master *master = file_priv->master;
+ int ret;
- DRM_LOCK(dev);
-
- if (dev->unique != NULL) {
- DRM_UNLOCK(dev);
- return EBUSY;
- }
-
- dev->unique_len = 20;
- dev->unique = malloc(dev->unique_len + 1, DRM_MEM_DRIVER, M_NOWAIT);
- if (dev->unique == NULL) {
- DRM_UNLOCK(dev);
- return ENOMEM;
- }
-
- snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%1x",
- dev->pci_domain, dev->pci_bus, dev->pci_slot, dev->pci_func);
-
- DRM_UNLOCK(dev);
+ if (master->unique != NULL)
+ drm_unset_busid(dev, master);
+ ret = dev->driver->bus->set_busid(dev, master);
+ if (ret)
+ goto err;
return 0;
+err:
+ drm_unset_busid(dev, master);
+ return ret;
}
-int drm_getmap(struct drm_device *dev, void *data, struct drm_file *file_priv)
+/**
+ * Get a mapping information.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_map structure.
+ *
+ * \return zero on success or a negative number on failure.
+ *
+ * Searches for the mapping with the specified offset and copies its information
+ * into userspace
+ */
+int drm_getmap(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
- struct drm_map *map = data;
- drm_local_map_t *mapinlist;
- int idx;
- int i = 0;
+ struct drm_map *map = data;
+ struct drm_map_list *r_list = NULL;
+ struct list_head *list;
+ int idx;
+ int i;
idx = map->offset;
+ if (idx < 0)
+ return -EINVAL;
+ i = 0;
DRM_LOCK(dev);
- if (idx < 0) {
- DRM_UNLOCK(dev);
- return EINVAL;
- }
-
- TAILQ_FOREACH(mapinlist, &dev->maplist, link) {
+ list_for_each(list, &dev->maplist) {
if (i == idx) {
- map->offset = mapinlist->offset;
- map->size = mapinlist->size;
- map->type = mapinlist->type;
- map->flags = mapinlist->flags;
- map->handle = mapinlist->handle;
- map->mtrr = mapinlist->mtrr;
+ r_list = list_entry(list, struct drm_map_list, head);
break;
}
i++;
}
+ if (!r_list || !r_list->map) {
+ DRM_UNLOCK(dev);
+ return -EINVAL;
+ }
+ map->offset = r_list->map->offset;
+ map->size = r_list->map->size;
+ map->type = r_list->map->type;
+ map->flags = r_list->map->flags;
+ map->handle = (void *)(unsigned long) r_list->user_token;
+ map->mtrr = r_list->map->mtrr;
DRM_UNLOCK(dev);
- if (mapinlist == NULL)
- return EINVAL;
-
return 0;
}
+/**
+ * Get client information.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_client structure.
+ *
+ * \return zero on success or a negative number on failure.
+ *
+ * Searches for the client with the specified index and copies its information
+ * into userspace
+ */
int drm_getclient(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_client *client = data;
struct drm_file *pt;
int idx;
- int i = 0;
+ int i;
idx = client->idx;
+ i = 0;
+
DRM_LOCK(dev);
- TAILQ_FOREACH(pt, &dev->files, link) {
- if (i == idx) {
- client->auth = pt->authenticated;
- client->pid = pt->pid;
- client->uid = pt->uid;
+ list_for_each_entry(pt, &dev->filelist, lhead) {
+ if (i++ >= idx) {
+ client->auth = pt->authenticated;
+ client->pid = pt->pid;
+ client->uid = pt->uid;
client->magic = pt->magic;
- client->iocs = pt->ioctl_count;
+ client->iocs = pt->ioctl_count;
DRM_UNLOCK(dev);
+
return 0;
}
- i++;
}
DRM_UNLOCK(dev);
- return EINVAL;
+ return -EINVAL;
}
-int drm_getstats(struct drm_device *dev, void *data, struct drm_file *file_priv)
+/**
+ * Get statistics information.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_stats structure.
+ *
+ * \return zero on success or a negative number on failure.
+ */
+int drm_getstats(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
struct drm_stats *stats = data;
- int i;
+ int i;
- memset(stats, 0, sizeof(struct drm_stats));
-
- DRM_LOCK(dev);
+ memset(stats, 0, sizeof(*stats));
for (i = 0; i < dev->counters; i++) {
if (dev->types[i] == _DRM_STAT_LOCK)
stats->data[i].value =
- (dev->lock.hw_lock ? dev->lock.hw_lock->lock : 0);
- else
+ (file_priv->master->lock.hw_lock ? file_priv->master->lock.hw_lock->lock : 0);
+ else
stats->data[i].value = atomic_read(&dev->counts[i]);
stats->data[i].type = dev->types[i];
}
-
- stats->count = dev->counters;
- DRM_UNLOCK(dev);
+ stats->count = dev->counters;
return 0;
}
+/**
+ * Get device/driver capabilities
+ */
int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
struct drm_get_cap *req = data;
@@ -258,67 +289,73 @@ int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
req->value = drm_timestamp_monotonic;
break;
default:
- return EINVAL;
+ return -EINVAL;
}
return 0;
}
-int drm_setversion(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
+/**
+ * Setversion ioctl.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_lock structure.
+ * \return zero on success or negative number on failure.
+ *
+ * Sets the requested interface version
+ */
+int drm_setversion(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
struct drm_set_version *sv = data;
- struct drm_set_version ver;
- int if_version;
-
- /* Save the incoming data, and set the response before continuing
- * any further.
- */
- ver = *sv;
- sv->drm_di_major = DRM_IF_MAJOR;
- sv->drm_di_minor = DRM_IF_MINOR;
- sv->drm_dd_major = dev->driver->major;
- sv->drm_dd_minor = dev->driver->minor;
+ int if_version, retcode = 0;
- DRM_DEBUG("ver.drm_di_major %d ver.drm_di_minor %d "
- "ver.drm_dd_major %d ver.drm_dd_minor %d\n",
- ver.drm_di_major, ver.drm_di_minor, ver.drm_dd_major,
- ver.drm_dd_minor);
- DRM_DEBUG("sv->drm_di_major %d sv->drm_di_minor %d "
- "sv->drm_dd_major %d sv->drm_dd_minor %d\n",
- sv->drm_di_major, sv->drm_di_minor, sv->drm_dd_major,
- sv->drm_dd_minor);
-
- if (ver.drm_di_major != -1) {
- if (ver.drm_di_major != DRM_IF_MAJOR ||
- ver.drm_di_minor < 0 || ver.drm_di_minor > DRM_IF_MINOR) {
- return EINVAL;
+ if (sv->drm_di_major != -1) {
+ if (sv->drm_di_major != DRM_IF_MAJOR ||
+ sv->drm_di_minor < 0 || sv->drm_di_minor > DRM_IF_MINOR) {
+ retcode = -EINVAL;
+ goto done;
}
- if_version = DRM_IF_VERSION(ver.drm_di_major,
- ver.drm_dd_minor);
- dev->if_version = DRM_MAX(if_version, dev->if_version);
- if (ver.drm_di_minor >= 1) {
+ if_version = DRM_IF_VERSION(sv->drm_di_major,
+ sv->drm_di_minor);
+ dev->if_version = max(if_version, dev->if_version);
+ if (sv->drm_di_minor >= 1) {
/*
* Version 1.1 includes tying of DRM to specific device
+ * Version 1.4 has proper PCI domain support
*/
- drm_set_busid(dev);
+ retcode = drm_set_busid(dev, file_priv);
+ if (retcode)
+ goto done;
}
}
- if (ver.drm_dd_major != -1) {
- if (ver.drm_dd_major != dev->driver->major ||
- ver.drm_dd_minor < 0 ||
- ver.drm_dd_minor > dev->driver->minor)
- {
- return EINVAL;
+ if (sv->drm_dd_major != -1) {
+ if (sv->drm_dd_major != dev->driver->major ||
+ sv->drm_dd_minor < 0 || sv->drm_dd_minor >
+ dev->driver->minor) {
+ retcode = -EINVAL;
+ goto done;
}
+
+ if (dev->driver->set_version)
+ dev->driver->set_version(dev, sv);
}
- return 0;
-}
+done:
+ sv->drm_di_major = DRM_IF_MAJOR;
+ sv->drm_di_minor = DRM_IF_MINOR;
+ sv->drm_dd_major = dev->driver->major;
+ sv->drm_dd_minor = dev->driver->minor;
+ return retcode;
+}
-int drm_noop(struct drm_device *dev, void *data, struct drm_file *file_priv)
+/** No-op ioctl. */
+int drm_noop(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
DRM_DEBUG("\n");
return 0;
}
+EXPORT_SYMBOL(drm_noop);
diff --git a/sys/dev/drm2/drm_irq.c b/sys/dev/drm2/drm_irq.c
index f79d46a..f93cd38 100644
--- a/sys/dev/drm2/drm_irq.c
+++ b/sys/dev/drm2/drm_irq.c
@@ -1,5 +1,16 @@
-/*-
- * Copyright 2003 Eric Anholt
+/**
+ * \file drm_irq.c
+ * IRQ support
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
+ * Created: Fri Mar 19 14:30:16 1999 by faith@valinux.com
+ *
+ * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -16,27 +27,16 @@
* 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
- * ERIC ANHOLT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Eric Anholt <anholt@FreeBSD.org>
- *
+ * 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.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-/** @file drm_irq.c
- * Support code for handling setup/teardown of interrupt handlers and
- * handing interrupt handlers off to the drivers.
- */
-
#include <dev/drm2/drmP.h>
-#include <dev/drm2/drm.h>
-
-MALLOC_DEFINE(DRM_MEM_VBLANK, "drm_vblank", "DRM VBLANK Handling Data");
/* Access macro for slots in vblank timestamp ringbuffer. */
#define vblanktimestamp(dev, crtc, count) ( \
@@ -53,179 +53,31 @@ MALLOC_DEFINE(DRM_MEM_VBLANK, "drm_vblank", "DRM VBLANK Handling Data");
*/
#define DRM_REDUNDANT_VBLIRQ_THRESH_NS 1000000
+/**
+ * Get interrupt from bus id.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_irq_busid structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Finds the PCI device with the specified bus id and gets its IRQ number.
+ * This IOCTL is deprecated, and will now return EINVAL for any busid not equal
+ * to that of the device that this DRM instance attached to.
+ */
int drm_irq_by_busid(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
- struct drm_irq_busid *irq = data;
-
- if ((irq->busnum >> 8) != dev->pci_domain ||
- (irq->busnum & 0xff) != dev->pci_bus ||
- irq->devnum != dev->pci_slot ||
- irq->funcnum != dev->pci_func)
- return EINVAL;
-
- irq->irq = dev->irq;
-
- DRM_DEBUG("%d:%d:%d => IRQ %d\n",
- irq->busnum, irq->devnum, irq->funcnum, irq->irq);
-
- return 0;
-}
-
-static void
-drm_irq_handler_wrap(void *arg)
-{
- struct drm_device *dev = arg;
-
- mtx_lock(&dev->irq_lock);
- dev->driver->irq_handler(arg);
- mtx_unlock(&dev->irq_lock);
-}
-
-int
-drm_irq_install(struct drm_device *dev)
-{
- int retcode;
-
- if (dev->irq == 0 || dev->dev_private == NULL)
- return (EINVAL);
-
- DRM_DEBUG("irq=%d\n", dev->irq);
-
- DRM_LOCK(dev);
- if (dev->irq_enabled) {
- DRM_UNLOCK(dev);
- return EBUSY;
- }
- dev->irq_enabled = 1;
-
- dev->context_flag = 0;
-
- /* Before installing handler */
- if (dev->driver->irq_preinstall)
- dev->driver->irq_preinstall(dev);
- DRM_UNLOCK(dev);
-
- /* Install handler */
- retcode = bus_setup_intr(dev->device, dev->irqr,
- INTR_TYPE_TTY | INTR_MPSAFE, NULL,
- (dev->driver->driver_features & DRIVER_LOCKLESS_IRQ) != 0 ?
- drm_irq_handler_wrap : dev->driver->irq_handler,
- dev, &dev->irqh);
- if (retcode != 0)
- goto err;
-
- /* After installing handler */
- DRM_LOCK(dev);
- if (dev->driver->irq_postinstall)
- dev->driver->irq_postinstall(dev);
- DRM_UNLOCK(dev);
-
- return (0);
-err:
- device_printf(dev->device, "Error setting interrupt: %d\n", retcode);
- dev->irq_enabled = 0;
-
- return (retcode);
-}
-
-int drm_irq_uninstall(struct drm_device *dev)
-{
- int i;
-
- if (!dev->irq_enabled)
- return EINVAL;
-
- dev->irq_enabled = 0;
-
- /*
- * Wake up any waiters so they don't hang.
- */
- if (dev->num_crtcs) {
- mtx_lock(&dev->vbl_lock);
- for (i = 0; i < dev->num_crtcs; i++) {
- wakeup(&dev->_vblank_count[i]);
- dev->vblank_enabled[i] = 0;
- dev->last_vblank[i] =
- dev->driver->get_vblank_counter(dev, i);
- }
- mtx_unlock(&dev->vbl_lock);
- }
-
- DRM_DEBUG("irq=%d\n", dev->irq);
+ struct drm_irq_busid *p = data;
- if (dev->driver->irq_uninstall)
- dev->driver->irq_uninstall(dev);
-
- DRM_UNLOCK(dev);
- bus_teardown_intr(dev->device, dev->irqr, dev->irqh);
- DRM_LOCK(dev);
-
- return 0;
-}
-
-int drm_control(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
- struct drm_control *ctl = data;
- int err;
-
- switch (ctl->func) {
- case DRM_INST_HANDLER:
- /* Handle drivers whose DRM used to require IRQ setup but the
- * no longer does.
- */
- if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
- return 0;
- if (drm_core_check_feature(dev, DRIVER_MODESET))
- return 0;
- if (dev->if_version < DRM_IF_VERSION(1, 2) &&
- ctl->irq != dev->irq)
- return EINVAL;
- return drm_irq_install(dev);
- case DRM_UNINST_HANDLER:
- if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
- return 0;
- if (drm_core_check_feature(dev, DRIVER_MODESET))
- return 0;
- DRM_LOCK(dev);
- err = drm_irq_uninstall(dev);
- DRM_UNLOCK(dev);
- return err;
- default:
- return EINVAL;
- }
-}
-
-#define NSEC_PER_USEC 1000L
-#define NSEC_PER_SEC 1000000000L
-
-int64_t
-timeval_to_ns(const struct timeval *tv)
-{
- return ((int64_t)tv->tv_sec * NSEC_PER_SEC) +
- tv->tv_usec * NSEC_PER_USEC;
-}
-
-struct timeval
-ns_to_timeval(const int64_t nsec)
-{
- struct timeval tv;
- long rem;
+ if (!dev->driver->bus->irq_by_busid)
+ return -EINVAL;
- if (nsec == 0) {
- tv.tv_sec = 0;
- tv.tv_usec = 0;
- return (tv);
- }
+ if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
+ return -EINVAL;
- tv.tv_sec = nsec / NSEC_PER_SEC;
- rem = nsec % NSEC_PER_SEC;
- if (rem < 0) {
- tv.tv_sec--;
- rem += NSEC_PER_SEC;
- }
- tv.tv_usec = rem / 1000;
- return (tv);
+ return dev->driver->bus->irq_by_busid(dev, p);
}
/*
@@ -237,13 +89,6 @@ static void clear_vblank_timestamps(struct drm_device *dev, int crtc)
DRM_VBLANKTIME_RBSIZE * sizeof(struct timeval));
}
-static int64_t
-abs64(int64_t x)
-{
-
- return (x < 0 ? -x : x);
-}
-
/*
* Disable vblank irq's on crtc, make sure that last vblank count
* of hardware and corresponding consistent software vblank counter
@@ -253,9 +98,10 @@ abs64(int64_t x)
static void vblank_disable_and_save(struct drm_device *dev, int crtc)
{
u32 vblcount;
- int64_t diff_ns;
+ s64 diff_ns;
int vblrc;
struct timeval tvblank;
+ int count = DRM_TIMESTAMP_MAXRETRIES;
/* Prevent vblank irq processing while disabling vblank irqs,
* so no updates of timestamps or count can happen after we've
@@ -281,7 +127,10 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc)
do {
dev->last_vblank[crtc] = dev->driver->get_vblank_counter(dev, crtc);
vblrc = drm_get_last_vbltimestamp(dev, crtc, &tvblank, 0);
- } while (dev->last_vblank[crtc] != dev->driver->get_vblank_counter(dev, crtc));
+ } while (dev->last_vblank[crtc] != dev->driver->get_vblank_counter(dev, crtc) && (--count) && vblrc);
+
+ if (!count)
+ vblrc = 0;
/* Compute time difference to stored timestamp of last vblank
* as updated by last invocation of drm_handle_vblank() in vblank irq.
@@ -304,6 +153,7 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc)
*/
if ((vblrc > 0) && (abs64(diff_ns) > 1000000)) {
atomic_inc(&dev->_vblank_count[crtc]);
+ smp_mb__after_atomic_inc();
}
/* Invalidate all timestamps while vblank irq's are off. */
@@ -312,7 +162,7 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc)
mtx_unlock(&dev->vblank_time_lock);
}
-static void vblank_disable_fn(void * arg)
+static void vblank_disable_fn(void *arg)
{
struct drm_device *dev = (struct drm_device *)arg;
int i;
@@ -349,35 +199,58 @@ void drm_vblank_cleanup(struct drm_device *dev)
free(dev->vblank_inmodeset, DRM_MEM_VBLANK);
free(dev->_vblank_time, DRM_MEM_VBLANK);
+ mtx_destroy(&dev->vbl_lock);
+ mtx_destroy(&dev->vblank_time_lock);
+
dev->num_crtcs = 0;
}
+EXPORT_SYMBOL(drm_vblank_cleanup);
int drm_vblank_init(struct drm_device *dev, int num_crtcs)
{
- int i;
+ int i, ret = -ENOMEM;
callout_init(&dev->vblank_disable_callout, CALLOUT_MPSAFE);
-#if 0
mtx_init(&dev->vbl_lock, "drmvbl", NULL, MTX_DEF);
-#endif
mtx_init(&dev->vblank_time_lock, "drmvtl", NULL, MTX_DEF);
dev->num_crtcs = num_crtcs;
dev->_vblank_count = malloc(sizeof(atomic_t) * num_crtcs,
- DRM_MEM_VBLANK, M_WAITOK);
+ DRM_MEM_VBLANK, M_NOWAIT);
+ if (!dev->_vblank_count)
+ goto err;
+
dev->vblank_refcount = malloc(sizeof(atomic_t) * num_crtcs,
- DRM_MEM_VBLANK, M_WAITOK);
+ DRM_MEM_VBLANK, M_NOWAIT);
+ if (!dev->vblank_refcount)
+ goto err;
+
dev->vblank_enabled = malloc(num_crtcs * sizeof(int),
- DRM_MEM_VBLANK, M_WAITOK | M_ZERO);
+ DRM_MEM_VBLANK, M_NOWAIT | M_ZERO);
+ if (!dev->vblank_enabled)
+ goto err;
+
dev->last_vblank = malloc(num_crtcs * sizeof(u32),
- DRM_MEM_VBLANK, M_WAITOK | M_ZERO);
+ DRM_MEM_VBLANK, M_NOWAIT | M_ZERO);
+ if (!dev->last_vblank)
+ goto err;
+
dev->last_vblank_wait = malloc(num_crtcs * sizeof(u32),
- DRM_MEM_VBLANK, M_WAITOK | M_ZERO);
+ DRM_MEM_VBLANK, M_NOWAIT | M_ZERO);
+ if (!dev->last_vblank_wait)
+ goto err;
+
dev->vblank_inmodeset = malloc(num_crtcs * sizeof(int),
- DRM_MEM_VBLANK, M_WAITOK | M_ZERO);
+ DRM_MEM_VBLANK, M_NOWAIT | M_ZERO);
+ if (!dev->vblank_inmodeset)
+ goto err;
+
dev->_vblank_time = malloc(num_crtcs * DRM_VBLANKTIME_RBSIZE *
- sizeof(struct timeval), DRM_MEM_VBLANK, M_WAITOK | M_ZERO);
+ sizeof(struct timeval), DRM_MEM_VBLANK, M_NOWAIT | M_ZERO);
+ if (!dev->_vblank_time)
+ goto err;
+
DRM_INFO("Supports vblank timestamp caching Rev 1 (10.10.2010).\n");
/* Driver specific high-precision vblank timestamping supported? */
@@ -394,16 +267,203 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs)
dev->vblank_disable_allowed = 0;
return 0;
+
+err:
+ drm_vblank_cleanup(dev);
+ return ret;
+}
+EXPORT_SYMBOL(drm_vblank_init);
+
+/**
+ * Install IRQ handler.
+ *
+ * \param dev DRM device.
+ *
+ * Initializes the IRQ related data. Installs the handler, calling the driver
+ * \c irq_preinstall() and \c irq_postinstall() functions
+ * before and after the installation.
+ */
+int drm_irq_install(struct drm_device *dev)
+{
+ int ret;
+ unsigned long sh_flags = 0;
+
+ if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
+ return -EINVAL;
+
+ if (drm_dev_to_irq(dev) == 0)
+ return -EINVAL;
+
+ DRM_LOCK(dev);
+
+ /* Driver must have been initialized */
+ if (!dev->dev_private) {
+ DRM_UNLOCK(dev);
+ return -EINVAL;
+ }
+
+ if (dev->irq_enabled) {
+ DRM_UNLOCK(dev);
+ return -EBUSY;
+ }
+ dev->irq_enabled = 1;
+ DRM_UNLOCK(dev);
+
+ DRM_DEBUG("irq=%d\n", drm_dev_to_irq(dev));
+
+ /* Before installing handler */
+ if (dev->driver->irq_preinstall)
+ dev->driver->irq_preinstall(dev);
+
+ /* Install handler */
+ sh_flags = INTR_TYPE_TTY | INTR_MPSAFE;
+ if (!drm_core_check_feature(dev, DRIVER_IRQ_SHARED))
+ /*
+ * FIXME Linux<->FreeBSD: This seems to make
+ * bus_setup_intr() unhappy: it was reported to return
+ * EINVAL on an i915 board (8086:2592 in a Thinkpad
+ * X41).
+ *
+ * For now, no driver we have use that.
+ */
+ sh_flags |= INTR_EXCL;
+
+ ret = -bus_setup_intr(dev->dev, dev->irqr, sh_flags, NULL,
+ dev->driver->irq_handler, dev, &dev->irqh);
+
+ if (ret < 0) {
+ device_printf(dev->dev, "Error setting interrupt: %d\n", -ret);
+ DRM_LOCK(dev);
+ dev->irq_enabled = 0;
+ DRM_UNLOCK(dev);
+ return ret;
+ }
+
+ /* After installing handler */
+ if (dev->driver->irq_postinstall)
+ ret = dev->driver->irq_postinstall(dev);
+
+ if (ret < 0) {
+ DRM_LOCK(dev);
+ dev->irq_enabled = 0;
+ DRM_UNLOCK(dev);
+ bus_teardown_intr(dev->dev, dev->irqr, dev->irqh);
+ dev->driver->bus->free_irq(dev);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(drm_irq_install);
+
+/**
+ * Uninstall the IRQ handler.
+ *
+ * \param dev DRM device.
+ *
+ * Calls the driver's \c irq_uninstall() function, and stops the irq.
+ */
+int drm_irq_uninstall(struct drm_device *dev)
+{
+ int irq_enabled, i;
+
+ if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
+ return -EINVAL;
+
+ DRM_LOCK(dev);
+ irq_enabled = dev->irq_enabled;
+ dev->irq_enabled = 0;
+ DRM_UNLOCK(dev);
+
+ /*
+ * Wake up any waiters so they don't hang.
+ */
+ if (dev->num_crtcs) {
+ mtx_lock(&dev->vbl_lock);
+ for (i = 0; i < dev->num_crtcs; i++) {
+ DRM_WAKEUP(&dev->_vblank_count[i]);
+ dev->vblank_enabled[i] = 0;
+ dev->last_vblank[i] =
+ dev->driver->get_vblank_counter(dev, i);
+ }
+ mtx_unlock(&dev->vbl_lock);
+ }
+
+ if (!irq_enabled)
+ return -EINVAL;
+
+ DRM_DEBUG("irq=%d\n", drm_dev_to_irq(dev));
+
+ if (dev->driver->irq_uninstall)
+ dev->driver->irq_uninstall(dev);
+
+ bus_teardown_intr(dev->dev, dev->irqr, dev->irqh);
+ dev->driver->bus->free_irq(dev);
+
+ return 0;
}
+EXPORT_SYMBOL(drm_irq_uninstall);
-void
-drm_calc_timestamping_constants(struct drm_crtc *crtc)
+/**
+ * IRQ control ioctl.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_control structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Calls irq_install() or irq_uninstall() according to \p arg.
+ */
+int drm_control(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
- int64_t linedur_ns = 0, pixeldur_ns = 0, framedur_ns = 0;
- uint64_t dotclock;
+ struct drm_control *ctl = data;
+
+ /* if we haven't irq we fallback for compatibility reasons -
+ * this used to be a separate function in drm_dma.h
+ */
+
+
+ switch (ctl->func) {
+ case DRM_INST_HANDLER:
+ if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
+ return 0;
+ if (drm_core_check_feature(dev, DRIVER_MODESET))
+ return 0;
+ if (dev->if_version < DRM_IF_VERSION(1, 2) &&
+ ctl->irq != drm_dev_to_irq(dev))
+ return -EINVAL;
+ return drm_irq_install(dev);
+ case DRM_UNINST_HANDLER:
+ if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
+ return 0;
+ if (drm_core_check_feature(dev, DRIVER_MODESET))
+ return 0;
+ return drm_irq_uninstall(dev);
+ default:
+ return -EINVAL;
+ }
+}
+
+/**
+ * drm_calc_timestamping_constants - Calculate and
+ * store various constants which are later needed by
+ * vblank and swap-completion timestamping, e.g, by
+ * drm_calc_vbltimestamp_from_scanoutpos().
+ * They are derived from crtc's true scanout timing,
+ * so they take things like panel scaling or other
+ * adjustments into account.
+ *
+ * @crtc drm_crtc whose timestamp constants should be updated.
+ *
+ */
+void drm_calc_timestamping_constants(struct drm_crtc *crtc)
+{
+ s64 linedur_ns = 0, pixeldur_ns = 0, framedur_ns = 0;
+ u64 dotclock;
/* Dot clock in Hz: */
- dotclock = (uint64_t) crtc->hwmode.clock * 1000;
+ dotclock = (u64) crtc->hwmode.clock * 1000;
/* Fields of interlaced scanout modes are only halve a frame duration.
* Double the dotclock to get halve the frame-/line-/pixelduration.
@@ -417,10 +477,10 @@ drm_calc_timestamping_constants(struct drm_crtc *crtc)
* line duration, frame duration and pixel duration in
* nanoseconds:
*/
- pixeldur_ns = (int64_t)1000000000 / dotclock;
- linedur_ns = ((uint64_t)crtc->hwmode.crtc_htotal *
- 1000000000) / dotclock;
- framedur_ns = (int64_t)crtc->hwmode.crtc_vtotal * linedur_ns;
+ pixeldur_ns = (s64) div64_u64(1000000000, dotclock);
+ linedur_ns = (s64) div64_u64(((u64) crtc->hwmode.crtc_htotal *
+ 1000000000), dotclock);
+ framedur_ns = (s64) crtc->hwmode.crtc_vtotal * linedur_ns;
} else
DRM_ERROR("crtc %d: Can't calculate constants, dotclock = 0!\n",
crtc->base.id);
@@ -436,6 +496,7 @@ drm_calc_timestamping_constants(struct drm_crtc *crtc)
crtc->base.id, (int) dotclock/1000, (int) framedur_ns,
(int) linedur_ns, (int) pixeldur_ns);
}
+EXPORT_SYMBOL(drm_calc_timestamping_constants);
/**
* drm_calc_vbltimestamp_from_scanoutpos - helper routine for kms
@@ -481,16 +542,17 @@ drm_calc_timestamping_constants(struct drm_crtc *crtc)
* DRM_VBLANKTIME_INVBL - Timestamp taken while scanout was in vblank interval.
*
*/
-int
-drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
- int *max_error, struct timeval *vblank_time, unsigned flags,
- struct drm_crtc *refcrtc)
+int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
+ int *max_error,
+ struct timeval *vblank_time,
+ unsigned flags,
+ struct drm_crtc *refcrtc)
{
struct timeval stime, raw_time;
struct drm_display_mode *mode;
int vbl_status, vtotal, vdisplay;
int vpos, hpos, i;
- int64_t framedur_ns, linedur_ns, pixeldur_ns, delta_ns, duration_ns;
+ s64 framedur_ns, linedur_ns, pixeldur_ns, delta_ns, duration_ns;
bool invbl;
if (crtc < 0 || crtc >= dev->num_crtcs) {
@@ -530,7 +592,7 @@ drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
*/
for (i = 0; i < DRM_TIMESTAMP_MAXRETRIES; i++) {
/* Disable preemption to make it very likely to
- * succeed in the first iteration.
+ * succeed in the first iteration even on PREEMPT_RT kernel.
*/
critical_enter();
@@ -542,6 +604,10 @@ drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
/* Get system timestamp after query. */
getmicrouptime(&raw_time);
+#ifdef FREEBSD_NOTYET
+ if (!drm_timestamp_monotonic)
+ mono_time_offset = ktime_get_monotonic_offset();
+#endif /* FREEBSD_NOTYET */
critical_exit();
@@ -555,7 +621,7 @@ drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
duration_ns = timeval_to_ns(&raw_time) - timeval_to_ns(&stime);
/* Accept result with < max_error nsecs timing uncertainty. */
- if (duration_ns <= (int64_t) *max_error)
+ if (duration_ns <= (s64) *max_error)
break;
}
@@ -579,7 +645,7 @@ drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
* since start of scanout at first display scanline. delta_ns
* can be negative if start of scanout hasn't happened yet.
*/
- delta_ns = (int64_t)vpos * linedur_ns + (int64_t)hpos * pixeldur_ns;
+ delta_ns = (s64) vpos * linedur_ns + (s64) hpos * pixeldur_ns;
/* Is vpos outside nominal vblank area, but less than
* 1/100 of a frame height away from start of vblank?
@@ -599,6 +665,13 @@ drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
vbl_status |= 0x8;
}
+#ifdef FREEBSD_NOTYET
+ if (!drm_timestamp_monotonic)
+ etime = ktime_sub(etime, mono_time_offset);
+
+ /* save this only for debugging purposes */
+ tv_etime = ktime_to_timeval(etime);
+#endif /* FREEBSD_NOTYET */
/* Subtract time delta from raw timestamp to get final
* vblank_time timestamp for end of vblank.
*/
@@ -615,6 +688,20 @@ drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
return vbl_status;
}
+EXPORT_SYMBOL(drm_calc_vbltimestamp_from_scanoutpos);
+
+static struct timeval get_drm_timestamp(void)
+{
+ struct timeval now;
+
+ microtime(&now);
+#ifdef FREEBSD_NOTYET
+ if (!drm_timestamp_monotonic)
+ now = ktime_sub(now, ktime_get_monotonic_offset());
+#endif /* defined(FREEBSD_NOTYET) */
+
+ return now;
+}
/**
* drm_get_last_vbltimestamp - retrieve raw timestamp for the most recent
@@ -653,12 +740,13 @@ u32 drm_get_last_vbltimestamp(struct drm_device *dev, int crtc,
}
/* GPU high precision timestamp query unsupported or failed.
- * Return gettimeofday timestamp as best estimate.
+ * Return current monotonic/gettimeofday timestamp as best estimate.
*/
- microtime(tvblank);
+ *tvblank = get_drm_timestamp();
return 0;
}
+EXPORT_SYMBOL(drm_get_last_vbltimestamp);
/**
* drm_vblank_count - retrieve "cooked" vblank counter value
@@ -673,6 +761,7 @@ u32 drm_vblank_count(struct drm_device *dev, int crtc)
{
return atomic_read(&dev->_vblank_count[crtc]);
}
+EXPORT_SYMBOL(drm_vblank_count);
/**
* drm_vblank_count_and_time - retrieve "cooked" vblank counter value
@@ -701,11 +790,53 @@ u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc,
do {
cur_vblank = atomic_read(&dev->_vblank_count[crtc]);
*vblanktime = vblanktimestamp(dev, crtc, cur_vblank);
- rmb();
+ smp_rmb();
} while (cur_vblank != atomic_read(&dev->_vblank_count[crtc]));
return cur_vblank;
}
+EXPORT_SYMBOL(drm_vblank_count_and_time);
+
+static void send_vblank_event(struct drm_device *dev,
+ struct drm_pending_vblank_event *e,
+ unsigned long seq, struct timeval *now)
+{
+ WARN_ON_SMP(!mtx_owned(&dev->event_lock));
+ e->event.sequence = seq;
+ e->event.tv_sec = now->tv_sec;
+ e->event.tv_usec = now->tv_usec;
+
+ list_add_tail(&e->base.link,
+ &e->base.file_priv->event_list);
+ drm_event_wakeup(&e->base);
+ CTR3(KTR_DRM, "vblank_event_delivered %d %d %d",
+ e->base.pid, e->pipe, e->event.sequence);
+}
+
+/**
+ * drm_send_vblank_event - helper to send vblank event after pageflip
+ * @dev: DRM device
+ * @crtc: CRTC in question
+ * @e: the event to send
+ *
+ * Updates sequence # and timestamp on event, and sends it to userspace.
+ * Caller must hold event lock.
+ */
+void drm_send_vblank_event(struct drm_device *dev, int crtc,
+ struct drm_pending_vblank_event *e)
+{
+ struct timeval now;
+ unsigned int seq;
+ if (crtc >= 0) {
+ seq = drm_vblank_count_and_time(dev, crtc, &now);
+ } else {
+ seq = 0;
+
+ now = get_drm_timestamp();
+ }
+ send_vblank_event(dev, e, seq, &now);
+}
+EXPORT_SYMBOL(drm_send_vblank_event);
/**
* drm_update_vblank_count - update the master vblank counter
@@ -766,7 +897,9 @@ static void drm_update_vblank_count(struct drm_device *dev, int crtc)
vblanktimestamp(dev, crtc, tslot) = t_vblank;
}
+ smp_mb__before_atomic_inc();
atomic_add(diff, &dev->_vblank_count[crtc]);
+ smp_mb__after_atomic_inc();
}
/**
@@ -795,7 +928,7 @@ int drm_vblank_get(struct drm_device *dev, int crtc)
* timestamps. Filtercode in drm_handle_vblank() will
* prevent double-accounting of same vblank interval.
*/
- ret = -dev->driver->enable_vblank(dev, crtc);
+ ret = dev->driver->enable_vblank(dev, crtc);
DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n",
crtc, ret);
if (ret)
@@ -809,13 +942,14 @@ int drm_vblank_get(struct drm_device *dev, int crtc)
} else {
if (!dev->vblank_enabled[crtc]) {
atomic_dec(&dev->vblank_refcount[crtc]);
- ret = EINVAL;
+ ret = -EINVAL;
}
}
mtx_unlock(&dev->vbl_lock);
return ret;
}
+EXPORT_SYMBOL(drm_vblank_get);
/**
* drm_vblank_put - give up ownership of vblank events
@@ -827,8 +961,7 @@ int drm_vblank_get(struct drm_device *dev, int crtc)
*/
void drm_vblank_put(struct drm_device *dev, int crtc)
{
- KASSERT(atomic_read(&dev->vblank_refcount[crtc]) != 0,
- ("Too many drm_vblank_put for crtc %d", crtc));
+ BUG_ON(atomic_read(&dev->vblank_refcount[crtc]) == 0);
/* Last user schedules interrupt disable */
if (atomic_dec_and_test(&dev->vblank_refcount[crtc]) &&
@@ -837,7 +970,15 @@ void drm_vblank_put(struct drm_device *dev, int crtc)
(drm_vblank_offdelay * DRM_HZ) / 1000,
vblank_disable_fn, dev);
}
+EXPORT_SYMBOL(drm_vblank_put);
+/**
+ * drm_vblank_off - disable vblank events on a CRTC
+ * @dev: DRM device
+ * @crtc: CRTC in question
+ *
+ * Caller must hold event lock.
+ */
void drm_vblank_off(struct drm_device *dev, int crtc)
{
struct drm_pending_vblank_event *e, *t;
@@ -846,37 +987,32 @@ void drm_vblank_off(struct drm_device *dev, int crtc)
mtx_lock(&dev->vbl_lock);
vblank_disable_and_save(dev, crtc);
- mtx_lock(&dev->event_lock);
- wakeup(&dev->_vblank_count[crtc]);
+ DRM_WAKEUP(&dev->_vblank_count[crtc]);
/* Send any queued vblank events, lest the natives grow disquiet */
seq = drm_vblank_count_and_time(dev, crtc, &now);
+
+ mtx_lock(&dev->event_lock);
list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) {
if (e->pipe != crtc)
continue;
DRM_DEBUG("Sending premature vblank event on disable: \
wanted %d, current %d\n",
e->event.sequence, seq);
-
- e->event.sequence = seq;
- e->event.tv_sec = now.tv_sec;
- e->event.tv_usec = now.tv_usec;
+ list_del(&e->base.link);
drm_vblank_put(dev, e->pipe);
- list_move_tail(&e->base.link, &e->base.file_priv->event_list);
- drm_event_wakeup(&e->base);
- CTR3(KTR_DRM, "vblank_event_delivered %d %d %d",
- e->base.pid, e->pipe, e->event.sequence);
+ send_vblank_event(dev, e, seq, &now);
}
-
mtx_unlock(&dev->event_lock);
+
mtx_unlock(&dev->vbl_lock);
}
+EXPORT_SYMBOL(drm_vblank_off);
/**
* drm_vblank_pre_modeset - account for vblanks across mode sets
* @dev: DRM device
* @crtc: CRTC in question
- * @post: post or pre mode set?
*
* Account for vblank events across mode setting events, which will likely
* reset the hardware frame counter.
@@ -899,6 +1035,7 @@ void drm_vblank_pre_modeset(struct drm_device *dev, int crtc)
dev->vblank_inmodeset[crtc] |= 0x2;
}
}
+EXPORT_SYMBOL(drm_vblank_pre_modeset);
void drm_vblank_post_modeset(struct drm_device *dev, int crtc)
{
@@ -917,6 +1054,7 @@ void drm_vblank_post_modeset(struct drm_device *dev, int crtc)
dev->vblank_inmodeset[crtc] = 0;
}
}
+EXPORT_SYMBOL(drm_vblank_post_modeset);
/**
* drm_modeset_ctl - handle vblank event counter changes across mode switch
@@ -939,6 +1077,10 @@ int drm_modeset_ctl(struct drm_device *dev, void *data,
if (!dev->num_crtcs)
return 0;
+ /* KMS drivers handle this internally */
+ if (drm_core_check_feature(dev, DRIVER_MODESET))
+ return 0;
+
crtc = modeset->crtc;
if (crtc >= dev->num_crtcs)
return -EINVAL;
@@ -952,7 +1094,6 @@ int drm_modeset_ctl(struct drm_device *dev, void *data,
break;
default:
return -EINVAL;
- break;
}
return 0;
@@ -974,7 +1115,11 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
unsigned int seq;
int ret;
- e = malloc(sizeof *e, DRM_MEM_VBLANK, M_WAITOK | M_ZERO);
+ e = malloc(sizeof *e, DRM_MEM_VBLANK, M_NOWAIT | M_ZERO);
+ if (e == NULL) {
+ ret = -ENOMEM;
+ goto err_put;
+ }
e->pipe = pipe;
e->base.pid = curproc->p_pid;
@@ -988,7 +1133,7 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
mtx_lock(&dev->event_lock);
if (file_priv->event_space < sizeof e->event) {
- ret = EBUSY;
+ ret = -EBUSY;
goto err_unlock;
}
@@ -1009,15 +1154,9 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
e->event.sequence = vblwait->request.sequence;
if ((seq - vblwait->request.sequence) <= (1 << 23)) {
- e->event.sequence = seq;
- e->event.tv_sec = now.tv_sec;
- e->event.tv_usec = now.tv_usec;
drm_vblank_put(dev, pipe);
- list_add_tail(&e->base.link, &e->base.file_priv->event_list);
- drm_event_wakeup(&e->base);
+ send_vblank_event(dev, e, seq, &now);
vblwait->reply.sequence = seq;
- CTR3(KTR_DRM, "vblank_event_wakeup p1 %d %d %d", curproc->p_pid,
- pipe, vblwait->request.sequence);
} else {
/* drm_handle_vblank_events will call drm_vblank_put */
list_add_tail(&e->base.link, &dev->vblank_event_list);
@@ -1031,6 +1170,7 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
err_unlock:
mtx_unlock(&dev->event_lock);
free(e, DRM_MEM_VBLANK);
+err_put:
drm_vblank_put(dev, pipe);
return ret;
}
@@ -1057,10 +1197,10 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
unsigned int flags, seq, crtc, high_crtc;
if (/*(!drm_dev_to_irq(dev)) || */(!dev->irq_enabled))
- return (EINVAL);
+ return -EINVAL;
if (vblwait->request.type & _DRM_VBLANK_SIGNAL)
- return (EINVAL);
+ return -EINVAL;
if (vblwait->request.type &
~(_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK |
@@ -1069,7 +1209,7 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
vblwait->request.type,
(_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK |
_DRM_VBLANK_HIGH_CRTC_MASK));
- return (EINVAL);
+ return -EINVAL;
}
flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK;
@@ -1079,12 +1219,12 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
else
crtc = flags & _DRM_VBLANK_SECONDARY ? 1 : 0;
if (crtc >= dev->num_crtcs)
- return (EINVAL);
+ return -EINVAL;
ret = drm_vblank_get(dev, crtc);
if (ret) {
DRM_DEBUG("failed to acquire vblank counter, %d\n", ret);
- return (ret);
+ return ret;
}
seq = drm_vblank_count(dev, crtc);
@@ -1095,7 +1235,7 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
case _DRM_VBLANK_ABSOLUTE:
break;
default:
- ret = (EINVAL);
+ ret = -EINVAL;
goto done;
}
@@ -1111,6 +1251,8 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
vblwait->request.sequence = seq + 1;
}
+ DRM_DEBUG("waiting on vblank count %d, crtc %d\n",
+ vblwait->request.sequence, crtc);
dev->last_vblank_wait[crtc] = vblwait->request.sequence;
mtx_lock(&dev->vblank_time_lock);
while (((drm_vblank_count(dev, crtc) - vblwait->request.sequence) >
@@ -1123,13 +1265,15 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
* application when crtc is disabled or irq
* uninstalled anyway.
*/
- ret = msleep(&dev->_vblank_count[crtc], &dev->vblank_time_lock,
+ ret = -msleep(&dev->_vblank_count[crtc], &dev->vblank_time_lock,
PCATCH, "drmvbl", 3 * hz);
+ if (ret == -ERESTART)
+ ret = -ERESTARTSYS;
if (ret != 0)
break;
}
mtx_unlock(&dev->vblank_time_lock);
- if (ret != EINTR) {
+ if (ret != -EINTR) {
struct timeval now;
long reply_seq;
@@ -1137,13 +1281,19 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
CTR5(KTR_DRM, "wait_vblank %d %d rt %x success %d %d",
curproc->p_pid, crtc, vblwait->request.type,
vblwait->request.sequence, reply_seq);
+
vblwait->reply.sequence = reply_seq;
vblwait->reply.tval_sec = now.tv_sec;
vblwait->reply.tval_usec = now.tv_usec;
+
+ DRM_DEBUG("returning %d to client\n",
+ vblwait->reply.sequence);
} else {
CTR5(KTR_DRM, "wait_vblank %d %d rt %x error %d %d",
curproc->p_pid, crtc, vblwait->request.type, ret,
vblwait->request.sequence);
+
+ DRM_DEBUG("vblank wait interrupted by signal\n");
}
done:
@@ -1151,14 +1301,13 @@ done:
return ret;
}
-void drm_handle_vblank_events(struct drm_device *dev, int crtc)
+static void drm_handle_vblank_events(struct drm_device *dev, int crtc)
{
struct drm_pending_vblank_event *e, *t;
struct timeval now;
unsigned int seq;
seq = drm_vblank_count_and_time(dev, crtc, &now);
- CTR2(KTR_DRM, "drm_handle_vblank_events %d %d", seq, crtc);
mtx_lock(&dev->event_lock);
@@ -1168,17 +1317,17 @@ void drm_handle_vblank_events(struct drm_device *dev, int crtc)
if ((seq - e->event.sequence) > (1<<23))
continue;
- e->event.sequence = seq;
- e->event.tv_sec = now.tv_sec;
- e->event.tv_usec = now.tv_usec;
+ DRM_DEBUG("vblank event on %d, current %d\n",
+ e->event.sequence, seq);
+
+ list_del(&e->base.link);
drm_vblank_put(dev, e->pipe);
- list_move_tail(&e->base.link, &e->base.file_priv->event_list);
- drm_event_wakeup(&e->base);
- CTR3(KTR_DRM, "vblank_event_wakeup p2 %d %d %d", e->base.pid,
- e->pipe, e->event.sequence);
+ send_vblank_event(dev, e, seq, &now);
}
mtx_unlock(&dev->event_lock);
+
+ CTR2(KTR_DRM, "drm_handle_vblank_events %d %d", seq, crtc);
}
/**
@@ -1192,7 +1341,7 @@ void drm_handle_vblank_events(struct drm_device *dev, int crtc)
bool drm_handle_vblank(struct drm_device *dev, int crtc)
{
u32 vblcount;
- int64_t diff_ns;
+ s64 diff_ns;
struct timeval tvblank;
if (!dev->num_crtcs)
@@ -1238,15 +1387,18 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc)
/* Increment cooked vblank count. This also atomically commits
* the timestamp computed above.
*/
+ smp_mb__before_atomic_inc();
atomic_inc(&dev->_vblank_count[crtc]);
+ smp_mb__after_atomic_inc();
} else {
DRM_DEBUG("crtc %d: Redundant vblirq ignored. diff_ns = %d\n",
crtc, (int) diff_ns);
}
- wakeup(&dev->_vblank_count[crtc]);
+ DRM_WAKEUP(&dev->_vblank_count[crtc]);
drm_handle_vblank_events(dev, crtc);
mtx_unlock(&dev->vblank_time_lock);
return true;
}
+EXPORT_SYMBOL(drm_handle_vblank);
diff --git a/sys/dev/drm2/drm_lock.c b/sys/dev/drm2/drm_lock.c
index 8ae2305..1bc681c 100644
--- a/sys/dev/drm2/drm_lock.c
+++ b/sys/dev/drm2/drm_lock.c
@@ -1,4 +1,14 @@
-/*-
+/**
+ * \file drm_lock.c
+ * IOCTLs for locking
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
+ * Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com
+ *
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
* All Rights Reserved.
@@ -21,179 +31,346 @@
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Rickard E. (Rik) Faith <faith@valinux.com>
- * Gareth Hughes <gareth@valinux.com>
- *
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-/** @file drm_lock.c
- * Implementation of the ioctls and other support code for dealing with the
- * hardware lock.
- *
- * The DRM hardware lock is a shared structure between the kernel and userland.
- *
- * On uncontended access where the new context was the last context, the
- * client may take the lock without dropping down into the kernel, using atomic
- * compare-and-set.
+#include <dev/drm2/drmP.h>
+
+static int drm_notifier(void *priv);
+
+static int drm_lock_take(struct drm_lock_data *lock_data, unsigned int context);
+
+/**
+ * Lock ioctl.
*
- * If the client finds during compare-and-set that it was not the last owner
- * of the lock, it calls the DRM lock ioctl, which may sleep waiting for the
- * lock, and may have side-effects of kernel-managed context switching.
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_lock structure.
+ * \return zero on success or negative number on failure.
*
- * When the client releases the lock, if the lock is marked as being contended
- * by another client, then the DRM unlock ioctl is called so that the
- * contending client may be woken up.
+ * Add the current task to the lock wait queue, and attempt to take to lock.
*/
-
-#include <dev/drm2/drmP.h>
-
int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
struct drm_lock *lock = data;
+ struct drm_master *master = file_priv->master;
int ret = 0;
+ ++file_priv->lock_count;
+
if (lock->context == DRM_KERNEL_CONTEXT) {
DRM_ERROR("Process %d using kernel context %d\n",
- DRM_CURRENTPID, lock->context);
- return EINVAL;
+ DRM_CURRENTPID, lock->context);
+ return -EINVAL;
}
DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
- lock->context, DRM_CURRENTPID, dev->lock.hw_lock->lock,
- lock->flags);
+ lock->context, DRM_CURRENTPID,
+ master->lock.hw_lock->lock, lock->flags);
- if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) &&
- lock->context < 0)
- return EINVAL;
+ mtx_lock(&master->lock.spinlock);
+ master->lock.user_waiters++;
+ mtx_unlock(&master->lock.spinlock);
- DRM_LOCK(dev);
for (;;) {
- if (drm_lock_take(&dev->lock, lock->context)) {
- dev->lock.file_priv = file_priv;
- dev->lock.lock_time = jiffies;
+#if defined(__linux__)
+ if (!master->lock.hw_lock) {
+ /* Device has been unregistered */
+ send_sig(SIGTERM, current, 0);
+ ret = -EINTR;
+ break;
+ }
+#endif
+ if (drm_lock_take(&master->lock, lock->context)) {
+ master->lock.file_priv = file_priv;
+ master->lock.lock_time = jiffies;
atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
- break; /* Got lock */
+ break; /* Got lock */
}
/* Contention */
- ret = DRM_LOCK_SLEEP(dev, &dev->lock.lock_queue,
+ DRM_UNLOCK_ASSERT(dev);
+ ret = -sx_sleep(&master->lock.lock_queue, &drm_global_mutex,
PCATCH, "drmlk2", 0);
+ if (ret == -ERESTART)
+ ret = -ERESTARTSYS;
if (ret != 0)
break;
}
- DRM_UNLOCK(dev);
-
- if (ret == ERESTART)
- DRM_DEBUG("restarting syscall\n");
- else
- DRM_DEBUG("%d %s\n", lock->context,
- ret ? "interrupted" : "has lock");
+ mtx_lock(&master->lock.spinlock);
+ master->lock.user_waiters--;
+ mtx_unlock(&master->lock.spinlock);
- if (ret != 0)
- return ret;
+ DRM_DEBUG("%d %s\n", lock->context,
+ ret ? "interrupted" : "has lock");
+ if (ret) return ret;
- /* XXX: Add signal blocking here */
+#if defined(__linux__)
+ /* don't set the block all signals on the master process for now
+ * really probably not the correct answer but lets us debug xkb
+ * xserver for now */
+ if (!file_priv->is_master) {
+ sigemptyset(&dev->sigmask);
+ sigaddset(&dev->sigmask, SIGSTOP);
+ sigaddset(&dev->sigmask, SIGTSTP);
+ sigaddset(&dev->sigmask, SIGTTIN);
+ sigaddset(&dev->sigmask, SIGTTOU);
+ dev->sigdata.context = lock->context;
+ dev->sigdata.lock = master->lock.hw_lock;
+ block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask);
+ }
+#endif
- if (dev->driver->dma_quiescent != NULL &&
- (lock->flags & _DRM_LOCK_QUIESCENT))
- dev->driver->dma_quiescent(dev);
+ if (dev->driver->dma_quiescent && (lock->flags & _DRM_LOCK_QUIESCENT))
+ {
+ if (dev->driver->dma_quiescent(dev)) {
+ DRM_DEBUG("%d waiting for DMA quiescent\n",
+ lock->context);
+ return -EBUSY;
+ }
+ }
return 0;
}
+/**
+ * Unlock ioctl.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_lock structure.
+ * \return zero on success or negative number on failure.
+ *
+ * Transfer and free the lock.
+ */
int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
struct drm_lock *lock = data;
-
- DRM_DEBUG("%d (pid %d) requests unlock (0x%08x), flags = 0x%08x\n",
- lock->context, DRM_CURRENTPID, dev->lock.hw_lock->lock,
- lock->flags);
+ struct drm_master *master = file_priv->master;
if (lock->context == DRM_KERNEL_CONTEXT) {
DRM_ERROR("Process %d using kernel context %d\n",
- DRM_CURRENTPID, lock->context);
- return EINVAL;
+ DRM_CURRENTPID, lock->context);
+ return -EINVAL;
}
atomic_inc(&dev->counts[_DRM_STAT_UNLOCKS]);
- DRM_LOCK(dev);
- drm_lock_transfer(&dev->lock, DRM_KERNEL_CONTEXT);
-
- if (drm_lock_free(&dev->lock, DRM_KERNEL_CONTEXT)) {
- DRM_ERROR("\n");
+ if (drm_lock_free(&master->lock, lock->context)) {
+ /* FIXME: Should really bail out here. */
}
- DRM_UNLOCK(dev);
+#if defined(__linux__)
+ unblock_all_signals();
+#endif
return 0;
}
-int drm_lock_take(struct drm_lock_data *lock_data, unsigned int context)
+/**
+ * Take the heavyweight lock.
+ *
+ * \param lock lock pointer.
+ * \param context locking context.
+ * \return one if the lock is held, or zero otherwise.
+ *
+ * Attempt to mark the lock as held by the given context, via the \p cmpxchg instruction.
+ */
+static
+int drm_lock_take(struct drm_lock_data *lock_data,
+ unsigned int context)
{
+ unsigned int old, new, prev;
volatile unsigned int *lock = &lock_data->hw_lock->lock;
- unsigned int old, new;
+ mtx_lock(&lock_data->spinlock);
do {
old = *lock;
if (old & _DRM_LOCK_HELD)
new = old | _DRM_LOCK_CONT;
- else
- new = context | _DRM_LOCK_HELD;
- } while (!atomic_cmpset_int(lock, old, new));
+ else {
+ new = context | _DRM_LOCK_HELD |
+ ((lock_data->user_waiters + lock_data->kernel_waiters > 1) ?
+ _DRM_LOCK_CONT : 0);
+ }
+ prev = cmpxchg(lock, old, new);
+ } while (prev != old);
+ mtx_unlock(&lock_data->spinlock);
if (_DRM_LOCKING_CONTEXT(old) == context) {
if (old & _DRM_LOCK_HELD) {
if (context != DRM_KERNEL_CONTEXT) {
DRM_ERROR("%d holds heavyweight lock\n",
- context);
+ context);
}
return 0;
}
}
- if (new == (context | _DRM_LOCK_HELD)) {
+
+ if ((_DRM_LOCKING_CONTEXT(new)) == context && (new & _DRM_LOCK_HELD)) {
/* Have lock */
return 1;
}
return 0;
}
-/* This takes a lock forcibly and hands it to context. Should ONLY be used
- inside *_unlock to give lock to kernel before calling *_dma_schedule. */
-int drm_lock_transfer(struct drm_lock_data *lock_data, unsigned int context)
+/**
+ * This takes a lock forcibly and hands it to context. Should ONLY be used
+ * inside *_unlock to give lock to kernel before calling *_dma_schedule.
+ *
+ * \param dev DRM device.
+ * \param lock lock pointer.
+ * \param context locking context.
+ * \return always one.
+ *
+ * Resets the lock file pointer.
+ * Marks the lock as held by the given context, via the \p cmpxchg instruction.
+ */
+static int drm_lock_transfer(struct drm_lock_data *lock_data,
+ unsigned int context)
{
+ unsigned int old, new, prev;
volatile unsigned int *lock = &lock_data->hw_lock->lock;
- unsigned int old, new;
lock_data->file_priv = NULL;
do {
old = *lock;
new = context | _DRM_LOCK_HELD;
- } while (!atomic_cmpset_int(lock, old, new));
-
+ prev = cmpxchg(lock, old, new);
+ } while (prev != old);
return 1;
}
+/**
+ * Free lock.
+ *
+ * \param dev DRM device.
+ * \param lock lock.
+ * \param context context.
+ *
+ * Resets the lock file pointer.
+ * Marks the lock as not held, via the \p cmpxchg instruction. Wakes any task
+ * waiting on the lock queue.
+ */
int drm_lock_free(struct drm_lock_data *lock_data, unsigned int context)
{
+ unsigned int old, new, prev;
volatile unsigned int *lock = &lock_data->hw_lock->lock;
- unsigned int old, new;
- lock_data->file_priv = NULL;
+ mtx_lock(&lock_data->spinlock);
+ if (lock_data->kernel_waiters != 0) {
+ drm_lock_transfer(lock_data, 0);
+ lock_data->idle_has_lock = 1;
+ mtx_unlock(&lock_data->spinlock);
+ return 1;
+ }
+ mtx_unlock(&lock_data->spinlock);
+
do {
old = *lock;
- new = 0;
- } while (!atomic_cmpset_int(lock, old, new));
+ new = _DRM_LOCKING_CONTEXT(old);
+ prev = cmpxchg(lock, old, new);
+ } while (prev != old);
if (_DRM_LOCK_IS_HELD(old) && _DRM_LOCKING_CONTEXT(old) != context) {
DRM_ERROR("%d freed heavyweight lock held by %d\n",
- context, _DRM_LOCKING_CONTEXT(old));
+ context, _DRM_LOCKING_CONTEXT(old));
return 1;
}
- DRM_WAKEUP_INT((void *)&lock_data->lock_queue);
+ wake_up_interruptible(&lock_data->lock_queue);
return 0;
}
+
+/**
+ * If we get here, it means that the process has called DRM_IOCTL_LOCK
+ * without calling DRM_IOCTL_UNLOCK.
+ *
+ * If the lock is not held, then let the signal proceed as usual. If the lock
+ * is held, then set the contended flag and keep the signal blocked.
+ *
+ * \param priv pointer to a drm_sigdata structure.
+ * \return one if the signal should be delivered normally, or zero if the
+ * signal should be blocked.
+ */
+static int drm_notifier(void *priv)
+{
+ struct drm_sigdata *s = (struct drm_sigdata *) priv;
+ unsigned int old, new, prev;
+
+ /* Allow signal delivery if lock isn't held */
+ if (!s->lock || !_DRM_LOCK_IS_HELD(s->lock->lock)
+ || _DRM_LOCKING_CONTEXT(s->lock->lock) != s->context)
+ return 1;
+
+ /* Otherwise, set flag to force call to
+ drmUnlock */
+ do {
+ old = s->lock->lock;
+ new = old | _DRM_LOCK_CONT;
+ prev = cmpxchg(&s->lock->lock, old, new);
+ } while (prev != old);
+ return 0;
+}
+
+/**
+ * This function returns immediately and takes the hw lock
+ * with the kernel context if it is free, otherwise it gets the highest priority when and if
+ * it is eventually released.
+ *
+ * This guarantees that the kernel will _eventually_ have the lock _unless_ it is held
+ * by a blocked process. (In the latter case an explicit wait for the hardware lock would cause
+ * a deadlock, which is why the "idlelock" was invented).
+ *
+ * This should be sufficient to wait for GPU idle without
+ * having to worry about starvation.
+ */
+
+void drm_idlelock_take(struct drm_lock_data *lock_data)
+{
+ int ret;
+
+ mtx_lock(&lock_data->spinlock);
+ lock_data->kernel_waiters++;
+ if (!lock_data->idle_has_lock) {
+
+ mtx_unlock(&lock_data->spinlock);
+ ret = drm_lock_take(lock_data, DRM_KERNEL_CONTEXT);
+ mtx_lock(&lock_data->spinlock);
+
+ if (ret == 1)
+ lock_data->idle_has_lock = 1;
+ }
+ mtx_unlock(&lock_data->spinlock);
+}
+EXPORT_SYMBOL(drm_idlelock_take);
+
+void drm_idlelock_release(struct drm_lock_data *lock_data)
+{
+ unsigned int old, prev;
+ volatile unsigned int *lock = &lock_data->hw_lock->lock;
+
+ mtx_lock(&lock_data->spinlock);
+ if (--lock_data->kernel_waiters == 0) {
+ if (lock_data->idle_has_lock) {
+ do {
+ old = *lock;
+ prev = cmpxchg(lock, old, DRM_KERNEL_CONTEXT);
+ } while (prev != old);
+ wake_up_interruptible(&lock_data->lock_queue);
+ lock_data->idle_has_lock = 0;
+ }
+ }
+ mtx_unlock(&lock_data->spinlock);
+}
+EXPORT_SYMBOL(drm_idlelock_release);
+
+int drm_i_have_hw_lock(struct drm_device *dev, struct drm_file *file_priv)
+{
+ struct drm_master *master = file_priv->master;
+ return (file_priv->lock_count && master->lock.hw_lock &&
+ _DRM_LOCK_IS_HELD(master->lock.hw_lock->lock) &&
+ master->lock.file_priv == file_priv);
+}
diff --git a/sys/dev/drm2/drm_memory.c b/sys/dev/drm2/drm_memory.c
index af43a89..a25e5a2 100644
--- a/sys/dev/drm2/drm_memory.c
+++ b/sys/dev/drm2/drm_memory.c
@@ -1,11 +1,17 @@
-/*-
- *Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * Copyright (c) 2011 The FreeBSD Foundation
- * All rights reserved.
+/**
+ * \file drm_memory.c
+ * Memory management wrappers for DRM
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
+ * Created: Thu Feb 4 14:00:34 1999 by faith@valinux.com
*
- * Portions of this software were developed by Konstantin Belousov
- * under sponsorship from the FreeBSD Foundation.
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -25,111 +31,104 @@
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Rickard E. (Rik) Faith <faith@valinux.com>
- * Gareth Hughes <gareth@valinux.com>
- *
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-/** @file drm_memory.c
- * Wrappers for kernel memory allocation routines, and MTRR management support.
- *
- * This file previously implemented a memory consumption tracking system using
- * the "area" argument for various different types of allocations, but that
- * has been stripped out for now.
- */
-
#include <dev/drm2/drmP.h>
-MALLOC_DEFINE(DRM_MEM_DMA, "drm_dma", "DRM DMA Data Structures");
-MALLOC_DEFINE(DRM_MEM_SAREA, "drm_sarea", "DRM SAREA Data Structures");
-MALLOC_DEFINE(DRM_MEM_DRIVER, "drm_driver", "DRM DRIVER Data Structures");
-MALLOC_DEFINE(DRM_MEM_MAGIC, "drm_magic", "DRM MAGIC Data Structures");
-MALLOC_DEFINE(DRM_MEM_IOCTLS, "drm_ioctls", "DRM IOCTL Data Structures");
-MALLOC_DEFINE(DRM_MEM_MAPS, "drm_maps", "DRM MAP Data Structures");
-MALLOC_DEFINE(DRM_MEM_BUFS, "drm_bufs", "DRM BUFFER Data Structures");
-MALLOC_DEFINE(DRM_MEM_SEGS, "drm_segs", "DRM SEGMENTS Data Structures");
-MALLOC_DEFINE(DRM_MEM_PAGES, "drm_pages", "DRM PAGES Data Structures");
-MALLOC_DEFINE(DRM_MEM_FILES, "drm_files", "DRM FILE Data Structures");
-MALLOC_DEFINE(DRM_MEM_QUEUES, "drm_queues", "DRM QUEUE Data Structures");
-MALLOC_DEFINE(DRM_MEM_CMDS, "drm_cmds", "DRM COMMAND Data Structures");
-MALLOC_DEFINE(DRM_MEM_MAPPINGS, "drm_mapping", "DRM MAPPING Data Structures");
-MALLOC_DEFINE(DRM_MEM_BUFLISTS, "drm_buflists", "DRM BUFLISTS Data Structures");
-MALLOC_DEFINE(DRM_MEM_AGPLISTS, "drm_agplists", "DRM AGPLISTS Data Structures");
-MALLOC_DEFINE(DRM_MEM_CTXBITMAP, "drm_ctxbitmap",
- "DRM CTXBITMAP Data Structures");
-MALLOC_DEFINE(DRM_MEM_SGLISTS, "drm_sglists", "DRM SGLISTS Data Structures");
-MALLOC_DEFINE(DRM_MEM_DRAWABLE, "drm_drawable", "DRM DRAWABLE Data Structures");
-MALLOC_DEFINE(DRM_MEM_MM, "drm_sman", "DRM MEMORY MANAGER Data Structures");
-MALLOC_DEFINE(DRM_MEM_HASHTAB, "drm_hashtab", "DRM HASHTABLE Data Structures");
-MALLOC_DEFINE(DRM_MEM_KMS, "drm_kms", "DRM KMS Data Structures");
-
-void drm_mem_init(void)
+#if __OS_HAS_AGP
+static void *agp_remap(unsigned long offset, unsigned long size,
+ struct drm_device * dev)
{
+ /*
+ * FIXME Linux<->FreeBSD: Not implemented. This is never called
+ * on FreeBSD anyway, because drm_agp_mem->cant_use_aperture is
+ * set to 0.
+ */
+ return NULL;
}
-void drm_mem_uninit(void)
-{
-}
+#define vunmap(handle)
-void *drm_ioremap_wc(struct drm_device *dev, drm_local_map_t *map)
+/** Wrapper around agp_free_memory() */
+void drm_free_agp(DRM_AGP_MEM * handle, int pages)
{
- return pmap_mapdev_attr(map->offset, map->size, VM_MEMATTR_WRITE_COMBINING);
+ device_t agpdev;
+
+ agpdev = agp_find_device();
+ if (!agpdev || !handle)
+ return;
+
+ agp_free_memory(agpdev, handle);
}
+EXPORT_SYMBOL(drm_free_agp);
-void *drm_ioremap(struct drm_device *dev, drm_local_map_t *map)
+/** Wrapper around agp_bind_memory() */
+int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start)
{
- return pmap_mapdev(map->offset, map->size);
+ device_t agpdev;
+
+ agpdev = agp_find_device();
+ if (!agpdev || !handle)
+ return -EINVAL;
+
+ return -agp_bind_memory(agpdev, handle, start * PAGE_SIZE);
}
-void drm_ioremapfree(drm_local_map_t *map)
+/** Wrapper around agp_unbind_memory() */
+int drm_unbind_agp(DRM_AGP_MEM * handle)
{
- pmap_unmapdev((vm_offset_t) map->virtual, map->size);
+ device_t agpdev;
+
+ agpdev = agp_find_device();
+ if (!agpdev || !handle)
+ return -EINVAL;
+
+ return -agp_unbind_memory(agpdev, handle);
}
+EXPORT_SYMBOL(drm_unbind_agp);
-int
-drm_mtrr_add(unsigned long offset, size_t size, int flags)
+#else /* __OS_HAS_AGP */
+static inline void *agp_remap(unsigned long offset, unsigned long size,
+ struct drm_device * dev)
{
- int act;
- struct mem_range_desc mrdesc;
-
- mrdesc.mr_base = offset;
- mrdesc.mr_len = size;
- mrdesc.mr_flags = flags;
- act = MEMRANGE_SET_UPDATE;
- strlcpy(mrdesc.mr_owner, "drm", sizeof(mrdesc.mr_owner));
- return mem_range_attr_set(&mrdesc, &act);
+ return NULL;
}
-int
-drm_mtrr_del(int __unused handle, unsigned long offset, size_t size, int flags)
+#endif /* agp */
+
+void drm_core_ioremap(struct drm_local_map *map, struct drm_device *dev)
{
- int act;
- struct mem_range_desc mrdesc;
-
- mrdesc.mr_base = offset;
- mrdesc.mr_len = size;
- mrdesc.mr_flags = flags;
- act = MEMRANGE_SET_REMOVE;
- strlcpy(mrdesc.mr_owner, "drm", sizeof(mrdesc.mr_owner));
- return mem_range_attr_set(&mrdesc, &act);
+ if (drm_core_has_AGP(dev) &&
+ dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP)
+ map->handle = agp_remap(map->offset, map->size, dev);
+ else
+ map->handle = pmap_mapdev(map->offset, map->size);
}
+EXPORT_SYMBOL(drm_core_ioremap);
-void
-drm_clflush_pages(vm_page_t *pages, unsigned long num_pages)
+void drm_core_ioremap_wc(struct drm_local_map *map, struct drm_device *dev)
{
-
- pmap_invalidate_cache_pages(pages, num_pages);
+ if (drm_core_has_AGP(dev) &&
+ dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP)
+ map->handle = agp_remap(map->offset, map->size, dev);
+ else
+ map->handle = pmap_mapdev_attr(map->offset, map->size,
+ VM_MEMATTR_WRITE_COMBINING);
}
+EXPORT_SYMBOL(drm_core_ioremap_wc);
-void
-drm_clflush_virt_range(char *addr, unsigned long length)
+void drm_core_ioremapfree(struct drm_local_map *map, struct drm_device *dev)
{
-
- pmap_invalidate_cache_range((vm_offset_t)addr,
- (vm_offset_t)addr + length, TRUE);
+ if (!map->handle || !map->size)
+ return;
+
+ if (drm_core_has_AGP(dev) &&
+ dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP)
+ vunmap(map->handle);
+ else
+ pmap_unmapdev((vm_offset_t)map->handle, map->size);
}
+EXPORT_SYMBOL(drm_core_ioremapfree);
diff --git a/sys/dev/drm2/drm_mm.c b/sys/dev/drm2/drm_mm.c
index 3617b05..6c11ff7 100644
--- a/sys/dev/drm2/drm_mm.c
+++ b/sys/dev/drm2/drm_mm.c
@@ -53,8 +53,7 @@ static struct drm_mm_node *drm_mm_kmalloc(struct drm_mm *mm, int atomic)
{
struct drm_mm_node *child;
- child = malloc(sizeof(*child), DRM_MEM_MM, M_ZERO |
- (atomic ? M_NOWAIT : M_WAITOK));
+ child = malloc(sizeof(*child), DRM_MEM_MM, M_NOWAIT | M_ZERO);
if (unlikely(child == NULL)) {
mtx_lock(&mm->unused_lock);
@@ -72,6 +71,11 @@ static struct drm_mm_node *drm_mm_kmalloc(struct drm_mm *mm, int atomic)
return child;
}
+/* drm_mm_pre_get() - pre allocate drm_mm_node structure
+ * drm_mm: memory manager struct we are pre-allocating for
+ *
+ * Returns 0 on success or -ENOMEM if allocation fails.
+ */
int drm_mm_pre_get(struct drm_mm *mm)
{
struct drm_mm_node *node;
@@ -79,7 +83,7 @@ int drm_mm_pre_get(struct drm_mm *mm)
mtx_lock(&mm->unused_lock);
while (mm->num_unused < MM_UNUSED_TARGET) {
mtx_unlock(&mm->unused_lock);
- node = malloc(sizeof(*node), DRM_MEM_MM, M_WAITOK);
+ node = malloc(sizeof(*node), DRM_MEM_MM, M_NOWAIT | M_ZERO);
mtx_lock(&mm->unused_lock);
if (unlikely(node == NULL)) {
@@ -93,6 +97,7 @@ int drm_mm_pre_get(struct drm_mm *mm)
mtx_unlock(&mm->unused_lock);
return 0;
}
+EXPORT_SYMBOL(drm_mm_pre_get);
static inline unsigned long drm_mm_hole_node_start(struct drm_mm_node *hole_node)
{
@@ -110,45 +115,53 @@ static inline unsigned long drm_mm_hole_node_end(struct drm_mm_node *hole_node)
static void drm_mm_insert_helper(struct drm_mm_node *hole_node,
struct drm_mm_node *node,
- unsigned long size, unsigned alignment)
+ unsigned long size, unsigned alignment,
+ unsigned long color)
{
struct drm_mm *mm = hole_node->mm;
- unsigned long tmp = 0, wasted = 0;
unsigned long hole_start = drm_mm_hole_node_start(hole_node);
unsigned long hole_end = drm_mm_hole_node_end(hole_node);
+ unsigned long adj_start = hole_start;
+ unsigned long adj_end = hole_end;
+
+ BUG_ON(!hole_node->hole_follows || node->allocated);
- KASSERT(hole_node->hole_follows && !node->allocated, ("hole_node"));
+ if (mm->color_adjust)
+ mm->color_adjust(hole_node, color, &adj_start, &adj_end);
- if (alignment)
- tmp = hole_start % alignment;
+ if (alignment) {
+ unsigned tmp = adj_start % alignment;
+ if (tmp)
+ adj_start += alignment - tmp;
+ }
- if (!tmp) {
+ if (adj_start == hole_start) {
hole_node->hole_follows = 0;
- list_del_init(&hole_node->hole_stack);
- } else
- wasted = alignment - tmp;
+ list_del(&hole_node->hole_stack);
+ }
- node->start = hole_start + wasted;
+ node->start = adj_start;
node->size = size;
node->mm = mm;
+ node->color = color;
node->allocated = 1;
INIT_LIST_HEAD(&node->hole_stack);
list_add(&node->node_list, &hole_node->node_list);
- KASSERT(node->start + node->size <= hole_end, ("hole pos"));
+ BUG_ON(node->start + node->size > adj_end);
+ node->hole_follows = 0;
if (node->start + node->size < hole_end) {
list_add(&node->hole_stack, &mm->hole_stack);
node->hole_follows = 1;
- } else {
- node->hole_follows = 0;
}
}
struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *hole_node,
unsigned long size,
unsigned alignment,
+ unsigned long color,
int atomic)
{
struct drm_mm_node *node;
@@ -157,72 +170,96 @@ struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *hole_node,
if (unlikely(node == NULL))
return NULL;
- drm_mm_insert_helper(hole_node, node, size, alignment);
+ drm_mm_insert_helper(hole_node, node, size, alignment, color);
return node;
}
+EXPORT_SYMBOL(drm_mm_get_block_generic);
-int drm_mm_insert_node(struct drm_mm *mm, struct drm_mm_node *node,
- unsigned long size, unsigned alignment)
+/**
+ * Search for free space and insert a preallocated memory node. Returns
+ * -ENOSPC if no suitable free area is available. The preallocated memory node
+ * must be cleared.
+ */
+int drm_mm_insert_node_generic(struct drm_mm *mm, struct drm_mm_node *node,
+ unsigned long size, unsigned alignment,
+ unsigned long color)
{
struct drm_mm_node *hole_node;
- hole_node = drm_mm_search_free(mm, size, alignment, 0);
+ hole_node = drm_mm_search_free_generic(mm, size, alignment,
+ color, 0);
if (!hole_node)
return -ENOSPC;
- drm_mm_insert_helper(hole_node, node, size, alignment);
-
+ drm_mm_insert_helper(hole_node, node, size, alignment, color);
return 0;
}
+EXPORT_SYMBOL(drm_mm_insert_node_generic);
+
+int drm_mm_insert_node(struct drm_mm *mm, struct drm_mm_node *node,
+ unsigned long size, unsigned alignment)
+{
+ return drm_mm_insert_node_generic(mm, node, size, alignment, 0);
+}
+EXPORT_SYMBOL(drm_mm_insert_node);
static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node,
struct drm_mm_node *node,
unsigned long size, unsigned alignment,
+ unsigned long color,
unsigned long start, unsigned long end)
{
struct drm_mm *mm = hole_node->mm;
- unsigned long tmp = 0, wasted = 0;
unsigned long hole_start = drm_mm_hole_node_start(hole_node);
unsigned long hole_end = drm_mm_hole_node_end(hole_node);
+ unsigned long adj_start = hole_start;
+ unsigned long adj_end = hole_end;
- KASSERT(hole_node->hole_follows && !node->allocated, ("hole_node"));
+ BUG_ON(!hole_node->hole_follows || node->allocated);
- if (hole_start < start)
- wasted += start - hole_start;
- if (alignment)
- tmp = (hole_start + wasted) % alignment;
+ if (adj_start < start)
+ adj_start = start;
+ if (adj_end > end)
+ adj_end = end;
- if (tmp)
- wasted += alignment - tmp;
+ if (mm->color_adjust)
+ mm->color_adjust(hole_node, color, &adj_start, &adj_end);
+
+ if (alignment) {
+ unsigned tmp = adj_start % alignment;
+ if (tmp)
+ adj_start += alignment - tmp;
+ }
- if (!wasted) {
+ if (adj_start == hole_start) {
hole_node->hole_follows = 0;
- list_del_init(&hole_node->hole_stack);
+ list_del(&hole_node->hole_stack);
}
- node->start = hole_start + wasted;
+ node->start = adj_start;
node->size = size;
node->mm = mm;
+ node->color = color;
node->allocated = 1;
INIT_LIST_HEAD(&node->hole_stack);
list_add(&node->node_list, &hole_node->node_list);
- KASSERT(node->start + node->size <= hole_end, ("hole_end"));
- KASSERT(node->start + node->size <= end, ("end"));
+ BUG_ON(node->start + node->size > adj_end);
+ BUG_ON(node->start + node->size > end);
+ node->hole_follows = 0;
if (node->start + node->size < hole_end) {
list_add(&node->hole_stack, &mm->hole_stack);
node->hole_follows = 1;
- } else {
- node->hole_follows = 0;
}
}
struct drm_mm_node *drm_mm_get_block_range_generic(struct drm_mm_node *hole_node,
unsigned long size,
unsigned alignment,
+ unsigned long color,
unsigned long start,
unsigned long end,
int atomic)
@@ -233,47 +270,66 @@ struct drm_mm_node *drm_mm_get_block_range_generic(struct drm_mm_node *hole_node
if (unlikely(node == NULL))
return NULL;
- drm_mm_insert_helper_range(hole_node, node, size, alignment,
+ drm_mm_insert_helper_range(hole_node, node, size, alignment, color,
start, end);
return node;
}
+EXPORT_SYMBOL(drm_mm_get_block_range_generic);
-int drm_mm_insert_node_in_range(struct drm_mm *mm, struct drm_mm_node *node,
- unsigned long size, unsigned alignment,
- unsigned long start, unsigned long end)
+/**
+ * Search for free space and insert a preallocated memory node. Returns
+ * -ENOSPC if no suitable free area is available. This is for range
+ * restricted allocations. The preallocated memory node must be cleared.
+ */
+int drm_mm_insert_node_in_range_generic(struct drm_mm *mm, struct drm_mm_node *node,
+ unsigned long size, unsigned alignment, unsigned long color,
+ unsigned long start, unsigned long end)
{
struct drm_mm_node *hole_node;
- hole_node = drm_mm_search_free_in_range(mm, size, alignment,
- start, end, 0);
+ hole_node = drm_mm_search_free_in_range_generic(mm,
+ size, alignment, color,
+ start, end, 0);
if (!hole_node)
return -ENOSPC;
- drm_mm_insert_helper_range(hole_node, node, size, alignment,
+ drm_mm_insert_helper_range(hole_node, node,
+ size, alignment, color,
start, end);
-
return 0;
}
+EXPORT_SYMBOL(drm_mm_insert_node_in_range_generic);
+int drm_mm_insert_node_in_range(struct drm_mm *mm, struct drm_mm_node *node,
+ unsigned long size, unsigned alignment,
+ unsigned long start, unsigned long end)
+{
+ return drm_mm_insert_node_in_range_generic(mm, node, size, alignment, 0, start, end);
+}
+EXPORT_SYMBOL(drm_mm_insert_node_in_range);
+
+/**
+ * Remove a memory node from the allocator.
+ */
void drm_mm_remove_node(struct drm_mm_node *node)
{
struct drm_mm *mm = node->mm;
struct drm_mm_node *prev_node;
- KASSERT(!node->scanned_block && !node->scanned_prev_free
- && !node->scanned_next_free, ("node"));
+ BUG_ON(node->scanned_block || node->scanned_prev_free
+ || node->scanned_next_free);
prev_node =
list_entry(node->node_list.prev, struct drm_mm_node, node_list);
if (node->hole_follows) {
- KASSERT(drm_mm_hole_node_start(node)
- != drm_mm_hole_node_end(node), ("hole_follows"));
+ BUG_ON(drm_mm_hole_node_start(node)
+ == drm_mm_hole_node_end(node));
list_del(&node->hole_stack);
} else
- KASSERT(drm_mm_hole_node_start(node)
- == drm_mm_hole_node_end(node), ("!hole_follows"));
+ BUG_ON(drm_mm_hole_node_start(node)
+ != drm_mm_hole_node_end(node));
if (!prev_node->hole_follows) {
prev_node->hole_follows = 1;
@@ -284,14 +340,16 @@ void drm_mm_remove_node(struct drm_mm_node *node)
list_del(&node->node_list);
node->allocated = 0;
}
+EXPORT_SYMBOL(drm_mm_remove_node);
/*
- * Put a block. Merge with the previous and / or next block if they are free.
- * Otherwise add to the free stack.
+ * Remove a memory node from the allocator and free the allocated struct
+ * drm_mm_node. Only to be used on a struct drm_mm_node obtained by one of the
+ * drm_mm_get_block functions.
*/
-
void drm_mm_put_block(struct drm_mm_node *node)
{
+
struct drm_mm *mm = node->mm;
drm_mm_remove_node(node);
@@ -304,45 +362,50 @@ void drm_mm_put_block(struct drm_mm_node *node)
free(node, DRM_MEM_MM);
mtx_unlock(&mm->unused_lock);
}
+EXPORT_SYMBOL(drm_mm_put_block);
static int check_free_hole(unsigned long start, unsigned long end,
unsigned long size, unsigned alignment)
{
- unsigned wasted = 0;
-
if (end - start < size)
return 0;
if (alignment) {
unsigned tmp = start % alignment;
if (tmp)
- wasted = alignment - tmp;
- }
-
- if (end >= start + size + wasted) {
- return 1;
+ start += alignment - tmp;
}
- return 0;
+ return end >= start + size;
}
-
-struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm,
- unsigned long size,
- unsigned alignment, int best_match)
+struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm,
+ unsigned long size,
+ unsigned alignment,
+ unsigned long color,
+ bool best_match)
{
struct drm_mm_node *entry;
struct drm_mm_node *best;
unsigned long best_size;
+ BUG_ON(mm->scanned_blocks);
+
best = NULL;
best_size = ~0UL;
list_for_each_entry(entry, &mm->hole_stack, hole_stack) {
- KASSERT(entry->hole_follows, ("hole_follows"));
- if (!check_free_hole(drm_mm_hole_node_start(entry),
- drm_mm_hole_node_end(entry),
- size, alignment))
+ unsigned long adj_start = drm_mm_hole_node_start(entry);
+ unsigned long adj_end = drm_mm_hole_node_end(entry);
+
+ if (mm->color_adjust) {
+ mm->color_adjust(entry, color, &adj_start, &adj_end);
+ if (adj_end <= adj_start)
+ continue;
+ }
+
+ BUG_ON(!entry->hole_follows);
+ if (!check_free_hole(adj_start, adj_end, size, alignment))
continue;
if (!best_match)
@@ -356,19 +419,21 @@ struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm,
return best;
}
-
-struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm,
- unsigned long size,
- unsigned alignment,
- unsigned long start,
- unsigned long end,
- int best_match)
+EXPORT_SYMBOL(drm_mm_search_free_generic);
+
+struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm,
+ unsigned long size,
+ unsigned alignment,
+ unsigned long color,
+ unsigned long start,
+ unsigned long end,
+ bool best_match)
{
struct drm_mm_node *entry;
struct drm_mm_node *best;
unsigned long best_size;
- KASSERT(!mm->scanned_blocks, ("scanned"));
+ BUG_ON(mm->scanned_blocks);
best = NULL;
best_size = ~0UL;
@@ -379,7 +444,14 @@ struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm,
unsigned long adj_end = drm_mm_hole_node_end(entry) > end ?
end : drm_mm_hole_node_end(entry);
- KASSERT(entry->hole_follows, ("hole_follows"));
+ BUG_ON(!entry->hole_follows);
+
+ if (mm->color_adjust) {
+ mm->color_adjust(entry, color, &adj_start, &adj_end);
+ if (adj_end <= adj_start)
+ continue;
+ }
+
if (!check_free_hole(adj_start, adj_end, size, alignment))
continue;
@@ -394,7 +466,11 @@ struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm,
return best;
}
+EXPORT_SYMBOL(drm_mm_search_free_in_range_generic);
+/**
+ * Moves an allocation. To be used with embedded struct drm_mm_node.
+ */
void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new)
{
list_replace(&old->node_list, &new->node_list);
@@ -403,50 +479,83 @@ void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new)
new->mm = old->mm;
new->start = old->start;
new->size = old->size;
+ new->color = old->color;
old->allocated = 0;
new->allocated = 1;
}
+EXPORT_SYMBOL(drm_mm_replace_node);
-void drm_mm_init_scan(struct drm_mm *mm, unsigned long size,
- unsigned alignment)
+/**
+ * Initializa lru scanning.
+ *
+ * This simply sets up the scanning routines with the parameters for the desired
+ * hole.
+ *
+ * Warning: As long as the scan list is non-empty, no other operations than
+ * adding/removing nodes to/from the scan list are allowed.
+ */
+void drm_mm_init_scan(struct drm_mm *mm,
+ unsigned long size,
+ unsigned alignment,
+ unsigned long color)
{
+ mm->scan_color = color;
mm->scan_alignment = alignment;
mm->scan_size = size;
mm->scanned_blocks = 0;
mm->scan_hit_start = 0;
- mm->scan_hit_size = 0;
+ mm->scan_hit_end = 0;
mm->scan_check_range = 0;
mm->prev_scanned_node = NULL;
}
+EXPORT_SYMBOL(drm_mm_init_scan);
-void drm_mm_init_scan_with_range(struct drm_mm *mm, unsigned long size,
+/**
+ * Initializa lru scanning.
+ *
+ * This simply sets up the scanning routines with the parameters for the desired
+ * hole. This version is for range-restricted scans.
+ *
+ * Warning: As long as the scan list is non-empty, no other operations than
+ * adding/removing nodes to/from the scan list are allowed.
+ */
+void drm_mm_init_scan_with_range(struct drm_mm *mm,
+ unsigned long size,
unsigned alignment,
+ unsigned long color,
unsigned long start,
unsigned long end)
{
+ mm->scan_color = color;
mm->scan_alignment = alignment;
mm->scan_size = size;
mm->scanned_blocks = 0;
mm->scan_hit_start = 0;
- mm->scan_hit_size = 0;
+ mm->scan_hit_end = 0;
mm->scan_start = start;
mm->scan_end = end;
mm->scan_check_range = 1;
mm->prev_scanned_node = NULL;
}
+EXPORT_SYMBOL(drm_mm_init_scan_with_range);
+/**
+ * Add a node to the scan list that might be freed to make space for the desired
+ * hole.
+ *
+ * Returns non-zero, if a hole has been found, zero otherwise.
+ */
int drm_mm_scan_add_block(struct drm_mm_node *node)
{
struct drm_mm *mm = node->mm;
struct drm_mm_node *prev_node;
unsigned long hole_start, hole_end;
- unsigned long adj_start;
- unsigned long adj_end;
+ unsigned long adj_start, adj_end;
mm->scanned_blocks++;
- KASSERT(!node->scanned_block, ("node->scanned_block"));
+ BUG_ON(node->scanned_block);
node->scanned_block = 1;
prev_node = list_entry(node->node_list.prev, struct drm_mm_node,
@@ -459,29 +568,45 @@ int drm_mm_scan_add_block(struct drm_mm_node *node)
node->node_list.next = &mm->prev_scanned_node->node_list;
mm->prev_scanned_node = node;
- hole_start = drm_mm_hole_node_start(prev_node);
- hole_end = drm_mm_hole_node_end(prev_node);
+ adj_start = hole_start = drm_mm_hole_node_start(prev_node);
+ adj_end = hole_end = drm_mm_hole_node_end(prev_node);
+
if (mm->scan_check_range) {
- adj_start = hole_start < mm->scan_start ?
- mm->scan_start : hole_start;
- adj_end = hole_end > mm->scan_end ?
- mm->scan_end : hole_end;
- } else {
- adj_start = hole_start;
- adj_end = hole_end;
+ if (adj_start < mm->scan_start)
+ adj_start = mm->scan_start;
+ if (adj_end > mm->scan_end)
+ adj_end = mm->scan_end;
}
- if (check_free_hole(adj_start , adj_end,
+ if (mm->color_adjust)
+ mm->color_adjust(prev_node, mm->scan_color,
+ &adj_start, &adj_end);
+
+ if (check_free_hole(adj_start, adj_end,
mm->scan_size, mm->scan_alignment)) {
mm->scan_hit_start = hole_start;
- mm->scan_hit_size = hole_end;
-
+ mm->scan_hit_end = hole_end;
return 1;
}
return 0;
}
+EXPORT_SYMBOL(drm_mm_scan_add_block);
+/**
+ * Remove a node from the scan list.
+ *
+ * Nodes _must_ be removed in the exact same order from the scan list as they
+ * have been added, otherwise the internal state of the memory manager will be
+ * corrupted.
+ *
+ * When the scan list is empty, the selected memory nodes can be freed. An
+ * immediately following drm_mm_search_free with best_match = 0 will then return
+ * the just freed block (because its at the top of the free_stack list).
+ *
+ * Returns one if this block should be evicted, zero otherwise. Will always
+ * return zero when no hole has been found.
+ */
int drm_mm_scan_remove_block(struct drm_mm_node *node)
{
struct drm_mm *mm = node->mm;
@@ -489,27 +614,19 @@ int drm_mm_scan_remove_block(struct drm_mm_node *node)
mm->scanned_blocks--;
- KASSERT(node->scanned_block, ("scanned_block"));
+ BUG_ON(!node->scanned_block);
node->scanned_block = 0;
prev_node = list_entry(node->node_list.prev, struct drm_mm_node,
node_list);
prev_node->hole_follows = node->scanned_preceeds_hole;
- INIT_LIST_HEAD(&node->node_list);
list_add(&node->node_list, &prev_node->node_list);
- /* Only need to check for containement because start&size for the
- * complete resulting free block (not just the desired part) is
- * stored. */
- if (node->start >= mm->scan_hit_start &&
- node->start + node->size
- <= mm->scan_hit_start + mm->scan_hit_size) {
- return 1;
- }
-
- return 0;
+ return (drm_mm_hole_node_end(node) > mm->scan_hit_start &&
+ node->start < mm->scan_hit_end);
}
+EXPORT_SYMBOL(drm_mm_scan_remove_block);
int drm_mm_clean(struct drm_mm * mm)
{
@@ -517,6 +634,7 @@ int drm_mm_clean(struct drm_mm * mm)
return (head->next->next == head);
}
+EXPORT_SYMBOL(drm_mm_clean);
int drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size)
{
@@ -526,6 +644,7 @@ int drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size)
mm->scanned_blocks = 0;
mtx_init(&mm->unused_lock, "drm_unused", NULL, MTX_DEF);
+ /* Clever trick to avoid a special case in the free hole tracking. */
INIT_LIST_HEAD(&mm->head_node.node_list);
INIT_LIST_HEAD(&mm->head_node.hole_stack);
mm->head_node.hole_follows = 1;
@@ -537,8 +656,11 @@ int drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size)
mm->head_node.size = start - mm->head_node.start;
list_add_tail(&mm->head_node.hole_stack, &mm->hole_stack);
+ mm->color_adjust = NULL;
+
return 0;
}
+EXPORT_SYMBOL(drm_mm_init);
void drm_mm_takedown(struct drm_mm * mm)
{
@@ -557,10 +679,9 @@ void drm_mm_takedown(struct drm_mm * mm)
}
mtx_unlock(&mm->unused_lock);
- mtx_destroy(&mm->unused_lock);
-
- KASSERT(mm->num_unused == 0, ("num_unused != 0"));
+ BUG_ON(mm->num_unused != 0);
}
+EXPORT_SYMBOL(drm_mm_takedown);
void drm_mm_debug_table(struct drm_mm *mm, const char *prefix)
{
@@ -572,13 +693,13 @@ void drm_mm_debug_table(struct drm_mm *mm, const char *prefix)
hole_end = drm_mm_hole_node_end(&mm->head_node);
hole_size = hole_end - hole_start;
if (hole_size)
- printf("%s 0x%08lx-0x%08lx: %8lu: free\n",
+ printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8lu: free\n",
prefix, hole_start, hole_end,
hole_size);
total_free += hole_size;
drm_mm_for_each_node(entry, mm) {
- printf("%s 0x%08lx-0x%08lx: %8lu: used\n",
+ printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8lu: used\n",
prefix, entry->start, entry->start + entry->size,
entry->size);
total_used += entry->size;
@@ -587,7 +708,7 @@ void drm_mm_debug_table(struct drm_mm *mm, const char *prefix)
hole_start = drm_mm_hole_node_start(entry);
hole_end = drm_mm_hole_node_end(entry);
hole_size = hole_end - hole_start;
- printf("%s 0x%08lx-0x%08lx: %8lu: free\n",
+ printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8lu: free\n",
prefix, hole_start, hole_end,
hole_size);
total_free += hole_size;
@@ -595,6 +716,7 @@ void drm_mm_debug_table(struct drm_mm *mm, const char *prefix)
}
total = total_free + total_used;
- printf("%s total: %lu, used %lu free %lu\n", prefix, total,
+ printk(KERN_DEBUG "%s total: %lu, used %lu free %lu\n", prefix, total,
total_used, total_free);
}
+EXPORT_SYMBOL(drm_mm_debug_table);
diff --git a/sys/dev/drm2/drm_mm.h b/sys/dev/drm2/drm_mm.h
index 7150e24..1bbc003 100644
--- a/sys/dev/drm2/drm_mm.h
+++ b/sys/dev/drm2/drm_mm.h
@@ -25,18 +25,20 @@
*
*
**************************************************************************/
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
/*
* Authors:
* Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
#ifndef _DRM_MM_H_
#define _DRM_MM_H_
+/*
+ * Generic range manager structs
+ */
#include <dev/drm2/drm_linux_list.h>
struct drm_mm_node {
@@ -48,27 +50,34 @@ struct drm_mm_node {
unsigned scanned_next_free : 1;
unsigned scanned_preceeds_hole : 1;
unsigned allocated : 1;
+ unsigned long color;
unsigned long start;
unsigned long size;
struct drm_mm *mm;
- void *private;
};
struct drm_mm {
+ /* List of all memory nodes that immediately precede a free hole. */
struct list_head hole_stack;
+ /* head_node.node_list is the list of all memory nodes, ordered
+ * according to the (increasing) start address of the memory node. */
struct drm_mm_node head_node;
struct list_head unused_nodes;
int num_unused;
struct mtx unused_lock;
unsigned int scan_check_range : 1;
unsigned scan_alignment;
+ unsigned long scan_color;
unsigned long scan_size;
unsigned long scan_hit_start;
- unsigned scan_hit_size;
+ unsigned long scan_hit_end;
unsigned scanned_blocks;
unsigned long scan_start;
unsigned long scan_end;
struct drm_mm_node *prev_scanned_node;
+
+ void (*color_adjust)(struct drm_mm_node *node, unsigned long color,
+ unsigned long *start, unsigned long *end);
};
static inline bool drm_mm_node_allocated(struct drm_mm_node *node)
@@ -78,7 +87,7 @@ static inline bool drm_mm_node_allocated(struct drm_mm_node *node)
static inline bool drm_mm_initialized(struct drm_mm *mm)
{
- return (mm->hole_stack.next != NULL);
+ return mm->hole_stack.next;
}
#define drm_mm_for_each_node(entry, mm) list_for_each_entry(entry, \
&(mm)->head_node.node_list, \
@@ -89,19 +98,20 @@ static inline bool drm_mm_initialized(struct drm_mm *mm)
struct drm_mm_node, node_list) : NULL; \
entry != NULL; entry = next, \
next = entry ? list_entry(entry->node_list.next, \
- struct drm_mm_node, node_list) : NULL)
-
+ struct drm_mm_node, node_list) : NULL) \
/*
* Basic range manager support (drm_mm.c)
*/
extern struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *node,
unsigned long size,
unsigned alignment,
+ unsigned long color,
int atomic);
extern struct drm_mm_node *drm_mm_get_block_range_generic(
struct drm_mm_node *node,
unsigned long size,
unsigned alignment,
+ unsigned long color,
unsigned long start,
unsigned long end,
int atomic);
@@ -109,13 +119,13 @@ static inline struct drm_mm_node *drm_mm_get_block(struct drm_mm_node *parent,
unsigned long size,
unsigned alignment)
{
- return drm_mm_get_block_generic(parent, size, alignment, 0);
+ return drm_mm_get_block_generic(parent, size, alignment, 0, 0);
}
static inline struct drm_mm_node *drm_mm_get_block_atomic(struct drm_mm_node *parent,
unsigned long size,
unsigned alignment)
{
- return drm_mm_get_block_generic(parent, size, alignment, 1);
+ return drm_mm_get_block_generic(parent, size, alignment, 0, 1);
}
static inline struct drm_mm_node *drm_mm_get_block_range(
struct drm_mm_node *parent,
@@ -124,8 +134,19 @@ static inline struct drm_mm_node *drm_mm_get_block_range(
unsigned long start,
unsigned long end)
{
- return drm_mm_get_block_range_generic(parent, size, alignment,
- start, end, 0);
+ return drm_mm_get_block_range_generic(parent, size, alignment, 0,
+ start, end, 0);
+}
+static inline struct drm_mm_node *drm_mm_get_color_block_range(
+ struct drm_mm_node *parent,
+ unsigned long size,
+ unsigned alignment,
+ unsigned long color,
+ unsigned long start,
+ unsigned long end)
+{
+ return drm_mm_get_block_range_generic(parent, size, alignment, color,
+ start, end, 0);
}
static inline struct drm_mm_node *drm_mm_get_block_atomic_range(
struct drm_mm_node *parent,
@@ -134,38 +155,91 @@ static inline struct drm_mm_node *drm_mm_get_block_atomic_range(
unsigned long start,
unsigned long end)
{
- return drm_mm_get_block_range_generic(parent, size, alignment,
+ return drm_mm_get_block_range_generic(parent, size, alignment, 0,
start, end, 1);
}
-extern int drm_mm_insert_node(struct drm_mm *mm, struct drm_mm_node *node,
- unsigned long size, unsigned alignment);
+
+extern int drm_mm_insert_node(struct drm_mm *mm,
+ struct drm_mm_node *node,
+ unsigned long size,
+ unsigned alignment);
extern int drm_mm_insert_node_in_range(struct drm_mm *mm,
struct drm_mm_node *node,
- unsigned long size, unsigned alignment,
- unsigned long start, unsigned long end);
+ unsigned long size,
+ unsigned alignment,
+ unsigned long start,
+ unsigned long end);
+extern int drm_mm_insert_node_generic(struct drm_mm *mm,
+ struct drm_mm_node *node,
+ unsigned long size,
+ unsigned alignment,
+ unsigned long color);
+extern int drm_mm_insert_node_in_range_generic(struct drm_mm *mm,
+ struct drm_mm_node *node,
+ unsigned long size,
+ unsigned alignment,
+ unsigned long color,
+ unsigned long start,
+ unsigned long end);
extern void drm_mm_put_block(struct drm_mm_node *cur);
extern void drm_mm_remove_node(struct drm_mm_node *node);
extern void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new);
-extern struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm,
- unsigned long size,
- unsigned alignment,
- int best_match);
-extern struct drm_mm_node *drm_mm_search_free_in_range(
+extern struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm,
+ unsigned long size,
+ unsigned alignment,
+ unsigned long color,
+ bool best_match);
+extern struct drm_mm_node *drm_mm_search_free_in_range_generic(
+ const struct drm_mm *mm,
+ unsigned long size,
+ unsigned alignment,
+ unsigned long color,
+ unsigned long start,
+ unsigned long end,
+ bool best_match);
+static inline struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm,
+ unsigned long size,
+ unsigned alignment,
+ bool best_match)
+{
+ return drm_mm_search_free_generic(mm,size, alignment, 0, best_match);
+}
+static inline struct drm_mm_node *drm_mm_search_free_in_range(
const struct drm_mm *mm,
unsigned long size,
unsigned alignment,
unsigned long start,
unsigned long end,
- int best_match);
-extern int drm_mm_init(struct drm_mm *mm, unsigned long start,
+ bool best_match)
+{
+ return drm_mm_search_free_in_range_generic(mm, size, alignment, 0,
+ start, end, best_match);
+}
+static inline struct drm_mm_node *drm_mm_search_free_color(const struct drm_mm *mm,
+ unsigned long size,
+ unsigned alignment,
+ unsigned long color,
+ bool best_match)
+{
+ return drm_mm_search_free_generic(mm,size, alignment, color, best_match);
+}
+static inline struct drm_mm_node *drm_mm_search_free_in_range_color(
+ const struct drm_mm *mm,
+ unsigned long size,
+ unsigned alignment,
+ unsigned long color,
+ unsigned long start,
+ unsigned long end,
+ bool best_match)
+{
+ return drm_mm_search_free_in_range_generic(mm, size, alignment, color,
+ start, end, best_match);
+}
+extern int drm_mm_init(struct drm_mm *mm,
+ unsigned long start,
unsigned long size);
extern void drm_mm_takedown(struct drm_mm *mm);
extern int drm_mm_clean(struct drm_mm *mm);
-extern unsigned long drm_mm_tail_space(struct drm_mm *mm);
-extern int drm_mm_remove_space_from_tail(struct drm_mm *mm,
- unsigned long size);
-extern int drm_mm_add_space_to_tail(struct drm_mm *mm,
- unsigned long size, int atomic);
extern int drm_mm_pre_get(struct drm_mm *mm);
static inline struct drm_mm *drm_get_mm(struct drm_mm_node *block)
@@ -173,15 +247,19 @@ static inline struct drm_mm *drm_get_mm(struct drm_mm_node *block)
return block->mm;
}
-void drm_mm_init_scan(struct drm_mm *mm, unsigned long size,
- unsigned alignment);
-void drm_mm_init_scan_with_range(struct drm_mm *mm, unsigned long size,
+void drm_mm_init_scan(struct drm_mm *mm,
+ unsigned long size,
+ unsigned alignment,
+ unsigned long color);
+void drm_mm_init_scan_with_range(struct drm_mm *mm,
+ unsigned long size,
unsigned alignment,
+ unsigned long color,
unsigned long start,
unsigned long end);
int drm_mm_scan_add_block(struct drm_mm_node *node);
int drm_mm_scan_remove_block(struct drm_mm_node *node);
-void drm_mm_debug_table(struct drm_mm *mm, const char *prefix);
+extern void drm_mm_debug_table(struct drm_mm *mm, const char *prefix);
#endif
diff --git a/sys/dev/drm2/drm_mode.h b/sys/dev/drm2/drm_mode.h
index 79cf933..3950625 100644
--- a/sys/dev/drm2/drm_mode.h
+++ b/sys/dev/drm2/drm_mode.h
@@ -29,6 +29,8 @@
#ifndef _DRM_MODE_H
#define _DRM_MODE_H
+#include <dev/drm2/drm_os_freebsd.h>
+
#define DRM_DISPLAY_INFO_LEN 32
#define DRM_CONNECTOR_NAME_LEN 32
#define DRM_DISPLAY_MODE_LEN 32
@@ -84,41 +86,41 @@
#define DRM_MODE_DIRTY_ANNOTATE 2
struct drm_mode_modeinfo {
- uint32_t clock;
- uint16_t hdisplay, hsync_start, hsync_end, htotal, hskew;
- uint16_t vdisplay, vsync_start, vsync_end, vtotal, vscan;
+ __u32 clock;
+ __u16 hdisplay, hsync_start, hsync_end, htotal, hskew;
+ __u16 vdisplay, vsync_start, vsync_end, vtotal, vscan;
- uint32_t vrefresh;
+ __u32 vrefresh;
- uint32_t flags;
- uint32_t type;
+ __u32 flags;
+ __u32 type;
char name[DRM_DISPLAY_MODE_LEN];
};
struct drm_mode_card_res {
- uint64_t fb_id_ptr;
- uint64_t crtc_id_ptr;
- uint64_t connector_id_ptr;
- uint64_t encoder_id_ptr;
- uint32_t count_fbs;
- uint32_t count_crtcs;
- uint32_t count_connectors;
- uint32_t count_encoders;
- uint32_t min_width, max_width;
- uint32_t min_height, max_height;
+ __u64 fb_id_ptr;
+ __u64 crtc_id_ptr;
+ __u64 connector_id_ptr;
+ __u64 encoder_id_ptr;
+ __u32 count_fbs;
+ __u32 count_crtcs;
+ __u32 count_connectors;
+ __u32 count_encoders;
+ __u32 min_width, max_width;
+ __u32 min_height, max_height;
};
struct drm_mode_crtc {
- uint64_t set_connectors_ptr;
- uint32_t count_connectors;
+ __u64 set_connectors_ptr;
+ __u32 count_connectors;
- uint32_t crtc_id; /**< Id */
- uint32_t fb_id; /**< Id of framebuffer */
+ __u32 crtc_id; /**< Id */
+ __u32 fb_id; /**< Id of framebuffer */
- uint32_t x, y; /**< Position on the frameuffer */
+ __u32 x, y; /**< Position on the frameuffer */
- uint32_t gamma_size;
- uint32_t mode_valid;
+ __u32 gamma_size;
+ __u32 mode_valid;
struct drm_mode_modeinfo mode;
};
@@ -127,36 +129,36 @@ struct drm_mode_crtc {
/* Planes blend with or override other bits on the CRTC */
struct drm_mode_set_plane {
- uint32_t plane_id;
- uint32_t crtc_id;
- uint32_t fb_id; /* fb object contains surface format type */
- uint32_t flags; /* see above flags */
+ __u32 plane_id;
+ __u32 crtc_id;
+ __u32 fb_id; /* fb object contains surface format type */
+ __u32 flags; /* see above flags */
/* Signed dest location allows it to be partially off screen */
- int32_t crtc_x, crtc_y;
- uint32_t crtc_w, crtc_h;
+ __s32 crtc_x, crtc_y;
+ __u32 crtc_w, crtc_h;
/* Source values are 16.16 fixed point */
- uint32_t src_x, src_y;
- uint32_t src_h, src_w;
+ __u32 src_x, src_y;
+ __u32 src_h, src_w;
};
struct drm_mode_get_plane {
- uint32_t plane_id;
+ __u32 plane_id;
- uint32_t crtc_id;
- uint32_t fb_id;
+ __u32 crtc_id;
+ __u32 fb_id;
- uint32_t possible_crtcs;
- uint32_t gamma_size;
+ __u32 possible_crtcs;
+ __u32 gamma_size;
- uint32_t count_format_types;
- uint64_t format_type_ptr;
+ __u32 count_format_types;
+ __u64 format_type_ptr;
};
struct drm_mode_get_plane_res {
- uint64_t plane_id_ptr;
- uint32_t count_planes;
+ __u64 plane_id_ptr;
+ __u32 count_planes;
};
#define DRM_MODE_ENCODER_NONE 0
@@ -164,15 +166,16 @@ struct drm_mode_get_plane_res {
#define DRM_MODE_ENCODER_TMDS 2
#define DRM_MODE_ENCODER_LVDS 3
#define DRM_MODE_ENCODER_TVDAC 4
+#define DRM_MODE_ENCODER_VIRTUAL 5
struct drm_mode_get_encoder {
- uint32_t encoder_id;
- uint32_t encoder_type;
+ __u32 encoder_id;
+ __u32 encoder_type;
- uint32_t crtc_id; /**< Id of crtc */
+ __u32 crtc_id; /**< Id of crtc */
- uint32_t possible_crtcs;
- uint32_t possible_clones;
+ __u32 possible_crtcs;
+ __u32 possible_clones;
};
/* This is for connectors with multiple signal types. */
@@ -201,26 +204,27 @@ struct drm_mode_get_encoder {
#define DRM_MODE_CONNECTOR_HDMIB 12
#define DRM_MODE_CONNECTOR_TV 13
#define DRM_MODE_CONNECTOR_eDP 14
+#define DRM_MODE_CONNECTOR_VIRTUAL 15
struct drm_mode_get_connector {
- uint64_t encoders_ptr;
- uint64_t modes_ptr;
- uint64_t props_ptr;
- uint64_t prop_values_ptr;
+ __u64 encoders_ptr;
+ __u64 modes_ptr;
+ __u64 props_ptr;
+ __u64 prop_values_ptr;
- uint32_t count_modes;
- uint32_t count_props;
- uint32_t count_encoders;
+ __u32 count_modes;
+ __u32 count_props;
+ __u32 count_encoders;
- uint32_t encoder_id; /**< Current Encoder */
- uint32_t connector_id; /**< Id */
- uint32_t connector_type;
- uint32_t connector_type_id;
+ __u32 encoder_id; /**< Current Encoder */
+ __u32 connector_id; /**< Id */
+ __u32 connector_type;
+ __u32 connector_type_id;
- uint32_t connection;
- uint32_t mm_width, mm_height; /**< HxW in millimeters */
- uint32_t subpixel;
+ __u32 connection;
+ __u32 mm_width, mm_height; /**< HxW in millimeters */
+ __u32 subpixel;
};
#define DRM_MODE_PROP_PENDING (1<<0)
@@ -231,66 +235,66 @@ struct drm_mode_get_connector {
#define DRM_MODE_PROP_BITMASK (1<<5) /* bitmask of enumerated types */
struct drm_mode_property_enum {
- uint64_t value;
+ __u64 value;
char name[DRM_PROP_NAME_LEN];
};
struct drm_mode_get_property {
- uint64_t values_ptr; /* values and blob lengths */
- uint64_t enum_blob_ptr; /* enum and blob id ptrs */
+ __u64 values_ptr; /* values and blob lengths */
+ __u64 enum_blob_ptr; /* enum and blob id ptrs */
- uint32_t prop_id;
- uint32_t flags;
+ __u32 prop_id;
+ __u32 flags;
char name[DRM_PROP_NAME_LEN];
- uint32_t count_values;
- uint32_t count_enum_blobs;
+ __u32 count_values;
+ __u32 count_enum_blobs;
};
struct drm_mode_connector_set_property {
- uint64_t value;
- uint32_t prop_id;
- uint32_t connector_id;
+ __u64 value;
+ __u32 prop_id;
+ __u32 connector_id;
};
struct drm_mode_obj_get_properties {
- uint64_t props_ptr;
- uint64_t prop_values_ptr;
- uint32_t count_props;
- uint32_t obj_id;
- uint32_t obj_type;
+ __u64 props_ptr;
+ __u64 prop_values_ptr;
+ __u32 count_props;
+ __u32 obj_id;
+ __u32 obj_type;
};
struct drm_mode_obj_set_property {
- uint64_t value;
- uint32_t prop_id;
- uint32_t obj_id;
- uint32_t obj_type;
+ __u64 value;
+ __u32 prop_id;
+ __u32 obj_id;
+ __u32 obj_type;
};
struct drm_mode_get_blob {
- uint32_t blob_id;
- uint32_t length;
- uint64_t data;
+ __u32 blob_id;
+ __u32 length;
+ __u64 data;
};
struct drm_mode_fb_cmd {
- uint32_t fb_id;
- uint32_t width, height;
- uint32_t pitch;
- uint32_t bpp;
- uint32_t depth;
+ __u32 fb_id;
+ __u32 width, height;
+ __u32 pitch;
+ __u32 bpp;
+ __u32 depth;
/* driver specific handle */
- uint32_t handle;
+ __u32 handle;
};
-#define DRM_MODE_FB_INTERLACED (1<<0 /* for interlaced framebuffers */
+#define DRM_MODE_FB_INTERLACED (1<<0) /* for interlaced framebuffers */
struct drm_mode_fb_cmd2 {
- uint32_t fb_id;
- uint32_t width, height;
- uint32_t pixel_format; /* fourcc code from drm_fourcc.h */
- uint32_t flags; /* see above flags */
+ __u32 fb_id;
+ __u32 width, height;
+ __u32 pixel_format; /* fourcc code from drm_fourcc.h */
+ __u32 flags; /* see above flags */
/*
* In case of planar formats, this ioctl allows up to 4
@@ -306,9 +310,9 @@ struct drm_mode_fb_cmd2 {
* offeset[1]. Note that offset[0] will generally
* be 0.
*/
- uint32_t handles[4];
- uint32_t pitches[4]; /* pitch for each plane */
- uint32_t offsets[4]; /* offset of each plane */
+ __u32 handles[4];
+ __u32 pitches[4]; /* pitch for each plane */
+ __u32 offsets[4]; /* offset of each plane */
};
#define DRM_MODE_FB_DIRTY_ANNOTATE_COPY 0x01
@@ -345,23 +349,24 @@ struct drm_mode_fb_cmd2 {
*/
struct drm_mode_fb_dirty_cmd {
- uint32_t fb_id;
- uint32_t flags;
- uint32_t color;
- uint32_t num_clips;
- uint64_t clips_ptr;
+ __u32 fb_id;
+ __u32 flags;
+ __u32 color;
+ __u32 num_clips;
+ __u64 clips_ptr;
};
struct drm_mode_mode_cmd {
- uint32_t connector_id;
+ __u32 connector_id;
struct drm_mode_modeinfo mode;
};
-#define DRM_MODE_CURSOR_BO (1<<0)
-#define DRM_MODE_CURSOR_MOVE (1<<1)
+#define DRM_MODE_CURSOR_BO 0x01
+#define DRM_MODE_CURSOR_MOVE 0x02
+#define DRM_MODE_CURSOR_FLAGS 0x03
/*
- * depending on the value in flags diffrent members are used.
+ * depending on the value in flags different members are used.
*
* CURSOR_BO uses
* crtc
@@ -375,24 +380,24 @@ struct drm_mode_mode_cmd {
* y
*/
struct drm_mode_cursor {
- uint32_t flags;
- uint32_t crtc_id;
- int32_t x;
- int32_t y;
- uint32_t width;
- uint32_t height;
+ __u32 flags;
+ __u32 crtc_id;
+ __s32 x;
+ __s32 y;
+ __u32 width;
+ __u32 height;
/* driver specific handle */
- uint32_t handle;
+ __u32 handle;
};
struct drm_mode_crtc_lut {
- uint32_t crtc_id;
- uint32_t gamma_size;
+ __u32 crtc_id;
+ __u32 gamma_size;
/* pointers to arrays */
- uint64_t red;
- uint64_t green;
- uint64_t blue;
+ __u64 red;
+ __u64 green;
+ __u64 blue;
};
#define DRM_MODE_PAGE_FLIP_EVENT 0x01
@@ -421,11 +426,11 @@ struct drm_mode_crtc_lut {
*/
struct drm_mode_crtc_page_flip {
- uint32_t crtc_id;
- uint32_t fb_id;
- uint32_t flags;
- uint32_t reserved;
- uint64_t user_data;
+ __u32 crtc_id;
+ __u32 fb_id;
+ __u32 flags;
+ __u32 reserved;
+ __u64 user_data;
};
/* create a dumb scanout buffer */
@@ -443,14 +448,14 @@ struct drm_mode_create_dumb {
/* set up for mmap of a dumb scanout buffer */
struct drm_mode_map_dumb {
/** Handle for the object being mapped. */
- uint32_t handle;
- uint32_t pad;
+ __u32 handle;
+ __u32 pad;
/**
* Fake offset to use for subsequent mmap call
*
* This is a fixed-size type for 32/64 compatibility.
*/
- uint64_t offset;
+ __u64 offset;
};
struct drm_mode_destroy_dumb {
diff --git a/sys/dev/drm2/drm_modes.c b/sys/dev/drm2/drm_modes.c
index a2dbbdd..5467be5 100644
--- a/sys/dev/drm2/drm_modes.c
+++ b/sys/dev/drm2/drm_modes.c
@@ -34,11 +34,8 @@
__FBSDID("$FreeBSD$");
#include <dev/drm2/drmP.h>
-#include <dev/drm2/drm.h>
#include <dev/drm2/drm_crtc.h>
-#define KHZ2PICOS(a) (1000000000UL/(a))
-
/**
* drm_mode_debug_printmodeline - debug print a mode
* @dev: DRM device
@@ -49,7 +46,7 @@ __FBSDID("$FreeBSD$");
*
* Describe @mode using DRM_DEBUG.
*/
-void drm_mode_debug_printmodeline(struct drm_display_mode *mode)
+void drm_mode_debug_printmodeline(const struct drm_display_mode *mode)
{
DRM_DEBUG_KMS("Modeline %d:\"%s\" %d %d %d %d %d %d %d %d %d %d "
"0x%x 0x%x\n",
@@ -59,6 +56,7 @@ void drm_mode_debug_printmodeline(struct drm_display_mode *mode)
mode->vdisplay, mode->vsync_start,
mode->vsync_end, mode->vtotal, mode->type, mode->flags);
}
+EXPORT_SYMBOL(drm_mode_debug_printmodeline);
/**
* drm_cvt_mode -create a modeline based on CVT algorithm
@@ -278,6 +276,7 @@ struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay,
return drm_mode;
}
+EXPORT_SYMBOL(drm_cvt_mode);
/**
* drm_gtf_mode_complex - create the modeline based on full GTF algorithm
@@ -463,6 +462,7 @@ drm_gtf_mode_complex(struct drm_device *dev, int hdisplay, int vdisplay,
return drm_mode;
}
+EXPORT_SYMBOL(drm_gtf_mode_complex);
/**
* drm_gtf_mode - create the modeline based on GTF algorithm
@@ -502,6 +502,7 @@ drm_gtf_mode(struct drm_device *dev, int hdisplay, int vdisplay, int vrefresh,
return drm_gtf_mode_complex(dev, hdisplay, vdisplay, vrefresh, lace,
margins, 600, 40 * 2, 128, 20 * 2);
}
+EXPORT_SYMBOL(drm_gtf_mode);
/**
* drm_mode_set_name - set the name on a mode
@@ -520,6 +521,7 @@ void drm_mode_set_name(struct drm_display_mode *mode)
mode->hdisplay, mode->vdisplay,
interlaced ? "i" : "");
}
+EXPORT_SYMBOL(drm_mode_set_name);
/**
* drm_mode_list_concat - move modes from one list to another
@@ -540,6 +542,7 @@ void drm_mode_list_concat(struct list_head *head, struct list_head *new)
list_move_tail(entry, new);
}
}
+EXPORT_SYMBOL(drm_mode_list_concat);
/**
* drm_mode_width - get the width of a mode
@@ -555,11 +558,12 @@ void drm_mode_list_concat(struct list_head *head, struct list_head *new)
* RETURNS:
* @mode->hdisplay
*/
-int drm_mode_width(struct drm_display_mode *mode)
+int drm_mode_width(const struct drm_display_mode *mode)
{
return mode->hdisplay;
}
+EXPORT_SYMBOL(drm_mode_width);
/**
* drm_mode_height - get the height of a mode
@@ -575,10 +579,11 @@ int drm_mode_width(struct drm_display_mode *mode)
* RETURNS:
* @mode->vdisplay
*/
-int drm_mode_height(struct drm_display_mode *mode)
+int drm_mode_height(const struct drm_display_mode *mode)
{
return mode->vdisplay;
}
+EXPORT_SYMBOL(drm_mode_height);
/** drm_mode_hsync - get the hsync of a mode
* @mode: mode
@@ -604,6 +609,7 @@ int drm_mode_hsync(const struct drm_display_mode *mode)
return calc_val;
}
+EXPORT_SYMBOL(drm_mode_hsync);
/**
* drm_mode_vrefresh - get the vrefresh of a mode
@@ -645,6 +651,7 @@ int drm_mode_vrefresh(const struct drm_display_mode *mode)
}
return refresh;
}
+EXPORT_SYMBOL(drm_mode_vrefresh);
/**
* drm_mode_set_crtcinfo - set CRTC modesetting parameters
@@ -678,8 +685,6 @@ void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags)
p->crtc_vsync_end /= 2;
p->crtc_vtotal /= 2;
}
-
- p->crtc_vtotal |= 1;
}
if (p->flags & DRM_MODE_FLAG_DBLSCAN) {
@@ -700,11 +705,30 @@ void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags)
p->crtc_vblank_end = max(p->crtc_vsync_end, p->crtc_vtotal);
p->crtc_hblank_start = min(p->crtc_hsync_start, p->crtc_hdisplay);
p->crtc_hblank_end = max(p->crtc_hsync_end, p->crtc_htotal);
-
- p->crtc_hadjusted = false;
- p->crtc_vadjusted = false;
}
+EXPORT_SYMBOL(drm_mode_set_crtcinfo);
+
+
+/**
+ * drm_mode_copy - copy the mode
+ * @dst: mode to overwrite
+ * @src: mode to copy
+ *
+ * LOCKING:
+ * None.
+ *
+ * Copy an existing mode into another mode, preserving the object id
+ * of the destination mode.
+ */
+void drm_mode_copy(struct drm_display_mode *dst, const struct drm_display_mode *src)
+{
+ int id = dst->base.id;
+ *dst = *src;
+ dst->base.id = id;
+ INIT_LIST_HEAD(&dst->head);
+}
+EXPORT_SYMBOL(drm_mode_copy);
/**
* drm_mode_duplicate - allocate and duplicate an existing mode
@@ -720,18 +744,16 @@ struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev,
const struct drm_display_mode *mode)
{
struct drm_display_mode *nmode;
- int new_id;
nmode = drm_mode_create(dev);
if (!nmode)
return NULL;
- new_id = nmode->base.id;
- *nmode = *mode;
- nmode->base.id = new_id;
- INIT_LIST_HEAD(&nmode->head);
+ drm_mode_copy(nmode, mode);
+
return nmode;
}
+EXPORT_SYMBOL(drm_mode_duplicate);
/**
* drm_mode_equal - test modes for equality
@@ -744,9 +766,9 @@ struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev,
* Check to see if @mode1 and @mode2 are equivalent.
*
* RETURNS:
- * true if the modes are equal, false otherwise.
+ * True if the modes are equal, false otherwise.
*/
-bool drm_mode_equal(struct drm_display_mode *mode1, struct drm_display_mode *mode2)
+bool drm_mode_equal(const struct drm_display_mode *mode1, const struct drm_display_mode *mode2)
{
/* do clock check convert to PICOS so fb modes get matched
* the same */
@@ -771,6 +793,7 @@ bool drm_mode_equal(struct drm_display_mode *mode1, struct drm_display_mode *mod
return false;
}
+EXPORT_SYMBOL(drm_mode_equal);
/**
* drm_mode_validate_size - make sure modes adhere to size constraints
@@ -804,6 +827,7 @@ void drm_mode_validate_size(struct drm_device *dev,
mode->status = MODE_VIRTUAL_Y;
}
}
+EXPORT_SYMBOL(drm_mode_validate_size);
/**
* drm_mode_validate_clocks - validate modes against clock limits
@@ -840,6 +864,7 @@ void drm_mode_validate_clocks(struct drm_device *dev,
mode->status = MODE_CLOCK_RANGE;
}
}
+EXPORT_SYMBOL(drm_mode_validate_clocks);
/**
* drm_mode_prune_invalid - remove invalid modes from mode list
@@ -871,6 +896,7 @@ void drm_mode_prune_invalid(struct drm_device *dev,
}
}
}
+EXPORT_SYMBOL(drm_mode_prune_invalid);
/**
* drm_mode_compare - compare modes for favorability
@@ -901,6 +927,11 @@ static int drm_mode_compare(void *priv, struct list_head *lh_a, struct list_head
diff = b->hdisplay * b->vdisplay - a->hdisplay * a->vdisplay;
if (diff)
return diff;
+
+ diff = b->vrefresh - a->vrefresh;
+ if (diff)
+ return diff;
+
diff = b->clock - a->clock;
return diff;
}
@@ -918,6 +949,7 @@ void drm_mode_sort(struct list_head *mode_list)
{
drm_list_sort(NULL, mode_list, drm_mode_compare);
}
+EXPORT_SYMBOL(drm_mode_sort);
/**
* drm_mode_connector_list_update - update the mode list for the connector
@@ -959,6 +991,7 @@ void drm_mode_connector_list_update(struct drm_connector *connector)
}
}
}
+EXPORT_SYMBOL(drm_mode_connector_list_update);
/**
* drm_mode_parse_command_line_for_connector - parse command line for connector
@@ -986,7 +1019,7 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
int i;
enum drm_connector_force force = DRM_FORCE_UNSPECIFIED;
-#ifdef XXX_CONFIG_FB
+#ifdef CONFIG_FB
if (!mode_option)
mode_option = fb_mode_option;
#endif
@@ -1003,7 +1036,7 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
case '@':
if (!refresh_specified && !bpp_specified &&
!yres_specified && !cvt && !rb && was_digit) {
- refresh = strtol(&name[i+1], NULL, 10);
+ refresh = simple_strtol(&name[i+1], NULL, 10);
refresh_specified = true;
was_digit = false;
} else
@@ -1012,7 +1045,7 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
case '-':
if (!bpp_specified && !yres_specified && !cvt &&
!rb && was_digit) {
- bpp = strtol(&name[i+1], NULL, 10);
+ bpp = simple_strtol(&name[i+1], NULL, 10);
bpp_specified = true;
was_digit = false;
} else
@@ -1020,7 +1053,7 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
break;
case 'x':
if (!yres_specified && was_digit) {
- yres = strtol(&name[i+1], NULL, 10);
+ yres = simple_strtol(&name[i+1], NULL, 10);
yres_specified = true;
was_digit = false;
} else
@@ -1080,7 +1113,7 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
if (i < 0 && yres_specified) {
char *ch;
- xres = strtol(name, &ch, 10);
+ xres = simple_strtol(name, &ch, 10);
if ((ch != NULL) && (*ch == 'x'))
res_specified = true;
else
@@ -1091,7 +1124,8 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
}
done:
if (i >= 0) {
- printf("parse error at position %i in video mode '%s'\n",
+ DRM_WARNING(
+ "parse error at position %i in video mode '%s'\n",
i, name);
mode->specified = false;
return false;
@@ -1120,6 +1154,7 @@ done:
return true;
}
+EXPORT_SYMBOL(drm_mode_parse_command_line_for_connector);
struct drm_display_mode *
drm_mode_create_from_cmdline_mode(struct drm_device *dev,
@@ -1145,3 +1180,4 @@ drm_mode_create_from_cmdline_mode(struct drm_device *dev,
drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
return mode;
}
+EXPORT_SYMBOL(drm_mode_create_from_cmdline_mode);
diff --git a/sys/dev/drm2/drm_os_freebsd.c b/sys/dev/drm2/drm_os_freebsd.c
new file mode 100644
index 0000000..11fe928
--- /dev/null
+++ b/sys/dev/drm2/drm_os_freebsd.c
@@ -0,0 +1,393 @@
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <dev/drm2/drmP.h>
+
+#include <dev/agp/agpreg.h>
+#include <dev/pci/pcireg.h>
+
+devclass_t drm_devclass;
+
+MALLOC_DEFINE(DRM_MEM_DMA, "drm_dma", "DRM DMA Data Structures");
+MALLOC_DEFINE(DRM_MEM_SAREA, "drm_sarea", "DRM SAREA Data Structures");
+MALLOC_DEFINE(DRM_MEM_DRIVER, "drm_driver", "DRM DRIVER Data Structures");
+MALLOC_DEFINE(DRM_MEM_MAGIC, "drm_magic", "DRM MAGIC Data Structures");
+MALLOC_DEFINE(DRM_MEM_MINOR, "drm_minor", "DRM MINOR Data Structures");
+MALLOC_DEFINE(DRM_MEM_IOCTLS, "drm_ioctls", "DRM IOCTL Data Structures");
+MALLOC_DEFINE(DRM_MEM_MAPS, "drm_maps", "DRM MAP Data Structures");
+MALLOC_DEFINE(DRM_MEM_BUFS, "drm_bufs", "DRM BUFFER Data Structures");
+MALLOC_DEFINE(DRM_MEM_SEGS, "drm_segs", "DRM SEGMENTS Data Structures");
+MALLOC_DEFINE(DRM_MEM_PAGES, "drm_pages", "DRM PAGES Data Structures");
+MALLOC_DEFINE(DRM_MEM_FILES, "drm_files", "DRM FILE Data Structures");
+MALLOC_DEFINE(DRM_MEM_QUEUES, "drm_queues", "DRM QUEUE Data Structures");
+MALLOC_DEFINE(DRM_MEM_CMDS, "drm_cmds", "DRM COMMAND Data Structures");
+MALLOC_DEFINE(DRM_MEM_MAPPINGS, "drm_mapping", "DRM MAPPING Data Structures");
+MALLOC_DEFINE(DRM_MEM_BUFLISTS, "drm_buflists", "DRM BUFLISTS Data Structures");
+MALLOC_DEFINE(DRM_MEM_AGPLISTS, "drm_agplists", "DRM AGPLISTS Data Structures");
+MALLOC_DEFINE(DRM_MEM_CTXBITMAP, "drm_ctxbitmap",
+ "DRM CTXBITMAP Data Structures");
+MALLOC_DEFINE(DRM_MEM_SGLISTS, "drm_sglists", "DRM SGLISTS Data Structures");
+MALLOC_DEFINE(DRM_MEM_MM, "drm_sman", "DRM MEMORY MANAGER Data Structures");
+MALLOC_DEFINE(DRM_MEM_HASHTAB, "drm_hashtab", "DRM HASHTABLE Data Structures");
+MALLOC_DEFINE(DRM_MEM_KMS, "drm_kms", "DRM KMS Data Structures");
+MALLOC_DEFINE(DRM_MEM_VBLANK, "drm_vblank", "DRM VBLANK Handling Data");
+
+const char *fb_mode_option = NULL;
+
+#define NSEC_PER_USEC 1000L
+#define NSEC_PER_SEC 1000000000L
+
+int64_t
+timeval_to_ns(const struct timeval *tv)
+{
+ return ((int64_t)tv->tv_sec * NSEC_PER_SEC) +
+ tv->tv_usec * NSEC_PER_USEC;
+}
+
+struct timeval
+ns_to_timeval(const int64_t nsec)
+{
+ struct timeval tv;
+ long rem;
+
+ if (nsec == 0) {
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ return (tv);
+ }
+
+ tv.tv_sec = nsec / NSEC_PER_SEC;
+ rem = nsec % NSEC_PER_SEC;
+ if (rem < 0) {
+ tv.tv_sec--;
+ rem += NSEC_PER_SEC;
+ }
+ tv.tv_usec = rem / 1000;
+ return (tv);
+}
+
+static drm_pci_id_list_t *
+drm_find_description(int vendor, int device, drm_pci_id_list_t *idlist)
+{
+ int i = 0;
+
+ for (i = 0; idlist[i].vendor != 0; i++) {
+ if ((idlist[i].vendor == vendor) &&
+ ((idlist[i].device == device) ||
+ (idlist[i].device == 0))) {
+ return (&idlist[i]);
+ }
+ }
+ return (NULL);
+}
+
+/*
+ * drm_probe_helper: called by a driver at the end of its probe
+ * method.
+ */
+int
+drm_probe_helper(device_t kdev, drm_pci_id_list_t *idlist)
+{
+ drm_pci_id_list_t *id_entry;
+ int vendor, device;
+
+ vendor = pci_get_vendor(kdev);
+ device = pci_get_device(kdev);
+
+ if (pci_get_class(kdev) != PCIC_DISPLAY ||
+ (pci_get_subclass(kdev) != PCIS_DISPLAY_VGA &&
+ pci_get_subclass(kdev) != PCIS_DISPLAY_OTHER))
+ return (-ENXIO);
+
+ id_entry = drm_find_description(vendor, device, idlist);
+ if (id_entry != NULL) {
+ if (device_get_desc(kdev) == NULL) {
+ DRM_DEBUG("%s desc: %s\n",
+ device_get_nameunit(kdev), id_entry->name);
+ device_set_desc(kdev, id_entry->name);
+ }
+ return (0);
+ }
+
+ return (-ENXIO);
+}
+
+/*
+ * drm_attach_helper: called by a driver at the end of its attach
+ * method.
+ */
+int
+drm_attach_helper(device_t kdev, drm_pci_id_list_t *idlist,
+ struct drm_driver *driver)
+{
+ struct drm_device *dev;
+ int vendor, device;
+ int ret;
+
+ dev = device_get_softc(kdev);
+
+ vendor = pci_get_vendor(kdev);
+ device = pci_get_device(kdev);
+ dev->id_entry = drm_find_description(vendor, device, idlist);
+
+ ret = drm_get_pci_dev(kdev, dev, driver);
+
+ return (ret);
+}
+
+int
+drm_generic_detach(device_t kdev)
+{
+ struct drm_device *dev;
+ int i;
+
+ dev = device_get_softc(kdev);
+
+ drm_put_dev(dev);
+
+ /* Clean up PCI resources allocated by drm_bufs.c. We're not really
+ * worried about resource consumption while the DRM is inactive (between
+ * lastclose and firstopen or unload) because these aren't actually
+ * taking up KVA, just keeping the PCI resource allocated.
+ */
+ for (i = 0; i < DRM_MAX_PCI_RESOURCE; i++) {
+ if (dev->pcir[i] == NULL)
+ continue;
+ bus_release_resource(dev->dev, SYS_RES_MEMORY,
+ dev->pcirid[i], dev->pcir[i]);
+ dev->pcir[i] = NULL;
+ }
+
+ if (pci_disable_busmaster(dev->dev))
+ DRM_ERROR("Request to disable bus-master failed.\n");
+
+ return (0);
+}
+
+int
+drm_add_busid_modesetting(struct drm_device *dev, struct sysctl_ctx_list *ctx,
+ struct sysctl_oid *top)
+{
+ struct sysctl_oid *oid;
+
+ snprintf(dev->busid_str, sizeof(dev->busid_str),
+ "pci:%04x:%02x:%02x.%d", dev->pci_domain, dev->pci_bus,
+ dev->pci_slot, dev->pci_func);
+ oid = SYSCTL_ADD_STRING(ctx, SYSCTL_CHILDREN(top), OID_AUTO, "busid",
+ CTLFLAG_RD, dev->busid_str, 0, NULL);
+ if (oid == NULL)
+ return (-ENOMEM);
+ dev->modesetting = (dev->driver->driver_features & DRIVER_MODESET) != 0;
+ oid = SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(top), OID_AUTO,
+ "modesetting", CTLFLAG_RD, &dev->modesetting, 0, NULL);
+ if (oid == NULL)
+ return (-ENOMEM);
+
+ return (0);
+}
+
+static int
+drm_device_find_capability(struct drm_device *dev, int cap)
+{
+
+ return (pci_find_cap(dev->dev, cap, NULL) == 0);
+}
+
+int
+drm_pci_device_is_agp(struct drm_device *dev)
+{
+ if (dev->driver->device_is_agp != NULL) {
+ int ret;
+
+ /* device_is_agp returns a tristate, 0 = not AGP, 1 = definitely
+ * AGP, 2 = fall back to PCI capability
+ */
+ ret = (*dev->driver->device_is_agp)(dev);
+ if (ret != DRM_MIGHT_BE_AGP)
+ return ret;
+ }
+
+ return (drm_device_find_capability(dev, PCIY_AGP));
+}
+
+int
+drm_pci_device_is_pcie(struct drm_device *dev)
+{
+
+ return (drm_device_find_capability(dev, PCIY_EXPRESS));
+}
+
+static bool
+dmi_found(const struct dmi_system_id *dsi)
+{
+ char *hw_vendor, *hw_prod;
+ int i, slot;
+ bool res;
+
+ hw_vendor = getenv("smbios.planar.maker");
+ hw_prod = getenv("smbios.planar.product");
+ res = true;
+ for (i = 0; i < nitems(dsi->matches); i++) {
+ slot = dsi->matches[i].slot;
+ switch (slot) {
+ case DMI_NONE:
+ break;
+ case DMI_SYS_VENDOR:
+ case DMI_BOARD_VENDOR:
+ if (hw_vendor != NULL &&
+ !strcmp(hw_vendor, dsi->matches[i].substr)) {
+ break;
+ } else {
+ res = false;
+ goto out;
+ }
+ case DMI_PRODUCT_NAME:
+ case DMI_BOARD_NAME:
+ if (hw_prod != NULL &&
+ !strcmp(hw_prod, dsi->matches[i].substr)) {
+ break;
+ } else {
+ res = false;
+ goto out;
+ }
+ default:
+ res = false;
+ goto out;
+ }
+ }
+out:
+ freeenv(hw_vendor);
+ freeenv(hw_prod);
+
+ return (res);
+}
+
+bool
+dmi_check_system(const struct dmi_system_id *sysid)
+{
+ const struct dmi_system_id *dsi;
+ bool res;
+
+ for (res = false, dsi = sysid; dsi->matches[0].slot != 0 ; dsi++) {
+ if (dmi_found(dsi)) {
+ res = true;
+ if (dsi->callback != NULL && dsi->callback(dsi))
+ break;
+ }
+ }
+ return (res);
+}
+
+int
+drm_mtrr_add(unsigned long offset, unsigned long size, unsigned int flags)
+{
+ int act;
+ struct mem_range_desc mrdesc;
+
+ mrdesc.mr_base = offset;
+ mrdesc.mr_len = size;
+ mrdesc.mr_flags = flags;
+ act = MEMRANGE_SET_UPDATE;
+ strlcpy(mrdesc.mr_owner, "drm", sizeof(mrdesc.mr_owner));
+ return (-mem_range_attr_set(&mrdesc, &act));
+}
+
+int
+drm_mtrr_del(int handle __unused, unsigned long offset, unsigned long size,
+ unsigned int flags)
+{
+ int act;
+ struct mem_range_desc mrdesc;
+
+ mrdesc.mr_base = offset;
+ mrdesc.mr_len = size;
+ mrdesc.mr_flags = flags;
+ act = MEMRANGE_SET_REMOVE;
+ strlcpy(mrdesc.mr_owner, "drm", sizeof(mrdesc.mr_owner));
+ return (-mem_range_attr_set(&mrdesc, &act));
+}
+
+void
+drm_clflush_pages(vm_page_t *pages, unsigned long num_pages)
+{
+
+#if defined(__i386__) || defined(__amd64__)
+ pmap_invalidate_cache_pages(pages, num_pages);
+#else
+ DRM_ERROR("drm_clflush_pages not implemented on this architecture");
+#endif
+}
+
+void
+drm_clflush_virt_range(char *addr, unsigned long length)
+{
+
+#if defined(__i386__) || defined(__amd64__)
+ pmap_invalidate_cache_range((vm_offset_t)addr,
+ (vm_offset_t)addr + length, TRUE);
+#else
+ DRM_ERROR("drm_clflush_virt_range not implemented on this architecture");
+#endif
+}
+
+#if DRM_LINUX
+
+#include <sys/sysproto.h>
+
+MODULE_DEPEND(DRIVER_NAME, linux, 1, 1, 1);
+
+#define LINUX_IOCTL_DRM_MIN 0x6400
+#define LINUX_IOCTL_DRM_MAX 0x64ff
+
+static linux_ioctl_function_t drm_linux_ioctl;
+static struct linux_ioctl_handler drm_handler = {drm_linux_ioctl,
+ LINUX_IOCTL_DRM_MIN, LINUX_IOCTL_DRM_MAX};
+
+/* The bits for in/out are switched on Linux */
+#define LINUX_IOC_IN IOC_OUT
+#define LINUX_IOC_OUT IOC_IN
+
+static int
+drm_linux_ioctl(DRM_STRUCTPROC *p, struct linux_ioctl_args* args)
+{
+ int error;
+ int cmd = args->cmd;
+
+ args->cmd &= ~(LINUX_IOC_IN | LINUX_IOC_OUT);
+ if (cmd & LINUX_IOC_IN)
+ args->cmd |= IOC_IN;
+ if (cmd & LINUX_IOC_OUT)
+ args->cmd |= IOC_OUT;
+
+ error = ioctl(p, (struct ioctl_args *)args);
+
+ return error;
+}
+#endif /* DRM_LINUX */
+
+static int
+drm_modevent(module_t mod, int type, void *data)
+{
+
+ switch (type) {
+ case MOD_LOAD:
+ TUNABLE_INT_FETCH("drm.debug", &drm_debug);
+ TUNABLE_INT_FETCH("drm.notyet", &drm_notyet);
+ break;
+ }
+ return (0);
+}
+
+static moduledata_t drm_mod = {
+ "drmn",
+ drm_modevent,
+ 0
+};
+
+DECLARE_MODULE(drmn, drm_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);
+MODULE_VERSION(drmn, 1);
+MODULE_DEPEND(drmn, agp, 1, 1, 1);
+MODULE_DEPEND(drmn, pci, 1, 1, 1);
+MODULE_DEPEND(drmn, mem, 1, 1, 1);
+MODULE_DEPEND(drmn, iicbus, 1, 1, 1);
diff --git a/sys/dev/drm2/drm_os_freebsd.h b/sys/dev/drm2/drm_os_freebsd.h
index af03f8d..8aa660a 100644
--- a/sys/dev/drm2/drm_os_freebsd.h
+++ b/sys/dev/drm2/drm_os_freebsd.h
@@ -6,6 +6,9 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#ifndef _DRM_OS_FREEBSD_H_
+#define _DRM_OS_FREEBSD_H_
+
#include <sys/fbio.h>
#if _BYTE_ORDER == _BIG_ENDIAN
@@ -14,6 +17,19 @@ __FBSDID("$FreeBSD$");
#define __LITTLE_ENDIAN 1234
#endif
+#ifdef __LP64__
+#define BITS_PER_LONG 64
+#else
+#define BITS_PER_LONG 32
+#endif
+
+#ifndef __user
+#define __user
+#endif
+#ifndef __iomem
+#define __iomem
+#endif
+
#define cpu_to_le16(x) htole16(x)
#define le16_to_cpu(x) le16toh(x)
#define cpu_to_le32(x) htole32(x)
@@ -26,31 +42,96 @@ __FBSDID("$FreeBSD$");
#define be32_to_cpup(x) be32toh(*x)
typedef vm_paddr_t dma_addr_t;
+typedef vm_paddr_t resource_size_t;
+#define wait_queue_head_t atomic_t
+
typedef uint64_t u64;
typedef uint32_t u32;
typedef uint16_t u16;
-typedef uint8_t u8;
+typedef uint8_t u8;
typedef int64_t s64;
typedef int32_t s32;
typedef int16_t s16;
-typedef int8_t s8;
-typedef int32_t __be32;
+typedef int8_t s8;
+typedef uint16_t __le16;
+typedef uint32_t __le32;
+typedef uint64_t __le64;
+typedef uint16_t __be16;
+typedef uint32_t __be32;
+typedef uint64_t __be64;
+
+#define DRM_IRQ_ARGS void *arg
+typedef void irqreturn_t;
+#define IRQ_HANDLED /* nothing */
+#define IRQ_NONE /* nothing */
+#define __init
+#define __exit
+#define __read_mostly
+
+#define WARN_ON(cond) KASSERT(!(cond), ("WARN ON: " #cond))
+#define WARN_ON_SMP(cond) WARN_ON(cond)
+#define BUG_ON(cond) KASSERT(!(cond), ("BUG ON: " #cond))
#define unlikely(x) __builtin_expect(!!(x), 0)
#define likely(x) __builtin_expect(!!(x), 1)
#define container_of(ptr, type, member) ({ \
__typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
-#define DRM_HZ hz
-#define DRM_UDELAY(udelay) DELAY(udelay)
-#define DRM_MDELAY(msecs) do { int loops = (msecs); \
+#define KHZ2PICOS(a) (1000000000UL/(a))
+
+#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
+
+#define HZ hz
+#define DRM_HZ hz
+#define DRM_CURRENTPID curthread->td_proc->p_pid
+#define DRM_SUSER(p) (priv_check(p, PRIV_DRIVER) == 0)
+#define udelay(usecs) DELAY(usecs)
+#define mdelay(msecs) do { int loops = (msecs); \
while (loops--) DELAY(1000); \
} while (0)
-#define DRM_MSLEEP(msecs) drm_msleep((msecs), "drm_msleep")
-#define DRM_TIME_SLICE (hz/20) /* Time slice for GLXContexts */
+#define DRM_UDELAY(udelay) DELAY(udelay)
+#define drm_msleep(x, msg) pause((msg), ((int64_t)(x)) * hz / 1000)
+#define DRM_MSLEEP(msecs) drm_msleep((msecs), "drm_msleep")
+
+#define DRM_READ8(map, offset) \
+ *(volatile u_int8_t *)(((vm_offset_t)(map)->handle) + \
+ (vm_offset_t)(offset))
+#define DRM_READ16(map, offset) \
+ le16toh(*(volatile u_int16_t *)(((vm_offset_t)(map)->handle) + \
+ (vm_offset_t)(offset)))
+#define DRM_READ32(map, offset) \
+ le32toh(*(volatile u_int32_t *)(((vm_offset_t)(map)->handle) + \
+ (vm_offset_t)(offset)))
+#define DRM_READ64(map, offset) \
+ le64toh(*(volatile u_int64_t *)(((vm_offset_t)(map)->handle) + \
+ (vm_offset_t)(offset)))
+#define DRM_WRITE8(map, offset, val) \
+ *(volatile u_int8_t *)(((vm_offset_t)(map)->handle) + \
+ (vm_offset_t)(offset)) = val
+#define DRM_WRITE16(map, offset, val) \
+ *(volatile u_int16_t *)(((vm_offset_t)(map)->handle) + \
+ (vm_offset_t)(offset)) = htole16(val)
+#define DRM_WRITE32(map, offset, val) \
+ *(volatile u_int32_t *)(((vm_offset_t)(map)->handle) + \
+ (vm_offset_t)(offset)) = htole32(val)
+#define DRM_WRITE64(map, offset, val) \
+ *(volatile u_int64_t *)(((vm_offset_t)(map)->handle) + \
+ (vm_offset_t)(offset)) = htole64(val)
+
+/* DRM_READMEMORYBARRIER() prevents reordering of reads.
+ * DRM_WRITEMEMORYBARRIER() prevents reordering of writes.
+ * DRM_MEMORYBARRIER() prevents reordering of reads and writes.
+ */
+#define DRM_READMEMORYBARRIER() rmb()
+#define DRM_WRITEMEMORYBARRIER() wmb()
+#define DRM_MEMORYBARRIER() mb()
+#define smp_rmb() rmb()
+#define smp_mb__before_atomic_inc() mb()
+#define smp_mb__after_atomic_inc() mb()
#define do_div(a, b) ((a) /= (b))
+#define div64_u64(a, b) ((a) / (b))
#define lower_32_bits(n) ((u32)(n))
#define min_t(type, x, y) ({ \
@@ -70,11 +151,14 @@ typedef int32_t __be32;
/* XXXKIB what is the right code for the FreeBSD ? */
/* kib@ used ENXIO here -- dumbbell@ */
#define EREMOTEIO EIO
-#define ERESTARTSYS ERESTART
+#define ERESTARTSYS 512 /* Same value as Linux. */
#define KTR_DRM KTR_DEV
#define KTR_DRM_REG KTR_SPARE3
+#define DRM_AGP_KERN struct agp_info
+#define DRM_AGP_MEM void
+
#define PCI_VENDOR_ID_APPLE 0x106b
#define PCI_VENDOR_ID_ASUSTEK 0x1043
#define PCI_VENDOR_ID_ATI 0x1002
@@ -92,6 +176,7 @@ typedef int32_t __be32;
static inline unsigned long
roundup_pow_of_two(unsigned long x)
{
+
return (1UL << flsl(x - 1));
}
@@ -102,8 +187,10 @@ roundup_pow_of_two(unsigned long x)
*
* Source: include/linux/bitops.h
*/
-static inline uint32_t ror32(uint32_t word, unsigned int shift)
+static inline uint32_t
+ror32(uint32_t word, unsigned int shift)
{
+
return (word >> shift) | (word << (32 - shift));
}
@@ -116,31 +203,184 @@ static inline uint32_t ror32(uint32_t word, unsigned int shift)
/* Taken from linux/include/linux/unaligned/le_struct.h. */
struct __una_u32 { u32 x; } __packed;
-static inline u32 __get_unaligned_cpu32(const void *p)
+static inline u32
+__get_unaligned_cpu32(const void *p)
{
const struct __una_u32 *ptr = (const struct __una_u32 *)p;
- return ptr->x;
+
+ return (ptr->x);
}
-static inline u32 get_unaligned_le32(const void *p)
+static inline u32
+get_unaligned_le32(const void *p)
{
- return __get_unaligned_cpu32((const u8 *)p);
+
+ return (__get_unaligned_cpu32((const u8 *)p));
}
#else
/* Taken from linux/include/linux/unaligned/le_byteshift.h. */
-static inline u32 __get_unaligned_le32(const u8 *p)
+static inline u32
+__get_unaligned_le32(const u8 *p)
+{
+
+ return (p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24);
+}
+
+static inline u32
+get_unaligned_le32(const void *p)
+{
+
+ return (__get_unaligned_le32((const u8 *)p));
+}
+#endif
+
+static inline unsigned long
+ilog2(unsigned long x)
+{
+
+ return (flsl(x) - 1);
+}
+
+static inline int64_t
+abs64(int64_t x)
+{
+
+ return (x < 0 ? -x : x);
+}
+
+int64_t timeval_to_ns(const struct timeval *tv);
+struct timeval ns_to_timeval(const int64_t nsec);
+
+#define PAGE_ALIGN(addr) round_page(addr)
+
+#define drm_get_device_from_kdev(_kdev) (((struct drm_minor *)(_kdev)->si_drv1)->dev)
+
+#define DRM_IOC_VOID IOC_VOID
+#define DRM_IOC_READ IOC_OUT
+#define DRM_IOC_WRITE IOC_IN
+#define DRM_IOC_READWRITE IOC_INOUT
+#define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size)
+
+static inline long
+__copy_to_user(void __user *to, const void *from, unsigned long n)
+{
+ return (copyout(from, to, n) != 0 ? n : 0);
+}
+#define copy_to_user(to, from, n) __copy_to_user((to), (from), (n))
+
+static inline int
+__put_user(size_t size, void *ptr, void *x)
{
- return p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24;
+
+ size = copy_to_user(ptr, x, size);
+
+ return (size ? -EFAULT : size);
}
+#define put_user(x, ptr) __put_user(sizeof(*ptr), (ptr), &(x))
-static inline u32 get_unaligned_le32(const void *p)
+static inline unsigned long
+__copy_from_user(void *to, const void __user *from, unsigned long n)
{
- return __get_unaligned_le32((const u8 *)p);
+ return ((copyin(__DECONST(void *, from), to, n) != 0 ? n : 0));
}
+#define copy_from_user(to, from, n) __copy_from_user((to), (from), (n))
+
+static inline int
+__get_user(size_t size, const void *ptr, void *x)
+{
+
+ size = copy_from_user(x, ptr, size);
+
+ return (size ? -EFAULT : size);
+}
+#define get_user(x, ptr) __get_user(sizeof(*ptr), (ptr), &(x))
+
+#define sigemptyset(set) SIGEMPTYSET(set)
+#define sigaddset(set, sig) SIGADDSET(set, sig)
+
+#define DRM_LOCK(dev) sx_xlock(&(dev)->dev_struct_lock)
+#define DRM_UNLOCK(dev) sx_xunlock(&(dev)->dev_struct_lock)
+
+#define jiffies ticks
+#define jiffies_to_msecs(x) (((int64_t)(x)) * 1000 / hz)
+#define msecs_to_jiffies(x) (((int64_t)(x)) * hz / 1000)
+#define time_after(a,b) ((long)(b) - (long)(a) < 0)
+#define time_after_eq(a,b) ((long)(b) - (long)(a) <= 0)
+
+#define wake_up(queue) wakeup((void *)queue)
+#define wake_up_interruptible(queue) wakeup((void *)queue)
+
+MALLOC_DECLARE(DRM_MEM_DMA);
+MALLOC_DECLARE(DRM_MEM_SAREA);
+MALLOC_DECLARE(DRM_MEM_DRIVER);
+MALLOC_DECLARE(DRM_MEM_MAGIC);
+MALLOC_DECLARE(DRM_MEM_MINOR);
+MALLOC_DECLARE(DRM_MEM_IOCTLS);
+MALLOC_DECLARE(DRM_MEM_MAPS);
+MALLOC_DECLARE(DRM_MEM_BUFS);
+MALLOC_DECLARE(DRM_MEM_SEGS);
+MALLOC_DECLARE(DRM_MEM_PAGES);
+MALLOC_DECLARE(DRM_MEM_FILES);
+MALLOC_DECLARE(DRM_MEM_QUEUES);
+MALLOC_DECLARE(DRM_MEM_CMDS);
+MALLOC_DECLARE(DRM_MEM_MAPPINGS);
+MALLOC_DECLARE(DRM_MEM_BUFLISTS);
+MALLOC_DECLARE(DRM_MEM_AGPLISTS);
+MALLOC_DECLARE(DRM_MEM_CTXBITMAP);
+MALLOC_DECLARE(DRM_MEM_SGLISTS);
+MALLOC_DECLARE(DRM_MEM_MM);
+MALLOC_DECLARE(DRM_MEM_HASHTAB);
+MALLOC_DECLARE(DRM_MEM_KMS);
+MALLOC_DECLARE(DRM_MEM_VBLANK);
+
+#define simple_strtol(a, b, c) strtol((a), (b), (c))
+
+typedef struct drm_pci_id_list
+{
+ int vendor;
+ int device;
+ long driver_private;
+ char *name;
+} drm_pci_id_list_t;
+
+#ifdef __i386__
+#define CONFIG_X86 1
+#endif
+#ifdef __amd64__
+#define CONFIG_X86 1
+#define CONFIG_X86_64 1
#endif
+#ifdef __ia64__
+#define CONFIG_IA64 1
+#endif
+
+#if defined(__i386__) || defined(__amd64__)
+#define CONFIG_ACPI
+#endif
+
+#define CONFIG_AGP 1
+#define CONFIG_MTRR 1
+
+#define CONFIG_FB 1
+extern const char *fb_mode_option;
+
+#define EXPORT_SYMBOL(x)
+#define MODULE_AUTHOR(author)
+#define MODULE_DESCRIPTION(desc)
+#define MODULE_LICENSE(license)
+#define MODULE_PARM_DESC(name, desc)
+#define module_param_named(name, var, type, perm)
+
+#define printk printf
+#define KERN_DEBUG ""
+
+struct fb_info * framebuffer_alloc(void);
+void framebuffer_release(struct fb_info *info);
#define KIB_NOTYET() \
do { \
- if (drm_debug_flag && drm_notyet_flag) \
+ if (drm_debug && drm_notyet) \
printf("NOTYET: %s at %s:%d\n", __func__, __FILE__, __LINE__); \
} while (0)
+
+#endif /* _DRM_OS_FREEBSD_H_ */
diff --git a/sys/dev/drm2/drm_pci.c b/sys/dev/drm2/drm_pci.c
index 5ca151c..7402315 100644
--- a/sys/dev/drm2/drm_pci.c
+++ b/sys/dev/drm2/drm_pci.c
@@ -1,5 +1,20 @@
-/*-
- * Copyright 2003 Eric Anholt.
+/* drm_pci.h -- PCI DMA memory management wrappers for DRM -*- linux-c -*- */
+/**
+ * \file drm_pci.c
+ * \brief Functions and ioctls to manage PCI memory
+ *
+ * \warning These interfaces aren't stable yet.
+ *
+ * \todo Implement the remaining ioctl's for the PCI pools.
+ * \todo The wrappers here are so thin that they would be better off inlined..
+ *
+ * \author José Fonseca <jrfonseca@tungstengraphics.com>
+ * \author Leif Delgass <ldelgass@retinalburn.net>
+ */
+
+/*
+ * Copyright 2003 José Fonseca.
+ * Copyright 2003 Leif Delgass.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -16,7 +31,7 @@
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
@@ -24,15 +39,13 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-/**
- * \file drm_pci.h
- * \brief PCI consistent, DMA-accessible memory allocation.
- *
- * \author Eric Anholt <anholt@FreeBSD.org>
- */
-
#include <dev/drm2/drmP.h>
+static int drm_msi = 1; /* Enable by default. */
+SYSCTL_NODE(_hw, OID_AUTO, drm, CTLFLAG_RW, NULL, "DRM device");
+SYSCTL_INT(_hw_drm, OID_AUTO, msi, CTLFLAG_RDTUN, &drm_msi, 1,
+ "Enable MSI interrupts for drm devices");
+
/**********************************************************************/
/** \name PCI memory */
/*@{*/
@@ -50,12 +63,10 @@ drm_pci_busdma_callback(void *arg, bus_dma_segment_t *segs, int nsegs, int error
}
/**
- * \brief Allocate a physically contiguous DMA-accessible consistent
- * memory block.
+ * \brief Allocate a PCI consistent memory block, for DMA.
*/
-drm_dma_handle_t *
-drm_pci_alloc(struct drm_device *dev, size_t size,
- size_t align, dma_addr_t maxaddr)
+drm_dma_handle_t *drm_pci_alloc(struct drm_device * dev, size_t size,
+ size_t align, dma_addr_t maxaddr)
{
drm_dma_handle_t *dmah;
int ret;
@@ -77,7 +88,7 @@ drm_pci_alloc(struct drm_device *dev, size_t size,
DRM_ERROR("called while holding dma_lock\n");
ret = bus_dma_tag_create(
- bus_get_dma_tag(dev->device), /* parent */
+ bus_get_dma_tag(dev->dev), /* parent */
align, 0, /* align, boundary */
maxaddr, BUS_SPACE_MAXADDR, /* lowaddr, highaddr */
NULL, NULL, /* filtfunc, filtfuncargs */
@@ -109,22 +120,320 @@ drm_pci_alloc(struct drm_device *dev, size_t size,
return dmah;
}
+EXPORT_SYMBOL(drm_pci_alloc);
+
/**
- * \brief Free a DMA-accessible consistent memory block.
+ * \brief Free a PCI consistent memory block without freeing its descriptor.
+ *
+ * This function is for internal use in the Linux-specific DRM core code.
*/
-void
-drm_pci_free(struct drm_device *dev, drm_dma_handle_t *dmah)
+void __drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah)
{
if (dmah == NULL)
return;
bus_dmamem_free(dmah->tag, dmah->vaddr, dmah->map);
bus_dma_tag_destroy(dmah->tag);
+}
+/**
+ * \brief Free a PCI consistent memory block
+ */
+void drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah)
+{
+ __drm_pci_free(dev, dmah);
free(dmah, DRM_MEM_DMA);
}
-/*@}*/
+EXPORT_SYMBOL(drm_pci_free);
+
+static int drm_get_pci_domain(struct drm_device *dev)
+{
+ return dev->pci_domain;
+}
+
+static int drm_pci_get_irq(struct drm_device *dev)
+{
+
+ if (dev->irqr)
+ return (dev->irq);
+
+ dev->irqr = bus_alloc_resource_any(dev->dev, SYS_RES_IRQ,
+ &dev->irqrid, RF_SHAREABLE);
+ if (!dev->irqr) {
+ dev_err(dev->dev, "Failed to allocate IRQ\n");
+ return (0);
+ }
+
+ dev->irq = (int) rman_get_start(dev->irqr);
+
+ return (dev->irq);
+}
+
+static void drm_pci_free_irq(struct drm_device *dev)
+{
+ if (dev->irqr == NULL)
+ return;
+
+ bus_release_resource(dev->dev, SYS_RES_IRQ,
+ dev->irqrid, dev->irqr);
+
+ dev->irqr = NULL;
+ dev->irq = 0;
+}
+
+static const char *drm_pci_get_name(struct drm_device *dev)
+{
+ return dev->driver->name;
+}
+
+int drm_pci_set_busid(struct drm_device *dev, struct drm_master *master)
+{
+ int len, ret;
+ master->unique_len = 40;
+ master->unique_size = master->unique_len;
+ master->unique = malloc(master->unique_size, DRM_MEM_DRIVER, M_NOWAIT);
+ if (master->unique == NULL)
+ return -ENOMEM;
+
+
+ len = snprintf(master->unique, master->unique_len,
+ "pci:%04x:%02x:%02x.%d",
+ dev->pci_domain,
+ dev->pci_bus,
+ dev->pci_slot,
+ dev->pci_func);
+
+ if (len >= master->unique_len) {
+ DRM_ERROR("buffer overflow");
+ ret = -EINVAL;
+ goto err;
+ } else
+ master->unique_len = len;
+
+ return 0;
+err:
+ return ret;
+}
+
+int drm_pci_set_unique(struct drm_device *dev,
+ struct drm_master *master,
+ struct drm_unique *u)
+{
+ int domain, bus, slot, func, ret;
+
+ master->unique_len = u->unique_len;
+ master->unique_size = u->unique_len + 1;
+ master->unique = malloc(master->unique_size, DRM_MEM_DRIVER, M_WAITOK);
+ if (!master->unique) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ if (copy_from_user(master->unique, u->unique, master->unique_len)) {
+ ret = -EFAULT;
+ goto err;
+ }
+
+ master->unique[master->unique_len] = '\0';
+
+ /* Return error if the busid submitted doesn't match the device's actual
+ * busid.
+ */
+ ret = sscanf(master->unique, "PCI:%d:%d:%d", &bus, &slot, &func);
+ if (ret != 3) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ domain = bus >> 8;
+ bus &= 0xff;
+
+ if ((domain != dev->pci_domain) ||
+ (bus != dev->pci_bus) ||
+ (slot != dev->pci_slot) ||
+ (func != dev->pci_func)) {
+ ret = -EINVAL;
+ goto err;
+ }
+ return 0;
+err:
+ return ret;
+}
+
+
+static int drm_pci_irq_by_busid(struct drm_device *dev, struct drm_irq_busid *p)
+{
+ if ((p->busnum >> 8) != drm_get_pci_domain(dev) ||
+ (p->busnum & 0xff) != dev->pci_bus ||
+ p->devnum != dev->pci_slot || p->funcnum != dev->pci_func)
+ return -EINVAL;
+
+ p->irq = dev->irq;
+
+ DRM_DEBUG("%d:%d:%d => IRQ %d\n", p->busnum, p->devnum, p->funcnum,
+ p->irq);
+ return 0;
+}
+
+int drm_pci_agp_init(struct drm_device *dev)
+{
+ if (drm_core_has_AGP(dev)) {
+ if (drm_pci_device_is_agp(dev))
+ dev->agp = drm_agp_init(dev);
+ if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP)
+ && (dev->agp == NULL)) {
+ DRM_ERROR("Cannot initialize the agpgart module.\n");
+ return -EINVAL;
+ }
+ if (drm_core_has_MTRR(dev)) {
+ if (dev->agp && dev->agp->agp_info.ai_aperture_base != 0) {
+ if (drm_mtrr_add(dev->agp->agp_info.ai_aperture_base,
+ dev->agp->agp_info.ai_aperture_size, DRM_MTRR_WC) == 0)
+ dev->agp->agp_mtrr = 1;
+ else
+ dev->agp->agp_mtrr = -1;
+ }
+ }
+ }
+ return 0;
+}
+
+static struct drm_bus drm_pci_bus = {
+ .bus_type = DRIVER_BUS_PCI,
+ .get_irq = drm_pci_get_irq,
+ .free_irq = drm_pci_free_irq,
+ .get_name = drm_pci_get_name,
+ .set_busid = drm_pci_set_busid,
+ .set_unique = drm_pci_set_unique,
+ .irq_by_busid = drm_pci_irq_by_busid,
+ .agp_init = drm_pci_agp_init,
+};
+
+/**
+ * Register.
+ *
+ * \param pdev - PCI device structure
+ * \param ent entry from the PCI ID table with device type flags
+ * \return zero on success or a negative number on failure.
+ *
+ * Attempt to gets inter module "drm" information. If we are first
+ * then register the character device and inter module information.
+ * Try and register, if we fail to register, backout previous work.
+ */
+int drm_get_pci_dev(device_t kdev, struct drm_device *dev,
+ struct drm_driver *driver)
+{
+ int ret;
+
+ DRM_DEBUG("\n");
+
+ driver->bus = &drm_pci_bus;
+
+ dev->dev = kdev;
+
+ dev->pci_domain = pci_get_domain(dev->dev);
+ dev->pci_bus = pci_get_bus(dev->dev);
+ dev->pci_slot = pci_get_slot(dev->dev);
+ dev->pci_func = pci_get_function(dev->dev);
+
+ dev->pci_vendor = pci_get_vendor(dev->dev);
+ dev->pci_device = pci_get_device(dev->dev);
+ dev->pci_subvendor = pci_get_subvendor(dev->dev);
+ dev->pci_subdevice = pci_get_subdevice(dev->dev);
+
+ sx_xlock(&drm_global_mutex);
+
+ if ((ret = drm_fill_in_dev(dev, driver))) {
+ DRM_ERROR("Failed to fill in dev: %d\n", ret);
+ goto err_g1;
+ }
+
+ if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+ ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL);
+ if (ret)
+ goto err_g2;
+ }
+
+ if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY)))
+ goto err_g3;
+
+ if (dev->driver->load) {
+ ret = dev->driver->load(dev,
+ dev->id_entry->driver_private);
+ if (ret)
+ goto err_g4;
+ }
+
+ /* setup the grouping for the legacy output */
+ if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+ ret = drm_mode_group_init_legacy_group(dev,
+ &dev->primary->mode_group);
+ if (ret)
+ goto err_g5;
+ }
+
+#ifdef FREEBSD_NOTYET
+ list_add_tail(&dev->driver_item, &driver->device_list);
+#endif /* FREEBSD_NOTYET */
+
+ DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n",
+ driver->name, driver->major, driver->minor, driver->patchlevel,
+ driver->date, device_get_nameunit(dev->dev), dev->primary->index);
+
+ sx_xunlock(&drm_global_mutex);
+ return 0;
+
+err_g5:
+ if (dev->driver->unload)
+ dev->driver->unload(dev);
+err_g4:
+ drm_put_minor(&dev->primary);
+err_g3:
+ if (drm_core_check_feature(dev, DRIVER_MODESET))
+ drm_put_minor(&dev->control);
+err_g2:
+ drm_cancel_fill_in_dev(dev);
+err_g1:
+ sx_xunlock(&drm_global_mutex);
+ return ret;
+}
+EXPORT_SYMBOL(drm_get_pci_dev);
+
+int
+drm_pci_enable_msi(struct drm_device *dev)
+{
+ int msicount, ret;
+
+ if (!drm_msi)
+ return (-ENOENT);
+
+ msicount = pci_msi_count(dev->dev);
+ DRM_DEBUG("MSI count = %d\n", msicount);
+ if (msicount > 1)
+ msicount = 1;
+
+ ret = pci_alloc_msi(dev->dev, &msicount);
+ if (ret == 0) {
+ DRM_INFO("MSI enabled %d message(s)\n", msicount);
+ dev->msi_enabled = 1;
+ dev->irqrid = 1;
+ }
+
+ return (-ret);
+}
+
+void
+drm_pci_disable_msi(struct drm_device *dev)
+{
+
+ if (!dev->msi_enabled)
+ return;
+
+ pci_release_msi(dev->dev);
+ dev->msi_enabled = 0;
+ dev->irqrid = 0;
+}
int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *mask)
{
@@ -133,14 +442,14 @@ int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *mask)
u32 lnkcap = 0, lnkcap2 = 0;
*mask = 0;
- if (!drm_device_is_pcie(dev))
+ if (!drm_pci_device_is_pcie(dev))
return -EINVAL;
root =
device_get_parent( /* pcib */
device_get_parent( /* `-- pci */
device_get_parent( /* `-- vgapci */
- dev->device))); /* `-- drmn */
+ dev->dev))); /* `-- drmn */
pos = 0;
pci_find_cap(root, PCIY_EXPRESS, &pos);
@@ -179,3 +488,4 @@ int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *mask)
DRM_INFO("probing gen 2 caps for device %x:%x = %x/%x\n", pci_get_vendor(root), pci_get_device(root), lnkcap, lnkcap2);
return 0;
}
+EXPORT_SYMBOL(drm_pcie_get_speed_cap_mask);
diff --git a/sys/dev/drm2/drm_pciids.h b/sys/dev/drm2/drm_pciids.h
index cad56a1..92591d2 100644
--- a/sys/dev/drm2/drm_pciids.h
+++ b/sys/dev/drm2/drm_pciids.h
@@ -49,12 +49,12 @@
{0x8086, 0x0166, CHIP_I9XX|CHIP_I915, "Intel IvyBridge (M)"}, \
{0x8086, 0x016A, CHIP_I9XX|CHIP_I915, "Intel IvyBridge (S)"}, \
{0x8086, 0x0402, CHIP_I9XX|CHIP_I915, "Intel Haswell"}, \
- {0x8086, 0x0412, CHIP_I9XX|CHIP_I915, "Intel Haswell"}, \
- {0x8086, 0x040a, CHIP_I9XX|CHIP_I915, "Intel Haswell (S)"}, \
- {0x8086, 0x041a, CHIP_I9XX|CHIP_I915, "Intel Haswell (S)"}, \
{0x8086, 0x0406, CHIP_I9XX|CHIP_I915, "Intel Haswell (M)"}, \
+ {0x8086, 0x040A, CHIP_I9XX|CHIP_I915, "Intel Haswell (S)"}, \
+ {0x8086, 0x0412, CHIP_I9XX|CHIP_I915, "Intel Haswell"}, \
{0x8086, 0x0416, CHIP_I9XX|CHIP_I915, "Intel Haswell (M)"}, \
- {0x8086, 0x0c16, CHIP_I9XX|CHIP_I915, "Intel Haswell (SDV)"}, \
+ {0x8086, 0x041A, CHIP_I9XX|CHIP_I915, "Intel Haswell (S)"}, \
+ {0x8086, 0x0C16, CHIP_I9XX|CHIP_I915, "Intel Haswell (SDV)"}, \
{0x8086, 0x2562, CHIP_I8XX, "Intel i845G GMCH"}, \
{0x8086, 0x2572, CHIP_I8XX, "Intel i865G GMCH"}, \
{0x8086, 0x2582, CHIP_I9XX|CHIP_I915, "Intel i915G"}, \
@@ -574,6 +574,7 @@
{0x1002, 0x6819, CHIP_PITCAIRN|RADEON_NEW_MEMMAP, "Pitcairn PRO [Radeon HD 7800]"}, \
{0x1002, 0x6820, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "Radeon HD 8800M Series"}, \
{0x1002, 0x6821, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "Radeon HD 8800M Series"}, \
+ {0x1002, 0x6822, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "Venus PRO [Radeon E8860]"}, \
{0x1002, 0x6823, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "Radeon HD 8800M Series"}, \
{0x1002, 0x6824, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "Chelsea [Radeon HD 7700M Series]"}, \
{0x1002, 0x6825, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "Cape Verde [Radeon HD 7800M Series]"}, \
@@ -581,11 +582,13 @@
{0x1002, 0x6827, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "Cape Verde [Radeon HD 7800M Series]"}, \
{0x1002, 0x6828, CHIP_VERDE|RADEON_NEW_MEMMAP, "Cape Verde"}, \
{0x1002, 0x6829, CHIP_VERDE|RADEON_NEW_MEMMAP, "Cape Verde"}, \
+ {0x1002, 0x682A, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "Venus PRO"}, \
{0x1002, 0x682B, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "Radeon HD 8800M Series"}, \
{0x1002, 0x682D, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "Unknown device name"}, \
{0x1002, 0x682F, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "Cape Verde [Radeon HD 7700M Series]"}, \
{0x1002, 0x6830, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "Cape Verde [Radeon HD 7800M Series]"}, \
{0x1002, 0x6831, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "Cape Verde [AMD Radeon HD 7700M Series]"}, \
+ {0x1002, 0x6835, CHIP_VERDE|RADEON_NEW_MEMMAP, "Cape Verde PRX [Radeon R9 255 OEM]"}, \
{0x1002, 0x6837, CHIP_VERDE|RADEON_NEW_MEMMAP, "Cape Verde LE [Radeon HD 7700 Series]"}, \
{0x1002, 0x6838, CHIP_VERDE|RADEON_NEW_MEMMAP, "Cape Verde"}, \
{0x1002, 0x6839, CHIP_VERDE|RADEON_NEW_MEMMAP, "Cape Verde"}, \
@@ -915,6 +918,10 @@
{0x1002, 0x9908, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Trinity [Radeon HD 7600G]"}, \
{0x1002, 0x9909, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Trinity [Radeon HD 7500G]"}, \
{0x1002, 0x990A, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Trinity [Radeon HD 7500G]"}, \
+ {0x1002, 0x990B, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Richland [Radeon HD 8650G]"}, \
+ {0x1002, 0x990C, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Richland [Radeon HD 8670D]"}, \
+ {0x1002, 0x990D, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Richland [Radeon HD 8550G]"}, \
+ {0x1002, 0x990E, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Richland [Radeon HD 8570D]"}, \
{0x1002, 0x990F, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Unknown device name"}, \
{0x1002, 0x9910, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Trinity [Radeon HD 7660G]"}, \
{0x1002, 0x9913, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Trinity [Radeon HD 7640G]"}, \
@@ -926,6 +933,15 @@
{0x1002, 0x9992, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Trinity [Radeon HD 7420G]"}, \
{0x1002, 0x9993, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Trinity [Radeon HD 7480D]"}, \
{0x1002, 0x9994, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Trinity [Radeon HD 7400G]"}, \
+ {0x1002, 0x9995, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Richland [Radeon HD 8450G]"}, \
+ {0x1002, 0x9996, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Richland [Radeon HD 8470D]"}, \
+ {0x1002, 0x9997, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Richland [Radeon HD 8350G]"}, \
+ {0x1002, 0x9998, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Richland [Radeon HD 8370D]"}, \
+ {0x1002, 0x9999, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Richland [Radeon HD 8510G]"}, \
+ {0x1002, 0x999A, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Richland [Radeon HD 8410G]"}, \
+ {0x1002, 0x999B, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Richland [Radeon HD 8310G]"}, \
+ {0x1002, 0x999C, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Richland"}, \
+ {0x1002, 0x999D, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Richland [Radeon HD 8550D]"}, \
{0x1002, 0x99A0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Trinity [Radeon HD 7520G]"}, \
{0x1002, 0x99A2, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Trinity [Radeon HD 7420G]"}, \
{0x1002, 0x99A4, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "Trinity [Radeon HD 7400G]"}, \
diff --git a/sys/dev/drm2/drm_sarea.h b/sys/dev/drm2/drm_sarea.h
index 9f37fcb..90c1178 100644
--- a/sys/dev/drm2/drm_sarea.h
+++ b/sys/dev/drm2/drm_sarea.h
@@ -39,12 +39,14 @@ __FBSDID("$FreeBSD$");
/* SAREA area needs to be at least a page */
#if defined(__alpha__)
-#define SAREA_MAX 0x2000
+#define SAREA_MAX 0x2000U
+#elif defined(__mips__)
+#define SAREA_MAX 0x4000U
#elif defined(__ia64__)
#define SAREA_MAX 0x10000 /* 64kB */
#else
/* Intel 830M driver needs at least 8k SAREA */
-#define SAREA_MAX 0x2000UL
+#define SAREA_MAX 0x2000U
#endif
/** Maximum number of drawables in the SAREA */
diff --git a/sys/dev/drm2/drm_scatter.c b/sys/dev/drm2/drm_scatter.c
index 3ff923c..9be3cb1 100644
--- a/sys/dev/drm2/drm_scatter.c
+++ b/sys/dev/drm2/drm_scatter.c
@@ -33,97 +33,104 @@ __FBSDID("$FreeBSD$");
#include <dev/drm2/drmP.h>
-int
-drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather *request)
+#define DEBUG_SCATTER 0
+
+static inline vm_offset_t drm_vmalloc_dma(vm_size_t size)
+{
+ return kmem_alloc_attr(kernel_arena, size, M_NOWAIT | M_ZERO,
+ 0, BUS_SPACE_MAXADDR_32BIT, VM_MEMATTR_WRITE_COMBINING);
+}
+
+void drm_sg_cleanup(struct drm_sg_mem * entry)
+{
+ if (entry == NULL)
+ return;
+
+ if (entry->vaddr != 0)
+ kmem_free(kernel_arena, entry->vaddr, IDX_TO_OFF(entry->pages));
+
+ free(entry->busaddr, DRM_MEM_SGLISTS);
+ free(entry, DRM_MEM_DRIVER);
+}
+
+int drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather * request)
{
struct drm_sg_mem *entry;
vm_size_t size;
vm_pindex_t pindex;
+ DRM_DEBUG("\n");
+
+ if (!drm_core_check_feature(dev, DRIVER_SG))
+ return -EINVAL;
+
if (dev->sg)
- return EINVAL;
+ return -EINVAL;
- DRM_DEBUG("request size=%ld\n", request->size);
+ entry = malloc(sizeof(*entry), DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
+ if (!entry)
+ return -ENOMEM;
- entry = malloc(sizeof(*entry), DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
+ DRM_DEBUG("request size=%ld\n", request->size);
size = round_page(request->size);
entry->pages = OFF_TO_IDX(size);
entry->busaddr = malloc(entry->pages * sizeof(*entry->busaddr),
- DRM_MEM_SGLISTS, M_WAITOK | M_ZERO);
+ DRM_MEM_SGLISTS, M_NOWAIT | M_ZERO);
+ if (!entry->busaddr) {
+ free(entry, DRM_MEM_DRIVER);
+ return -ENOMEM;
+ }
- entry->vaddr = kmem_alloc_attr(kernel_arena, size, M_WAITOK | M_ZERO,
- 0, BUS_SPACE_MAXADDR_32BIT, VM_MEMATTR_WRITE_COMBINING);
+ entry->vaddr = drm_vmalloc_dma(size);
if (entry->vaddr == 0) {
- drm_sg_cleanup(entry);
- return (ENOMEM);
+ free(entry->busaddr, DRM_MEM_DRIVER);
+ free(entry, DRM_MEM_DRIVER);
+ return -ENOMEM;
}
- for(pindex = 0; pindex < entry->pages; pindex++) {
+ for (pindex = 0; pindex < entry->pages; pindex++) {
entry->busaddr[pindex] =
vtophys(entry->vaddr + IDX_TO_OFF(pindex));
}
- DRM_LOCK(dev);
- if (dev->sg) {
- DRM_UNLOCK(dev);
- drm_sg_cleanup(entry);
- return (EINVAL);
- }
- dev->sg = entry;
- DRM_UNLOCK(dev);
-
request->handle = entry->vaddr;
+ dev->sg = entry;
+
DRM_DEBUG("allocated %ju pages @ 0x%08zx, contents=%08lx\n",
entry->pages, entry->vaddr, *(unsigned long *)entry->vaddr);
- return (0);
+ return 0;
}
-int
-drm_sg_alloc_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
+int drm_sg_alloc_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
struct drm_scatter_gather *request = data;
- DRM_DEBUG("\n");
+ return drm_sg_alloc(dev, request);
- return (drm_sg_alloc(dev, request));
}
-void
-drm_sg_cleanup(struct drm_sg_mem *entry)
-{
- if (entry == NULL)
- return;
-
- if (entry->vaddr != 0)
- kmem_free(kernel_arena, entry->vaddr, IDX_TO_OFF(entry->pages));
-
- free(entry->busaddr, DRM_MEM_SGLISTS);
- free(entry, DRM_MEM_DRIVER);
-
- return;
-}
-
-int
-drm_sg_free(struct drm_device *dev, void *data, struct drm_file *file_priv)
+int drm_sg_free(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
struct drm_scatter_gather *request = data;
struct drm_sg_mem *entry;
- DRM_LOCK(dev);
+ if (!drm_core_check_feature(dev, DRIVER_SG))
+ return -EINVAL;
+
entry = dev->sg;
dev->sg = NULL;
- DRM_UNLOCK(dev);
if (!entry || entry->vaddr != request->handle)
- return (EINVAL);
+ return -EINVAL;
DRM_DEBUG("free 0x%zx\n", entry->vaddr);
drm_sg_cleanup(entry);
- return (0);
+ return 0;
}
diff --git a/sys/dev/drm2/drm_sman.c b/sys/dev/drm2/drm_sman.c
deleted file mode 100644
index 1c1e4af..0000000
--- a/sys/dev/drm2/drm_sman.c
+++ /dev/null
@@ -1,352 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2006 Tungsten Graphics, Inc., Bismarck., ND., USA.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- *
- **************************************************************************/
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-/*
- * Simple memory manager interface that keeps track on allocate regions on a
- * per "owner" basis. All regions associated with an "owner" can be released
- * with a simple call. Typically if the "owner" exists. The owner is any
- * "unsigned long" identifier. Can typically be a pointer to a file private
- * struct or a context identifier.
- *
- * Authors:
- * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
- */
-
-#include <dev/drm2/drmP.h>
-#include <dev/drm2/drm_sman.h>
-
-struct drm_owner_item {
- struct drm_hash_item owner_hash;
- struct list_head sman_list;
- struct list_head mem_blocks;
-};
-
-void drm_sman_takedown(struct drm_sman * sman)
-{
- drm_ht_remove(&sman->user_hash_tab);
- drm_ht_remove(&sman->owner_hash_tab);
- if (sman->mm)
- drm_free(sman->mm, sman->num_managers * sizeof(*sman->mm),
- DRM_MEM_MM);
-}
-
-int
-drm_sman_init(struct drm_sman * sman, unsigned int num_managers,
- unsigned int user_order, unsigned int owner_order)
-{
- int ret = 0;
-
- sman->mm = (struct drm_sman_mm *) drm_calloc(num_managers,
- sizeof(*sman->mm), DRM_MEM_MM);
- if (!sman->mm) {
- ret = -ENOMEM;
- goto out;
- }
- sman->num_managers = num_managers;
- INIT_LIST_HEAD(&sman->owner_items);
- ret = drm_ht_create(&sman->owner_hash_tab, owner_order);
- if (ret)
- goto out1;
- ret = drm_ht_create(&sman->user_hash_tab, user_order);
- if (!ret)
- goto out;
-
- drm_ht_remove(&sman->owner_hash_tab);
-out1:
- drm_free(sman->mm, num_managers * sizeof(*sman->mm), DRM_MEM_MM);
-out:
- return ret;
-}
-
-static void *drm_sman_mm_allocate(void *private, unsigned long size,
- unsigned alignment)
-{
- struct drm_mm *mm = (struct drm_mm *) private;
- struct drm_mm_node *tmp;
-
- tmp = drm_mm_search_free(mm, size, alignment, 1);
- if (!tmp) {
- return NULL;
- }
- /* This could be non-atomic, but we are called from a locked path */
- tmp = drm_mm_get_block_atomic(tmp, size, alignment);
- return tmp;
-}
-
-static void drm_sman_mm_free(void *private, void *ref)
-{
- struct drm_mm_node *node = (struct drm_mm_node *) ref;
-
- drm_mm_put_block(node);
-}
-
-static void drm_sman_mm_destroy(void *private)
-{
- struct drm_mm *mm = (struct drm_mm *) private;
- drm_mm_takedown(mm);
- drm_free(mm, sizeof(*mm), DRM_MEM_MM);
-}
-
-static unsigned long drm_sman_mm_offset(void *private, void *ref)
-{
- struct drm_mm_node *node = (struct drm_mm_node *) ref;
- return node->start;
-}
-
-int
-drm_sman_set_range(struct drm_sman * sman, unsigned int manager,
- unsigned long start, unsigned long size)
-{
- struct drm_sman_mm *sman_mm;
- struct drm_mm *mm;
- int ret;
-
- KASSERT(manager < sman->num_managers, ("Invalid manager"));
-
- sman_mm = &sman->mm[manager];
- mm = malloc(sizeof(*mm), DRM_MEM_MM, M_NOWAIT | M_ZERO);
- if (!mm) {
- return -ENOMEM;
- }
- sman_mm->private = mm;
- ret = drm_mm_init(mm, start, size);
-
- if (ret) {
- drm_free(mm, sizeof(*mm), DRM_MEM_MM);
- return ret;
- }
-
- sman_mm->allocate = drm_sman_mm_allocate;
- sman_mm->free = drm_sman_mm_free;
- sman_mm->destroy = drm_sman_mm_destroy;
- sman_mm->offset = drm_sman_mm_offset;
-
- return 0;
-}
-
-int
-drm_sman_set_manager(struct drm_sman * sman, unsigned int manager,
- struct drm_sman_mm * allocator)
-{
- KASSERT(manager < sman->num_managers, ("Invalid manager"));
- sman->mm[manager] = *allocator;
-
- return 0;
-}
-
-static struct drm_owner_item *drm_sman_get_owner_item(struct drm_sman * sman,
- unsigned long owner)
-{
- int ret;
- struct drm_hash_item *owner_hash_item;
- struct drm_owner_item *owner_item;
-
- ret = drm_ht_find_item(&sman->owner_hash_tab, owner, &owner_hash_item);
- if (!ret) {
- return drm_hash_entry(owner_hash_item, struct drm_owner_item,
- owner_hash);
- }
-
- owner_item = malloc(sizeof(*owner_item), DRM_MEM_MM, M_NOWAIT | M_ZERO);
- if (!owner_item)
- goto out;
-
- INIT_LIST_HEAD(&owner_item->mem_blocks);
- owner_item->owner_hash.key = owner;
- DRM_DEBUG("owner_item = %p, mem_blocks = %p\n", owner_item, &owner_item->mem_blocks);
- if (drm_ht_insert_item(&sman->owner_hash_tab, &owner_item->owner_hash))
- goto out1;
-
- list_add_tail(&owner_item->sman_list, &sman->owner_items);
- return owner_item;
-
-out1:
- drm_free(owner_item, sizeof(*owner_item), DRM_MEM_MM);
-out:
- return NULL;
-}
-
-struct drm_memblock_item *drm_sman_alloc(struct drm_sman *sman, unsigned int manager,
- unsigned long size, unsigned alignment,
- unsigned long owner)
-{
- void *tmp;
- struct drm_sman_mm *sman_mm;
- struct drm_owner_item *owner_item;
- struct drm_memblock_item *memblock;
-
- KASSERT(manager < sman->num_managers, ("Invalid manager"));
-
- sman_mm = &sman->mm[manager];
- tmp = sman_mm->allocate(sman_mm->private, size, alignment);
- if (!tmp) {
- return NULL;
- }
-
- memblock = malloc(sizeof(*memblock), DRM_MEM_MM, M_NOWAIT | M_ZERO);
- DRM_DEBUG("allocated mem_block %p\n", memblock);
- if (!memblock)
- goto out;
-
- memblock->mm_info = tmp;
- memblock->mm = sman_mm;
- memblock->sman = sman;
- INIT_LIST_HEAD(&memblock->owner_list);
-
- if (drm_ht_just_insert_please
- (&sman->user_hash_tab, &memblock->user_hash,
- (unsigned long)memblock, 32, 0, 0))
- goto out1;
-
- owner_item = drm_sman_get_owner_item(sman, owner);
- if (!owner_item)
- goto out2;
-
- DRM_DEBUG("owner_item = %p, mem_blocks = %p\n", owner_item, &owner_item->mem_blocks);
- DRM_DEBUG("owner_list.prev = %p, mem_blocks.prev = %p\n", memblock->owner_list.prev, owner_item->mem_blocks.prev);
- DRM_DEBUG("owner_list.next = %p, mem_blocks.next = %p\n", memblock->owner_list.next, owner_item->mem_blocks.next);
- list_add_tail(&memblock->owner_list, &owner_item->mem_blocks);
-
- DRM_DEBUG("Complete\n");
- return memblock;
-
-out2:
- drm_ht_remove_item(&sman->user_hash_tab, &memblock->user_hash);
-out1:
- drm_free(memblock, sizeof(*memblock), DRM_MEM_MM);
-out:
- sman_mm->free(sman_mm->private, tmp);
-
- return NULL;
-}
-
-static void drm_sman_free(struct drm_memblock_item *item)
-{
- struct drm_sman *sman = item->sman;
-
- list_del(&item->owner_list);
- drm_ht_remove_item(&sman->user_hash_tab, &item->user_hash);
- item->mm->free(item->mm->private, item->mm_info);
- drm_free(item, sizeof(*item), DRM_MEM_MM);
-}
-
-int drm_sman_free_key(struct drm_sman *sman, unsigned int key)
-{
- struct drm_hash_item *hash_item;
- struct drm_memblock_item *memblock_item;
-
- if (drm_ht_find_item(&sman->user_hash_tab, key, &hash_item))
- return -EINVAL;
-
- memblock_item = drm_hash_entry(hash_item, struct drm_memblock_item,
- user_hash);
- drm_sman_free(memblock_item);
- return 0;
-}
-
-static void drm_sman_remove_owner(struct drm_sman *sman,
- struct drm_owner_item *owner_item)
-{
- list_del(&owner_item->sman_list);
- drm_ht_remove_item(&sman->owner_hash_tab, &owner_item->owner_hash);
- drm_free(owner_item, sizeof(*owner_item), DRM_MEM_MM);
-}
-
-int drm_sman_owner_clean(struct drm_sman *sman, unsigned long owner)
-{
-
- struct drm_hash_item *hash_item;
- struct drm_owner_item *owner_item;
-
- if (drm_ht_find_item(&sman->owner_hash_tab, owner, &hash_item)) {
- return -1;
- }
-
- owner_item = drm_hash_entry(hash_item, struct drm_owner_item, owner_hash);
- DRM_DEBUG("cleaning owner_item %p\n", owner_item);
- if (owner_item->mem_blocks.next == &owner_item->mem_blocks) {
- drm_sman_remove_owner(sman, owner_item);
- return -1;
- }
-
- return 0;
-}
-
-static void drm_sman_do_owner_cleanup(struct drm_sman *sman,
- struct drm_owner_item *owner_item)
-{
- struct drm_memblock_item *entry, *next;
-
- list_for_each_entry_safe(entry, next, &owner_item->mem_blocks,
- owner_list) {
- DRM_DEBUG("freeing mem_block %p\n", entry);
- drm_sman_free(entry);
- }
- drm_sman_remove_owner(sman, owner_item);
-}
-
-void drm_sman_owner_cleanup(struct drm_sman *sman, unsigned long owner)
-{
-
- struct drm_hash_item *hash_item;
- struct drm_owner_item *owner_item;
-
- if (drm_ht_find_item(&sman->owner_hash_tab, owner, &hash_item)) {
-
- return;
- }
-
- owner_item = drm_hash_entry(hash_item, struct drm_owner_item, owner_hash);
- drm_sman_do_owner_cleanup(sman, owner_item);
-}
-
-void drm_sman_cleanup(struct drm_sman *sman)
-{
- struct drm_owner_item *entry, *next;
- unsigned int i;
- struct drm_sman_mm *sman_mm;
-
- DRM_DEBUG("sman = %p, owner_items = %p\n",
- sman, &sman->owner_items);
- list_for_each_entry_safe(entry, next, &sman->owner_items, sman_list) {
- DRM_DEBUG("cleaning owner_item = %p\n", entry);
- drm_sman_do_owner_cleanup(sman, entry);
- }
- if (sman->mm) {
- for (i = 0; i < sman->num_managers; ++i) {
- sman_mm = &sman->mm[i];
- if (sman_mm->private) {
- sman_mm->destroy(sman_mm->private);
- sman_mm->private = NULL;
- }
- }
- }
-}
diff --git a/sys/dev/drm2/drm_sman.h b/sys/dev/drm2/drm_sman.h
deleted file mode 100644
index 3b1693f..0000000
--- a/sys/dev/drm2/drm_sman.h
+++ /dev/null
@@ -1,181 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- *
- **************************************************************************/
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-/*
- * Simple memory MANager interface that keeps track on allocate regions on a
- * per "owner" basis. All regions associated with an "owner" can be released
- * with a simple call. Typically if the "owner" exists. The owner is any
- * "unsigned long" identifier. Can typically be a pointer to a file private
- * struct or a context identifier.
- *
- * Authors:
- * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
- */
-
-#ifndef DRM_SMAN_H
-#define DRM_SMAN_H
-
-#include <dev/drm2/drm_hashtab.h>
-#include <dev/drm2/drm_linux_list.h>
-#include <dev/drm2/drm_mm.h>
-
-/*
- * A class that is an abstration of a simple memory allocator.
- * The sman implementation provides a default such allocator
- * using the drm_mm.c implementation. But the user can replace it.
- * See the SiS implementation, which may use the SiS FB kernel module
- * for memory management.
- */
-
-struct drm_sman_mm {
- /* private info. If allocated, needs to be destroyed by the destroy
- function */
- void *private;
-
- /* Allocate a memory block with given size and alignment.
- Return an opaque reference to the memory block */
-
- void *(*allocate) (void *private, unsigned long size,
- unsigned alignment);
-
- /* Free a memory block. "ref" is the opaque reference that we got from
- the "alloc" function */
-
- void (*free) (void *private, void *ref);
-
- /* Free all resources associated with this allocator */
-
- void (*destroy) (void *private);
-
- /* Return a memory offset from the opaque reference returned from the
- "alloc" function */
-
- unsigned long (*offset) (void *private, void *ref);
-};
-
-struct drm_memblock_item {
- struct list_head owner_list;
- struct drm_hash_item user_hash;
- void *mm_info;
- struct drm_sman_mm *mm;
- struct drm_sman *sman;
-};
-
-struct drm_sman {
- struct drm_sman_mm *mm;
- int num_managers;
- struct drm_open_hash owner_hash_tab;
- struct drm_open_hash user_hash_tab;
- struct list_head owner_items;
-};
-
-/*
- * Take down a memory manager. This function should only be called after a
- * successful init and after a call to drm_sman_cleanup.
- */
-
-extern void drm_sman_takedown(struct drm_sman * sman);
-
-/*
- * Allocate structures for a manager.
- * num_managers are the number of memory pools to manage. (VRAM, AGP, ....)
- * user_order is the log2 of the number of buckets in the user hash table.
- * set this to approximately log2 of the max number of memory regions
- * that will be allocated for _all_ pools together.
- * owner_order is the log2 of the number of buckets in the owner hash table.
- * set this to approximately log2 of
- * the number of client file connections that will
- * be using the manager.
- *
- */
-
-extern int drm_sman_init(struct drm_sman * sman, unsigned int num_managers,
- unsigned int user_order, unsigned int owner_order);
-
-/*
- * Initialize a drm_mm.c allocator. Should be called only once for each
- * manager unless a customized allogator is used.
- */
-
-extern int drm_sman_set_range(struct drm_sman * sman, unsigned int manager,
- unsigned long start, unsigned long size);
-
-/*
- * Initialize a customized allocator for one of the managers.
- * (See the SiS module). The object pointed to by "allocator" is copied,
- * so it can be destroyed after this call.
- */
-
-extern int drm_sman_set_manager(struct drm_sman * sman, unsigned int mananger,
- struct drm_sman_mm * allocator);
-
-/*
- * Allocate a memory block. Aligment is not implemented yet.
- */
-
-extern struct drm_memblock_item *drm_sman_alloc(struct drm_sman * sman,
- unsigned int manager,
- unsigned long size,
- unsigned alignment,
- unsigned long owner);
-/*
- * Free a memory block identified by its user hash key.
- */
-
-extern int drm_sman_free_key(struct drm_sman * sman, unsigned int key);
-
-/*
- * returns 1 iff there are no stale memory blocks associated with this owner.
- * Typically called to determine if we need to idle the hardware and call
- * drm_sman_owner_cleanup. If there are no stale memory blocks, it removes all
- * resources associated with owner.
- */
-
-extern int drm_sman_owner_clean(struct drm_sman * sman, unsigned long owner);
-
-/*
- * Frees all stale memory blocks associated with this owner. Note that this
- * requires that the hardware is finished with all blocks, so the graphics engine
- * should be idled before this call is made. This function also frees
- * any resources associated with "owner" and should be called when owner
- * is not going to be referenced anymore.
- */
-
-extern void drm_sman_owner_cleanup(struct drm_sman * sman, unsigned long owner);
-
-/*
- * Frees all stale memory blocks associated with the memory manager.
- * See idling above.
- */
-
-extern void drm_sman_cleanup(struct drm_sman * sman);
-
-#endif
diff --git a/sys/dev/drm2/drm_stub.c b/sys/dev/drm2/drm_stub.c
index 6f6af51..d7ec6cb 100644
--- a/sys/dev/drm2/drm_stub.c
+++ b/sys/dev/drm2/drm_stub.c
@@ -34,27 +34,468 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include "drmP.h"
+#include <dev/drm2/drmP.h>
+#include <dev/drm2/drm_core.h>
-int
-drm_setmaster_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
+#ifdef DRM_DEBUG_DEFAULT_ON
+unsigned int drm_debug = (DRM_DEBUGBITS_DEBUG | DRM_DEBUGBITS_KMS |
+ DRM_DEBUGBITS_FAILED_IOCTL);
+#else
+unsigned int drm_debug = 0; /* 1 to enable debug output */
+#endif
+EXPORT_SYMBOL(drm_debug);
+
+unsigned int drm_notyet = 0;
+
+unsigned int drm_vblank_offdelay = 5000; /* Default to 5000 msecs. */
+EXPORT_SYMBOL(drm_vblank_offdelay);
+
+unsigned int drm_timestamp_precision = 20; /* Default to 20 usecs. */
+EXPORT_SYMBOL(drm_timestamp_precision);
+
+/*
+ * Default to use monotonic timestamps for wait-for-vblank and page-flip
+ * complete events.
+ */
+unsigned int drm_timestamp_monotonic = 1;
+
+MODULE_AUTHOR(CORE_AUTHOR);
+MODULE_DESCRIPTION(CORE_DESC);
+MODULE_LICENSE("GPL and additional rights");
+MODULE_PARM_DESC(debug, "Enable debug output");
+MODULE_PARM_DESC(vblankoffdelay, "Delay until vblank irq auto-disable [msecs]");
+MODULE_PARM_DESC(timestamp_precision_usec, "Max. error on timestamps [usecs]");
+MODULE_PARM_DESC(timestamp_monotonic, "Use monotonic timestamps");
+
+module_param_named(debug, drm_debug, int, 0600);
+module_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600);
+module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600);
+module_param_named(timestamp_monotonic, drm_timestamp_monotonic, int, 0600);
+
+static struct cdevsw drm_cdevsw = {
+ .d_version = D_VERSION,
+ .d_open = drm_open,
+ .d_read = drm_read,
+ .d_ioctl = drm_ioctl,
+ .d_poll = drm_poll,
+ .d_mmap_single = drm_mmap_single,
+ .d_name = "drm",
+ .d_flags = D_TRACKCLOSE
+};
+
+static int drm_minor_get_id(struct drm_device *dev, int type)
+{
+ int new_id;
+
+ new_id = device_get_unit(dev->dev);
+
+ if (new_id >= 64)
+ return -EINVAL;
+
+ if (type == DRM_MINOR_CONTROL) {
+ new_id += 64;
+ } else if (type == DRM_MINOR_RENDER) {
+ new_id += 128;
+ }
+
+ return new_id;
+}
+
+struct drm_master *drm_master_create(struct drm_minor *minor)
+{
+ struct drm_master *master;
+
+ master = malloc(sizeof(*master), DRM_MEM_KMS, M_NOWAIT | M_ZERO);
+ if (!master)
+ return NULL;
+
+ refcount_init(&master->refcount, 1);
+ mtx_init(&master->lock.spinlock, "drm_master__lock__spinlock",
+ NULL, MTX_DEF);
+ DRM_INIT_WAITQUEUE(&master->lock.lock_queue);
+ drm_ht_create(&master->magiclist, DRM_MAGIC_HASH_ORDER);
+ INIT_LIST_HEAD(&master->magicfree);
+ master->minor = minor;
+
+ list_add_tail(&master->head, &minor->master_list);
+
+ return master;
+}
+
+struct drm_master *drm_master_get(struct drm_master *master)
+{
+ refcount_acquire(&master->refcount);
+ return master;
+}
+EXPORT_SYMBOL(drm_master_get);
+
+static void drm_master_destroy(struct drm_master *master)
+{
+ struct drm_magic_entry *pt, *next;
+ struct drm_device *dev = master->minor->dev;
+ struct drm_map_list *r_list, *list_temp;
+
+ list_del(&master->head);
+
+ if (dev->driver->master_destroy)
+ dev->driver->master_destroy(dev, master);
+
+ list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head) {
+ if (r_list->master == master) {
+ drm_rmmap_locked(dev, r_list->map);
+ r_list = NULL;
+ }
+ }
+
+ if (master->unique) {
+ free(master->unique, DRM_MEM_DRIVER);
+ master->unique = NULL;
+ master->unique_len = 0;
+ }
+
+ list_for_each_entry_safe(pt, next, &master->magicfree, head) {
+ list_del(&pt->head);
+ drm_ht_remove_item(&master->magiclist, &pt->hash_item);
+ free(pt, DRM_MEM_MAGIC);
+ }
+
+ drm_ht_remove(&master->magiclist);
+
+ free(master, DRM_MEM_KMS);
+}
+
+void drm_master_put(struct drm_master **master)
+{
+ if (refcount_release(&(*master)->refcount))
+ drm_master_destroy(*master);
+ *master = NULL;
+}
+EXPORT_SYMBOL(drm_master_put);
+
+int drm_setmaster_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ int ret;
+
+ if (file_priv->is_master)
+ return 0;
+
+ if (file_priv->minor->master && file_priv->minor->master != file_priv->master)
+ return -EINVAL;
+
+ if (!file_priv->master)
+ return -EINVAL;
+
+ if (file_priv->minor->master)
+ return -EINVAL;
+
+ DRM_LOCK(dev);
+ file_priv->minor->master = drm_master_get(file_priv->master);
+ file_priv->is_master = 1;
+ if (dev->driver->master_set) {
+ ret = dev->driver->master_set(dev, file_priv, false);
+ if (unlikely(ret != 0)) {
+ file_priv->is_master = 0;
+ drm_master_put(&file_priv->minor->master);
+ }
+ }
+ DRM_UNLOCK(dev);
+
+ return 0;
+}
+
+int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ if (!file_priv->is_master)
+ return -EINVAL;
+
+ if (!file_priv->minor->master)
+ return -EINVAL;
+
+ DRM_LOCK(dev);
+ if (dev->driver->master_drop)
+ dev->driver->master_drop(dev, file_priv, false);
+ drm_master_put(&file_priv->minor->master);
+ file_priv->is_master = 0;
+ DRM_UNLOCK(dev);
+ return 0;
+}
+
+int drm_fill_in_dev(struct drm_device *dev,
+ struct drm_driver *driver)
+{
+ int retcode, i;
+
+ INIT_LIST_HEAD(&dev->filelist);
+ INIT_LIST_HEAD(&dev->ctxlist);
+ INIT_LIST_HEAD(&dev->maplist);
+ INIT_LIST_HEAD(&dev->vblank_event_list);
+
+ mtx_init(&dev->irq_lock, "drmirq", NULL, MTX_DEF);
+ mtx_init(&dev->count_lock, "drmcount", NULL, MTX_DEF);
+ mtx_init(&dev->event_lock, "drmev", NULL, MTX_DEF);
+ sx_init(&dev->dev_struct_lock, "drmslk");
+ mtx_init(&dev->ctxlist_mutex, "drmctxlist", NULL, MTX_DEF);
+ mtx_init(&dev->pcir_lock, "drmpcir", NULL, MTX_DEF);
+
+ if (drm_ht_create(&dev->map_hash, 12)) {
+ return -ENOMEM;
+ }
+
+ /* the DRM has 6 basic counters */
+ dev->counters = 6;
+ dev->types[0] = _DRM_STAT_LOCK;
+ dev->types[1] = _DRM_STAT_OPENS;
+ dev->types[2] = _DRM_STAT_CLOSES;
+ dev->types[3] = _DRM_STAT_IOCTLS;
+ dev->types[4] = _DRM_STAT_LOCKS;
+ dev->types[5] = _DRM_STAT_UNLOCKS;
+
+ /*
+ * FIXME Linux<->FreeBSD: this is done in drm_setup() on Linux.
+ */
+ for (i = 0; i < ARRAY_SIZE(dev->counts); i++)
+ atomic_set(&dev->counts[i], 0);
+
+ dev->driver = driver;
+
+ retcode = drm_pci_agp_init(dev);
+ if (retcode)
+ goto error_out_unreg;
+
+
+
+ retcode = drm_ctxbitmap_init(dev);
+ if (retcode) {
+ DRM_ERROR("Cannot allocate memory for context bitmap.\n");
+ goto error_out_unreg;
+ }
+
+ if (driver->driver_features & DRIVER_GEM) {
+ retcode = drm_gem_init(dev);
+ if (retcode) {
+ DRM_ERROR("Cannot initialize graphics execution "
+ "manager (GEM)\n");
+ goto error_out_unreg;
+ }
+ }
+
+ retcode = drm_sysctl_init(dev);
+ if (retcode != 0) {
+ DRM_ERROR("Failed to create hw.dri sysctl entry: %d\n",
+ retcode);
+ }
+
+ return 0;
+
+ error_out_unreg:
+ drm_cancel_fill_in_dev(dev);
+ return retcode;
+}
+EXPORT_SYMBOL(drm_fill_in_dev);
+
+void drm_cancel_fill_in_dev(struct drm_device *dev)
{
+ struct drm_driver *driver;
+
+ driver = dev->driver;
+
+ drm_sysctl_cleanup(dev);
+ if (driver->driver_features & DRIVER_GEM)
+ drm_gem_destroy(dev);
+ drm_ctxbitmap_cleanup(dev);
- DRM_DEBUG("setmaster\n");
+ if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) &&
+ dev->agp && dev->agp->agp_mtrr >= 0) {
+ int retval;
+ retval = drm_mtrr_del(dev->agp->agp_mtrr,
+ dev->agp->agp_info.ai_aperture_base,
+ dev->agp->agp_info.ai_aperture_size,
+ DRM_MTRR_WC);
+ DRM_DEBUG("mtrr_del=%d\n", retval);
+ }
+ free(dev->agp, DRM_MEM_AGPLISTS);
+ dev->agp = NULL;
- if (file_priv->master != 0)
- return (0);
- return (EPERM);
+ drm_ht_remove(&dev->map_hash);
+
+ mtx_destroy(&dev->irq_lock);
+ mtx_destroy(&dev->count_lock);
+ mtx_destroy(&dev->event_lock);
+ sx_destroy(&dev->dev_struct_lock);
+ mtx_destroy(&dev->ctxlist_mutex);
+ mtx_destroy(&dev->pcir_lock);
}
-int
-drm_dropmaster_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
+/**
+ * Get a secondary minor number.
+ *
+ * \param dev device data structure
+ * \param sec-minor structure to hold the assigned minor
+ * \return negative number on failure.
+ *
+ * Search an empty entry and initialize it to the given parameters, and
+ * create the proc init entry via proc_init(). This routines assigns
+ * minor numbers to secondary heads of multi-headed cards
+ */
+int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int type)
{
+ struct drm_minor *new_minor;
+ int ret;
+ int minor_id;
+ const char *minor_devname;
+
+ DRM_DEBUG("\n");
+
+ minor_id = drm_minor_get_id(dev, type);
+ if (minor_id < 0)
+ return minor_id;
+
+ new_minor = malloc(sizeof(struct drm_minor), DRM_MEM_MINOR,
+ M_NOWAIT | M_ZERO);
+ if (!new_minor) {
+ ret = -ENOMEM;
+ goto err_idr;
+ }
+
+ new_minor->type = type;
+ new_minor->dev = dev;
+ new_minor->index = minor_id;
+ INIT_LIST_HEAD(&new_minor->master_list);
+
+ new_minor->buf_sigio = NULL;
+
+ switch (type) {
+ case DRM_MINOR_CONTROL:
+ minor_devname = "dri/controlD%d";
+ break;
+ case DRM_MINOR_RENDER:
+ minor_devname = "dri/renderD%d";
+ break;
+ default:
+ minor_devname = "dri/card%d";
+ break;
+ }
+
+ ret = make_dev_p(MAKEDEV_WAITOK | MAKEDEV_CHECKNAME, &new_minor->device,
+ &drm_cdevsw, 0, DRM_DEV_UID, DRM_DEV_GID,
+ DRM_DEV_MODE, minor_devname, minor_id);
+ if (ret) {
+ DRM_ERROR("Failed to create cdev: %d\n", ret);
+ goto err_mem;
+ }
+ new_minor->device->si_drv1 = new_minor;
+ *minor = new_minor;
+
+ DRM_DEBUG("new minor assigned %d\n", minor_id);
+ return 0;
+
+
+err_mem:
+ free(new_minor, DRM_MEM_MINOR);
+err_idr:
+ *minor = NULL;
+ return ret;
+}
+EXPORT_SYMBOL(drm_get_minor);
+
+/**
+ * Put a secondary minor number.
+ *
+ * \param sec_minor - structure to be released
+ * \return always zero
+ *
+ * Cleans up the proc resources. Not legal for this to be the
+ * last minor released.
+ *
+ */
+int drm_put_minor(struct drm_minor **minor_p)
+{
+ struct drm_minor *minor = *minor_p;
+
+ DRM_DEBUG("release secondary minor %d\n", minor->index);
+
+ funsetown(&minor->buf_sigio);
+
+ destroy_dev(minor->device);
+
+ free(minor, DRM_MEM_MINOR);
+ *minor_p = NULL;
+ return 0;
+}
+EXPORT_SYMBOL(drm_put_minor);
+
+/**
+ * Called via drm_exit() at module unload time or when pci device is
+ * unplugged.
+ *
+ * Cleans up all DRM device, calling drm_lastclose().
+ *
+ */
+void drm_put_dev(struct drm_device *dev)
+{
+ struct drm_driver *driver;
+ struct drm_map_list *r_list, *list_temp;
+
+ DRM_DEBUG("\n");
+
+ if (!dev) {
+ DRM_ERROR("cleanup called no dev\n");
+ return;
+ }
+ driver = dev->driver;
+
+ drm_lastclose(dev);
+
+ if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) &&
+ dev->agp && dev->agp->agp_mtrr >= 0) {
+ int retval;
+ retval = drm_mtrr_del(dev->agp->agp_mtrr,
+ dev->agp->agp_info.ai_aperture_base,
+ dev->agp->agp_info.ai_aperture_size,
+ DRM_MTRR_WC);
+ DRM_DEBUG("mtrr_del=%d\n", retval);
+ }
+
+ if (drm_core_check_feature(dev, DRIVER_MODESET))
+ drm_mode_group_free(&dev->primary->mode_group);
+
+ if (dev->driver->unload)
+ dev->driver->unload(dev);
+
+ drm_sysctl_cleanup(dev);
+
+ if (drm_core_has_AGP(dev) && dev->agp) {
+ free(dev->agp, DRM_MEM_AGPLISTS);
+ dev->agp = NULL;
+ }
+
+ drm_vblank_cleanup(dev);
+
+ list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head)
+ drm_rmmap(dev, r_list->map);
+ drm_ht_remove(&dev->map_hash);
+
+ drm_ctxbitmap_cleanup(dev);
+
+ if (drm_core_check_feature(dev, DRIVER_MODESET))
+ drm_put_minor(&dev->control);
+
+ if (driver->driver_features & DRIVER_GEM)
+ drm_gem_destroy(dev);
+
+ drm_put_minor(&dev->primary);
+
+ mtx_destroy(&dev->irq_lock);
+ mtx_destroy(&dev->count_lock);
+ mtx_destroy(&dev->event_lock);
+ sx_destroy(&dev->dev_struct_lock);
+ mtx_destroy(&dev->ctxlist_mutex);
+ mtx_destroy(&dev->pcir_lock);
- DRM_DEBUG("dropmaster\n");
- if (file_priv->master != 0)
- return (EINVAL);
- return (0);
+#ifdef FREEBSD_NOTYET
+ list_del(&dev->driver_item);
+#endif /* FREEBSD_NOTYET */
}
+EXPORT_SYMBOL(drm_put_dev);
diff --git a/sys/dev/drm2/drm_sysctl.c b/sys/dev/drm2/drm_sysctl.c
index a30c7ab..646f86c 100644
--- a/sys/dev/drm2/drm_sysctl.c
+++ b/sys/dev/drm2/drm_sysctl.c
@@ -8,11 +8,11 @@
* 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
@@ -70,8 +70,11 @@ int drm_sysctl_init(struct drm_device *dev)
/* Add the sysctl node for DRI if it doesn't already exist */
drioid = SYSCTL_ADD_NODE(&info->ctx, &sysctl__hw_children, OID_AUTO,
"dri", CTLFLAG_RW, NULL, "DRI Graphics");
- if (!drioid)
- return 1;
+ if (!drioid) {
+ free(dev->sysctl, DRM_MEM_DRIVER);
+ dev->sysctl = NULL;
+ return (-ENOMEM);
+ }
/* Find the next free slot under hw.dri */
i = 0;
@@ -79,18 +82,22 @@ int drm_sysctl_init(struct drm_device *dev)
if (i <= oid->oid_arg2)
i = oid->oid_arg2 + 1;
}
- if (i > 9)
- return (1);
-
+ if (i > 9) {
+ drm_sysctl_cleanup(dev);
+ return (-ENOSPC);
+ }
+
dev->sysctl_node_idx = i;
/* Add the hw.dri.x for our device */
info->name[0] = '0' + i;
info->name[1] = 0;
top = SYSCTL_ADD_NODE(&info->ctx, SYSCTL_CHILDREN(drioid),
OID_AUTO, info->name, CTLFLAG_RW, NULL, NULL);
- if (!top)
- return 1;
-
+ if (!top) {
+ drm_sysctl_cleanup(dev);
+ return (-ENOMEM);
+ }
+
for (i = 0; i < DRM_SYSCTL_ENTRIES; i++) {
oid = SYSCTL_ADD_OID(&info->ctx,
SYSCTL_CHILDREN(top),
@@ -102,14 +109,16 @@ int drm_sysctl_init(struct drm_device *dev)
drm_sysctl_list[i].f,
"A",
NULL);
- if (!oid)
- return 1;
+ if (!oid) {
+ drm_sysctl_cleanup(dev);
+ return (-ENOMEM);
+ }
}
SYSCTL_ADD_INT(&info->ctx, SYSCTL_CHILDREN(drioid), OID_AUTO, "debug",
- CTLFLAG_RW, &drm_debug_flag, sizeof(drm_debug_flag),
+ CTLFLAG_RW, &drm_debug, sizeof(drm_debug),
"Enable debugging output");
SYSCTL_ADD_INT(&info->ctx, SYSCTL_CHILDREN(drioid), OID_AUTO, "notyet",
- CTLFLAG_RW, &drm_notyet_flag, sizeof(drm_debug_flag),
+ CTLFLAG_RW, &drm_notyet, sizeof(drm_debug),
"Enable notyet reminders");
if (dev->driver->sysctl_init != NULL)
@@ -131,13 +140,16 @@ int drm_sysctl_cleanup(struct drm_device *dev)
{
int error;
+ if (dev->sysctl == NULL)
+ return (0);
+
error = sysctl_ctx_free(&dev->sysctl->ctx);
free(dev->sysctl, DRM_MEM_DRIVER);
dev->sysctl = NULL;
if (dev->driver->sysctl_cleanup != NULL)
dev->driver->sysctl_cleanup(dev);
- return (error);
+ return (-error);
}
#define DRM_SYSCTL_PRINT(fmt, arg...) \
@@ -151,19 +163,24 @@ do { \
static int drm_name_info DRM_SYSCTL_HANDLER_ARGS
{
struct drm_device *dev = arg1;
+ struct drm_minor *minor;
+ struct drm_master *master;
char buf[128];
int retcode;
int hasunique = 0;
- DRM_SYSCTL_PRINT("%s 0x%x", dev->driver->name, dev2udev(dev->devnode));
+ /* FIXME: This still uses primary minor. */
+ minor = dev->primary;
+ DRM_SYSCTL_PRINT("%s 0x%x", dev->driver->name, dev2udev(minor->device));
DRM_LOCK(dev);
- if (dev->unique) {
- snprintf(buf, sizeof(buf), " %s", dev->unique);
+ master = minor->master;
+ if (master != NULL && master->unique) {
+ snprintf(buf, sizeof(buf), " %s", master->unique);
hasunique = 1;
}
DRM_UNLOCK(dev);
-
+
if (hasunique)
SYSCTL_OUT(req, buf, strlen(buf));
@@ -176,7 +193,8 @@ done:
static int drm_vm_info DRM_SYSCTL_HANDLER_ARGS
{
struct drm_device *dev = arg1;
- drm_local_map_t *map, *tempmaps;
+ struct drm_map_list *entry;
+ struct drm_local_map *map, *tempmaps;
const char *types[] = {
[_DRM_FRAME_BUFFER] = "FB",
[_DRM_REGISTERS] = "REG",
@@ -197,10 +215,12 @@ static int drm_vm_info DRM_SYSCTL_HANDLER_ARGS
DRM_LOCK(dev);
mapcount = 0;
- TAILQ_FOREACH(map, &dev->maplist, link)
- mapcount++;
+ list_for_each_entry(entry, &dev->maplist, head) {
+ if (entry->map != NULL)
+ mapcount++;
+ }
- tempmaps = malloc(sizeof(drm_local_map_t) * mapcount, DRM_MEM_DRIVER,
+ tempmaps = malloc(sizeof(*tempmaps) * mapcount, DRM_MEM_DRIVER,
M_NOWAIT);
if (tempmaps == NULL) {
DRM_UNLOCK(dev);
@@ -208,13 +228,15 @@ static int drm_vm_info DRM_SYSCTL_HANDLER_ARGS
}
i = 0;
- TAILQ_FOREACH(map, &dev->maplist, link)
- tempmaps[i++] = *map;
+ list_for_each_entry(entry, &dev->maplist, head) {
+ if (entry->map != NULL)
+ tempmaps[i++] = *entry->map;
+ }
DRM_UNLOCK(dev);
DRM_SYSCTL_PRINT("\nslot offset size "
- "type flags address handle mtrr\n");
+ "type flags address mtrr\n");
for (i = 0; i < mapcount; i++) {
map = &tempmaps[i];
@@ -234,17 +256,15 @@ static int drm_vm_info DRM_SYSCTL_HANDLER_ARGS
break;
}
- if (!map->mtrr)
+ if (map->mtrr < 0)
yesno = "no";
else
yesno = "yes";
DRM_SYSCTL_PRINT(
- "%4d 0x%016lx 0x%08lx %4.4s 0x%02x 0x%016lx %6d %s\n",
- i, map->offset, map->size, type, map->flags,
- (unsigned long)map->virtual,
- (unsigned int)((unsigned long)map->handle >>
- DRM_MAP_HANDLE_SHIFT), yesno);
+ "%4d 0x%016llx 0x%08lx %4.4s 0x%02x 0x%016lx %s\n",
+ i, (unsigned long long)map->offset, map->size, type,
+ map->flags, (unsigned long)map->handle, yesno);
}
SYSCTL_OUT(req, "", 1);
@@ -256,8 +276,8 @@ done:
static int drm_bufs_info DRM_SYSCTL_HANDLER_ARGS
{
struct drm_device *dev = arg1;
- drm_device_dma_t *dma = dev->dma;
- drm_device_dma_t tempdma;
+ struct drm_device_dma *dma = dev->dma;
+ struct drm_device_dma tempdma;
int *templists;
int i;
char buf[128];
@@ -321,7 +341,7 @@ static int drm_clients_info DRM_SYSCTL_HANDLER_ARGS
DRM_LOCK(dev);
privcount = 0;
- TAILQ_FOREACH(priv, &dev->files, link)
+ list_for_each_entry(priv, &dev->filelist, lhead)
privcount++;
tempprivs = malloc(sizeof(struct drm_file) * privcount, DRM_MEM_DRIVER,
@@ -331,7 +351,7 @@ static int drm_clients_info DRM_SYSCTL_HANDLER_ARGS
return ENOMEM;
}
i = 0;
- TAILQ_FOREACH(priv, &dev->files, link)
+ list_for_each_entry(priv, &dev->filelist, lhead)
tempprivs[i++] = *priv;
DRM_UNLOCK(dev);
@@ -342,7 +362,7 @@ static int drm_clients_info DRM_SYSCTL_HANDLER_ARGS
priv = &tempprivs[i];
DRM_SYSCTL_PRINT("%c %-12s %5d %5d %10u %10lu\n",
priv->authenticated ? 'y' : 'n',
- devtoname(priv->dev->devnode),
+ devtoname(priv->minor->device),
priv->pid,
priv->uid,
priv->magic,
diff --git a/sys/dev/drm2/drm_vm.c b/sys/dev/drm2/drm_vm.c
index a70fe7b..3fa2aba 100644
--- a/sys/dev/drm2/drm_vm.c
+++ b/sys/dev/drm2/drm_vm.c
@@ -1,5 +1,16 @@
-/*-
- * Copyright 2003 Eric Anholt
+/**
+ * \file drm_vm.c
+ * Memory mapping for DRM
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
+ * Created: Mon Jan 4 08:58:31 1999 by faith@valinux.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -8,17 +19,18 @@
* 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
- * ERIC ANHOLT 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.
+ * 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.
*/
#include <sys/cdefs.h>
@@ -31,6 +43,7 @@ __FBSDID("$FreeBSD$");
#include <dev/drm2/drmP.h>
#include <dev/drm2/drm.h>
+#ifdef FREEBSD_NOTYET
int
drm_mmap(struct cdev *kdev, vm_ooffset_t offset, vm_paddr_t *paddr,
int prot, vm_memattr_t *memattr)
@@ -131,4 +144,4 @@ drm_mmap(struct cdev *kdev, vm_ooffset_t offset, vm_paddr_t *paddr,
*paddr = phys;
return 0;
}
-
+#endif /* FREEBSD_NOTYET */
diff --git a/sys/dev/drm2/i915/i915_debug.c b/sys/dev/drm2/i915/i915_debug.c
index 5f44a99..43d67f8 100644
--- a/sys/dev/drm2/i915/i915_debug.c
+++ b/sys/dev/drm2/i915/i915_debug.c
@@ -45,14 +45,12 @@ enum {
PINNED_LIST,
};
-static const char *
-yesno(int v)
+static const char *yesno(int v)
{
- return (v ? "yes" : "no");
+ return v ? "yes" : "no";
}
-static int
-i915_capabilities(struct drm_device *dev, struct sbuf *m, void *data)
+static int i915_capabilities(struct drm_device *dev, struct sbuf *m, void *data)
{
const struct intel_device_info *info = INTEL_INFO(dev);
@@ -80,11 +78,10 @@ i915_capabilities(struct drm_device *dev, struct sbuf *m, void *data)
B(has_llc);
#undef B
- return (0);
+ return 0;
}
-static const char *
-get_pin_flag(struct drm_i915_gem_object *obj)
+static const char *get_pin_flag(struct drm_i915_gem_object *obj)
{
if (obj->user_pin_count > 0)
return "P";
@@ -94,25 +91,23 @@ get_pin_flag(struct drm_i915_gem_object *obj)
return " ";
}
-static const char *
-get_tiling_flag(struct drm_i915_gem_object *obj)
+static const char *get_tiling_flag(struct drm_i915_gem_object *obj)
{
switch (obj->tiling_mode) {
default:
- case I915_TILING_NONE: return (" ");
- case I915_TILING_X: return ("X");
- case I915_TILING_Y: return ("Y");
+ case I915_TILING_NONE: return " ";
+ case I915_TILING_X: return "X";
+ case I915_TILING_Y: return "Y";
}
}
-static const char *
-cache_level_str(int type)
+static const char *cache_level_str(int type)
{
switch (type) {
case I915_CACHE_NONE: return " uncached";
case I915_CACHE_LLC: return " snooped (LLC)";
case I915_CACHE_LLC_MLC: return " snooped (LLC+MLC)";
- default: return ("");
+ default: return "";
}
}
@@ -154,8 +149,7 @@ describe_obj(struct sbuf *m, struct drm_i915_gem_object *obj)
sbuf_printf(m, " (%s)", obj->ring->name);
}
-static int
-i915_gem_object_list_info(struct drm_device *dev, struct sbuf *m, void *data)
+static int i915_gem_object_list_info(struct drm_device *dev, struct sbuf *m, void *data)
{
uintptr_t list = (uintptr_t)data;
struct list_head *head;
@@ -165,7 +159,7 @@ i915_gem_object_list_info(struct drm_device *dev, struct sbuf *m, void *data)
int count;
if (sx_xlock_sig(&dev->dev_struct_lock))
- return (EINTR);
+ return -EINTR;
switch (list) {
case ACTIVE_LIST:
@@ -182,7 +176,7 @@ i915_gem_object_list_info(struct drm_device *dev, struct sbuf *m, void *data)
break;
default:
DRM_UNLOCK(dev);
- return (EINVAL);
+ return -EINVAL;
}
total_obj_size = total_gtt_size = count = 0;
@@ -198,7 +192,7 @@ i915_gem_object_list_info(struct drm_device *dev, struct sbuf *m, void *data)
sbuf_printf(m, "Total %d objects, %zu bytes, %zu GTT size\n",
count, total_obj_size, total_gtt_size);
- return (0);
+ return 0;
}
#define count_objects(list, member) do { \
@@ -212,8 +206,7 @@ i915_gem_object_list_info(struct drm_device *dev, struct sbuf *m, void *data)
} \
} while (0)
-static int
-i915_gem_object_info(struct drm_device *dev, struct sbuf *m, void *data)
+static int i915_gem_object_info(struct drm_device *dev, struct sbuf *m, void *data)
{
struct drm_i915_private *dev_priv = dev->dev_private;
u32 count, mappable_count;
@@ -221,7 +214,7 @@ i915_gem_object_info(struct drm_device *dev, struct sbuf *m, void *data)
struct drm_i915_gem_object *obj;
if (sx_xlock_sig(&dev->dev_struct_lock))
- return (EINTR);
+ return -EINTR;
sbuf_printf(m, "%u objects, %zu bytes\n",
dev_priv->mm.object_count,
dev_priv->mm.object_memory);
@@ -260,13 +253,13 @@ i915_gem_object_info(struct drm_device *dev, struct sbuf *m, void *data)
sbuf_printf(m, "%zu [%zu] gtt total\n",
dev_priv->mm.gtt_total, dev_priv->mm.mappable_gtt_total);
+
DRM_UNLOCK(dev);
- return (0);
+ return 0;
}
-static int
-i915_gem_gtt_info(struct drm_device *dev, struct sbuf *m, void *data)
+static int i915_gem_gtt_info(struct drm_device *dev, struct sbuf *m, void *data)
{
struct drm_i915_private *dev_priv = dev->dev_private;
uintptr_t list = (uintptr_t)data;
@@ -275,7 +268,7 @@ i915_gem_gtt_info(struct drm_device *dev, struct sbuf *m, void *data)
int count;
if (sx_xlock_sig(&dev->dev_struct_lock))
- return (EINTR);
+ return -EINTR;
total_obj_size = total_gtt_size = count = 0;
list_for_each_entry(obj, &dev_priv->mm.gtt_list, gtt_list) {
@@ -295,11 +288,10 @@ i915_gem_gtt_info(struct drm_device *dev, struct sbuf *m, void *data)
sbuf_printf(m, "Total %d objects, %zu bytes, %zu GTT size\n",
count, total_obj_size, total_gtt_size);
- return (0);
+ return 0;
}
-static int
-i915_gem_pageflip_info(struct drm_device *dev, struct sbuf *m, void *data)
+static int i915_gem_pageflip_info(struct drm_device *dev, struct sbuf *m, void *data)
{
struct intel_crtc *crtc;
struct drm_i915_gem_object *obj;
@@ -307,8 +299,6 @@ i915_gem_pageflip_info(struct drm_device *dev, struct sbuf *m, void *data)
char pipe;
char plane;
- if ((dev->driver->driver_features & DRIVER_MODESET) == 0)
- return (0);
list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) {
pipe = pipe_name(crtc->pipe);
plane = plane_name(crtc->plane);
@@ -346,18 +336,17 @@ i915_gem_pageflip_info(struct drm_device *dev, struct sbuf *m, void *data)
mtx_unlock(&dev->event_lock);
}
- return (0);
+ return 0;
}
-static int
-i915_gem_request_info(struct drm_device *dev, struct sbuf *m, void *data)
+static int i915_gem_request_info(struct drm_device *dev, struct sbuf *m, void *data)
{
drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_i915_gem_request *gem_request;
int count;
if (sx_xlock_sig(&dev->dev_struct_lock))
- return (EINTR);
+ return -EINTR;
count = 0;
if (!list_empty(&dev_priv->rings[RCS].request_list)) {
@@ -401,8 +390,7 @@ i915_gem_request_info(struct drm_device *dev, struct sbuf *m, void *data)
return 0;
}
-static void
-i915_ring_seqno_info(struct sbuf *m, struct intel_ring_buffer *ring)
+static void i915_ring_seqno_info(struct sbuf *m, struct intel_ring_buffer *ring)
{
if (ring->get_seqno) {
sbuf_printf(m, "Current sequence (%s): %d\n",
@@ -410,29 +398,30 @@ i915_ring_seqno_info(struct sbuf *m, struct intel_ring_buffer *ring)
}
}
-static int
-i915_gem_seqno_info(struct drm_device *dev, struct sbuf *m, void *data)
+static int i915_gem_seqno_info(struct drm_device *dev, struct sbuf *m, void *data)
{
drm_i915_private_t *dev_priv = dev->dev_private;
int i;
if (sx_xlock_sig(&dev->dev_struct_lock))
- return (EINTR);
+ return -EINTR;
+
for (i = 0; i < I915_NUM_RINGS; i++)
i915_ring_seqno_info(m, &dev_priv->rings[i]);
+
DRM_UNLOCK(dev);
- return (0);
+
+ return 0;
}
-static int
-i915_interrupt_info(struct drm_device *dev, struct sbuf *m, void *data)
+static int i915_interrupt_info(struct drm_device *dev, struct sbuf *m, void *data)
{
drm_i915_private_t *dev_priv = dev->dev_private;
int i, pipe;
if (sx_xlock_sig(&dev->dev_struct_lock))
- return (EINTR);
+ return -EINTR;
if (IS_VALLEYVIEW(dev)) {
sbuf_printf(m, "Display IER:\t%08x\n",
@@ -515,17 +504,16 @@ i915_interrupt_info(struct drm_device *dev, struct sbuf *m, void *data)
}
DRM_UNLOCK(dev);
- return (0);
+ return 0;
}
-static int
-i915_gem_fence_regs_info(struct drm_device *dev, struct sbuf *m, void *data)
+static int i915_gem_fence_regs_info(struct drm_device *dev, struct sbuf *m, void *data)
{
drm_i915_private_t *dev_priv = dev->dev_private;
int i;
if (sx_xlock_sig(&dev->dev_struct_lock))
- return (EINTR);
+ return -EINTR;
sbuf_printf(m, "Reserved fences = %d\n", dev_priv->fence_reg_start);
sbuf_printf(m, "Total fences = %d\n", dev_priv->num_fence_regs);
@@ -541,50 +529,47 @@ i915_gem_fence_regs_info(struct drm_device *dev, struct sbuf *m, void *data)
}
DRM_UNLOCK(dev);
- return (0);
+ return 0;
}
-static int
-i915_hws_info(struct drm_device *dev, struct sbuf *m, void *data)
+static int i915_hws_info(struct drm_device *dev, struct sbuf *m, void *data)
{
drm_i915_private_t *dev_priv = dev->dev_private;
struct intel_ring_buffer *ring;
- const volatile u32 *hws;
+ const volatile u32 __iomem *hws;
int i;
ring = &dev_priv->rings[(uintptr_t)data];
hws = (volatile u32 *)ring->status_page.page_addr;
if (hws == NULL)
- return (0);
+ return 0;
for (i = 0; i < 4096 / sizeof(u32) / 4; i += 4) {
sbuf_printf(m, "0x%08x: 0x%08x 0x%08x 0x%08x 0x%08x\n",
i * 4,
hws[i], hws[i + 1], hws[i + 2], hws[i + 3]);
}
- return (0);
+ return 0;
}
-static const char *
-ring_str(int ring)
+static const char *ring_str(int ring)
{
switch (ring) {
- case RCS: return (" render");
- case VCS: return (" bsd");
- case BCS: return (" blt");
- default: return ("");
+ case RCS: return " render";
+ case VCS: return " bsd";
+ case BCS: return " blt";
+ default: return "";
}
}
-static const char *
-pin_flag(int pinned)
+static const char *pin_flag(int pinned)
{
if (pinned > 0)
- return (" P");
+ return " P";
else if (pinned < 0)
- return (" p");
+ return " p";
else
- return ("");
+ return "";
}
static const char *tiling_flag(int tiling)
@@ -607,8 +592,10 @@ static const char *purgeable_flag(int purgeable)
return purgeable ? " purgeable" : "";
}
-static void print_error_buffers(struct sbuf *m, const char *name,
- struct drm_i915_error_buffer *err, int count)
+static void print_error_buffers(struct sbuf *m,
+ const char *name,
+ struct drm_i915_error_buffer *err,
+ int count)
{
sbuf_printf(m, "%s [%d]:\n", name, count);
@@ -638,9 +625,10 @@ static void print_error_buffers(struct sbuf *m, const char *name,
}
}
-static void
-i915_ring_error_state(struct sbuf *m, struct drm_device *dev,
- struct drm_i915_error_state *error, unsigned ring)
+static void i915_ring_error_state(struct sbuf *m,
+ struct drm_device *dev,
+ struct drm_i915_error_state *error,
+ unsigned ring)
{
MPASS((ring < I915_NUM_RINGS)); /* shut up confused gcc */
@@ -672,8 +660,7 @@ i915_ring_error_state(struct sbuf *m, struct drm_device *dev,
sbuf_printf(m, " ring->tail: 0x%08x\n", error->cpu_ring_tail[ring]);
}
-static int
-i915_error_state(struct drm_device *dev, struct sbuf *m,
+static int i915_error_state(struct drm_device *dev, struct sbuf *m,
void *unused)
{
drm_i915_private_t *dev_priv = dev->dev_private;
@@ -686,9 +673,9 @@ i915_error_state(struct drm_device *dev, struct sbuf *m,
if (error != NULL)
refcount_acquire(&error->ref);
mtx_unlock(&dev_priv->error_lock);
- if (error == NULL) {
+ if (!error) {
sbuf_printf(m, "no error state collected\n");
- return (0);
+ return 0;
}
error = dev_priv->first_error;
@@ -722,9 +709,9 @@ i915_error_state(struct drm_device *dev, struct sbuf *m,
error->pinned_bo,
error->pinned_bo_count);
- for (i = 0; i < DRM_ARRAY_SIZE(error->ring); i++) {
+ for (i = 0; i < ARRAY_SIZE(error->ring); i++) {
struct drm_i915_error_object *obj;
-
+
if ((obj = error->ring[i].batchbuffer)) {
sbuf_printf(m, "%s --- gtt_offset = 0x%08x\n",
dev_priv->rings[i].name,
@@ -776,7 +763,7 @@ i915_error_state(struct drm_device *dev, struct sbuf *m,
if (refcount_release(&error->ref))
i915_error_state_free(error);
- return (0);
+ return 0;
}
static int
@@ -802,8 +789,10 @@ i915_rstdby_delays(struct drm_device *dev, struct sbuf *m, void *unused)
u16 crstanddelay;
if (sx_xlock_sig(&dev->dev_struct_lock))
- return (EINTR);
+ return -EINTR;
+
crstanddelay = I915_READ16(CRSTANDVID);
+
DRM_UNLOCK(dev);
sbuf_printf(m, "w/ctx: %d, w/o ctx: %d\n",
@@ -812,8 +801,7 @@ i915_rstdby_delays(struct drm_device *dev, struct sbuf *m, void *unused)
return 0;
}
-static int
-i915_cur_delayinfo(struct drm_device *dev, struct sbuf *m, void *unused)
+static int i915_cur_delayinfo(struct drm_device *dev, struct sbuf *m, void *unused)
{
drm_i915_private_t *dev_priv = dev->dev_private;
@@ -838,7 +826,7 @@ i915_cur_delayinfo(struct drm_device *dev, struct sbuf *m, void *unused)
/* RPSTAT1 is in the GT power well */
if (sx_xlock_sig(&dev->dev_struct_lock))
- return (EINTR);
+ return -EINTR;
gen6_gt_force_wake_get(dev_priv);
rpstat = I915_READ(GEN6_RPSTAT1);
@@ -893,50 +881,51 @@ i915_cur_delayinfo(struct drm_device *dev, struct sbuf *m, void *unused)
return 0;
}
-static int
-i915_delayfreq_table(struct drm_device *dev, struct sbuf *m, void *unused)
+static int i915_delayfreq_table(struct drm_device *dev, struct sbuf *m, void *unused)
{
drm_i915_private_t *dev_priv = dev->dev_private;
u32 delayfreq;
int i;
if (sx_xlock_sig(&dev->dev_struct_lock))
- return (EINTR);
+ return -EINTR;
+
for (i = 0; i < 16; i++) {
delayfreq = I915_READ(PXVFREQ_BASE + i * 4);
sbuf_printf(m, "P%02dVIDFREQ: 0x%08x (VID: %d)\n", i, delayfreq,
(delayfreq & PXVFREQ_PX_MASK) >> PXVFREQ_PX_SHIFT);
}
+
DRM_UNLOCK(dev);
- return (0);
+
+ return 0;
}
-static inline int
-MAP_TO_MV(int map)
+static inline int MAP_TO_MV(int map)
{
return 1250 - (map * 25);
}
-static int
-i915_inttoext_table(struct drm_device *dev, struct sbuf *m, void *unused)
+static int i915_inttoext_table(struct drm_device *dev, struct sbuf *m, void *unused)
{
drm_i915_private_t *dev_priv = dev->dev_private;
u32 inttoext;
int i;
if (sx_xlock_sig(&dev->dev_struct_lock))
- return (EINTR);
+ return -EINTR;
+
for (i = 1; i <= 32; i++) {
inttoext = I915_READ(INTTOEXT_BASE_ILK + i * 4);
sbuf_printf(m, "INTTOEXT%02d: 0x%08x\n", i, inttoext);
}
+
DRM_UNLOCK(dev);
- return (0);
+ return 0;
}
-static int
-ironlake_drpc_info(struct drm_device *dev, struct sbuf *m)
+static int ironlake_drpc_info(struct drm_device *dev, struct sbuf *m)
{
drm_i915_private_t *dev_priv = dev->dev_private;
u32 rgvmodectl;
@@ -944,10 +933,12 @@ ironlake_drpc_info(struct drm_device *dev, struct sbuf *m)
u16 crstandvid;
if (sx_xlock_sig(&dev->dev_struct_lock))
- return (EINTR);
+ return -EINTR;
+
rgvmodectl = I915_READ(MEMMODECTL);
rstdbyctl = I915_READ(RSTDBYCTL);
crstandvid = I915_READ16(CRSTANDVID);
+
DRM_UNLOCK(dev);
sbuf_printf(m, "HD boost: %s\n", (rgvmodectl & MEMMODE_BOOST_EN) ?
@@ -998,16 +989,16 @@ ironlake_drpc_info(struct drm_device *dev, struct sbuf *m)
return 0;
}
-static int
-gen6_drpc_info(struct drm_device *dev, struct sbuf *m)
+static int gen6_drpc_info(struct drm_device *dev, struct sbuf *m)
{
drm_i915_private_t *dev_priv = dev->dev_private;
u32 rpmodectl1, gt_core_status, rcctl1;
unsigned forcewake_count;
int count=0;
+
if (sx_xlock_sig(&dev->dev_struct_lock))
- return (EINTR);
+ return -EINTR;
mtx_lock(&dev_priv->gt_lock);
forcewake_count = dev_priv->forcewake_count;
@@ -1019,7 +1010,7 @@ gen6_drpc_info(struct drm_device *dev, struct sbuf *m)
} else {
/* NB: we cannot use forcewake, else we read the wrong values */
while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK) & 1))
- DRM_UDELAY(10);
+ udelay(10);
sbuf_printf(m, "RC information accurate: %s\n", yesno(count < 51));
}
@@ -1087,12 +1078,12 @@ static int i915_drpc_info(struct drm_device *dev, struct sbuf *m, void *unused)
{
if (IS_GEN6(dev) || IS_GEN7(dev))
- return (gen6_drpc_info(dev, m));
+ return gen6_drpc_info(dev, m);
else
- return (ironlake_drpc_info(dev, m));
+ return ironlake_drpc_info(dev, m);
}
-static int
-i915_fbc_status(struct drm_device *dev, struct sbuf *m, void *unused)
+
+static int i915_fbc_status(struct drm_device *dev, struct sbuf *m, void *unused)
{
drm_i915_private_t *dev_priv = dev->dev_private;
@@ -1134,8 +1125,7 @@ i915_fbc_status(struct drm_device *dev, struct sbuf *m, void *unused)
return 0;
}
-static int
-i915_sr_status(struct drm_device *dev, struct sbuf *m, void *unused)
+static int i915_sr_status(struct drm_device *dev, struct sbuf *m, void *unused)
{
drm_i915_private_t *dev_priv = dev->dev_private;
bool sr_enabled = false;
@@ -1152,7 +1142,31 @@ i915_sr_status(struct drm_device *dev, struct sbuf *m, void *unused)
sbuf_printf(m, "self-refresh: %s",
sr_enabled ? "enabled" : "disabled");
- return (0);
+ return 0;
+}
+
+static int i915_emon_status(struct drm_device *dev, struct sbuf *m, void *unused)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ unsigned long temp, chipset, gfx;
+
+ if (!IS_GEN5(dev))
+ return -ENODEV;
+
+ if (sx_xlock_sig(&dev->dev_struct_lock))
+ return -EINTR;
+
+ temp = i915_mch_val(dev_priv);
+ chipset = i915_chipset_val(dev_priv);
+ gfx = i915_gfx_val(dev_priv);
+ DRM_UNLOCK(dev);
+
+ sbuf_printf(m, "GMCH temp: %ld\n", temp);
+ sbuf_printf(m, "Chipset power: %ld\n", chipset);
+ sbuf_printf(m, "GFX power: %ld\n", gfx);
+ sbuf_printf(m, "Total power: %ld\n", chipset + gfx);
+
+ return 0;
}
static int i915_ring_freq_table(struct drm_device *dev, struct sbuf *m,
@@ -1163,11 +1177,11 @@ static int i915_ring_freq_table(struct drm_device *dev, struct sbuf *m,
if (!(IS_GEN6(dev) || IS_GEN7(dev))) {
sbuf_printf(m, "unsupported on this chipset");
- return (0);
+ return 0;
}
if (sx_xlock_sig(&dev->dev_struct_lock))
- return (EINTR);
+ return -EINTR;
sbuf_printf(m, "GPU freq (MHz)\tEffective CPU freq (MHz)\n");
@@ -1188,79 +1202,54 @@ static int i915_ring_freq_table(struct drm_device *dev, struct sbuf *m,
DRM_UNLOCK(dev);
- return (0);
+ return 0;
}
-static int
-i915_emon_status(struct drm_device *dev, struct sbuf *m, void *unused)
+static int i915_gfxec(struct drm_device *dev, struct sbuf *m, void *unused)
{
drm_i915_private_t *dev_priv = dev->dev_private;
- unsigned long temp, chipset, gfx;
-
- if (!IS_GEN5(dev)) {
- sbuf_printf(m, "Not supported\n");
- return (0);
- }
if (sx_xlock_sig(&dev->dev_struct_lock))
- return (EINTR);
- temp = i915_mch_val(dev_priv);
- chipset = i915_chipset_val(dev_priv);
- gfx = i915_gfx_val(dev_priv);
- DRM_UNLOCK(dev);
-
- sbuf_printf(m, "GMCH temp: %ld\n", temp);
- sbuf_printf(m, "Chipset power: %ld\n", chipset);
- sbuf_printf(m, "GFX power: %ld\n", gfx);
- sbuf_printf(m, "Total power: %ld\n", chipset + gfx);
+ return -EINTR;
- return (0);
-}
-
-static int
-i915_gfxec(struct drm_device *dev, struct sbuf *m, void *unused)
-{
- drm_i915_private_t *dev_priv = dev->dev_private;
-
- if (sx_xlock_sig(&dev->dev_struct_lock))
- return (EINTR);
sbuf_printf(m, "GFXEC: %ld\n", (unsigned long)I915_READ(0x112f4));
+
DRM_UNLOCK(dev);
- return (0);
+ return 0;
}
#if 0
-static int
-i915_opregion(struct drm_device *dev, struct sbuf *m, void *unused)
+static int i915_opregion(struct drm_device *dev, struct sbuf *m, void *unused)
{
drm_i915_private_t *dev_priv = dev->dev_private;
struct intel_opregion *opregion = &dev_priv->opregion;
if (sx_xlock_sig(&dev->dev_struct_lock))
- return (EINTR);
+ return -EINTR;
+
if (opregion->header)
seq_write(m, opregion->header, OPREGION_SIZE);
+
DRM_UNLOCK(dev);
return 0;
}
#endif
-static int
-i915_gem_framebuffer_info(struct drm_device *dev, struct sbuf *m, void *data)
+static int i915_gem_framebuffer_info(struct drm_device *dev, struct sbuf *m, void *data)
{
drm_i915_private_t *dev_priv = dev->dev_private;
struct intel_fbdev *ifbdev;
struct intel_framebuffer *fb;
if (sx_xlock_sig(&dev->dev_struct_lock))
- return (EINTR);
+ return -EINTR;
ifbdev = dev_priv->fbdev;
if (ifbdev == NULL) {
DRM_UNLOCK(dev);
- return (0);
+ return 0;
}
fb = to_intel_framebuffer(ifbdev->helper.fb);
@@ -1287,22 +1276,18 @@ i915_gem_framebuffer_info(struct drm_device *dev, struct sbuf *m, void *data)
DRM_UNLOCK(dev);
- return (0);
+ return 0;
}
-static int
-i915_context_status(struct drm_device *dev, struct sbuf *m, void *data)
+static int i915_context_status(struct drm_device *dev, struct sbuf *m, void *data)
{
drm_i915_private_t *dev_priv;
int ret;
- if ((dev->driver->driver_features & DRIVER_MODESET) == 0)
- return (0);
-
dev_priv = dev->dev_private;
ret = sx_xlock_sig(&dev->mode_config.mutex);
if (ret != 0)
- return (EINTR);
+ return -EINTR;
if (dev_priv->pwrctx != NULL) {
sbuf_printf(m, "power context ");
@@ -1318,11 +1303,10 @@ i915_context_status(struct drm_device *dev, struct sbuf *m, void *data)
sx_xunlock(&dev->mode_config.mutex);
- return (0);
+ return 0;
}
-static int
-i915_gen6_forcewake_count_info(struct drm_device *dev, struct sbuf *m,
+static int i915_gen6_forcewake_count_info(struct drm_device *dev, struct sbuf *m,
void *data)
{
struct drm_i915_private *dev_priv;
@@ -1335,11 +1319,10 @@ i915_gen6_forcewake_count_info(struct drm_device *dev, struct sbuf *m,
sbuf_printf(m, "forcewake count = %u\n", forcewake_count);
- return (0);
+ return 0;
}
-static const char *
-swizzle_string(unsigned swizzle)
+static const char *swizzle_string(unsigned swizzle)
{
switch(swizzle) {
@@ -1364,8 +1347,7 @@ swizzle_string(unsigned swizzle)
return "bug";
}
-static int
-i915_swizzle_info(struct drm_device *dev, struct sbuf *m, void *data)
+static int i915_swizzle_info(struct drm_device *dev, struct sbuf *m, void *data)
{
struct drm_i915_private *dev_priv;
int ret;
@@ -1373,7 +1355,7 @@ i915_swizzle_info(struct drm_device *dev, struct sbuf *m, void *data)
dev_priv = dev->dev_private;
ret = sx_xlock_sig(&dev->dev_struct_lock);
if (ret != 0)
- return (EINTR);
+ return -EINTR;
sbuf_printf(m, "bit6 swizzle for X-tiling = %s\n",
swizzle_string(dev_priv->mm.bit_6_swizzle_x));
@@ -1400,14 +1382,13 @@ i915_swizzle_info(struct drm_device *dev, struct sbuf *m, void *data)
I915_READ(ARB_MODE));
sbuf_printf(m, "DISP_ARB_CTL = 0x%08x\n",
I915_READ(DISP_ARB_CTL));
- }
+ }
DRM_UNLOCK(dev);
- return (0);
+ return 0;
}
-static int
-i915_ppgtt_info(struct drm_device *dev, struct sbuf *m, void *data)
+static int i915_ppgtt_info(struct drm_device *dev, struct sbuf *m, void *data)
{
struct drm_i915_private *dev_priv;
struct intel_ring_buffer *ring;
@@ -1417,7 +1398,7 @@ i915_ppgtt_info(struct drm_device *dev, struct sbuf *m, void *data)
ret = sx_xlock_sig(&dev->dev_struct_lock);
if (ret != 0)
- return (EINTR);
+ return -EINTR;
if (INTEL_INFO(dev)->gen == 6)
sbuf_printf(m, "GFX_MODE: 0x%08x\n", I915_READ(GFX_MODE));
@@ -1440,7 +1421,7 @@ i915_ppgtt_info(struct drm_device *dev, struct sbuf *m, void *data)
sbuf_printf(m, "ECOCHK: 0x%08x\n", I915_READ(GAM_ECOCHK));
DRM_UNLOCK(dev);
- return (0);
+ return 0;
}
static int i915_dpio_info(struct drm_device *dev, struct sbuf *m, void *data)
@@ -1457,7 +1438,7 @@ static int i915_dpio_info(struct drm_device *dev, struct sbuf *m, void *data)
ret = sx_xlock_sig(&dev->mode_config.mutex);
if (ret != 0)
- return (EINTR);
+ return -EINTR;
sbuf_printf(m, "DPIO_CTL: 0x%08x\n", I915_READ(DPIO_CTL));
@@ -1663,7 +1644,7 @@ i915_info_sysctl_handler(SYSCTL_HANDLER_ARGS)
if (error != 0)
return (error);
sbuf_new_for_sysctl(&m, NULL, 128, req);
- error = i915_info_sysctl_list[thunk->idx].ptr(dev, &m,
+ error = -i915_info_sysctl_list[thunk->idx].ptr(dev, &m,
thunk->arg);
if (error == 0)
error = sbuf_finish(&m);
@@ -1697,9 +1678,9 @@ i915_sysctl_init(struct drm_device *dev, struct sysctl_ctx_list *ctx,
struct i915_info_sysctl_thunk *thunks;
int i, error;
- thunks = malloc(sizeof(*thunks) * DRM_ARRAY_SIZE(i915_info_sysctl_list),
+ thunks = malloc(sizeof(*thunks) * ARRAY_SIZE(i915_info_sysctl_list),
DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
- for (i = 0; i < DRM_ARRAY_SIZE(i915_info_sysctl_list); i++) {
+ for (i = 0; i < ARRAY_SIZE(i915_info_sysctl_list); i++) {
thunks[i].dev = dev;
thunks[i].idx = i;
thunks[i].arg = i915_info_sysctl_list[i].data;
@@ -1708,15 +1689,15 @@ i915_sysctl_init(struct drm_device *dev, struct sysctl_ctx_list *ctx,
info = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(top), OID_AUTO, "info",
CTLFLAG_RW, NULL, NULL);
if (info == NULL)
- return (ENOMEM);
- for (i = 0; i < DRM_ARRAY_SIZE(i915_info_sysctl_list); i++) {
+ return (-ENOMEM);
+ for (i = 0; i < ARRAY_SIZE(i915_info_sysctl_list); i++) {
oid = SYSCTL_ADD_OID(ctx, SYSCTL_CHILDREN(info), OID_AUTO,
i915_info_sysctl_list[i].name, CTLTYPE_STRING |
(i915_info_sysctl_list[i].ptr_w != NULL ? CTLFLAG_RW :
CTLFLAG_RD),
&thunks[i], 0, i915_info_sysctl_handler, "A", NULL);
if (oid == NULL)
- return (ENOMEM);
+ return (-ENOMEM);
}
oid = SYSCTL_ADD_LONG(ctx, SYSCTL_CHILDREN(info), OID_AUTO,
"i915_gem_wired_pages", CTLFLAG_RD, &i915_gem_wired_pages_cnt,
@@ -1725,34 +1706,34 @@ i915_sysctl_init(struct drm_device *dev, struct sysctl_ctx_list *ctx,
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, dev, 0,
i915_debug_set_wedged, "I", NULL);
if (oid == NULL)
- return (ENOMEM);
+ return (-ENOMEM);
oid = SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(top), OID_AUTO, "max_freq",
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, dev, 0, i915_max_freq,
"I", NULL);
if (oid == NULL)
- return (ENOMEM);
+ return (-ENOMEM);
oid = SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(top), OID_AUTO,
"cache_sharing", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, dev,
0, i915_cache_sharing, "I", NULL);
if (oid == NULL)
- return (ENOMEM);
+ return (-ENOMEM);
oid = SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(top), OID_AUTO,
"stop_rings", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, dev,
0, i915_stop_rings, "I", NULL);
if (oid == NULL)
- return (ENOMEM);
+ return (-ENOMEM);
oid = SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(top), OID_AUTO, "sync_exec",
CTLFLAG_RW, &i915_gem_sync_exec_requests, 0, NULL);
if (oid == NULL)
- return (ENOMEM);
+ return (-ENOMEM);
oid = SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(top), OID_AUTO, "fix_mi",
CTLFLAG_RW, &i915_fix_mi_batchbuffer_end, 0, NULL);
if (oid == NULL)
- return (ENOMEM);
+ return (-ENOMEM);
oid = SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(top), OID_AUTO, "intr_pf",
CTLFLAG_RW, &i915_intr_pf, 0, NULL);
if (oid == NULL)
- return (ENOMEM);
+ return (-ENOMEM);
error = drm_add_busid_modesetting(dev, ctx, top);
if (error != 0)
diff --git a/sys/dev/drm2/i915/i915_dma.c b/sys/dev/drm2/i915/i915_dma.c
index 58dcae7..910b35a 100644
--- a/sys/dev/drm2/i915/i915_dma.c
+++ b/sys/dev/drm2/i915/i915_dma.c
@@ -65,12 +65,9 @@ intel_read_legacy_status_page(struct drm_i915_private *dev_priv, int reg)
#define READ_BREADCRUMB(dev_priv) READ_HWSP(dev_priv, I915_BREADCRUMB_INDEX)
#define I915_BREADCRUMB_INDEX 0x21
-static int i915_driver_unload_int(struct drm_device *dev, bool locked);
-
void i915_update_dri1_breadcrumb(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;
-#if 0
struct drm_i915_master_private *master_priv;
if (dev->primary->master) {
@@ -79,11 +76,6 @@ void i915_update_dri1_breadcrumb(struct drm_device *dev)
master_priv->sarea_priv->last_dispatch =
READ_BREADCRUMB(dev_priv);
}
-#else
- if (dev_priv->sarea_priv)
- dev_priv->sarea_priv->last_dispatch =
- READ_BREADCRUMB(dev_priv);
-#endif
}
static void i915_write_hws_pga(struct drm_device *dev)
@@ -112,10 +104,8 @@ static int i915_init_phys_hws(struct drm_device *dev)
* of allocation is used on <= 965 hardware, that has several
* erratas regarding the use of physical memory > 4 GB.
*/
- DRM_UNLOCK(dev);
dev_priv->status_page_dmah =
- drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff);
- DRM_LOCK(dev);
+ drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, BUS_SPACE_MAXADDR);
if (!dev_priv->status_page_dmah) {
DRM_ERROR("Can not allocate hardware status page\n");
return -ENOMEM;
@@ -160,6 +150,7 @@ static void i915_free_hws(struct drm_device *dev)
void i915_kernel_lost_context(struct drm_device * dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_i915_master_private *master_priv;
struct intel_ring_buffer *ring = LP_RING(dev_priv);
/*
@@ -175,15 +166,12 @@ void i915_kernel_lost_context(struct drm_device * dev)
if (ring->space < 0)
ring->space += ring->size;
-#if 1
- KIB_NOTYET();
-#else
if (!dev->primary->master)
return;
-#endif
- if (ring->head == ring->tail && dev_priv->sarea_priv)
- dev_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY;
+ master_priv = dev->primary->master->driver_priv;
+ if (ring->head == ring->tail && master_priv->sarea_priv)
+ master_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY;
}
static int i915_dma_cleanup(struct drm_device * dev)
@@ -199,8 +187,10 @@ static int i915_dma_cleanup(struct drm_device * dev)
if (dev->irq_enabled)
drm_irq_uninstall(dev);
+ DRM_LOCK(dev);
for (i = 0; i < I915_NUM_RINGS; i++)
intel_cleanup_ring_buffer(&dev_priv->rings[i]);
+ DRM_UNLOCK(dev);
/* Clear the HWS virtual address at teardown */
if (I915_NEED_GFX_HWS(dev))
@@ -212,18 +202,17 @@ static int i915_dma_cleanup(struct drm_device * dev)
static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
{
drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
int ret;
- dev_priv->sarea = drm_getsarea(dev);
- if (!dev_priv->sarea) {
- DRM_ERROR("can not find sarea!\n");
- i915_dma_cleanup(dev);
- return -EINVAL;
+ master_priv->sarea = drm_getsarea(dev);
+ if (master_priv->sarea) {
+ master_priv->sarea_priv = (drm_i915_sarea_t *)
+ ((u8 *)master_priv->sarea->handle + init->sarea_priv_offset);
+ } else {
+ DRM_DEBUG_DRIVER("sarea not found assuming DRI2 userspace\n");
}
- dev_priv->sarea_priv = (drm_i915_sarea_t *)
- ((u8 *) dev_priv->sarea->virtual + init->sarea_priv_offset);
-
if (init->ring_size != 0) {
if (LP_RING(dev_priv)->obj != NULL) {
i915_dma_cleanup(dev);
@@ -245,7 +234,8 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
dev_priv->back_offset = init->back_offset;
dev_priv->front_offset = init->front_offset;
dev_priv->current_page = 0;
- dev_priv->sarea_priv->pf_current_page = 0;
+ if (master_priv->sarea_priv)
+ master_priv->sarea_priv->pf_current_page = 0;
/* Allow hardware batchbuffers unless told otherwise.
*/
@@ -485,11 +475,12 @@ i915_emit_box_p(struct drm_device *dev, struct drm_clip_rect *box,
static void i915_emit_breadcrumb(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
if (++dev_priv->counter > 0x7FFFFFFFUL)
dev_priv->counter = 0;
- if (dev_priv->sarea_priv)
- dev_priv->sarea_priv->last_enqueue = dev_priv->counter;
+ if (master_priv->sarea_priv)
+ master_priv->sarea_priv->last_enqueue = dev_priv->counter;
if (BEGIN_LP_RING(4) == 0) {
OUT_RING(MI_STORE_DWORD_INDEX);
@@ -594,15 +585,17 @@ i915_dispatch_batchbuffer(struct drm_device * dev,
static int i915_dispatch_flip(struct drm_device * dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_i915_master_private *master_priv =
+ dev->primary->master->driver_priv;
int ret;
- if (!dev_priv->sarea_priv)
+ if (!master_priv->sarea_priv)
return -EINVAL;
DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
__func__,
dev_priv->current_page,
- dev_priv->sarea_priv->pf_current_page);
+ master_priv->sarea_priv->pf_current_page);
i915_kernel_lost_context(dev);
@@ -628,10 +621,7 @@ static int i915_dispatch_flip(struct drm_device * dev)
ADVANCE_LP_RING();
- if (++dev_priv->counter > 0x7FFFFFFFUL)
- dev_priv->counter = 0;
- if (dev_priv->sarea_priv)
- dev_priv->sarea_priv->last_enqueue = dev_priv->counter;
+ master_priv->sarea_priv->last_enqueue = dev_priv->counter++;
if (BEGIN_LP_RING(4) == 0) {
OUT_RING(MI_STORE_DWORD_INDEX);
@@ -641,7 +631,7 @@ static int i915_dispatch_flip(struct drm_device * dev)
ADVANCE_LP_RING();
}
- dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
+ master_priv->sarea_priv->pf_current_page = dev_priv->current_page;
return 0;
}
@@ -675,7 +665,9 @@ int i915_batchbuffer(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
- drm_i915_sarea_t *sarea_priv;
+ struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
+ drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
+ master_priv->sarea_priv;
drm_i915_batchbuffer_t *batch = data;
struct drm_clip_rect *cliprects;
size_t cliplen;
@@ -685,7 +677,6 @@ int i915_batchbuffer(struct drm_device *dev, void *data,
DRM_ERROR("Batchbuffer ioctl disabled\n");
return -EINVAL;
}
- DRM_UNLOCK(dev);
DRM_DEBUG("i915 batchbuffer, start %x used %d cliprects %d\n",
batch->start, batch->used, batch->num_cliprects);
@@ -700,18 +691,16 @@ int i915_batchbuffer(struct drm_device *dev, void *data,
ret = -copyin(batch->cliprects, cliprects,
batch->num_cliprects * sizeof(struct drm_clip_rect));
- if (ret != 0) {
- DRM_LOCK(dev);
+ if (ret != 0)
goto fail_free;
- }
} else
cliprects = NULL;
DRM_LOCK(dev);
RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
ret = i915_dispatch_batchbuffer(dev, batch, cliprects);
+ DRM_UNLOCK(dev);
- sarea_priv = (drm_i915_sarea_t *)dev_priv->sarea_priv;
if (sarea_priv)
sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
@@ -724,7 +713,9 @@ int i915_cmdbuffer(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
- drm_i915_sarea_t *sarea_priv;
+ struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
+ drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
+ master_priv->sarea_priv;
drm_i915_cmdbuffer_t *cmdbuf = data;
struct drm_clip_rect *cliprects = NULL;
void *batch_data;
@@ -739,15 +730,11 @@ int i915_cmdbuffer(struct drm_device *dev, void *data,
if (cmdbuf->num_cliprects < 0)
return -EINVAL;
- DRM_UNLOCK(dev);
-
batch_data = malloc(cmdbuf->sz, DRM_MEM_DMA, M_WAITOK);
ret = -copyin(cmdbuf->buf, batch_data, cmdbuf->sz);
- if (ret != 0) {
- DRM_LOCK(dev);
+ if (ret != 0)
goto fail_batch_free;
- }
if (cmdbuf->num_cliprects) {
cliprects = malloc(cmdbuf->num_cliprects *
@@ -755,21 +742,19 @@ int i915_cmdbuffer(struct drm_device *dev, void *data,
M_WAITOK | M_ZERO);
ret = -copyin(cmdbuf->cliprects, cliprects,
cmdbuf->num_cliprects * sizeof(struct drm_clip_rect));
- if (ret != 0) {
- DRM_LOCK(dev);
+ if (ret != 0)
goto fail_clip_free;
- }
}
DRM_LOCK(dev);
RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
ret = i915_dispatch_cmdbuffer(dev, cmdbuf, cliprects, batch_data);
+ DRM_UNLOCK(dev);
if (ret) {
DRM_ERROR("i915_dispatch_cmdbuffer failed\n");
goto fail_clip_free;
}
- sarea_priv = (drm_i915_sarea_t *)dev_priv->sarea_priv;
if (sarea_priv)
sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
@@ -783,9 +768,7 @@ fail_batch_free:
static int i915_emit_irq(struct drm_device * dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;
-#if 0
struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
-#endif
i915_kernel_lost_context(dev);
@@ -794,13 +777,8 @@ static int i915_emit_irq(struct drm_device * dev)
dev_priv->counter++;
if (dev_priv->counter > 0x7FFFFFFFUL)
dev_priv->counter = 1;
-#if 0
if (master_priv->sarea_priv)
master_priv->sarea_priv->last_enqueue = dev_priv->counter;
-#else
- if (dev_priv->sarea_priv)
- dev_priv->sarea_priv->last_enqueue = dev_priv->counter;
-#endif
if (BEGIN_LP_RING(4) == 0) {
OUT_RING(MI_STORE_DWORD_INDEX);
@@ -816,16 +794,13 @@ static int i915_emit_irq(struct drm_device * dev)
static int i915_wait_irq(struct drm_device * dev, int irq_nr)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-#if 0
struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
-#endif
int ret;
struct intel_ring_buffer *ring = LP_RING(dev_priv);
DRM_DEBUG("irq_nr=%d breadcrumb=%d\n", irq_nr,
READ_BREADCRUMB(dev_priv));
-#if 0
if (READ_BREADCRUMB(dev_priv) >= irq_nr) {
if (master_priv->sarea_priv)
master_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
@@ -834,30 +809,18 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr)
if (master_priv->sarea_priv)
master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
-#else
- if (READ_BREADCRUMB(dev_priv) >= irq_nr) {
- if (dev_priv->sarea_priv) {
- dev_priv->sarea_priv->last_dispatch =
- READ_BREADCRUMB(dev_priv);
- }
- return 0;
- }
-
- if (dev_priv->sarea_priv)
- dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
-#endif
ret = 0;
mtx_lock(&dev_priv->irq_lock);
if (ring->irq_get(ring)) {
- DRM_UNLOCK(dev);
while (ret == 0 && READ_BREADCRUMB(dev_priv) < irq_nr) {
ret = -msleep(ring, &dev_priv->irq_lock, PCATCH,
"915wtq", 3 * hz);
+ if (ret == -ERESTART)
+ ret = -ERESTARTSYS;
}
ring->irq_put(ring);
mtx_unlock(&dev_priv->irq_lock);
- DRM_LOCK(dev);
} else {
mtx_unlock(&dev_priv->irq_lock);
if (_intel_wait_for(dev, READ_BREADCRUMB(dev_priv) >= irq_nr,
@@ -977,7 +940,9 @@ static int i915_flip_bufs(struct drm_device *dev, void *data,
RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
+ DRM_LOCK(dev);
ret = i915_dispatch_flip(dev);
+ DRM_UNLOCK(dev);
return ret;
}
@@ -1200,6 +1165,31 @@ cleanup_vga_switcheroo:
return (ret);
}
+int i915_master_create(struct drm_device *dev, struct drm_master *master)
+{
+ struct drm_i915_master_private *master_priv;
+
+ master_priv = malloc(sizeof(*master_priv), DRM_MEM_DMA,
+ M_NOWAIT | M_ZERO);
+ if (!master_priv)
+ return -ENOMEM;
+
+ master->driver_priv = master_priv;
+ return 0;
+}
+
+void i915_master_destroy(struct drm_device *dev, struct drm_master *master)
+{
+ struct drm_i915_master_private *master_priv = master->driver_priv;
+
+ if (!master_priv)
+ return;
+
+ free(master_priv, DRM_MEM_DMA);
+
+ master->driver_priv = NULL;
+}
+
static int
i915_get_bridge_dev(struct drm_device *dev)
{
@@ -1250,10 +1240,10 @@ intel_alloc_mchbar_resource(struct drm_device *dev)
#endif
/* Get some space for it */
- vga = device_get_parent(dev->device);
+ vga = device_get_parent(dev->dev);
dev_priv->mch_res_rid = 0x100;
dev_priv->mch_res = BUS_ALLOC_RESOURCE(device_get_parent(vga),
- dev->device, SYS_RES_MEMORY, &dev_priv->mch_res_rid, 0, ~0UL,
+ dev->dev, SYS_RES_MEMORY, &dev_priv->mch_res_rid, 0, ~0UL,
MCHBAR_SIZE, RF_ACTIVE | RF_SHAREABLE);
if (dev_priv->mch_res == NULL) {
DRM_ERROR("failed mchbar resource alloc\n");
@@ -1340,10 +1330,10 @@ intel_teardown_mchbar(struct drm_device *dev)
}
if (dev_priv->mch_res != NULL) {
- vga = device_get_parent(dev->device);
- BUS_DEACTIVATE_RESOURCE(device_get_parent(vga), dev->device,
+ vga = device_get_parent(dev->dev);
+ BUS_DEACTIVATE_RESOURCE(device_get_parent(vga), dev->dev,
SYS_RES_MEMORY, dev_priv->mch_res_rid, dev_priv->mch_res);
- BUS_RELEASE_RESOURCE(device_get_parent(vga), dev->device,
+ BUS_RELEASE_RESOURCE(device_get_parent(vga), dev->dev,
SYS_RES_MEMORY, dev_priv->mch_res_rid, dev_priv->mch_res);
dev_priv->mch_res = NULL;
}
@@ -1393,6 +1383,11 @@ i915_driver_load(struct drm_device *dev, unsigned long flags)
ret = drm_addmap(dev, base, size, _DRM_REGISTERS,
_DRM_KERNEL | _DRM_DRIVER, &dev_priv->mmio_map);
+ if (ret != 0) {
+ DRM_ERROR("Failed to allocate mmio_map: %d\n", ret);
+ free(dev_priv, DRM_MEM_DRIVER);
+ return (ret);
+ }
dev_priv->tq = taskqueue_create("915", M_WAITOK,
taskqueue_thread_enqueue, &dev_priv->tq);
@@ -1413,13 +1408,26 @@ i915_driver_load(struct drm_device *dev, unsigned long flags)
i915_gem_load(dev);
+ /* On the 945G/GM, the chipset reports the MSI capability on the
+ * integrated graphics even though the support isn't actually there
+ * according to the published specs. It doesn't appear to function
+ * correctly in testing on 945G.
+ * This may be a side effect of MSI having been made available for PEG
+ * and the registers being closely associated.
+ *
+ * According to chipset errata, on the 965GM, MSI interrupts may
+ * be lost or delayed, but we use them anyways to avoid
+ * stuck interrupts on some machines.
+ */
+ if (!IS_I945G(dev) && !IS_I945GM(dev))
+ drm_pci_enable_msi(dev);
+
/* Init HWS */
if (!I915_NEED_GFX_HWS(dev)) {
ret = i915_init_phys_hws(dev);
if (ret != 0) {
drm_rmmap(dev, dev_priv->mmio_map);
- drm_free(dev_priv, sizeof(struct drm_i915_private),
- DRM_MEM_DRIVER);
+ free(dev_priv, DRM_MEM_DRIVER);
return ret;
}
}
@@ -1443,9 +1451,7 @@ i915_driver_load(struct drm_device *dev, unsigned long flags)
intel_detect_pch(dev);
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
- DRM_UNLOCK(dev);
ret = i915_load_modeset_init(dev);
- DRM_LOCK(dev);
if (ret < 0) {
DRM_ERROR("failed to init modeset\n");
goto out_gem_unload;
@@ -1465,31 +1471,27 @@ i915_driver_load(struct drm_device *dev, unsigned long flags)
out_gem_unload:
/* XXXKIB */
- (void) i915_driver_unload_int(dev, true);
+ (void) i915_driver_unload(dev);
return (ret);
}
-static int
-i915_driver_unload_int(struct drm_device *dev, bool locked)
+int
+i915_driver_unload(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
int ret;
- if (!locked)
- DRM_LOCK(dev);
+ DRM_LOCK(dev);
ret = i915_gpu_idle(dev);
if (ret)
DRM_ERROR("failed to idle hardware: %d\n", ret);
i915_gem_retire_requests(dev);
- if (!locked)
- DRM_UNLOCK(dev);
+ DRM_UNLOCK(dev);
i915_free_hws(dev);
intel_teardown_mchbar(dev);
- if (locked)
- DRM_UNLOCK(dev);
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
intel_fbdev_fini(dev);
intel_modeset_cleanup(dev);
@@ -1501,19 +1503,17 @@ i915_driver_unload_int(struct drm_device *dev, bool locked)
i915_destroy_error_state(dev);
- intel_opregion_fini(dev);
+ if (dev->msi_enabled)
+ drm_pci_disable_msi(dev);
- if (locked)
- DRM_LOCK(dev);
+ intel_opregion_fini(dev);
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
- if (!locked)
- DRM_LOCK(dev);
+ DRM_LOCK(dev);
i915_gem_free_all_phys_object(dev);
i915_gem_cleanup_ringbuffer(dev);
i915_gem_context_fini(dev);
- if (!locked)
- DRM_UNLOCK(dev);
+ DRM_UNLOCK(dev);
i915_gem_cleanup_aliasing_ppgtt(dev);
#if 1
KIB_NOTYET();
@@ -1536,7 +1536,7 @@ i915_driver_unload_int(struct drm_device *dev, bool locked)
if (dev_priv->tq != NULL)
taskqueue_free(dev_priv->tq);
- bus_generic_detach(dev->device);
+ bus_generic_detach(dev->dev);
drm_rmmap(dev, dev_priv->mmio_map);
intel_teardown_gmbus(dev);
@@ -1544,20 +1544,12 @@ i915_driver_unload_int(struct drm_device *dev, bool locked)
mtx_destroy(&dev_priv->error_lock);
mtx_destroy(&dev_priv->error_completion_lock);
mtx_destroy(&dev_priv->rps_lock);
- drm_free(dev->dev_private, sizeof(drm_i915_private_t),
- DRM_MEM_DRIVER);
+ free(dev->dev_private, DRM_MEM_DRIVER);
return (0);
}
int
-i915_driver_unload(struct drm_device *dev)
-{
-
- return (i915_driver_unload_int(dev, true));
-}
-
-int
i915_driver_open(struct drm_device *dev, struct drm_file *file_priv)
{
struct drm_i915_file_private *i915_file_priv;
@@ -1604,7 +1596,7 @@ void i915_driver_postclose(struct drm_device *dev, struct drm_file *file_priv)
struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv;
mtx_destroy(&i915_file_priv->mm.lck);
- drm_free(i915_file_priv, sizeof(*i915_file_priv), DRM_MEM_FILES);
+ free(i915_file_priv, DRM_MEM_FILES);
}
struct drm_ioctl_desc i915_ioctls[] = {
@@ -1625,24 +1617,24 @@ struct drm_ioctl_desc i915_ioctls[] = {
DRM_IOCTL_DEF(DRM_I915_GET_VBLANK_PIPE, i915_vblank_pipe_get, DRM_AUTH ),
DRM_IOCTL_DEF(DRM_I915_VBLANK_SWAP, i915_vblank_swap, DRM_AUTH),
DRM_IOCTL_DEF(DRM_I915_HWS_ADDR, i915_set_status_page, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_I915_GEM_INIT, i915_gem_init_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF(DRM_I915_GEM_INIT, i915_gem_init_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH | DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER2, i915_gem_execbuffer2, DRM_AUTH | DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_I915_GEM_PIN, i915_gem_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_I915_GEM_UNPIN, i915_gem_unpin_ioctl, DRM_AUTH|DRM_ROOT_ONLY|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_I915_GEM_THROTTLE, i915_gem_throttle_ioctl, DRM_AUTH),
- DRM_IOCTL_DEF(DRM_I915_GEM_ENTERVT, i915_gem_entervt_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_I915_GEM_LEAVEVT, i915_gem_leavevt_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_I915_GEM_CREATE, i915_gem_create_ioctl, 0),
+ DRM_IOCTL_DEF(DRM_I915_GEM_THROTTLE, i915_gem_throttle_ioctl, DRM_AUTH|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_I915_GEM_ENTERVT, i915_gem_entervt_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_I915_GEM_LEAVEVT, i915_gem_leavevt_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_I915_GEM_CREATE, i915_gem_create_ioctl, DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_I915_GEM_PREAD, i915_gem_pread_ioctl, DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_I915_GEM_PWRITE, i915_gem_pwrite_ioctl, DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_I915_GEM_MMAP, i915_gem_mmap_ioctl, 0),
+ DRM_IOCTL_DEF(DRM_I915_GEM_MMAP, i915_gem_mmap_ioctl, DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_I915_GEM_MMAP_GTT, i915_gem_mmap_gtt_ioctl, DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_I915_GEM_SET_DOMAIN, i915_gem_set_domain_ioctl, DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_I915_GEM_SW_FINISH, i915_gem_sw_finish_ioctl, DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_I915_GEM_SET_TILING, i915_gem_set_tiling, 0),
- DRM_IOCTL_DEF(DRM_I915_GEM_GET_TILING, i915_gem_get_tiling, 0),
+ DRM_IOCTL_DEF(DRM_I915_GEM_SET_TILING, i915_gem_set_tiling, DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_I915_GEM_GET_TILING, i915_gem_get_tiling, DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_I915_GEM_GET_APERTURE, i915_gem_get_aperture_ioctl, DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_I915_GET_PIPE_FROM_CRTC_ID, intel_get_pipe_from_crtc_id, DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_I915_GEM_MADVISE, i915_gem_madvise_ioctl, DRM_UNLOCKED),
@@ -1655,14 +1647,18 @@ struct drm_ioctl_desc i915_ioctls[] = {
};
#ifdef COMPAT_FREEBSD32
-extern drm_ioctl_desc_t i915_compat_ioctls[];
+extern struct drm_ioctl_desc i915_compat_ioctls[];
extern int i915_compat_ioctls_nr;
#endif
-struct drm_driver_info i915_driver_info = {
- .driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP |
- DRIVER_USE_MTRR | DRIVER_HAVE_IRQ | DRIVER_LOCKLESS_IRQ |
- DRIVER_GEM /*| DRIVER_MODESET*/,
+struct drm_driver i915_driver_info = {
+ /*
+ * FIXME Linux<->FreeBSD: DRIVER_USE_MTRR is commented out on
+ * Linux.
+ */
+ .driver_features =
+ DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR |
+ DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM | DRIVER_PRIME,
.buf_priv_size = sizeof(drm_i915_private_t),
.load = i915_driver_load,
@@ -1672,6 +1668,8 @@ struct drm_driver_info i915_driver_info = {
.lastclose = i915_driver_lastclose,
.postclose = i915_driver_postclose,
.device_is_agp = i915_driver_device_is_agp,
+ .master_create = i915_master_create,
+ .master_destroy = i915_master_destroy,
.gem_init_object = i915_gem_init_object,
.gem_free_object = i915_gem_free_object,
.gem_pager_ops = &i915_gem_pager_ops,
@@ -1684,9 +1682,9 @@ struct drm_driver_info i915_driver_info = {
.ioctls = i915_ioctls,
#ifdef COMPAT_FREEBSD32
.compat_ioctls = i915_compat_ioctls,
- .compat_ioctls_nr = &i915_compat_ioctls_nr,
+ .num_compat_ioctls = &i915_compat_ioctls_nr,
#endif
- .max_ioctl = DRM_ARRAY_SIZE(i915_ioctls),
+ .num_ioctls = ARRAY_SIZE(i915_ioctls),
.name = DRIVER_NAME,
.desc = DRIVER_DESC,
@@ -1705,4 +1703,3 @@ int i915_driver_device_is_agp(struct drm_device * dev)
{
return 1;
}
-
diff --git a/sys/dev/drm2/i915/i915_drm.h b/sys/dev/drm2/i915/i915_drm.h
index c6e5c7e..968bba5 100644
--- a/sys/dev/drm2/i915/i915_drm.h
+++ b/sys/dev/drm2/i915/i915_drm.h
@@ -72,7 +72,7 @@ typedef struct _drm_i915_init {
unsigned int sarea_handle;
} drm_i915_init_t;
-typedef struct drm_i915_sarea {
+typedef struct _drm_i915_sarea {
struct drm_tex_region texList[I915_NR_TEX_REGIONS + 1];
int last_upload; /* last time texture was uploaded */
int last_enqueue; /* last time a buffer was enqueued */
@@ -114,14 +114,14 @@ typedef struct drm_i915_sarea {
unsigned int rotated_tiled;
unsigned int rotated2_tiled;
- int planeA_x;
- int planeA_y;
- int planeA_w;
- int planeA_h;
- int planeB_x;
- int planeB_y;
- int planeB_w;
- int planeB_h;
+ int pipeA_x;
+ int pipeA_y;
+ int pipeA_w;
+ int pipeA_h;
+ int pipeB_x;
+ int pipeB_y;
+ int pipeB_w;
+ int pipeB_h;
/* Triple buffering */
drm_handle_t third_handle;
@@ -139,6 +139,16 @@ typedef struct drm_i915_sarea {
unsigned int depth_bo_handle;
} drm_i915_sarea_t;
+/* due to userspace building against these headers we need some compat here */
+#define planeA_x pipeA_x
+#define planeA_y pipeA_y
+#define planeA_w pipeA_w
+#define planeA_h pipeA_h
+#define planeB_x pipeB_x
+#define planeB_y pipeB_y
+#define planeB_w pipeB_w
+#define planeB_h pipeB_h
+
/* Driver specific fence types and classes.
*/
@@ -224,7 +234,6 @@ typedef struct drm_i915_sarea {
#define DRM_IOCTL_I915_GET_VBLANK_PIPE DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t)
#define DRM_IOCTL_I915_VBLANK_SWAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t)
#define DRM_IOCTL_I915_MMIO DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_MMIO, drm_i915_mmio)
-#define DRM_IOCTL_I915_EXECBUFFER DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_EXECBUFFER, struct drm_i915_execbuffer)
#define DRM_IOCTL_I915_GEM_INIT DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_INIT, struct drm_i915_gem_init)
#define DRM_IOCTL_I915_GEM_EXECBUFFER DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER, struct drm_i915_gem_execbuffer)
#define DRM_IOCTL_I915_GEM_EXECBUFFER2 DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER2, struct drm_i915_gem_execbuffer2)
@@ -447,26 +456,6 @@ typedef struct drm_i915_hws_addr {
#define I915_RELOC1_STRIDE 4
-struct drm_i915_op_arg {
- uint64_t next;
- uint64_t reloc_ptr;
- int handled;
- unsigned int pad64;
- union {
- struct drm_bo_op_req req;
- struct drm_bo_arg_rep rep;
- } d;
-
-};
-
-struct drm_i915_execbuffer {
- uint64_t ops_list;
- uint32_t num_buffers;
- struct drm_i915_batchbuffer batch;
- drm_context_t context; /* for lockless use in the future */
- struct drm_fence_arg fence_arg;
-};
-
struct drm_i915_gem_init {
/**
* Beginning offset in the GTT to be managed by the DRM memory
diff --git a/sys/dev/drm2/i915/i915_drv.c b/sys/dev/drm2/i915/i915_drv.c
index ef6a151..d38c1c9 100644
--- a/sys/dev/drm2/i915/i915_drv.c
+++ b/sys/dev/drm2/i915/i915_drv.c
@@ -298,13 +298,11 @@ static int i915_drm_freeze(struct drm_device *dev)
pci_save_state(dev->pdev);
#endif
- DRM_LOCK(dev);
/* If KMS is active, we do the leavevt stuff here */
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
- error = -i915_gem_idle(dev);
+ error = i915_gem_idle(dev);
if (error) {
- DRM_UNLOCK(dev);
- device_printf(dev->device,
+ device_printf(dev->dev,
"GEM idle failed, resume might fail\n");
return (error);
}
@@ -317,7 +315,6 @@ static int i915_drm_freeze(struct drm_device *dev)
/* Modeset on resume, not lid events */
dev_priv->modeset_on_lid = 0;
- DRM_UNLOCK(dev);
return 0;
}
@@ -331,13 +328,13 @@ i915_suspend(device_t kdev)
dev = device_get_softc(kdev);
if (dev == NULL || dev->dev_private == NULL) {
DRM_ERROR("DRM not initialized, aborting suspend.\n");
- return -ENODEV;
+ return ENODEV;
}
DRM_DEBUG_KMS("starting suspend\n");
error = i915_drm_freeze(dev);
if (error)
- return (error);
+ return (-error);
error = bus_generic_suspend(kdev);
DRM_DEBUG_KMS("finished suspend %d\n", error);
@@ -349,9 +346,10 @@ static int i915_drm_thaw(struct drm_device *dev)
struct drm_i915_private *dev_priv = dev->dev_private;
int error = 0;
- DRM_LOCK(dev);
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+ DRM_LOCK(dev);
i915_gem_restore_gtt_mappings(dev);
+ DRM_UNLOCK(dev);
}
i915_restore_state(dev);
@@ -362,6 +360,7 @@ static int i915_drm_thaw(struct drm_device *dev)
if (HAS_PCH_SPLIT(dev))
ironlake_init_pch_refclk(dev);
+ DRM_LOCK(dev);
dev_priv->mm.suspended = 0;
error = i915_gem_init_hw(dev);
@@ -377,15 +376,12 @@ static int i915_drm_thaw(struct drm_device *dev)
/* Resume the modeset for every activated CRTC */
drm_helper_resume_force_mode(dev);
sx_xunlock(&dev->mode_config.mutex);
- DRM_LOCK(dev);
}
intel_opregion_init(dev);
dev_priv->modeset_on_lid = 0;
- DRM_UNLOCK(dev);
-
return error;
}
@@ -404,9 +400,9 @@ i915_resume(device_t kdev)
pci_set_master(dev->pdev);
#endif
- ret = -i915_drm_thaw(dev);
+ ret = i915_drm_thaw(dev);
if (ret != 0)
- return (ret);
+ return (-ret);
drm_kms_helper_poll_enable(dev);
ret = bus_generic_resume(kdev);
@@ -420,9 +416,9 @@ i915_probe(device_t kdev)
const struct intel_device_info *info;
int error;
- error = drm_probe(kdev, i915_pciidlist);
+ error = drm_probe_helper(kdev, i915_pciidlist);
if (error != 0)
- return (error);
+ return (-error);
info = i915_get_device_id(pci_get_device(kdev));
if (info == NULL)
return (ENXIO);
@@ -434,13 +430,10 @@ int i915_modeset;
static int
i915_attach(device_t kdev)
{
- struct drm_device *dev;
- dev = device_get_softc(kdev);
if (i915_modeset == 1)
i915_driver_info.driver_features |= DRIVER_MODESET;
- dev->driver = &i915_driver_info;
- return (drm_attach(kdev, i915_pciidlist));
+ return (-drm_attach_helper(kdev, i915_pciidlist, &i915_driver_info));
}
static struct fb_info *
@@ -483,7 +476,7 @@ static device_method_t i915_methods[] = {
DEVMETHOD(device_attach, i915_attach),
DEVMETHOD(device_suspend, i915_suspend),
DEVMETHOD(device_resume, i915_resume),
- DEVMETHOD(device_detach, drm_detach),
+ DEVMETHOD(device_detach, drm_generic_detach),
/* Framebuffer service methods */
DEVMETHOD(fb_getinfo, i915_fb_helper_getinfo),
@@ -773,7 +766,7 @@ i965_reset_complete(struct drm_device *dev)
{
u8 gdrst;
- gdrst = pci_read_config(dev->device, I965_GDRST, 1);
+ gdrst = pci_read_config(dev->dev, I965_GDRST, 1);
return (gdrst & GRDOM_RESET_ENABLE) == 0;
}
@@ -788,8 +781,8 @@ i965_do_reset(struct drm_device *dev)
* well as the reset bit (GR/bit 0). Setting the GR bit
* triggers the reset; when done, the hardware will clear it.
*/
- gdrst = pci_read_config(dev->device, I965_GDRST, 1);
- pci_write_config(dev->device, I965_GDRST,
+ gdrst = pci_read_config(dev->dev, I965_GDRST, 1);
+ pci_write_config(dev->dev, I965_GDRST,
gdrst | GRDOM_RENDER | GRDOM_RESET_ENABLE, 1);
ret = wait_for(i965_reset_complete(dev), 500);
@@ -797,8 +790,8 @@ i965_do_reset(struct drm_device *dev)
return ret;
/* We can't reset render&media without also resetting display ... */
- gdrst = pci_read_config(dev->device, I965_GDRST, 1);
- pci_write_config(dev->device, I965_GDRST,
+ gdrst = pci_read_config(dev->dev, I965_GDRST, 1);
+ pci_write_config(dev->dev, I965_GDRST,
gdrst | GRDOM_MEDIA | GRDOM_RESET_ENABLE, 1);
return wait_for(i965_reset_complete(dev), 500);
@@ -949,9 +942,7 @@ int i915_reset(struct drm_device *dev)
if (drm_core_check_feature(dev, DRIVER_MODESET))
intel_modeset_init_hw(dev);
- DRM_LOCK(dev);
drm_irq_uninstall(dev);
- DRM_UNLOCK(dev);
drm_irq_install(dev);
} else
DRM_UNLOCK(dev);
diff --git a/sys/dev/drm2/i915/i915_drv.h b/sys/dev/drm2/i915/i915_drv.h
index a51282c..0a79d3b 100644
--- a/sys/dev/drm2/i915/i915_drv.h
+++ b/sys/dev/drm2/i915/i915_drv.h
@@ -248,6 +248,10 @@ struct intel_opregion {
};
#define OPREGION_SIZE (8*1024)
+struct drm_i915_master_private {
+ drm_local_map_t *sarea;
+ struct _drm_i915_sarea *sarea_priv;
+};
#define I915_FENCE_REG_NONE -1
#define I915_MAX_NUM_FENCES 16
/* 16 fences + sign bit for FENCE_REG_NONE */
@@ -295,7 +299,6 @@ typedef struct drm_i915_private {
int relative_constants_mode;
- drm_local_map_t *sarea;
drm_local_map_t *mmio_map;
/** gt_fifo_count and the subsequent register write are synchronized
@@ -306,7 +309,6 @@ typedef struct drm_i915_private {
/** gt_lock is also taken in irq contexts. */
struct mtx gt_lock;
- drm_i915_sarea_t *sarea_priv;
/* drm_i915_ring_buffer_t ring; */
struct intel_ring_buffer rings[I915_NUM_RINGS];
uint32_t next_seqno;
@@ -1067,7 +1069,7 @@ struct drm_i915_error_state {
extern int intel_iommu_enabled;
extern struct drm_ioctl_desc i915_ioctls[];
-extern struct drm_driver_info i915_driver_info;
+extern struct drm_driver i915_driver_info;
extern struct cdev_pager_ops i915_gem_pager_ops;
extern unsigned int i915_fbpercrtc;
extern int i915_panel_ignore_lid;
@@ -1094,6 +1096,9 @@ int i915_sysctl_init(struct drm_device *dev, struct sysctl_ctx_list *ctx,
struct sysctl_oid *top);
void i915_sysctl_cleanup(struct drm_device *dev);
+extern int i915_master_create(struct drm_device *dev, struct drm_master *master);
+extern void i915_master_destroy(struct drm_device *dev, struct drm_master *master);
+
/* i915_dma.c */
int i915_batchbuffer(struct drm_device *dev, void *data,
struct drm_file *file_priv);
diff --git a/sys/dev/drm2/i915/i915_gem.c b/sys/dev/drm2/i915/i915_gem.c
index b08cca4..f2c8ecb 100644
--- a/sys/dev/drm2/i915/i915_gem.c
+++ b/sys/dev/drm2/i915/i915_gem.c
@@ -161,6 +161,8 @@ i915_gem_wait_for_error(struct drm_device *dev)
while (dev_priv->error_completion == 0) {
ret = -msleep(&dev_priv->error_completion,
&dev_priv->error_completion_lock, PCATCH, "915wco", 0);
+ if (ret == -ERESTART)
+ ret = -ERESTARTSYS;
if (ret != 0) {
mtx_unlock(&dev_priv->error_completion_lock);
return (ret);
@@ -299,6 +301,7 @@ i915_gem_init_ioctl(struct drm_device *dev, void *data,
{
struct drm_i915_gem_init *args;
drm_i915_private_t *dev_priv;
+ int error;
if (drm_core_check_feature(dev, DRIVER_MODESET))
return -ENODEV;
@@ -321,8 +324,11 @@ i915_gem_init_ioctl(struct drm_device *dev, void *data,
* XXXKIB. The second-time initialization should be guarded
* against.
*/
- return (i915_gem_init_global_gtt(dev, args->gtt_start, args->gtt_end,
- args->gtt_end));
+ DRM_LOCK(dev);
+ error = i915_gem_init_global_gtt(dev, args->gtt_start,
+ args->gtt_end, args->gtt_end);
+ DRM_UNLOCK(dev);
+ return (error);
}
int
@@ -331,20 +337,28 @@ i915_gem_idle(struct drm_device *dev)
drm_i915_private_t *dev_priv;
int ret;
+ DRM_LOCK(dev);
+
dev_priv = dev->dev_private;
- if (dev_priv->mm.suspended)
+ if (dev_priv->mm.suspended) {
+ DRM_UNLOCK(dev);
return (0);
+ }
ret = i915_gpu_idle(dev);
- if (ret != 0)
+ if (ret != 0) {
+ DRM_UNLOCK(dev);
return (ret);
+ }
i915_gem_retire_requests(dev);
/* Under UMS, be paranoid and evict. */
if (!drm_core_check_feature(dev, DRIVER_MODESET)) {
ret = i915_gem_evict_everything(dev, false);
- if (ret != 0)
+ if (ret != 0) {
+ DRM_UNLOCK(dev);
return ret;
+ }
}
i915_gem_reset_fences(dev);
@@ -359,6 +373,8 @@ i915_gem_idle(struct drm_device *dev)
i915_kernel_lost_context(dev);
i915_gem_cleanup_ringbuffer(dev);
+ DRM_UNLOCK(dev);
+
/* Cancel the retire work handler, which should be idle now. */
taskqueue_cancel_timeout(dev_priv->tq, &dev_priv->mm.retire_task, NULL);
return (ret);
@@ -613,7 +629,7 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj, uint32_t alignment,
void
i915_gem_object_unpin(struct drm_i915_gem_object *obj)
{
-
+
KASSERT(obj->pin_count != 0, ("zero pin count"));
KASSERT(obj->gtt_space != NULL, ("No gtt mapping"));
@@ -873,10 +889,12 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
atomic_store_rel_int(&dev_priv->mm.wedged, 0);
}
+ DRM_LOCK(dev);
dev_priv->mm.suspended = 0;
ret = i915_gem_init_hw(dev);
if (ret != 0) {
+ DRM_UNLOCK(dev);
return (ret);
}
@@ -884,16 +902,18 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
KASSERT(list_empty(&dev_priv->mm.flushing_list), ("flushing list"));
KASSERT(list_empty(&dev_priv->mm.inactive_list), ("inactive list"));
DRM_UNLOCK(dev);
+
ret = drm_irq_install(dev);
- DRM_LOCK(dev);
if (ret)
goto cleanup_ringbuffer;
return (0);
cleanup_ringbuffer:
+ DRM_LOCK(dev);
i915_gem_cleanup_ringbuffer(dev);
dev_priv->mm.suspended = 1;
+ DRM_UNLOCK(dev);
return (ret);
}
@@ -926,13 +946,12 @@ i915_gem_create(struct drm_file *file, struct drm_device *dev, uint64_t size,
if (obj == NULL)
return (-ENOMEM);
- handle = 0;
ret = drm_gem_handle_create(file, &obj->base, &handle);
if (ret != 0) {
drm_gem_object_release(&obj->base);
i915_gem_info_remove_obj(dev->dev_private, obj->base.size);
free(obj, DRM_I915_GEM);
- return (-ret);
+ return (ret);
}
/* drop reference from allocate - handle holds it now */
@@ -976,23 +995,12 @@ i915_gem_create_ioctl(struct drm_device *dev, void *data,
#define to_user_ptr(x) ((void *)(uintptr_t)(x))
#define offset_in_page(x) ((x) & PAGE_MASK)
#define page_to_phys(x) VM_PAGE_TO_PHYS(x)
-static inline long
-__copy_to_user(void __user *to, const void *from, unsigned long n)
-{
- return (copyout(from, to, n) != 0 ? n : 0);
-}
static inline int
__copy_to_user_inatomic(void __user *to, const void *from, unsigned n)
{
return (copyout_nofault(from, to, n) != 0 ? n : 0);
}
static inline unsigned long
-__copy_from_user(void *to, const void __user *from, unsigned long n)
-{
- return ((copyin(__DECONST(void *, from), to, n) != 0 ? n : 0));
-}
-#define copy_from_user(to, from, n) __copy_from_user((to), (from), (n))
-static inline unsigned long
__copy_from_user_inatomic_nocache(void *to, const void __user *from,
unsigned long n)
{
@@ -1017,7 +1025,7 @@ fault_in_multipages_readable(const char __user *uaddr, int size)
return ret;
while (uaddr <= end) {
- ret = copyin(uaddr, &c, 1);
+ ret = -copyin(uaddr, &c, 1);
if (ret != 0)
return -EFAULT;
uaddr += PAGE_SIZE;
@@ -1026,10 +1034,10 @@ fault_in_multipages_readable(const char __user *uaddr, int size)
/* Check whether the range spilled into the next page. */
if (((unsigned long)uaddr & ~PAGE_MASK) ==
((unsigned long)end & ~PAGE_MASK)) {
- ret = copyin(end, &c, 1);
+ ret = -copyin(end, &c, 1);
}
- return -ret;
+ return ret;
}
static inline int
@@ -1868,14 +1876,13 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
PROC_LOCK(p);
if (map->size + size > lim_cur(p, RLIMIT_VMEM)) {
PROC_UNLOCK(p);
- error = ENOMEM;
+ error = -ENOMEM;
goto out;
}
PROC_UNLOCK(p);
addr = 0;
vm_object_reference(obj->vm_obj);
- DRM_UNLOCK(dev);
rv = vm_map_find(map, obj->vm_obj, args->offset, &addr, args->size, 0,
VMFS_OPTIMAL_SPACE, VM_PROT_READ | VM_PROT_WRITE,
VM_PROT_READ | VM_PROT_WRITE, MAP_INHERIT_SHARE);
@@ -1885,7 +1892,6 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
} else {
args->addr_ptr = (uint64_t)addr;
}
- DRM_LOCK(dev);
out:
drm_gem_object_unreference(obj);
return (error);
@@ -2631,11 +2637,11 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
if (free_space != NULL) {
if (map_and_fenceable)
obj->gtt_space = drm_mm_get_block_range_generic(
- free_space, size, alignment, 0,
+ free_space, size, alignment, 0, 0,
dev_priv->mm.gtt_mappable_end, 1);
else
obj->gtt_space = drm_mm_get_block_generic(free_space,
- size, alignment, 1);
+ size, alignment, 0, 1);
}
if (obj->gtt_space == NULL) {
ret = i915_gem_evict_something(dev, size, alignment,
@@ -2771,14 +2777,14 @@ i915_gem_object_unbind(struct drm_i915_gem_object *obj)
}
ret = i915_gem_object_finish_gpu(obj);
- if (ret == -ERESTART || ret == -EINTR)
+ if (ret == -ERESTARTSYS || ret == -EINTR)
return (ret);
i915_gem_object_finish_gtt(obj);
if (ret == 0)
ret = i915_gem_object_set_to_cpu_domain(obj, 1);
- if (ret == -ERESTART || ret == -EINTR)
+ if (ret == -ERESTARTSYS || ret == -EINTR)
return (ret);
if (ret != 0) {
i915_gem_clflush_object(obj);
@@ -3326,8 +3332,11 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
flags = interruptible ? PCATCH : 0;
while (!i915_seqno_passed(ring->get_seqno(ring), seqno)
&& !atomic_load_acq_int(&dev_priv->mm.wedged) &&
- ret == 0)
+ ret == 0) {
ret = -msleep(ring, &dev_priv->irq_lock, flags, "915gwr", 0);
+ if (ret == -ERESTART)
+ ret = -ERESTARTSYS;
+ }
ring->irq_put(ring);
mtx_unlock(&dev_priv->irq_lock);
@@ -3584,7 +3593,7 @@ i915_gem_retire_requests_ring(struct intel_ring_buffer *ring)
seqno = ring->get_seqno(ring);
CTR2(KTR_DRM, "retire_request_ring %s %d", ring->name, seqno);
- for (i = 0; i < DRM_ARRAY_SIZE(ring->sync_seqno); i++)
+ for (i = 0; i < ARRAY_SIZE(ring->sync_seqno); i++)
if (seqno >= ring->sync_seqno[i])
ring->sync_seqno[i] = 0;
@@ -4047,7 +4056,7 @@ i915_gem_init_phys_object(struct drm_device *dev, int id, int size, int align)
phys_obj->id = id;
- phys_obj->handle = drm_pci_alloc(dev, size, align, ~0);
+ phys_obj->handle = drm_pci_alloc(dev, size, align, BUS_SPACE_MAXADDR);
if (phys_obj->handle == NULL) {
ret = -ENOMEM;
goto free_obj;
@@ -4196,7 +4205,7 @@ i915_gem_attach_phys_object(struct drm_device *dev,
}
VM_OBJECT_WUNLOCK(obj->base.vm_obj);
- return (0);
+ return (ret);
}
static int
diff --git a/sys/dev/drm2/i915/i915_gem_context.c b/sys/dev/drm2/i915/i915_gem_context.c
index dc42043..39d09b0 100644
--- a/sys/dev/drm2/i915/i915_gem_context.c
+++ b/sys/dev/drm2/i915/i915_gem_context.c
@@ -317,10 +317,10 @@ void i915_gem_context_close(struct drm_device *dev, struct drm_file *file)
{
struct drm_i915_file_private *file_priv = file->driver_priv;
- //DRM_LOCK(dev); /* Called from preclose(), the lock is already owned. */
+ DRM_LOCK(dev);
drm_gem_names_foreach(&file_priv->context_idr, context_idr_cleanup, NULL);
drm_gem_names_fini(&file_priv->context_idr);
- //DRM_UNLOCK(dev);
+ DRM_UNLOCK(dev);
}
static struct i915_hw_context *
diff --git a/sys/dev/drm2/i915/i915_gem_evict.c b/sys/dev/drm2/i915/i915_gem_evict.c
index cadd9ff..e800b8f 100644
--- a/sys/dev/drm2/i915/i915_gem_evict.c
+++ b/sys/dev/drm2/i915/i915_gem_evict.c
@@ -82,10 +82,10 @@ i915_gem_evict_something(struct drm_device *dev, int min_size,
INIT_LIST_HEAD(&unwind_list);
if (mappable)
drm_mm_init_scan_with_range(&dev_priv->mm.gtt_space, min_size,
- alignment, 0,
+ alignment, 0, 0,
dev_priv->mm.gtt_mappable_end);
else
- drm_mm_init_scan(&dev_priv->mm.gtt_space, min_size, alignment);
+ drm_mm_init_scan(&dev_priv->mm.gtt_space, min_size, alignment, 0);
/* First see if there is a large enough contiguous idle region... */
list_for_each_entry(obj, &dev_priv->mm.inactive_list, mm_list) {
diff --git a/sys/dev/drm2/i915/i915_gem_execbuffer.c b/sys/dev/drm2/i915/i915_gem_execbuffer.c
index b84dab5..5f0614c 100644
--- a/sys/dev/drm2/i915/i915_gem_execbuffer.c
+++ b/sys/dev/drm2/i915/i915_gem_execbuffer.c
@@ -1240,14 +1240,16 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
goto pre_struct_lock_err;
if (dev_priv->mm.suspended) {
+ DRM_UNLOCK(dev);
ret = -EBUSY;
- goto struct_lock_err;
+ goto pre_struct_lock_err;
}
eb = eb_create(args->buffer_count);
if (eb == NULL) {
+ DRM_UNLOCK(dev);
ret = -ENOMEM;
- goto struct_lock_err;
+ goto pre_struct_lock_err;
}
/* Look up object handles */
@@ -1394,7 +1396,6 @@ err:
list_del_init(&obj->exec_list);
drm_gem_object_unreference(&obj->base);
}
-struct_lock_err:
DRM_UNLOCK(dev);
pre_struct_lock_err:
diff --git a/sys/dev/drm2/i915/i915_gem_gtt.c b/sys/dev/drm2/i915/i915_gem_gtt.c
index 3fcd3f5..5ec552a 100644
--- a/sys/dev/drm2/i915/i915_gem_gtt.c
+++ b/sys/dev/drm2/i915/i915_gem_gtt.c
@@ -355,7 +355,7 @@ i915_gem_init_global_gtt(struct drm_device *dev, unsigned long start,
/* ... but ensure that we clear the entire range. */
intel_gtt_clear_range(start / PAGE_SIZE, (end-start) / PAGE_SIZE);
- device_printf(dev->device,
+ device_printf(dev->dev,
"taking over the fictitious range 0x%lx-0x%lx\n",
dev->agp->base + start, dev->agp->base + start + mappable);
error = -vm_phys_fictitious_reg_range(dev->agp->base + start,
diff --git a/sys/dev/drm2/i915/i915_gem_tiling.c b/sys/dev/drm2/i915/i915_gem_tiling.c
index 6ca3962..edc0e3c 100644
--- a/sys/dev/drm2/i915/i915_gem_tiling.c
+++ b/sys/dev/drm2/i915/i915_gem_tiling.c
@@ -352,6 +352,7 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
}
}
+ DRM_LOCK(dev);
if (args->tiling_mode != obj->tiling_mode ||
args->stride != obj->stride) {
/* We need to rebind the object if its current allocation
@@ -399,6 +400,7 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
args->stride = obj->stride;
args->tiling_mode = obj->tiling_mode;
drm_gem_object_unreference(&obj->base);
+ DRM_UNLOCK(dev);
return (ret);
}
@@ -418,6 +420,8 @@ i915_gem_get_tiling(struct drm_device *dev, void *data,
if (&obj->base == NULL)
return -ENOENT;
+ DRM_LOCK(dev);
+
args->tiling_mode = obj->tiling_mode;
switch (obj->tiling_mode) {
case I915_TILING_X:
@@ -440,6 +444,7 @@ i915_gem_get_tiling(struct drm_device *dev, void *data,
args->swizzle_mode = I915_BIT_6_SWIZZLE_9_10;
drm_gem_object_unreference(&obj->base);
+ DRM_UNLOCK(dev);
return 0;
}
diff --git a/sys/dev/drm2/i915/i915_ioc32.c b/sys/dev/drm2/i915/i915_ioc32.c
index 26040e8..d9a5184 100644
--- a/sys/dev/drm2/i915/i915_ioc32.c
+++ b/sys/dev/drm2/i915/i915_ioc32.c
@@ -127,12 +127,12 @@ typedef struct drm_i915_mem_alloc32 {
u32 region_offset; /* offset from start of fb or agp */
} drm_i915_mem_alloc32_t;
-drm_ioctl_desc_t i915_compat_ioctls[] = {
+struct drm_ioctl_desc i915_compat_ioctls[] = {
DRM_IOCTL_DEF(DRM_I915_BATCHBUFFER, compat_i915_batchbuffer, DRM_AUTH),
DRM_IOCTL_DEF(DRM_I915_CMDBUFFER, compat_i915_cmdbuffer, DRM_AUTH),
DRM_IOCTL_DEF(DRM_I915_GETPARAM, compat_i915_getparam, DRM_AUTH),
DRM_IOCTL_DEF(DRM_I915_IRQ_EMIT, compat_i915_irq_emit, DRM_AUTH)
};
-int i915_compat_ioctls_nr = DRM_ARRAY_SIZE(i915_compat_ioctls);
+int i915_compat_ioctls_nr = ARRAY_SIZE(i915_compat_ioctls);
#endif
diff --git a/sys/dev/drm2/i915/i915_irq.c b/sys/dev/drm2/i915/i915_irq.c
index 346d9c0..ac89032 100644
--- a/sys/dev/drm2/i915/i915_irq.c
+++ b/sys/dev/drm2/i915/i915_irq.c
@@ -1458,11 +1458,11 @@ static int valleyview_irq_postinstall(struct drm_device *dev)
dev_priv->pipestat[1] = 0;
/* Hack for broken MSIs on VLV */
- pci_write_config(dev->device, 0x94, 0xfee00000, 4);
- msid = pci_read_config(dev->device, 0x98, 2);
+ pci_write_config(dev->dev, 0x94, 0xfee00000, 4);
+ msid = pci_read_config(dev->dev, 0x98, 2);
msid &= 0xff; /* mask out delivery bits */
msid |= (1<<14);
- pci_write_config(dev->device, 0x98, msid, 2);
+ pci_write_config(dev->dev, 0x98, msid, 2);
I915_WRITE(VLV_IMR, dev_priv->irq_mask);
I915_WRITE(VLV_IER, enable_mask);
@@ -2329,7 +2329,7 @@ i915_error_state_free(struct drm_i915_error_state *error)
{
int i;
- for (i = 0; i < DRM_ARRAY_SIZE(error->ring); i++) {
+ for (i = 0; i < ARRAY_SIZE(error->ring); i++) {
i915_error_object_free(error->ring[i].batchbuffer);
i915_error_object_free(error->ring[i].ringbuffer);
free(error->ring[i].requests, DRM_I915_GEM);
diff --git a/sys/dev/drm2/i915/i915_suspend.c b/sys/dev/drm2/i915/i915_suspend.c
index fd31120..384a1d1 100644
--- a/sys/dev/drm2/i915/i915_suspend.c
+++ b/sys/dev/drm2/i915/i915_suspend.c
@@ -460,19 +460,19 @@ static void i915_restore_modeset_reg(struct drm_device *dev)
I915_WRITE(dpll_a_reg, dev_priv->saveDPLL_A &
~DPLL_VCO_ENABLE);
POSTING_READ(dpll_a_reg);
- DRM_UDELAY(150);
+ udelay(150);
}
I915_WRITE(fpa0_reg, dev_priv->saveFPA0);
I915_WRITE(fpa1_reg, dev_priv->saveFPA1);
/* Actually enable it */
I915_WRITE(dpll_a_reg, dev_priv->saveDPLL_A);
POSTING_READ(dpll_a_reg);
- DRM_UDELAY(150);
+ udelay(150);
if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) {
I915_WRITE(_DPLL_A_MD, dev_priv->saveDPLL_A_MD);
POSTING_READ(_DPLL_A_MD);
}
- DRM_UDELAY(150);
+ udelay(150);
/* Restore mode */
I915_WRITE(_HTOTAL_A, dev_priv->saveHTOTAL_A);
@@ -529,19 +529,19 @@ static void i915_restore_modeset_reg(struct drm_device *dev)
I915_WRITE(dpll_b_reg, dev_priv->saveDPLL_B &
~DPLL_VCO_ENABLE);
POSTING_READ(dpll_b_reg);
- DRM_UDELAY(150);
+ udelay(150);
}
I915_WRITE(fpb0_reg, dev_priv->saveFPB0);
I915_WRITE(fpb1_reg, dev_priv->saveFPB1);
/* Actually enable it */
I915_WRITE(dpll_b_reg, dev_priv->saveDPLL_B);
POSTING_READ(dpll_b_reg);
- DRM_UDELAY(150);
+ udelay(150);
if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) {
I915_WRITE(_DPLL_B_MD, dev_priv->saveDPLL_B_MD);
POSTING_READ(_DPLL_B_MD);
}
- DRM_UDELAY(150);
+ udelay(150);
/* Restore mode */
I915_WRITE(_HTOTAL_B, dev_priv->saveHTOTAL_B);
@@ -792,7 +792,7 @@ static void i915_restore_display(struct drm_device *dev)
I915_WRITE(VGA1, dev_priv->saveVGA1);
I915_WRITE(VGA_PD, dev_priv->saveVGA_PD);
POSTING_READ(VGA_PD);
- DRM_UDELAY(150);
+ udelay(150);
i915_restore_vga(dev);
}
@@ -802,11 +802,13 @@ int i915_save_state(struct drm_device *dev)
struct drm_i915_private *dev_priv = dev->dev_private;
int i;
- dev_priv->saveLBB = pci_read_config(dev->device, LBB, 1);
+ dev_priv->saveLBB = pci_read_config(dev->dev, LBB, 1);
/* Hardware status page */
dev_priv->saveHWS = I915_READ(HWS_PGA);
+ DRM_LOCK(dev);
+
i915_save_display(dev);
/* Interrupt state */
@@ -844,6 +846,8 @@ int i915_save_state(struct drm_device *dev)
for (i = 0; i < 3; i++)
dev_priv->saveSWF2[i] = I915_READ(SWF30 + (i << 2));
+ DRM_UNLOCK(dev);
+
return 0;
}
@@ -852,8 +856,9 @@ int i915_restore_state(struct drm_device *dev)
struct drm_i915_private *dev_priv = dev->dev_private;
int i;
- pci_write_config(dev->device, LBB, dev_priv->saveLBB, 1);
+ pci_write_config(dev->dev, LBB, dev_priv->saveLBB, 1);
+ DRM_LOCK(dev);
/* Hardware status page */
I915_WRITE(HWS_PGA, dev_priv->saveHWS);
@@ -887,6 +892,8 @@ int i915_restore_state(struct drm_device *dev)
for (i = 0; i < 3; i++)
I915_WRITE(SWF30 + (i << 2), dev_priv->saveSWF2[i]);
+ DRM_UNLOCK(dev);
+
intel_iic_reset(dev);
return 0;
diff --git a/sys/dev/drm2/i915/intel_crt.c b/sys/dev/drm2/i915/intel_crt.c
index c1b39eb..5f52bfd 100644
--- a/sys/dev/drm2/i915/intel_crt.c
+++ b/sys/dev/drm2/i915/intel_crt.c
@@ -129,7 +129,7 @@ static int intel_crt_mode_valid(struct drm_connector *connector,
}
static bool intel_crt_mode_fixup(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
+ const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
return true;
@@ -310,7 +310,6 @@ static bool intel_crt_detect_ddc(struct drm_connector *connector)
*/
if (edid != NULL) {
is_digital = edid->input & DRM_EDID_INPUT_DIGITAL;
- connector->display_info.raw_edid = NULL;
free(edid, DRM_MEM_KMS);
}
diff --git a/sys/dev/drm2/i915/intel_display.c b/sys/dev/drm2/i915/intel_display.c
index a844c7f..aafd4fa 100644
--- a/sys/dev/drm2/i915/intel_display.c
+++ b/sys/dev/drm2/i915/intel_display.c
@@ -2051,9 +2051,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
{
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
-#if 0
struct drm_i915_master_private *master_priv;
-#endif
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int ret;
@@ -2099,7 +2097,6 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
intel_update_fbc(dev);
DRM_UNLOCK(dev);
-#if 0
if (!dev->primary->master)
return 0;
@@ -2114,19 +2111,6 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
master_priv->sarea_priv->pipeA_x = x;
master_priv->sarea_priv->pipeA_y = y;
}
-#else
-
- if (!dev_priv->sarea_priv)
- return 0;
-
- if (intel_crtc->pipe) {
- dev_priv->sarea_priv->planeB_x = x;
- dev_priv->sarea_priv->planeB_y = y;
- } else {
- dev_priv->sarea_priv->planeA_x = x;
- dev_priv->sarea_priv->planeA_y = y;
- }
-#endif
return 0;
}
@@ -3329,9 +3313,7 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode)
{
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
-#if 0
struct drm_i915_master_private *master_priv;
-#endif
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int pipe = intel_crtc->pipe;
bool enabled;
@@ -3343,38 +3325,23 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode)
dev_priv->display.dpms(crtc, mode);
-#if 0
if (!dev->primary->master)
return;
master_priv = dev->primary->master->driver_priv;
if (!master_priv->sarea_priv)
return;
-#else
- if (!dev_priv->sarea_priv)
- return;
-#endif
enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF;
switch (pipe) {
case 0:
-#if 0
master_priv->sarea_priv->pipeA_w = enabled ? crtc->mode.hdisplay : 0;
master_priv->sarea_priv->pipeA_h = enabled ? crtc->mode.vdisplay : 0;
-#else
- dev_priv->sarea_priv->planeA_w = enabled ? crtc->mode.hdisplay : 0;
- dev_priv->sarea_priv->planeA_h = enabled ? crtc->mode.vdisplay : 0;
-#endif
break;
case 1:
-#if 0
master_priv->sarea_priv->pipeB_w = enabled ? crtc->mode.hdisplay : 0;
master_priv->sarea_priv->pipeB_h = enabled ? crtc->mode.vdisplay : 0;
-#else
- dev_priv->sarea_priv->planeB_w = enabled ? crtc->mode.hdisplay : 0;
- dev_priv->sarea_priv->planeB_h = enabled ? crtc->mode.vdisplay : 0;
-#endif
break;
default:
DRM_ERROR("Can't update pipe %c in SAREA\n", pipe_name(pipe));
@@ -3502,7 +3469,7 @@ static int i915gm_get_display_clock_speed(struct drm_device *dev)
{
u16 gcfgc = 0;
- gcfgc = pci_read_config(dev->device, GCFGC, 2);
+ gcfgc = pci_read_config(dev->dev, GCFGC, 2);
if (gcfgc & GC_LOW_FREQUENCY_ENABLE)
return 133000;
@@ -6946,8 +6913,8 @@ static void intel_init_quirks(struct drm_device *dev)
device_t d;
int i;
- d = dev->device;
- for (i = 0; i < DRM_ARRAY_SIZE(intel_quirks); i++) {
+ d = dev->dev;
+ for (i = 0; i < ARRAY_SIZE(intel_quirks); i++) {
q = &intel_quirks[i];
if (pci_get_device(d) == q->device &&
(pci_get_subvendor(d) == q->subsystem_vendor ||
@@ -7116,10 +7083,11 @@ void intel_modeset_cleanup(struct drm_device *dev)
if (IS_VALLEYVIEW(dev))
vlv_init_dpio(dev);
+ DRM_UNLOCK(dev);
+
/* Disable the irq before mode object teardown, for the irq might
* enqueue unpin/hotplug work. */
drm_irq_uninstall(dev);
- DRM_UNLOCK(dev);
if (taskqueue_cancel(dev_priv->tq, &dev_priv->hotplug_task, NULL))
taskqueue_drain(dev_priv->tq, &dev_priv->hotplug_task);
diff --git a/sys/dev/drm2/i915/intel_dp.c b/sys/dev/drm2/i915/intel_dp.c
index e9674b0..5791caf 100644
--- a/sys/dev/drm2/i915/intel_dp.c
+++ b/sys/dev/drm2/i915/intel_dp.c
@@ -665,7 +665,7 @@ intel_dp_i2c_init(struct intel_dp *intel_dp,
DRM_DEBUG_KMS("i2c_init %s\n", name);
ironlake_edp_panel_vdd_on(intel_dp);
- ret = iic_dp_aux_add_bus(intel_connector->base.dev->device, name,
+ ret = iic_dp_aux_add_bus(intel_connector->base.dev->dev, name,
intel_dp_i2c_aux_ch, intel_dp, &intel_dp->dp_iic_bus,
&intel_dp->adapter);
ironlake_edp_panel_vdd_off(intel_dp, false);
@@ -673,7 +673,7 @@ intel_dp_i2c_init(struct intel_dp *intel_dp,
}
static bool
-intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
+intel_dp_mode_fixup(struct drm_encoder *encoder, const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct drm_device *dev = encoder->dev;
@@ -688,11 +688,6 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
intel_fixed_panel_mode(intel_dp->panel_fixed_mode, adjusted_mode);
intel_pch_panel_fitting(dev, DRM_MODE_SCALE_FULLSCREEN,
mode, adjusted_mode);
- /*
- * the mode->clock is used to calculate the Data&Link M/N
- * of the pipe. For the eDP the fixed clock should be used.
- */
- mode->clock = intel_dp->panel_fixed_mode->clock;
}
DRM_DEBUG_KMS("DP link computation with max lane count %i "
@@ -703,7 +698,7 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
return false;
bpp = adjusted_mode->private_flags & INTEL_MODE_DP_FORCE_6BPC ? 18 : 24;
- mode_rate = intel_dp_link_required(mode->clock, bpp);
+ mode_rate = intel_dp_link_required(adjusted_mode->clock, bpp);
for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) {
for (clock = 0; clock <= max_clock; clock++) {
@@ -2151,7 +2146,6 @@ intel_dp_detect(struct drm_connector *connector, bool force)
edid = intel_dp_get_edid(connector, intel_dp->adapter);
if (edid) {
intel_dp->has_audio = drm_detect_monitor_audio(edid);
- connector->display_info.raw_edid = NULL;
free(edid, DRM_MEM_KMS);
}
}
@@ -2217,7 +2211,6 @@ intel_dp_detect_audio(struct drm_connector *connector)
if (edid) {
has_audio = drm_detect_monitor_audio(edid);
- connector->display_info.raw_edid = NULL;
free(edid, DRM_MEM_KMS);
}
@@ -2233,7 +2226,7 @@ intel_dp_set_property(struct drm_connector *connector,
struct intel_dp *intel_dp = intel_attached_dp(connector);
int ret;
- ret = drm_connector_property_set_value(connector, property, val);
+ ret = drm_object_property_set_value(&connector->base, property, val);
if (ret)
return ret;
@@ -2307,7 +2300,7 @@ static void intel_dp_encoder_destroy(struct drm_encoder *encoder)
device_delete_child(intel_dp->dp_iic_bus,
intel_dp->adapter);
}
- device_delete_child(dev->device, intel_dp->dp_iic_bus);
+ device_delete_child(dev->dev, intel_dp->dp_iic_bus);
}
drm_encoder_cleanup(encoder);
if (is_edp(intel_dp)) {
diff --git a/sys/dev/drm2/i915/intel_fb.c b/sys/dev/drm2/i915/intel_fb.c
index 124b769..130d87a 100644
--- a/sys/dev/drm2/i915/intel_fb.c
+++ b/sys/dev/drm2/i915/intel_fb.c
@@ -79,20 +79,17 @@ static int intelfb_create(struct intel_fbdev *ifbdev,
goto out_unref;
}
-#if 0
- info = framebuffer_alloc(0, device);
+ info = framebuffer_alloc();
if (!info) {
ret = -ENOMEM;
goto out_unpin;
}
+#if 0
info->par = ifbdev;
#else
- info = malloc(sizeof(struct fb_info), DRM_MEM_KMS, M_WAITOK | M_ZERO);
info->fb_size = size;
info->fb_bpp = sizes->surface_bpp;
- info->fb_width = sizes->fb_width;
- info->fb_height = sizes->fb_height;
info->fb_pbase = dev->agp->base + obj->gtt_offset;
info->fb_vbase = (vm_offset_t)pmap_mapdev_attr(info->fb_pbase, size,
PAT_WRITE_COMBINING);
@@ -140,12 +137,12 @@ static int intelfb_create(struct intel_fbdev *ifbdev,
info->screen_size = size;
// memset(info->screen_base, 0, size);
+#endif
drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
drm_fb_helper_fill_var(info, &ifbdev->helper, sizes->fb_width, sizes->fb_height);
/* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
-#endif
DRM_DEBUG_KMS("allocated %dx%d (s %dbits) fb: 0x%08x, bo %p\n",
fb->width, fb->height, fb->depth,
obj->gtt_offset, obj);
@@ -192,21 +189,19 @@ static struct drm_fb_helper_funcs intel_fb_helper_funcs = {
static void intel_fbdev_destroy(struct drm_device *dev,
struct intel_fbdev *ifbdev)
{
-#if 0
struct fb_info *info;
-#endif
struct intel_framebuffer *ifb = &ifbdev->ifb;
-#if 0
if (ifbdev->helper.fbdev) {
info = ifbdev->helper.fbdev;
+#if 0
unregister_framebuffer(info);
iounmap(info->screen_base);
if (info->cmap.len)
fb_dealloc_cmap(&info->cmap);
+#endif
framebuffer_release(info);
}
-#endif
drm_fb_helper_fini(&ifbdev->helper);
diff --git a/sys/dev/drm2/i915/intel_hdmi.c b/sys/dev/drm2/i915/intel_hdmi.c
index 3f0572f..c009b03 100644
--- a/sys/dev/drm2/i915/intel_hdmi.c
+++ b/sys/dev/drm2/i915/intel_hdmi.c
@@ -446,7 +446,7 @@ static int intel_hdmi_mode_valid(struct drm_connector *connector,
}
static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
+ const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
return true;
@@ -473,7 +473,6 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)
drm_detect_hdmi_monitor(edid);
intel_hdmi->has_audio = drm_detect_monitor_audio(edid);
}
- connector->display_info.raw_edid = NULL;
free(edid, DRM_MEM_KMS);
} else {
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] got no edid, ddc port %d\n",
@@ -519,7 +518,6 @@ intel_hdmi_detect_audio(struct drm_connector *connector)
if (edid->input & DRM_EDID_INPUT_DIGITAL)
has_audio = drm_detect_monitor_audio(edid);
- connector->display_info.raw_edid = NULL;
free(edid, DRM_MEM_KMS);
}
@@ -535,7 +533,7 @@ intel_hdmi_set_property(struct drm_connector *connector,
struct drm_i915_private *dev_priv = connector->dev->dev_private;
int ret;
- ret = drm_connector_property_set_value(connector, property, val);
+ ret = drm_object_property_set_value(&connector->base, property, val);
if (ret)
return ret;
diff --git a/sys/dev/drm2/i915/intel_iic.c b/sys/dev/drm2/i915/intel_iic.c
index aa12a78..36a5b9e 100644
--- a/sys/dev/drm2/i915/intel_iic.c
+++ b/sys/dev/drm2/i915/intel_iic.c
@@ -258,9 +258,9 @@ gmbus_xfer_read(struct drm_i915_private *dev_priv, struct iic_msg *msg,
(GMBUS_SATOER | GMBUS_HW_RDY)),
50, 1, "915gbr");
if (ret)
- return (ETIMEDOUT);
+ return (-ETIMEDOUT);
if (gmbus2 & GMBUS_SATOER)
- return (ENXIO);
+ return (-ENXIO);
val = I915_READ(GMBUS3 + reg_offset);
do {
@@ -308,9 +308,9 @@ gmbus_xfer_write(struct drm_i915_private *dev_priv, struct iic_msg *msg)
(GMBUS_SATOER | GMBUS_HW_RDY)),
50, 1, "915gbw");
if (ret)
- return (ETIMEDOUT);
+ return (-ETIMEDOUT);
if (gmbus2 & GMBUS_SATOER)
- return (ENXIO);
+ return (-ENXIO);
}
return 0;
}
@@ -369,7 +369,7 @@ intel_gmbus_transfer(device_t idev, struct iic_msg *msgs, uint32_t nmsgs)
sx_xlock(&dev_priv->gmbus_sx);
if (sc->force_bit_dev) {
- error = IICBUS_TRANSFER(dev_priv->bbbus[unit], msgs, nmsgs);
+ error = -IICBUS_TRANSFER(dev_priv->bbbus[unit], msgs, nmsgs);
goto out;
}
@@ -389,9 +389,9 @@ intel_gmbus_transfer(device_t idev, struct iic_msg *msgs, uint32_t nmsgs)
error = gmbus_xfer_write(dev_priv, &msgs[i]);
}
- if (error == ETIMEDOUT)
+ if (error == -ETIMEDOUT)
goto timeout;
- if (error == ENXIO)
+ if (error == -ENXIO)
goto clear_err;
ret = _intel_wait_for(sc->drm_dev,
@@ -419,7 +419,7 @@ intel_gmbus_transfer(device_t idev, struct iic_msg *msgs, uint32_t nmsgs)
10, 1, "915gbu")) {
DRM_DEBUG_KMS("GMBUS [%s] timed out waiting for idle\n",
sc->name);
- error = ETIMEDOUT;
+ error = -ETIMEDOUT;
}
I915_WRITE(GMBUS0 + reg_offset, 0);
goto out;
@@ -454,7 +454,7 @@ clear_err:
* So, we always return -ENXIO in all NAK cases, to ensure we send
* it at least during the one case that is specified.
*/
- error = ENXIO;
+ error = -ENXIO;
goto out;
timeout:
@@ -467,12 +467,12 @@ timeout:
* Try GPIO bitbanging instead.
*/
sc->force_bit_dev = true;
- error = IICBUS_TRANSFER(idev, msgs, nmsgs);
+ error = -IICBUS_TRANSFER(idev, msgs, nmsgs);
goto out;
out:
sx_xunlock(&dev_priv->gmbus_sx);
- return (error);
+ return (-error);
}
device_t
@@ -730,15 +730,15 @@ intel_setup_gmbus(struct drm_device *dev)
* gmbus may decide to force quirk transfer in the
* attachment code.
*/
- dev_priv->bbbus_bridge[i] = device_add_child(dev->device,
+ dev_priv->bbbus_bridge[i] = device_add_child(dev->dev,
"intel_iicbb", i);
if (dev_priv->bbbus_bridge[i] == NULL) {
DRM_ERROR("bbbus bridge %d creation failed\n", i);
- ret = ENXIO;
+ ret = -ENXIO;
goto err;
}
device_quiet(dev_priv->bbbus_bridge[i]);
- ret = device_probe_and_attach(dev_priv->bbbus_bridge[i]);
+ ret = -device_probe_and_attach(dev_priv->bbbus_bridge[i]);
if (ret != 0) {
DRM_ERROR("bbbus bridge %d attach failed, %d\n", i,
ret);
@@ -760,19 +760,19 @@ intel_setup_gmbus(struct drm_device *dev)
dev_priv->bbbus[i] = iic_dev;
- dev_priv->gmbus_bridge[i] = device_add_child(dev->device,
+ dev_priv->gmbus_bridge[i] = device_add_child(dev->dev,
"intel_gmbus", i);
if (dev_priv->gmbus_bridge[i] == NULL) {
DRM_ERROR("gmbus bridge %d creation failed\n", i);
- ret = ENXIO;
+ ret = -ENXIO;
goto err;
}
device_quiet(dev_priv->gmbus_bridge[i]);
- ret = device_probe_and_attach(dev_priv->gmbus_bridge[i]);
+ ret = -device_probe_and_attach(dev_priv->gmbus_bridge[i]);
if (ret != 0) {
DRM_ERROR("gmbus bridge %d attach failed, %d\n", i,
ret);
- ret = ENXIO;
+ ret = -ENXIO;
goto err;
}
diff --git a/sys/dev/drm2/i915/intel_lvds.c b/sys/dev/drm2/i915/intel_lvds.c
index 5f749ce..9e6c667 100644
--- a/sys/dev/drm2/i915/intel_lvds.c
+++ b/sys/dev/drm2/i915/intel_lvds.c
@@ -230,7 +230,7 @@ static inline u32 panel_fitter_scaling(u32 source, u32 target)
}
static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
+ const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct drm_device *dev = encoder->dev;
@@ -978,7 +978,7 @@ bool intel_lvds_init(struct drm_device *dev)
* the initial panel fitting mode will be FULL_SCREEN.
*/
- drm_connector_attach_property(&intel_connector->base,
+ drm_object_attach_property(&connector->base,
dev->mode_config.scaling_mode_property,
DRM_MODE_SCALE_ASPECT);
intel_lvds->fitting_mode = DRM_MODE_SCALE_ASPECT;
diff --git a/sys/dev/drm2/i915/intel_modes.c b/sys/dev/drm2/i915/intel_modes.c
index 6b83bae..d061d08 100644
--- a/sys/dev/drm2/i915/intel_modes.c
+++ b/sys/dev/drm2/i915/intel_modes.c
@@ -80,7 +80,6 @@ intel_ddc_get_modes(struct drm_connector *connector, device_t adapter)
drm_mode_connector_update_edid_property(connector, edid);
ret = drm_add_edid_modes(connector, edid);
drm_edid_to_eld(connector, edid);
- connector->display_info.raw_edid = NULL;
free(edid, DRM_MEM_KMS);
}
@@ -106,13 +105,13 @@ intel_attach_force_audio_property(struct drm_connector *connector)
prop = drm_property_create_enum(dev, 0,
"audio",
force_audio_names,
- DRM_ARRAY_SIZE(force_audio_names));
+ ARRAY_SIZE(force_audio_names));
if (prop == NULL)
return;
dev_priv->force_audio_property = prop;
}
- drm_connector_attach_property(connector, prop, 0);
+ drm_object_attach_property(&connector->base, prop, 0);
}
static const struct drm_prop_enum_list broadcast_rgb_names[] = {
@@ -132,12 +131,12 @@ intel_attach_broadcast_rgb_property(struct drm_connector *connector)
prop = drm_property_create_enum(dev, DRM_MODE_PROP_ENUM,
"Broadcast RGB",
broadcast_rgb_names,
- DRM_ARRAY_SIZE(broadcast_rgb_names));
+ ARRAY_SIZE(broadcast_rgb_names));
if (prop == NULL)
return;
dev_priv->broadcast_rgb_property = prop;
}
- drm_connector_attach_property(connector, prop, 0);
+ drm_object_attach_property(&connector->base, prop, 0);
}
diff --git a/sys/dev/drm2/i915/intel_opregion.c b/sys/dev/drm2/i915/intel_opregion.c
index 7b02f71..411e530 100644
--- a/sys/dev/drm2/i915/intel_opregion.c
+++ b/sys/dev/drm2/i915/intel_opregion.c
@@ -147,7 +147,7 @@ struct opregion_asle {
#define ACPI_DIGITAL_OUTPUT (3<<8)
#define ACPI_LVDS_OUTPUT (4<<8)
-#if 1
+#if defined(CONFIG_ACPI)
static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -350,7 +350,7 @@ static void intel_didl_outputs(struct drm_device *dev)
ACPI_STATUS status;
int i = 0;
- handle = acpi_get_handle(dev->device);
+ handle = acpi_get_handle(dev->dev);
if (!handle)
return;
@@ -377,7 +377,7 @@ static void intel_didl_outputs(struct drm_device *dev)
}
if (!acpi_video_bus) {
- device_printf(dev->device, "No ACPI video bus found\n");
+ device_printf(dev->dev, "No ACPI video bus found\n");
return;
}
@@ -385,7 +385,7 @@ static void intel_didl_outputs(struct drm_device *dev)
while (AcpiGetNextObject(ACPI_TYPE_DEVICE, acpi_video_bus, acpi_cdev,
&acpi_cdev) != AE_NOT_FOUND) {
if (i >= 8) {
- device_printf(dev->device, "More than 8 outputs detected\n");
+ device_printf(dev->dev, "More than 8 outputs detected\n");
return;
}
status = acpi_GetInteger(acpi_cdev, "_ADR", &device_id);
@@ -426,7 +426,7 @@ blind_set:
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
int output_type = ACPI_OTHER_OUTPUT;
if (i >= 8) {
- device_printf(dev->device,
+ device_printf(dev->dev,
"More than 8 outputs detected\n");
return;
}
@@ -569,7 +569,7 @@ int intel_opregion_setup(struct drm_device *dev)
u32 asls, mboxes;
int err = 0;
- asls = pci_read_config(dev->device, PCI_ASLS, 4);
+ asls = pci_read_config(dev->dev, PCI_ASLS, 4);
DRM_DEBUG("graphic opregion physical addr: 0x%x\n", asls);
if (asls == 0) {
DRM_DEBUG("ACPI OpRegion not supported!\n");
diff --git a/sys/dev/drm2/i915/intel_overlay.c b/sys/dev/drm2/i915/intel_overlay.c
index 715da2f..94b8d5d 100644
--- a/sys/dev/drm2/i915/intel_overlay.c
+++ b/sys/dev/drm2/i915/intel_overlay.c
@@ -774,7 +774,6 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
KASSERT(overlay != NULL, ("No overlay ?"));
DRM_LOCK_ASSERT(overlay->dev);
- DRM_MODE_CONFIG_ASSERT_LOCKED(overlay->dev);
ret = intel_overlay_release_old_vid(overlay);
if (ret != 0)
@@ -877,7 +876,6 @@ int intel_overlay_switch_off(struct intel_overlay *overlay)
int ret;
DRM_LOCK_ASSERT(overlay->dev);
- DRM_MODE_CONFIG_ASSERT_LOCKED(overlay->dev);
ret = intel_overlay_recover_from_interrupt(overlay);
if (ret != 0)
@@ -1458,8 +1456,8 @@ void intel_setup_overlay(struct drm_device *dev)
intel_overlay_unmap_regs(overlay, regs);
dev_priv->overlay = overlay;
- DRM_INFO("initialized overlay support\n");
DRM_UNLOCK(dev);
+ DRM_INFO("initialized overlay support\n");
return;
out_unpin_bo:
diff --git a/sys/dev/drm2/i915/intel_panel.c b/sys/dev/drm2/i915/intel_panel.c
index ef60f49..2d4210d 100644
--- a/sys/dev/drm2/i915/intel_panel.c
+++ b/sys/dev/drm2/i915/intel_panel.c
@@ -226,7 +226,7 @@ u32 intel_panel_get_backlight(struct drm_device *dev)
if (is_backlight_combination_mode(dev)) {
u8 lbpc;
- lbpc = pci_read_config(dev->device, PCI_LBPC, 1);
+ lbpc = pci_read_config(dev->dev, PCI_LBPC, 1);
val *= lbpc;
}
}
@@ -260,7 +260,7 @@ static void intel_panel_actually_set_backlight(struct drm_device *dev, u32 level
lbpc = level * 0xfe / max + 1;
level /= lbpc;
- pci_write_config(dev->device, PCI_LBPC, lbpc, 4);
+ pci_write_config(dev->dev, PCI_LBPC, lbpc, 4);
}
tmp = I915_READ(BLC_PWM_CTL);
diff --git a/sys/dev/drm2/i915/intel_ringbuffer.c b/sys/dev/drm2/i915/intel_ringbuffer.c
index d373865..2251220 100644
--- a/sys/dev/drm2/i915/intel_ringbuffer.c
+++ b/sys/dev/drm2/i915/intel_ringbuffer.c
@@ -1206,16 +1206,11 @@ int intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n)
return 0;
}
-#if 0
if (dev->primary->master) {
struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
if (master_priv->sarea_priv)
master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
}
-#else
- if (dev_priv->sarea_priv)
- dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
-#endif
pause("915rng", 1);
if (atomic_load_acq_32(&dev_priv->mm.wedged) != 0) {
diff --git a/sys/dev/drm2/i915/intel_sdvo.c b/sys/dev/drm2/i915/intel_sdvo.c
index 74e479a..91056d7 100644
--- a/sys/dev/drm2/i915/intel_sdvo.c
+++ b/sys/dev/drm2/i915/intel_sdvo.c
@@ -416,20 +416,20 @@ static void intel_sdvo_debug_write(struct intel_sdvo *intel_sdvo, u8 cmd,
{
int i;
- if ((drm_debug_flag & DRM_DEBUGBITS_KMS) == 0)
+ if ((drm_debug & DRM_DEBUGBITS_KMS) == 0)
return;
DRM_DEBUG_KMS("%s: W: %02X ", SDVO_NAME(intel_sdvo), cmd);
for (i = 0; i < args_len; i++)
printf("%02X ", ((const u8 *)args)[i]);
for (; i < 8; i++)
printf(" ");
- for (i = 0; i < DRM_ARRAY_SIZE(sdvo_cmd_names); i++) {
+ for (i = 0; i < ARRAY_SIZE(sdvo_cmd_names); i++) {
if (cmd == sdvo_cmd_names[i].cmd) {
printf("(%s)", sdvo_cmd_names[i].name);
break;
}
}
- if (i == DRM_ARRAY_SIZE(sdvo_cmd_names))
+ if (i == ARRAY_SIZE(sdvo_cmd_names))
printf("(%02X)", cmd);
printf("\n");
}
@@ -525,7 +525,7 @@ intel_sdvo_read_response(struct intel_sdvo *intel_sdvo, void *response,
goto log_fail;
}
- if ((drm_debug_flag & DRM_DEBUGBITS_KMS) != 0) {
+ if ((drm_debug & DRM_DEBUGBITS_KMS) != 0) {
if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP)
printf("(%s)", cmd_status_names[status]);
else
@@ -541,15 +541,15 @@ intel_sdvo_read_response(struct intel_sdvo *intel_sdvo, void *response,
SDVO_I2C_RETURN_0 + i,
&((u8 *)response)[i]))
goto log_fail;
- if ((drm_debug_flag & DRM_DEBUGBITS_KMS) != 0)
+ if ((drm_debug & DRM_DEBUGBITS_KMS) != 0)
printf(" %02X", ((u8 *)response)[i]);
}
- if ((drm_debug_flag & DRM_DEBUGBITS_KMS) != 0)
+ if ((drm_debug & DRM_DEBUGBITS_KMS) != 0)
printf("\n");
return (true);
log_fail:
- if ((drm_debug_flag & DRM_DEBUGBITS_KMS) != 0)
+ if ((drm_debug & DRM_DEBUGBITS_KMS) != 0)
printf("... failed\n");
return (false);
}
@@ -972,7 +972,7 @@ intel_sdvo_set_input_timings_for_mode(struct intel_sdvo *intel_sdvo,
}
static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
+ const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct intel_sdvo *intel_sdvo = to_intel_sdvo(encoder);
@@ -1332,7 +1332,6 @@ intel_sdvo_tmds_sink_detect(struct drm_connector *connector)
}
} else
status = connector_status_disconnected;
- connector->display_info.raw_edid = NULL;
free(edid, DRM_MEM_KMS);
}
@@ -1406,7 +1405,6 @@ intel_sdvo_detect(struct drm_connector *connector, bool force)
else
ret = connector_status_disconnected;
- connector->display_info.raw_edid = NULL;
free(edid, DRM_MEM_KMS);
} else
ret = connector_status_connected;
@@ -1452,7 +1450,6 @@ static void intel_sdvo_get_ddc_modes(struct drm_connector *connector)
drm_add_edid_modes(connector, edid);
}
- connector->display_info.raw_edid = NULL;
free(edid, DRM_MEM_KMS);
}
}
@@ -1547,7 +1544,7 @@ static void intel_sdvo_get_tv_modes(struct drm_connector *connector)
if (!intel_sdvo_read_response(intel_sdvo, &reply, 3))
return;
- for (i = 0; i < DRM_ARRAY_SIZE(sdvo_tv_modes); i++)
+ for (i = 0; i < ARRAY_SIZE(sdvo_tv_modes); i++)
if (reply & (1 << i)) {
struct drm_display_mode *nmode;
nmode = drm_mode_duplicate(connector->dev,
@@ -1697,7 +1694,7 @@ intel_sdvo_set_property(struct drm_connector *connector,
uint8_t cmd;
int ret;
- ret = drm_connector_property_set_value(connector, property, val);
+ ret = drm_object_property_set_value(&connector->base, property, val);
if (ret)
return ret;
@@ -1752,7 +1749,7 @@ intel_sdvo_set_property(struct drm_connector *connector,
} else if (IS_TV_OR_LVDS(intel_sdvo_connector)) {
temp_value = val;
if (intel_sdvo_connector->left == property) {
- drm_connector_property_set_value(connector,
+ drm_object_property_set_value(&connector->base,
intel_sdvo_connector->right, val);
if (intel_sdvo_connector->left_margin == temp_value)
return 0;
@@ -1764,7 +1761,7 @@ intel_sdvo_set_property(struct drm_connector *connector,
cmd = SDVO_CMD_SET_OVERSCAN_H;
goto set_value;
} else if (intel_sdvo_connector->right == property) {
- drm_connector_property_set_value(connector,
+ drm_object_property_set_value(&connector->base,
intel_sdvo_connector->left, val);
if (intel_sdvo_connector->right_margin == temp_value)
return 0;
@@ -1776,7 +1773,7 @@ intel_sdvo_set_property(struct drm_connector *connector,
cmd = SDVO_CMD_SET_OVERSCAN_H;
goto set_value;
} else if (intel_sdvo_connector->top == property) {
- drm_connector_property_set_value(connector,
+ drm_object_property_set_value(&connector->base,
intel_sdvo_connector->bottom, val);
if (intel_sdvo_connector->top_margin == temp_value)
return 0;
@@ -1788,7 +1785,7 @@ intel_sdvo_set_property(struct drm_connector *connector,
cmd = SDVO_CMD_SET_OVERSCAN_V;
goto set_value;
} else if (intel_sdvo_connector->bottom == property) {
- drm_connector_property_set_value(connector,
+ drm_object_property_set_value(&connector->base,
intel_sdvo_connector->top, val);
if (intel_sdvo_connector->bottom_margin == temp_value)
return 0;
@@ -1863,7 +1860,7 @@ static void intel_sdvo_enc_destroy(struct drm_encoder *encoder)
drm_mode_destroy(encoder->dev,
intel_sdvo->sdvo_lvds_fixed_mode);
- device_delete_child(intel_sdvo->base.base.dev->device,
+ device_delete_child(intel_sdvo->base.base.dev->dev,
intel_sdvo->ddc_iic_bus);
intel_encoder_destroy(encoder);
}
@@ -2294,7 +2291,7 @@ static bool intel_sdvo_tv_create_property(struct intel_sdvo *intel_sdvo,
i, tv_format_names[intel_sdvo_connector->tv_format_supported[i]]);
intel_sdvo->tv_format_index = intel_sdvo_connector->tv_format_supported[0];
- drm_connector_attach_property(&intel_sdvo_connector->base.base,
+ drm_object_attach_property(&intel_sdvo_connector->base.base.base,
intel_sdvo_connector->tv_format, 0);
return true;
@@ -2310,7 +2307,7 @@ static bool intel_sdvo_tv_create_property(struct intel_sdvo *intel_sdvo,
intel_sdvo_connector->name = \
drm_property_create_range(dev, 0, #name, 0, data_value[0]); \
if (!intel_sdvo_connector->name) return false; \
- drm_connector_attach_property(connector, \
+ drm_object_attach_property(&connector->base, \
intel_sdvo_connector->name, \
intel_sdvo_connector->cur_##name); \
DRM_DEBUG_KMS(#name ": max %d, default %d, current %d\n", \
@@ -2347,7 +2344,7 @@ intel_sdvo_create_enhance_property_tv(struct intel_sdvo *intel_sdvo,
if (!intel_sdvo_connector->left)
return false;
- drm_connector_attach_property(connector,
+ drm_object_attach_property(&connector->base,
intel_sdvo_connector->left,
intel_sdvo_connector->left_margin);
@@ -2356,7 +2353,7 @@ intel_sdvo_create_enhance_property_tv(struct intel_sdvo *intel_sdvo,
if (!intel_sdvo_connector->right)
return false;
- drm_connector_attach_property(connector,
+ drm_object_attach_property(&connector->base,
intel_sdvo_connector->right,
intel_sdvo_connector->right_margin);
DRM_DEBUG_KMS("h_overscan: max %d, "
@@ -2384,7 +2381,7 @@ intel_sdvo_create_enhance_property_tv(struct intel_sdvo *intel_sdvo,
if (!intel_sdvo_connector->top)
return false;
- drm_connector_attach_property(connector,
+ drm_object_attach_property(&connector->base,
intel_sdvo_connector->top,
intel_sdvo_connector->top_margin);
@@ -2394,7 +2391,7 @@ intel_sdvo_create_enhance_property_tv(struct intel_sdvo *intel_sdvo,
if (!intel_sdvo_connector->bottom)
return false;
- drm_connector_attach_property(connector,
+ drm_object_attach_property(&connector->base,
intel_sdvo_connector->bottom,
intel_sdvo_connector->bottom_margin);
DRM_DEBUG_KMS("v_overscan: max %d, "
@@ -2426,7 +2423,7 @@ intel_sdvo_create_enhance_property_tv(struct intel_sdvo *intel_sdvo,
if (!intel_sdvo_connector->dot_crawl)
return false;
- drm_connector_attach_property(connector,
+ drm_object_attach_property(&connector->base,
intel_sdvo_connector->dot_crawl,
intel_sdvo_connector->cur_dot_crawl);
DRM_DEBUG_KMS("dot crawl: current %d\n", response);
@@ -2553,7 +2550,7 @@ intel_sdvo_init_ddc_proxy(struct intel_sdvo *sdvo, struct drm_device *dev,
struct intel_sdvo_ddc_proxy_sc *sc;
int ret;
- sdvo->ddc_iic_bus = device_add_child(dev->device,
+ sdvo->ddc_iic_bus = device_add_child(dev->dev,
"intel_sdvo_ddc_proxy", sdvo_reg);
if (sdvo->ddc_iic_bus == NULL) {
DRM_ERROR("cannot create ddc proxy bus %d\n", sdvo_reg);
@@ -2564,7 +2561,7 @@ intel_sdvo_init_ddc_proxy(struct intel_sdvo *sdvo, struct drm_device *dev,
if (ret != 0) {
DRM_ERROR("cannot attach proxy bus %d error %d\n",
sdvo_reg, ret);
- device_delete_child(dev->device, sdvo->ddc_iic_bus);
+ device_delete_child(dev->dev, sdvo->ddc_iic_bus);
return (false);
}
sc = device_get_softc(sdvo->ddc_iic_bus);
diff --git a/sys/dev/drm2/i915/intel_tv.c b/sys/dev/drm2/i915/intel_tv.c
index ddc6c97..bc276d8 100644
--- a/sys/dev/drm2/i915/intel_tv.c
+++ b/sys/dev/drm2/i915/intel_tv.c
@@ -846,7 +846,7 @@ intel_tv_mode_valid(struct drm_connector *connector,
static bool
-intel_tv_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
+intel_tv_mode_fixup(struct drm_encoder *encoder, const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct drm_device *dev = encoder->dev;
@@ -1233,7 +1233,7 @@ static void intel_tv_find_better_format(struct drm_connector *connector)
}
intel_tv->tv_format = tv_mode->name;
- drm_connector_property_set_value(connector,
+ drm_object_property_set_value(&connector->base,
connector->dev->mode_config.tv_mode_property, i);
}
@@ -1326,7 +1326,7 @@ intel_tv_get_modes(struct drm_connector *connector)
int j, count = 0;
u64 tmp;
- for (j = 0; j < DRM_ARRAY_SIZE(input_res_table);
+ for (j = 0; j < ARRAY_SIZE(input_res_table);
j++) {
const struct input_res *input = &input_res_table[j];
unsigned int hactive_s = input->w;
@@ -1393,7 +1393,7 @@ intel_tv_set_property(struct drm_connector *connector, struct drm_property *prop
int ret = 0;
bool changed = false;
- ret = drm_connector_property_set_value(connector, property, val);
+ ret = drm_object_property_set_value(&connector->base, property, val);
if (ret < 0)
goto out;
@@ -1414,7 +1414,7 @@ intel_tv_set_property(struct drm_connector *connector, struct drm_property *prop
intel_tv->margin[TV_MARGIN_BOTTOM] = val;
changed = true;
} else if (property == dev->mode_config.tv_mode_property) {
- if (val >= DRM_ARRAY_SIZE(tv_modes)) {
+ if (val >= ARRAY_SIZE(tv_modes)) {
ret = -EINVAL;
goto out;
}
@@ -1506,7 +1506,7 @@ intel_tv_init(struct drm_device *dev)
struct intel_encoder *intel_encoder;
struct intel_connector *intel_connector;
u32 tv_dac_on, tv_dac_off, save_tv_dac;
- char *tv_format_names[DRM_ARRAY_SIZE(tv_modes)];
+ char *tv_format_names[ARRAY_SIZE(tv_modes)];
int i, initial_mode = 0;
if ((I915_READ(TV_CTL) & TV_FUSE_STATE_MASK) == TV_FUSE_STATE_DISABLED)
@@ -1590,24 +1590,24 @@ intel_tv_init(struct drm_device *dev)
connector->doublescan_allowed = false;
/* Create TV properties then attach current values */
- for (i = 0; i < DRM_ARRAY_SIZE(tv_modes); i++)
+ for (i = 0; i < ARRAY_SIZE(tv_modes); i++)
tv_format_names[i] = __DECONST(char *, tv_modes[i].name);
drm_mode_create_tv_properties(dev,
- DRM_ARRAY_SIZE(tv_modes),
+ ARRAY_SIZE(tv_modes),
tv_format_names);
- drm_connector_attach_property(connector, dev->mode_config.tv_mode_property,
+ drm_object_attach_property(&connector->base, dev->mode_config.tv_mode_property,
initial_mode);
- drm_connector_attach_property(connector,
+ drm_object_attach_property(&connector->base,
dev->mode_config.tv_left_margin_property,
intel_tv->margin[TV_MARGIN_LEFT]);
- drm_connector_attach_property(connector,
+ drm_object_attach_property(&connector->base,
dev->mode_config.tv_top_margin_property,
intel_tv->margin[TV_MARGIN_TOP]);
- drm_connector_attach_property(connector,
+ drm_object_attach_property(&connector->base,
dev->mode_config.tv_right_margin_property,
intel_tv->margin[TV_MARGIN_RIGHT]);
- drm_connector_attach_property(connector,
+ drm_object_attach_property(&connector->base,
dev->mode_config.tv_bottom_margin_property,
intel_tv->margin[TV_MARGIN_BOTTOM]);
#if 0
diff --git a/sys/dev/drm2/radeon/atom.c b/sys/dev/drm2/radeon/atom.c
index 7cecd07..f4ca5e9 100644
--- a/sys/dev/drm2/radeon/atom.c
+++ b/sys/dev/drm2/radeon/atom.c
@@ -661,9 +661,9 @@ static void atom_op_delay(atom_exec_context *ctx, int *ptr, int arg)
unsigned count = U8((*ptr)++);
ATOM_SDEBUG_PRINT(" count: %d\n", count);
if (arg == ATOM_UNIT_MICROSEC)
- DRM_UDELAY(count);
+ udelay(count);
else if (!drm_can_sleep())
- DRM_MDELAY(count);
+ mdelay(count);
else
DRM_MSLEEP(count);
}
@@ -1178,7 +1178,7 @@ static int atom_execute_table_locked(struct atom_context *ctx, int index, uint32
ectx.abort = false;
ectx.last_jump = 0;
if (ws)
- ectx.ws = malloc(4 * ws, DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
+ ectx.ws = malloc(4 * ws, DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
else
ectx.ws = NULL;
@@ -1234,7 +1234,7 @@ static int atom_iio_len[] = { 1, 2, 3, 3, 3, 3, 4, 4, 4, 3 };
static void atom_index_iio(struct atom_context *ctx, int base)
{
- ctx->iio = malloc(2 * 256, DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
+ ctx->iio = malloc(2 * 256, DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
while (CU8(base) == ATOM_IIO_START) {
ctx->iio[CU8(base + 1)] = base + 2;
base += 2;
@@ -1248,7 +1248,7 @@ struct atom_context *atom_parse(struct card_info *card, void *bios)
{
int base;
struct atom_context *ctx =
- malloc(sizeof(struct atom_context), DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
+ malloc(sizeof(struct atom_context), DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
char *str;
char name[512];
int i;
@@ -1386,16 +1386,16 @@ int atom_allocate_fb_scratch(struct atom_context *ctx)
firmware_usage = (struct _ATOM_VRAM_USAGE_BY_FIRMWARE *)((char *)ctx->bios + data_offset);
DRM_DEBUG("atom firmware requested %08x %dkb\n",
- firmware_usage->asFirmwareVramReserveInfo[0].ulStartAddrUsedByFirmware,
- firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb);
+ le32_to_cpu(firmware_usage->asFirmwareVramReserveInfo[0].ulStartAddrUsedByFirmware),
+ le16_to_cpu(firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb));
- usage_bytes = firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb * 1024;
+ usage_bytes = le16_to_cpu(firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb) * 1024;
}
ctx->scratch_size_bytes = 0;
if (usage_bytes == 0)
usage_bytes = 20 * 1024;
/* allocate some scratch memory */
- ctx->scratch = malloc(usage_bytes, DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
+ ctx->scratch = malloc(usage_bytes, DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (!ctx->scratch)
return -ENOMEM;
ctx->scratch_size_bytes = usage_bytes;
diff --git a/sys/dev/drm2/radeon/atombios_crtc.c b/sys/dev/drm2/radeon/atombios_crtc.c
index c4c5c46..0be4cf2 100644
--- a/sys/dev/drm2/radeon/atombios_crtc.c
+++ b/sys/dev/drm2/radeon/atombios_crtc.c
@@ -256,8 +256,6 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode)
radeon_crtc->enabled = true;
/* adjust pm to dpms changes BEFORE enabling crtcs */
radeon_pm_compute_clocks(rdev);
- if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set)
- atombios_powergate_crtc(crtc, ATOM_DISABLE);
atombios_enable_crtc(crtc, ATOM_ENABLE);
if (ASIC_IS_DCE3(rdev) && !ASIC_IS_DCE6(rdev))
atombios_enable_crtc_memreq(crtc, ATOM_ENABLE);
@@ -275,8 +273,6 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode)
atombios_enable_crtc_memreq(crtc, ATOM_DISABLE);
atombios_enable_crtc(crtc, ATOM_DISABLE);
radeon_crtc->enabled = false;
- if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set)
- atombios_powergate_crtc(crtc, ATOM_ENABLE);
/* adjust pm to dpms changes AFTER disabling crtcs */
radeon_pm_compute_clocks(rdev);
break;
@@ -565,6 +561,9 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
/* use frac fb div on APUs */
if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev))
radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV;
+ /* use frac fb div on RS780/RS880 */
+ if ((rdev->family == CHIP_RS780) || (rdev->family == CHIP_RS880))
+ radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV;
if (ASIC_IS_DCE32(rdev) && mode->clock > 165000)
radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV;
} else {
@@ -1848,6 +1847,8 @@ static void atombios_crtc_disable(struct drm_crtc *crtc)
int i;
atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
+ if (ASIC_IS_DCE6(rdev))
+ atombios_powergate_crtc(crtc, ATOM_ENABLE);
for (i = 0; i < rdev->num_crtc; i++) {
if (rdev->mode_info.crtcs[i] &&
diff --git a/sys/dev/drm2/radeon/atombios_dp.c b/sys/dev/drm2/radeon/atombios_dp.c
index f92df62..1a3f4e1 100644
--- a/sys/dev/drm2/radeon/atombios_dp.c
+++ b/sys/dev/drm2/radeon/atombios_dp.c
@@ -140,7 +140,7 @@ static int radeon_dp_aux_native_write(struct radeon_connector *radeon_connector,
if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK)
return send_bytes;
else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER)
- DRM_UDELAY(400);
+ udelay(400);
else
return -EIO;
}
@@ -173,7 +173,7 @@ static int radeon_dp_aux_native_read(struct radeon_connector *radeon_connector,
if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK)
return ret;
else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER)
- DRM_UDELAY(400);
+ udelay(400);
else if (ret == 0)
return -EPROTO;
else
@@ -261,7 +261,7 @@ int radeon_dp_i2c_aux_ch(device_t dev, int mode, u8 write_byte, u8 *read_byte)
return -EREMOTEIO;
case AUX_NATIVE_REPLY_DEFER:
DRM_DEBUG_KMS("aux_ch native defer\n");
- DRM_UDELAY(400);
+ udelay(400);
continue;
default:
DRM_ERROR("aux_ch invalid native reply 0x%02x\n", ack);
@@ -272,13 +272,13 @@ int radeon_dp_i2c_aux_ch(device_t dev, int mode, u8 write_byte, u8 *read_byte)
case AUX_I2C_REPLY_ACK:
if (mode == MODE_I2C_READ)
*read_byte = reply[0];
- return (0); /* Return ret on Linux. */
+ return ret;
case AUX_I2C_REPLY_NACK:
DRM_DEBUG_KMS("aux_i2c nack\n");
return -EREMOTEIO;
case AUX_I2C_REPLY_DEFER:
DRM_DEBUG_KMS("aux_i2c defer\n");
- DRM_UDELAY(400);
+ udelay(400);
break;
default:
DRM_ERROR("aux_i2c invalid reply 0x%02x\n", ack);
@@ -685,7 +685,7 @@ static int radeon_dp_link_train_init(struct radeon_dp_link_train_info *dp_info)
static int radeon_dp_link_train_finish(struct radeon_dp_link_train_info *dp_info)
{
- DRM_UDELAY(400);
+ udelay(400);
/* disable the training pattern on the sink */
radeon_write_dpcd_reg(dp_info->radeon_connector,
@@ -713,7 +713,7 @@ static int radeon_dp_link_train_cr(struct radeon_dp_link_train_info *dp_info)
memset(dp_info->train_set, 0, 4);
radeon_dp_update_vs_emph(dp_info);
- DRM_UDELAY(400);
+ udelay(400);
/* clock recovery loop */
clock_recovery = false;
diff --git a/sys/dev/drm2/radeon/atombios_encoders.c b/sys/dev/drm2/radeon/atombios_encoders.c
index 9128aac..3ee6fc5 100644
--- a/sys/dev/drm2/radeon/atombios_encoders.c
+++ b/sys/dev/drm2/radeon/atombios_encoders.c
@@ -197,7 +197,7 @@ void radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder,
if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU))
return;
- pdata = malloc(sizeof(struct radeon_backlight_privdata), DRM_MEM_DRIVER, M_WAITOK);
+ pdata = malloc(sizeof(struct radeon_backlight_privdata), DRM_MEM_DRIVER, M_NOWAIT);
if (!pdata) {
DRM_ERROR("Memory allocation failed\n");
goto error;
@@ -279,6 +279,12 @@ static void radeon_atom_backlight_exit(struct radeon_encoder *encoder)
#endif
+#ifdef FREEBSD_WIP /* FreeBSD: to please GCC 4.2. */
+/* evil but including atombios.h is much worse */
+bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
+ struct drm_display_mode *mode);
+#endif
+
static inline bool radeon_encoder_is_digital(struct drm_encoder *encoder)
{
@@ -302,7 +308,7 @@ static inline bool radeon_encoder_is_digital(struct drm_encoder *encoder)
}
static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
+ const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
@@ -1342,7 +1348,7 @@ atombios_set_edp_panel_power(struct drm_connector *connector, int action)
for (i = 0; i < 300; i++) {
if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd))
return true;
- DRM_MDELAY(1);
+ mdelay(1);
}
return false;
}
@@ -2451,7 +2457,7 @@ radeon_atom_ext_dpms(struct drm_encoder *encoder, int mode)
}
static bool radeon_atom_ext_mode_fixup(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
+ const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
return true;
@@ -2506,7 +2512,7 @@ radeon_atombios_set_dac_info(struct radeon_encoder *radeon_encoder)
struct drm_device *dev = radeon_encoder->base.dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_encoder_atom_dac *dac = malloc(sizeof(struct radeon_encoder_atom_dac),
- DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (!dac)
return NULL;
@@ -2520,7 +2526,7 @@ radeon_atombios_set_dig_info(struct radeon_encoder *radeon_encoder)
{
int encoder_enum = (radeon_encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT;
struct radeon_encoder_atom_dig *dig = malloc(sizeof(struct radeon_encoder_atom_dig),
- DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (!dig)
return NULL;
@@ -2559,7 +2565,7 @@ radeon_add_atom_encoder(struct drm_device *dev,
/* add a new one */
radeon_encoder = malloc(sizeof(struct radeon_encoder),
- DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (!radeon_encoder)
return;
diff --git a/sys/dev/drm2/radeon/atombios_i2c.c b/sys/dev/drm2/radeon/atombios_i2c.c
index 40ba15b..fb57ff9 100644
--- a/sys/dev/drm2/radeon/atombios_i2c.c
+++ b/sys/dev/drm2/radeon/atombios_i2c.c
@@ -60,10 +60,17 @@ static int radeon_process_i2c_ch(struct radeon_i2c_chan *chan,
if (flags & HW_I2C_WRITE) {
if (num > ATOM_MAX_HW_I2C_WRITE) {
DRM_ERROR("hw i2c: tried to write too many bytes (%d vs 2)\n", num);
- return EINVAL;
+ return -EINVAL;
}
memcpy(&out, buf, num);
args.lpI2CDataOut = cpu_to_le16(out);
+ } else {
+#ifdef FREEBSD_WIP /* FreeBSD: to please GCC 4.2. */
+ if (num > ATOM_MAX_HW_I2C_READ) {
+ DRM_ERROR("hw i2c: tried to read too many bytes (%d vs 255)\n", num);
+ return -EINVAL;
+ }
+#endif
}
args.ucI2CSpeed = TARGET_HW_I2C_CLOCK;
@@ -77,7 +84,7 @@ static int radeon_process_i2c_ch(struct radeon_i2c_chan *chan,
/* error */
if (args.ucStatus != HW_ASSISTED_I2C_STATUS_SUCCESS) {
DRM_DEBUG_KMS("hw_i2c error\n");
- return EIO;
+ return -EIO;
}
if (!(flags & HW_I2C_WRITE))
@@ -101,9 +108,9 @@ radeon_atom_hw_i2c_xfer(device_t dev, struct iic_msg *msgs, u_int num)
p->slave, HW_I2C_WRITE,
&buf, 1);
if (ret)
- return ret;
+ return -ret; /* "ret" is returned on Linux. */
else
- return (0);
+ return (0); /* "num" is returned on Linux. */
}
for (i = 0; i < num; i++) {
@@ -127,13 +134,13 @@ radeon_atom_hw_i2c_xfer(device_t dev, struct iic_msg *msgs, u_int num)
p->slave, flags,
&p->buf[buffer_offset], current_count);
if (ret)
- return ret;
+ return -ret; /* "ret" is returned on Linux. */
remaining -= current_count;
buffer_offset += current_count;
}
}
- return (0);
+ return (0); /* "num" is returned on Linux. */
}
static int
diff --git a/sys/dev/drm2/radeon/cayman_blit_shaders.c b/sys/dev/drm2/radeon/cayman_blit_shaders.c
index 779f305..6130250 100644
--- a/sys/dev/drm2/radeon/cayman_blit_shaders.c
+++ b/sys/dev/drm2/radeon/cayman_blit_shaders.c
@@ -370,6 +370,6 @@ const u32 cayman_ps[] =
0x00000000,
};
-const u32 cayman_ps_size = DRM_ARRAY_SIZE(cayman_ps);
-const u32 cayman_vs_size = DRM_ARRAY_SIZE(cayman_vs);
-const u32 cayman_default_size = DRM_ARRAY_SIZE(cayman_default_state);
+const u32 cayman_ps_size = ARRAY_SIZE(cayman_ps);
+const u32 cayman_vs_size = ARRAY_SIZE(cayman_vs);
+const u32 cayman_default_size = ARRAY_SIZE(cayman_default_state);
diff --git a/sys/dev/drm2/radeon/evergreen.c b/sys/dev/drm2/radeon/evergreen.c
index 3c98d53..4643d62 100644
--- a/sys/dev/drm2/radeon/evergreen.c
+++ b/sys/dev/drm2/radeon/evergreen.c
@@ -49,7 +49,14 @@ static const u32 crtc_offsets[6] =
};
static void evergreen_gpu_init(struct radeon_device *rdev);
+#ifdef FREEBSD_WIP /* FreeBSD: to please GCC 4.2. */
+void evergreen_fini(struct radeon_device *rdev);
+#endif
void evergreen_pcie_gen2_enable(struct radeon_device *rdev);
+#ifdef FREEBSD_WIP /* FreeBSD: to please GCC 4.2. */
+extern void cayman_cp_int_cntl_setup(struct radeon_device *rdev,
+ int ring, u32 cp_int_cntl);
+#endif
void evergreen_tiling_fields(unsigned tiling_flags, unsigned *bankw,
unsigned *bankh, unsigned *mtaspect,
@@ -107,6 +114,27 @@ void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev)
}
}
+static bool dce4_is_in_vblank(struct radeon_device *rdev, int crtc)
+{
+ if (RREG32(EVERGREEN_CRTC_STATUS + crtc_offsets[crtc]) & EVERGREEN_CRTC_V_BLANK)
+ return true;
+ else
+ return false;
+}
+
+static bool dce4_is_counter_moving(struct radeon_device *rdev, int crtc)
+{
+ u32 pos1, pos2;
+
+ pos1 = RREG32(EVERGREEN_CRTC_STATUS_POSITION + crtc_offsets[crtc]);
+ pos2 = RREG32(EVERGREEN_CRTC_STATUS_POSITION + crtc_offsets[crtc]);
+
+ if (pos1 != pos2)
+ return true;
+ else
+ return false;
+}
+
/**
* dce4_wait_for_vblank - vblank wait asic callback.
*
@@ -117,21 +145,28 @@ void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev)
*/
void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc)
{
- int i;
+ unsigned i = 0;
if (crtc >= rdev->num_crtc)
return;
- if (RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[crtc]) & EVERGREEN_CRTC_MASTER_EN) {
- for (i = 0; i < rdev->usec_timeout; i++) {
- if (!(RREG32(EVERGREEN_CRTC_STATUS + crtc_offsets[crtc]) & EVERGREEN_CRTC_V_BLANK))
+ if (!(RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[crtc]) & EVERGREEN_CRTC_MASTER_EN))
+ return;
+
+ /* depending on when we hit vblank, we may be close to active; if so,
+ * wait for another frame.
+ */
+ while (dce4_is_in_vblank(rdev, crtc)) {
+ if (i++ % 100 == 0) {
+ if (!dce4_is_counter_moving(rdev, crtc))
break;
- DRM_UDELAY(1);
}
- for (i = 0; i < rdev->usec_timeout; i++) {
- if (RREG32(EVERGREEN_CRTC_STATUS + crtc_offsets[crtc]) & EVERGREEN_CRTC_V_BLANK)
+ }
+
+ while (!dce4_is_in_vblank(rdev, crtc)) {
+ if (i++ % 100 == 0) {
+ if (!dce4_is_counter_moving(rdev, crtc))
break;
- DRM_UDELAY(1);
}
}
}
@@ -204,7 +239,7 @@ u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
for (i = 0; i < rdev->usec_timeout; i++) {
if (RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING)
break;
- DRM_UDELAY(1);
+ udelay(1);
}
DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
@@ -405,6 +440,19 @@ void evergreen_pm_misc(struct radeon_device *rdev)
rdev->pm.current_vddc = voltage->voltage;
DRM_DEBUG("Setting: vddc: %d\n", voltage->voltage);
}
+
+ /* starting with BTC, there is one state that is used for both
+ * MH and SH. Difference is that we always use the high clock index for
+ * mclk and vddci.
+ */
+ if ((rdev->pm.pm_method == PM_METHOD_PROFILE) &&
+ (rdev->family >= CHIP_BARTS) &&
+ rdev->pm.active_crtc_count &&
+ ((rdev->pm.profile_index == PM_PROFILE_MID_MH_IDX) ||
+ (rdev->pm.profile_index == PM_PROFILE_LOW_MH_IDX)))
+ voltage = &rdev->pm.power_state[req_ps_idx].
+ clock_info[rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx].voltage;
+
/* 0xff01 is a flag rather then an actual voltage */
if (voltage->vddci == 0xff01)
return;
@@ -597,6 +645,16 @@ void evergreen_hpd_init(struct radeon_device *rdev)
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+
+ if (connector->connector_type == DRM_MODE_CONNECTOR_eDP ||
+ connector->connector_type == DRM_MODE_CONNECTOR_LVDS) {
+ /* don't try to enable hpd on eDP or LVDS avoid breaking the
+ * aux dp channel on imac and help (but not completely fix)
+ * https://bugzilla.redhat.com/show_bug.cgi?id=726143
+ * also avoid interrupt storms during dpms.
+ */
+ continue;
+ }
switch (radeon_connector->hpd.hpd) {
case RADEON_HPD_1:
WREG32(DC_HPD1_CONTROL, tmp);
@@ -1146,7 +1204,7 @@ int evergreen_mc_wait_for_idle(struct radeon_device *rdev)
tmp = RREG32(SRBM_STATUS) & 0x1F00;
if (!tmp)
return 0;
- DRM_UDELAY(1);
+ udelay(1);
}
return -1;
}
@@ -1173,7 +1231,7 @@ void evergreen_pcie_gart_tlb_flush(struct radeon_device *rdev)
if (tmp) {
return;
}
- DRM_UDELAY(1);
+ udelay(1);
}
}
@@ -1314,17 +1372,16 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav
tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]);
if (!(tmp & EVERGREEN_CRTC_BLANK_DATA_EN)) {
radeon_wait_for_vblank(rdev, i);
- tmp |= EVERGREEN_CRTC_BLANK_DATA_EN;
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1);
+ tmp |= EVERGREEN_CRTC_BLANK_DATA_EN;
WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp);
- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0);
}
} else {
tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]);
if (!(tmp & EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE)) {
radeon_wait_for_vblank(rdev, i);
- tmp |= EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE;
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1);
+ tmp |= EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE;
WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp);
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0);
}
@@ -1334,8 +1391,17 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav
for (j = 0; j < rdev->usec_timeout; j++) {
if (radeon_get_vblank_counter(rdev, i) != frame_count)
break;
- DRM_UDELAY(1);
+ udelay(1);
}
+
+ /* XXX this is a hack to avoid strange behavior with EFI on certain systems */
+ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1);
+ tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]);
+ tmp &= ~EVERGREEN_CRTC_MASTER_EN;
+ WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp);
+ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0);
+ save->crtc_enabled[i] = false;
+ /* ***** */
} else {
save->crtc_enabled[i] = false;
}
@@ -1352,7 +1418,23 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav
WREG32(MC_SHARED_BLACKOUT_CNTL, blackout | 1);
}
/* wait for the MC to settle */
- DRM_UDELAY(100);
+ udelay(100);
+
+ /* lock double buffered regs */
+ for (i = 0; i < rdev->num_crtc; i++) {
+ if (save->crtc_enabled[i]) {
+ tmp = RREG32(EVERGREEN_GRPH_UPDATE + crtc_offsets[i]);
+ if (!(tmp & EVERGREEN_GRPH_UPDATE_LOCK)) {
+ tmp |= EVERGREEN_GRPH_UPDATE_LOCK;
+ WREG32(EVERGREEN_GRPH_UPDATE + crtc_offsets[i], tmp);
+ }
+ tmp = RREG32(EVERGREEN_MASTER_UPDATE_LOCK + crtc_offsets[i]);
+ if (!(tmp & 1)) {
+ tmp |= 1;
+ WREG32(EVERGREEN_MASTER_UPDATE_LOCK + crtc_offsets[i], tmp);
+ }
+ }
+ }
}
void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save)
@@ -1374,6 +1456,33 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s
WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS_HIGH, upper_32_bits(rdev->mc.vram_start));
WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS, (u32)rdev->mc.vram_start);
+ /* unlock regs and wait for update */
+ for (i = 0; i < rdev->num_crtc; i++) {
+ if (save->crtc_enabled[i]) {
+ tmp = RREG32(EVERGREEN_MASTER_UPDATE_MODE + crtc_offsets[i]);
+ if ((tmp & 0x3) != 0) {
+ tmp &= ~0x3;
+ WREG32(EVERGREEN_MASTER_UPDATE_MODE + crtc_offsets[i], tmp);
+ }
+ tmp = RREG32(EVERGREEN_GRPH_UPDATE + crtc_offsets[i]);
+ if (tmp & EVERGREEN_GRPH_UPDATE_LOCK) {
+ tmp &= ~EVERGREEN_GRPH_UPDATE_LOCK;
+ WREG32(EVERGREEN_GRPH_UPDATE + crtc_offsets[i], tmp);
+ }
+ tmp = RREG32(EVERGREEN_MASTER_UPDATE_LOCK + crtc_offsets[i]);
+ if (tmp & 1) {
+ tmp &= ~1;
+ WREG32(EVERGREEN_MASTER_UPDATE_LOCK + crtc_offsets[i], tmp);
+ }
+ for (j = 0; j < rdev->usec_timeout; j++) {
+ tmp = RREG32(EVERGREEN_GRPH_UPDATE + crtc_offsets[i]);
+ if ((tmp & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING) == 0)
+ break;
+ udelay(1);
+ }
+ }
+ }
+
/* unblackout the MC */
tmp = RREG32(MC_SHARED_BLACKOUT_CNTL);
tmp &= ~BLACKOUT_MODE_MASK;
@@ -1401,13 +1510,13 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s
for (j = 0; j < rdev->usec_timeout; j++) {
if (radeon_get_vblank_counter(rdev, i) != frame_count)
break;
- DRM_UDELAY(1);
+ udelay(1);
}
}
}
/* Unlock vga access */
WREG32(VGA_HDP_CONTROL, save->vga_hdp_control);
- DRM_MDELAY(1);
+ mdelay(1);
WREG32(VGA_RENDER_CONTROL, save->vga_render_control);
}
@@ -1639,7 +1748,7 @@ static int evergreen_cp_resume(struct radeon_device *rdev)
SOFT_RESET_SPI |
SOFT_RESET_SX));
RREG32(GRBM_SOFT_RESET);
- DRM_MDELAY(15);
+ mdelay(15);
WREG32(GRBM_SOFT_RESET, 0);
RREG32(GRBM_SOFT_RESET);
@@ -1675,7 +1784,7 @@ static int evergreen_cp_resume(struct radeon_device *rdev)
WREG32(SCRATCH_UMSK, 0);
}
- DRM_MDELAY(1);
+ mdelay(1);
WREG32(CP_RB_CNTL, tmp);
WREG32(CP_RB_BASE, ring->gpu_addr >> 8);
@@ -2247,7 +2356,7 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
WREG32(PA_CL_ENHANCE, CLIP_VTX_REORDER_ENA | NUM_CLIP_SEQ(3));
- DRM_UDELAY(50);
+ udelay(50);
}
@@ -2373,7 +2482,7 @@ static void evergreen_gpu_soft_reset_gfx(struct radeon_device *rdev)
dev_info(rdev->dev, " GRBM_SOFT_RESET=0x%08X\n", grbm_reset);
WREG32(GRBM_SOFT_RESET, grbm_reset);
(void)RREG32(GRBM_SOFT_RESET);
- DRM_UDELAY(50);
+ udelay(50);
WREG32(GRBM_SOFT_RESET, 0);
(void)RREG32(GRBM_SOFT_RESET);
@@ -2413,7 +2522,7 @@ static void evergreen_gpu_soft_reset_dma(struct radeon_device *rdev)
/* Reset dma */
WREG32(SRBM_SOFT_RESET, SOFT_RESET_DMA);
RREG32(SRBM_SOFT_RESET);
- DRM_UDELAY(50);
+ udelay(50);
WREG32(SRBM_SOFT_RESET, 0);
dev_info(rdev->dev, " R_00D034_DMA_STATUS_REG = 0x%08X\n",
@@ -2447,7 +2556,7 @@ static int evergreen_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
evergreen_gpu_soft_reset_dma(rdev);
/* Wait a little for things to settle down */
- DRM_UDELAY(50);
+ udelay(50);
evergreen_mc_resume(rdev, &save);
return 0;
@@ -2871,7 +2980,7 @@ static void evergreen_irq_disable(struct radeon_device *rdev)
{
r600_disable_interrupts(rdev);
/* Wait and acknowledge irq */
- DRM_MDELAY(1);
+ mdelay(1);
evergreen_irq_ack(rdev);
evergreen_disable_interrupt_state(rdev);
}
diff --git a/sys/dev/drm2/radeon/evergreen_blit_shaders.c b/sys/dev/drm2/radeon/evergreen_blit_shaders.c
index 6db3cef..7121859 100644
--- a/sys/dev/drm2/radeon/evergreen_blit_shaders.c
+++ b/sys/dev/drm2/radeon/evergreen_blit_shaders.c
@@ -353,6 +353,6 @@ const u32 evergreen_ps[] =
0x00000000,
};
-const u32 evergreen_ps_size = DRM_ARRAY_SIZE(evergreen_ps);
-const u32 evergreen_vs_size = DRM_ARRAY_SIZE(evergreen_vs);
-const u32 evergreen_default_size = DRM_ARRAY_SIZE(evergreen_default_state);
+const u32 evergreen_ps_size = ARRAY_SIZE(evergreen_ps);
+const u32 evergreen_vs_size = ARRAY_SIZE(evergreen_vs);
+const u32 evergreen_default_size = ARRAY_SIZE(evergreen_default_state);
diff --git a/sys/dev/drm2/radeon/evergreen_cs.c b/sys/dev/drm2/radeon/evergreen_cs.c
index 1dac265..018ffcc 100644
--- a/sys/dev/drm2/radeon/evergreen_cs.c
+++ b/sys/dev/drm2/radeon/evergreen_cs.c
@@ -40,6 +40,10 @@ __FBSDID("$FreeBSD$");
#define MAX(a,b) (((a)>(b))?(a):(b))
#define MIN(a,b) (((a)<(b))?(a):(b))
+#ifdef FREEBSD_WIP /* FreeBSD: to please GCC 4.2. */
+int r600_dma_cs_next_reloc(struct radeon_cs_parser *p,
+ struct radeon_cs_reloc **cs_reloc);
+#endif
static int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p,
struct radeon_cs_reloc **cs_reloc);
@@ -1292,9 +1296,9 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
int r;
if (p->rdev->family >= CHIP_CAYMAN)
- last_reg = DRM_ARRAY_SIZE(cayman_reg_safe_bm);
+ last_reg = ARRAY_SIZE(cayman_reg_safe_bm);
else
- last_reg = DRM_ARRAY_SIZE(evergreen_reg_safe_bm);
+ last_reg = ARRAY_SIZE(evergreen_reg_safe_bm);
i = (reg >> 7);
if (i >= last_reg) {
@@ -1960,9 +1964,9 @@ static bool evergreen_is_safe_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
u32 last_reg, m, i;
if (p->rdev->family >= CHIP_CAYMAN)
- last_reg = DRM_ARRAY_SIZE(cayman_reg_safe_bm);
+ last_reg = ARRAY_SIZE(cayman_reg_safe_bm);
else
- last_reg = DRM_ARRAY_SIZE(evergreen_reg_safe_bm);
+ last_reg = ARRAY_SIZE(evergreen_reg_safe_bm);
i = (reg >> 7);
if (i >= last_reg) {
@@ -2759,7 +2763,7 @@ int evergreen_cs_parse(struct radeon_cs_parser *p)
if (p->track == NULL) {
/* initialize tracker, we are in kms */
- track = malloc(sizeof(*track), DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
+ track = malloc(sizeof(*track), DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (track == NULL)
return -ENOMEM;
evergreen_cs_track_init(track);
diff --git a/sys/dev/drm2/radeon/evergreen_reg.h b/sys/dev/drm2/radeon/evergreen_reg.h
index 7603168..7d3e9d7 100644
--- a/sys/dev/drm2/radeon/evergreen_reg.h
+++ b/sys/dev/drm2/radeon/evergreen_reg.h
@@ -229,6 +229,8 @@ __FBSDID("$FreeBSD$");
#define EVERGREEN_CRTC_STATUS_POSITION 0x6e90
#define EVERGREEN_MASTER_UPDATE_MODE 0x6ef8
#define EVERGREEN_CRTC_UPDATE_LOCK 0x6ed4
+#define EVERGREEN_MASTER_UPDATE_LOCK 0x6ef4
+#define EVERGREEN_MASTER_UPDATE_MODE 0x6ef8
#define EVERGREEN_DC_GPIO_HPD_MASK 0x64b0
#define EVERGREEN_DC_GPIO_HPD_A 0x64b4
diff --git a/sys/dev/drm2/radeon/ni.c b/sys/dev/drm2/radeon/ni.c
index 1484b3e..57ae00c 100644
--- a/sys/dev/drm2/radeon/ni.c
+++ b/sys/dev/drm2/radeon/ni.c
@@ -34,7 +34,20 @@ __FBSDID("$FreeBSD$");
#include "ni_reg.h"
#include "cayman_blit_shaders.h"
+#ifdef FREEBSD_WIP /* FreeBSD: to please GCC 4.2. */
+extern void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save);
+extern void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save);
+extern int evergreen_mc_wait_for_idle(struct radeon_device *rdev);
+extern void evergreen_mc_program(struct radeon_device *rdev);
+extern void evergreen_irq_suspend(struct radeon_device *rdev);
+extern int evergreen_mc_init(struct radeon_device *rdev);
+extern void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev);
+#endif
extern void evergreen_pcie_gen2_enable(struct radeon_device *rdev);
+#ifdef FREEBSD_WIP /* FreeBSD: to please GCC 4.2. */
+extern void si_rlc_fini(struct radeon_device *rdev);
+extern int si_rlc_init(struct radeon_device *rdev);
+#endif
#define EVERGREEN_PFP_UCODE_SIZE 1120
#define EVERGREEN_PM4_UCODE_SIZE 1376
@@ -48,6 +61,27 @@ extern void evergreen_pcie_gen2_enable(struct radeon_device *rdev);
#define ARUBA_RLC_UCODE_SIZE 1536
+#ifdef __linux__
+/* Firmware Names */
+MODULE_FIRMWARE("radeon/BARTS_pfp.bin");
+MODULE_FIRMWARE("radeon/BARTS_me.bin");
+MODULE_FIRMWARE("radeon/BARTS_mc.bin");
+MODULE_FIRMWARE("radeon/BTC_rlc.bin");
+MODULE_FIRMWARE("radeon/TURKS_pfp.bin");
+MODULE_FIRMWARE("radeon/TURKS_me.bin");
+MODULE_FIRMWARE("radeon/TURKS_mc.bin");
+MODULE_FIRMWARE("radeon/CAICOS_pfp.bin");
+MODULE_FIRMWARE("radeon/CAICOS_me.bin");
+MODULE_FIRMWARE("radeon/CAICOS_mc.bin");
+MODULE_FIRMWARE("radeon/CAYMAN_pfp.bin");
+MODULE_FIRMWARE("radeon/CAYMAN_me.bin");
+MODULE_FIRMWARE("radeon/CAYMAN_mc.bin");
+MODULE_FIRMWARE("radeon/CAYMAN_rlc.bin");
+MODULE_FIRMWARE("radeon/ARUBA_pfp.bin");
+MODULE_FIRMWARE("radeon/ARUBA_me.bin");
+MODULE_FIRMWARE("radeon/ARUBA_rlc.bin");
+#endif
+
#define BTC_IO_MC_REGS_SIZE 29
static const u32 barts_io_mc_regs[BTC_IO_MC_REGS_SIZE][2] = {
@@ -244,7 +278,7 @@ int ni_mc_load_microcode(struct radeon_device *rdev)
for (i = 0; i < rdev->usec_timeout; i++) {
if (RREG32(MC_IO_PAD_CNTL_D0) & MEM_FALL_OUT_CMD)
break;
- DRM_UDELAY(1);
+ udelay(1);
}
if (running)
@@ -478,21 +512,32 @@ static void cayman_gpu_init(struct radeon_device *rdev)
(rdev->ddev->pci_device == 0x9907) ||
(rdev->ddev->pci_device == 0x9908) ||
(rdev->ddev->pci_device == 0x9909) ||
+ (rdev->ddev->pci_device == 0x990B) ||
+ (rdev->ddev->pci_device == 0x990C) ||
+ (rdev->ddev->pci_device == 0x990F) ||
(rdev->ddev->pci_device == 0x9910) ||
- (rdev->ddev->pci_device == 0x9917)) {
+ (rdev->ddev->pci_device == 0x9917) ||
+ (rdev->ddev->pci_device == 0x9999) ||
+ (rdev->ddev->pci_device == 0x999C)) {
rdev->config.cayman.max_simds_per_se = 6;
rdev->config.cayman.max_backends_per_se = 2;
} else if ((rdev->ddev->pci_device == 0x9903) ||
(rdev->ddev->pci_device == 0x9904) ||
(rdev->ddev->pci_device == 0x990A) ||
+ (rdev->ddev->pci_device == 0x990D) ||
+ (rdev->ddev->pci_device == 0x990E) ||
(rdev->ddev->pci_device == 0x9913) ||
- (rdev->ddev->pci_device == 0x9918)) {
+ (rdev->ddev->pci_device == 0x9918) ||
+ (rdev->ddev->pci_device == 0x999D)) {
rdev->config.cayman.max_simds_per_se = 4;
rdev->config.cayman.max_backends_per_se = 2;
} else if ((rdev->ddev->pci_device == 0x9919) ||
(rdev->ddev->pci_device == 0x9990) ||
(rdev->ddev->pci_device == 0x9991) ||
(rdev->ddev->pci_device == 0x9994) ||
+ (rdev->ddev->pci_device == 0x9995) ||
+ (rdev->ddev->pci_device == 0x9996) ||
+ (rdev->ddev->pci_device == 0x999A) ||
(rdev->ddev->pci_device == 0x99A0)) {
rdev->config.cayman.max_simds_per_se = 3;
rdev->config.cayman.max_backends_per_se = 1;
@@ -622,15 +667,28 @@ static void cayman_gpu_init(struct radeon_device *rdev)
WREG32(GB_ADDR_CONFIG, gb_addr_config);
WREG32(DMIF_ADDR_CONFIG, gb_addr_config);
+ if (ASIC_IS_DCE6(rdev))
+ WREG32(DMIF_ADDR_CALC, gb_addr_config);
WREG32(HDP_ADDR_CONFIG, gb_addr_config);
WREG32(DMA_TILING_CONFIG + DMA0_REGISTER_OFFSET, gb_addr_config);
WREG32(DMA_TILING_CONFIG + DMA1_REGISTER_OFFSET, gb_addr_config);
- tmp = gb_addr_config & NUM_PIPES_MASK;
- tmp = r6xx_remap_render_backend(rdev, tmp,
- rdev->config.cayman.max_backends_per_se *
- rdev->config.cayman.max_shader_engines,
- CAYMAN_MAX_BACKENDS, disabled_rb_mask);
+ if ((rdev->config.cayman.max_backends_per_se == 1) &&
+ (rdev->flags & RADEON_IS_IGP)) {
+ if ((disabled_rb_mask & 3) == 1) {
+ /* RB0 disabled, RB1 enabled */
+ tmp = 0x11111111;
+ } else {
+ /* RB1 disabled, RB0 enabled */
+ tmp = 0x00000000;
+ }
+ } else {
+ tmp = gb_addr_config & NUM_PIPES_MASK;
+ tmp = r6xx_remap_render_backend(rdev, tmp,
+ rdev->config.cayman.max_backends_per_se *
+ rdev->config.cayman.max_shader_engines,
+ CAYMAN_MAX_BACKENDS, disabled_rb_mask);
+ }
WREG32(GB_BACKEND_MAP, tmp);
cgts_tcc_disable = 0xffff0000;
@@ -725,7 +783,7 @@ static void cayman_gpu_init(struct radeon_device *rdev)
WREG32(PA_CL_ENHANCE, CLIP_VTX_REORDER_ENA | NUM_CLIP_SEQ(3));
- DRM_UDELAY(50);
+ udelay(50);
}
/*
@@ -1072,7 +1130,7 @@ static int cayman_cp_resume(struct radeon_device *rdev)
SOFT_RESET_SPI |
SOFT_RESET_SX));
RREG32(GRBM_SOFT_RESET);
- DRM_MDELAY(15);
+ mdelay(15);
WREG32(GRBM_SOFT_RESET, 0);
RREG32(GRBM_SOFT_RESET);
@@ -1122,7 +1180,7 @@ static int cayman_cp_resume(struct radeon_device *rdev)
WREG32(ring->rptr_reg, ring->rptr);
WREG32(ring->wptr_reg, ring->wptr);
- DRM_MDELAY(1);
+ mdelay(1);
WREG32_P(cp_rb_cntl[i], 0, ~RB_RPTR_WR_ENA);
}
@@ -1236,7 +1294,7 @@ int cayman_dma_resume(struct radeon_device *rdev)
/* Reset dma */
WREG32(SRBM_SOFT_RESET, SOFT_RESET_DMA | SOFT_RESET_DMA1);
RREG32(SRBM_SOFT_RESET);
- DRM_UDELAY(50);
+ udelay(50);
WREG32(SRBM_SOFT_RESET, 0);
for (i = 0; i < 2; i++) {
@@ -1367,7 +1425,7 @@ static void cayman_gpu_soft_reset_gfx(struct radeon_device *rdev)
dev_info(rdev->dev, " GRBM_SOFT_RESET=0x%08X\n", grbm_reset);
WREG32(GRBM_SOFT_RESET, grbm_reset);
(void)RREG32(GRBM_SOFT_RESET);
- DRM_UDELAY(50);
+ udelay(50);
WREG32(GRBM_SOFT_RESET, 0);
(void)RREG32(GRBM_SOFT_RESET);
@@ -1413,7 +1471,7 @@ static void cayman_gpu_soft_reset_dma(struct radeon_device *rdev)
/* Reset dma */
WREG32(SRBM_SOFT_RESET, SOFT_RESET_DMA | SOFT_RESET_DMA1);
RREG32(SRBM_SOFT_RESET);
- DRM_UDELAY(50);
+ udelay(50);
WREG32(SRBM_SOFT_RESET, 0);
dev_info(rdev->dev, " R_00D034_DMA_STATUS_REG = 0x%08X\n",
@@ -1457,7 +1515,7 @@ static int cayman_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
cayman_gpu_soft_reset_dma(rdev);
/* Wait a little for things to settle down */
- DRM_UDELAY(50);
+ udelay(50);
evergreen_mc_resume(rdev, &save);
return 0;
@@ -1674,6 +1732,7 @@ int cayman_resume(struct radeon_device *rdev)
int cayman_suspend(struct radeon_device *rdev)
{
r600_audio_fini(rdev);
+ radeon_vm_manager_fini(rdev);
cayman_cp_enable(rdev, false);
cayman_dma_stop(rdev);
evergreen_irq_suspend(rdev);
diff --git a/sys/dev/drm2/radeon/nid.h b/sys/dev/drm2/radeon/nid.h
index 89c0237..e68e386 100644
--- a/sys/dev/drm2/radeon/nid.h
+++ b/sys/dev/drm2/radeon/nid.h
@@ -48,6 +48,10 @@ __FBSDID("$FreeBSD$");
#define ARUBA_GB_ADDR_CONFIG_GOLDEN 0x12010001
#define DMIF_ADDR_CONFIG 0xBD4
+
+/* DCE6 only */
+#define DMIF_ADDR_CALC 0xC00
+
#define SRBM_GFX_CNTL 0x0E44
#define RINGID(x) (((x) & 0x3) << 0)
#define VMID(x) (((x) & 0x7) << 0)
diff --git a/sys/dev/drm2/radeon/r100.c b/sys/dev/drm2/radeon/r100.c
index a66c7c2..84f47d3 100644
--- a/sys/dev/drm2/radeon/r100.c
+++ b/sys/dev/drm2/radeon/r100.c
@@ -52,6 +52,16 @@ __FBSDID("$FreeBSD$");
#define FIRMWARE_RS600 "radeonkmsfw_RS600_cp"
#define FIRMWARE_R520 "radeonkmsfw_R520_cp"
+#ifdef __linux__
+MODULE_FIRMWARE(FIRMWARE_R100);
+MODULE_FIRMWARE(FIRMWARE_R200);
+MODULE_FIRMWARE(FIRMWARE_R300);
+MODULE_FIRMWARE(FIRMWARE_R420);
+MODULE_FIRMWARE(FIRMWARE_RS690);
+MODULE_FIRMWARE(FIRMWARE_RS600);
+MODULE_FIRMWARE(FIRMWARE_R520);
+#endif
+
#include "r100_track.h"
/* This files gather functions specifics to:
@@ -59,6 +69,38 @@ __FBSDID("$FreeBSD$");
* and others in some cases.
*/
+static bool r100_is_in_vblank(struct radeon_device *rdev, int crtc)
+{
+ if (crtc == 0) {
+ if (RREG32(RADEON_CRTC_STATUS) & RADEON_CRTC_VBLANK_CUR)
+ return true;
+ else
+ return false;
+ } else {
+ if (RREG32(RADEON_CRTC2_STATUS) & RADEON_CRTC2_VBLANK_CUR)
+ return true;
+ else
+ return false;
+ }
+}
+
+static bool r100_is_counter_moving(struct radeon_device *rdev, int crtc)
+{
+ u32 vline1, vline2;
+
+ if (crtc == 0) {
+ vline1 = (RREG32(RADEON_CRTC_VLINE_CRNT_VLINE) >> 16) & RADEON_CRTC_V_TOTAL;
+ vline2 = (RREG32(RADEON_CRTC_VLINE_CRNT_VLINE) >> 16) & RADEON_CRTC_V_TOTAL;
+ } else {
+ vline1 = (RREG32(RADEON_CRTC2_VLINE_CRNT_VLINE) >> 16) & RADEON_CRTC_V_TOTAL;
+ vline2 = (RREG32(RADEON_CRTC2_VLINE_CRNT_VLINE) >> 16) & RADEON_CRTC_V_TOTAL;
+ }
+ if (vline1 != vline2)
+ return true;
+ else
+ return false;
+}
+
/**
* r100_wait_for_vblank - vblank wait asic callback.
*
@@ -69,36 +111,33 @@ __FBSDID("$FreeBSD$");
*/
void r100_wait_for_vblank(struct radeon_device *rdev, int crtc)
{
- int i;
+ unsigned i = 0;
if (crtc >= rdev->num_crtc)
return;
if (crtc == 0) {
- if (RREG32(RADEON_CRTC_GEN_CNTL) & RADEON_CRTC_EN) {
- for (i = 0; i < rdev->usec_timeout; i++) {
- if (!(RREG32(RADEON_CRTC_STATUS) & RADEON_CRTC_VBLANK_CUR))
- break;
- DRM_UDELAY(1);
- }
- for (i = 0; i < rdev->usec_timeout; i++) {
- if (RREG32(RADEON_CRTC_STATUS) & RADEON_CRTC_VBLANK_CUR)
- break;
- DRM_UDELAY(1);
- }
- }
+ if (!(RREG32(RADEON_CRTC_GEN_CNTL) & RADEON_CRTC_EN))
+ return;
} else {
- if (RREG32(RADEON_CRTC2_GEN_CNTL) & RADEON_CRTC2_EN) {
- for (i = 0; i < rdev->usec_timeout; i++) {
- if (!(RREG32(RADEON_CRTC2_STATUS) & RADEON_CRTC2_VBLANK_CUR))
- break;
- DRM_UDELAY(1);
- }
- for (i = 0; i < rdev->usec_timeout; i++) {
- if (RREG32(RADEON_CRTC2_STATUS) & RADEON_CRTC2_VBLANK_CUR)
- break;
- DRM_UDELAY(1);
- }
+ if (!(RREG32(RADEON_CRTC2_GEN_CNTL) & RADEON_CRTC2_EN))
+ return;
+ }
+
+ /* depending on when we hit vblank, we may be close to active; if so,
+ * wait for another frame.
+ */
+ while (r100_is_in_vblank(rdev, crtc)) {
+ if (i++ % 100 == 0) {
+ if (!r100_is_counter_moving(rdev, crtc))
+ break;
+ }
+ }
+
+ while (!r100_is_in_vblank(rdev, crtc)) {
+ if (i++ % 100 == 0) {
+ if (!r100_is_counter_moving(rdev, crtc))
+ break;
}
}
}
@@ -160,7 +199,7 @@ u32 r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
for (i = 0; i < rdev->usec_timeout; i++) {
if (RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET)
break;
- DRM_UDELAY(1);
+ udelay(1);
}
DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
@@ -335,7 +374,7 @@ void r100_pm_misc(struct radeon_device *rdev)
tmp &= ~(voltage->gpio.mask);
WREG32(voltage->gpio.reg, tmp);
if (voltage->delay)
- DRM_UDELAY(voltage->delay);
+ udelay(voltage->delay);
} else {
tmp = RREG32(voltage->gpio.reg);
if (voltage->active_high)
@@ -344,7 +383,7 @@ void r100_pm_misc(struct radeon_device *rdev)
tmp |= voltage->gpio.mask;
WREG32(voltage->gpio.reg, tmp);
if (voltage->delay)
- DRM_UDELAY(voltage->delay);
+ udelay(voltage->delay);
}
}
@@ -713,7 +752,7 @@ void r100_irq_disable(struct radeon_device *rdev)
WREG32(R_000040_GEN_INT_CNTL, 0);
/* Wait and acknowledge irq */
- DRM_MDELAY(1);
+ mdelay(1);
tmp = RREG32(R_000044_GEN_INT_STATUS);
WREG32(R_000044_GEN_INT_STATUS, tmp);
}
@@ -924,7 +963,7 @@ static int r100_cp_wait_for_idle(struct radeon_device *rdev)
if (!G_000E40_CP_CMDSTRM_BUSY(tmp)) {
return 0;
}
- DRM_UDELAY(1);
+ udelay(1);
}
return -1;
}
@@ -1143,7 +1182,7 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size)
}
WREG32(RADEON_CP_RB_CNTL, tmp);
- DRM_UDELAY(10);
+ udelay(10);
ring->rptr = RREG32(RADEON_CP_RB_RPTR);
/* Set cp mode to bus mastering & enable cp*/
WREG32(RADEON_CP_CSQ_MODE,
@@ -2616,14 +2655,14 @@ void r100_bm_disable(struct radeon_device *rdev)
/* disable bus mastering */
tmp = RREG32(R_000030_BUS_CNTL);
WREG32(R_000030_BUS_CNTL, (tmp & 0xFFFFFFFF) | 0x00000044);
- DRM_MDELAY(1);
+ mdelay(1);
WREG32(R_000030_BUS_CNTL, (tmp & 0xFFFFFFFF) | 0x00000042);
- DRM_MDELAY(1);
+ mdelay(1);
WREG32(R_000030_BUS_CNTL, (tmp & 0xFFFFFFFF) | 0x00000040);
tmp = RREG32(RADEON_BUS_CNTL);
- DRM_MDELAY(1);
+ mdelay(1);
pci_disable_busmaster(rdev->dev);
- DRM_MDELAY(1);
+ mdelay(1);
}
int r100_asic_reset(struct radeon_device *rdev)
@@ -2655,17 +2694,17 @@ int r100_asic_reset(struct radeon_device *rdev)
S_0000F0_SOFT_RESET_PP(1) |
S_0000F0_SOFT_RESET_RB(1));
RREG32(R_0000F0_RBBM_SOFT_RESET);
- DRM_MDELAY(500);
+ mdelay(500);
WREG32(R_0000F0_RBBM_SOFT_RESET, 0);
- DRM_MDELAY(1);
+ mdelay(1);
status = RREG32(R_000E40_RBBM_STATUS);
dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status);
/* reset CP */
WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_CP(1));
RREG32(R_0000F0_RBBM_SOFT_RESET);
- DRM_MDELAY(500);
+ mdelay(500);
WREG32(R_0000F0_RBBM_SOFT_RESET, 0);
- DRM_MDELAY(1);
+ mdelay(1);
status = RREG32(R_000E40_RBBM_STATUS);
dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status);
/* restore PCI & busmastering */
@@ -2931,7 +2970,7 @@ static void r100_pll_errata_after_data(struct radeon_device *rdev)
* or the chip could hang on a subsequent access
*/
if (rdev->pll_errata & CHIP_ERRATA_PLL_DELAY) {
- DRM_MDELAY(5);
+ mdelay(5);
}
/* This function is required to workaround a hardware bug in some (all?)
@@ -2973,10 +3012,10 @@ static void r100_set_safe_registers(struct radeon_device *rdev)
{
if (ASIC_IS_RN50(rdev)) {
rdev->config.r100.reg_safe_bm = rn50_reg_safe_bm;
- rdev->config.r100.reg_safe_bm_size = DRM_ARRAY_SIZE(rn50_reg_safe_bm);
+ rdev->config.r100.reg_safe_bm_size = ARRAY_SIZE(rn50_reg_safe_bm);
} else if (rdev->family < CHIP_R200) {
rdev->config.r100.reg_safe_bm = r100_reg_safe_bm;
- rdev->config.r100.reg_safe_bm_size = DRM_ARRAY_SIZE(r100_reg_safe_bm);
+ rdev->config.r100.reg_safe_bm_size = ARRAY_SIZE(r100_reg_safe_bm);
} else {
r200_set_safe_registers(rdev);
}
diff --git a/sys/dev/drm2/radeon/r200.c b/sys/dev/drm2/radeon/r200.c
index 566645f..25a197e 100644
--- a/sys/dev/drm2/radeon/r200.c
+++ b/sys/dev/drm2/radeon/r200.c
@@ -548,5 +548,5 @@ int r200_packet0_check(struct radeon_cs_parser *p,
void r200_set_safe_registers(struct radeon_device *rdev)
{
rdev->config.r100.reg_safe_bm = r200_reg_safe_bm;
- rdev->config.r100.reg_safe_bm_size = DRM_ARRAY_SIZE(r200_reg_safe_bm);
+ rdev->config.r100.reg_safe_bm_size = ARRAY_SIZE(r200_reg_safe_bm);
}
diff --git a/sys/dev/drm2/radeon/r300.c b/sys/dev/drm2/radeon/r300.c
index 5681035..caaff4a 100644
--- a/sys/dev/drm2/radeon/r300.c
+++ b/sys/dev/drm2/radeon/r300.c
@@ -407,9 +407,9 @@ int r300_asic_reset(struct radeon_device *rdev)
WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_VAP(1) |
S_0000F0_SOFT_RESET_GA(1));
RREG32(R_0000F0_RBBM_SOFT_RESET);
- DRM_MDELAY(500);
+ mdelay(500);
WREG32(R_0000F0_RBBM_SOFT_RESET, 0);
- DRM_MDELAY(1);
+ mdelay(1);
status = RREG32(R_000E40_RBBM_STATUS);
dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status);
/* resetting the CP seems to be problematic sometimes it end up
@@ -419,9 +419,9 @@ int r300_asic_reset(struct radeon_device *rdev)
*/
WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_CP(1));
RREG32(R_0000F0_RBBM_SOFT_RESET);
- DRM_MDELAY(500);
+ mdelay(500);
WREG32(R_0000F0_RBBM_SOFT_RESET, 0);
- DRM_MDELAY(1);
+ mdelay(1);
status = RREG32(R_000E40_RBBM_STATUS);
dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status);
/* restore PCI & busmastering */
@@ -1254,7 +1254,7 @@ int r300_cs_parse(struct radeon_cs_parser *p)
struct r100_cs_track *track;
int r;
- track = malloc(sizeof(*track), DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
+ track = malloc(sizeof(*track), DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (track == NULL)
return -ENOMEM;
r100_cs_track_clear(p->rdev, track);
@@ -1299,7 +1299,7 @@ int r300_cs_parse(struct radeon_cs_parser *p)
void r300_set_reg_safe(struct radeon_device *rdev)
{
rdev->config.r300.reg_safe_bm = r300_reg_safe_bm;
- rdev->config.r300.reg_safe_bm_size = DRM_ARRAY_SIZE(r300_reg_safe_bm);
+ rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(r300_reg_safe_bm);
}
void r300_mc_program(struct radeon_device *rdev)
diff --git a/sys/dev/drm2/radeon/r300_cmdbuf.c b/sys/dev/drm2/radeon/r300_cmdbuf.c
index 4f41b13..421747c 100644
--- a/sys/dev/drm2/radeon/r300_cmdbuf.c
+++ b/sys/dev/drm2/radeon/r300_cmdbuf.c
@@ -1013,7 +1013,7 @@ int r300_do_cp_cmdbuf(struct drm_device *dev,
drm_radeon_kcmd_buffer_t *cmdbuf)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
- struct drm_radeon_master_private *master_priv = file_priv->masterp->driver_priv;
+ struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
struct drm_device_dma *dma = dev->dma;
struct drm_buf *buf = NULL;
int emit_dispatch_age = 0;
@@ -1120,7 +1120,7 @@ int r300_do_cp_cmdbuf(struct drm_device *dev,
}
emit_dispatch_age = 1;
- r300_discard_buffer(dev, file_priv->masterp, buf);
+ r300_discard_buffer(dev, file_priv->master, buf);
break;
case R300_CMD_WAIT:
diff --git a/sys/dev/drm2/radeon/r420.c b/sys/dev/drm2/radeon/r420.c
index e422f9d..eb38d46 100644
--- a/sys/dev/drm2/radeon/r420.c
+++ b/sys/dev/drm2/radeon/r420.c
@@ -80,7 +80,7 @@ void r420_pm_init_profile(struct radeon_device *rdev)
static void r420_set_reg_safe(struct radeon_device *rdev)
{
rdev->config.r300.reg_safe_bm = r420_reg_safe_bm;
- rdev->config.r300.reg_safe_bm_size = DRM_ARRAY_SIZE(r420_reg_safe_bm);
+ rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(r420_reg_safe_bm);
}
void r420_pipes_init(struct radeon_device *rdev)
diff --git a/sys/dev/drm2/radeon/r500_reg.h b/sys/dev/drm2/radeon/r500_reg.h
index 7b7130e..78e7bd0 100644
--- a/sys/dev/drm2/radeon/r500_reg.h
+++ b/sys/dev/drm2/radeon/r500_reg.h
@@ -129,10 +129,6 @@ __FBSDID("$FreeBSD$");
# define RS690_MC_INDEX_MASK 0x1ff
# define RS690_MC_INDEX_WR_EN (1 << 9)
# define RS690_MC_INDEX_WR_ACK 0x7f
-#define RS690_MC_NB_CNTL 0x0
-# define RS690_HIDE_MMCFG_BAR (1 << 3)
-# define RS690_AGPMODE30 (1 << 4)
-# define RS690_AGP30ENHANCED (1 << 5)
#define RS690_MC_DATA 0x7c
#define RS690_MC_STATUS 0x90
#define RS690_MC_STATUS_IDLE (1 << 0)
@@ -364,7 +360,9 @@ __FBSDID("$FreeBSD$");
#define AVIVO_D1CRTC_FRAME_COUNT 0x60a4
#define AVIVO_D1CRTC_STEREO_CONTROL 0x60c4
+#define AVIVO_D1MODE_MASTER_UPDATE_LOCK 0x60e0
#define AVIVO_D1MODE_MASTER_UPDATE_MODE 0x60e4
+#define AVIVO_D1CRTC_UPDATE_LOCK 0x60e8
/* master controls */
#define AVIVO_DC_CRTC_MASTER_EN 0x60f8
diff --git a/sys/dev/drm2/radeon/r600.c b/sys/dev/drm2/radeon/r600.c
index 586427d..68f417c 100644
--- a/sys/dev/drm2/radeon/r600.c
+++ b/sys/dev/drm2/radeon/r600.c
@@ -50,7 +50,7 @@ __FBSDID("$FreeBSD$");
#define CAYMAN_RLC_UCODE_SIZE 1024
#define ARUBA_RLC_UCODE_SIZE 1536
-#ifdef DUMBBELL_WIP
+#ifdef __linux__
/* Firmware Names */
MODULE_FIRMWARE("radeon/R600_pfp.bin");
MODULE_FIRMWARE("radeon/R600_me.bin");
@@ -93,12 +93,18 @@ MODULE_FIRMWARE("radeon/SUMO_pfp.bin");
MODULE_FIRMWARE("radeon/SUMO_me.bin");
MODULE_FIRMWARE("radeon/SUMO2_pfp.bin");
MODULE_FIRMWARE("radeon/SUMO2_me.bin");
-#endif /* DUMBBELL_WIP */
+#endif
int r600_debugfs_mc_info_init(struct radeon_device *rdev);
/* r600,rv610,rv630,rv620,rv635,rv670 */
+#ifdef FREEBSD_WIP /* FreeBSD: to please GCC 4.2. */
+int r600_mc_wait_for_idle(struct radeon_device *rdev);
+#endif
static void r600_gpu_init(struct radeon_device *rdev);
+#ifdef FREEBSD_WIP /* FreeBSD: to please GCC 4.2. */
+void r600_fini(struct radeon_device *rdev);
+#endif
void r600_irq_disable(struct radeon_device *rdev);
static void r600_pcie_gen2_enable(struct radeon_device *rdev);
@@ -860,7 +866,7 @@ void r600_pcie_gart_tlb_flush(struct radeon_device *rdev)
if (tmp) {
return;
}
- DRM_UDELAY(1);
+ udelay(1);
}
}
@@ -1021,7 +1027,7 @@ int r600_mc_wait_for_idle(struct radeon_device *rdev)
tmp = RREG32(R_000E50_SRBM_STATUS) & 0x3F00;
if (!tmp)
return 0;
- DRM_UDELAY(1);
+ udelay(1);
}
return -1;
}
@@ -1209,7 +1215,7 @@ static int r600_mc_init(struct radeon_device *rdev)
int r600_vram_scratch_init(struct radeon_device *rdev)
{
int r;
- void *vram_scratch_ptr_ptr;
+ void *vram_scratch_ptr_ptr; /* FreeBSD: to please GCC 4.2. */
if (rdev->vram_scratch.robj == NULL) {
r = radeon_bo_create(rdev, RADEON_GPU_PAGE_SIZE,
@@ -1324,7 +1330,7 @@ static void r600_gpu_soft_reset_gfx(struct radeon_device *rdev)
dev_info(rdev->dev, " R_008020_GRBM_SOFT_RESET=0x%08X\n", tmp);
WREG32(R_008020_GRBM_SOFT_RESET, tmp);
RREG32(R_008020_GRBM_SOFT_RESET);
- DRM_MDELAY(15);
+ mdelay(15);
WREG32(R_008020_GRBM_SOFT_RESET, 0);
}
/* Reset CP (we always reset CP) */
@@ -1332,7 +1338,7 @@ static void r600_gpu_soft_reset_gfx(struct radeon_device *rdev)
dev_info(rdev->dev, "R_008020_GRBM_SOFT_RESET=0x%08X\n", tmp);
WREG32(R_008020_GRBM_SOFT_RESET, tmp);
RREG32(R_008020_GRBM_SOFT_RESET);
- DRM_MDELAY(15);
+ mdelay(15);
WREG32(R_008020_GRBM_SOFT_RESET, 0);
dev_info(rdev->dev, " R_008010_GRBM_STATUS = 0x%08X\n",
@@ -1373,7 +1379,7 @@ static void r600_gpu_soft_reset_dma(struct radeon_device *rdev)
else
WREG32(SRBM_SOFT_RESET, SOFT_RESET_DMA);
RREG32(SRBM_SOFT_RESET);
- DRM_UDELAY(50);
+ udelay(50);
WREG32(SRBM_SOFT_RESET, 0);
dev_info(rdev->dev, " R_00D034_DMA_STATUS_REG = 0x%08X\n",
@@ -1407,7 +1413,7 @@ static int r600_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
r600_gpu_soft_reset_dma(rdev);
/* Wait a little for things to settle down */
- DRM_MDELAY(1);
+ mdelay(1);
rv515_mc_resume(rdev, &save);
return 0;
@@ -2168,7 +2174,7 @@ static int r600_cp_load_microcode(struct radeon_device *rdev)
/* Reset cp */
WREG32(GRBM_SOFT_RESET, SOFT_RESET_CP);
RREG32(GRBM_SOFT_RESET);
- DRM_MDELAY(15);
+ mdelay(15);
WREG32(GRBM_SOFT_RESET, 0);
WREG32(CP_ME_RAM_WADDR, 0);
@@ -2231,7 +2237,7 @@ int r600_cp_resume(struct radeon_device *rdev)
/* Reset cp */
WREG32(GRBM_SOFT_RESET, SOFT_RESET_CP);
RREG32(GRBM_SOFT_RESET);
- DRM_MDELAY(15);
+ mdelay(15);
WREG32(GRBM_SOFT_RESET, 0);
/* Set ring buffer size */
@@ -2265,7 +2271,7 @@ int r600_cp_resume(struct radeon_device *rdev)
WREG32(SCRATCH_UMSK, 0);
}
- DRM_MDELAY(1);
+ mdelay(1);
WREG32(CP_RB_CNTL, tmp);
WREG32(CP_RB_BASE, ring->gpu_addr >> 8);
@@ -2362,7 +2368,7 @@ int r600_dma_resume(struct radeon_device *rdev)
else
WREG32(SRBM_SOFT_RESET, SOFT_RESET_DMA);
RREG32(SRBM_SOFT_RESET);
- DRM_UDELAY(50);
+ udelay(50);
WREG32(SRBM_SOFT_RESET, 0);
WREG32(DMA_SEM_INCOMPLETE_TIMER_CNTL, 0);
@@ -3255,7 +3261,7 @@ void r600_ih_ring_init(struct radeon_device *rdev, unsigned ring_size)
int r600_ih_ring_alloc(struct radeon_device *rdev)
{
int r;
- void *ring_ptr;
+ void *ring_ptr; /* FreeBSD: to please GCC 4.2. */
/* Allocate ring buffer */
if (rdev->ih.ring_obj == NULL) {
@@ -3320,7 +3326,7 @@ void r600_rlc_stop(struct radeon_device *rdev)
/* r7xx asics need to soft reset RLC before halting */
WREG32(SRBM_SOFT_RESET, SOFT_RESET_RLC);
RREG32(SRBM_SOFT_RESET);
- DRM_MDELAY(15);
+ mdelay(15);
WREG32(SRBM_SOFT_RESET, 0);
RREG32(SRBM_SOFT_RESET);
}
@@ -3813,7 +3819,7 @@ void r600_irq_disable(struct radeon_device *rdev)
{
r600_disable_interrupts(rdev);
/* Wait and acknowledge irq */
- DRM_MDELAY(1);
+ mdelay(1);
r600_irq_ack(rdev);
r600_disable_interrupt_state(rdev);
}
diff --git a/sys/dev/drm2/radeon/r600_blit.c b/sys/dev/drm2/radeon/r600_blit.c
index f44fd79..514a92d 100644
--- a/sys/dev/drm2/radeon/r600_blit.c
+++ b/sys/dev/drm2/radeon/r600_blit.c
@@ -539,7 +539,7 @@ static void r600_nomm_put_vb(struct drm_device *dev)
drm_radeon_private_t *dev_priv = dev->dev_private;
dev_priv->blit_vb->used = 0;
- radeon_cp_discard_buffer(dev, dev_priv->blit_vb->file_priv->masterp, dev_priv->blit_vb);
+ radeon_cp_discard_buffer(dev, dev_priv->blit_vb->file_priv->master, dev_priv->blit_vb);
}
static void *r600_nomm_get_vb_ptr(struct drm_device *dev)
diff --git a/sys/dev/drm2/radeon/r600_blit_shaders.c b/sys/dev/drm2/radeon/r600_blit_shaders.c
index 1095a2c..6f284de 100644
--- a/sys/dev/drm2/radeon/r600_blit_shaders.c
+++ b/sys/dev/drm2/radeon/r600_blit_shaders.c
@@ -714,7 +714,7 @@ const u32 r6xx_ps[] =
0x00000000,
};
-const u32 r6xx_ps_size = DRM_ARRAY_SIZE(r6xx_ps);
-const u32 r6xx_vs_size = DRM_ARRAY_SIZE(r6xx_vs);
-const u32 r6xx_default_size = DRM_ARRAY_SIZE(r6xx_default_state);
-const u32 r7xx_default_size = DRM_ARRAY_SIZE(r7xx_default_state);
+const u32 r6xx_ps_size = ARRAY_SIZE(r6xx_ps);
+const u32 r6xx_vs_size = ARRAY_SIZE(r6xx_vs);
+const u32 r6xx_default_size = ARRAY_SIZE(r6xx_default_state);
+const u32 r7xx_default_size = ARRAY_SIZE(r7xx_default_state);
diff --git a/sys/dev/drm2/radeon/r600_cp.c b/sys/dev/drm2/radeon/r600_cp.c
index 2907bdb..f4a78df 100644
--- a/sys/dev/drm2/radeon/r600_cp.c
+++ b/sys/dev/drm2/radeon/r600_cp.c
@@ -44,6 +44,37 @@ __FBSDID("$FreeBSD$");
#define R700_PFP_UCODE_SIZE 848
#define R700_PM4_UCODE_SIZE 1360
+#ifdef __linux__
+/* Firmware Names */
+MODULE_FIRMWARE("radeon/R600_pfp.bin");
+MODULE_FIRMWARE("radeon/R600_me.bin");
+MODULE_FIRMWARE("radeon/RV610_pfp.bin");
+MODULE_FIRMWARE("radeon/RV610_me.bin");
+MODULE_FIRMWARE("radeon/RV630_pfp.bin");
+MODULE_FIRMWARE("radeon/RV630_me.bin");
+MODULE_FIRMWARE("radeon/RV620_pfp.bin");
+MODULE_FIRMWARE("radeon/RV620_me.bin");
+MODULE_FIRMWARE("radeon/RV635_pfp.bin");
+MODULE_FIRMWARE("radeon/RV635_me.bin");
+MODULE_FIRMWARE("radeon/RV670_pfp.bin");
+MODULE_FIRMWARE("radeon/RV670_me.bin");
+MODULE_FIRMWARE("radeon/RS780_pfp.bin");
+MODULE_FIRMWARE("radeon/RS780_me.bin");
+MODULE_FIRMWARE("radeon/RV770_pfp.bin");
+MODULE_FIRMWARE("radeon/RV770_me.bin");
+MODULE_FIRMWARE("radeon/RV730_pfp.bin");
+MODULE_FIRMWARE("radeon/RV730_me.bin");
+MODULE_FIRMWARE("radeon/RV710_pfp.bin");
+MODULE_FIRMWARE("radeon/RV710_me.bin");
+#endif
+
+
+#ifdef FREEBSD_WIP /* FreeBSD: to please GCC 4.2. */
+int r600_cs_legacy(struct drm_device *dev, void *data, struct drm_file *filp,
+ unsigned family, u32 *ib, int *l);
+void r600_cs_legacy_init(void);
+#endif
+
# define ATI_PCIGART_PAGE_SIZE 4096 /**< PCI GART page size */
# define ATI_PCIGART_PAGE_MASK (~(ATI_PCIGART_PAGE_SIZE-1))
@@ -392,7 +423,7 @@ static void r600_cp_load_microcode(drm_radeon_private_t *dev_priv)
RADEON_WRITE(R600_GRBM_SOFT_RESET, R600_SOFT_RESET_CP);
RADEON_READ(R600_GRBM_SOFT_RESET);
- DRM_MDELAY(15);
+ mdelay(15);
RADEON_WRITE(R600_GRBM_SOFT_RESET, 0);
fw_data = (const __be32 *)dev_priv->me_fw->data;
@@ -485,7 +516,7 @@ static void r700_cp_load_microcode(drm_radeon_private_t *dev_priv)
RADEON_WRITE(R600_GRBM_SOFT_RESET, R600_SOFT_RESET_CP);
RADEON_READ(R600_GRBM_SOFT_RESET);
- DRM_MDELAY(15);
+ mdelay(15);
RADEON_WRITE(R600_GRBM_SOFT_RESET, 0);
fw_data = (const __be32 *)dev_priv->pfp_fw->data;
@@ -1777,7 +1808,7 @@ static void r600_cp_init_ring_buffer(struct drm_device *dev,
RADEON_WRITE(R600_GRBM_SOFT_RESET, R600_SOFT_RESET_CP);
RADEON_READ(R600_GRBM_SOFT_RESET);
- DRM_MDELAY(15);
+ mdelay(15);
RADEON_WRITE(R600_GRBM_SOFT_RESET, 0);
@@ -1907,7 +1938,7 @@ static void r600_cp_init_ring_buffer(struct drm_device *dev,
RADEON_WRITE(R600_LAST_CLEAR_REG, 0);
/* reset sarea copies of these */
- master_priv = file_priv->masterp->driver_priv;
+ master_priv = file_priv->master->driver_priv;
if (master_priv->sarea_priv) {
master_priv->sarea_priv->last_frame = 0;
master_priv->sarea_priv->last_dispatch = 0;
@@ -1966,7 +1997,7 @@ int r600_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
struct drm_file *file_priv)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
- struct drm_radeon_master_private *master_priv = file_priv->masterp->driver_priv;
+ struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
DRM_DEBUG("\n");
@@ -2401,7 +2432,7 @@ int r600_cp_dispatch_indirect(struct drm_device *dev,
void r600_cp_dispatch_swap(struct drm_device *dev, struct drm_file *file_priv)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
- struct drm_master *master = file_priv->masterp;
+ struct drm_master *master = file_priv->master;
struct drm_radeon_master_private *master_priv = master->driver_priv;
drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv;
int nbox = sarea_priv->nbox;
@@ -2523,7 +2554,7 @@ int r600_cp_dispatch_texture(struct drm_device *dev,
r600_blit_copy(dev, src_offset, dst_offset, pass_size);
- radeon_cp_discard_buffer(dev, file_priv->masterp, buf);
+ radeon_cp_discard_buffer(dev, file_priv->master, buf);
/* Update the input parameters for next time */
image->data = (const u8 __user *)image->data + pass_size;
@@ -2588,7 +2619,7 @@ static void r600_ib_free(struct drm_device *dev, struct drm_buf *buf,
if (buf) {
if (!r)
r600_cp_dispatch_indirect(dev, buf, 0, l * 4);
- radeon_cp_discard_buffer(dev, fpriv->masterp, buf);
+ radeon_cp_discard_buffer(dev, fpriv->master, buf);
COMMIT_RING();
}
}
diff --git a/sys/dev/drm2/radeon/r600_cs.c b/sys/dev/drm2/radeon/r600_cs.c
index 9000b3c..4b1a705 100644
--- a/sys/dev/drm2/radeon/r600_cs.c
+++ b/sys/dev/drm2/radeon/r600_cs.c
@@ -43,6 +43,9 @@ static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p,
struct radeon_cs_reloc **cs_reloc);
typedef int (*next_reloc_t)(struct radeon_cs_parser*, struct radeon_cs_reloc**);
static next_reloc_t r600_cs_packet_next_reloc = &r600_cs_packet_next_reloc_mm;
+#ifdef FREEBSD_WIP /* FreeBSD: to please GCC 4.2. */
+extern void r600_cs_legacy_get_tiling_conf(struct drm_device *dev, u32 *npipes, u32 *nbanks, u32 *group_size);
+#endif
struct r600_cs_track {
@@ -186,7 +189,7 @@ static const struct gpu_formats color_formats_table[] = {
bool r600_fmt_is_valid_color(u32 format)
{
- if (format >= DRM_ARRAY_SIZE(color_formats_table))
+ if (format >= ARRAY_SIZE(color_formats_table))
return false;
if (color_formats_table[format].valid_color)
@@ -197,7 +200,7 @@ bool r600_fmt_is_valid_color(u32 format)
bool r600_fmt_is_valid_texture(u32 format, enum radeon_family family)
{
- if (format >= DRM_ARRAY_SIZE(color_formats_table))
+ if (format >= ARRAY_SIZE(color_formats_table))
return false;
if (family < color_formats_table[format].min_family)
@@ -211,7 +214,7 @@ bool r600_fmt_is_valid_texture(u32 format, enum radeon_family family)
int r600_fmt_get_blocksize(u32 format)
{
- if (format >= DRM_ARRAY_SIZE(color_formats_table))
+ if (format >= ARRAY_SIZE(color_formats_table))
return 0;
return color_formats_table[format].blocksize;
@@ -221,7 +224,7 @@ int r600_fmt_get_nblocksx(u32 format, u32 w)
{
unsigned bw;
- if (format >= DRM_ARRAY_SIZE(color_formats_table))
+ if (format >= ARRAY_SIZE(color_formats_table))
return 0;
bw = color_formats_table[format].blockwidth;
@@ -235,7 +238,7 @@ int r600_fmt_get_nblocksy(u32 format, u32 h)
{
unsigned bh;
- if (format >= DRM_ARRAY_SIZE(color_formats_table))
+ if (format >= ARRAY_SIZE(color_formats_table))
return 0;
bh = color_formats_table[format].blockheight;
@@ -1117,7 +1120,7 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
int r;
i = (reg >> 7);
- if (i >= DRM_ARRAY_SIZE(r600_reg_safe_bm)) {
+ if (i >= ARRAY_SIZE(r600_reg_safe_bm)) {
dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
return -EINVAL;
}
@@ -1741,7 +1744,7 @@ static bool r600_is_safe_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
u32 m, i;
i = (reg >> 7);
- if (i >= DRM_ARRAY_SIZE(r600_reg_safe_bm)) {
+ if (i >= ARRAY_SIZE(r600_reg_safe_bm)) {
dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
return false;
}
@@ -2400,7 +2403,7 @@ int r600_cs_parse(struct radeon_cs_parser *p)
if (p->track == NULL) {
/* initialize tracker, we are in kms */
track = malloc(sizeof(*track),
- DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (track == NULL)
return -ENOMEM;
r600_cs_track_init(track);
@@ -2447,7 +2450,7 @@ int r600_cs_parse(struct radeon_cs_parser *p)
#if 0
for (r = 0; r < p->ib.length_dw; r++) {
DRM_INFO("%05d 0x%08X\n", r, p->ib.ptr[r]);
- DRM_MDELAY(1);
+ mdelay(1);
}
#endif
free(p->track, DRM_MEM_DRIVER);
@@ -2461,7 +2464,7 @@ static int r600_cs_parser_relocs_legacy(struct radeon_cs_parser *p)
return 0;
}
p->relocs = malloc(sizeof(struct radeon_cs_reloc),
- DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (p->relocs == NULL) {
return -ENOMEM;
}
@@ -2502,7 +2505,7 @@ int r600_cs_legacy(struct drm_device *dev, void *data, struct drm_file *filp,
int r;
/* initialize tracker */
- track = malloc(sizeof(*track), DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
+ track = malloc(sizeof(*track), DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (track == NULL)
return -ENOMEM;
r600_cs_track_init(track);
@@ -2510,7 +2513,7 @@ int r600_cs_legacy(struct drm_device *dev, void *data, struct drm_file *filp,
/* initialize parser */
memset(&parser, 0, sizeof(struct radeon_cs_parser));
parser.filp = filp;
- parser.dev = dev->device;
+ parser.dev = dev->dev;
parser.rdev = NULL;
parser.family = family;
parser.track = track;
@@ -2754,7 +2757,7 @@ int r600_dma_cs_parse(struct radeon_cs_parser *p)
#if 0
for (r = 0; r < p->ib->length_dw; r++) {
DRM_INFO("%05d 0x%08X\n", r, p->ib.ptr[r]);
- DRM_MDELAY(1);
+ mdelay(1);
}
#endif
return 0;
diff --git a/sys/dev/drm2/radeon/r600_hdmi.c b/sys/dev/drm2/radeon/r600_hdmi.c
index 46a72fb..d75b3d3 100644
--- a/sys/dev/drm2/radeon/r600_hdmi.c
+++ b/sys/dev/drm2/radeon/r600_hdmi.c
@@ -493,7 +493,7 @@ void r600_hdmi_enable(struct drm_encoder *encoder)
offset = dig->afmt->offset;
/* Older chipsets require setting HDMI and routing manually */
- if (rdev->family >= CHIP_R600 && !ASIC_IS_DCE3(rdev)) {
+ if (ASIC_IS_DCE2(rdev) && !ASIC_IS_DCE3(rdev)) {
hdmi = HDMI0_ERROR_ACK | HDMI0_ENABLE;
switch (radeon_encoder->encoder_id) {
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
@@ -548,7 +548,6 @@ void r600_hdmi_disable(struct drm_encoder *encoder)
/* Called for ATOM_ENCODER_MODE_HDMI only */
if (!dig || !dig->afmt) {
- DRM_ERROR("%s: !dig || !dig->afmt", __func__);
return;
}
if (!dig->afmt->enabled)
@@ -562,7 +561,7 @@ void r600_hdmi_disable(struct drm_encoder *encoder)
radeon_irq_kms_disable_afmt(rdev, dig->afmt->id);
/* Older chipsets not handled by AtomBIOS */
- if (rdev->family >= CHIP_R600 && !ASIC_IS_DCE3(rdev)) {
+ if (ASIC_IS_DCE2(rdev) && !ASIC_IS_DCE3(rdev)) {
switch (radeon_encoder->encoder_id) {
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
WREG32_P(AVIVO_TMDSA_CNTL, 0,
diff --git a/sys/dev/drm2/radeon/r600d.h b/sys/dev/drm2/radeon/r600d.h
index 174b1fe..92f35de 100644
--- a/sys/dev/drm2/radeon/r600d.h
+++ b/sys/dev/drm2/radeon/r600d.h
@@ -48,11 +48,17 @@ __FBSDID("$FreeBSD$");
#define R6XX_MAX_PIPES_MASK 0xff
/* PTE flags */
+/*
+ * FIXME Linux<->FreeBSD: PTE_VALID is already defined on PowerPC on FreeBSD.
+ * Fortunately, it's never used in the Radeon driver.
+ */
+/*
#define PTE_VALID (1 << 0)
#define PTE_SYSTEM (1 << 1)
#define PTE_SNOOPED (1 << 2)
#define PTE_READABLE (1 << 5)
#define PTE_WRITEABLE (1 << 6)
+*/
/* tiling bits */
#define ARRAY_LINEAR_GENERAL 0x00000000
diff --git a/sys/dev/drm2/radeon/radeon.h b/sys/dev/drm2/radeon/radeon.h
index 8d932d9..4a63cf6 100644
--- a/sys/dev/drm2/radeon/radeon.h
+++ b/sys/dev/drm2/radeon/radeon.h
@@ -72,8 +72,10 @@ __FBSDID("$FreeBSD$");
#include <sys/linker.h>
#include <sys/firmware.h>
+#if defined(CONFIG_ACPI)
#include <contrib/dev/acpica/include/acpi.h>
#include <dev/acpica/acpivar.h>
+#endif
#include <dev/drm2/ttm/ttm_bo_api.h>
#include <dev/drm2/ttm/ttm_bo_driver.h>
@@ -111,7 +113,7 @@ extern int radeon_lockup_timeout;
* symbol;
*/
#define RADEON_MAX_USEC_TIMEOUT 100000 /* 100 ms */
-#define RADEON_FENCE_JIFFIES_TIMEOUT (DRM_HZ / 2)
+#define RADEON_FENCE_JIFFIES_TIMEOUT (HZ / 2)
/* RADEON_IB_POOL_SIZE must be a power of 2 */
#define RADEON_IB_POOL_SIZE 16
#define RADEON_DEBUGFS_MAX_COMPONENTS 32
@@ -1103,9 +1105,9 @@ struct radeon_pm {
/* selected pm method */
enum radeon_pm_method pm_method;
/* dynpm power management */
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
struct delayed_work dynpm_idle_work;
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
enum radeon_dynpm_state dynpm_state;
enum radeon_dynpm_action dynpm_planned_action;
unsigned long dynpm_action_timeout;
@@ -1117,9 +1119,9 @@ struct radeon_pm {
struct radeon_pm_profile profiles[PM_PROFILE_MAX];
/* internal thermal controller on rv6xx+ */
enum radeon_int_thermal_type int_thermal_type;
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
struct device *int_hwmon_dev;
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
};
int radeon_pm_get_type_index(struct radeon_device *rdev,
@@ -1637,10 +1639,12 @@ struct radeon_device {
struct sx dc_hw_i2c_mutex; /* display controller hw i2c mutex */
bool audio_enabled;
struct r600_audio audio_status; /* audio stuff */
+#if defined(CONFIG_ACPI)
struct {
ACPI_HANDLE handle;
ACPI_NOTIFY_HANDLER notifier_call;
} acpi;
+#endif
/* only one userspace can use Hyperz features or CMASK at a time */
struct drm_file *hyperz_filp;
struct drm_file *cmask_filp;
@@ -1796,7 +1800,7 @@ void radeon_atombios_fini(struct radeon_device *rdev);
/*
* RING helpers.
*/
-#if !defined(DRM_DEBUG_CODE) || DRM_DEBUG_CODE == 0
+#if DRM_DEBUG_CODE == 0
static inline void radeon_ring_write(struct radeon_ring *ring, uint32_t v)
{
ring->ring[ring->wptr++] = v;
@@ -1985,8 +1989,13 @@ extern int ni_mc_load_microcode(struct radeon_device *rdev);
extern void ni_fini_microcode(struct radeon_device *rdev);
/* radeon_acpi.c */
+#if defined(CONFIG_ACPI)
extern int radeon_acpi_init(struct radeon_device *rdev);
extern void radeon_acpi_fini(struct radeon_device *rdev);
+#else
+static inline int radeon_acpi_init(struct radeon_device *rdev) { return 0; }
+static inline void radeon_acpi_fini(struct radeon_device *rdev) { }
+#endif
/* Prototypes added by @dumbbell. */
diff --git a/sys/dev/drm2/radeon/radeon_acpi.c b/sys/dev/drm2/radeon/radeon_acpi.c
index 176e160..a725ab7 100644
--- a/sys/dev/drm2/radeon/radeon_acpi.c
+++ b/sys/dev/drm2/radeon/radeon_acpi.c
@@ -32,6 +32,8 @@ __FBSDID("$FreeBSD$");
#define ACPI_AC_CLASS "ac_adapter"
+extern void radeon_pm_acpi_event_handler(struct radeon_device *rdev);
+
struct atif_verify_interface {
u16 size; /* structure size in bytes (includes size field) */
u16 version; /* version */
@@ -358,7 +360,7 @@ void radeon_atif_handler(struct radeon_device *rdev,
radeon_set_backlight_level(rdev, enc, req.backlight_level);
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
if (rdev->is_atom_bios) {
struct radeon_encoder_atom_dig *dig = enc->enc_priv;
backlight_force_update(dig->bl_dev,
@@ -368,7 +370,7 @@ void radeon_atif_handler(struct radeon_device *rdev,
backlight_force_update(dig->bl_dev,
BACKLIGHT_UPDATE_HOTKEY);
}
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
}
}
/* TODO: check other events */
@@ -508,7 +510,7 @@ static void radeon_acpi_event(ACPI_HANDLE handle, UINT32 type,
{
struct radeon_device *rdev = (struct radeon_device *)context;
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
if (strcmp(entry->device_class, ACPI_AC_CLASS) == 0) {
if (power_supply_is_system_supplied() > 0)
DRM_DEBUG_DRIVER("pm: AC\n");
@@ -517,7 +519,7 @@ static void radeon_acpi_event(ACPI_HANDLE handle, UINT32 type,
radeon_pm_acpi_event_handler(rdev);
}
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
/* Check for pending SBIOS requests */
radeon_atif_handler(rdev, type);
diff --git a/sys/dev/drm2/radeon/radeon_agp.c b/sys/dev/drm2/radeon/radeon_agp.c
index 0ac376b..aabdf72 100644
--- a/sys/dev/drm2/radeon/radeon_agp.c
+++ b/sys/dev/drm2/radeon/radeon_agp.c
@@ -153,11 +153,11 @@ int radeon_agp_init(struct radeon_device *rdev)
return ret;
}
- if ((rdev->ddev->agp->info.ai_aperture_size >> 20) < 32) {
+ if ((rdev->ddev->agp->agp_info.ai_aperture_size >> 20) < 32) {
drm_agp_release(rdev->ddev);
dev_warn(rdev->dev, "AGP aperture too small (%zuM) "
"need at least 32M, disabling AGP\n",
- rdev->ddev->agp->info.ai_aperture_size >> 20);
+ rdev->ddev->agp->agp_info.ai_aperture_size >> 20);
return -EINVAL;
}
@@ -245,8 +245,8 @@ int radeon_agp_init(struct radeon_device *rdev)
return ret;
}
- rdev->mc.agp_base = rdev->ddev->agp->info.ai_aperture_base;
- rdev->mc.gtt_size = rdev->ddev->agp->info.ai_aperture_size;
+ rdev->mc.agp_base = rdev->ddev->agp->agp_info.ai_aperture_base;
+ rdev->mc.gtt_size = rdev->ddev->agp->agp_info.ai_aperture_size;
rdev->mc.gtt_start = rdev->mc.agp_base;
rdev->mc.gtt_end = rdev->mc.gtt_start + rdev->mc.gtt_size - 1;
dev_info(rdev->dev, "GTT: %juM 0x%08jX - 0x%08jX\n",
diff --git a/sys/dev/drm2/radeon/radeon_atombios.c b/sys/dev/drm2/radeon/radeon_atombios.c
index 309f147..e00c8b3 100644
--- a/sys/dev/drm2/radeon/radeon_atombios.c
+++ b/sys/dev/drm2/radeon/radeon_atombios.c
@@ -35,6 +35,34 @@ __FBSDID("$FreeBSD$");
#include "atom.h"
#include "atom-bits.h"
+#ifdef FREEBSD_WIP /* FreeBSD: to please GCC 4.2. */
+/* from radeon_encoder.c */
+extern uint32_t
+radeon_get_encoder_enum(struct drm_device *dev, uint32_t supported_device,
+ uint8_t dac);
+extern void radeon_link_encoder_connector(struct drm_device *dev);
+extern void
+radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_enum,
+ uint32_t supported_device, u16 caps);
+
+/* from radeon_connector.c */
+extern void
+radeon_add_atom_connector(struct drm_device *dev,
+ uint32_t connector_id,
+ uint32_t supported_device,
+ int connector_type,
+ struct radeon_i2c_bus_rec *i2c_bus,
+ uint32_t igp_lane_info,
+ uint16_t connector_object_id,
+ struct radeon_hpd *hpd,
+ struct radeon_router *router);
+
+/* from radeon_legacy_encoder.c */
+extern void
+radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_enum,
+ uint32_t supported_device);
+#endif
+
/* local */
static int radeon_atom_get_max_vddc(struct radeon_device *rdev, u8 voltage_type,
u16 voltage_id, u16 *voltage);
@@ -904,7 +932,7 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
router.ddc_valid = false;
router.cd_valid = false;
- bios_connectors = malloc(bc_size, DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
+ bios_connectors = malloc(bc_size, DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (!bios_connectors)
return false;
@@ -1532,7 +1560,7 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct
(union lvds_info *)((char *)mode_info->atom_context->bios + data_offset);
lvds =
malloc(sizeof(struct radeon_encoder_atom_dig),
- DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (!lvds)
return NULL;
@@ -1619,7 +1647,7 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct
struct edid *edid;
int edid_size =
max((int)EDID_LENGTH, (int)fake_edid_record->ucFakeEDIDLength);
- edid = malloc(edid_size, DRM_MEM_KMS, M_WAITOK);
+ edid = malloc(edid_size, DRM_MEM_KMS, M_NOWAIT);
if (edid) {
memcpy((u8 *)edid, (u8 *)&fake_edid_record->ucFakeEDIDString[0],
fake_edid_record->ucFakeEDIDLength);
@@ -1671,7 +1699,7 @@ radeon_atombios_get_primary_dac_info(struct radeon_encoder *encoder)
((char *)mode_info->atom_context->bios + data_offset);
p_dac = malloc(sizeof(struct radeon_encoder_primary_dac),
- DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (!p_dac)
return NULL;
@@ -1857,7 +1885,7 @@ radeon_atombios_get_tv_dac_info(struct radeon_encoder *encoder)
((char *)mode_info->atom_context->bios + data_offset);
tv_dac = malloc(sizeof(struct radeon_encoder_tv_dac),
- DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (!tv_dac)
return NULL;
@@ -1992,13 +2020,13 @@ static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev)
/* add the i2c bus for thermal/fan chip */
if ((power_info->info.ucOverdriveThermalController > 0) &&
- (power_info->info.ucOverdriveThermalController < DRM_ARRAY_SIZE(thermal_controller_names))) {
+ (power_info->info.ucOverdriveThermalController < ARRAY_SIZE(thermal_controller_names))) {
DRM_INFO("Possible %s thermal controller at 0x%02x\n",
thermal_controller_names[power_info->info.ucOverdriveThermalController],
power_info->info.ucOverdriveControllerAddress >> 1);
i2c_bus = radeon_lookup_i2c_gpio(rdev, power_info->info.ucOverdriveI2cLine);
rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus);
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
if (rdev->pm.i2c_bus) {
struct i2c_board_info info = { };
const char *name = thermal_controller_names[power_info->info.
@@ -2007,20 +2035,22 @@ static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev)
strlcpy(info.type, name, sizeof(info.type));
i2c_new_device(&rdev->pm.i2c_bus->adapter, &info);
}
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
}
num_modes = power_info->info.ucNumOfPowerModeEntries;
if (num_modes > ATOM_MAX_NUMBEROF_POWER_BLOCK)
num_modes = ATOM_MAX_NUMBEROF_POWER_BLOCK;
+ if (num_modes == 0)
+ return state_index;
rdev->pm.power_state = malloc(sizeof(struct radeon_power_state) * num_modes,
- DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (!rdev->pm.power_state)
return state_index;
/* last mode is usually default, array is low to high */
for (i = 0; i < num_modes; i++) {
rdev->pm.power_state[state_index].clock_info =
malloc(sizeof(struct radeon_pm_clock_info) * 1,
- DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (!rdev->pm.power_state[state_index].clock_info)
return state_index;
rdev->pm.power_state[state_index].num_clock_modes = 1;
@@ -2200,7 +2230,7 @@ static void radeon_atombios_add_pplib_thermal_controller(struct radeon_device *r
(controller->ucType ==
ATOM_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL)) {
DRM_INFO("Special thermal controller config\n");
- } else if (controller->ucType < DRM_ARRAY_SIZE(pp_lib_thermal_controller_names)) {
+ } else if (controller->ucType < ARRAY_SIZE(pp_lib_thermal_controller_names)) {
DRM_INFO("Possible %s thermal controller at 0x%02x %s fan control\n",
pp_lib_thermal_controller_names[controller->ucType],
controller->ucI2cAddress >> 1,
@@ -2208,7 +2238,7 @@ static void radeon_atombios_add_pplib_thermal_controller(struct radeon_device *r
ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
i2c_bus = radeon_lookup_i2c_gpio(rdev, controller->ucI2cLine);
rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus);
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
if (rdev->pm.i2c_bus) {
struct i2c_board_info info = { };
const char *name = pp_lib_thermal_controller_names[controller->ucType];
@@ -2216,7 +2246,7 @@ static void radeon_atombios_add_pplib_thermal_controller(struct radeon_device *r
strlcpy(info.type, name, sizeof(info.type));
i2c_new_device(&rdev->pm.i2c_bus->adapter, &info);
}
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
} else {
DRM_INFO("Unknown thermal controller type %d at 0x%02x %s fan control\n",
controller->ucType,
@@ -2420,9 +2450,11 @@ static int radeon_atombios_parse_power_table_4_5(struct radeon_device *rdev)
power_info = (union power_info *)((char *)mode_info->atom_context->bios + data_offset);
radeon_atombios_add_pplib_thermal_controller(rdev, &power_info->pplib.sThermalController);
+ if (power_info->pplib.ucNumStates == 0)
+ return state_index;
rdev->pm.power_state = malloc(sizeof(struct radeon_power_state) *
power_info->pplib.ucNumStates,
- DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (!rdev->pm.power_state)
return state_index;
/* first mode is usually default, followed by low to high */
@@ -2440,7 +2472,7 @@ static int radeon_atombios_parse_power_table_4_5(struct radeon_device *rdev)
rdev->pm.power_state[i].clock_info = malloc(sizeof(struct radeon_pm_clock_info) *
((power_info->pplib.ucStateEntrySize - 1) ?
(power_info->pplib.ucStateEntrySize - 1) : 1),
- DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (!rdev->pm.power_state[i].clock_info)
return state_index;
if (power_info->pplib.ucStateEntrySize - 1) {
@@ -2503,6 +2535,7 @@ static int radeon_atombios_parse_power_table_6(struct radeon_device *rdev)
int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
u16 data_offset;
u8 frev, crev;
+ u8 *power_state_offset;
if (!atom_parse_data_header(mode_info->atom_context, index, NULL,
&frev, &crev, &data_offset))
@@ -2519,30 +2552,29 @@ static int radeon_atombios_parse_power_table_6(struct radeon_device *rdev)
non_clock_info_array = (struct _NonClockInfoArray *)
((char *)mode_info->atom_context->bios + data_offset +
le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset));
+ if (state_array->ucNumEntries == 0)
+ return state_index;
rdev->pm.power_state = malloc(sizeof(struct radeon_power_state) *
state_array->ucNumEntries,
- DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (!rdev->pm.power_state)
return state_index;
+ power_state_offset = (u8 *)state_array->states;
for (i = 0; i < state_array->ucNumEntries; i++) {
mode_index = 0;
- power_state = (union pplib_power_state *)&state_array->states[i];
- /* XXX this might be an inagua bug... */
- non_clock_array_index = i; /* power_state->v2.nonClockInfoIndex */
+ power_state = (union pplib_power_state *)power_state_offset;
+ non_clock_array_index = power_state->v2.nonClockInfoIndex;
non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
&non_clock_info_array->nonClockInfo[non_clock_array_index];
rdev->pm.power_state[i].clock_info = malloc(sizeof(struct radeon_pm_clock_info) *
(power_state->v2.ucNumDPMLevels ?
power_state->v2.ucNumDPMLevels : 1),
- DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (!rdev->pm.power_state[i].clock_info)
return state_index;
if (power_state->v2.ucNumDPMLevels) {
for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) {
clock_array_index = power_state->v2.clockInfoIndex[j];
- /* XXX this might be an inagua bug... */
- if (clock_array_index >= clock_info_array->ucNumEntries)
- continue;
clock_info = (union pplib_clock_info *)
&clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize];
valid = radeon_atombios_parse_pplib_clock_info(rdev,
@@ -2564,6 +2596,7 @@ static int radeon_atombios_parse_power_table_6(struct radeon_device *rdev)
non_clock_info);
state_index++;
}
+ power_state_offset += 2 + power_state->v2.ucNumDPMLevels;
}
/* if multiple clock modes, mark the lowest as no display */
for (i = 0; i < state_index; i++) {
@@ -2610,13 +2643,15 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
default:
break;
}
- } else {
+ }
+
+ if (state_index == 0) {
rdev->pm.power_state = malloc(sizeof(struct radeon_power_state),
- DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (rdev->pm.power_state) {
rdev->pm.power_state[0].clock_info =
malloc(sizeof(struct radeon_pm_clock_info) * 1,
- DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (rdev->pm.power_state[0].clock_info) {
/* add the default mode */
rdev->pm.power_state[state_index].type =
diff --git a/sys/dev/drm2/radeon/radeon_atpx_handler.c b/sys/dev/drm2/radeon/radeon_atpx_handler.c
deleted file mode 100644
index 4cfd743..0000000
--- a/sys/dev/drm2/radeon/radeon_atpx_handler.c
+++ /dev/null
@@ -1,506 +0,0 @@
-/*
- * Copyright (c) 2010 Red Hat Inc.
- * Author : Dave Airlie <airlied@redhat.com>
- *
- * Licensed under GPLv2
- *
- * ATPX support for both Intel/ATI
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/bus.h>
-#include <sys/linker.h>
-
-#include <contrib/dev/acpica/include/acpi.h>
-#include <dev/acpica/acpivar.h>
-
-#include <dev/drm2/drmP.h>
-#include <dev/drm2/radeon/radeon_drm.h>
-#include "radeon_acpi.h"
-#include "radeon_drv.h"
-
-#ifdef DUMBBELL_WIP
-struct radeon_atpx_functions {
- bool px_params;
- bool power_cntl;
- bool disp_mux_cntl;
- bool i2c_mux_cntl;
- bool switch_start;
- bool switch_end;
- bool disp_connectors_mapping;
- bool disp_detetion_ports;
-};
-
-struct radeon_atpx {
- ACPI_HANDLE handle;
- struct radeon_atpx_functions functions;
-};
-
-static struct radeon_atpx_priv {
- bool atpx_detected;
- /* handle for device - and atpx */
- ACPI_HANDLE dhandle;
- struct radeon_atpx atpx;
-} radeon_atpx_priv;
-
-struct atpx_verify_interface {
- u16 size; /* structure size in bytes (includes size field) */
- u16 version; /* version */
- u32 function_bits; /* supported functions bit vector */
-} __packed;
-
-struct atpx_power_control {
- u16 size;
- u8 dgpu_state;
-} __packed;
-
-struct atpx_mux {
- u16 size;
- u16 mux;
-} __packed;
-
-/**
- * radeon_atpx_call - call an ATPX method
- *
- * @handle: acpi handle
- * @function: the ATPX function to execute
- * @params: ATPX function params
- *
- * Executes the requested ATPX function (all asics).
- * Returns a pointer to the acpi output buffer.
- */
-static ACPI_OBJECT *radeon_atpx_call(ACPI_HANDLE handle, int function,
- ACPI_BUFFER *params)
-{
- ACPI_STATUS status;
- ACPI_OBJECT atpx_arg_elements[2];
- ACPI_OBJECT_LIST atpx_arg;
- ACPI_BUFFER buffer = { ACPI_ALLOCATE_BUFFER, NULL };
-
- atpx_arg.Count = 2;
- atpx_arg.Pointer = &atpx_arg_elements[0];
-
- atpx_arg_elements[0].Type = ACPI_TYPE_INTEGER;
- atpx_arg_elements[0].Integer.Value = function;
-
- if (params) {
- atpx_arg_elements[1].Type = ACPI_TYPE_BUFFER;
- atpx_arg_elements[1].Buffer.Length = params->Length;
- atpx_arg_elements[1].Buffer.Pointer = params->Pointer;
- } else {
- /* We need a second fake parameter */
- atpx_arg_elements[1].Type = ACPI_TYPE_INTEGER;
- atpx_arg_elements[1].Integer.Value = 0;
- }
-
- status = AcpiEvaluateObject(handle, NULL, &atpx_arg, &buffer);
-
- /* Fail only if calling the method fails and ATPX is supported */
- if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
- DRM_ERROR("failed to evaluate ATPX got %s\n",
- AcpiFormatException(status));
- AcpiOsFree(buffer.Pointer);
- return NULL;
- }
-
- return buffer.Pointer;
-}
-
-/**
- * radeon_atpx_parse_functions - parse supported functions
- *
- * @f: supported functions struct
- * @mask: supported functions mask from ATPX
- *
- * Use the supported functions mask from ATPX function
- * ATPX_FUNCTION_VERIFY_INTERFACE to determine what functions
- * are supported (all asics).
- */
-static void radeon_atpx_parse_functions(struct radeon_atpx_functions *f, u32 mask)
-{
- f->px_params = mask & ATPX_GET_PX_PARAMETERS_SUPPORTED;
- f->power_cntl = mask & ATPX_POWER_CONTROL_SUPPORTED;
- f->disp_mux_cntl = mask & ATPX_DISPLAY_MUX_CONTROL_SUPPORTED;
- f->i2c_mux_cntl = mask & ATPX_I2C_MUX_CONTROL_SUPPORTED;
- f->switch_start = mask & ATPX_GRAPHICS_DEVICE_SWITCH_START_NOTIFICATION_SUPPORTED;
- f->switch_end = mask & ATPX_GRAPHICS_DEVICE_SWITCH_END_NOTIFICATION_SUPPORTED;
- f->disp_connectors_mapping = mask & ATPX_GET_DISPLAY_CONNECTORS_MAPPING_SUPPORTED;
- f->disp_detetion_ports = mask & ATPX_GET_DISPLAY_DETECTION_PORTS_SUPPORTED;
-}
-
-/**
- * radeon_atpx_verify_interface - verify ATPX
- *
- * @handle: acpi handle
- * @atpx: radeon atpx struct
- *
- * Execute the ATPX_FUNCTION_VERIFY_INTERFACE ATPX function
- * to initialize ATPX and determine what features are supported
- * (all asics).
- * returns 0 on success, error on failure.
- */
-static int radeon_atpx_verify_interface(struct radeon_atpx *atpx)
-{
- ACPI_OBJECT *info;
- struct atpx_verify_interface output;
- size_t size;
- int err = 0;
-
- info = radeon_atpx_call(atpx->handle, ATPX_FUNCTION_VERIFY_INTERFACE, NULL);
- if (!info)
- return -EIO;
-
- memset(&output, 0, sizeof(output));
-
- size = *(u16 *) info->Buffer.Pointer;
- if (size < 8) {
- DRM_ERROR("ATPX buffer is too small: %zu\n", size);
- err = -EINVAL;
- goto out;
- }
- size = min(sizeof(output), size);
-
- memcpy(&output, info->Buffer.Pointer, size);
-
- /* TODO: check version? */
- DRM_INFO("ATPX version %u\n", output.version);
-
- radeon_atpx_parse_functions(&atpx->functions, output.function_bits);
-
-out:
- AcpiOsFree(info);
- return err;
-}
-
-/**
- * radeon_atpx_set_discrete_state - power up/down discrete GPU
- *
- * @atpx: atpx info struct
- * @state: discrete GPU state (0 = power down, 1 = power up)
- *
- * Execute the ATPX_FUNCTION_POWER_CONTROL ATPX function to
- * power down/up the discrete GPU (all asics).
- * Returns 0 on success, error on failure.
- */
-static int radeon_atpx_set_discrete_state(struct radeon_atpx *atpx, u8 state)
-{
- ACPI_BUFFER params;
- ACPI_OBJECT *info;
- struct atpx_power_control input;
-
- if (atpx->functions.power_cntl) {
- input.size = 3;
- input.dgpu_state = state;
- params.Length = input.size;
- params.Pointer = &input;
- info = radeon_atpx_call(atpx->handle,
- ATPX_FUNCTION_POWER_CONTROL,
- &params);
- if (!info)
- return -EIO;
- AcpiOsFree(info);
- }
- return 0;
-}
-
-/**
- * radeon_atpx_switch_disp_mux - switch display mux
- *
- * @atpx: atpx info struct
- * @mux_id: mux state (0 = integrated GPU, 1 = discrete GPU)
- *
- * Execute the ATPX_FUNCTION_DISPLAY_MUX_CONTROL ATPX function to
- * switch the display mux between the discrete GPU and integrated GPU
- * (all asics).
- * Returns 0 on success, error on failure.
- */
-static int radeon_atpx_switch_disp_mux(struct radeon_atpx *atpx, u16 mux_id)
-{
- ACPI_BUFFER params;
- ACPI_OBJECT *info;
- struct atpx_mux input;
-
- if (atpx->functions.disp_mux_cntl) {
- input.size = 4;
- input.mux = mux_id;
- params.Length = input.size;
- params.Pointer = &input;
- info = radeon_atpx_call(atpx->handle,
- ATPX_FUNCTION_DISPLAY_MUX_CONTROL,
- &params);
- if (!info)
- return -EIO;
- AcpiOsFree(info);
- }
- return 0;
-}
-
-/**
- * radeon_atpx_switch_i2c_mux - switch i2c/hpd mux
- *
- * @atpx: atpx info struct
- * @mux_id: mux state (0 = integrated GPU, 1 = discrete GPU)
- *
- * Execute the ATPX_FUNCTION_I2C_MUX_CONTROL ATPX function to
- * switch the i2c/hpd mux between the discrete GPU and integrated GPU
- * (all asics).
- * Returns 0 on success, error on failure.
- */
-static int radeon_atpx_switch_i2c_mux(struct radeon_atpx *atpx, u16 mux_id)
-{
- ACPI_BUFFER params;
- ACPI_OBJECT *info;
- struct atpx_mux input;
-
- if (atpx->functions.i2c_mux_cntl) {
- input.size = 4;
- input.mux = mux_id;
- params.Length = input.size;
- params.Pointer = &input;
- info = radeon_atpx_call(atpx->handle,
- ATPX_FUNCTION_I2C_MUX_CONTROL,
- &params);
- if (!info)
- return -EIO;
- AcpiOsFree(info);
- }
- return 0;
-}
-
-/**
- * radeon_atpx_switch_start - notify the sbios of a GPU switch
- *
- * @atpx: atpx info struct
- * @mux_id: mux state (0 = integrated GPU, 1 = discrete GPU)
- *
- * Execute the ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_START_NOTIFICATION ATPX
- * function to notify the sbios that a switch between the discrete GPU and
- * integrated GPU has begun (all asics).
- * Returns 0 on success, error on failure.
- */
-static int radeon_atpx_switch_start(struct radeon_atpx *atpx, u16 mux_id)
-{
- ACPI_BUFFER params;
- ACPI_OBJECT *info;
- struct atpx_mux input;
-
- if (atpx->functions.switch_start) {
- input.size = 4;
- input.mux = mux_id;
- params.Length = input.size;
- params.Pointer = &input;
- info = radeon_atpx_call(atpx->handle,
- ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_START_NOTIFICATION,
- &params);
- if (!info)
- return -EIO;
- AcpiOsFree(info);
- }
- return 0;
-}
-
-/**
- * radeon_atpx_switch_end - notify the sbios of a GPU switch
- *
- * @atpx: atpx info struct
- * @mux_id: mux state (0 = integrated GPU, 1 = discrete GPU)
- *
- * Execute the ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_END_NOTIFICATION ATPX
- * function to notify the sbios that a switch between the discrete GPU and
- * integrated GPU has ended (all asics).
- * Returns 0 on success, error on failure.
- */
-static int radeon_atpx_switch_end(struct radeon_atpx *atpx, u16 mux_id)
-{
- ACPI_BUFFER params;
- ACPI_OBJECT *info;
- struct atpx_mux input;
-
- if (atpx->functions.switch_end) {
- input.size = 4;
- input.mux = mux_id;
- params.Length = input.size;
- params.Pointer = &input;
- info = radeon_atpx_call(atpx->handle,
- ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_END_NOTIFICATION,
- &params);
- if (!info)
- return -EIO;
- AcpiOsFree(info);
- }
- return 0;
-}
-
-/**
- * radeon_atpx_switchto - switch to the requested GPU
- *
- * @id: GPU to switch to
- *
- * Execute the necessary ATPX functions to switch between the discrete GPU and
- * integrated GPU (all asics).
- * Returns 0 on success, error on failure.
- */
-static int radeon_atpx_switchto(enum vga_switcheroo_client_id id)
-{
- u16 gpu_id;
-
- if (id == VGA_SWITCHEROO_IGD)
- gpu_id = ATPX_INTEGRATED_GPU;
- else
- gpu_id = ATPX_DISCRETE_GPU;
-
- radeon_atpx_switch_start(&radeon_atpx_priv.atpx, gpu_id);
- radeon_atpx_switch_disp_mux(&radeon_atpx_priv.atpx, gpu_id);
- radeon_atpx_switch_i2c_mux(&radeon_atpx_priv.atpx, gpu_id);
- radeon_atpx_switch_end(&radeon_atpx_priv.atpx, gpu_id);
-
- return 0;
-}
-
-/**
- * radeon_atpx_power_state - power down/up the requested GPU
- *
- * @id: GPU to power down/up
- * @state: requested power state (0 = off, 1 = on)
- *
- * Execute the necessary ATPX function to power down/up the discrete GPU
- * (all asics).
- * Returns 0 on success, error on failure.
- */
-static int radeon_atpx_power_state(enum vga_switcheroo_client_id id,
- enum vga_switcheroo_state state)
-{
- /* on w500 ACPI can't change intel gpu state */
- if (id == VGA_SWITCHEROO_IGD)
- return 0;
-
- radeon_atpx_set_discrete_state(&radeon_atpx_priv.atpx, state);
- return 0;
-}
-
-/**
- * radeon_atpx_pci_probe_handle - look up the ATPX handle
- *
- * @pdev: pci device
- *
- * Look up the ATPX handles (all asics).
- * Returns true if the handles are found, false if not.
- */
-static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev)
-{
- ACPI_HANDLE dhandle, atpx_handle;
- ACPI_STATUS status;
-
- dhandle = DEVICE_ACPI_HANDLE(&pdev->dev);
- if (!dhandle)
- return false;
-
- status = AcpiGetHandle(dhandle, "ATPX", &atpx_handle);
- if (ACPI_FAILURE(status))
- return false;
-
- radeon_atpx_priv.dhandle = dhandle;
- radeon_atpx_priv.atpx.handle = atpx_handle;
- return true;
-}
-
-/**
- * radeon_atpx_init - verify the ATPX interface
- *
- * Verify the ATPX interface (all asics).
- * Returns 0 on success, error on failure.
- */
-static int radeon_atpx_init(void)
-{
- /* set up the ATPX handle */
- return radeon_atpx_verify_interface(&radeon_atpx_priv.atpx);
-}
-
-/**
- * radeon_atpx_get_client_id - get the client id
- *
- * @pdev: pci device
- *
- * look up whether we are the integrated or discrete GPU (all asics).
- * Returns the client id.
- */
-static int radeon_atpx_get_client_id(struct pci_dev *pdev)
-{
- if (radeon_atpx_priv.dhandle == DEVICE_ACPI_HANDLE(&pdev->dev))
- return VGA_SWITCHEROO_IGD;
- else
- return VGA_SWITCHEROO_DIS;
-}
-
-static struct vga_switcheroo_handler radeon_atpx_handler = {
- .switchto = radeon_atpx_switchto,
- .power_state = radeon_atpx_power_state,
- .init = radeon_atpx_init,
- .get_client_id = radeon_atpx_get_client_id,
-};
-
-/**
- * radeon_atpx_detect - detect whether we have PX
- *
- * Check if we have a PX system (all asics).
- * Returns true if we have a PX system, false if not.
- */
-static bool radeon_atpx_detect(void)
-{
- char acpi_method_name[255] = { 0 };
- ACPI_BUFFER buffer = {sizeof(acpi_method_name), acpi_method_name};
- struct pci_dev *pdev = NULL;
- bool has_atpx = false;
- int vga_count = 0;
-
- while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
- vga_count++;
-
- has_atpx |= (radeon_atpx_pci_probe_handle(pdev) == true);
- }
-
- if (has_atpx && vga_count == 2) {
- AcpiGetName(radeon_atpx_priv.atpx.handle, ACPI_FULL_PATHNAME, &buffer);
- DRM_INFO("VGA switcheroo: detected switching method %s handle\n",
- acpi_method_name);
- radeon_atpx_priv.atpx_detected = true;
- return true;
- }
- return false;
-}
-#endif /* DUMBBELL_WIP */
-
-/**
- * radeon_register_atpx_handler - register with vga_switcheroo
- *
- * Register the PX callbacks with vga_switcheroo (all asics).
- */
-void radeon_register_atpx_handler(void)
-{
-#ifdef DUMBBELL_WIP
- bool r;
-
- /* detect if we have any ATPX + 2 VGA in the system */
- r = radeon_atpx_detect();
- if (!r)
- return;
-
- vga_switcheroo_register_handler(&radeon_atpx_handler);
-#endif /* DUMBBELL_WIP */
-}
-
-/**
- * radeon_unregister_atpx_handler - unregister with vga_switcheroo
- *
- * Unregister the PX callbacks with vga_switcheroo (all asics).
- */
-void radeon_unregister_atpx_handler(void)
-{
-#ifdef DUMBBELL_WIP
- vga_switcheroo_unregister_handler();
-#endif /* DUMBBELL_WIP */
-}
diff --git a/sys/dev/drm2/radeon/radeon_benchmark.c b/sys/dev/drm2/radeon/radeon_benchmark.c
index ce39748..a90ebf6 100644
--- a/sys/dev/drm2/radeon/radeon_benchmark.c
+++ b/sys/dev/drm2/radeon/radeon_benchmark.c
@@ -139,13 +139,15 @@ static void radeon_benchmark_move(struct radeon_device *rdev, unsigned size,
sdomain, ddomain, "dma");
}
- time = radeon_benchmark_do_move(rdev, size, saddr, daddr,
- RADEON_BENCHMARK_COPY_BLIT, n);
- if (time < 0)
- goto out_cleanup;
- if (time > 0)
- radeon_benchmark_log_results(n, size, time,
- sdomain, ddomain, "blit");
+ if (rdev->asic->copy.blit) {
+ time = radeon_benchmark_do_move(rdev, size, saddr, daddr,
+ RADEON_BENCHMARK_COPY_BLIT, n);
+ if (time < 0)
+ goto out_cleanup;
+ if (time > 0)
+ radeon_benchmark_log_results(n, size, time,
+ sdomain, ddomain, "blit");
+ }
out_cleanup:
if (sobj) {
diff --git a/sys/dev/drm2/radeon/radeon_bios.c b/sys/dev/drm2/radeon/radeon_bios.c
index ee48268..ffb3756 100644
--- a/sys/dev/drm2/radeon/radeon_bios.c
+++ b/sys/dev/drm2/radeon/radeon_bios.c
@@ -46,7 +46,7 @@ __FBSDID("$FreeBSD$");
*/
static bool igp_read_bios_from_vram(struct radeon_device *rdev)
{
- drm_local_map_t bios_map;
+ struct drm_local_map bios_map;
uint8_t __iomem *bios;
resource_size_t vram_base;
resource_size_t size = 256 * 1024; /* ??? */
@@ -70,11 +70,11 @@ static bool igp_read_bios_from_vram(struct radeon_device *rdev)
bios_map.flags = 0;
bios_map.mtrr = 0;
drm_core_ioremap(&bios_map, rdev->ddev);
- if (bios_map.virtual == NULL) {
+ if (bios_map.handle == NULL) {
DRM_INFO("%s: failed to ioremap\n", __func__);
return false;
}
- bios = bios_map.virtual;
+ bios = bios_map.handle;
size = bios_map.size;
DRM_INFO("%s: Map address: %p (%ju bytes)\n", __func__, bios, (uintmax_t)size);
@@ -88,7 +88,7 @@ static bool igp_read_bios_from_vram(struct radeon_device *rdev)
drm_core_ioremapfree(&bios_map, rdev->ddev);
return false;
}
- rdev->bios = malloc(size, DRM_MEM_DRIVER, M_WAITOK);
+ rdev->bios = malloc(size, DRM_MEM_DRIVER, M_NOWAIT);
if (rdev->bios == NULL) {
drm_core_ioremapfree(&bios_map, rdev->ddev);
return false;
@@ -125,12 +125,17 @@ static bool radeon_read_bios(struct radeon_device *rdev)
vga_pci_unmap_bios(vga_dev, bios);
return false;
}
- rdev->bios = malloc(size, DRM_MEM_DRIVER, M_WAITOK);
+ rdev->bios = malloc(size, DRM_MEM_DRIVER, M_NOWAIT);
+ if (rdev->bios == NULL) {
+ vga_pci_unmap_bios(vga_dev, bios);
+ return false;
+ }
memcpy(rdev->bios, bios, size);
vga_pci_unmap_bios(vga_dev, bios);
return true;
}
+#ifdef CONFIG_ACPI
/* ATRM is used to get the BIOS on the discrete cards in
* dual-gpu systems.
*/
@@ -197,9 +202,9 @@ static bool radeon_atrm_get_bios(struct radeon_device *rdev)
return false;
}
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
if ((dev = pci_find_class(PCIC_DISPLAY, PCIS_DISPLAY_VGA)) != NULL) {
DRM_INFO("%s: pci_find_class() found: %d:%d:%d:%d, vendor=%04x, device=%04x\n",
__func__,
@@ -211,10 +216,10 @@ static bool radeon_atrm_get_bios(struct radeon_device *rdev)
pci_get_device(dev));
DRM_INFO("%s: Get ACPI device handle\n", __func__);
dhandle = acpi_get_handle(dev);
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
if (!dhandle)
continue;
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
if (!dhandle)
return false;
@@ -222,9 +227,9 @@ static bool radeon_atrm_get_bios(struct radeon_device *rdev)
status = AcpiGetHandle(dhandle, "ATRM", &atrm_handle);
if (!ACPI_FAILURE(status)) {
found = true;
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
break;
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
} else {
DRM_INFO("%s: Failed to get \"ATRM\" handle: %s\n",
__func__, AcpiFormatException(status));
@@ -234,7 +239,7 @@ static bool radeon_atrm_get_bios(struct radeon_device *rdev)
if (!found)
return false;
- rdev->bios = malloc(size, DRM_MEM_DRIVER, M_WAITOK);
+ rdev->bios = malloc(size, DRM_MEM_DRIVER, M_NOWAIT);
if (!rdev->bios) {
DRM_ERROR("Unable to allocate bios\n");
return false;
@@ -262,6 +267,12 @@ static bool radeon_atrm_get_bios(struct radeon_device *rdev)
}
return true;
}
+#else
+static inline bool radeon_atrm_get_bios(struct radeon_device *rdev)
+{
+ return false;
+}
+#endif
static bool ni_read_disabled_bios(struct radeon_device *rdev)
{
@@ -620,6 +631,7 @@ static bool radeon_read_disabled_bios(struct radeon_device *rdev)
return legacy_read_disabled_bios(rdev);
}
+#ifdef CONFIG_ACPI
static bool radeon_acpi_vfct_bios(struct radeon_device *rdev)
{
bool ret = false;
@@ -671,13 +683,20 @@ static bool radeon_acpi_vfct_bios(struct radeon_device *rdev)
goto out_unmap;
}
- rdev->bios = malloc(vhdr->ImageLength, DRM_MEM_DRIVER, M_WAITOK);
- memcpy(rdev->bios, &vbios->VbiosContent, vhdr->ImageLength);
+ rdev->bios = malloc(vhdr->ImageLength, DRM_MEM_DRIVER, M_NOWAIT);
+ if (rdev->bios)
+ memcpy(rdev->bios, &vbios->VbiosContent, vhdr->ImageLength);
ret = !!rdev->bios;
out_unmap:
return ret;
}
+#else
+static inline bool radeon_acpi_vfct_bios(struct radeon_device *rdev)
+{
+ return false;
+}
+#endif
bool radeon_get_bios(struct radeon_device *rdev)
{
diff --git a/sys/dev/drm2/radeon/radeon_clocks.c b/sys/dev/drm2/radeon/radeon_clocks.c
index 9ecd18a..4bd9f0d 100644
--- a/sys/dev/drm2/radeon/radeon_clocks.c
+++ b/sys/dev/drm2/radeon/radeon_clocks.c
@@ -405,19 +405,19 @@ void radeon_legacy_set_engine_clock(struct radeon_device *rdev,
tmp &= ~RADEON_SCLK_SRC_SEL_MASK;
WREG32_PLL(RADEON_SCLK_CNTL, tmp);
- DRM_UDELAY(10);
+ udelay(10);
tmp = RREG32_PLL(RADEON_SPLL_CNTL);
tmp |= RADEON_SPLL_SLEEP;
WREG32_PLL(RADEON_SPLL_CNTL, tmp);
- DRM_UDELAY(2);
+ udelay(2);
tmp = RREG32_PLL(RADEON_SPLL_CNTL);
tmp |= RADEON_SPLL_RESET;
WREG32_PLL(RADEON_SPLL_CNTL, tmp);
- DRM_UDELAY(200);
+ udelay(200);
tmp = RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV);
tmp &= ~(RADEON_SPLL_FB_DIV_MASK << RADEON_SPLL_FB_DIV_SHIFT);
@@ -437,13 +437,13 @@ void radeon_legacy_set_engine_clock(struct radeon_device *rdev,
tmp &= ~RADEON_SPLL_SLEEP;
WREG32_PLL(RADEON_SPLL_CNTL, tmp);
- DRM_UDELAY(2);
+ udelay(2);
tmp = RREG32_PLL(RADEON_SPLL_CNTL);
tmp &= ~RADEON_SPLL_RESET;
WREG32_PLL(RADEON_SPLL_CNTL, tmp);
- DRM_UDELAY(200);
+ udelay(200);
tmp = RREG32_PLL(RADEON_SCLK_CNTL);
tmp &= ~RADEON_SCLK_SRC_SEL_MASK;
@@ -464,13 +464,13 @@ void radeon_legacy_set_engine_clock(struct radeon_device *rdev,
}
WREG32_PLL(RADEON_SCLK_CNTL, tmp);
- DRM_UDELAY(20);
+ udelay(20);
tmp = RREG32_PLL(RADEON_CLK_PIN_CNTL);
tmp |= RADEON_DONT_USE_XTALIN;
WREG32_PLL(RADEON_CLK_PIN_CNTL, tmp);
- DRM_UDELAY(10);
+ udelay(10);
}
void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable)
@@ -638,7 +638,7 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable)
tmp &= ~(R300_SCLK_FORCE_VAP);
tmp |= RADEON_SCLK_FORCE_CP;
WREG32_PLL(RADEON_SCLK_CNTL, tmp);
- DRM_MDELAY(15);
+ mdelay(15);
tmp = RREG32_PLL(R300_SCLK_CNTL2);
tmp &= ~(R300_SCLK_FORCE_TCL |
@@ -656,12 +656,12 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable)
tmp |= (RADEON_ENGIN_DYNCLK_MODE |
(0x01 << RADEON_ACTIVE_HILO_LAT_SHIFT));
WREG32_PLL(RADEON_CLK_PWRMGT_CNTL, tmp);
- DRM_MDELAY(15);
+ mdelay(15);
tmp = RREG32_PLL(RADEON_CLK_PIN_CNTL);
tmp |= RADEON_SCLK_DYN_START_CNTL;
WREG32_PLL(RADEON_CLK_PIN_CNTL, tmp);
- DRM_MDELAY(15);
+ mdelay(15);
/* When DRI is enabled, setting DYN_STOP_LAT to zero can cause some R200
to lockup randomly, leave them as set by BIOS.
@@ -701,7 +701,7 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable)
tmp |= RADEON_SCLK_MORE_FORCEON;
}
WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp);
- DRM_MDELAY(15);
+ mdelay(15);
}
/* RV200::A11 A12, RV250::A11 A12 */
@@ -714,7 +714,7 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable)
tmp |= RADEON_TCL_BYPASS_DISABLE;
WREG32_PLL(RADEON_PLL_PWRMGT_CNTL, tmp);
}
- DRM_MDELAY(15);
+ mdelay(15);
/*enable dynamic mode for display clocks (PIXCLK and PIX2CLK) */
tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL);
@@ -727,14 +727,14 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable)
RADEON_PIXCLK_TMDS_ALWAYS_ONb);
WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp);
- DRM_MDELAY(15);
+ mdelay(15);
tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL);
tmp |= (RADEON_PIXCLK_ALWAYS_ONb |
RADEON_PIXCLK_DAC_ALWAYS_ONb);
WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp);
- DRM_MDELAY(15);
+ mdelay(15);
}
} else {
/* Turn everything OFF (ForceON to everything) */
@@ -866,7 +866,7 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable)
}
WREG32_PLL(RADEON_SCLK_CNTL, tmp);
- DRM_MDELAY(16);
+ mdelay(16);
if ((rdev->family == CHIP_R300) ||
(rdev->family == CHIP_R350)) {
@@ -875,7 +875,7 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable)
R300_SCLK_FORCE_GA |
R300_SCLK_FORCE_CBA);
WREG32_PLL(R300_SCLK_CNTL2, tmp);
- DRM_MDELAY(16);
+ mdelay(16);
}
if (rdev->flags & RADEON_IS_IGP) {
@@ -883,7 +883,7 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable)
tmp &= ~(RADEON_FORCEON_MCLKA |
RADEON_FORCEON_YCLKA);
WREG32_PLL(RADEON_MCLK_CNTL, tmp);
- DRM_MDELAY(16);
+ mdelay(16);
}
if ((rdev->family == CHIP_RV200) ||
@@ -892,7 +892,7 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable)
tmp = RREG32_PLL(RADEON_SCLK_MORE_CNTL);
tmp |= RADEON_SCLK_MORE_FORCEON;
WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp);
- DRM_MDELAY(16);
+ mdelay(16);
}
tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL);
@@ -905,7 +905,7 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable)
RADEON_PIXCLK_TMDS_ALWAYS_ONb);
WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp);
- DRM_MDELAY(16);
+ mdelay(16);
tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL);
tmp &= ~(RADEON_PIXCLK_ALWAYS_ONb |
diff --git a/sys/dev/drm2/radeon/radeon_combios.c b/sys/dev/drm2/radeon/radeon_combios.c
index caa8a00..7d0fd61 100644
--- a/sys/dev/drm2/radeon/radeon_combios.c
+++ b/sys/dev/drm2/radeon/radeon_combios.c
@@ -41,6 +41,29 @@ __FBSDID("$FreeBSD$");
#include <asm/pci-bridge.h>
#endif /* CONFIG_PPC_PMAC */
+#ifdef FREEBSD_WIP /* FreeBSD: to please GCC 4.2. */
+/* from radeon_encoder.c */
+extern uint32_t
+radeon_get_encoder_enum(struct drm_device *dev, uint32_t supported_device,
+ uint8_t dac);
+extern void radeon_link_encoder_connector(struct drm_device *dev);
+
+/* from radeon_connector.c */
+extern void
+radeon_add_legacy_connector(struct drm_device *dev,
+ uint32_t connector_id,
+ uint32_t supported_device,
+ int connector_type,
+ struct radeon_i2c_bus_rec *i2c_bus,
+ uint16_t connector_object_id,
+ struct radeon_hpd *hpd);
+
+/* from radeon_legacy_encoder.c */
+extern void
+radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_enum,
+ uint32_t supported_device);
+#endif
+
/* old legacy ATI BIOS routines */
/* COMBIOS table offsets */
@@ -440,7 +463,7 @@ bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev)
raw = rdev->bios + edid_info;
size = EDID_LENGTH * (raw[0x7e] + 1);
- edid = malloc(size, DRM_MEM_KMS, M_WAITOK);
+ edid = malloc(size, DRM_MEM_KMS, M_NOWAIT);
if (edid == NULL)
return false;
@@ -464,7 +487,7 @@ radeon_bios_get_hardcoded_edid(struct radeon_device *rdev)
if (rdev->mode_info.bios_hardcoded_edid) {
edid = malloc(rdev->mode_info.bios_hardcoded_edid_size,
- DRM_MEM_KMS, M_WAITOK);
+ DRM_MEM_KMS, M_NOWAIT);
if (edid) {
memcpy((unsigned char *)edid,
(unsigned char *)rdev->mode_info.bios_hardcoded_edid,
@@ -931,7 +954,7 @@ struct radeon_encoder_primary_dac *radeon_combios_get_primary_dac_info(struct
int found = 0;
p_dac = malloc(sizeof(struct radeon_encoder_primary_dac),
- DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (!p_dac)
return NULL;
@@ -954,6 +977,15 @@ struct radeon_encoder_primary_dac *radeon_combios_get_primary_dac_info(struct
found = 1;
}
+ /* quirks */
+ /* Radeon 9100 (R200) */
+ if ((dev->pci_device == 0x514D) &&
+ (dev->pci_subvendor == 0x174B) &&
+ (dev->pci_subdevice == 0x7149)) {
+ /* vbios value is bad, use the default */
+ found = 0;
+ }
+
if (!found) /* fallback to defaults */
radeon_legacy_get_primary_dac_info_from_table(rdev, p_dac);
@@ -1067,7 +1099,7 @@ struct radeon_encoder_tv_dac *radeon_combios_get_tv_dac_info(struct
int found = 0;
tv_dac = malloc(sizeof(struct radeon_encoder_tv_dac),
- DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (!tv_dac)
return NULL;
@@ -1156,7 +1188,7 @@ static struct radeon_encoder_lvds *radeon_legacy_get_lvds_info_from_regs(struct
uint32_t lvds_ss_gen_cntl = RREG32(RADEON_LVDS_SS_GEN_CNTL);
lvds = malloc(sizeof(struct radeon_encoder_lvds),
- DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (!lvds)
return NULL;
@@ -1232,7 +1264,7 @@ struct radeon_encoder_lvds *radeon_combios_get_lvds_info(struct radeon_encoder
if (lcd_info) {
lvds = malloc(sizeof(struct radeon_encoder_lvds),
- DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (!lvds)
return NULL;
@@ -2690,15 +2722,15 @@ void radeon_combios_get_power_modes(struct radeon_device *rdev)
/* allocate 2 power states */
rdev->pm.power_state = malloc(sizeof(struct radeon_power_state) * 2,
- DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (rdev->pm.power_state) {
/* allocate 1 clock mode per state */
rdev->pm.power_state[0].clock_info =
malloc(sizeof(struct radeon_pm_clock_info) * 1,
- DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
rdev->pm.power_state[1].clock_info =
malloc(sizeof(struct radeon_pm_clock_info) * 1,
- DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (!rdev->pm.power_state[0].clock_info ||
!rdev->pm.power_state[1].clock_info)
goto pm_failed;
@@ -2743,13 +2775,13 @@ void radeon_combios_get_power_modes(struct radeon_device *rdev)
i2c_bus = combios_setup_i2c_bus(rdev, gpio, 0, 0);
rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus);
if (rdev->pm.i2c_bus) {
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
struct i2c_board_info info = { };
const char *name = thermal_controller_names[thermal_controller];
info.addr = i2c_addr >> 1;
strlcpy(info.type, name, sizeof(info.type));
i2c_new_device(&rdev->pm.i2c_bus->adapter, &info);
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
}
}
} else {
@@ -2762,7 +2794,7 @@ void radeon_combios_get_power_modes(struct radeon_device *rdev)
i2c_bus = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0);
rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus);
if (rdev->pm.i2c_bus) {
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
struct i2c_board_info info = { };
const char *name = "f75375";
info.addr = 0x28;
@@ -2770,7 +2802,7 @@ void radeon_combios_get_power_modes(struct radeon_device *rdev)
i2c_new_device(&rdev->pm.i2c_bus->adapter, &info);
DRM_INFO("Possible %s thermal controller at 0x%02x\n",
name, info.addr);
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
}
}
}
@@ -2974,12 +3006,12 @@ bool radeon_combios_external_tmds_setup(struct drm_encoder *encoder)
case 3:
val = RBIOS16(index);
index += 2;
- DRM_UDELAY(val);
+ udelay(val);
break;
case 4:
val = RBIOS16(index);
index += 2;
- DRM_MDELAY(val);
+ mdelay(val);
break;
case 6:
slave_addr = id & 0xff;
@@ -3028,7 +3060,7 @@ bool radeon_combios_external_tmds_setup(struct drm_encoder *encoder)
case 4:
val = RBIOS16(index);
index += 2;
- DRM_UDELAY(val);
+ udelay(val);
break;
case 5:
reg = id & 0x1fff;
@@ -3106,7 +3138,7 @@ static void combios_parse_mmio_table(struct drm_device *dev, uint16_t offset)
case 4:
val = RBIOS16(offset);
offset += 2;
- DRM_UDELAY(val);
+ udelay(val);
break;
case 5:
val = RBIOS16(offset);
@@ -3175,10 +3207,10 @@ static void combios_parse_pll_table(struct drm_device *dev, uint16_t offset)
tmp = 1000;
switch (addr) {
case 1:
- DRM_UDELAY(150);
+ udelay(150);
break;
case 2:
- DRM_MDELAY(1);
+ mdelay(1);
break;
case 3:
while (tmp--) {
@@ -3209,13 +3241,13 @@ static void combios_parse_pll_table(struct drm_device *dev, uint16_t offset)
/*mclk_cntl |= 0x00001111;*//* ??? */
WREG32_PLL(RADEON_MCLK_CNTL,
mclk_cntl);
- DRM_MDELAY(10);
+ mdelay(10);
#endif
WREG32_PLL
(RADEON_CLK_PWRMGT_CNTL,
tmp &
~RADEON_CG_NO1_DEBUG_0);
- DRM_MDELAY(10);
+ mdelay(10);
}
break;
default:
diff --git a/sys/dev/drm2/radeon/radeon_connectors.c b/sys/dev/drm2/radeon/radeon_connectors.c
index d303dfa..8c55325 100644
--- a/sys/dev/drm2/radeon/radeon_connectors.c
+++ b/sys/dev/drm2/radeon/radeon_connectors.c
@@ -35,6 +35,17 @@ __FBSDID("$FreeBSD$");
#include "radeon.h"
#include "atom.h"
+#ifdef FREEBSD_WIP /* FreeBSD: to please GCC 4.2. */
+extern void
+radeon_combios_connected_scratch_regs(struct drm_connector *connector,
+ struct drm_encoder *encoder,
+ bool connected);
+extern void
+radeon_atombios_connected_scratch_regs(struct drm_connector *connector,
+ struct drm_encoder *encoder,
+ bool connected);
+#endif
+
void radeon_connector_hotplug(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
@@ -641,9 +652,9 @@ static void radeon_connector_destroy(struct drm_connector *connector)
if (radeon_connector->edid)
free(radeon_connector->edid, DRM_MEM_KMS);
free(radeon_connector->con_priv, DRM_MEM_DRIVER);
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
drm_sysfs_connector_remove(connector);
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
drm_connector_cleanup(connector);
free(connector, DRM_MEM_DRIVER);
}
@@ -1211,9 +1222,9 @@ static void radeon_dp_connector_destroy(struct drm_connector *connector)
if (radeon_dig_connector->dp_i2c_bus)
radeon_i2c_destroy(radeon_dig_connector->dp_i2c_bus);
free(radeon_connector->con_priv, DRM_MEM_DRIVER);
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
drm_sysfs_connector_remove(connector);
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
drm_connector_cleanup(connector);
free(connector, DRM_MEM_DRIVER);
}
@@ -1555,7 +1566,7 @@ radeon_add_atom_connector(struct drm_device *dev,
}
radeon_connector = malloc(sizeof(struct radeon_connector),
- DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (!radeon_connector)
return;
@@ -1577,7 +1588,7 @@ radeon_add_atom_connector(struct drm_device *dev,
if (is_dp_bridge) {
radeon_dig_connector = malloc(
sizeof(struct radeon_connector_atom_dig),
- DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (!radeon_dig_connector)
goto failed;
radeon_dig_connector->igp_lane_info = igp_lane_info;
@@ -1603,7 +1614,7 @@ radeon_add_atom_connector(struct drm_device *dev,
connector->interlace_allowed = true;
connector->doublescan_allowed = true;
radeon_connector->dac_load_detect = true;
- drm_connector_attach_property(&radeon_connector->base,
+ drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.load_detect_property,
1);
break;
@@ -1612,13 +1623,13 @@ radeon_add_atom_connector(struct drm_device *dev,
case DRM_MODE_CONNECTOR_HDMIA:
case DRM_MODE_CONNECTOR_HDMIB:
case DRM_MODE_CONNECTOR_DisplayPort:
- drm_connector_attach_property(&radeon_connector->base,
+ drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.underscan_property,
UNDERSCAN_OFF);
- drm_connector_attach_property(&radeon_connector->base,
+ drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.underscan_hborder_property,
0);
- drm_connector_attach_property(&radeon_connector->base,
+ drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.underscan_vborder_property,
0);
subpixel_order = SubPixelHorizontalRGB;
@@ -1629,14 +1640,14 @@ radeon_add_atom_connector(struct drm_device *dev,
connector->doublescan_allowed = false;
if (connector_type == DRM_MODE_CONNECTOR_DVII) {
radeon_connector->dac_load_detect = true;
- drm_connector_attach_property(&radeon_connector->base,
+ drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.load_detect_property,
1);
}
break;
case DRM_MODE_CONNECTOR_LVDS:
case DRM_MODE_CONNECTOR_eDP:
- drm_connector_attach_property(&radeon_connector->base,
+ drm_object_attach_property(&radeon_connector->base.base,
dev->mode_config.scaling_mode_property,
DRM_MODE_SCALE_FULLSCREEN);
subpixel_order = SubPixelHorizontalRGB;
@@ -1655,7 +1666,7 @@ radeon_add_atom_connector(struct drm_device *dev,
DRM_ERROR("VGA: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
}
radeon_connector->dac_load_detect = true;
- drm_connector_attach_property(&radeon_connector->base,
+ drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.load_detect_property,
1);
/* no HPD on analog connectors */
@@ -1673,7 +1684,7 @@ radeon_add_atom_connector(struct drm_device *dev,
DRM_ERROR("DVIA: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
}
radeon_connector->dac_load_detect = true;
- drm_connector_attach_property(&radeon_connector->base,
+ drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.load_detect_property,
1);
/* no HPD on analog connectors */
@@ -1685,7 +1696,7 @@ radeon_add_atom_connector(struct drm_device *dev,
case DRM_MODE_CONNECTOR_DVID:
radeon_dig_connector = malloc(
sizeof(struct radeon_connector_atom_dig),
- DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (!radeon_dig_connector)
goto failed;
radeon_dig_connector->igp_lane_info = igp_lane_info;
@@ -1698,23 +1709,23 @@ radeon_add_atom_connector(struct drm_device *dev,
DRM_ERROR("DVI: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
}
subpixel_order = SubPixelHorizontalRGB;
- drm_connector_attach_property(&radeon_connector->base,
+ drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.coherent_mode_property,
1);
if (ASIC_IS_AVIVO(rdev)) {
- drm_connector_attach_property(&radeon_connector->base,
+ drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.underscan_property,
UNDERSCAN_OFF);
- drm_connector_attach_property(&radeon_connector->base,
+ drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.underscan_hborder_property,
0);
- drm_connector_attach_property(&radeon_connector->base,
+ drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.underscan_vborder_property,
0);
}
if (connector_type == DRM_MODE_CONNECTOR_DVII) {
radeon_connector->dac_load_detect = true;
- drm_connector_attach_property(&radeon_connector->base,
+ drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.load_detect_property,
1);
}
@@ -1728,7 +1739,7 @@ radeon_add_atom_connector(struct drm_device *dev,
case DRM_MODE_CONNECTOR_HDMIB:
radeon_dig_connector = malloc(
sizeof(struct radeon_connector_atom_dig),
- DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (!radeon_dig_connector)
goto failed;
radeon_dig_connector->igp_lane_info = igp_lane_info;
@@ -1740,17 +1751,17 @@ radeon_add_atom_connector(struct drm_device *dev,
if (!radeon_connector->ddc_bus)
DRM_ERROR("HDMI: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
}
- drm_connector_attach_property(&radeon_connector->base,
+ drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.coherent_mode_property,
1);
if (ASIC_IS_AVIVO(rdev)) {
- drm_connector_attach_property(&radeon_connector->base,
+ drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.underscan_property,
UNDERSCAN_OFF);
- drm_connector_attach_property(&radeon_connector->base,
+ drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.underscan_hborder_property,
0);
- drm_connector_attach_property(&radeon_connector->base,
+ drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.underscan_vborder_property,
0);
}
@@ -1764,7 +1775,7 @@ radeon_add_atom_connector(struct drm_device *dev,
case DRM_MODE_CONNECTOR_DisplayPort:
radeon_dig_connector = malloc(
sizeof(struct radeon_connector_atom_dig),
- DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (!radeon_dig_connector)
goto failed;
radeon_dig_connector->igp_lane_info = igp_lane_info;
@@ -1781,17 +1792,17 @@ radeon_add_atom_connector(struct drm_device *dev,
DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
}
subpixel_order = SubPixelHorizontalRGB;
- drm_connector_attach_property(&radeon_connector->base,
+ drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.coherent_mode_property,
1);
if (ASIC_IS_AVIVO(rdev)) {
- drm_connector_attach_property(&radeon_connector->base,
+ drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.underscan_property,
UNDERSCAN_OFF);
- drm_connector_attach_property(&radeon_connector->base,
+ drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.underscan_hborder_property,
0);
- drm_connector_attach_property(&radeon_connector->base,
+ drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.underscan_vborder_property,
0);
}
@@ -1802,7 +1813,7 @@ radeon_add_atom_connector(struct drm_device *dev,
case DRM_MODE_CONNECTOR_eDP:
radeon_dig_connector = malloc(
sizeof(struct radeon_connector_atom_dig),
- DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (!radeon_dig_connector)
goto failed;
radeon_dig_connector->igp_lane_info = igp_lane_info;
@@ -1818,7 +1829,7 @@ radeon_add_atom_connector(struct drm_device *dev,
if (!radeon_connector->ddc_bus)
DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
}
- drm_connector_attach_property(&radeon_connector->base,
+ drm_object_attach_property(&radeon_connector->base.base,
dev->mode_config.scaling_mode_property,
DRM_MODE_SCALE_FULLSCREEN);
subpixel_order = SubPixelHorizontalRGB;
@@ -1831,10 +1842,10 @@ radeon_add_atom_connector(struct drm_device *dev,
drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type);
drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs);
radeon_connector->dac_load_detect = true;
- drm_connector_attach_property(&radeon_connector->base,
+ drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.load_detect_property,
1);
- drm_connector_attach_property(&radeon_connector->base,
+ drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.tv_std_property,
radeon_atombios_get_tv_info(rdev));
/* no HPD on analog connectors */
@@ -1845,7 +1856,7 @@ radeon_add_atom_connector(struct drm_device *dev,
case DRM_MODE_CONNECTOR_LVDS:
radeon_dig_connector = malloc(
sizeof(struct radeon_connector_atom_dig),
- DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (!radeon_dig_connector)
goto failed;
radeon_dig_connector->igp_lane_info = igp_lane_info;
@@ -1857,7 +1868,7 @@ radeon_add_atom_connector(struct drm_device *dev,
if (!radeon_connector->ddc_bus)
DRM_ERROR("LVDS: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
}
- drm_connector_attach_property(&radeon_connector->base,
+ drm_object_attach_property(&radeon_connector->base.base,
dev->mode_config.scaling_mode_property,
DRM_MODE_SCALE_FULLSCREEN);
subpixel_order = SubPixelHorizontalRGB;
@@ -1874,9 +1885,9 @@ radeon_add_atom_connector(struct drm_device *dev,
connector->polled = DRM_CONNECTOR_POLL_HPD;
connector->display_info.subpixel_order = subpixel_order;
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
drm_sysfs_connector_add(connector);
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
return;
failed:
@@ -1918,7 +1929,7 @@ radeon_add_legacy_connector(struct drm_device *dev,
}
radeon_connector = malloc(sizeof(struct radeon_connector),
- DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (!radeon_connector)
return;
@@ -1939,7 +1950,7 @@ radeon_add_legacy_connector(struct drm_device *dev,
DRM_ERROR("VGA: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
}
radeon_connector->dac_load_detect = true;
- drm_connector_attach_property(&radeon_connector->base,
+ drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.load_detect_property,
1);
/* no HPD on analog connectors */
@@ -1957,7 +1968,7 @@ radeon_add_legacy_connector(struct drm_device *dev,
DRM_ERROR("DVIA: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
}
radeon_connector->dac_load_detect = true;
- drm_connector_attach_property(&radeon_connector->base,
+ drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.load_detect_property,
1);
/* no HPD on analog connectors */
@@ -1976,7 +1987,7 @@ radeon_add_legacy_connector(struct drm_device *dev,
}
if (connector_type == DRM_MODE_CONNECTOR_DVII) {
radeon_connector->dac_load_detect = true;
- drm_connector_attach_property(&radeon_connector->base,
+ drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.load_detect_property,
1);
}
@@ -2000,10 +2011,10 @@ radeon_add_legacy_connector(struct drm_device *dev,
*/
if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480)
radeon_connector->dac_load_detect = false;
- drm_connector_attach_property(&radeon_connector->base,
+ drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.load_detect_property,
radeon_connector->dac_load_detect);
- drm_connector_attach_property(&radeon_connector->base,
+ drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.tv_std_property,
radeon_combios_get_tv_info(rdev));
/* no HPD on analog connectors */
@@ -2019,7 +2030,7 @@ radeon_add_legacy_connector(struct drm_device *dev,
if (!radeon_connector->ddc_bus)
DRM_ERROR("LVDS: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
}
- drm_connector_attach_property(&radeon_connector->base,
+ drm_object_attach_property(&radeon_connector->base.base,
dev->mode_config.scaling_mode_property,
DRM_MODE_SCALE_FULLSCREEN);
subpixel_order = SubPixelHorizontalRGB;
@@ -2034,7 +2045,7 @@ radeon_add_legacy_connector(struct drm_device *dev,
} else
connector->polled = DRM_CONNECTOR_POLL_HPD;
connector->display_info.subpixel_order = subpixel_order;
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
drm_sysfs_connector_add(connector);
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
}
diff --git a/sys/dev/drm2/radeon/radeon_cp.c b/sys/dev/drm2/radeon/radeon_cp.c
index 4ec2773..e53c6d0 100644
--- a/sys/dev/drm2/radeon/radeon_cp.c
+++ b/sys/dev/drm2/radeon/radeon_cp.c
@@ -53,6 +53,16 @@ __FBSDID("$FreeBSD$");
#define FIRMWARE_RS600 "radeonkmsfw_RS600_cp"
#define FIRMWARE_R520 "radeonkmsfw_R520_cp"
+#ifdef __linux__
+MODULE_FIRMWARE(FIRMWARE_R100);
+MODULE_FIRMWARE(FIRMWARE_R200);
+MODULE_FIRMWARE(FIRMWARE_R300);
+MODULE_FIRMWARE(FIRMWARE_R420);
+MODULE_FIRMWARE(FIRMWARE_RS690);
+MODULE_FIRMWARE(FIRMWARE_RS600);
+MODULE_FIRMWARE(FIRMWARE_R520);
+#endif
+
static int radeon_do_cleanup_cp(struct drm_device * dev);
static void radeon_do_cp_start(drm_radeon_private_t * dev_priv);
@@ -834,7 +844,7 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev,
RADEON_WRITE(RADEON_LAST_CLEAR_REG, 0);
/* reset sarea copies of these */
- master_priv = file_priv->masterp->driver_priv;
+ master_priv = file_priv->master->driver_priv;
if (master_priv->sarea_priv) {
master_priv->sarea_priv->last_frame = 0;
master_priv->sarea_priv->last_dispatch = 0;
@@ -1163,7 +1173,7 @@ static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
struct drm_file *file_priv)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
- struct drm_radeon_master_private *master_priv = file_priv->masterp->driver_priv;
+ struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
DRM_DEBUG("\n");
@@ -1655,7 +1665,6 @@ int radeon_cp_init(struct drm_device *dev, void *data, struct drm_file *file_pri
return radeon_do_init_cp(dev, init, file_priv);
case RADEON_INIT_R600_CP:
return r600_do_init_cp(dev, init, file_priv);
- break;
case RADEON_CLEANUP_CP:
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
return r600_do_cleanup_cp(dev);
@@ -2066,7 +2075,7 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags)
int ret = 0;
dev_priv = malloc(sizeof(drm_radeon_private_t),
- DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (dev_priv == NULL)
return -ENOMEM;
@@ -2093,11 +2102,11 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags)
break;
}
- pci_enable_busmaster(dev->device);
+ pci_enable_busmaster(dev->dev);
- if (drm_device_is_agp(dev))
+ if (drm_pci_device_is_agp(dev))
dev_priv->flags |= RADEON_IS_AGP;
- else if (drm_device_is_pcie(dev))
+ else if (drm_pci_device_is_pcie(dev))
dev_priv->flags |= RADEON_IS_PCIE;
else
dev_priv->flags |= RADEON_IS_PCI;
@@ -2126,7 +2135,7 @@ int radeon_master_create(struct drm_device *dev, struct drm_master *master)
int ret;
master_priv = malloc(sizeof(*master_priv),
- DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (!master_priv)
return -ENOMEM;
@@ -2160,11 +2169,7 @@ void radeon_master_destroy(struct drm_device *dev, struct drm_master *master)
master_priv->sarea_priv = NULL;
if (master_priv->sarea)
-#ifdef __linux__
drm_rmmap_locked(dev, master_priv->sarea);
-#else
- drm_rmmap(dev, master_priv->sarea);
-#endif
free(master_priv, DRM_MEM_DRIVER);
diff --git a/sys/dev/drm2/radeon/radeon_cs.c b/sys/dev/drm2/radeon/radeon_cs.c
index ee299fa..7adde83 100644
--- a/sys/dev/drm2/radeon/radeon_cs.c
+++ b/sys/dev/drm2/radeon/radeon_cs.c
@@ -51,12 +51,12 @@ static int radeon_cs_parser_relocs(struct radeon_cs_parser *p)
/* FIXME: we assume that each relocs use 4 dwords */
p->nrelocs = chunk->length_dw / 4;
p->relocs_ptr = malloc(p->nrelocs * sizeof(void *),
- DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (p->relocs_ptr == NULL) {
return -ENOMEM;
}
p->relocs = malloc(p->nrelocs * sizeof(struct radeon_cs_reloc),
- DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (p->relocs == NULL) {
return -ENOMEM;
}
@@ -182,7 +182,7 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
p->chunk_flags_idx = -1;
p->chunk_const_ib_idx = -1;
p->chunks_array = malloc(cs->num_chunks * sizeof(uint64_t),
- DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (p->chunks_array == NULL) {
return -ENOMEM;
}
@@ -194,7 +194,7 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
p->cs_flags = 0;
p->nchunks = cs->num_chunks;
p->chunks = malloc(p->nchunks * sizeof(struct radeon_cs_chunk),
- DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (p->chunks == NULL) {
return -ENOMEM;
}
@@ -241,7 +241,7 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
if ((p->chunks[i].chunk_id == RADEON_CHUNK_ID_RELOCS) ||
(p->chunks[i].chunk_id == RADEON_CHUNK_ID_FLAGS)) {
size = p->chunks[i].length_dw * sizeof(uint32_t);
- p->chunks[i].kdata = malloc(size, DRM_MEM_DRIVER, M_WAITOK);
+ p->chunks[i].kdata = malloc(size, DRM_MEM_DRIVER, M_NOWAIT);
if (p->chunks[i].kdata == NULL) {
return -ENOMEM;
}
@@ -288,8 +288,8 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
return -EINVAL;
}
if (p->rdev && (p->rdev->flags & RADEON_IS_AGP)) {
- p->chunks[p->chunk_ib_idx].kpage[0] = malloc(PAGE_SIZE, DRM_MEM_DRIVER, M_WAITOK);
- p->chunks[p->chunk_ib_idx].kpage[1] = malloc(PAGE_SIZE, DRM_MEM_DRIVER, M_WAITOK);
+ p->chunks[p->chunk_ib_idx].kpage[0] = malloc(PAGE_SIZE, DRM_MEM_DRIVER, M_NOWAIT);
+ p->chunks[p->chunk_ib_idx].kpage[1] = malloc(PAGE_SIZE, DRM_MEM_DRIVER, M_NOWAIT);
if (p->chunks[p->chunk_ib_idx].kpage[0] == NULL ||
p->chunks[p->chunk_ib_idx].kpage[1] == NULL) {
free(p->chunks[p->chunk_ib_idx].kpage[0], DRM_MEM_DRIVER);
diff --git a/sys/dev/drm2/radeon/radeon_device.c b/sys/dev/drm2/radeon/radeon_device.c
index 370e541..e5c676b 100644
--- a/sys/dev/drm2/radeon/radeon_device.c
+++ b/sys/dev/drm2/radeon/radeon_device.c
@@ -248,7 +248,7 @@ void radeon_wb_fini(struct radeon_device *rdev)
int radeon_wb_init(struct radeon_device *rdev)
{
int r;
- void *wb_ptr;
+ void *wb_ptr; /* FreeBSD: to please GCC 4.2. */
if (rdev->wb.wb_obj == NULL) {
r = radeon_bo_create(rdev, RADEON_GPU_PAGE_SIZE, PAGE_SIZE, true,
@@ -430,11 +430,11 @@ bool radeon_card_posted(struct radeon_device *rdev)
{
uint32_t reg;
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
if (efi_enabled(EFI_BOOT) &&
rdev->dev->pci_subvendor == PCI_VENDOR_ID_APPLE)
return false;
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
/* first check CRTCs */
if (ASIC_IS_DCE41(rdev)) {
@@ -548,7 +548,7 @@ int radeon_dummy_page_init(struct radeon_device *rdev)
if (rdev->dummy_page.dmah)
return 0;
rdev->dummy_page.dmah = drm_pci_alloc(rdev->ddev,
- PAGE_SIZE, PAGE_SIZE, BUS_SPACE_MAXSIZE_32BIT);
+ PAGE_SIZE, PAGE_SIZE, BUS_SPACE_MAXADDR_32BIT);
if (rdev->dummy_page.dmah == NULL)
return -ENOMEM;
rdev->dummy_page.addr = rdev->dummy_page.dmah->busaddr;
@@ -731,7 +731,7 @@ int radeon_atombios_init(struct radeon_device *rdev)
{
struct card_info *atom_card_info =
malloc(sizeof(struct card_info),
- DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (!atom_card_info)
return -ENOMEM;
@@ -814,7 +814,7 @@ void radeon_combios_fini(struct radeon_device *rdev)
{
}
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
/* if we get transitioned to only one device, take VGA back */
/**
* radeon_vga_set_decode - enable/disable vga decode
@@ -835,7 +835,7 @@ static unsigned int radeon_vga_set_decode(void *cookie, bool state)
else
return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
}
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
/**
* radeon_check_pot_argument - check that argument is a power of two
@@ -903,7 +903,7 @@ static void radeon_check_arguments(struct radeon_device *rdev)
*
* @pdev: pci dev pointer
*/
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
static bool radeon_switcheroo_quirk_long_wakeup(struct pci_dev *pdev)
{
@@ -916,7 +916,7 @@ static bool radeon_switcheroo_quirk_long_wakeup(struct pci_dev *pdev)
return false;
}
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
/**
* radeon_switcheroo_set_state - set switcheroo state
@@ -927,7 +927,7 @@ static bool radeon_switcheroo_quirk_long_wakeup(struct pci_dev *pdev)
* Callback for the switcheroo driver. Suspends or resumes the
* the asics before or after it is powered up using ACPI methods.
*/
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state)
{
struct drm_device *dev = pci_get_drvdata(pdev);
@@ -956,7 +956,7 @@ static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switchero
dev->switch_power_state = DRM_SWITCH_POWER_OFF;
}
}
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
/**
* radeon_switcheroo_can_switch - see if switcheroo state can change
@@ -967,7 +967,7 @@ static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switchero
* state can be changed.
* Returns true if the state can be changed, false if not.
*/
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
static bool radeon_switcheroo_can_switch(struct pci_dev *pdev)
{
struct drm_device *dev = pci_get_drvdata(pdev);
@@ -984,7 +984,7 @@ static const struct vga_switcheroo_client_ops radeon_switcheroo_ops = {
.reprobe = NULL,
.can_switch = radeon_switcheroo_can_switch,
};
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
/**
* radeon_device_init - initialize the driver
@@ -1005,7 +1005,7 @@ int radeon_device_init(struct radeon_device *rdev,
int dma_bits;
rdev->shutdown = false;
- rdev->dev = ddev->device;
+ rdev->dev = ddev->dev;
rdev->ddev = ddev;
rdev->flags = flags;
rdev->family = flags & RADEON_FAMILY_MASK;
@@ -1079,7 +1079,7 @@ int radeon_device_init(struct radeon_device *rdev,
rdev->need_dma32 = true;
dma_bits = rdev->need_dma32 ? 32 : 40;
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
r = pci_set_dma_mask(rdev->pdev, DMA_BIT_MASK(dma_bits));
if (r) {
rdev->need_dma32 = true;
@@ -1091,7 +1091,7 @@ int radeon_device_init(struct radeon_device *rdev,
pci_set_consistent_dma_mask(rdev->pdev, DMA_BIT_MASK(32));
printk(KERN_WARNING "radeon: No coherent DMA available.\n");
}
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
/* Registers mapping */
/* TODO: block userspace mapping of io register */
@@ -1127,13 +1127,13 @@ int radeon_device_init(struct radeon_device *rdev,
taskqueue_thread_enqueue, &rdev->tq);
taskqueue_start_threads(&rdev->tq, 1, PWAIT, "radeon taskq");
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
/* if we have > 1 VGA cards, then disable the radeon VGA resources */
/* this will fail for cards that aren't VGA class devices, just
* ignore it */
vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode);
vga_switcheroo_register_client(rdev->pdev, &radeon_switcheroo_ops);
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
r = radeon_init(rdev);
if (r)
@@ -1200,9 +1200,9 @@ int radeon_device_init(struct radeon_device *rdev,
return 0;
}
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
static void radeon_debugfs_remove_files(struct radeon_device *rdev);
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
/**
* radeon_device_fini - tear down the driver
@@ -1233,10 +1233,10 @@ void radeon_device_fini(struct radeon_device *rdev)
#endif
radeon_fini(rdev);
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
vga_switcheroo_unregister_client(rdev->pdev);
vga_client_register(rdev->pdev, NULL, NULL, NULL);
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
if (rdev->tq != NULL) {
taskqueue_free(rdev->tq);
@@ -1250,9 +1250,9 @@ void radeon_device_fini(struct radeon_device *rdev)
bus_release_resource(rdev->dev, SYS_RES_MEMORY, rdev->rmmio_rid,
rdev->rmmio);
rdev->rmmio = NULL;
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
radeon_debugfs_remove_files(rdev);
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
}
@@ -1280,11 +1280,11 @@ int radeon_suspend_kms(struct drm_device *dev)
if (dev == NULL || dev->dev_private == NULL) {
return -ENODEV;
}
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
if (state.event == PM_EVENT_PRETHAW) {
return 0;
}
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
rdev = dev->dev_private;
if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
@@ -1342,21 +1342,21 @@ int radeon_suspend_kms(struct drm_device *dev)
radeon_agp_suspend(rdev);
- pci_save_state(device_get_parent(rdev->dev));
-#ifdef DUMBBELL_WIP
+ pci_save_state(device_get_parent(dev->dev));
+#ifdef FREEBSD_WIP
if (state.event == PM_EVENT_SUSPEND) {
/* Shut down the device */
pci_disable_device(dev->pdev);
-#endif /* DUMBBELL_WIP */
- pci_set_powerstate(dev->device, PCI_POWERSTATE_D3);
-#ifdef DUMBBELL_WIP
+#endif /* FREEBSD_WIP */
+ pci_set_powerstate(dev->dev, PCI_POWERSTATE_D3);
+#ifdef FREEBSD_WIP
}
console_lock();
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
radeon_fbdev_set_suspend(rdev, 1);
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
console_unlock();
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
return 0;
}
@@ -1378,17 +1378,17 @@ int radeon_resume_kms(struct drm_device *dev)
if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
return 0;
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
console_lock();
-#endif /* DUMBBELL_WIP */
- pci_set_powerstate(dev->device, PCI_POWERSTATE_D0);
- pci_restore_state(device_get_parent(rdev->dev));
-#ifdef DUMBBELL_WIP
+#endif /* FREEBSD_WIP */
+ pci_set_powerstate(device_get_parent(dev->dev), PCI_POWERSTATE_D0);
+ pci_restore_state(device_get_parent(dev->dev));
+#ifdef FREEBSD_WIP
if (pci_enable_device(dev->pdev)) {
console_unlock();
return -1;
}
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
/* resume AGP if in use */
radeon_agp_resume(rdev);
radeon_resume(rdev);
@@ -1401,9 +1401,9 @@ int radeon_resume_kms(struct drm_device *dev)
radeon_restore_bios_scratch_regs(rdev);
radeon_fbdev_set_suspend(rdev, 0);
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
console_unlock();
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
/* init dig PHYs, disp eng pll */
if (rdev->is_atom_bios) {
@@ -1513,7 +1513,7 @@ retry:
/*
* Debugfs
*/
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
int radeon_debugfs_add_files(struct radeon_device *rdev,
struct drm_info_list *files,
unsigned nfiles)
@@ -1573,5 +1573,5 @@ int radeon_debugfs_init(struct drm_minor *minor)
void radeon_debugfs_cleanup(struct drm_minor *minor)
{
}
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
#endif
diff --git a/sys/dev/drm2/radeon/radeon_display.c b/sys/dev/drm2/radeon/radeon_display.c
index ee74ed4..1f9b917 100644
--- a/sys/dev/drm2/radeon/radeon_display.c
+++ b/sys/dev/drm2/radeon/radeon_display.c
@@ -363,7 +363,7 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
u64 base;
int r;
- work = malloc(sizeof *work, DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
+ work = malloc(sizeof *work, DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (work == NULL)
return -ENOMEM;
@@ -511,7 +511,7 @@ static void radeon_crtc_init(struct drm_device *dev, int index)
struct radeon_crtc *radeon_crtc;
int i;
- radeon_crtc = malloc(sizeof(struct radeon_crtc) + (RADEONFB_CONN_LIMIT * sizeof(struct drm_connector *)), DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
+ radeon_crtc = malloc(sizeof(struct radeon_crtc) + (RADEONFB_CONN_LIMIT * sizeof(struct drm_connector *)), DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (radeon_crtc == NULL)
return;
@@ -1112,12 +1112,12 @@ radeon_user_framebuffer_create(struct drm_device *dev,
obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]);
if (obj == NULL) {
- dev_err(dev->device, "No GEM object associated to handle 0x%08X, "
+ dev_err(dev->dev, "No GEM object associated to handle 0x%08X, "
"can't create framebuffer\n", mode_cmd->handles[0]);
return -ENOENT;
}
- radeon_fb = malloc(sizeof(*radeon_fb), DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
+ radeon_fb = malloc(sizeof(*radeon_fb), DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (radeon_fb == NULL) {
drm_gem_object_unreference_unlocked(obj);
return (-ENOMEM);
@@ -1179,7 +1179,7 @@ static int radeon_modeset_create_props(struct radeon_device *rdev)
}
if (!ASIC_IS_AVIVO(rdev)) {
- sz = DRM_ARRAY_SIZE(radeon_tmds_pll_enum_list);
+ sz = ARRAY_SIZE(radeon_tmds_pll_enum_list);
rdev->mode_info.tmds_pll_property =
drm_property_create_enum(rdev->ddev, 0,
"tmds_pll",
@@ -1193,13 +1193,13 @@ static int radeon_modeset_create_props(struct radeon_device *rdev)
drm_mode_create_scaling_mode_property(rdev->ddev);
- sz = DRM_ARRAY_SIZE(radeon_tv_std_enum_list);
+ sz = ARRAY_SIZE(radeon_tv_std_enum_list);
rdev->mode_info.tv_std_property =
drm_property_create_enum(rdev->ddev, 0,
"tv standard",
radeon_tv_std_enum_list, sz);
- sz = DRM_ARRAY_SIZE(radeon_underscan_enum_list);
+ sz = ARRAY_SIZE(radeon_underscan_enum_list);
rdev->mode_info.underscan_property =
drm_property_create_enum(rdev->ddev, 0,
"underscan",
@@ -1256,38 +1256,38 @@ static void radeon_afmt_init(struct radeon_device *rdev)
/* DCE4/5 has 6 audio blocks tied to DIG encoders */
/* DCE4.1 has 2 audio blocks tied to DIG encoders */
rdev->mode_info.afmt[0] = malloc(sizeof(struct radeon_afmt),
- DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (rdev->mode_info.afmt[0]) {
rdev->mode_info.afmt[0]->offset = EVERGREEN_CRTC0_REGISTER_OFFSET;
rdev->mode_info.afmt[0]->id = 0;
}
rdev->mode_info.afmt[1] = malloc(sizeof(struct radeon_afmt),
- DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (rdev->mode_info.afmt[1]) {
rdev->mode_info.afmt[1]->offset = EVERGREEN_CRTC1_REGISTER_OFFSET;
rdev->mode_info.afmt[1]->id = 1;
}
if (!ASIC_IS_DCE41(rdev)) {
rdev->mode_info.afmt[2] = malloc(sizeof(struct radeon_afmt),
- DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (rdev->mode_info.afmt[2]) {
rdev->mode_info.afmt[2]->offset = EVERGREEN_CRTC2_REGISTER_OFFSET;
rdev->mode_info.afmt[2]->id = 2;
}
rdev->mode_info.afmt[3] = malloc(sizeof(struct radeon_afmt),
- DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (rdev->mode_info.afmt[3]) {
rdev->mode_info.afmt[3]->offset = EVERGREEN_CRTC3_REGISTER_OFFSET;
rdev->mode_info.afmt[3]->id = 3;
}
rdev->mode_info.afmt[4] = malloc(sizeof(struct radeon_afmt),
- DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (rdev->mode_info.afmt[4]) {
rdev->mode_info.afmt[4]->offset = EVERGREEN_CRTC4_REGISTER_OFFSET;
rdev->mode_info.afmt[4]->id = 4;
}
rdev->mode_info.afmt[5] = malloc(sizeof(struct radeon_afmt),
- DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (rdev->mode_info.afmt[5]) {
rdev->mode_info.afmt[5]->offset = EVERGREEN_CRTC5_REGISTER_OFFSET;
rdev->mode_info.afmt[5]->id = 5;
@@ -1296,13 +1296,13 @@ static void radeon_afmt_init(struct radeon_device *rdev)
} else if (ASIC_IS_DCE3(rdev)) {
/* DCE3.x has 2 audio blocks tied to DIG encoders */
rdev->mode_info.afmt[0] = malloc(sizeof(struct radeon_afmt),
- DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (rdev->mode_info.afmt[0]) {
rdev->mode_info.afmt[0]->offset = DCE3_HDMI_OFFSET0;
rdev->mode_info.afmt[0]->id = 0;
}
rdev->mode_info.afmt[1] = malloc(sizeof(struct radeon_afmt),
- DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (rdev->mode_info.afmt[1]) {
rdev->mode_info.afmt[1]->offset = DCE3_HDMI_OFFSET1;
rdev->mode_info.afmt[1]->id = 1;
@@ -1310,7 +1310,7 @@ static void radeon_afmt_init(struct radeon_device *rdev)
} else if (ASIC_IS_DCE2(rdev)) {
/* DCE2 has at least 1 routable audio block */
rdev->mode_info.afmt[0] = malloc(sizeof(struct radeon_afmt),
- DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (rdev->mode_info.afmt[0]) {
rdev->mode_info.afmt[0]->offset = DCE2_HDMI_OFFSET0;
rdev->mode_info.afmt[0]->id = 0;
@@ -1318,7 +1318,7 @@ static void radeon_afmt_init(struct radeon_device *rdev)
/* r6xx has 2 routable audio blocks */
if (rdev->family >= CHIP_R600) {
rdev->mode_info.afmt[1] = malloc(sizeof(struct radeon_afmt),
- DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (rdev->mode_info.afmt[1]) {
rdev->mode_info.afmt[1]->offset = DCE2_HDMI_OFFSET1;
rdev->mode_info.afmt[1]->id = 1;
@@ -1419,9 +1419,7 @@ void radeon_modeset_fini(struct radeon_device *rdev)
radeon_afmt_fini(rdev);
drm_kms_helper_poll_fini(rdev->ddev);
radeon_hpd_fini(rdev);
- DRM_UNLOCK(rdev->ddev); /* Work around lock recursion. dumbbell@ */
drm_mode_config_cleanup(rdev->ddev);
- DRM_LOCK(rdev->ddev);
rdev->mode_info.mode_config_initialized = false;
}
/* free i2c buses */
diff --git a/sys/dev/drm2/radeon/radeon_drm.h b/sys/dev/drm2/radeon/radeon_drm.h
index e84500c..a339753 100644
--- a/sys/dev/drm2/radeon/radeon_drm.h
+++ b/sys/dev/drm2/radeon/radeon_drm.h
@@ -760,7 +760,7 @@ typedef struct drm_radeon_irq_wait {
typedef struct drm_radeon_setparam {
unsigned int param;
- int64_t value;
+ __s64 value;
} drm_radeon_setparam_t;
#define RADEON_SETPARAM_FB_LOCATION 1 /* determined framebuffer location */
diff --git a/sys/dev/drm2/radeon/radeon_drv.c b/sys/dev/drm2/radeon/radeon_drv.c
index 37b4e26..7c433c6 100644
--- a/sys/dev/drm2/radeon/radeon_drv.c
+++ b/sys/dev/drm2/radeon/radeon_drv.c
@@ -85,13 +85,9 @@ extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc,
int *vpos, int *hpos);
extern struct drm_ioctl_desc radeon_ioctls_kms[];
extern int radeon_max_kms_ioctl;
-#ifdef COMPAT_FREEBSD32
-extern struct drm_ioctl_desc radeon_compat_ioctls[];
-extern int radeon_num_compat_ioctls;
-#endif
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
int radeon_mmap(struct file *filp, struct vm_area_struct *vma);
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
int radeon_mode_dumb_mmap(struct drm_file *filp,
struct drm_device *dev,
uint32_t handle, uint64_t *offset_p);
@@ -131,7 +127,6 @@ int radeon_pcie_gen2 = -1;
int radeon_msi = -1;
int radeon_lockup_timeout = 10000;
-#ifdef DUMBBELL_WIP
MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers");
module_param_named(no_wb, radeon_no_wb, int, 0444);
@@ -183,165 +178,11 @@ module_param_named(msi, radeon_msi, int, 0444);
MODULE_PARM_DESC(lockup_timeout, "GPU lockup timeout in ms (defaul 10000 = 10 seconds, 0 = disable)");
module_param_named(lockup_timeout, radeon_lockup_timeout, int, 0444);
-static int radeon_suspend(struct drm_device *dev, pm_message_t state)
-{
- drm_radeon_private_t *dev_priv = dev->dev_private;
-
- if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
- return 0;
-
- /* Disable *all* interrupts */
- if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600)
- RADEON_WRITE(R500_DxMODE_INT_MASK, 0);
- RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
- return 0;
-}
-
-static int radeon_resume(struct drm_device *dev)
-{
- drm_radeon_private_t *dev_priv = dev->dev_private;
-
- if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
- return 0;
-
- /* Restore interrupt registers */
- if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600)
- RADEON_WRITE(R500_DxMODE_INT_MASK, dev_priv->r500_disp_irq_reg);
- RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
- return 0;
-}
-#endif /* DUMBBELL_WIP */
-
static drm_pci_id_list_t pciidlist[] = {
radeon_PCI_IDS
};
-#ifdef DUMBBELL_WIP
-static const struct file_operations radeon_driver_old_fops = {
- .owner = THIS_MODULE,
- .open = drm_open,
- .release = drm_release,
- .unlocked_ioctl = drm_ioctl,
- .mmap = drm_mmap,
- .poll = drm_poll,
- .fasync = drm_fasync,
- .read = drm_read,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = radeon_compat_ioctl,
-#endif
- .llseek = noop_llseek,
-};
-
-static struct drm_driver driver_old = {
- .driver_features =
- DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
- DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED,
- .dev_priv_size = sizeof(drm_radeon_buf_priv_t),
- .load = radeon_driver_load,
- .firstopen = radeon_driver_firstopen,
- .open = radeon_driver_open,
- .preclose = radeon_driver_preclose,
- .postclose = radeon_driver_postclose,
- .lastclose = radeon_driver_lastclose,
- .unload = radeon_driver_unload,
-#ifdef DUMBBELL_WIP
- .suspend = radeon_suspend,
- .resume = radeon_resume,
-#endif /* DUMBBELL_WIP */
- .get_vblank_counter = radeon_get_vblank_counter,
- .enable_vblank = radeon_enable_vblank,
- .disable_vblank = radeon_disable_vblank,
- .master_create = radeon_master_create,
- .master_destroy = radeon_master_destroy,
- .irq_preinstall = radeon_driver_irq_preinstall,
- .irq_postinstall = radeon_driver_irq_postinstall,
- .irq_uninstall = radeon_driver_irq_uninstall,
- .irq_handler = radeon_driver_irq_handler,
- .ioctls = radeon_ioctls,
- .dma_ioctl = radeon_cp_buffers,
- .fops = &radeon_driver_old_fops,
- .name = DRIVER_NAME,
- .desc = DRIVER_DESC,
- .date = DRIVER_DATE,
- .major = DRIVER_MAJOR,
- .minor = DRIVER_MINOR,
- .patchlevel = DRIVER_PATCHLEVEL,
-};
-#endif /* DUMBBELL_WIP */
-
-static struct drm_driver_info kms_driver;
-
-#ifdef DUMBBELL_WIP
-static int radeon_kick_out_firmware_fb(struct pci_dev *pdev)
-{
- struct apertures_struct *ap;
- bool primary = false;
-
- ap = alloc_apertures(1);
- if (!ap)
- return -ENOMEM;
-
- ap->ranges[0].base = pci_resource_start(pdev, 0);
- ap->ranges[0].size = pci_resource_len(pdev, 0);
-
-#ifdef CONFIG_X86
- primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
-#endif
- remove_conflicting_framebuffers(ap, "radeondrmfb", primary);
- kfree(ap);
-
- return 0;
-}
-
-static int radeon_pci_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
-{
- int ret;
-
- /* Get rid of things like offb */
- ret = radeon_kick_out_firmware_fb(pdev);
- if (ret)
- return ret;
-
- return drm_get_pci_dev(pdev, ent, &kms_driver);
-}
-
-static void
-radeon_pci_remove(struct pci_dev *pdev)
-{
- struct drm_device *dev = pci_get_drvdata(pdev);
-
- drm_put_dev(dev);
-}
-
-static int
-radeon_pci_suspend(struct pci_dev *pdev, pm_message_t state)
-{
- struct drm_device *dev = pci_get_drvdata(pdev);
- return radeon_suspend_kms(dev, state);
-}
-
-static int
-radeon_pci_resume(struct pci_dev *pdev)
-{
- struct drm_device *dev = pci_get_drvdata(pdev);
- return radeon_resume_kms(dev);
-}
-
-static const struct file_operations radeon_driver_kms_fops = {
- .owner = THIS_MODULE,
- .open = drm_open,
- .release = drm_release,
- .unlocked_ioctl = drm_ioctl,
- .mmap = radeon_mmap,
- .poll = drm_poll,
- .fasync = drm_fasync,
- .read = drm_read,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = radeon_kms_compat_ioctl,
-#endif
-};
-#endif /* DUMBBELL_WIP */
+static struct drm_driver kms_driver;
static int radeon_sysctl_init(struct drm_device *dev, struct sysctl_ctx_list *ctx,
struct sysctl_oid *top)
@@ -349,31 +190,34 @@ static int radeon_sysctl_init(struct drm_device *dev, struct sysctl_ctx_list *ct
return drm_add_busid_modesetting(dev, ctx, top);
}
-static struct drm_driver_info kms_driver = {
+static struct drm_driver kms_driver = {
.driver_features =
DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED | DRIVER_GEM |
- DRIVER_PRIME /* | DRIVE_MODESET */,
-#ifdef DUMBBELL_WIP
+ DRIVER_PRIME,
+#ifdef FREEBSD_WIP
.dev_priv_size = 0,
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
.load = radeon_driver_load_kms,
- .use_msi = radeon_msi_ok,
.firstopen = radeon_driver_firstopen_kms,
.open = radeon_driver_open_kms,
.preclose = radeon_driver_preclose_kms,
.postclose = radeon_driver_postclose_kms,
.lastclose = radeon_driver_lastclose_kms,
.unload = radeon_driver_unload_kms,
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
.suspend = radeon_suspend_kms,
.resume = radeon_resume_kms,
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
.get_vblank_counter = radeon_get_vblank_counter_kms,
.enable_vblank = radeon_enable_vblank_kms,
.disable_vblank = radeon_disable_vblank_kms,
.get_vblank_timestamp = radeon_get_vblank_timestamp_kms,
.get_scanout_position = radeon_get_crtc_scanoutpos,
+#if defined(CONFIG_DEBUG_FS)
+ .debugfs_init = radeon_debugfs_init,
+ .debugfs_cleanup = radeon_debugfs_cleanup,
+#endif
.irq_preinstall = radeon_driver_irq_preinstall_kms,
.irq_postinstall = radeon_driver_irq_postinstall_kms,
.irq_uninstall = radeon_driver_irq_uninstall_kms,
@@ -388,16 +232,16 @@ static struct drm_driver_info kms_driver = {
.dumb_create = radeon_mode_dumb_create,
.dumb_map_offset = radeon_mode_dumb_mmap,
.dumb_destroy = radeon_mode_dumb_destroy,
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
.fops = &radeon_driver_kms_fops,
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
.gem_prime_export = radeon_gem_prime_export,
.gem_prime_import = radeon_gem_prime_import,
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
.name = DRIVER_NAME,
.desc = DRIVER_DESC,
@@ -407,7 +251,7 @@ static struct drm_driver_info kms_driver = {
.patchlevel = KMS_DRIVER_PATCHLEVEL,
};
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
static int __init radeon_init(void)
{
driver = &driver_old;
@@ -450,7 +294,7 @@ static void __exit radeon_exit(void)
drm_pci_exit(driver, pdriver);
radeon_unregister_atpx_handler();
}
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
/* =================================================================== */
@@ -458,26 +302,23 @@ static int
radeon_probe(device_t kdev)
{
- return drm_probe(kdev, pciidlist);
+ return (-drm_probe_helper(kdev, pciidlist));
}
static int
radeon_attach(device_t kdev)
{
- struct drm_device *dev;
- dev = device_get_softc(kdev);
if (radeon_modeset == 1) {
kms_driver.driver_features |= DRIVER_MODESET;
- kms_driver.max_ioctl = radeon_max_kms_ioctl;
+ kms_driver.num_ioctls = radeon_max_kms_ioctl;
#ifdef COMPAT_FREEBSD32
kms_driver.compat_ioctls = radeon_compat_ioctls;
- kms_driver.compat_ioctls_nr = &radeon_num_compat_ioctls;
+ kms_driver.num_compat_ioctls = &radeon_num_compat_ioctls;
#endif
radeon_register_atpx_handler();
}
- dev->driver = &kms_driver;
- return (drm_attach(kdev, pciidlist));
+ return (-drm_attach_helper(kdev, pciidlist, &kms_driver));
}
static int
@@ -488,8 +329,12 @@ radeon_suspend(device_t kdev)
dev = device_get_softc(kdev);
ret = radeon_suspend_kms(dev);
+ if (ret)
+ return (-ret);
- return (-ret);
+ ret = bus_generic_suspend(kdev);
+
+ return (ret);
}
static int
@@ -500,8 +345,12 @@ radeon_resume(device_t kdev)
dev = device_get_softc(kdev);
ret = radeon_resume_kms(dev);
+ if (ret)
+ return (-ret);
+
+ ret = bus_generic_resume(kdev);
- return (-ret);
+ return (ret);
}
extern struct fb_info * radeon_fb_helper_getinfo(device_t kdev);
@@ -512,7 +361,7 @@ static device_method_t radeon_methods[] = {
DEVMETHOD(device_attach, radeon_attach),
DEVMETHOD(device_suspend, radeon_suspend),
DEVMETHOD(device_resume, radeon_resume),
- DEVMETHOD(device_detach, drm_detach),
+ DEVMETHOD(device_detach, drm_generic_detach),
/* Framebuffer service methods */
DEVMETHOD(fb_getinfo, radeon_fb_helper_getinfo),
diff --git a/sys/dev/drm2/radeon/radeon_drv.h b/sys/dev/drm2/radeon/radeon_drv.h
index 99c6aa4..af05bbf 100644
--- a/sys/dev/drm2/radeon/radeon_drv.h
+++ b/sys/dev/drm2/radeon/radeon_drv.h
@@ -328,6 +328,10 @@ typedef struct drm_radeon_kcmd_buffer {
extern int radeon_no_wb;
extern struct drm_ioctl_desc radeon_ioctls[];
extern int radeon_max_ioctl;
+#ifdef COMPAT_FREEBSD32
+extern struct drm_ioctl_desc radeon_compat_ioctls[];
+extern int radeon_num_compat_ioctls;
+#endif
extern u32 radeon_get_ring_head(drm_radeon_private_t *dev_priv);
extern void radeon_set_ring_head(drm_radeon_private_t *dev_priv, u32 val);
@@ -463,8 +467,13 @@ extern void r600_blit_swap(struct drm_device *dev,
int w, int h, int src_pitch, int dst_pitch, int cpp);
/* atpx handler */
+#if defined(CONFIG_VGA_SWITCHEROO)
void radeon_register_atpx_handler(void);
void radeon_unregister_atpx_handler(void);
+#else
+static inline void radeon_register_atpx_handler(void) {}
+static inline void radeon_unregister_atpx_handler(void) {}
+#endif
/* Flags for stats.boxes
*/
@@ -2004,7 +2013,7 @@ do { \
#define VB_AGE_TEST_WITH_RETURN( dev_priv ) \
do { \
- struct drm_radeon_master_private *master_priv = file_priv->masterp->driver_priv;\
+ struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv; \
drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv; \
if ( sarea_priv->last_dispatch >= RADEON_MAX_VB_AGE ) { \
int __ret; \
diff --git a/sys/dev/drm2/radeon/radeon_fb.c b/sys/dev/drm2/radeon/radeon_fb.c
index d4b24a3..d4bd7b2 100644
--- a/sys/dev/drm2/radeon/radeon_fb.c
+++ b/sys/dev/drm2/radeon/radeon_fb.c
@@ -219,7 +219,12 @@ static int radeonfb_create(struct radeon_fbdev *rfbdev,
rbo = gem_to_radeon_bo(gobj);
- info = malloc(sizeof(*info), DRM_MEM_KMS, M_WAITOK | M_ZERO);
+ /* okay we have an object now allocate the framebuffer */
+ info = framebuffer_alloc();
+ if (info == NULL) {
+ ret = -ENOMEM;
+ goto out_unref;
+ }
ret = radeon_framebuffer_init(rdev->ddev, &rfbdev->rfb, &mode_cmd, gobj);
if (ret) {
@@ -235,14 +240,16 @@ static int radeonfb_create(struct radeon_fbdev *rfbdev,
memset(rbo->kptr, 0x0, radeon_bo_size(rbo));
+ drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
+
tmp = radeon_bo_gpu_offset(rbo) - rdev->mc.vram_start;
info->fb_size = radeon_bo_size(rbo);
info->fb_bpp = sizes->surface_bpp;
- info->fb_width = sizes->surface_width;
- info->fb_height = sizes->surface_height;
info->fb_pbase = rdev->mc.aper_base + tmp;
info->fb_vbase = (vm_offset_t)rbo->kptr;
+ drm_fb_helper_fill_var(info, &rfbdev->helper, sizes->fb_width, sizes->fb_height);
+
DRM_INFO("fb mappable at 0x%" PRIXPTR "\n", info->fb_pbase);
DRM_INFO("vram apper at 0x%lX\n", (unsigned long)rdev->mc.aper_base);
DRM_INFO("size %lu\n", (unsigned long)radeon_bo_size(rbo));
@@ -291,14 +298,11 @@ static int radeon_fbdev_destroy(struct drm_device *dev, struct radeon_fbdev *rfb
if (rfbdev->helper.fbdev) {
info = rfbdev->helper.fbdev;
- free(info->fb_priv, DRM_MEM_KMS);
- free(info, DRM_MEM_KMS);
+ framebuffer_release(info);
}
if (rfb->obj) {
- DRM_UNLOCK(dev); /* Work around lock recursion. dumbbell@ */
radeonfb_destroy_pinned_object(rfb->obj);
- DRM_LOCK(dev);
rfb->obj = NULL;
}
drm_fb_helper_fini(&rfbdev->helper);
@@ -324,7 +328,7 @@ int radeon_fbdev_init(struct radeon_device *rdev)
bpp_sel = 8;
rfbdev = malloc(sizeof(struct radeon_fbdev),
- DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (!rfbdev)
return -ENOMEM;
@@ -357,9 +361,9 @@ void radeon_fbdev_fini(struct radeon_device *rdev)
void radeon_fbdev_set_suspend(struct radeon_device *rdev, int state)
{
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
fb_set_suspend(rdev->mode_info.rfbdev->helper.fbdev, state);
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
}
int radeon_fbdev_total_size(struct radeon_device *rdev)
diff --git a/sys/dev/drm2/radeon/radeon_fence.c b/sys/dev/drm2/radeon/radeon_fence.c
index 3b43a8c..21c3541 100644
--- a/sys/dev/drm2/radeon/radeon_fence.c
+++ b/sys/dev/drm2/radeon/radeon_fence.c
@@ -35,9 +35,9 @@ __FBSDID("$FreeBSD$");
#include <dev/drm2/drmP.h>
#include "radeon_reg.h"
#include "radeon.h"
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
#include "radeon_trace.h"
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
/*
* Fences
@@ -106,7 +106,7 @@ int radeon_fence_emit(struct radeon_device *rdev,
int ring)
{
/* we are protected by the ring emission mutex */
- *fence = malloc(sizeof(struct radeon_fence), DRM_MEM_DRIVER, M_WAITOK);
+ *fence = malloc(sizeof(struct radeon_fence), DRM_MEM_DRIVER, M_NOWAIT);
if ((*fence) == NULL) {
return -ENOMEM;
}
@@ -155,7 +155,7 @@ void radeon_fence_process(struct radeon_device *rdev, int ring)
* have temporarly set the last_seq not to the true real last
* seq but to an older one.
*/
- last_seq = atomic_load_acq_64(&rdev->fence_drv[ring].last_seq);
+ last_seq = atomic64_read(&rdev->fence_drv[ring].last_seq);
do {
last_emitted = rdev->fence_drv[ring].sync_seq[ring];
seq = radeon_fence_read(rdev, ring);
@@ -220,12 +220,12 @@ static void radeon_fence_destroy(struct radeon_fence *fence)
static bool radeon_fence_seq_signaled(struct radeon_device *rdev,
u64 seq, unsigned ring)
{
- if (atomic_load_acq_64(&rdev->fence_drv[ring].last_seq) >= seq) {
+ if (atomic64_read(&rdev->fence_drv[ring].last_seq) >= seq) {
return true;
}
/* poll new last sequence at least once */
radeon_fence_process(rdev, ring);
- if (atomic_load_acq_64(&rdev->fence_drv[ring].last_seq) >= seq) {
+ if (atomic64_read(&rdev->fence_drv[ring].last_seq) >= seq) {
return true;
}
return false;
@@ -281,7 +281,7 @@ static int radeon_fence_wait_seq(struct radeon_device *rdev, u64 target_seq,
bool signaled, fence_queue_locked;
int r;
- while (target_seq > atomic_load_acq_64(&rdev->fence_drv[ring].last_seq)) {
+ while (target_seq > atomic64_read(&rdev->fence_drv[ring].last_seq)) {
if (!rdev->ring[ring].ready) {
return -EBUSY;
}
@@ -296,7 +296,7 @@ static int radeon_fence_wait_seq(struct radeon_device *rdev, u64 target_seq,
*/
timeout = 1;
}
- seq = atomic_load_acq_64(&rdev->fence_drv[ring].last_seq);
+ seq = atomic64_read(&rdev->fence_drv[ring].last_seq);
/* Save current last activity valuee, used to check for GPU lockups */
last_activity = rdev->fence_drv[ring].last_activity;
@@ -352,7 +352,7 @@ static int radeon_fence_wait_seq(struct radeon_device *rdev, u64 target_seq,
#endif
/* check if sequence value has changed since last_activity */
- if (seq != atomic_load_acq_64(&rdev->fence_drv[ring].last_seq)) {
+ if (seq != atomic64_read(&rdev->fence_drv[ring].last_seq)) {
continue;
}
@@ -641,7 +641,7 @@ int radeon_fence_wait_next_locked(struct radeon_device *rdev, int ring)
{
uint64_t seq;
- seq = atomic_load_acq_64(&rdev->fence_drv[ring].last_seq) + 1ULL;
+ seq = atomic64_read(&rdev->fence_drv[ring].last_seq) + 1ULL;
if (seq >= rdev->fence_drv[ring].sync_seq[ring]) {
/* nothing to wait for, last_seq is
already the last emited fence */
@@ -728,7 +728,7 @@ unsigned radeon_fence_count_emitted(struct radeon_device *rdev, int ring)
*/
radeon_fence_process(rdev, ring);
emitted = rdev->fence_drv[ring].sync_seq[ring]
- - atomic_load_acq_64(&rdev->fence_drv[ring].last_seq);
+ - atomic64_read(&rdev->fence_drv[ring].last_seq);
/* to avoid 32bits warp around */
if (emitted > 0x10000000) {
emitted = 0x10000000;
@@ -834,7 +834,7 @@ int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring)
}
rdev->fence_drv[ring].cpu_addr = &rdev->wb.wb[index/4];
rdev->fence_drv[ring].gpu_addr = rdev->wb.gpu_addr + index;
- radeon_fence_write(rdev, atomic_load_acq_64(&rdev->fence_drv[ring].last_seq), ring);
+ radeon_fence_write(rdev, atomic64_read(&rdev->fence_drv[ring].last_seq), ring);
rdev->fence_drv[ring].initialized = true;
dev_info(rdev->dev, "fence driver on ring %d use gpu addr 0x%016jx and cpu addr 0x%p\n",
ring, (uintmax_t)rdev->fence_drv[ring].gpu_addr, rdev->fence_drv[ring].cpu_addr);
@@ -860,7 +860,7 @@ static void radeon_fence_driver_init_ring(struct radeon_device *rdev, int ring)
rdev->fence_drv[ring].gpu_addr = 0;
for (i = 0; i < RADEON_NUM_RINGS; ++i)
rdev->fence_drv[ring].sync_seq[i] = 0;
- atomic_store_rel_64(&rdev->fence_drv[ring].last_seq, 0);
+ atomic64_set(&rdev->fence_drv[ring].last_seq, 0);
rdev->fence_drv[ring].last_activity = jiffies;
rdev->fence_drv[ring].initialized = false;
}
@@ -959,7 +959,7 @@ static int radeon_debugfs_fence_info(struct seq_file *m, void *data)
seq_printf(m, "--- ring %d ---\n", i);
seq_printf(m, "Last signaled fence 0x%016llx\n",
- (unsigned long long)atomic_load_acq_64(&rdev->fence_drv[i].last_seq));
+ (unsigned long long)atomic64_read(&rdev->fence_drv[i].last_seq));
seq_printf(m, "Last emitted 0x%016llx\n",
rdev->fence_drv[i].sync_seq[i]);
diff --git a/sys/dev/drm2/radeon/radeon_gart.c b/sys/dev/drm2/radeon/radeon_gart.c
index 36b4452..3dae6ae 100644
--- a/sys/dev/drm2/radeon/radeon_gart.c
+++ b/sys/dev/drm2/radeon/radeon_gart.c
@@ -72,13 +72,13 @@ int radeon_gart_table_ram_alloc(struct radeon_device *rdev)
drm_dma_handle_t *dmah;
dmah = drm_pci_alloc(rdev->ddev, rdev->gart.table_size,
- PAGE_SIZE, 0xFFFFFFFFUL);
+ PAGE_SIZE, BUS_SPACE_MAXADDR);
if (dmah == NULL) {
return -ENOMEM;
}
rdev->gart.dmah = dmah;
rdev->gart.ptr = dmah->vaddr;
-#if defined(__i386) || defined(__amd64)
+#ifdef CONFIG_X86
if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480 ||
rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) {
pmap_change_attr((vm_offset_t)rdev->gart.ptr,
@@ -104,7 +104,7 @@ void radeon_gart_table_ram_free(struct radeon_device *rdev)
if (rdev->gart.ptr == NULL) {
return;
}
-#if defined(__i386) || defined(__amd64)
+#ifdef CONFIG_X86
if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480 ||
rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) {
pmap_change_attr((vm_offset_t)rdev->gart.ptr,
@@ -361,14 +361,14 @@ int radeon_gart_init(struct radeon_device *rdev)
rdev->gart.num_cpu_pages, rdev->gart.num_gpu_pages);
/* Allocate pages table */
rdev->gart.pages = malloc(sizeof(void *) * rdev->gart.num_cpu_pages,
- DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (rdev->gart.pages == NULL) {
radeon_gart_fini(rdev);
return -ENOMEM;
}
rdev->gart.pages_addr = malloc(sizeof(dma_addr_t) *
rdev->gart.num_cpu_pages,
- DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (rdev->gart.pages_addr == NULL) {
radeon_gart_fini(rdev);
return -ENOMEM;
@@ -648,7 +648,7 @@ retry:
memset(pd_addr, 0, pd_size);
pts_size = radeon_vm_num_pdes(rdev) * sizeof(struct radeon_sa_bo *);
- vm->page_tables = malloc(pts_size, DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
+ vm->page_tables = malloc(pts_size, DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (vm->page_tables == NULL) {
DRM_ERROR("Cannot allocate memory for page table array\n");
@@ -797,7 +797,7 @@ struct radeon_bo_va *radeon_vm_bo_add(struct radeon_device *rdev,
struct radeon_bo_va *bo_va;
bo_va = malloc(sizeof(struct radeon_bo_va),
- DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (bo_va == NULL) {
return NULL;
}
@@ -916,7 +916,12 @@ uint64_t radeon_vm_map_gart(struct radeon_device *rdev, uint64_t addr)
result = rdev->gart.pages_addr[addr >> PAGE_SHIFT];
/* in case cpu page size != gpu page size*/
- result |= addr & (~PAGE_MASK);
+ /*
+ * FreeBSD port note: FreeBSD's PAGE_MASK is the inverse of
+ * Linux's one. That's why the test below doesn't inverse the
+ * constant.
+ */
+ result |= addr & (PAGE_MASK);
return result;
}
diff --git a/sys/dev/drm2/radeon/radeon_gem.c b/sys/dev/drm2/radeon/radeon_gem.c
index e8975bd..2a55101 100644
--- a/sys/dev/drm2/radeon/radeon_gem.c
+++ b/sys/dev/drm2/radeon/radeon_gem.c
@@ -46,10 +46,10 @@ void radeon_gem_object_free(struct drm_gem_object *gobj)
struct radeon_bo *robj = gem_to_radeon_bo(gobj);
if (robj) {
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
if (robj->gem_base.import_attach)
drm_prime_gem_destroy(&robj->gem_base, robj->tbo.sg);
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
radeon_bo_unref(&robj);
}
}
@@ -80,7 +80,7 @@ int radeon_gem_object_create(struct radeon_device *rdev, int size,
retry:
r = radeon_bo_create(rdev, size, alignment, kernel, initial_domain, NULL, &robj);
if (r) {
- if (r != -ERESTART) {
+ if (r != -ERESTARTSYS) {
if (initial_domain == RADEON_GEM_DOMAIN_VRAM) {
initial_domain |= RADEON_GEM_DOMAIN_GTT;
goto retry;
@@ -268,11 +268,12 @@ int radeon_gem_create_ioctl(struct drm_device *dev, void *data,
args->initial_domain, false,
false, &gobj);
if (r) {
+ if (r == -ERESTARTSYS)
+ r = -EINTR;
sx_sunlock(&rdev->exclusive_lock);
r = radeon_gem_handle_lockup(rdev, r);
return r;
}
- handle = 0;
r = drm_gem_handle_create(filp, gobj, &handle);
/* drop reference from allocate - handle holds it now */
drm_gem_object_unreference_unlocked(gobj);
@@ -394,6 +395,8 @@ int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data,
if (rdev->asic->ioctl_wait_idle)
robj->rdev->asic->ioctl_wait_idle(rdev, robj);
drm_gem_object_unreference_unlocked(gobj);
+ if (r == -ERESTARTSYS)
+ r = -EINTR;
r = radeon_gem_handle_lockup(rdev, r);
return r;
}
@@ -467,7 +470,7 @@ int radeon_gem_va_ioctl(struct drm_device *dev, void *data,
}
if (args->offset < RADEON_VA_RESERVED_SIZE) {
- dev_err(dev->device,
+ dev_err(dev->dev,
"offset 0x%lX is in reserved area 0x%X\n",
(unsigned long)args->offset,
RADEON_VA_RESERVED_SIZE);
@@ -481,13 +484,13 @@ int radeon_gem_va_ioctl(struct drm_device *dev, void *data,
*/
invalid_flags = RADEON_VM_PAGE_VALID | RADEON_VM_PAGE_SYSTEM;
if ((args->flags & invalid_flags)) {
- dev_err(dev->device, "invalid flags 0x%08X vs 0x%08X\n",
+ dev_err(dev->dev, "invalid flags 0x%08X vs 0x%08X\n",
args->flags, invalid_flags);
args->operation = RADEON_VA_RESULT_ERROR;
return -EINVAL;
}
if (!(args->flags & RADEON_VM_PAGE_SNOOPED)) {
- dev_err(dev->device, "only supported snooped mapping for now\n");
+ dev_err(dev->dev, "only supported snooped mapping for now\n");
args->operation = RADEON_VA_RESULT_ERROR;
return -EINVAL;
}
@@ -497,7 +500,7 @@ int radeon_gem_va_ioctl(struct drm_device *dev, void *data,
case RADEON_VA_UNMAP:
break;
default:
- dev_err(dev->device, "unsupported operation %d\n",
+ dev_err(dev->dev, "unsupported operation %d\n",
args->operation);
args->operation = RADEON_VA_RESULT_ERROR;
return -EINVAL;
@@ -567,7 +570,6 @@ int radeon_mode_dumb_create(struct drm_file *file_priv,
if (r)
return -ENOMEM;
- handle = 0;
r = drm_gem_handle_create(file_priv, gobj, &handle);
/* drop reference from allocate - handle holds it now */
drm_gem_object_unreference_unlocked(gobj);
diff --git a/sys/dev/drm2/radeon/radeon_i2c.c b/sys/dev/drm2/radeon/radeon_i2c.c
index 917286a..8a8a904 100644
--- a/sys/dev/drm2/radeon/radeon_i2c.c
+++ b/sys/dev/drm2/radeon/radeon_i2c.c
@@ -449,7 +449,7 @@ static int r100_hw_i2c_xfer(struct radeon_i2c_chan *i2c,
break;
default:
DRM_ERROR("gpio not supported with hw i2c\n");
- ret = EINVAL;
+ ret = -EINVAL;
goto done;
}
break;
@@ -464,7 +464,7 @@ static int r100_hw_i2c_xfer(struct radeon_i2c_chan *i2c,
break;
default:
DRM_ERROR("gpio not supported with hw i2c\n");
- ret = EINVAL;
+ ret = -EINVAL;
goto done;
}
break;
@@ -483,7 +483,7 @@ static int r100_hw_i2c_xfer(struct radeon_i2c_chan *i2c,
break;
default:
DRM_ERROR("gpio not supported with hw i2c\n");
- ret = EINVAL;
+ ret = -EINVAL;
goto done;
}
break;
@@ -499,7 +499,7 @@ static int r100_hw_i2c_xfer(struct radeon_i2c_chan *i2c,
break;
default:
DRM_ERROR("gpio not supported with hw i2c\n");
- ret = EINVAL;
+ ret = -EINVAL;
goto done;
}
break;
@@ -523,13 +523,13 @@ static int r100_hw_i2c_xfer(struct radeon_i2c_chan *i2c,
break;
default:
DRM_ERROR("gpio not supported with hw i2c\n");
- ret = EINVAL;
+ ret = -EINVAL;
goto done;
}
break;
default:
DRM_ERROR("unsupported asic\n");
- ret = EINVAL;
+ ret = -EINVAL;
goto done;
break;
}
@@ -550,7 +550,7 @@ static int r100_hw_i2c_xfer(struct radeon_i2c_chan *i2c,
(48 << RADEON_I2C_TIME_LIMIT_SHIFT)));
WREG32(i2c_cntl_0, reg);
for (k = 0; k < 32; k++) {
- DRM_UDELAY(10);
+ udelay(10);
tmp = RREG32(i2c_cntl_0);
if (tmp & RADEON_I2C_GO)
continue;
@@ -560,7 +560,7 @@ static int r100_hw_i2c_xfer(struct radeon_i2c_chan *i2c,
else {
DRM_DEBUG("i2c write error 0x%08x\n", tmp);
WREG32(i2c_cntl_0, tmp | RADEON_I2C_ABORT);
- ret = EIO;
+ ret = -EIO;
goto done;
}
}
@@ -582,7 +582,7 @@ static int r100_hw_i2c_xfer(struct radeon_i2c_chan *i2c,
(48 << RADEON_I2C_TIME_LIMIT_SHIFT)));
WREG32(i2c_cntl_0, reg | RADEON_I2C_RECEIVE);
for (k = 0; k < 32; k++) {
- DRM_UDELAY(10);
+ udelay(10);
tmp = RREG32(i2c_cntl_0);
if (tmp & RADEON_I2C_GO)
continue;
@@ -592,7 +592,7 @@ static int r100_hw_i2c_xfer(struct radeon_i2c_chan *i2c,
else {
DRM_DEBUG("i2c read error 0x%08x\n", tmp);
WREG32(i2c_cntl_0, tmp | RADEON_I2C_ABORT);
- ret = EIO;
+ ret = -EIO;
goto done;
}
}
@@ -610,7 +610,7 @@ static int r100_hw_i2c_xfer(struct radeon_i2c_chan *i2c,
(48 << RADEON_I2C_TIME_LIMIT_SHIFT)));
WREG32(i2c_cntl_0, reg);
for (k = 0; k < 32; k++) {
- DRM_UDELAY(10);
+ udelay(10);
tmp = RREG32(i2c_cntl_0);
if (tmp & RADEON_I2C_GO)
continue;
@@ -620,7 +620,7 @@ static int r100_hw_i2c_xfer(struct radeon_i2c_chan *i2c,
else {
DRM_DEBUG("i2c write error 0x%08x\n", tmp);
WREG32(i2c_cntl_0, tmp | RADEON_I2C_ABORT);
- ret = EIO;
+ ret = -EIO;
goto done;
}
}
@@ -710,13 +710,13 @@ static int r500_hw_i2c_xfer(struct radeon_i2c_chan *i2c,
WREG32(AVIVO_DC_I2C_ARBITRATION, AVIVO_DC_I2C_SW_WANTS_TO_USE_I2C);
for (i = 0; i < 50; i++) {
- DRM_UDELAY(1);
+ udelay(1);
if (RREG32(AVIVO_DC_I2C_ARBITRATION) & AVIVO_DC_I2C_SW_CAN_USE_I2C)
break;
}
if (i == 50) {
DRM_ERROR("failed to get i2c bus\n");
- ret = EBUSY;
+ ret = -EBUSY;
goto done;
}
@@ -733,7 +733,7 @@ static int r500_hw_i2c_xfer(struct radeon_i2c_chan *i2c,
break;
default:
DRM_ERROR("gpio not supported with hw i2c\n");
- ret = EINVAL;
+ ret = -EINVAL;
goto done;
}
@@ -744,7 +744,7 @@ static int r500_hw_i2c_xfer(struct radeon_i2c_chan *i2c,
AVIVO_DC_I2C_NACK |
AVIVO_DC_I2C_HALT));
WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_SOFT_RESET);
- DRM_UDELAY(1);
+ udelay(1);
WREG32(AVIVO_DC_I2C_RESET, 0);
WREG32(AVIVO_DC_I2C_DATA, (p->slave << 1) & 0xff);
@@ -757,7 +757,7 @@ static int r500_hw_i2c_xfer(struct radeon_i2c_chan *i2c,
WREG32(AVIVO_DC_I2C_CONTROL1, reg);
WREG32(AVIVO_DC_I2C_STATUS1, AVIVO_DC_I2C_GO);
for (j = 0; j < 200; j++) {
- DRM_UDELAY(50);
+ udelay(50);
tmp = RREG32(AVIVO_DC_I2C_STATUS1);
if (tmp & AVIVO_DC_I2C_GO)
continue;
@@ -767,7 +767,7 @@ static int r500_hw_i2c_xfer(struct radeon_i2c_chan *i2c,
else {
DRM_DEBUG("i2c write error 0x%08x\n", tmp);
WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_ABORT);
- ret = EIO;
+ ret = -EIO;
goto done;
}
}
@@ -788,7 +788,7 @@ static int r500_hw_i2c_xfer(struct radeon_i2c_chan *i2c,
AVIVO_DC_I2C_NACK |
AVIVO_DC_I2C_HALT));
WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_SOFT_RESET);
- DRM_UDELAY(1);
+ udelay(1);
WREG32(AVIVO_DC_I2C_RESET, 0);
WREG32(AVIVO_DC_I2C_DATA, ((p->slave << 1) & 0xff) | 0x1);
@@ -799,7 +799,7 @@ static int r500_hw_i2c_xfer(struct radeon_i2c_chan *i2c,
WREG32(AVIVO_DC_I2C_CONTROL1, reg | AVIVO_DC_I2C_RECEIVE);
WREG32(AVIVO_DC_I2C_STATUS1, AVIVO_DC_I2C_GO);
for (j = 0; j < 200; j++) {
- DRM_UDELAY(50);
+ udelay(50);
tmp = RREG32(AVIVO_DC_I2C_STATUS1);
if (tmp & AVIVO_DC_I2C_GO)
continue;
@@ -809,7 +809,7 @@ static int r500_hw_i2c_xfer(struct radeon_i2c_chan *i2c,
else {
DRM_DEBUG("i2c read error 0x%08x\n", tmp);
WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_ABORT);
- ret = EIO;
+ ret = -EIO;
goto done;
}
}
@@ -828,7 +828,7 @@ static int r500_hw_i2c_xfer(struct radeon_i2c_chan *i2c,
AVIVO_DC_I2C_NACK |
AVIVO_DC_I2C_HALT));
WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_SOFT_RESET);
- DRM_UDELAY(1);
+ udelay(1);
WREG32(AVIVO_DC_I2C_RESET, 0);
WREG32(AVIVO_DC_I2C_DATA, (p->slave << 1) & 0xff);
@@ -842,7 +842,7 @@ static int r500_hw_i2c_xfer(struct radeon_i2c_chan *i2c,
WREG32(AVIVO_DC_I2C_CONTROL1, reg);
WREG32(AVIVO_DC_I2C_STATUS1, AVIVO_DC_I2C_GO);
for (j = 0; j < 200; j++) {
- DRM_UDELAY(50);
+ udelay(50);
tmp = RREG32(AVIVO_DC_I2C_STATUS1);
if (tmp & AVIVO_DC_I2C_GO)
continue;
@@ -852,7 +852,7 @@ static int r500_hw_i2c_xfer(struct radeon_i2c_chan *i2c,
else {
DRM_DEBUG("i2c write error 0x%08x\n", tmp);
WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_ABORT);
- ret = EIO;
+ ret = -EIO;
goto done;
}
}
@@ -867,7 +867,7 @@ done:
AVIVO_DC_I2C_NACK |
AVIVO_DC_I2C_HALT));
WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_SOFT_RESET);
- DRM_UDELAY(1);
+ udelay(1);
WREG32(AVIVO_DC_I2C_RESET, 0);
WREG32(AVIVO_DC_I2C_ARBITRATION, AVIVO_DC_I2C_SW_DONE_USING_I2C);
@@ -953,11 +953,11 @@ static int radeon_hw_i2c_xfer(device_t dev,
break;
default:
DRM_ERROR("i2c: unhandled radeon chip\n");
- ret = EIO;
+ ret = -EIO;
break;
}
- return ret;
+ return -ret;
}
static int
@@ -1043,7 +1043,7 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
return NULL;
i2c = malloc(sizeof(struct radeon_i2c_chan),
- DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (i2c == NULL)
return NULL;
@@ -1063,7 +1063,7 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
/* set the radeon hw i2c adapter */
snprintf(i2c->name, sizeof(i2c->name),
"Radeon i2c hw bus %s", name);
- iicbus_dev = device_add_child(dev->device, "radeon_hw_i2c", -1);
+ iicbus_dev = device_add_child(dev->dev, "radeon_hw_i2c", -1);
if (iicbus_dev == NULL) {
DRM_ERROR("Failed to create bridge for hw i2c %s\n",
name);
@@ -1076,14 +1076,14 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
if (ret != 0) {
DRM_ERROR("Attach failed for bridge for hw i2c %s\n",
name);
- device_delete_child(dev->device, iicbus_dev);
+ device_delete_child(dev->dev, iicbus_dev);
goto out_free;
}
i2c->adapter = device_find_child(iicbus_dev, "iicbus", -1);
if (i2c->adapter == NULL) {
DRM_ERROR("hw i2c bridge doesn't have iicbus child\n");
- device_delete_child(dev->device, iicbus_dev);
+ device_delete_child(dev->dev, iicbus_dev);
goto out_free;
}
} else if (rec->hw_capable &&
@@ -1092,7 +1092,7 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
/* hw i2c using atom */
snprintf(i2c->name, sizeof(i2c->name),
"Radeon i2c hw bus %s", name);
- iicbus_dev = device_add_child(dev->device, "radeon_atom_hw_i2c", -1);
+ iicbus_dev = device_add_child(dev->dev, "radeon_atom_hw_i2c", -1);
if (iicbus_dev == NULL) {
DRM_ERROR("Failed to create bridge for hw i2c %s\n",
name);
@@ -1105,14 +1105,14 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
if (ret != 0) {
DRM_ERROR("Attach failed for bridge for hw i2c %s\n",
name);
- device_delete_child(dev->device, iicbus_dev);
+ device_delete_child(dev->dev, iicbus_dev);
goto out_free;
}
i2c->adapter = device_find_child(iicbus_dev, "iicbus", -1);
if (i2c->adapter == NULL) {
DRM_ERROR("hw i2c bridge doesn't have iicbus child\n");
- device_delete_child(dev->device, iicbus_dev);
+ device_delete_child(dev->dev, iicbus_dev);
goto out_free;
}
} else {
@@ -1121,7 +1121,7 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
/* set the radeon bit adapter */
snprintf(i2c->name, sizeof(i2c->name),
"Radeon i2c bit bus %s", name);
- iicbus_dev = device_add_child(dev->device, "radeon_iicbb", -1);
+ iicbus_dev = device_add_child(dev->dev, "radeon_iicbb", -1);
if (iicbus_dev == NULL) {
DRM_ERROR("Failed to create bridge for bb i2c %s\n",
name);
@@ -1134,14 +1134,14 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
if (ret != 0) {
DRM_ERROR("Attach failed for bridge for bb i2c %s\n",
name);
- device_delete_child(dev->device, iicbus_dev);
+ device_delete_child(dev->dev, iicbus_dev);
goto out_free;
}
iicbb_dev = device_find_child(iicbus_dev, "iicbb", -1);
if (iicbb_dev == NULL) {
DRM_ERROR("bb i2c bridge doesn't have iicbb child\n");
- device_delete_child(dev->device, iicbus_dev);
+ device_delete_child(dev->dev, iicbus_dev);
goto out_free;
}
@@ -1149,7 +1149,7 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
if (i2c->adapter == NULL) {
DRM_ERROR(
"bbbus bridge doesn't have iicbus grandchild\n");
- device_delete_child(dev->device, iicbus_dev);
+ device_delete_child(dev->dev, iicbus_dev);
goto out_free;
}
}
@@ -1174,7 +1174,7 @@ struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev,
int ret;
i2c = malloc(sizeof(struct radeon_i2c_chan),
- DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (i2c == NULL)
return NULL;
@@ -1182,7 +1182,7 @@ struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev,
i2c->dev = dev;
snprintf(i2c->name, sizeof(i2c->name),
"Radeon aux bus %s", name);
- ret = iic_dp_aux_add_bus(dev->device, i2c->name,
+ ret = iic_dp_aux_add_bus(dev->dev, i2c->name,
radeon_dp_i2c_aux_ch, i2c, &i2c->iic_bus,
&i2c->adapter);
if (ret) {
@@ -1205,7 +1205,7 @@ void radeon_i2c_destroy(struct radeon_i2c_chan *i2c)
int ret;
mtx_lock(&Giant);
- ret = device_delete_child(i2c->dev->device, i2c->iic_bus);
+ ret = device_delete_child(i2c->dev->dev, i2c->iic_bus);
mtx_unlock(&Giant);
KASSERT(ret == 0, ("unable to detach iic bus %s: %d",
i2c->name, ret));
diff --git a/sys/dev/drm2/radeon/radeon_ioc32.c b/sys/dev/drm2/radeon/radeon_ioc32.c
index ee691be..89ec8d7 100644
--- a/sys/dev/drm2/radeon/radeon_ioc32.c
+++ b/sys/dev/drm2/radeon/radeon_ioc32.c
@@ -291,6 +291,7 @@ static int compat_radeon_irq_emit(struct drm_device *dev, void *arg,
}
/* The two 64-bit arches where alignof(u64)==4 in 32-bit code */
+#if defined (CONFIG_X86_64) || defined(CONFIG_IA64)
typedef struct drm_radeon_setparam32 {
int param;
u64 value;
@@ -309,6 +310,9 @@ static int compat_radeon_cp_setparam(struct drm_device *dev, void *arg,
return radeon_ioctls[DRM_IOCTL_RADEON_SETPARAM].func(dev, &request, file_priv);
}
+#else
+#define compat_radeon_cp_setparam NULL
+#endif /* X86_64 || IA64 */
struct drm_ioctl_desc radeon_compat_ioctls[] = {
DRM_IOCTL_DEF(DRM_RADEON_CP_INIT, compat_radeon_cp_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
@@ -322,6 +326,6 @@ struct drm_ioctl_desc radeon_compat_ioctls[] = {
DRM_IOCTL_DEF(DRM_RADEON_ALLOC, compat_radeon_mem_alloc, DRM_AUTH),
DRM_IOCTL_DEF(DRM_RADEON_IRQ_EMIT, compat_radeon_irq_emit, DRM_AUTH)
};
-int radeon_num_compat_ioctls = DRM_ARRAY_SIZE(radeon_compat_ioctls);
+int radeon_num_compat_ioctls = ARRAY_SIZE(radeon_compat_ioctls);
#endif
diff --git a/sys/dev/drm2/radeon/radeon_irq_kms.c b/sys/dev/drm2/radeon/radeon_irq_kms.c
index a679ed1..280322f 100644
--- a/sys/dev/drm2/radeon/radeon_irq_kms.c
+++ b/sys/dev/drm2/radeon/radeon_irq_kms.c
@@ -171,18 +171,14 @@ void radeon_driver_irq_uninstall_kms(struct drm_device *dev)
* Returns true if MSIs should be enabled, false if MSIs
* should not be enabled.
*/
-int radeon_msi_ok(struct drm_device *dev, unsigned long flags)
+static bool radeon_msi_ok(struct radeon_device *rdev)
{
- int family;
-
- family = flags & RADEON_FAMILY_MASK;
-
/* RV370/RV380 was first asic with MSI support */
- if (family < CHIP_RV380)
+ if (rdev->family < CHIP_RV380)
return false;
/* MSIs don't work on AGP */
- if (drm_device_is_agp(dev))
+ if (rdev->flags & RADEON_IS_AGP)
return false;
/* force MSI on */
@@ -193,42 +189,42 @@ int radeon_msi_ok(struct drm_device *dev, unsigned long flags)
/* Quirks */
/* HP RS690 only seems to work with MSIs. */
- if ((dev->pci_device == 0x791f) &&
- (dev->pci_subvendor == 0x103c) &&
- (dev->pci_subdevice == 0x30c2))
+ if ((rdev->ddev->pci_device == 0x791f) &&
+ (rdev->ddev->pci_subvendor == 0x103c) &&
+ (rdev->ddev->pci_subdevice == 0x30c2))
return true;
/* Dell RS690 only seems to work with MSIs. */
- if ((dev->pci_device == 0x791f) &&
- (dev->pci_subvendor == 0x1028) &&
- (dev->pci_subdevice == 0x01fc))
+ if ((rdev->ddev->pci_device == 0x791f) &&
+ (rdev->ddev->pci_subvendor == 0x1028) &&
+ (rdev->ddev->pci_subdevice == 0x01fc))
return true;
/* Dell RS690 only seems to work with MSIs. */
- if ((dev->pci_device == 0x791f) &&
- (dev->pci_subvendor == 0x1028) &&
- (dev->pci_subdevice == 0x01fd))
+ if ((rdev->ddev->pci_device == 0x791f) &&
+ (rdev->ddev->pci_subvendor == 0x1028) &&
+ (rdev->ddev->pci_subdevice == 0x01fd))
return true;
/* Gateway RS690 only seems to work with MSIs. */
- if ((dev->pci_device == 0x791f) &&
- (dev->pci_subvendor == 0x107b) &&
- (dev->pci_subdevice == 0x0185))
+ if ((rdev->ddev->pci_device == 0x791f) &&
+ (rdev->ddev->pci_subvendor == 0x107b) &&
+ (rdev->ddev->pci_subdevice == 0x0185))
return true;
/* try and enable MSIs by default on all RS690s */
- if (family == CHIP_RS690)
+ if (rdev->family == CHIP_RS690)
return true;
/* RV515 seems to have MSI issues where it loses
* MSI rearms occasionally. This leads to lockups and freezes.
* disable it by default.
*/
- if (family == CHIP_RV515)
+ if (rdev->family == CHIP_RV515)
return false;
- if (flags & RADEON_IS_IGP) {
+ if (rdev->flags & RADEON_IS_IGP) {
/* APUs work fine with MSIs */
- if (family >= CHIP_PALM)
+ if (rdev->family >= CHIP_PALM)
return true;
/* lots of IGPs have problems with MSIs */
return false;
@@ -258,12 +254,17 @@ int radeon_irq_kms_init(struct radeon_device *rdev)
return r;
}
/* enable msi */
- rdev->msi_enabled = rdev->ddev->msi_enabled;
-
+ rdev->msi_enabled = 0;
+
+ if (radeon_msi_ok(rdev)) {
+ int ret = drm_pci_enable_msi(rdev->ddev);
+ if (!ret) {
+ rdev->msi_enabled = 1;
+ dev_info(rdev->dev, "radeon: using MSI.\n");
+ }
+ }
rdev->irq.installed = true;
- DRM_UNLOCK(rdev->ddev);
r = drm_irq_install(rdev->ddev);
- DRM_LOCK(rdev->ddev);
if (r) {
rdev->irq.installed = false;
return r;
@@ -285,6 +286,8 @@ void radeon_irq_kms_fini(struct radeon_device *rdev)
if (rdev->irq.installed) {
drm_irq_uninstall(rdev->ddev);
rdev->irq.installed = false;
+ if (rdev->msi_enabled)
+ drm_pci_disable_msi(rdev->ddev);
}
taskqueue_drain(rdev->tq, &rdev->hotplug_work);
}
@@ -401,6 +404,9 @@ void radeon_irq_kms_enable_afmt(struct radeon_device *rdev, int block)
{
unsigned long irqflags;
+ if (!rdev->ddev->irq_enabled)
+ return;
+
DRM_SPINLOCK_IRQSAVE(&rdev->irq.lock, irqflags);
rdev->irq.afmt[block] = true;
radeon_irq_set(rdev);
@@ -420,6 +426,9 @@ void radeon_irq_kms_disable_afmt(struct radeon_device *rdev, int block)
{
unsigned long irqflags;
+ if (!rdev->ddev->irq_enabled)
+ return;
+
DRM_SPINLOCK_IRQSAVE(&rdev->irq.lock, irqflags);
rdev->irq.afmt[block] = false;
radeon_irq_set(rdev);
@@ -439,6 +448,9 @@ void radeon_irq_kms_enable_hpd(struct radeon_device *rdev, unsigned hpd_mask)
unsigned long irqflags;
int i;
+ if (!rdev->ddev->irq_enabled)
+ return;
+
DRM_SPINLOCK_IRQSAVE(&rdev->irq.lock, irqflags);
for (i = 0; i < RADEON_MAX_HPD_PINS; ++i)
rdev->irq.hpd[i] |= !!(hpd_mask & (1 << i));
@@ -459,6 +471,9 @@ void radeon_irq_kms_disable_hpd(struct radeon_device *rdev, unsigned hpd_mask)
unsigned long irqflags;
int i;
+ if (!rdev->ddev->irq_enabled)
+ return;
+
DRM_SPINLOCK_IRQSAVE(&rdev->irq.lock, irqflags);
for (i = 0; i < RADEON_MAX_HPD_PINS; ++i)
rdev->irq.hpd[i] &= !(hpd_mask & (1 << i));
diff --git a/sys/dev/drm2/radeon/radeon_irq_kms.h b/sys/dev/drm2/radeon/radeon_irq_kms.h
index 6bfb988..431bdaa 100644
--- a/sys/dev/drm2/radeon/radeon_irq_kms.h
+++ b/sys/dev/drm2/radeon/radeon_irq_kms.h
@@ -10,6 +10,4 @@ void radeon_driver_irq_preinstall_kms(struct drm_device *dev);
int radeon_driver_irq_postinstall_kms(struct drm_device *dev);
void radeon_driver_irq_uninstall_kms(struct drm_device *dev);
-int radeon_msi_ok(struct drm_device *dev, unsigned long flags);
-
#endif /* !defined(__RADEON_IRQ_KMS_H__) */
diff --git a/sys/dev/drm2/radeon/radeon_kms.c b/sys/dev/drm2/radeon/radeon_kms.c
index 8507d01..29e19df 100644
--- a/sys/dev/drm2/radeon/radeon_kms.c
+++ b/sys/dev/drm2/radeon/radeon_kms.c
@@ -52,9 +52,13 @@ int radeon_driver_unload_kms(struct drm_device *dev)
if (rdev == NULL)
return 0;
+ if (rdev->rmmio == NULL)
+ goto done_free;
radeon_acpi_fini(rdev);
radeon_modeset_fini(rdev);
radeon_device_fini(rdev);
+
+done_free:
free(rdev, DRM_MEM_DRIVER);
dev->dev_private = NULL;
return 0;
@@ -78,17 +82,17 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags)
struct radeon_device *rdev;
int r, acpi_status;
- rdev = malloc(sizeof(struct radeon_device), DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
+ rdev = malloc(sizeof(struct radeon_device), DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (rdev == NULL) {
return -ENOMEM;
}
dev->dev_private = (void *)rdev;
/* update BUS flag */
- if (drm_device_is_agp(dev)) {
+ if (drm_pci_device_is_agp(dev)) {
DRM_INFO("RADEON_IS_AGP\n");
flags |= RADEON_IS_AGP;
- } else if (drm_device_is_pcie(dev)) {
+ } else if (drm_pci_device_is_pcie(dev)) {
DRM_INFO("RADEON_IS_PCIE\n");
flags |= RADEON_IS_PCIE;
} else {
@@ -104,7 +108,7 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags)
*/
r = radeon_device_init(rdev, dev, flags);
if (r) {
- dev_err(dev->device, "Fatal error during GPU init\n");
+ dev_err(dev->dev, "Fatal error during GPU init\n");
goto out;
}
@@ -114,7 +118,7 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags)
*/
r = radeon_modeset_init(rdev);
if (r)
- dev_err(dev->device, "Fatal error during modeset init\n");
+ dev_err(dev->dev, "Fatal error during modeset init\n");
/* Call ACPI methods: require modeset init
* but failure is not fatal
@@ -122,7 +126,7 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags)
if (!r) {
acpi_status = radeon_acpi_init(rdev);
if (acpi_status)
- dev_dbg(dev->device,
+ dev_dbg(dev->dev,
"Error during ACPI methods call\n");
}
@@ -419,9 +423,9 @@ int radeon_driver_firstopen_kms(struct drm_device *dev)
*/
void radeon_driver_lastclose_kms(struct drm_device *dev)
{
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
vga_switcheroo_process_delayed_switch();
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
}
/**
@@ -445,7 +449,7 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
struct radeon_bo_va *bo_va;
int r;
- fpriv = malloc(sizeof(*fpriv), DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
+ fpriv = malloc(sizeof(*fpriv), DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (unlikely(!fpriv)) {
return -ENOMEM;
}
@@ -724,4 +728,4 @@ struct drm_ioctl_desc radeon_ioctls_kms[] = {
DRM_IOCTL_DEF_DRV(RADEON_GEM_BUSY, radeon_gem_busy_ioctl, DRM_AUTH|DRM_UNLOCKED),
DRM_IOCTL_DEF_DRV(RADEON_GEM_VA, radeon_gem_va_ioctl, DRM_AUTH|DRM_UNLOCKED),
};
-int radeon_max_kms_ioctl = DRM_ARRAY_SIZE(radeon_ioctls_kms);
+int radeon_max_kms_ioctl = ARRAY_SIZE(radeon_ioctls_kms);
diff --git a/sys/dev/drm2/radeon/radeon_legacy_crtc.c b/sys/dev/drm2/radeon/radeon_legacy_crtc.c
index 54f755a..282f200 100644
--- a/sys/dev/drm2/radeon/radeon_legacy_crtc.c
+++ b/sys/dev/drm2/radeon/radeon_legacy_crtc.c
@@ -883,7 +883,7 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
(unsigned)((pll_fb_post_div &
RADEON_P2PLL_POST0_DIV_MASK) >> 16));
- DRM_MDELAY(50); /* Let the clock to lock */
+ mdelay(50); /* Let the clock to lock */
WREG32_PLL_P(RADEON_PIXCLKS_CNTL,
RADEON_PIX2CLK_SRC_SEL_P2PLLCLK,
@@ -988,7 +988,7 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
pll_fb_post_div & RADEON_PPLL_FB3_DIV_MASK,
(pll_fb_post_div & RADEON_PPLL_POST3_DIV_MASK) >> 16);
- DRM_MDELAY(50); /* Let the clock to lock */
+ mdelay(50); /* Let the clock to lock */
WREG32_PLL_P(RADEON_VCLK_ECP_CNTL,
RADEON_VCLK_SRC_SEL_PPLLCLK,
diff --git a/sys/dev/drm2/radeon/radeon_legacy_encoders.c b/sys/dev/drm2/radeon/radeon_legacy_encoders.c
index a4e6e28..d0db92f 100644
--- a/sys/dev/drm2/radeon/radeon_legacy_encoders.c
+++ b/sys/dev/drm2/radeon/radeon_legacy_encoders.c
@@ -89,7 +89,7 @@ static void radeon_legacy_lvds_update(struct drm_encoder *encoder, int mode)
lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL);
lvds_pll_cntl |= RADEON_LVDS_PLL_EN;
WREG32(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl);
- DRM_MDELAY(1);
+ mdelay(1);
lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL);
lvds_pll_cntl &= ~RADEON_LVDS_PLL_RESET;
@@ -102,7 +102,7 @@ static void radeon_legacy_lvds_update(struct drm_encoder *encoder, int mode)
(backlight_level << RADEON_LVDS_BL_MOD_LEVEL_SHIFT));
if (is_mac)
lvds_gen_cntl |= RADEON_LVDS_BL_MOD_EN;
- DRM_MDELAY(panel_pwr_delay);
+ mdelay(panel_pwr_delay);
WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
break;
case DRM_MODE_DPMS_STANDBY:
@@ -119,10 +119,10 @@ static void radeon_legacy_lvds_update(struct drm_encoder *encoder, int mode)
WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN | RADEON_LVDS_DIGON);
}
- DRM_MDELAY(panel_pwr_delay);
+ mdelay(panel_pwr_delay);
WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);
- DRM_MDELAY(panel_pwr_delay);
+ mdelay(panel_pwr_delay);
break;
}
@@ -245,7 +245,7 @@ static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder,
}
static bool radeon_legacy_mode_fixup(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
+ const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
@@ -383,7 +383,7 @@ void radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,
#endif
pdata = malloc(sizeof(struct radeon_backlight_privdata),
- DRM_MEM_DRIVER, M_WAITOK);
+ DRM_MEM_DRIVER, M_NOWAIT);
if (!pdata) {
DRM_ERROR("Memory allocation failed\n");
goto error;
@@ -693,7 +693,7 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc
WREG32(RADEON_DAC_MACRO_CNTL, tmp);
- DRM_MDELAY(2);
+ mdelay(2);
if (RREG32(RADEON_DAC_CNTL) & RADEON_DAC_CMP_OUTPUT)
found = connector_status_connected;
@@ -1338,7 +1338,7 @@ static bool r300_legacy_tv_detect(struct drm_encoder *encoder,
(6 << RADEON_TV_DAC_DACADJ_SHIFT));
RREG32(RADEON_TV_DAC_CNTL);
- DRM_MDELAY(4);
+ mdelay(4);
WREG32(RADEON_TV_DAC_CNTL,
RADEON_TV_DAC_NBLANK |
@@ -1349,7 +1349,7 @@ static bool r300_legacy_tv_detect(struct drm_encoder *encoder,
(6 << RADEON_TV_DAC_DACADJ_SHIFT));
RREG32(RADEON_TV_DAC_CNTL);
- DRM_MDELAY(6);
+ mdelay(6);
tmp = RREG32(RADEON_TV_DAC_CNTL);
if ((tmp & RADEON_TV_DAC_GDACDET) != 0) {
@@ -1416,7 +1416,7 @@ static bool radeon_legacy_tv_detect(struct drm_encoder *encoder,
(0x109 << RADEON_TV_FORCE_DAC_DATA_SHIFT);
WREG32(RADEON_TV_PRE_DAC_MUX_CNTL, tmp);
- DRM_MDELAY(3);
+ mdelay(3);
tmp = RREG32(RADEON_TV_DAC_CNTL);
if (tmp & RADEON_TV_DAC_GDACDET) {
found = true;
@@ -1498,9 +1498,8 @@ static bool radeon_legacy_ext_dac_detect(struct drm_encoder *encoder,
if (found)
break;
- DRM_MDELAY(1);
if (!drm_can_sleep())
- DRM_MDELAY(1);
+ mdelay(1);
else
DRM_MSLEEP(1);
}
@@ -1642,7 +1641,7 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder
tmp = dac_cntl2 | RADEON_DAC2_DAC2_CLK_SEL | RADEON_DAC2_CMP_EN;
WREG32(RADEON_DAC_CNTL2, tmp);
- DRM_MDELAY(10);
+ mdelay(10);
if (ASIC_IS_R300(rdev)) {
if (RREG32(RADEON_DAC_CNTL2) & RADEON_DAC2_CMP_OUT_B)
@@ -1699,7 +1698,7 @@ static struct radeon_encoder_int_tmds *radeon_legacy_get_tmds_info(struct radeon
bool ret;
tmds = malloc(sizeof(struct radeon_encoder_int_tmds),
- DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (!tmds)
return NULL;
@@ -1726,7 +1725,7 @@ static struct radeon_encoder_ext_tmds *radeon_legacy_get_ext_tmds_info(struct ra
return NULL;
tmds = malloc(sizeof(struct radeon_encoder_ext_tmds),
- DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (!tmds)
return NULL;
@@ -1758,7 +1757,7 @@ radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_enum, uint32_
/* add a new one */
radeon_encoder = malloc(sizeof(struct radeon_encoder),
- DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (!radeon_encoder)
return;
diff --git a/sys/dev/drm2/radeon/radeon_legacy_tv.c b/sys/dev/drm2/radeon/radeon_legacy_tv.c
index 5311a48..c124a74 100644
--- a/sys/dev/drm2/radeon/radeon_legacy_tv.c
+++ b/sys/dev/drm2/radeon/radeon_legacy_tv.c
@@ -232,7 +232,7 @@ static const struct radeon_tv_mode_constants available_tv_modes[] = {
},
};
-#define N_AVAILABLE_MODES DRM_ARRAY_SIZE(available_tv_modes)
+#define N_AVAILABLE_MODES ARRAY_SIZE(available_tv_modes)
static const struct radeon_tv_mode_constants *radeon_legacy_tv_get_std_mode(struct radeon_encoder *radeon_encoder,
uint16_t *pll_ref_freq)
@@ -647,7 +647,7 @@ void radeon_legacy_tv_mode_set(struct drm_encoder *encoder,
if (flicker_removal < 3)
flicker_removal = 3;
- for (i = 0; i < DRM_ARRAY_SIZE(SLOPE_limit); ++i) {
+ for (i = 0; i < ARRAY_SIZE(SLOPE_limit); ++i) {
if (flicker_removal == SLOPE_limit[i])
break;
}
diff --git a/sys/dev/drm2/radeon/radeon_mem.c b/sys/dev/drm2/radeon/radeon_mem.c
index 9ff8791..b14c0ce 100644
--- a/sys/dev/drm2/radeon/radeon_mem.c
+++ b/sys/dev/drm2/radeon/radeon_mem.c
@@ -46,7 +46,7 @@ static struct mem_block *split_block(struct mem_block *p, int start, int size,
/* Maybe cut off the start of an existing block */
if (start > p->start) {
struct mem_block *newblock = malloc(sizeof(*newblock),
- DRM_MEM_DRIVER, M_WAITOK);
+ DRM_MEM_DRIVER, M_NOWAIT);
if (!newblock)
goto out;
newblock->start = start;
@@ -63,7 +63,7 @@ static struct mem_block *split_block(struct mem_block *p, int start, int size,
/* Maybe cut off the end of an existing block */
if (size < p->size) {
struct mem_block *newblock = malloc(sizeof(*newblock),
- DRM_MEM_DRIVER, M_WAITOK);
+ DRM_MEM_DRIVER, M_NOWAIT);
if (!newblock)
goto out;
newblock->start = start + size;
@@ -137,12 +137,12 @@ static void free_block(struct mem_block *p)
static int init_heap(struct mem_block **heap, int start, int size)
{
struct mem_block *blocks = malloc(sizeof(*blocks),
- DRM_MEM_DRIVER, M_WAITOK);
+ DRM_MEM_DRIVER, M_NOWAIT);
if (!blocks)
return -ENOMEM;
- *heap = malloc(sizeof(**heap), DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
+ *heap = malloc(sizeof(**heap), DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (!*heap) {
free(blocks, DRM_MEM_DRIVER);
return -ENOMEM;
diff --git a/sys/dev/drm2/radeon/radeon_object.c b/sys/dev/drm2/radeon/radeon_object.c
index 30d3d81..eadfe74 100644
--- a/sys/dev/drm2/radeon/radeon_object.c
+++ b/sys/dev/drm2/radeon/radeon_object.c
@@ -36,11 +36,15 @@ __FBSDID("$FreeBSD$");
#include <dev/drm2/drmP.h>
#include <dev/drm2/radeon/radeon_drm.h>
#include "radeon.h"
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
#include "radeon_trace.h"
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
+#ifdef FREEBSD_WIP /* FreeBSD: to please GCC 4.2. */
+int radeon_ttm_init(struct radeon_device *rdev);
+void radeon_ttm_fini(struct radeon_device *rdev);
+#endif
static void radeon_bo_clear_surface_reg(struct radeon_bo *bo);
/*
@@ -135,7 +139,7 @@ int radeon_bo_create(struct radeon_device *rdev,
sizeof(struct radeon_bo));
bo = malloc(sizeof(struct radeon_bo),
- DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (bo == NULL)
return -ENOMEM;
r = drm_gem_object_init(rdev->ddev, &bo->gem_base, size);
@@ -160,9 +164,9 @@ int radeon_bo_create(struct radeon_device *rdev,
}
*bo_ptr = bo;
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
trace_radeon_bo_create(bo);
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
return 0;
}
@@ -315,6 +319,7 @@ void radeon_bo_force_delete(struct radeon_device *rdev)
}
dev_err(rdev->dev, "Userspace still has active objects !\n");
list_for_each_entry_safe(bo, n, &rdev->gem.objects, list) {
+ DRM_LOCK(rdev->ddev);
dev_err(rdev->dev, "%p %p %lu %lu force free\n",
&bo->gem_base, bo, (unsigned long)bo->gem_base.size,
*((unsigned long *)&bo->gem_base.refcount));
@@ -323,6 +328,7 @@ void radeon_bo_force_delete(struct radeon_device *rdev)
sx_xunlock(&bo->rdev->gem.mutex);
/* this should unref the ttm bo */
drm_gem_object_unreference(&bo->gem_base);
+ DRM_UNLOCK(rdev->ddev);
}
}
@@ -388,13 +394,13 @@ int radeon_bo_list_validate(struct list_head *head)
return 0;
}
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
int radeon_bo_fbdev_mmap(struct radeon_bo *bo,
struct vm_area_struct *vma)
{
return ttm_fbdev_mmap(vma, &bo->tbo);
}
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
int radeon_bo_get_surface_reg(struct radeon_bo *bo)
{
diff --git a/sys/dev/drm2/radeon/radeon_object.h b/sys/dev/drm2/radeon/radeon_object.h
index efb7149..c115514 100644
--- a/sys/dev/drm2/radeon/radeon_object.h
+++ b/sys/dev/drm2/radeon/radeon_object.h
@@ -139,10 +139,10 @@ extern void radeon_bo_fini(struct radeon_device *rdev);
extern void radeon_bo_list_add_object(struct radeon_bo_list *lobj,
struct list_head *head);
extern int radeon_bo_list_validate(struct list_head *head);
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
extern int radeon_bo_fbdev_mmap(struct radeon_bo *bo,
struct vm_area_struct *vma);
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
extern int radeon_bo_set_tiling_flags(struct radeon_bo *bo,
u32 tiling_flags, u32 pitch);
extern void radeon_bo_get_tiling_flags(struct radeon_bo *bo,
diff --git a/sys/dev/drm2/radeon/radeon_pm.c b/sys/dev/drm2/radeon/radeon_pm.c
index 0caa1b7..18d8003 100644
--- a/sys/dev/drm2/radeon/radeon_pm.c
+++ b/sys/dev/drm2/radeon/radeon_pm.c
@@ -41,9 +41,9 @@ static const char *radeon_pm_state_type_name[5] = {
"Performance",
};
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
static void radeon_dynpm_idle_work_handler(struct work_struct *work);
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
static int radeon_debugfs_pm_init(struct radeon_device *rdev);
static bool radeon_pm_in_vbl(struct radeon_device *rdev);
static bool radeon_pm_debug_check_in_vbl(struct radeon_device *rdev, bool finish);
@@ -87,7 +87,7 @@ static void radeon_pm_update_profile(struct radeon_device *rdev)
rdev->pm.profile_index = PM_PROFILE_DEFAULT_IDX;
break;
case PM_PROFILE_AUTO:
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
if (power_supply_is_system_supplied() > 0) {
if (rdev->pm.active_crtc_count > 1)
rdev->pm.profile_index = PM_PROFILE_HIGH_MH_IDX;
@@ -99,7 +99,7 @@ static void radeon_pm_update_profile(struct radeon_device *rdev)
else
rdev->pm.profile_index = PM_PROFILE_MID_SH_IDX;
}
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
break;
case PM_PROFILE_LOW:
if (rdev->pm.active_crtc_count > 1)
@@ -151,11 +151,11 @@ static void radeon_sync_with_vblank(struct radeon_device *rdev)
{
if (rdev->pm.active_crtcs) {
rdev->pm.vblank_sync = false;
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
wait_event_timeout(
rdev->irq.vblank_queue, rdev->pm.vblank_sync,
msecs_to_jiffies(RADEON_WAIT_VBLANK_TIMEOUT));
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
}
}
@@ -176,7 +176,7 @@ static void radeon_set_power_state(struct radeon_device *rdev)
/* starting with BTC, there is one state that is used for both
* MH and SH. Difference is that we always use the high clock index for
- * mclk.
+ * mclk and vddci.
*/
if ((rdev->pm.pm_method == PM_METHOD_PROFILE) &&
(rdev->family >= CHIP_BARTS) &&
@@ -248,7 +248,7 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev)
(rdev->pm.requested_power_state_index == rdev->pm.current_power_state_index))
return;
- //DRM_LOCK(rdev->ddev); XXX Recursion, already locked in drm_attach/drm_load -- dumbbell@
+ DRM_LOCK(rdev->ddev);
sx_xlock(&rdev->pm.mclk_lock);
sx_xlock(&rdev->ring_lock);
@@ -263,7 +263,7 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev)
/* needs a GPU reset dont reset here */
sx_xunlock(&rdev->ring_lock);
sx_xunlock(&rdev->pm.mclk_lock);
- //DRM_UNLOCK(rdev->ddev); XXX Recursion, already locked in drm_attach/drm_load -- dumbbell@
+ DRM_UNLOCK(rdev->ddev);
return;
}
}
@@ -299,7 +299,7 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev)
sx_xunlock(&rdev->ring_lock);
sx_xunlock(&rdev->pm.mclk_lock);
- //DRM_UNLOCK(rdev->ddev); XXX Recursion, already locked in drm_attach/drm_load -- dumbbell@
+ DRM_UNLOCK(rdev->ddev);
}
static void radeon_pm_print_states(struct radeon_device *rdev)
@@ -336,7 +336,7 @@ static void radeon_pm_print_states(struct radeon_device *rdev)
}
}
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
static ssize_t radeon_get_pm_profile(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -421,9 +421,9 @@ static ssize_t radeon_set_pm_method(struct device *dev,
rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE;
rdev->pm.pm_method = PM_METHOD_PROFILE;
sx_xunlock(&rdev->pm.mutex);
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
cancel_delayed_work_sync(&rdev->pm.dynpm_idle_work);
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
} else {
count = -EINVAL;
goto fail;
@@ -488,15 +488,15 @@ static struct attribute *hwmon_attributes[] = {
static const struct attribute_group hwmon_attrgroup = {
.attrs = hwmon_attributes,
};
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
static int radeon_hwmon_init(struct radeon_device *rdev)
{
int err = 0;
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
rdev->pm.int_hwmon_dev = NULL;
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
switch (rdev->pm.int_thermal_type) {
case THERMAL_TYPE_RV6XX:
@@ -508,7 +508,7 @@ static int radeon_hwmon_init(struct radeon_device *rdev)
/* No support for TN yet */
if (rdev->family == CHIP_ARUBA)
return err;
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
rdev->pm.int_hwmon_dev = hwmon_device_register(rdev->dev);
if (IS_ERR(rdev->pm.int_hwmon_dev)) {
err = PTR_ERR(rdev->pm.int_hwmon_dev);
@@ -524,7 +524,7 @@ static int radeon_hwmon_init(struct radeon_device *rdev)
"Unable to create hwmon sysfs file: %d\n", err);
hwmon_device_unregister(rdev->dev);
}
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
break;
default:
break;
@@ -535,12 +535,12 @@ static int radeon_hwmon_init(struct radeon_device *rdev)
static void radeon_hwmon_fini(struct radeon_device *rdev)
{
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
if (rdev->pm.int_hwmon_dev) {
sysfs_remove_group(&rdev->pm.int_hwmon_dev->kobj, &hwmon_attrgroup);
hwmon_device_unregister(rdev->pm.int_hwmon_dev);
}
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
}
void radeon_pm_suspend(struct radeon_device *rdev)
@@ -552,9 +552,9 @@ void radeon_pm_suspend(struct radeon_device *rdev)
}
sx_xunlock(&rdev->pm.mutex);
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
cancel_delayed_work_sync(&rdev->pm.dynpm_idle_work);
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
}
void radeon_pm_resume(struct radeon_device *rdev)
@@ -585,10 +585,10 @@ void radeon_pm_resume(struct radeon_device *rdev)
if (rdev->pm.pm_method == PM_METHOD_DYNPM
&& rdev->pm.dynpm_state == DYNPM_STATE_SUSPENDED) {
rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE;
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
schedule_delayed_work(&rdev->pm.dynpm_idle_work,
msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
}
sx_xunlock(&rdev->pm.mutex);
radeon_pm_compute_clocks(rdev);
@@ -640,20 +640,20 @@ int radeon_pm_init(struct radeon_device *rdev)
if (ret)
return ret;
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
INIT_DELAYED_WORK(&rdev->pm.dynpm_idle_work, radeon_dynpm_idle_work_handler);
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
if (rdev->pm.num_power_states > 1) {
/* where's the best place to put these? */
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
ret = device_create_file(rdev->dev, &dev_attr_power_profile);
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
if (ret)
DRM_ERROR("failed to create device file for power profile\n");
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
ret = device_create_file(rdev->dev, &dev_attr_power_method);
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
if (ret)
DRM_ERROR("failed to create device file for power method\n");
@@ -670,7 +670,6 @@ int radeon_pm_init(struct radeon_device *rdev)
void radeon_pm_fini(struct radeon_device *rdev)
{
if (rdev->pm.num_power_states > 1) {
- DRM_UNLOCK(rdev->ddev); /* Work around LOR. */
sx_xlock(&rdev->pm.mutex);
if (rdev->pm.pm_method == PM_METHOD_PROFILE) {
rdev->pm.profile = PM_PROFILE_DEFAULT;
@@ -683,14 +682,13 @@ void radeon_pm_fini(struct radeon_device *rdev)
radeon_pm_set_clocks(rdev);
}
sx_xunlock(&rdev->pm.mutex);
- DRM_LOCK(rdev->ddev);
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
cancel_delayed_work_sync(&rdev->pm.dynpm_idle_work);
device_remove_file(rdev->dev, &dev_attr_power_profile);
device_remove_file(rdev->dev, &dev_attr_power_method);
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
}
if (rdev->pm.power_state) {
@@ -735,9 +733,9 @@ void radeon_pm_compute_clocks(struct radeon_device *rdev)
if (rdev->pm.dynpm_state != DYNPM_STATE_DISABLED) {
if (rdev->pm.active_crtc_count > 1) {
if (rdev->pm.dynpm_state == DYNPM_STATE_ACTIVE) {
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
cancel_delayed_work(&rdev->pm.dynpm_idle_work);
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
rdev->pm.dynpm_state = DYNPM_STATE_PAUSED;
rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;
@@ -755,23 +753,23 @@ void radeon_pm_compute_clocks(struct radeon_device *rdev)
radeon_pm_get_dynpm_state(rdev);
radeon_pm_set_clocks(rdev);
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
schedule_delayed_work(&rdev->pm.dynpm_idle_work,
msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
} else if (rdev->pm.dynpm_state == DYNPM_STATE_PAUSED) {
rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE;
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
schedule_delayed_work(&rdev->pm.dynpm_idle_work,
msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
DRM_DEBUG_DRIVER("radeon: dynamic power management activated\n");
}
} else { /* count == 0 */
if (rdev->pm.dynpm_state != DYNPM_STATE_MINIMUM) {
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
cancel_delayed_work(&rdev->pm.dynpm_idle_work);
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
rdev->pm.dynpm_state = DYNPM_STATE_MINIMUM;
rdev->pm.dynpm_planned_action = DYNPM_ACTION_MINIMUM;
@@ -816,7 +814,7 @@ static bool radeon_pm_debug_check_in_vbl(struct radeon_device *rdev, bool finish
return in_vbl;
}
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
static void radeon_dynpm_idle_work_handler(struct work_struct *work)
{
struct radeon_device *rdev;
@@ -877,7 +875,7 @@ static void radeon_dynpm_idle_work_handler(struct work_struct *work)
sx_xunlock(&rdev->pm.mutex);
ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched);
}
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
/*
* Debugfs info
@@ -891,7 +889,11 @@ static int radeon_debugfs_pm_info(struct seq_file *m, void *data)
struct radeon_device *rdev = dev->dev_private;
seq_printf(m, "default engine clock: %u0 kHz\n", rdev->pm.default_sclk);
- seq_printf(m, "current engine clock: %u0 kHz\n", radeon_get_engine_clock(rdev));
+ /* radeon_get_engine_clock is not reliable on APUs so just print the current clock */
+ if ((rdev->family >= CHIP_PALM) && (rdev->flags & RADEON_IS_IGP))
+ seq_printf(m, "current engine clock: %u0 kHz\n", rdev->pm.current_sclk);
+ else
+ seq_printf(m, "current engine clock: %u0 kHz\n", radeon_get_engine_clock(rdev));
seq_printf(m, "default memory clock: %u0 kHz\n", rdev->pm.default_mclk);
if (rdev->asic->pm.get_memory_clock)
seq_printf(m, "current memory clock: %u0 kHz\n", radeon_get_memory_clock(rdev));
diff --git a/sys/dev/drm2/radeon/radeon_ring.c b/sys/dev/drm2/radeon/radeon_ring.c
index 37d0ade..387182a 100644
--- a/sys/dev/drm2/radeon/radeon_ring.c
+++ b/sys/dev/drm2/radeon/radeon_ring.c
@@ -36,7 +36,7 @@ __FBSDID("$FreeBSD$");
#include "radeon.h"
#include "atom.h"
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
/*
* IB
* IBs (Indirect Buffers) and areas of GPU accessible memory where
@@ -47,7 +47,7 @@ __FBSDID("$FreeBSD$");
* put in IBs for execution by the requested ring.
*/
static int radeon_debugfs_sa_init(struct radeon_device *rdev);
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
/**
* radeon_ib_get - request an IB (Indirect Buffer)
@@ -165,7 +165,8 @@ int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib,
radeon_semaphore_free(rdev, &ib->semaphore, NULL);
}
/* if we can't remember our last VM flush then flush now! */
- if (ib->vm && !ib->vm->last_flush) {
+ /* XXX figure out why we have to flush for every IB */
+ if (ib->vm /*&& !ib->vm->last_flush*/) {
radeon_ring_vm_flush(rdev, ib->ring, ib->vm);
}
if (const_ib) {
@@ -219,11 +220,11 @@ int radeon_ib_pool_init(struct radeon_device *rdev)
}
rdev->ib_pool_ready = true;
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
if (radeon_debugfs_sa_init(rdev)) {
dev_err(rdev->dev, "failed to register debugfs file for SA\n");
}
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
return 0;
}
@@ -284,7 +285,7 @@ int radeon_ib_ring_tests(struct radeon_device *rdev)
return 0;
}
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
/*
* Rings
* Most engines on the GPU are fed via ring buffers. Ring
@@ -299,9 +300,8 @@ int radeon_ib_ring_tests(struct radeon_device *rdev)
* them until the pointers are equal again.
*/
static int radeon_debugfs_ring_init(struct radeon_device *rdev, struct radeon_ring *ring);
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
-#if defined(DRM_DEBUG_CODE) && DRM_DEBUG_CODE != 0
/**
* radeon_ring_write - write a value to the ring
*
@@ -322,7 +322,6 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v)
ring->count_dw--;
ring->ring_free_dw--;
}
-#endif
/**
* radeon_ring_supports_scratch_reg - check if the ring supports
@@ -623,7 +622,7 @@ unsigned radeon_ring_backup(struct radeon_device *rdev, struct radeon_ring *ring
}
/* and then save the content of the ring */
- *data = malloc(size * sizeof(uint32_t), DRM_MEM_DRIVER, M_WAITOK);
+ *data = malloc(size * sizeof(uint32_t), DRM_MEM_DRIVER, M_NOWAIT);
if (!*data) {
sx_xunlock(&rdev->ring_lock);
return 0;
@@ -690,7 +689,7 @@ int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsig
u32 ptr_reg_shift, u32 ptr_reg_mask, u32 nop)
{
int r;
- void *ring_ptr;
+ void *ring_ptr; /* FreeBSD: to please GCC 4.2. */
ring->ring_size = ring_size;
ring->rptr_offs = rptr_offs;
@@ -738,11 +737,11 @@ int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsig
ring->next_rptr_gpu_addr = rdev->wb.gpu_addr + index;
ring->next_rptr_cpu_addr = &rdev->wb.wb[index/4];
}
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
if (radeon_debugfs_ring_init(rdev, ring)) {
DRM_ERROR("Failed to register debugfs file for rings !\n");
}
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
radeon_ring_lockup_update(ring);
return 0;
}
@@ -852,7 +851,7 @@ static struct drm_info_list radeon_debugfs_sa_list[] = {
#endif
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
static int radeon_debugfs_ring_init(struct radeon_device *rdev, struct radeon_ring *ring)
{
#if defined(CONFIG_DEBUG_FS)
@@ -881,4 +880,4 @@ static int radeon_debugfs_sa_init(struct radeon_device *rdev)
return 0;
#endif
}
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
diff --git a/sys/dev/drm2/radeon/radeon_sa.c b/sys/dev/drm2/radeon/radeon_sa.c
index 25695a4..9290612 100644
--- a/sys/dev/drm2/radeon/radeon_sa.c
+++ b/sys/dev/drm2/radeon/radeon_sa.c
@@ -327,7 +327,7 @@ int radeon_sa_bo_new(struct radeon_device *rdev,
KASSERT(align <= RADEON_GPU_PAGE_SIZE, ("align > RADEON_GPU_PAGE_SIZE"));
KASSERT(size <= sa_manager->size, ("size > sa_manager->size"));
- *sa_bo = malloc(sizeof(struct radeon_sa_bo), DRM_MEM_DRIVER, M_WAITOK);
+ *sa_bo = malloc(sizeof(struct radeon_sa_bo), DRM_MEM_DRIVER, M_NOWAIT);
if ((*sa_bo) == NULL) {
return -ENOMEM;
}
diff --git a/sys/dev/drm2/radeon/radeon_semaphore.c b/sys/dev/drm2/radeon/radeon_semaphore.c
index 717a94a..ecd09dd 100644
--- a/sys/dev/drm2/radeon/radeon_semaphore.c
+++ b/sys/dev/drm2/radeon/radeon_semaphore.c
@@ -41,7 +41,7 @@ int radeon_semaphore_create(struct radeon_device *rdev,
int r;
*semaphore = malloc(sizeof(struct radeon_semaphore),
- DRM_MEM_DRIVER, M_WAITOK);
+ DRM_MEM_DRIVER, M_NOWAIT);
if (*semaphore == NULL) {
return -ENOMEM;
}
diff --git a/sys/dev/drm2/radeon/radeon_state.c b/sys/dev/drm2/radeon/radeon_state.c
index 1716830..d5aa9d1 100644
--- a/sys/dev/drm2/radeon/radeon_state.c
+++ b/sys/dev/drm2/radeon/radeon_state.c
@@ -1534,7 +1534,7 @@ static void radeon_cp_dispatch_vertex(struct drm_device * dev,
drm_radeon_tcl_prim_t * prim)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
- struct drm_radeon_master_private *master_priv = file_priv->masterp->driver_priv;
+ struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv;
int offset = dev_priv->gart_buffers_offset + buf->offset + prim->start;
int numverts = (int)prim->numverts;
@@ -1916,7 +1916,7 @@ static int radeon_cp_dispatch_texture(struct drm_device * dev,
ADVANCE_RING();
COMMIT_RING();
- radeon_cp_discard_buffer(dev, file_priv->masterp, buf);
+ radeon_cp_discard_buffer(dev, file_priv->master, buf);
/* Update the input parameters for next time */
image->y += height;
@@ -2156,7 +2156,7 @@ static int radeon_surface_free(struct drm_device *dev, void *data, struct drm_fi
static int radeon_cp_clear(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
- struct drm_radeon_master_private *master_priv = file_priv->masterp->driver_priv;
+ struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv;
drm_radeon_clear_t *clear = data;
drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS];
@@ -2173,7 +2173,7 @@ static int radeon_cp_clear(struct drm_device *dev, void *data, struct drm_file *
sarea_priv->nbox * sizeof(depth_boxes[0])))
return -EFAULT;
- radeon_cp_dispatch_clear(dev, file_priv->masterp, clear, depth_boxes);
+ radeon_cp_dispatch_clear(dev, file_priv->master, clear, depth_boxes);
COMMIT_RING();
return 0;
@@ -2220,9 +2220,9 @@ static int radeon_cp_flip(struct drm_device *dev, void *data, struct drm_file *f
RING_SPACE_TEST_WITH_RETURN(dev_priv);
if (!dev_priv->page_flipping)
- radeon_do_init_pageflip(dev, file_priv->masterp);
+ radeon_do_init_pageflip(dev, file_priv->master);
- radeon_cp_dispatch_flip(dev, file_priv->masterp);
+ radeon_cp_dispatch_flip(dev, file_priv->master);
COMMIT_RING();
return 0;
@@ -2231,7 +2231,7 @@ static int radeon_cp_flip(struct drm_device *dev, void *data, struct drm_file *f
static int radeon_cp_swap(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
- struct drm_radeon_master_private *master_priv = file_priv->masterp->driver_priv;
+ struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv;
DRM_DEBUG("\n");
@@ -2246,7 +2246,7 @@ static int radeon_cp_swap(struct drm_device *dev, void *data, struct drm_file *f
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
r600_cp_dispatch_swap(dev, file_priv);
else
- radeon_cp_dispatch_swap(dev, file_priv->masterp);
+ radeon_cp_dispatch_swap(dev, file_priv->master);
sarea_priv->ctx_owner = 0;
COMMIT_RING();
@@ -2256,7 +2256,7 @@ static int radeon_cp_swap(struct drm_device *dev, void *data, struct drm_file *f
static int radeon_cp_vertex(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
- struct drm_radeon_master_private *master_priv = file_priv->masterp->driver_priv;
+ struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
drm_radeon_sarea_t *sarea_priv;
struct drm_device_dma *dma = dev->dma;
struct drm_buf *buf;
@@ -2325,7 +2325,7 @@ static int radeon_cp_vertex(struct drm_device *dev, void *data, struct drm_file
}
if (vertex->discard) {
- radeon_cp_discard_buffer(dev, file_priv->masterp, buf);
+ radeon_cp_discard_buffer(dev, file_priv->master, buf);
}
COMMIT_RING();
@@ -2335,7 +2335,7 @@ static int radeon_cp_vertex(struct drm_device *dev, void *data, struct drm_file
static int radeon_cp_indices(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
- struct drm_radeon_master_private *master_priv = file_priv->masterp->driver_priv;
+ struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
drm_radeon_sarea_t *sarea_priv;
struct drm_device_dma *dma = dev->dma;
struct drm_buf *buf;
@@ -2414,9 +2414,9 @@ static int radeon_cp_indices(struct drm_device *dev, void *data, struct drm_file
prim.numverts = RADEON_MAX_VB_VERTS; /* duh */
prim.vc_format = sarea_priv->vc_format;
- radeon_cp_dispatch_indices(dev, file_priv->masterp, buf, &prim);
+ radeon_cp_dispatch_indices(dev, file_priv->master, buf, &prim);
if (elts->discard) {
- radeon_cp_discard_buffer(dev, file_priv->masterp, buf);
+ radeon_cp_discard_buffer(dev, file_priv->master, buf);
}
COMMIT_RING();
@@ -2532,7 +2532,7 @@ static int radeon_cp_indirect(struct drm_device *dev, void *data, struct drm_fil
}
if (indirect->discard) {
- radeon_cp_discard_buffer(dev, file_priv->masterp, buf);
+ radeon_cp_discard_buffer(dev, file_priv->master, buf);
}
COMMIT_RING();
@@ -2542,7 +2542,7 @@ static int radeon_cp_indirect(struct drm_device *dev, void *data, struct drm_fil
static int radeon_cp_vertex2(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
- struct drm_radeon_master_private *master_priv = file_priv->masterp->driver_priv;
+ struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
drm_radeon_sarea_t *sarea_priv;
struct drm_device_dma *dma = dev->dma;
struct drm_buf *buf;
@@ -2614,7 +2614,7 @@ static int radeon_cp_vertex2(struct drm_device *dev, void *data, struct drm_file
tclprim.offset = prim.numverts * 64;
tclprim.numverts = RADEON_MAX_VB_VERTS; /* duh */
- radeon_cp_dispatch_indices(dev, file_priv->masterp, buf, &tclprim);
+ radeon_cp_dispatch_indices(dev, file_priv->master, buf, &tclprim);
} else {
tclprim.numverts = prim.numverts;
tclprim.offset = 0; /* not used */
@@ -2627,7 +2627,7 @@ static int radeon_cp_vertex2(struct drm_device *dev, void *data, struct drm_file
}
if (vertex->discard) {
- radeon_cp_discard_buffer(dev, file_priv->masterp, buf);
+ radeon_cp_discard_buffer(dev, file_priv->master, buf);
}
COMMIT_RING();
@@ -2965,7 +2965,7 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data,
goto err;
}
- radeon_cp_discard_buffer(dev, file_priv->masterp, buf);
+ radeon_cp_discard_buffer(dev, file_priv->master, buf);
break;
case RADEON_CMD_PACKET3:
@@ -3066,7 +3066,7 @@ static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_fil
case RADEON_PARAM_STATUS_HANDLE:
value = dev_priv->ring_rptr_offset;
break;
-#ifndef __LP64__
+#if BITS_PER_LONG == 32
/*
* This ioctl() doesn't work on 64-bit platforms because hw_lock is a
* pointer which can't fit into an int-sized variable. According to
@@ -3128,7 +3128,7 @@ static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_fil
static int radeon_cp_setparam(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
- struct drm_radeon_master_private *master_priv = file_priv->masterp->driver_priv;
+ struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
drm_radeon_setparam_t *sp = data;
struct drm_radeon_driver_file_fields *radeon_priv;
@@ -3206,7 +3206,7 @@ int radeon_driver_open(struct drm_device *dev, struct drm_file *file_priv)
struct drm_radeon_driver_file_fields *radeon_priv;
DRM_DEBUG("\n");
- radeon_priv = malloc(sizeof(*radeon_priv), DRM_MEM_DRIVER, M_WAITOK);
+ radeon_priv = malloc(sizeof(*radeon_priv), DRM_MEM_DRIVER, M_NOWAIT);
if (!radeon_priv)
return -ENOMEM;
@@ -3259,4 +3259,4 @@ struct drm_ioctl_desc radeon_ioctls[] = {
DRM_IOCTL_DEF_DRV(RADEON_CS, r600_cs_legacy_ioctl, DRM_AUTH)
};
-int radeon_max_ioctl = DRM_ARRAY_SIZE(radeon_ioctls);
+int radeon_max_ioctl = ARRAY_SIZE(radeon_ioctls);
diff --git a/sys/dev/drm2/radeon/radeon_test.c b/sys/dev/drm2/radeon/radeon_test.c
index 7774699..94bb9f3 100644
--- a/sys/dev/drm2/radeon/radeon_test.c
+++ b/sys/dev/drm2/radeon/radeon_test.c
@@ -70,7 +70,7 @@ static void radeon_do_test_moves(struct radeon_device *rdev, int flag)
n -= rdev->ih.ring_size;
n /= size;
- gtt_obj = malloc(n * sizeof(*gtt_obj), DRM_MEM_DRIVER, M_ZERO | M_WAITOK);
+ gtt_obj = malloc(n * sizeof(*gtt_obj), DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (!gtt_obj) {
DRM_ERROR("Failed to allocate %d pointers\n", n);
r = 1;
@@ -291,7 +291,7 @@ void radeon_test_ring_sync(struct radeon_device *rdev,
}
radeon_ring_unlock_commit(rdev, ringA);
- DRM_MDELAY(1000);
+ mdelay(1000);
if (radeon_fence_signaled(fence1)) {
DRM_ERROR("Fence 1 signaled without waiting for semaphore.\n");
@@ -312,7 +312,7 @@ void radeon_test_ring_sync(struct radeon_device *rdev,
goto out_cleanup;
}
- DRM_MDELAY(1000);
+ mdelay(1000);
if (radeon_fence_signaled(fence2)) {
DRM_ERROR("Fence 2 signaled without waiting for semaphore.\n");
@@ -390,7 +390,7 @@ static void radeon_test_ring_sync2(struct radeon_device *rdev,
}
radeon_ring_unlock_commit(rdev, ringB);
- DRM_MDELAY(1000);
+ mdelay(1000);
if (radeon_fence_signaled(fenceA)) {
DRM_ERROR("Fence A signaled without waiting for semaphore.\n");
@@ -410,7 +410,7 @@ static void radeon_test_ring_sync2(struct radeon_device *rdev,
radeon_ring_unlock_commit(rdev, ringC);
for (i = 0; i < 30; ++i) {
- DRM_MDELAY(100);
+ mdelay(100);
sigA = radeon_fence_signaled(fenceA);
sigB = radeon_fence_signaled(fenceB);
if (sigA || sigB)
@@ -435,7 +435,7 @@ static void radeon_test_ring_sync2(struct radeon_device *rdev,
radeon_semaphore_emit_signal(rdev, ringC->idx, semaphore);
radeon_ring_unlock_commit(rdev, ringC);
- DRM_MDELAY(1000);
+ mdelay(1000);
r = radeon_fence_wait(fenceA, false);
if (r) {
diff --git a/sys/dev/drm2/radeon/radeon_ttm.c b/sys/dev/drm2/radeon/radeon_ttm.c
index f4ac178..abfe774 100644
--- a/sys/dev/drm2/radeon/radeon_ttm.c
+++ b/sys/dev/drm2/radeon/radeon_ttm.c
@@ -561,13 +561,13 @@ static struct ttm_tt *radeon_ttm_tt_create(struct ttm_bo_device *bdev,
rdev = radeon_get_rdev(bdev);
#if __OS_HAS_AGP
if (rdev->flags & RADEON_IS_AGP) {
- return ttm_agp_tt_create(bdev, rdev->ddev->agp->agpdev,
+ return ttm_agp_tt_create(bdev, rdev->ddev->agp->bridge,
size, page_flags, dummy_read_page);
}
#endif
gtt = malloc(sizeof(struct radeon_ttm_tt),
- DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
+ DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
if (gtt == NULL) {
return NULL;
}
@@ -586,25 +586,21 @@ static int radeon_ttm_tt_populate(struct ttm_tt *ttm)
struct radeon_ttm_tt *gtt = (void *)ttm;
unsigned i;
int r;
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG);
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
if (ttm->state != tt_unpopulated)
return 0;
-#ifdef DUMBBELL_WIP
- /*
- * Maybe unneeded on FreeBSD.
- * -- dumbbell@
- */
+#ifdef FREEBSD_WIP
if (slave && ttm->sg) {
drm_prime_sg_to_page_addr_arrays(ttm->sg, ttm->pages,
gtt->ttm.dma_address, ttm->num_pages);
ttm->state = tt_unbound;
return 0;
}
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
rdev = radeon_get_rdev(ttm->bdev);
#if __OS_HAS_AGP
@@ -626,7 +622,7 @@ static int radeon_ttm_tt_populate(struct ttm_tt *ttm)
for (i = 0; i < ttm->num_pages; i++) {
gtt->ttm.dma_address[i] = VM_PAGE_TO_PHYS(ttm->pages[i]);
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
gtt->ttm.dma_address[i] = pci_map_page(rdev->pdev, ttm->pages[i],
0, PAGE_SIZE,
PCI_DMA_BIDIRECTIONAL);
@@ -639,7 +635,7 @@ static int radeon_ttm_tt_populate(struct ttm_tt *ttm)
ttm_pool_unpopulate(ttm);
return -EFAULT;
}
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
}
return 0;
}
@@ -672,10 +668,10 @@ static void radeon_ttm_tt_unpopulate(struct ttm_tt *ttm)
for (i = 0; i < ttm->num_pages; i++) {
if (gtt->ttm.dma_address[i]) {
gtt->ttm.dma_address[i] = 0;
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
pci_unmap_page(rdev->pdev, gtt->ttm.dma_address[i],
PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
}
}
@@ -704,7 +700,7 @@ static struct ttm_bo_driver radeon_bo_driver = {
int radeon_ttm_init(struct radeon_device *rdev)
{
- int r, r2;
+ int r;
r = radeon_ttm_global_init(rdev);
if (r) {
@@ -750,12 +746,6 @@ int radeon_ttm_init(struct radeon_device *rdev)
rdev->mc.gtt_size >> PAGE_SHIFT);
if (r) {
DRM_ERROR("Failed initializing GTT heap.\n");
- r2 = radeon_bo_reserve(rdev->stollen_vga_memory, false);
- if (likely(r2 == 0)) {
- radeon_bo_unpin(rdev->stollen_vga_memory);
- radeon_bo_unreserve(rdev->stollen_vga_memory);
- }
- radeon_bo_unref(&rdev->stollen_vga_memory);
return r;
}
DRM_INFO("radeon: %uM of GTT memory ready.\n",
@@ -764,12 +754,6 @@ int radeon_ttm_init(struct radeon_device *rdev)
r = radeon_ttm_debugfs_init(rdev);
if (r) {
DRM_ERROR("Failed to init debugfs\n");
- r2 = radeon_bo_reserve(rdev->stollen_vga_memory, false);
- if (likely(r2 == 0)) {
- radeon_bo_unpin(rdev->stollen_vga_memory);
- radeon_bo_unreserve(rdev->stollen_vga_memory);
- }
- radeon_bo_unref(&rdev->stollen_vga_memory);
return r;
}
return 0;
@@ -812,7 +796,7 @@ void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, u64 size)
man->size = size >> PAGE_SHIFT;
}
-#ifdef DUMBBELL_WIP
+#ifdef FREEBSD_WIP
static struct vm_operations_struct radeon_ttm_vm_ops;
static const struct vm_operations_struct *ttm_vm_ops = NULL;
@@ -860,7 +844,7 @@ int radeon_mmap(struct file *filp, struct vm_area_struct *vma)
vma->vm_ops = &radeon_ttm_vm_ops;
return 0;
}
-#endif /* DUMBBELL_WIP */
+#endif /* FREEBSD_WIP */
#define RADEON_DEBUGFS_MEM_TYPES 2
diff --git a/sys/dev/drm2/radeon/rs400.c b/sys/dev/drm2/radeon/rs400.c
index f9d638d..714c36b 100644
--- a/sys/dev/drm2/radeon/rs400.c
+++ b/sys/dev/drm2/radeon/rs400.c
@@ -173,12 +173,9 @@ int rs400_gart_enable(struct radeon_device *rdev)
WREG32_MC(RS480_AGP_MODE_CNTL,
(1 << RS480_REQ_TYPE_SNOOP_SHIFT) | RS480_REQ_TYPE_SNOOP_DIS);
/* Disable AGP mode */
+ /* FIXME: according to doc we should set HIDE_MMCFG_BAR=0,
+ * AGPMODE30=0 & AGP30ENHANCED=0 in NB_CNTL */
if ((rdev->family == CHIP_RS690) || (rdev->family == CHIP_RS740)) {
- tmp = RREG32_MC(RS690_MC_NB_CNTL);
- tmp &= ~(RS690_HIDE_MMCFG_BAR |
- RS690_AGPMODE30 |
- RS690_AGP30ENHANCED);
- WREG32_MC(RS690_MC_NB_CNTL, tmp);
WREG32_MC(RS480_MC_MISC_CNTL,
(RS480_GART_INDEX_REG_EN | RS690_BLOCK_GFX_D3_EN));
} else {
@@ -223,7 +220,7 @@ int rs400_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
return -EINVAL;
}
- entry = (lower_32_bits(addr) & 0xfffff000) |
+ entry = (lower_32_bits(addr) & ~PAGE_MASK) |
((upper_32_bits(addr) & 0xff) << 4) |
RS400_PTE_WRITEABLE | RS400_PTE_READABLE;
entry = cpu_to_le32(entry);
diff --git a/sys/dev/drm2/radeon/rs600.c b/sys/dev/drm2/radeon/rs600.c
index 11edbdf..73d0d0c 100644
--- a/sys/dev/drm2/radeon/rs600.c
+++ b/sys/dev/drm2/radeon/rs600.c
@@ -48,6 +48,9 @@ __FBSDID("$FreeBSD$");
#include "rs600_reg_safe.h"
static void rs600_gpu_init(struct radeon_device *rdev);
+#ifdef FREEBSD_WIP /* FreeBSD: to please GCC 4.2. */
+int rs600_mc_wait_for_idle(struct radeon_device *rdev);
+#endif
static const u32 crtc_offsets[2] =
{
@@ -55,23 +58,59 @@ static const u32 crtc_offsets[2] =
AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL
};
+static bool avivo_is_in_vblank(struct radeon_device *rdev, int crtc)
+{
+ if (RREG32(AVIVO_D1CRTC_STATUS + crtc_offsets[crtc]) & AVIVO_D1CRTC_V_BLANK)
+ return true;
+ else
+ return false;
+}
+
+static bool avivo_is_counter_moving(struct radeon_device *rdev, int crtc)
+{
+ u32 pos1, pos2;
+
+ pos1 = RREG32(AVIVO_D1CRTC_STATUS_POSITION + crtc_offsets[crtc]);
+ pos2 = RREG32(AVIVO_D1CRTC_STATUS_POSITION + crtc_offsets[crtc]);
+
+ if (pos1 != pos2)
+ return true;
+ else
+ return false;
+}
+
+/**
+ * avivo_wait_for_vblank - vblank wait asic callback.
+ *
+ * @rdev: radeon_device pointer
+ * @crtc: crtc to wait for vblank on
+ *
+ * Wait for vblank on the requested crtc (r5xx-r7xx).
+ */
void avivo_wait_for_vblank(struct radeon_device *rdev, int crtc)
{
- int i;
+ unsigned i = 0;
if (crtc >= rdev->num_crtc)
return;
- if (RREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[crtc]) & AVIVO_CRTC_EN) {
- for (i = 0; i < rdev->usec_timeout; i++) {
- if (!(RREG32(AVIVO_D1CRTC_STATUS + crtc_offsets[crtc]) & AVIVO_D1CRTC_V_BLANK))
+ if (!(RREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[crtc]) & AVIVO_CRTC_EN))
+ return;
+
+ /* depending on when we hit vblank, we may be close to active; if so,
+ * wait for another frame.
+ */
+ while (avivo_is_in_vblank(rdev, crtc)) {
+ if (i++ % 100 == 0) {
+ if (!avivo_is_counter_moving(rdev, crtc))
break;
- DRM_UDELAY(1);
}
- for (i = 0; i < rdev->usec_timeout; i++) {
- if (RREG32(AVIVO_D1CRTC_STATUS + crtc_offsets[crtc]) & AVIVO_D1CRTC_V_BLANK)
+ }
+
+ while (!avivo_is_in_vblank(rdev, crtc)) {
+ if (i++ % 100 == 0) {
+ if (!avivo_is_counter_moving(rdev, crtc))
break;
- DRM_UDELAY(1);
}
}
}
@@ -108,7 +147,7 @@ u32 rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
for (i = 0; i < rdev->usec_timeout; i++) {
if (RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING)
break;
- DRM_UDELAY(1);
+ udelay(1);
}
DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
@@ -137,7 +176,7 @@ void rs600_pm_misc(struct radeon_device *rdev)
tmp &= ~(voltage->gpio.mask);
WREG32(voltage->gpio.reg, tmp);
if (voltage->delay)
- DRM_UDELAY(voltage->delay);
+ udelay(voltage->delay);
} else {
tmp = RREG32(voltage->gpio.reg);
if (voltage->active_high)
@@ -146,7 +185,7 @@ void rs600_pm_misc(struct radeon_device *rdev)
tmp |= voltage->gpio.mask;
WREG32(voltage->gpio.reg, tmp);
if (voltage->delay)
- DRM_UDELAY(voltage->delay);
+ udelay(voltage->delay);
}
} else if (voltage->type == VOLTAGE_VDDC)
radeon_atom_set_voltage(rdev, voltage->vddc_id, SET_VOLTAGE_TYPE_ASIC_VDDC);
@@ -376,30 +415,30 @@ int rs600_asic_reset(struct radeon_device *rdev)
pci_save_state(device_get_parent(rdev->dev));
/* disable bus mastering */
pci_disable_busmaster(rdev->dev);
- DRM_MDELAY(1);
+ mdelay(1);
/* reset GA+VAP */
WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_VAP(1) |
S_0000F0_SOFT_RESET_GA(1));
RREG32(R_0000F0_RBBM_SOFT_RESET);
- DRM_MDELAY(500);
+ mdelay(500);
WREG32(R_0000F0_RBBM_SOFT_RESET, 0);
- DRM_MDELAY(1);
+ mdelay(1);
status = RREG32(R_000E40_RBBM_STATUS);
dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status);
/* reset CP */
WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_CP(1));
RREG32(R_0000F0_RBBM_SOFT_RESET);
- DRM_MDELAY(500);
+ mdelay(500);
WREG32(R_0000F0_RBBM_SOFT_RESET, 0);
- DRM_MDELAY(1);
+ mdelay(1);
status = RREG32(R_000E40_RBBM_STATUS);
dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status);
/* reset MC */
WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_MC(1));
RREG32(R_0000F0_RBBM_SOFT_RESET);
- DRM_MDELAY(500);
+ mdelay(500);
WREG32(R_0000F0_RBBM_SOFT_RESET, 0);
- DRM_MDELAY(1);
+ mdelay(1);
status = RREG32(R_000E40_RBBM_STATUS);
dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status);
/* restore PCI & busmastering */
@@ -659,7 +698,7 @@ void rs600_irq_disable(struct radeon_device *rdev)
WREG32(R_000040_GEN_INT_CNTL, 0);
WREG32(R_006540_DxMODE_INT_MASK, 0);
/* Wait and acknowledge irq */
- DRM_MDELAY(1);
+ mdelay(1);
rs600_irq_ack(rdev);
}
@@ -751,7 +790,7 @@ int rs600_mc_wait_for_idle(struct radeon_device *rdev)
for (i = 0; i < rdev->usec_timeout; i++) {
if (G_000000_MC_IDLE(RREG32_MC(R_000000_MC_STATUS)))
return 0;
- DRM_UDELAY(1);
+ udelay(1);
}
return -1;
}
@@ -835,7 +874,7 @@ static void rs600_debugfs(struct radeon_device *rdev)
void rs600_set_safe_registers(struct radeon_device *rdev)
{
rdev->config.r300.reg_safe_bm = rs600_reg_safe_bm;
- rdev->config.r300.reg_safe_bm_size = DRM_ARRAY_SIZE(rs600_reg_safe_bm);
+ rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(rs600_reg_safe_bm);
}
static void rs600_mc_program(struct radeon_device *rdev)
diff --git a/sys/dev/drm2/radeon/rs690.c b/sys/dev/drm2/radeon/rs690.c
index dbf64d9..2ff0485 100644
--- a/sys/dev/drm2/radeon/rs690.c
+++ b/sys/dev/drm2/radeon/rs690.c
@@ -45,7 +45,7 @@ int rs690_mc_wait_for_idle(struct radeon_device *rdev)
tmp = RREG32_MC(R_000090_MC_SYSTEM_STATUS);
if (G_000090_MC_SYSTEM_IDLE(tmp))
return 0;
- DRM_UDELAY(1);
+ udelay(1);
}
return -1;
}
diff --git a/sys/dev/drm2/radeon/rv515.c b/sys/dev/drm2/radeon/rv515.c
index ba292de..e41ba9a 100644
--- a/sys/dev/drm2/radeon/rv515.c
+++ b/sys/dev/drm2/radeon/rv515.c
@@ -40,6 +40,9 @@ __FBSDID("$FreeBSD$");
static int rv515_debugfs_pipes_info_init(struct radeon_device *rdev);
static int rv515_debugfs_ga_info_init(struct radeon_device *rdev);
static void rv515_gpu_init(struct radeon_device *rdev);
+#ifdef FREEBSD_WIP /* FreeBSD: to please GCC 4.2. */
+int rv515_mc_wait_for_idle(struct radeon_device *rdev);
+#endif
static const u32 crtc_offsets[2] =
{
@@ -304,16 +307,27 @@ void rv515_mc_stop(struct radeon_device *rdev, struct rv515_mc_save *save)
tmp = RREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[i]);
if (!(tmp & AVIVO_CRTC_DISP_READ_REQUEST_DISABLE)) {
radeon_wait_for_vblank(rdev, i);
+ WREG32(AVIVO_D1CRTC_UPDATE_LOCK + crtc_offsets[i], 1);
tmp |= AVIVO_CRTC_DISP_READ_REQUEST_DISABLE;
WREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[i], tmp);
+ WREG32(AVIVO_D1CRTC_UPDATE_LOCK + crtc_offsets[i], 0);
}
/* wait for the next frame */
frame_count = radeon_get_vblank_counter(rdev, i);
for (j = 0; j < rdev->usec_timeout; j++) {
if (radeon_get_vblank_counter(rdev, i) != frame_count)
break;
- DRM_UDELAY(1);
+ udelay(1);
}
+
+ /* XXX this is a hack to avoid strange behavior with EFI on certain systems */
+ WREG32(AVIVO_D1CRTC_UPDATE_LOCK + crtc_offsets[i], 1);
+ tmp = RREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[i]);
+ tmp &= ~AVIVO_CRTC_EN;
+ WREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[i], tmp);
+ WREG32(AVIVO_D1CRTC_UPDATE_LOCK + crtc_offsets[i], 0);
+ save->crtc_enabled[i] = false;
+ /* ***** */
} else {
save->crtc_enabled[i] = false;
}
@@ -338,7 +352,23 @@ void rv515_mc_stop(struct radeon_device *rdev, struct rv515_mc_save *save)
}
}
/* wait for the MC to settle */
- DRM_UDELAY(100);
+ udelay(100);
+
+ /* lock double buffered regs */
+ for (i = 0; i < rdev->num_crtc; i++) {
+ if (save->crtc_enabled[i]) {
+ tmp = RREG32(AVIVO_D1GRPH_UPDATE + crtc_offsets[i]);
+ if (!(tmp & AVIVO_D1GRPH_UPDATE_LOCK)) {
+ tmp |= AVIVO_D1GRPH_UPDATE_LOCK;
+ WREG32(AVIVO_D1GRPH_UPDATE + crtc_offsets[i], tmp);
+ }
+ tmp = RREG32(AVIVO_D1MODE_MASTER_UPDATE_LOCK + crtc_offsets[i]);
+ if (!(tmp & 1)) {
+ tmp |= 1;
+ WREG32(AVIVO_D1MODE_MASTER_UPDATE_LOCK + crtc_offsets[i], tmp);
+ }
+ }
+ }
}
void rv515_mc_resume(struct radeon_device *rdev, struct rv515_mc_save *save)
@@ -349,7 +379,7 @@ void rv515_mc_resume(struct radeon_device *rdev, struct rv515_mc_save *save)
/* update crtc base addresses */
for (i = 0; i < rdev->num_crtc; i++) {
if (rdev->family >= CHIP_RV770) {
- if (i == 1) {
+ if (i == 0) {
WREG32(R700_D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH,
upper_32_bits(rdev->mc.vram_start));
WREG32(R700_D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH,
@@ -368,6 +398,33 @@ void rv515_mc_resume(struct radeon_device *rdev, struct rv515_mc_save *save)
}
WREG32(R_000310_VGA_MEMORY_BASE_ADDRESS, (u32)rdev->mc.vram_start);
+ /* unlock regs and wait for update */
+ for (i = 0; i < rdev->num_crtc; i++) {
+ if (save->crtc_enabled[i]) {
+ tmp = RREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + crtc_offsets[i]);
+ if ((tmp & 0x3) != 0) {
+ tmp &= ~0x3;
+ WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + crtc_offsets[i], tmp);
+ }
+ tmp = RREG32(AVIVO_D1GRPH_UPDATE + crtc_offsets[i]);
+ if (tmp & AVIVO_D1GRPH_UPDATE_LOCK) {
+ tmp &= ~AVIVO_D1GRPH_UPDATE_LOCK;
+ WREG32(AVIVO_D1GRPH_UPDATE + crtc_offsets[i], tmp);
+ }
+ tmp = RREG32(AVIVO_D1MODE_MASTER_UPDATE_LOCK + crtc_offsets[i]);
+ if (tmp & 1) {
+ tmp &= ~1;
+ WREG32(AVIVO_D1MODE_MASTER_UPDATE_LOCK + crtc_offsets[i], tmp);
+ }
+ for (j = 0; j < rdev->usec_timeout; j++) {
+ tmp = RREG32(AVIVO_D1GRPH_UPDATE + crtc_offsets[i]);
+ if ((tmp & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING) == 0)
+ break;
+ udelay(1);
+ }
+ }
+ }
+
if (rdev->family >= CHIP_R600) {
/* unblackout the MC */
if (rdev->family >= CHIP_RV770)
@@ -393,13 +450,13 @@ void rv515_mc_resume(struct radeon_device *rdev, struct rv515_mc_save *save)
for (j = 0; j < rdev->usec_timeout; j++) {
if (radeon_get_vblank_counter(rdev, i) != frame_count)
break;
- DRM_UDELAY(1);
+ udelay(1);
}
}
}
/* Unlock vga access */
WREG32(R_000328_VGA_HDP_CONTROL, save->vga_hdp_control);
- DRM_MDELAY(1);
+ mdelay(1);
WREG32(R_000300_VGA_RENDER_CONTROL, save->vga_render_control);
}
@@ -540,7 +597,7 @@ int rv515_suspend(struct radeon_device *rdev)
void rv515_set_safe_registers(struct radeon_device *rdev)
{
rdev->config.r300.reg_safe_bm = rv515_reg_safe_bm;
- rdev->config.r300.reg_safe_bm_size = DRM_ARRAY_SIZE(rv515_reg_safe_bm);
+ rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(rv515_reg_safe_bm);
}
void rv515_fini(struct radeon_device *rdev)
diff --git a/sys/dev/drm2/radeon/rv770.c b/sys/dev/drm2/radeon/rv770.c
index 549ed90..4d6b67b 100644
--- a/sys/dev/drm2/radeon/rv770.c
+++ b/sys/dev/drm2/radeon/rv770.c
@@ -41,6 +41,9 @@ __FBSDID("$FreeBSD$");
#define R700_PM4_UCODE_SIZE 1360
static void rv770_gpu_init(struct radeon_device *rdev);
+#ifdef FREEBSD_WIP /* FreeBSD: to please GCC 4.2. */
+void rv770_fini(struct radeon_device *rdev);
+#endif
static void rv770_pcie_gen2_enable(struct radeon_device *rdev);
u32 rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
@@ -70,7 +73,7 @@ u32 rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
for (i = 0; i < rdev->usec_timeout; i++) {
if (RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING)
break;
- DRM_UDELAY(1);
+ udelay(1);
}
DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
@@ -337,7 +340,7 @@ static int rv770_cp_load_microcode(struct radeon_device *rdev)
/* Reset cp */
WREG32(GRBM_SOFT_RESET, SOFT_RESET_CP);
RREG32(GRBM_SOFT_RESET);
- DRM_MDELAY(15);
+ mdelay(15);
WREG32(GRBM_SOFT_RESET, 0);
fw_data = (const __be32 *)rdev->pfp_fw->data;
diff --git a/sys/dev/drm2/radeon/si.c b/sys/dev/drm2/radeon/si.c
index 0fdefd2..8e18d8d 100644
--- a/sys/dev/drm2/radeon/si.c
+++ b/sys/dev/drm2/radeon/si.c
@@ -39,6 +39,33 @@ __FBSDID("$FreeBSD$");
#define SI_RLC_UCODE_SIZE 2048
#define SI_MC_UCODE_SIZE 7769
+#ifdef __linux__
+MODULE_FIRMWARE("radeon/TAHITI_pfp.bin");
+MODULE_FIRMWARE("radeon/TAHITI_me.bin");
+MODULE_FIRMWARE("radeon/TAHITI_ce.bin");
+MODULE_FIRMWARE("radeon/TAHITI_mc.bin");
+MODULE_FIRMWARE("radeon/TAHITI_rlc.bin");
+MODULE_FIRMWARE("radeon/PITCAIRN_pfp.bin");
+MODULE_FIRMWARE("radeon/PITCAIRN_me.bin");
+MODULE_FIRMWARE("radeon/PITCAIRN_ce.bin");
+MODULE_FIRMWARE("radeon/PITCAIRN_mc.bin");
+MODULE_FIRMWARE("radeon/PITCAIRN_rlc.bin");
+MODULE_FIRMWARE("radeon/VERDE_pfp.bin");
+MODULE_FIRMWARE("radeon/VERDE_me.bin");
+MODULE_FIRMWARE("radeon/VERDE_ce.bin");
+MODULE_FIRMWARE("radeon/VERDE_mc.bin");
+MODULE_FIRMWARE("radeon/VERDE_rlc.bin");
+#endif
+
+#ifdef FREEBSD_WIP /* FreeBSD: to please GCC 4.2. */
+extern int r600_ih_ring_alloc(struct radeon_device *rdev);
+extern void r600_ih_ring_fini(struct radeon_device *rdev);
+extern void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev);
+extern void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save);
+extern void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save);
+extern u32 evergreen_get_number_of_dram_channels(struct radeon_device *rdev);
+#endif
+
/* get temperature in millidegrees */
int si_get_temp(struct radeon_device *rdev)
{
@@ -238,12 +265,12 @@ static int si_mc_load_microcode(struct radeon_device *rdev)
for (i = 0; i < rdev->usec_timeout; i++) {
if (RREG32(MC_SEQ_TRAIN_WAKEUP_CNTL) & TRAIN_DONE_D0)
break;
- DRM_UDELAY(1);
+ udelay(1);
}
for (i = 0; i < rdev->usec_timeout; i++) {
if (RREG32(MC_SEQ_TRAIN_WAKEUP_CNTL) & TRAIN_DONE_D1)
break;
- DRM_UDELAY(1);
+ udelay(1);
}
if (running)
@@ -1399,7 +1426,7 @@ static void si_select_se_sh(struct radeon_device *rdev,
u32 data = INSTANCE_BROADCAST_WRITES;
if ((se_num == 0xffffffff) && (sh_num == 0xffffffff))
- data = SH_BROADCAST_WRITES | SE_BROADCAST_WRITES;
+ data |= SH_BROADCAST_WRITES | SE_BROADCAST_WRITES;
else if (se_num == 0xffffffff)
data |= SE_BROADCAST_WRITES | SH_INDEX(sh_num);
else if (sh_num == 0xffffffff)
@@ -1684,6 +1711,7 @@ static void si_gpu_init(struct radeon_device *rdev)
WREG32(GB_ADDR_CONFIG, gb_addr_config);
WREG32(DMIF_ADDR_CONFIG, gb_addr_config);
+ WREG32(DMIF_ADDR_CALC, gb_addr_config);
WREG32(HDP_ADDR_CONFIG, gb_addr_config);
WREG32(DMA_TILING_CONFIG + DMA0_REGISTER_OFFSET, gb_addr_config);
WREG32(DMA_TILING_CONFIG + DMA1_REGISTER_OFFSET, gb_addr_config);
@@ -1747,7 +1775,7 @@ static void si_gpu_init(struct radeon_device *rdev)
WREG32(PA_CL_ENHANCE, CLIP_VTX_REORDER_ENA | NUM_CLIP_SEQ(3));
- DRM_UDELAY(50);
+ udelay(50);
}
/*
@@ -1867,7 +1895,7 @@ static void si_cp_enable(struct radeon_device *rdev, bool enable)
rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX].ready = false;
rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX].ready = false;
}
- DRM_UDELAY(50);
+ udelay(50);
}
static int si_cp_load_microcode(struct radeon_device *rdev)
@@ -2009,7 +2037,7 @@ static int si_cp_resume(struct radeon_device *rdev)
SOFT_RESET_SPI |
SOFT_RESET_SX));
RREG32(GRBM_SOFT_RESET);
- DRM_MDELAY(15);
+ mdelay(15);
WREG32(GRBM_SOFT_RESET, 0);
RREG32(GRBM_SOFT_RESET);
@@ -2048,7 +2076,7 @@ static int si_cp_resume(struct radeon_device *rdev)
WREG32(SCRATCH_UMSK, 0);
}
- DRM_MDELAY(1);
+ mdelay(1);
WREG32(CP_RB0_CNTL, tmp);
WREG32(CP_RB0_BASE, ring->gpu_addr >> 8);
@@ -2074,7 +2102,7 @@ static int si_cp_resume(struct radeon_device *rdev)
WREG32(CP_RB1_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP1_RPTR_OFFSET) & 0xFFFFFFFC);
WREG32(CP_RB1_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP1_RPTR_OFFSET) & 0xFF);
- DRM_MDELAY(1);
+ mdelay(1);
WREG32(CP_RB1_CNTL, tmp);
WREG32(CP_RB1_BASE, ring->gpu_addr >> 8);
@@ -2100,7 +2128,7 @@ static int si_cp_resume(struct radeon_device *rdev)
WREG32(CP_RB2_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP2_RPTR_OFFSET) & 0xFFFFFFFC);
WREG32(CP_RB2_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP2_RPTR_OFFSET) & 0xFF);
- DRM_MDELAY(1);
+ mdelay(1);
WREG32(CP_RB2_CNTL, tmp);
WREG32(CP_RB2_BASE, ring->gpu_addr >> 8);
@@ -2190,7 +2218,7 @@ static void si_gpu_soft_reset_gfx(struct radeon_device *rdev)
dev_info(rdev->dev, " GRBM_SOFT_RESET=0x%08X\n", grbm_reset);
WREG32(GRBM_SOFT_RESET, grbm_reset);
(void)RREG32(GRBM_SOFT_RESET);
- DRM_UDELAY(50);
+ udelay(50);
WREG32(GRBM_SOFT_RESET, 0);
(void)RREG32(GRBM_SOFT_RESET);
@@ -2229,7 +2257,7 @@ static void si_gpu_soft_reset_dma(struct radeon_device *rdev)
/* Reset dma */
WREG32(SRBM_SOFT_RESET, SOFT_RESET_DMA | SOFT_RESET_DMA1);
RREG32(SRBM_SOFT_RESET);
- DRM_UDELAY(50);
+ udelay(50);
WREG32(SRBM_SOFT_RESET, 0);
dev_info(rdev->dev, " DMA_STATUS_REG = 0x%08X\n",
@@ -2268,7 +2296,7 @@ static int si_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
si_gpu_soft_reset_dma(rdev);
/* Wait a little for things to settle down */
- DRM_UDELAY(50);
+ udelay(50);
evergreen_mc_resume(rdev, &save);
return 0;
@@ -3645,7 +3673,7 @@ static void si_irq_disable(struct radeon_device *rdev)
{
si_disable_interrupts(rdev);
/* Wait and acknowledge irq */
- DRM_MDELAY(1);
+ mdelay(1);
si_irq_ack(rdev);
si_disable_interrupt_state(rdev);
}
@@ -4257,6 +4285,7 @@ int si_resume(struct radeon_device *rdev)
int si_suspend(struct radeon_device *rdev)
{
+ radeon_vm_manager_fini(rdev);
si_cp_enable(rdev, false);
cayman_dma_stop(rdev);
si_irq_suspend(rdev);
diff --git a/sys/dev/drm2/radeon/si_blit_shaders.c b/sys/dev/drm2/radeon/si_blit_shaders.c
index dc31fe3..483a93d 100644
--- a/sys/dev/drm2/radeon/si_blit_shaders.c
+++ b/sys/dev/drm2/radeon/si_blit_shaders.c
@@ -251,4 +251,4 @@ const u32 si_default_state[] =
0x00000010, /* */
};
-const u32 si_default_size = DRM_ARRAY_SIZE(si_default_state);
+const u32 si_default_size = ARRAY_SIZE(si_default_state);
diff --git a/sys/dev/drm2/radeon/sid.h b/sys/dev/drm2/radeon/sid.h
index 7aa21c1..eaf95fb 100644
--- a/sys/dev/drm2/radeon/sid.h
+++ b/sys/dev/drm2/radeon/sid.h
@@ -63,6 +63,8 @@ __FBSDID("$FreeBSD$");
#define DMIF_ADDR_CONFIG 0xBD4
+#define DMIF_ADDR_CALC 0xC00
+
#define SRBM_STATUS 0xE50
#define SRBM_SOFT_RESET 0x0E60
diff --git a/sys/dev/drm2/ttm/ttm_bo.c b/sys/dev/drm2/ttm/ttm_bo.c
index d87940c..4340ed7 100644
--- a/sys/dev/drm2/ttm/ttm_bo.c
+++ b/sys/dev/drm2/ttm/ttm_bo.c
@@ -147,7 +147,7 @@ ttm_bo_wait_unreserved_locked(struct ttm_buffer_object *bo, bool interruptible)
}
while (ttm_bo_is_reserved(bo)) {
ret = -msleep(bo, &bo->glob->lru_lock, flags, wmsg, 0);
- if (ret == -EINTR)
+ if (ret == -EINTR || ret == -ERESTART)
ret = -ERESTARTSYS;
if (ret != 0)
break;
@@ -815,7 +815,7 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo, bool interruptible,
mtx_unlock(&bdev->fence_lock);
if (unlikely(ret != 0)) {
- if (ret != -ERESTART) {
+ if (ret != -ERESTARTSYS) {
printf("[TTM] Failed to expire sync object before buffer eviction\n");
}
goto out;
@@ -836,7 +836,7 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo, bool interruptible,
ret = ttm_bo_mem_space(bo, &placement, &evict_mem, interruptible,
no_wait_gpu);
if (ret) {
- if (ret != -ERESTART) {
+ if (ret != -ERESTARTSYS) {
printf("[TTM] Failed to find memory space for buffer 0x%p eviction\n",
bo);
ttm_bo_mem_space_debug(bo, &placement);
@@ -847,7 +847,7 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo, bool interruptible,
ret = ttm_bo_handle_move_mem(bo, &evict_mem, true, interruptible,
no_wait_gpu);
if (ret) {
- if (ret != -ERESTART)
+ if (ret != -ERESTARTSYS)
printf("[TTM] Buffer eviction failed\n");
ttm_bo_mem_put(bo, &evict_mem);
goto out;
@@ -1095,10 +1095,10 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo,
mem->placement = cur_flags;
return 0;
}
- if (ret == -ERESTART)
+ if (ret == -ERESTARTSYS)
has_erestartsys = true;
}
- ret = (has_erestartsys) ? -ERESTART : -ENOMEM;
+ ret = (has_erestartsys) ? -ERESTARTSYS : -ENOMEM;
return ret;
}
diff --git a/sys/dev/drm2/ttm/ttm_bo_util.c b/sys/dev/drm2/ttm/ttm_bo_util.c
index 177cc00..fbbaaf2 100644
--- a/sys/dev/drm2/ttm/ttm_bo_util.c
+++ b/sys/dev/drm2/ttm/ttm_bo_util.c
@@ -439,7 +439,7 @@ ttm_buffer_object_transfer(struct ttm_buffer_object *bo,
vm_memattr_t
ttm_io_prot(uint32_t caching_flags)
{
-#if defined(__i386__) || defined(__amd64__)
+#if defined(__i386__) || defined(__amd64__) || defined(__powerpc__)
if (caching_flags & TTM_PL_FLAG_WC)
return (VM_MEMATTR_WRITE_COMBINING);
else
diff --git a/sys/dev/drm2/ttm/ttm_bo_vm.c b/sys/dev/drm2/ttm/ttm_bo_vm.c
index 7aa1ac0..5d72d97 100644
--- a/sys/dev/drm2/ttm/ttm_bo_vm.c
+++ b/sys/dev/drm2/ttm/ttm_bo_vm.c
@@ -140,7 +140,7 @@ reserve:
case 0:
break;
case -EBUSY:
- case -ERESTART:
+ case -ERESTARTSYS:
case -EINTR:
kern_yield(0);
goto reserve;
@@ -339,22 +339,22 @@ ttm_bo_mmap_single(struct ttm_bo_device *bdev, vm_ooffset_t *offset, vm_size_t s
if (unlikely(bo == NULL)) {
printf("[TTM] Could not find buffer object to map\n");
- return (EINVAL);
+ return (-EINVAL);
}
driver = bo->bdev->driver;
if (unlikely(!driver->verify_access)) {
- ret = EPERM;
+ ret = -EPERM;
goto out_unref;
}
- ret = -driver->verify_access(bo);
+ ret = driver->verify_access(bo);
if (unlikely(ret != 0))
goto out_unref;
vm_obj = cdev_pager_allocate(bo, OBJT_MGTDEVICE, &ttm_pager_ops,
size, nprot, 0, curthread->td_ucred);
if (vm_obj == NULL) {
- ret = EINVAL;
+ ret = -EINVAL;
goto out_unref;
}
/*
diff --git a/sys/dev/drm2/ttm/ttm_lock.c b/sys/dev/drm2/ttm/ttm_lock.c
index ae06565..870877e 100644
--- a/sys/dev/drm2/ttm/ttm_lock.c
+++ b/sys/dev/drm2/ttm/ttm_lock.c
@@ -106,13 +106,13 @@ ttm_read_lock(struct ttm_lock *lock, bool interruptible)
}
mtx_lock(&lock->lock);
while (!__ttm_read_lock(lock)) {
- ret = msleep(lock, &lock->lock, flags, wmsg, 0);
- if (ret == EINTR)
- ret = ERESTARTSYS;
+ ret = -msleep(lock, &lock->lock, flags, wmsg, 0);
+ if (ret == -EINTR || ret == -ERESTART)
+ ret = -ERESTARTSYS;
if (ret != 0)
break;
}
- return (-ret);
+ return (ret);
}
static bool __ttm_read_trylock(struct ttm_lock *lock, bool *locked)
@@ -152,9 +152,9 @@ int ttm_read_trylock(struct ttm_lock *lock, bool interruptible)
}
mtx_lock(&lock->lock);
while (!__ttm_read_trylock(lock, &locked)) {
- ret = msleep(lock, &lock->lock, flags, wmsg, 0);
- if (ret == EINTR)
- ret = ERESTARTSYS;
+ ret = -msleep(lock, &lock->lock, flags, wmsg, 0);
+ if (ret == -EINTR || ret == -ERESTART)
+ ret = -ERESTARTSYS;
if (ret != 0)
break;
}
@@ -207,9 +207,9 @@ ttm_write_lock(struct ttm_lock *lock, bool interruptible)
mtx_lock(&lock->lock);
/* XXXKIB: linux uses __ttm_read_lock for uninterruptible sleeps */
while (!__ttm_write_lock(lock)) {
- ret = msleep(lock, &lock->lock, flags, wmsg, 0);
- if (ret == EINTR)
- ret = ERESTARTSYS;
+ ret = -msleep(lock, &lock->lock, flags, wmsg, 0);
+ if (ret == -EINTR || ret == -ERESTART)
+ ret = -ERESTARTSYS;
if (interruptible && ret != 0) {
lock->flags &= ~TTM_WRITE_LOCK_PENDING;
wakeup(lock);
@@ -218,7 +218,7 @@ ttm_write_lock(struct ttm_lock *lock, bool interruptible)
}
mtx_unlock(&lock->lock);
- return (-ret);
+ return (ret);
}
void ttm_write_lock_downgrade(struct ttm_lock *lock)
@@ -285,9 +285,9 @@ int ttm_vt_lock(struct ttm_lock *lock,
}
mtx_lock(&lock->lock);
while (!__ttm_vt_lock(lock)) {
- ret = msleep(lock, &lock->lock, flags, wmsg, 0);
- if (ret == EINTR)
- ret = ERESTARTSYS;
+ ret = -msleep(lock, &lock->lock, flags, wmsg, 0);
+ if (ret == -EINTR || ret == -ERESTART)
+ ret = -ERESTARTSYS;
if (interruptible && ret != 0) {
lock->flags &= ~TTM_VT_LOCK_PENDING;
wakeup(lock);
@@ -308,7 +308,7 @@ int ttm_vt_lock(struct ttm_lock *lock,
else
lock->vt_holder = tfile;
- return (-ret);
+ return (ret);
}
int ttm_vt_unlock(struct ttm_lock *lock)
diff --git a/sys/modules/Makefile b/sys/modules/Makefile
index cbbf239..f903391 100644
--- a/sys/modules/Makefile
+++ b/sys/modules/Makefile
@@ -866,6 +866,8 @@ _wi= wi
.endif
.if ${MACHINE_ARCH} == "powerpc64"
+_drm2= drm2
+_i2c= i2c
.if ${MK_ZFS} != "no" || defined(ALL_MODULES)
_zfs= zfs
.endif
diff --git a/sys/modules/drm2/Makefile b/sys/modules/drm2/Makefile
index abbe80f..e4e19fb 100644
--- a/sys/modules/drm2/Makefile
+++ b/sys/modules/drm2/Makefile
@@ -20,6 +20,13 @@ _radeonkmsfw= radeonkmsfw
. endif
.endif
+.if ${MACHINE_CPUARCH} == "powerpc"
+_radeonkms= radeonkms
+. if ${MK_SOURCELESS_UCODE} != "no"
+_radeonkmsfw= radeonkmsfw
+. endif
+.endif
+
SUBDIR = \
drm2 \
${_i915kms} \
diff --git a/sys/modules/drm2/drm2/Makefile b/sys/modules/drm2/drm2/Makefile
index 3bbccb5..35bee29 100644
--- a/sys/modules/drm2/drm2/Makefile
+++ b/sys/modules/drm2/drm2/Makefile
@@ -13,7 +13,6 @@ SRCS = \
drm_dma.c \
drm_dp_helper.c \
drm_dp_iic_helper.c \
- drm_drawable.c \
drm_drv.c \
drm_edid.c \
drm_fb_helper.c \
@@ -31,10 +30,10 @@ SRCS = \
drm_modes.c \
drm_pci.c \
drm_scatter.c \
- drm_sman.c \
drm_stub.c \
drm_sysctl.c \
drm_vm.c \
+ drm_os_freebsd.c \
ttm_agp_backend.c \
ttm_lock.c \
ttm_object.c \
@@ -49,11 +48,16 @@ SRCS = \
ati_pcigart.c
#ttm_page_alloc_dma.c
-.if ${MACHINE_CPUARCH} == "amd64"
+.if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_ARCH} == "powerpc64"
SRCS += drm_ioc32.c
.endif
SRCS +=device_if.h bus_if.h pci_if.h device_if.h iicbus_if.h opt_drm.h \
opt_vm.h opt_compat.h opt_syscons.h
+
+.if ${MACHINE_CPUARCH} == "powerpc"
+CWARNFLAGS+=-Wno-cast-qual
+.endif
+
.include <bsd.kmod.mk>
diff --git a/sys/modules/drm2/radeonkms/Makefile b/sys/modules/drm2/radeonkms/Makefile
index 6315a85..9c9695f 100644
--- a/sys/modules/drm2/radeonkms/Makefile
+++ b/sys/modules/drm2/radeonkms/Makefile
@@ -17,11 +17,11 @@ SRCS = \
evergreen_reg_safe.h \
cayman_reg_safe.h
SRCS += \
- radeon_acpi.c \
+ ${radeon_acpi} \
radeon_agp.c \
radeon_asic.c \
radeon_atombios.c \
- radeon_atpx_handler.c \
+ ${radeon_atpx_handler} \
radeon_benchmark.c \
radeon_bios.c \
radeon_clocks.c \
@@ -39,6 +39,7 @@ SRCS += \
radeon_gart.c \
radeon_gem.c \
radeon_i2c.c \
+ ${radeon_ioc32} \
radeon_irq.c \
radeon_irq_kms.c \
radeon_kms.c \
@@ -88,8 +89,13 @@ SRCS += \
si.c \
si_blit_shaders.c
-.if ${MACHINE_CPUARCH} == "amd64"
-SRCS += radeon_ioc32.c
+.if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386"
+radeon_acpi= radeon_acpi.c
+#radeon_atpx_handler= radeon_atpx_handler.c
+.endif
+
+.if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_ARCH} == "powerpc64"
+radeon_ioc32= radeon_ioc32.c
.endif
#radeon_prime.c
@@ -108,6 +114,10 @@ SRCS += \
iicbus_if.h \
pci_if.h
-CFLAGS += -I${.CURDIR}/../../../dev/drm2/radeon ${GCC_MS_EXTENSIONS}
-
.include <bsd.kmod.mk>
+
+CFLAGS+= -I${.CURDIR}/../../../dev/drm2/radeon ${GCC_MS_EXTENSIONS}
+
+CWARNFLAGS.radeon_cp.c= -Wno-unused-value
+CWARNFLAGS.r600_cp.c= -Wno-unused-value
+CWARNFLAGS+= ${CWARNFLAGS.${.IMPSRC:T}}
OpenPOWER on IntegriCloud