diff options
Diffstat (limited to 'usr/src/uts/common')
| -rw-r--r-- | usr/src/uts/common/io/drm/drm.h | 9 | ||||
| -rw-r--r-- | usr/src/uts/common/io/drm/drmP.h | 53 | ||||
| -rw-r--r-- | usr/src/uts/common/io/drm/drm_atomic.h | 6 | ||||
| -rw-r--r-- | usr/src/uts/common/io/drm/drm_bufs.c | 10 | ||||
| -rw-r--r-- | usr/src/uts/common/io/drm/drm_drawable.c | 12 | ||||
| -rw-r--r-- | usr/src/uts/common/io/drm/drm_drv.c | 16 | ||||
| -rw-r--r-- | usr/src/uts/common/io/drm/drm_io32.h | 14 | ||||
| -rw-r--r-- | usr/src/uts/common/io/drm/drm_irq.c | 288 | ||||
| -rw-r--r-- | usr/src/uts/common/io/drm/drm_lock.c | 39 | ||||
| -rw-r--r-- | usr/src/uts/common/sys/agp/agpdefs.h | 4 |
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 */ |
