summaryrefslogtreecommitdiff
path: root/usr/src/uts/common
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common')
-rw-r--r--usr/src/uts/common/io/drm/drm.h9
-rw-r--r--usr/src/uts/common/io/drm/drmP.h53
-rw-r--r--usr/src/uts/common/io/drm/drm_atomic.h6
-rw-r--r--usr/src/uts/common/io/drm/drm_bufs.c10
-rw-r--r--usr/src/uts/common/io/drm/drm_drawable.c12
-rw-r--r--usr/src/uts/common/io/drm/drm_drv.c16
-rw-r--r--usr/src/uts/common/io/drm/drm_io32.h14
-rw-r--r--usr/src/uts/common/io/drm/drm_irq.c288
-rw-r--r--usr/src/uts/common/io/drm/drm_lock.c39
-rw-r--r--usr/src/uts/common/sys/agp/agpdefs.h4
10 files changed, 322 insertions, 129 deletions
diff --git a/usr/src/uts/common/io/drm/drm.h b/usr/src/uts/common/io/drm/drm.h
index 1b56718d9c..13e8bcf33c 100644
--- a/usr/src/uts/common/io/drm/drm.h
+++ b/usr/src/uts/common/io/drm/drm.h
@@ -58,15 +58,13 @@
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _DRM_H_
#define _DRM_H_
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/types32.h>
#ifndef __user
@@ -357,7 +355,8 @@ typedef enum drm_map_flags {
_DRM_KERNEL = 0x08, /**< kernel requires access */
_DRM_WRITE_COMBINING = 0x10, /**< use write-combining if available */
_DRM_CONTAINS_LOCK = 0x20, /**< SHM page that contains lock */
- _DRM_REMOVABLE = 0x40 /**< Removable mapping */
+ _DRM_REMOVABLE = 0x40, /**< Removable mapping */
+ _DRM_DRIVER = 0x80 /**< Managed by driver */
} drm_map_flags_t;
typedef struct drm_ctx_priv_map {
@@ -633,6 +632,7 @@ typedef struct drm_irq_busid {
typedef enum {
_DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */
_DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */
+ _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 */
@@ -802,6 +802,7 @@ typedef struct drm_set_version {
#define DRM_IOCTL_WAIT_VBLANK DRM_IOWR(0x3a, drm_wait_vblank_t)
+#define DRM_IOCTL_UPDATE_DRAW DRM_IOW(0x3f, drm_update_draw_t)
/*@}*/
/**
diff --git a/usr/src/uts/common/io/drm/drmP.h b/usr/src/uts/common/io/drm/drmP.h
index 5a6745c4e3..a02604296f 100644
--- a/usr/src/uts/common/io/drm/drmP.h
+++ b/usr/src/uts/common/io/drm/drmP.h
@@ -33,7 +33,7 @@
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -454,7 +454,6 @@ typedef struct drm_dma_handle {
uint_t cookie_num;
uintptr_t vaddr; /* virtual addr */
uintptr_t paddr; /* physical addr */
- size_t req_sz; /* required size of memory */
size_t real_sz; /* real size of memory */
} drm_dma_handle_t;
@@ -518,8 +517,6 @@ typedef struct ati_pcigart_info {
drm_local_map_t mapping;
} drm_ati_pcigart_info;
-
-
/* DRM device structure */
struct drm_device;
struct drm_driver_info {
@@ -554,6 +551,10 @@ struct drm_driver_info {
uint_t (*irq_handler)(DRM_IRQ_ARGS);
int (*vblank_wait)(struct drm_device *, unsigned int *);
int (*vblank_wait2)(struct drm_device *, unsigned int *);
+ /* added for intel minimized vblank */
+ 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);
drm_ioctl_desc_t *driver_ioctls;
int max_driver_ioctl;
@@ -578,7 +579,6 @@ struct drm_driver_info {
unsigned use_mtrr :1;
};
-
/*
* hardware-specific code needs to initialize mutexes which
* can be used in interrupt context, so they need to know
@@ -607,6 +607,7 @@ struct drm_device {
int flags; /* Flags to open(2) */
/* Locks */
+ kmutex_t vbl_lock; /* protects vblank operations */
kmutex_t dma_lock; /* protects dev->dma */
kmutex_t irq_lock; /* protects irq condition checks */
kmutex_t dev_lock; /* protects everything else */
@@ -644,12 +645,38 @@ struct drm_device {
atomic_t context_flag; /* Context swapping flag */
int last_context; /* Last current context */
+ /* Only used for Radeon */
atomic_t vbl_received;
atomic_t vbl_received2;
+
drm_vbl_sig_list_t vbl_sig_list;
drm_vbl_sig_list_t vbl_sig_list2;
- wait_queue_head_t vbl_queue; /* vbl wait channel */
+ wait_queue_head_t vbl_queue; /* vbl wait channel */
+ /* vbl wait channel array */
+ wait_queue_head_t *vbl_queues;
+
+ /* number of VBLANK interrupts */
+ /* (driver must alloc the right number of counters) */
+ atomic_t *_vblank_count;
+ /* signal list to send on VBLANK */
+ struct drm_vbl_sig_list *vbl_sigs;
+
+ /* number of signals pending on all crtcs */
+ atomic_t vbl_signal_pending;
+ /* number of users of vblank interrupts per crtc */
+ atomic_t *vblank_refcount;
+ /* protected by dev->vbl_lock, used for wraparound handling */
+ u32 *last_vblank;
+ /* so we don't call enable more than */
+ atomic_t *vblank_enabled;
+ /* for compensation of spurious wraparounds */
+ u32 *vblank_premodeset;
+ /* Don't wait while crtc is likely disabled */
+ int *vblank_suspend;
+ /* size of vblank counter register */
+ u32 max_vblank_count;
+ int num_crtcs;
kmutex_t tasklet_lock;
void (*locked_tasklet_func)(struct drm_device *dev);
@@ -669,7 +696,6 @@ struct drm_device {
u32 *drw_bitfield;
unsigned int drw_info_length;
drm_drawable_info_t **drw_info;
-
/*
* Saving S3 context
*/
@@ -704,7 +730,7 @@ int drm_ctxbitmap_next(drm_device_t *);
/* Locking IOCTL support (drm_lock.c) */
int drm_lock_take(drm_lock_data_t *, unsigned int);
int drm_lock_transfer(drm_device_t *,
- volatile unsigned int *, unsigned int);
+ drm_lock_data_t *, unsigned int);
int drm_lock_free(drm_device_t *,
volatile unsigned int *, unsigned int);
@@ -734,6 +760,11 @@ void drm_driver_irq_postinstall(drm_device_t *);
void drm_driver_irq_uninstall(drm_device_t *);
int drm_vblank_wait(drm_device_t *, unsigned int *);
void drm_vbl_send_signals(drm_device_t *);
+void drm_handle_vblank(struct drm_device *dev, int crtc);
+u32 drm_vblank_count(struct drm_device *dev, int crtc);
+int drm_vblank_get(struct drm_device *dev, int crtc);
+void drm_vblank_put(struct drm_device *dev, int crtc);
+int drm_vblank_init(struct drm_device *dev, int num_crtcs);
void drm_locked_tasklet(drm_device_t *, void(*func)(drm_device_t *));
/* AGP/GART support (drm_agpsupport.c) */
@@ -787,6 +818,7 @@ int drm_getsareactx(DRM_IOCTL_ARGS);
/* Drawable IOCTL support (drm_drawable.c) */
int drm_adddraw(DRM_IOCTL_ARGS);
int drm_rmdraw(DRM_IOCTL_ARGS);
+int drm_update_draw(DRM_IOCTL_ARGS);
/* Authentication IOCTL support (drm_auth.c) */
int drm_getmagic(DRM_IOCTL_ARGS);
@@ -862,9 +894,8 @@ extern int pci_get_irq(drm_device_t *);
extern int pci_get_vendor(drm_device_t *);
extern int pci_get_device(drm_device_t *);
-extern drm_drawable_info_t *drm_get_drawable_info(drm_device_t *,
- drm_drawable_t);
-
+extern struct drm_drawable_info *drm_get_drawable_info(drm_device_t *,
+ drm_drawable_t);
/* File Operations helpers (drm_fops.c) */
extern drm_file_t *drm_find_file_by_proc(drm_device_t *, cred_t *);
extern drm_cminor_t *drm_find_file_by_minor(drm_device_t *, int);
diff --git a/usr/src/uts/common/io/drm/drm_atomic.h b/usr/src/uts/common/io/drm/drm_atomic.h
index 3958f4c920..002b974933 100644
--- a/usr/src/uts/common/io/drm/drm_atomic.h
+++ b/usr/src/uts/common/io/drm/drm_atomic.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
@@ -40,8 +40,6 @@
#ifndef _SYS_DRM_ATOMIC_H_
#define _SYS_DRM_ATOMIC_H_
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -57,7 +55,7 @@ typedef uint32_t atomic_t;
#define atomic_set(p, v) (*(p) = (v))
#define atomic_read(p) (*(p))
#define atomic_inc(p) atomic_add_int(p, 1)
-#define atomic_dec(p) atomic_dec_uint(p, 1)
+#define atomic_dec(p) atomic_dec_uint(p)
#define atomic_add(n, p) atomic_add_int(p, n)
#define atomic_sub(n, p) atomic_dec_uint(p, n)
#define atomic_set_int(p, bits) atomic_or_uint(p, bits)
diff --git a/usr/src/uts/common/io/drm/drm_bufs.c b/usr/src/uts/common/io/drm/drm_bufs.c
index 8f8757b2b9..ad1254072a 100644
--- a/usr/src/uts/common/io/drm/drm_bufs.c
+++ b/usr/src/uts/common/io/drm/drm_bufs.c
@@ -33,12 +33,10 @@
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include "drmP.h"
#include <gfx_private.h>
#include "drm_io32.h"
@@ -88,9 +86,6 @@ int drm_addmap(drm_device_t *dev, unsigned long offset,
caddr_t kva;
int retval;
- if (!(dev->flags & (FREAD|FWRITE)))
- return (EACCES); /* Require read/write */
-
/*
* Only allow shared memory to be removable since we only keep
* enough book keeping information about shared memory to allow
@@ -213,9 +208,6 @@ drm_addmap_ioctl(DRM_IOCTL_ARGS)
int err;
DRM_DEVICE;
- if (!(dev->flags & (FREAD|FWRITE)))
- return (EACCES); /* Require read/write */
-
#ifdef _MULTI_DATAMODEL
if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
drm_map_32_t request32;
diff --git a/usr/src/uts/common/io/drm/drm_drawable.c b/usr/src/uts/common/io/drm/drm_drawable.c
index 0a6f05034f..3ccc443944 100644
--- a/usr/src/uts/common/io/drm/drm_drawable.c
+++ b/usr/src/uts/common/io/drm/drm_drawable.c
@@ -32,12 +32,10 @@
*
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include "drmP.h"
/*ARGSUSED*/
@@ -66,3 +64,11 @@ drm_drawable_info_t *
drm_get_drawable_info(drm_device_t *dev, drm_drawable_t id) {
return (NULL);
}
+
+/*ARGSUSED*/
+int
+drm_update_draw(DRM_IOCTL_ARGS)
+{
+ DRM_DEBUG("drm_update_draw\n");
+ return (0);
+}
diff --git a/usr/src/uts/common/io/drm/drm_drv.c b/usr/src/uts/common/io/drm/drm_drv.c
index 587c076332..253c158ff9 100644
--- a/usr/src/uts/common/io/drm/drm_drv.c
+++ b/usr/src/uts/common/io/drm/drm_drv.c
@@ -33,7 +33,7 @@
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -137,6 +137,8 @@ drm_ioctl_desc_t drm_ioctls[DRIVER_IOCTL_COUNT] = {
{drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
[DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] =
{drm_wait_vblank, 0},
+ [DRM_IOCTL_NR(DRM_IOCTL_UPDATE_DRAW)] =
+ {drm_update_draw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
};
const char *
@@ -308,9 +310,13 @@ drm_load(drm_device_t *dev)
cv_init(&(dev->lock.lock_cv), NULL, CV_DRIVER, NULL);
mutex_init(&(dev->lock.lock_mutex), NULL, MUTEX_DRIVER, NULL);
- mutex_init(&(dev->dev_lock), NULL, MUTEX_DRIVER, NULL);
- mutex_init(&dev->drw_lock, NULL, MUTEX_DRIVER, NULL);
+ mutex_init(&(dev->dev_lock), "drmdev", MUTEX_DRIVER, NULL);
+ mutex_init(&dev->irq_lock, "drmirq", MUTEX_DRIVER,
+ (void *)dev->intr_block);
+ mutex_init(&dev->drw_lock, "drmdrw", MUTEX_DRIVER, NULL);
+ mutex_init(&dev->tasklet_lock, "drmtsk", MUTEX_DRIVER, NULL);
+ dev->irq = pci_get_irq(dev);
dev->pci_vendor = pci_get_vendor(dev);
dev->pci_device = pci_get_device(dev);
@@ -351,8 +357,10 @@ error:
DRM_UNLOCK();
cv_destroy(&(dev->lock.lock_cv));
mutex_destroy(&(dev->lock.lock_mutex));
+ mutex_destroy(&dev->irq_lock);
mutex_destroy(&(dev->dev_lock));
mutex_destroy(&dev->drw_lock);
+ mutex_destroy(&dev->tasklet_lock);
return (retcode);
}
@@ -379,8 +387,10 @@ drm_unload(drm_device_t *dev)
drm_mem_uninit();
cv_destroy(&dev->lock.lock_cv);
mutex_destroy(&dev->lock.lock_mutex);
+ mutex_destroy(&dev->irq_lock);
mutex_destroy(&dev->dev_lock);
mutex_destroy(&dev->drw_lock);
+ mutex_destroy(&dev->tasklet_lock);
}
diff --git a/usr/src/uts/common/io/drm/drm_io32.h b/usr/src/uts/common/io/drm/drm_io32.h
index ca0a7843e7..e710697f98 100644
--- a/usr/src/uts/common/io/drm/drm_io32.h
+++ b/usr/src/uts/common/io/drm/drm_io32.h
@@ -20,12 +20,10 @@
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifndef _DRM_IO32_H_
#define _DRM_IO32_H_
@@ -163,14 +161,14 @@ typedef struct drm_ctx_res_32 {
struct drm_wait_vblank_request_32 {
drm_vblank_seq_type_t type;
- unsigned int sequence;
- unsigned long signal;
+ uint32_t sequence;
+ uint32_t signal;
};
struct drm_wait_vblank_reply_32 {
drm_vblank_seq_type_t type;
- unsigned int sequence;
- long tval_sec;
- long tval_usec;
+ uint32_t sequence;
+ int32_t tval_sec;
+ int32_t tval_usec;
};
/*
diff --git a/usr/src/uts/common/io/drm/drm_irq.c b/usr/src/uts/common/io/drm/drm_irq.c
index 783d32be6c..a91a461333 100644
--- a/usr/src/uts/common/io/drm/drm_irq.c
+++ b/usr/src/uts/common/io/drm/drm_irq.c
@@ -30,12 +30,10 @@
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include "drmP.h"
#include "drm.h"
#include "drm_io32.h"
@@ -57,6 +55,9 @@ drm_irq_by_busid(DRM_IOCTL_ARGS)
irq.irq = dev->irq;
+ DRM_DEBUG("%d:%d:%d => IRQ %d\n",
+ irq.busnum, irq.devnum, irq.funcnum, irq.irq);
+
DRM_COPYTO_WITH_RETURN((void *)data, &irq, sizeof (irq));
return (0);
@@ -76,6 +77,100 @@ drm_irq_handler_wrap(DRM_IRQ_ARGS)
return (ret);
}
+static void vblank_disable_fn(void *arg)
+{
+ struct drm_device *dev = (struct drm_device *)arg;
+ int i;
+
+ for (i = 0; i < dev->num_crtcs; i++) {
+ if (atomic_read(&dev->vblank_refcount[i]) == 0 &&
+ atomic_read(&dev->vblank_enabled[i]) == 1) {
+ dev->last_vblank[i] =
+ dev->driver->get_vblank_counter(dev, i);
+ dev->driver->disable_vblank(dev, i);
+ atomic_set(&dev->vblank_enabled[i], 0);
+ DRM_DEBUG("disable vblank");
+ }
+ }
+}
+
+static void drm_vblank_cleanup(struct drm_device *dev)
+{
+ /* Bail if the driver didn't call drm_vblank_init() */
+ if (dev->num_crtcs == 0)
+ return;
+
+
+ vblank_disable_fn((void *)dev);
+
+ drm_free(dev->vbl_queues, sizeof (wait_queue_head_t) * dev->num_crtcs,
+ DRM_MEM_DRIVER);
+ drm_free(dev->vbl_sigs, sizeof (struct drm_vbl_sig) * dev->num_crtcs,
+ DRM_MEM_DRIVER);
+ drm_free(dev->_vblank_count, sizeof (atomic_t) *
+ dev->num_crtcs, DRM_MEM_DRIVER);
+ drm_free(dev->vblank_refcount, sizeof (atomic_t) *
+ dev->num_crtcs, DRM_MEM_DRIVER);
+ drm_free(dev->vblank_enabled, sizeof (int) *
+ dev->num_crtcs, DRM_MEM_DRIVER);
+ drm_free(dev->last_vblank, sizeof (u32) * dev->num_crtcs,
+ DRM_MEM_DRIVER);
+ dev->num_crtcs = 0;
+}
+
+int
+drm_vblank_init(struct drm_device *dev, int num_crtcs)
+{
+ int i, ret = ENOMEM;
+
+ atomic_set(&dev->vbl_signal_pending, 0);
+ dev->num_crtcs = num_crtcs;
+
+
+ dev->vbl_queues = drm_alloc(sizeof (wait_queue_head_t) * num_crtcs,
+ DRM_MEM_DRIVER);
+ if (!dev->vbl_queues)
+ goto err;
+
+ dev->vbl_sigs = drm_alloc(sizeof (struct drm_vbl_sig) * num_crtcs,
+ DRM_MEM_DRIVER);
+ if (!dev->vbl_sigs)
+ goto err;
+
+ dev->_vblank_count = drm_alloc(sizeof (atomic_t) * num_crtcs,
+ DRM_MEM_DRIVER);
+ if (!dev->_vblank_count)
+ goto err;
+
+ dev->vblank_refcount = drm_alloc(sizeof (atomic_t) * num_crtcs,
+ DRM_MEM_DRIVER);
+ if (!dev->vblank_refcount)
+ goto err;
+
+ dev->vblank_enabled = drm_alloc(num_crtcs * sizeof (int),
+ DRM_MEM_DRIVER);
+ if (!dev->vblank_enabled)
+ goto err;
+
+ dev->last_vblank = drm_alloc(num_crtcs * sizeof (u32), DRM_MEM_DRIVER);
+ if (!dev->last_vblank)
+ goto err;
+ /* Zero per-crtc vblank stuff */
+ for (i = 0; i < num_crtcs; i++) {
+ DRM_INIT_WAITQUEUE(&dev->vbl_queues[i], DRM_INTR_PRI(dev));
+ TAILQ_INIT(&dev->vbl_sigs[i]);
+ atomic_set(&dev->_vblank_count[i], 0);
+ atomic_set(&dev->vblank_refcount[i], 0);
+ atomic_set(&dev->vblank_enabled[i], 1);
+ }
+ vblank_disable_fn((void *)dev);
+ return (0);
+
+err:
+ DRM_ERROR("drm_vblank_init: alloc error");
+ drm_vblank_cleanup(dev);
+ return (ret);
+}
/*ARGSUSED*/
static int
@@ -100,8 +195,6 @@ drm_install_irq_handle(drm_device_t *dev)
return (DDI_FAILURE);
}
- mutex_init(&dev->irq_lock, NULL, MUTEX_DRIVER, (void *)dev->intr_block);
-
/* setup the interrupt handler */
if (ddi_add_intr(dip, 0, &dev->intr_block,
(ddi_idevice_cookie_t *)NULL, drm_irq_handler_wrap,
@@ -128,10 +221,9 @@ drm_irq_install(drm_device_t *dev)
DRM_ERROR("drm_irq_install: irq already enabled");
return (EBUSY);
}
-
+ dev->irq_enabled = 1;
+ DRM_DEBUG("drm_irq_install irq=%d\n", dev->irq);
dev->context_flag = 0;
- mutex_init(&dev->tasklet_lock, NULL, MUTEX_DRIVER, NULL);
-
/* before installing handler */
dev->driver->irq_preinstall(dev);
@@ -143,15 +235,9 @@ drm_irq_install(drm_device_t *dev)
return (ret);
}
- if (dev->driver->use_vbl_irq) {
- DRM_INIT_WAITQUEUE(&dev->vbl_queue, DRM_INTR_PRI(dev));
- }
-
/* after installing handler */
dev->driver->irq_postinstall(dev);
- dev->irq_enabled = 1;
-
return (0);
}
@@ -160,7 +246,6 @@ drm_uninstall_irq_handle(drm_device_t *dev)
{
ASSERT(dev->dip);
ddi_remove_intr(dev->dip, 0, dev->intr_block);
- mutex_destroy(&dev->irq_lock);
}
@@ -176,10 +261,9 @@ drm_irq_uninstall(drm_device_t *dev)
dev->driver->irq_uninstall(dev);
drm_uninstall_irq_handle(dev);
dev->locked_tasklet_func = NULL;
- if (dev->driver->use_vbl_irq) {
- DRM_FINI_WAITQUEUE(&dev->vbl_queue);
- }
- mutex_destroy(&dev->tasklet_lock);
+
+ drm_vblank_cleanup(dev);
+
return (DDI_SUCCESS);
}
@@ -208,19 +292,90 @@ drm_control(DRM_IOCTL_ARGS)
}
}
+u32
+drm_vblank_count(struct drm_device *dev, int crtc)
+{
+ return (atomic_read(&dev->_vblank_count[crtc]));
+}
+
+static void drm_update_vblank_count(struct drm_device *dev, int crtc)
+{
+ u32 cur_vblank, diff;
+ /*
+ * Interrupts were disabled prior to this call, so deal with counter
+ * wrap if needed.
+ * NOTE! It's possible we lost a full dev->max_vblank_count events
+ * here if the register is small or we had vblank interrupts off for
+ * a long time.
+ */
+ cur_vblank = dev->driver->get_vblank_counter(dev, crtc);
+ diff = cur_vblank - dev->last_vblank[crtc];
+ if (cur_vblank < dev->last_vblank[crtc]) {
+ diff += dev->max_vblank_count;
+ DRM_DEBUG("last_vblank[%d]=0x%x, cur_vblank=0x%x => diff=0x%x\n",
+ crtc, dev->last_vblank[crtc], cur_vblank, diff);
+ }
+
+ atomic_add(diff, &dev->_vblank_count[crtc]);
+}
+
+static timeout_id_t timer_id = NULL;
+
+int
+drm_vblank_get(struct drm_device *dev, int crtc)
+{
+ int ret = 0;
+
+ DRM_SPINLOCK(&dev->vbl_lock);
+
+ if (timer_id != NULL) {
+ (void) untimeout(timer_id);
+ timer_id = NULL;
+ }
+
+ /* Going from 0->1 means we have to enable interrupts again */
+ atomic_add(1, &dev->vblank_refcount[crtc]);
+ if (dev->vblank_refcount[crtc] == 1 &&
+ atomic_read(&dev->vblank_enabled[crtc]) == 0) {
+ ret = dev->driver->enable_vblank(dev, crtc);
+ if (ret)
+ atomic_dec(&dev->vblank_refcount[crtc]);
+ else {
+ atomic_set(&dev->vblank_enabled[crtc], 1);
+ drm_update_vblank_count(dev, crtc);
+ }
+ }
+ DRM_SPINUNLOCK(&dev->vbl_lock);
+
+ return (ret);
+}
+
+void
+drm_vblank_put(struct drm_device *dev, int crtc)
+{
+ DRM_SPINLOCK(&dev->vbl_lock);
+ /* Last user schedules interrupt disable */
+ atomic_dec(&dev->vblank_refcount[crtc]);
+
+ if (dev->vblank_refcount[crtc] == 0)
+ timer_id = timeout(vblank_disable_fn, (void *) dev, 5*DRM_HZ);
+
+ DRM_SPINUNLOCK(&dev->vbl_lock);
+}
+
/*ARGSUSED*/
int
drm_wait_vblank(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_wait_vblank_t vblwait;
- struct timeval now;
- int ret, flags;
+ int ret, flags, crtc;
unsigned int sequence;
- if (!dev->irq_enabled)
+ if (!dev->irq_enabled) {
+ DRM_DEBUG("wait vblank, EINVAL");
return (EINVAL);
-
+ }
#ifdef _MULTI_DATAMODEL
if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
drm_wait_vblank_32_t vblwait32;
@@ -245,27 +400,28 @@ drm_wait_vblank(DRM_IOCTL_ARGS)
}
flags = vblwait.request.type & _DRM_VBLANK_FLAGS_MASK;
- if (flags & _DRM_VBLANK_SECONDARY) {
- if (dev->driver->use_vbl_irq2 != 1)
- return (ENOTSUP);
- } else {
- if (dev->driver->use_vbl_irq != 1)
- return (ENOTSUP);
- }
+ crtc = flags & _DRM_VBLANK_SECONDARY ? 1 : 0;
+ if (crtc >= dev->num_crtcs)
+ return (ENOTSUP);
- sequence = atomic_read((flags & _DRM_VBLANK_SECONDARY) ?
- &dev->vbl_received2 : &dev->vbl_received);
+ ret = drm_vblank_get(dev, crtc);
+ if (ret) {
+ DRM_DEBUG("can't get drm vblank");
+ return (ret);
+ }
+ sequence = drm_vblank_count(dev, crtc);
- if (vblwait.request.type & _DRM_VBLANK_RELATIVE) {
+ switch (vblwait.request.type & _DRM_VBLANK_TYPES_MASK) {
+ case _DRM_VBLANK_RELATIVE:
vblwait.request.sequence += sequence;
vblwait.request.type &= ~_DRM_VBLANK_RELATIVE;
- }
-#ifdef DEBUG
- else if ((vblwait.request.type & _DRM_VBLANK_ABSOLUTE) == 0) {
- cmn_err(CE_WARN, "vblank_wait: unkown request type");
+ /*FALLTHROUGH*/
+ case _DRM_VBLANK_ABSOLUTE:
+ break;
+ default:
+ DRM_DEBUG("wait vblank return EINVAL");
return (EINVAL);
}
-#endif
if ((flags & _DRM_VBLANK_NEXTONMISS) &&
(sequence - vblwait.request.sequence) <= (1<<23)) {
@@ -276,32 +432,33 @@ drm_wait_vblank(DRM_IOCTL_ARGS)
/*
* Don't block process, send signal when vblank interrupt
*/
-
+ DRM_DEBUG("NOT SUPPORT YET, SHOULD BE ADDED");
cmn_err(CE_WARN, "NOT SUPPORT YET, SHOULD BE ADDED");
ret = EINVAL;
+ goto done;
} else {
/* block until vblank interupt */
-
- if (flags & _DRM_VBLANK_SECONDARY) {
- ret = dev->driver->vblank_wait2(dev,
- &vblwait.request.sequence);
- } else {
- ret = dev->driver->vblank_wait(dev,
- &vblwait.request.sequence);
+ /* shared code returns -errno */
+ DRM_WAIT_ON(ret, &dev->vbl_queues[crtc], 3 * DRM_HZ,
+ ((drm_vblank_count(dev, crtc)
+ - vblwait.request.sequence) <= (1 << 23)));
+ if (ret != EINTR) {
+ struct timeval now;
+ (void) uniqtime(&now);
+ vblwait.reply.tval_sec = now.tv_sec;
+ vblwait.reply.tval_usec = now.tv_usec;
+ vblwait.reply.sequence = drm_vblank_count(dev, crtc);
}
-
- (void) uniqtime(&now);
- vblwait.reply.tval_sec = now.tv_sec;
- vblwait.reply.tval_usec = now.tv_usec;
}
+done:
#ifdef _MULTI_DATAMODEL
if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
drm_wait_vblank_32_t vblwait32;
vblwait32.reply.type = vblwait.reply.type;
vblwait32.reply.sequence = vblwait.reply.sequence;
- vblwait32.reply.tval_sec = vblwait.reply.tval_sec;
- vblwait32.reply.tval_usec = vblwait.reply.tval_usec;
+ vblwait32.reply.tval_sec = (int32_t)vblwait.reply.tval_sec;
+ vblwait32.reply.tval_usec = (int32_t)vblwait.reply.tval_usec;
DRM_COPYTO_WITH_RETURN((void *)data, &vblwait32,
sizeof (vblwait32));
} else {
@@ -311,6 +468,8 @@ drm_wait_vblank(DRM_IOCTL_ARGS)
#ifdef _MULTI_DATAMODEL
}
#endif
+
+ drm_vblank_put(dev, crtc);
return (ret);
}
@@ -319,24 +478,15 @@ drm_wait_vblank(DRM_IOCTL_ARGS)
void
drm_vbl_send_signals(drm_device_t *dev)
{
- drm_vbl_sig_t *vbl_sig;
- unsigned int vbl_seq = atomic_read(&dev->vbl_received);
- proc_t *pp;
-
- vbl_sig = TAILQ_FIRST(&dev->vbl_sig_list);
- while (vbl_sig != NULL) {
- drm_vbl_sig_t *next = TAILQ_NEXT(vbl_sig, link);
-
- if ((vbl_seq - vbl_sig->sequence) <= (1<<23)) {
- pp = prfind(vbl_sig->pid);
- if (pp != NULL)
- psignal(pp, vbl_sig->signo);
+ DRM_DEBUG("drm_vbl_send_signals");
+}
- TAILQ_REMOVE(&dev->vbl_sig_list, vbl_sig, link);
- drm_free(vbl_sig, sizeof (*vbl_sig), DRM_MEM_DRIVER);
- }
- vbl_sig = next;
- }
+void
+drm_handle_vblank(struct drm_device *dev, int crtc)
+{
+ atomic_inc(&dev->_vblank_count[crtc]);
+ DRM_WAKEUP(&dev->vbl_queues[crtc]);
+ drm_vbl_send_signals(dev);
}
/*
diff --git a/usr/src/uts/common/io/drm/drm_lock.c b/usr/src/uts/common/io/drm/drm_lock.c
index 308106ba61..69a43a7598 100644
--- a/usr/src/uts/common/io/drm/drm_lock.c
+++ b/usr/src/uts/common/io/drm/drm_lock.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -37,14 +37,12 @@
*
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include "drmP.h"
int
drm_lock_take(drm_lock_data_t *lock_data, unsigned int context)
{
- unsigned int old, new, prev;
+ unsigned int old, new;
volatile unsigned int *lock = &lock_data->hw_lock->lock;
do {
@@ -53,8 +51,7 @@ drm_lock_take(drm_lock_data_t *lock_data, unsigned int context)
new = old | _DRM_LOCK_CONT;
else
new = context | _DRM_LOCK_HELD;
- prev = atomic_cas_uint(lock, old, new);
- } while (prev != old);
+ } while (!atomic_cmpset_int(lock, old, new));
if (_DRM_LOCKING_CONTEXT(old) == context) {
if (old & _DRM_LOCK_HELD) {
@@ -65,9 +62,8 @@ drm_lock_take(drm_lock_data_t *lock_data, unsigned int context)
return (0);
}
}
- if ((_DRM_LOCKING_CONTEXT(new)) == context &&
- _DRM_LOCK_IS_HELD(new)) {
- /* Have lock */
+ if (new == (context | _DRM_LOCK_HELD)) {
+ /* Have lock */
return (1);
}
return (0);
@@ -78,17 +74,17 @@ drm_lock_take(drm_lock_data_t *lock_data, unsigned int context)
* inside *_unlock to give lock to kernel before calling *_dma_schedule.
*/
int
-drm_lock_transfer(drm_device_t *dev, volatile unsigned int *lock,
- unsigned int context)
+drm_lock_transfer(drm_device_t *dev, drm_lock_data_t *lock_data,
+ unsigned int context)
{
- unsigned int old, new, prev;
+ unsigned int old, new;
+ volatile unsigned int *lock = &lock_data->hw_lock->lock;
dev->lock.filp = NULL;
do {
old = *lock;
new = context | _DRM_LOCK_HELD;
- prev = atomic_cas_uint(lock, old, new);
- } while (prev != old);
+ } while (!atomic_cmpset_int(lock, old, new));
return (1);
}
@@ -97,15 +93,14 @@ int
drm_lock_free(drm_device_t *dev, volatile unsigned int *lock,
unsigned int context)
{
- unsigned int old, new, prev;
+ unsigned int old, new;
mutex_enter(&(dev->lock.lock_mutex));
dev->lock.filp = NULL;
do {
old = *lock;
new = 0;
- prev = atomic_cas_uint(lock, old, new);
- } while (prev != old);
+ } while (!atomic_cmpset_int(lock, old, new));
if (_DRM_LOCK_IS_HELD(old) &&
(_DRM_LOCKING_CONTEXT(old) != context)) {
@@ -130,9 +125,14 @@ drm_lock(DRM_IOCTL_ARGS)
DRM_COPYFROM_WITH_RETURN(&lock, (void *)data, sizeof (lock));
if (lock.context == DRM_KERNEL_CONTEXT) {
+ DRM_ERROR("Process %d using kernel context %d\n",
+ 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);
if (dev->driver->use_dma_queue && lock.context < 0)
return (EINVAL);
@@ -152,6 +152,7 @@ drm_lock(DRM_IOCTL_ARGS)
}
}
mutex_exit(&(dev->lock.lock_mutex));
+ DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock");
if (dev->driver->dma_quiescent != NULL &&
(lock.flags & _DRM_LOCK_QUIESCENT))
@@ -169,6 +170,10 @@ drm_unlock(DRM_IOCTL_ARGS)
DRM_COPYFROM_WITH_RETURN(&lock, (void *)data, sizeof (lock));
+ DRM_DEBUG("%d (pid %d) requests unlock (0x%08x), flags = 0x%08x\n",
+ lock.context, DRM_CURRENTPID, dev->lock.hw_lock->lock,
+ lock.flags);
+
if (lock.context == DRM_KERNEL_CONTEXT) {
DRM_ERROR("Process %d using kernel context %d\n",
DRM_CURRENTPID, lock.context);
diff --git a/usr/src/uts/common/sys/agp/agpdefs.h b/usr/src/uts/common/sys/agp/agpdefs.h
index c77559ea85..507953f83c 100644
--- a/usr/src/uts/common/sys/agp/agpdefs.h
+++ b/usr/src/uts/common/sys/agp/agpdefs.h
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -102,6 +102,7 @@ extern "C" {
#define INTEL_BR_EL 0x2e008086
#define INTEL_BR_Q45 0x2e108086
#define INTEL_BR_G45 0x2e208086
+#define INTEL_BR_G41 0x2e308086
/* AGP common register offset in pci configuration space */
#define AGP_CONF_MISC 0x51 /* one byte */
@@ -170,6 +171,7 @@ extern "C" {
#define INTEL_IGD_EL 0x2e028086
#define INTEL_IGD_Q45 0x2e128086
#define INTEL_IGD_G45 0x2e228086
+#define INTEL_IGD_G41 0x2e328086
/* register offsets in PCI config space */
#define I8XX_CONF_GMADR 0x10 /* GMADR of i8xx series */