Date: Sat, 28 Feb 2009 17:56:11 +0000 (UTC) From: John Birrell <jb@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r189180 - projects/jbuild/sys/dev/drm Message-ID: <200902281756.n1SHuBak017020@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: jb Date: Sat Feb 28 17:56:11 2009 New Revision: 189180 URL: http://svn.freebsd.org/changeset/base/189180 Log: MFC Added: projects/jbuild/sys/dev/drm/i915_reg.h - copied unchanged from r189173, head/sys/dev/drm/i915_reg.h Modified: projects/jbuild/sys/dev/drm/drmP.h projects/jbuild/sys/dev/drm/drm_bufs.c projects/jbuild/sys/dev/drm/drm_drv.c projects/jbuild/sys/dev/drm/drm_irq.c projects/jbuild/sys/dev/drm/drm_lock.c projects/jbuild/sys/dev/drm/i915_dma.c projects/jbuild/sys/dev/drm/i915_drv.c projects/jbuild/sys/dev/drm/i915_drv.h projects/jbuild/sys/dev/drm/i915_irq.c projects/jbuild/sys/dev/drm/mach64_drv.c projects/jbuild/sys/dev/drm/mach64_drv.h projects/jbuild/sys/dev/drm/mach64_irq.c projects/jbuild/sys/dev/drm/mga_dma.c projects/jbuild/sys/dev/drm/mga_irq.c projects/jbuild/sys/dev/drm/r128_drv.c projects/jbuild/sys/dev/drm/r128_drv.h projects/jbuild/sys/dev/drm/r128_irq.c projects/jbuild/sys/dev/drm/radeon_cp.c projects/jbuild/sys/dev/drm/radeon_irq.c Modified: projects/jbuild/sys/dev/drm/drmP.h ============================================================================== --- projects/jbuild/sys/dev/drm/drmP.h Sat Feb 28 17:55:32 2009 (r189179) +++ projects/jbuild/sys/dev/drm/drmP.h Sat Feb 28 17:56:11 2009 (r189180) @@ -63,7 +63,6 @@ struct drm_file; #include <sys/signalvar.h> #include <sys/poll.h> #include <sys/tree.h> -#include <sys/taskqueue.h> #include <vm/vm.h> #include <vm/pmap.h> #include <vm/vm_extern.h> @@ -294,8 +293,8 @@ for ( ret = 0 ; !ret && !(condition) ; ) DRM_UNLOCK(); \ mtx_lock(&dev->irq_lock); \ if (!(condition)) \ - ret = -mtx_sleep(&(queue), &dev->irq_lock, \ - PZERO | PCATCH, "drmwtq", (timeout)); \ + ret = -mtx_sleep(&(queue), &dev->irq_lock, \ + PCATCH, "drmwtq", (timeout)); \ mtx_unlock(&dev->irq_lock); \ DRM_LOCK(); \ } @@ -320,6 +319,12 @@ typedef struct drm_pci_id_list char *name; } drm_pci_id_list_t; +struct drm_msi_blacklist_entry +{ + int vendor; + int device; +}; + #define DRM_AUTH 0x1 #define DRM_MASTER 0x2 #define DRM_ROOT_ONLY 0x4 @@ -628,7 +633,6 @@ struct drm_device { struct mtx irq_lock; /* protects irq condition checks */ struct mtx dev_lock; /* protects everything else */ DRM_SPINTYPE drw_lock; - DRM_SPINTYPE tsk_lock; /* Usage Counters */ int open_count; /* Outstanding files open */ @@ -657,6 +661,7 @@ struct drm_device { /* 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 */ @@ -695,9 +700,6 @@ struct drm_device { struct unrhdr *drw_unrhdr; /* RB tree of drawable infos */ RB_HEAD(drawable_tree, bsd_drm_drawable_info) drw_head; - - struct task locked_task; - void (*locked_task_call)(struct drm_device *dev); }; static __inline__ int drm_core_check_feature(struct drm_device *dev, @@ -792,6 +794,7 @@ void drm_handle_vblank(struct drm_device 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); +void drm_vblank_cleanup(struct drm_device *dev); int drm_vblank_wait(struct drm_device *dev, unsigned int *vbl_seq); int drm_vblank_init(struct drm_device *dev, int num_crtcs); void drm_vbl_send_signals(struct drm_device *dev, int crtc); @@ -899,8 +902,8 @@ int drm_addmap_ioctl(struct drm_device * struct drm_file *file_priv); int drm_rmmap_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -int drm_addbufs_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, @@ -918,8 +921,6 @@ int drm_control(struct drm_device *dev, struct drm_file *file_priv); int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_priv); -void drm_locked_tasklet(struct drm_device *dev, - void (*tasklet)(struct drm_device *dev)); /* AGP/GART support (drm_agpsupport.c) */ int drm_agp_acquire_ioctl(struct drm_device *dev, void *data, Modified: projects/jbuild/sys/dev/drm/drm_bufs.c ============================================================================== --- projects/jbuild/sys/dev/drm/drm_bufs.c Sat Feb 28 17:55:32 2009 (r189179) +++ projects/jbuild/sys/dev/drm/drm_bufs.c Sat Feb 28 17:56:11 2009 (r189180) @@ -880,8 +880,7 @@ int drm_addbufs_pci(struct drm_device *d return ret; } -int drm_addbufs_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) { struct drm_buf_desc *request = data; int err; Modified: projects/jbuild/sys/dev/drm/drm_drv.c ============================================================================== --- projects/jbuild/sys/dev/drm/drm_drv.c Sat Feb 28 17:55:32 2009 (r189179) +++ projects/jbuild/sys/dev/drm/drm_drv.c Sat Feb 28 17:56:11 2009 (r189180) @@ -82,7 +82,7 @@ static drm_ioctl_desc_t drm_ioctls[25 DRM_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_getsareactx, DRM_AUTH), - DRM_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_addctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_addctx, DRM_AUTH|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_IOCTL_GET_CTX, drm_getctx, DRM_AUTH), @@ -95,10 +95,11 @@ static drm_ioctl_desc_t drm_ioctls[25 DRM_IOCTL_DEF(DRM_IOCTL_LOCK, drm_lock, DRM_AUTH), DRM_IOCTL_DEF(DRM_IOCTL_UNLOCK, drm_unlock, DRM_AUTH), + DRM_IOCTL_DEF(DRM_IOCTL_FINISH, drm_noop, DRM_AUTH), - DRM_IOCTL_DEF(DRM_IOCTL_ADD_BUFS, drm_addbufs_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_IOCTL_MARK_BUFS, drm_markbufs, DRM_AUTH|DRM_MASTER), + DRM_IOCTL_DEF(DRM_IOCTL_ADD_BUFS, drm_addbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_MARK_BUFS, drm_markbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 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), @@ -117,7 +118,6 @@ static drm_ioctl_desc_t drm_ioctls[25 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, 0), 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), @@ -131,9 +131,33 @@ static struct cdevsw drm_cdevsw = { .d_poll = drm_poll, .d_mmap = drm_mmap, .d_name = "drm", - .d_flags = D_TRACKCLOSE | D_NEEDGIANT + .d_flags = D_TRACKCLOSE }; +int drm_msi = 1; /* Enable by default. */ +TUNABLE_INT("hw.drm.msi", &drm_msi); + +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(int vendor, int device) +{ + int i = 0; + + for (i = 0; drm_msi_blacklist[i].vendor != 0; i++) { + if ((drm_msi_blacklist[i].vendor == vendor) && + (drm_msi_blacklist[i].device == device)) { + return 1; + } + } + + return 0; +} + int drm_probe(device_t dev, drm_pci_id_list_t *idlist) { drm_pci_id_list_t *id_entry; @@ -169,7 +193,7 @@ int drm_attach(device_t nbdev, drm_pci_i { struct drm_device *dev; drm_pci_id_list_t *id_entry; - int unit; + int unit, msicount; unit = device_get_unit(nbdev); dev = device_get_softc(nbdev); @@ -189,22 +213,67 @@ int drm_attach(device_t nbdev, drm_pci_i DRM_DEV_MODE, "dri/card%d", unit); +#if __FreeBSD_version >= 700053 + dev->pci_domain = pci_get_domain(dev->device); +#else + dev->pci_domain = 0; +#endif + 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); + + if (drm_msi && + !drm_msi_is_blacklisted(dev->pci_vendor, dev->pci_device)) { + 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->tsk_lock, "drmtsk", NULL, MTX_DEF); - id_entry = drm_find_description(pci_get_vendor(dev->device), - pci_get_device(dev->device), idlist); + id_entry = drm_find_description(dev->pci_vendor, + dev->pci_device, idlist); dev->id_entry = id_entry; return drm_load(dev); } -int drm_detach(device_t dev) +int drm_detach(device_t nbdev) { - drm_unload(device_get_softc(dev)); + struct drm_device *dev; + + dev = device_get_softc(nbdev); + + drm_unload(dev); + + 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; } @@ -353,19 +422,6 @@ static int drm_load(struct drm_device *d DRM_DEBUG("\n"); - dev->irq = pci_get_irq(dev->device); -#if __FreeBSD_version >= 700053 - dev->pci_domain = pci_get_domain(dev->device); -#else - dev->pci_domain = 0; -#endif - 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); - TAILQ_INIT(&dev->maplist); drm_mem_init(); @@ -440,7 +496,6 @@ error: DRM_UNLOCK(); destroy_dev(dev->devnode); - mtx_destroy(&dev->tsk_lock); mtx_destroy(&dev->drw_lock); mtx_destroy(&dev->vbl_lock); mtx_destroy(&dev->irq_lock); @@ -468,6 +523,8 @@ static void drm_unload(struct drm_device DRM_DEBUG("mtrr_del = %d", retcode); } + drm_vblank_cleanup(dev); + DRM_LOCK(); drm_lastclose(dev); DRM_UNLOCK(); @@ -503,14 +560,12 @@ static void drm_unload(struct drm_device if (pci_disable_busmaster(dev->device)) DRM_ERROR("Request to disable bus-master failed.\n"); - mtx_destroy(&dev->tsk_lock); mtx_destroy(&dev->drw_lock); mtx_destroy(&dev->vbl_lock); mtx_destroy(&dev->irq_lock); mtx_destroy(&dev->dev_lock); } - int drm_version(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_version *version = data; @@ -658,9 +713,7 @@ int drm_ioctl(struct cdev *kdev, u_long int is_driver_ioctl = 0; struct drm_file *file_priv; - DRM_LOCK(); retcode = devfs_get_cdevpriv((void **)&file_priv); - DRM_UNLOCK(); if (retcode != 0) { DRM_ERROR("can't find authenticator\n"); return EINVAL; Modified: projects/jbuild/sys/dev/drm/drm_irq.c ============================================================================== --- projects/jbuild/sys/dev/drm/drm_irq.c Sat Feb 28 17:55:32 2009 (r189179) +++ projects/jbuild/sys/dev/drm/drm_irq.c Sat Feb 28 17:56:11 2009 (r189180) @@ -36,8 +36,6 @@ __FBSDID("$FreeBSD$"); #include "dev/drm/drmP.h" #include "dev/drm/drm.h" -static void drm_locked_task(void *context, int pending __unused); - int drm_irq_by_busid(struct drm_device *dev, void *data, struct drm_file *file_priv) { @@ -98,7 +96,7 @@ static void vblank_disable_fn(void *arg) } } -static void drm_vblank_cleanup(struct drm_device *dev) +void drm_vblank_cleanup(struct drm_device *dev) { unsigned long irqflags; @@ -174,13 +172,6 @@ int drm_irq_install(struct drm_device *d DRM_UNLOCK(); /* Install handler */ - dev->irqrid = 0; - dev->irqr = bus_alloc_resource_any(dev->device, SYS_RES_IRQ, - &dev->irqrid, RF_SHAREABLE); - if (!dev->irqr) { - retcode = ENOENT; - goto err; - } #if __FreeBSD_version >= 700031 retcode = bus_setup_intr(dev->device, dev->irqr, INTR_TYPE_TTY | INTR_MPSAFE, @@ -198,30 +189,21 @@ int drm_irq_install(struct drm_device *d dev->driver->irq_postinstall(dev); DRM_UNLOCK(); - TASK_INIT(&dev->locked_task, 0, drm_locked_task, dev); return 0; err: DRM_LOCK(); dev->irq_enabled = 0; - if (dev->irqrid != 0) { - bus_release_resource(dev->device, SYS_RES_IRQ, dev->irqrid, - dev->irqr); - dev->irqrid = 0; - } DRM_UNLOCK(); + return retcode; } int drm_irq_uninstall(struct drm_device *dev) { - int irqrid; - if (!dev->irq_enabled) return EINVAL; dev->irq_enabled = 0; - irqrid = dev->irqrid; - dev->irqrid = 0; DRM_DEBUG("irq=%d\n", dev->irq); @@ -229,11 +211,8 @@ int drm_irq_uninstall(struct drm_device DRM_UNLOCK(); bus_teardown_intr(dev->device, dev->irqr, dev->irqh); - bus_release_resource(dev->device, SYS_RES_IRQ, irqrid, dev->irqr); DRM_LOCK(); - drm_vblank_cleanup(dev); - return 0; } @@ -304,6 +283,7 @@ int drm_vblank_get(struct drm_device *de DRM_SPINLOCK_IRQSAVE(&dev->vbl_lock, irqflags); /* Going from 0->1 means we have to enable interrupts again */ atomic_add_acq_int(&dev->vblank[crtc].refcount, 1); + DRM_DEBUG("vblank refcount = %d\n", dev->vblank[crtc].refcount); if (dev->vblank[crtc].refcount == 1 && !dev->vblank[crtc].enabled) { ret = dev->driver->enable_vblank(dev, crtc); @@ -326,6 +306,7 @@ void drm_vblank_put(struct drm_device *d DRM_SPINLOCK_IRQSAVE(&dev->vbl_lock, irqflags); /* Last user schedules interrupt disable */ atomic_subtract_acq_int(&dev->vblank[crtc].refcount, 1); + DRM_DEBUG("vblank refcount = %d\n", dev->vblank[crtc].refcount); if (dev->vblank[crtc].refcount == 0) callout_reset(&dev->vblank_disable_timer, 5 * DRM_HZ, (timeout_t *)vblank_disable_fn, (void *)dev); @@ -388,8 +369,8 @@ out: int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_priv) { union drm_wait_vblank *vblwait = data; + unsigned int flags, seq, crtc; int ret = 0; - int flags, seq, crtc; if (!dev->irq_enabled) return EINVAL; @@ -409,8 +390,10 @@ int drm_wait_vblank(struct drm_device *d return EINVAL; ret = drm_vblank_get(dev, crtc); - if (ret) + if (ret) { + DRM_ERROR("failed to acquire vblank counter, %d\n", ret); return ret; + } seq = drm_vblank_count(dev, crtc); switch (vblwait->request.type & _DRM_VBLANK_TYPES_MASK) { @@ -449,14 +432,20 @@ int drm_wait_vblank(struct drm_device *d #endif ret = EINVAL; } else { - DRM_LOCK(); - /* shared code returns -errno */ - - DRM_WAIT_ON(ret, dev->vblank[crtc].queue, 3 * DRM_HZ, - ((drm_vblank_count(dev, crtc) - - vblwait->request.sequence) <= (1 << 23))); - DRM_UNLOCK(); + DRM_DEBUG("waiting on vblank count %d, crtc %d\n", + vblwait->request.sequence, crtc); + for ( ret = 0 ; !ret && !((drm_vblank_count(dev, crtc) - + vblwait->request.sequence) <= (1 << 23)) ; ) { + mtx_lock(&dev->irq_lock); + if (!((drm_vblank_count(dev, crtc) - + vblwait->request.sequence) <= (1 << 23))) + ret = mtx_sleep(&dev->vblank[crtc].queue, + &dev->irq_lock, PCATCH, "vblwtq", + 3 * DRM_HZ); + mtx_unlock(&dev->irq_lock); + } + DRM_DEBUG("return = %d\n", ret); if (ret != EINTR) { struct timeval now; @@ -464,6 +453,10 @@ int drm_wait_vblank(struct drm_device *d vblwait->reply.tval_sec = now.tv_sec; vblwait->reply.tval_usec = now.tv_usec; vblwait->reply.sequence = drm_vblank_count(dev, crtc); + DRM_DEBUG("returning %d to client\n", + vblwait->reply.sequence); + } else { + DRM_DEBUG("vblank wait interrupted by signal\n"); } } @@ -507,46 +500,3 @@ void drm_handle_vblank(struct drm_device drm_vbl_send_signals(dev, crtc); } -static void drm_locked_task(void *context, int pending __unused) -{ - struct drm_device *dev = context; - - DRM_SPINLOCK(&dev->tsk_lock); - - DRM_LOCK(); /* XXX drm_lock_take() should do it's own locking */ - if (dev->locked_task_call == NULL || - drm_lock_take(&dev->lock, DRM_KERNEL_CONTEXT) == 0) { - DRM_UNLOCK(); - DRM_SPINUNLOCK(&dev->tsk_lock); - return; - } - - dev->lock.file_priv = NULL; /* kernel owned */ - dev->lock.lock_time = jiffies; - atomic_inc(&dev->counts[_DRM_STAT_LOCKS]); - - DRM_UNLOCK(); - - dev->locked_task_call(dev); - - drm_lock_free(&dev->lock, DRM_KERNEL_CONTEXT); - - dev->locked_task_call = NULL; - - DRM_SPINUNLOCK(&dev->tsk_lock); -} - -void -drm_locked_tasklet(struct drm_device *dev, - void (*tasklet)(struct drm_device *dev)) -{ - DRM_SPINLOCK(&dev->tsk_lock); - if (dev->locked_task_call != NULL) { - DRM_SPINUNLOCK(&dev->tsk_lock); - return; - } - - dev->locked_task_call = tasklet; - DRM_SPINUNLOCK(&dev->tsk_lock); - taskqueue_enqueue(taskqueue_swi, &dev->locked_task); -} Modified: projects/jbuild/sys/dev/drm/drm_lock.c ============================================================================== --- projects/jbuild/sys/dev/drm/drm_lock.c Sat Feb 28 17:55:32 2009 (r189179) +++ projects/jbuild/sys/dev/drm/drm_lock.c Sat Feb 28 17:56:11 2009 (r189180) @@ -115,13 +115,6 @@ int drm_unlock(struct drm_device *dev, v return EINVAL; } - DRM_SPINLOCK(&dev->tsk_lock); - if (dev->locked_task_call != NULL) { - dev->locked_task_call(dev); - dev->locked_task_call = NULL; - } - DRM_SPINUNLOCK(&dev->tsk_lock); - atomic_inc(&dev->counts[_DRM_STAT_UNLOCKS]); DRM_LOCK(); Modified: projects/jbuild/sys/dev/drm/i915_dma.c ============================================================================== --- projects/jbuild/sys/dev/drm/i915_dma.c Sat Feb 28 17:55:32 2009 (r189179) +++ projects/jbuild/sys/dev/drm/i915_dma.c Sat Feb 28 17:56:11 2009 (r189180) @@ -58,6 +58,9 @@ int i915_wait_ring(struct drm_device * d if (ring->space >= n) return 0; + if (dev_priv->sarea_priv) + dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT; + if (ring->head != last_head) i = 0; @@ -72,77 +75,53 @@ int i915_wait_ring(struct drm_device * d return -EBUSY; } -int i915_init_hardware_status(struct drm_device *dev) +/** + * Sets up the hardware status page for devices that need a physical address + * in the register. + */ +static int i915_init_phys_hws(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; - drm_dma_handle_t *dmah; /* Program Hardware Status Page */ -#ifdef __FreeBSD__ DRM_UNLOCK(); -#endif - dmah = drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff); -#ifdef __FreeBSD__ + dev_priv->status_page_dmah = + drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff); DRM_LOCK(); -#endif - if (!dmah) { + if (!dev_priv->status_page_dmah) { DRM_ERROR("Can not allocate hardware status page\n"); return -ENOMEM; } - - dev_priv->status_page_dmah = dmah; - dev_priv->hw_status_page = dmah->vaddr; - dev_priv->dma_status_page = dmah->busaddr; + dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr; + dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr; memset(dev_priv->hw_status_page, 0, PAGE_SIZE); - I915_WRITE(0x02080, dev_priv->dma_status_page); + I915_WRITE(HWS_PGA, dev_priv->dma_status_page); DRM_DEBUG("Enabled hardware status page\n"); return 0; } -void i915_free_hardware_status(struct drm_device *dev) +/** + * Frees the hardware status page, whether it's a physical address or a virtual + * address set up by the X Server. + */ +static void i915_free_hws(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; if (dev_priv->status_page_dmah) { drm_pci_free(dev, dev_priv->status_page_dmah); dev_priv->status_page_dmah = NULL; - /* Need to rewrite hardware status page */ - I915_WRITE(0x02080, 0x1ffff000); } if (dev_priv->status_gfx_addr) { dev_priv->status_gfx_addr = 0; drm_core_ioremapfree(&dev_priv->hws_map, dev); - I915_WRITE(0x02080, 0x1ffff000); } -} -#if I915_RING_VALIDATE -/** - * Validate the cached ring tail value - * - * If the X server writes to the ring and DRM doesn't - * reload the head and tail pointers, it will end up writing - * data to the wrong place in the ring, causing havoc. - */ -void i915_ring_validate(struct drm_device *dev, const char *func, int line) -{ - drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_ring_buffer_t *ring = &(dev_priv->ring); - u32 tail = I915_READ(PRB0_TAIL) & HEAD_ADDR; - u32 head = I915_READ(PRB0_HEAD) & HEAD_ADDR; - - if (tail != ring->tail) { - DRM_ERROR("%s:%d head sw %x, hw %x. tail sw %x hw %x\n", - func, line, - ring->head, head, ring->tail, tail); -#ifdef __linux__ - BUG_ON(1); -#endif - } + /* Need to rewrite hardware status page */ + I915_WRITE(HWS_PGA, 0x1ffff000); } -#endif void i915_kernel_lost_context(struct drm_device * dev) { @@ -154,6 +133,9 @@ void i915_kernel_lost_context(struct drm ring->space = ring->head - (ring->tail + 8); if (ring->space < 0) ring->space += ring->Size; + + if (ring->head == ring->tail && dev_priv->sarea_priv) + dev_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY; } static int i915_dma_cleanup(struct drm_device * dev) @@ -168,86 +150,22 @@ static int i915_dma_cleanup(struct drm_d if (dev_priv->ring.virtual_start) { drm_core_ioremapfree(&dev_priv->ring.map, dev); - dev_priv->ring.virtual_start = 0; - dev_priv->ring.map.handle = 0; + dev_priv->ring.virtual_start = NULL; + dev_priv->ring.map.handle = NULL; dev_priv->ring.map.size = 0; } + /* Clear the HWS virtual address at teardown */ if (I915_NEED_GFX_HWS(dev)) - i915_free_hardware_status(dev); + i915_free_hws(dev); return 0; } -#if defined(I915_HAVE_BUFFER) -#define DRI2_SAREA_BLOCK_TYPE(b) ((b) >> 16) -#define DRI2_SAREA_BLOCK_SIZE(b) ((b) & 0xffff) -#define DRI2_SAREA_BLOCK_NEXT(p) \ - ((void *) ((unsigned char *) (p) + \ - DRI2_SAREA_BLOCK_SIZE(*(unsigned int *) p))) - -#define DRI2_SAREA_BLOCK_END 0x0000 -#define DRI2_SAREA_BLOCK_LOCK 0x0001 -#define DRI2_SAREA_BLOCK_EVENT_BUFFER 0x0002 - -static int -setup_dri2_sarea(struct drm_device * dev, - struct drm_file *file_priv, - drm_i915_init_t * init) +static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init) { drm_i915_private_t *dev_priv = dev->dev_private; - int ret; - unsigned int *p, *end, *next; - - mutex_lock(&dev->struct_mutex); - dev_priv->sarea_bo = - drm_lookup_buffer_object(file_priv, - init->sarea_handle, 1); - mutex_unlock(&dev->struct_mutex); - - if (!dev_priv->sarea_bo) { - DRM_ERROR("did not find sarea bo\n"); - return -EINVAL; - } - - ret = drm_bo_kmap(dev_priv->sarea_bo, 0, - dev_priv->sarea_bo->num_pages, - &dev_priv->sarea_kmap); - if (ret) { - DRM_ERROR("could not map sarea bo\n"); - return ret; - } - p = dev_priv->sarea_kmap.virtual; - end = (void *) p + (dev_priv->sarea_bo->num_pages << PAGE_SHIFT); - while (p < end && DRI2_SAREA_BLOCK_TYPE(*p) != DRI2_SAREA_BLOCK_END) { - switch (DRI2_SAREA_BLOCK_TYPE(*p)) { - case DRI2_SAREA_BLOCK_LOCK: - dev->lock.hw_lock = (void *) (p + 1); - dev->sigdata.lock = dev->lock.hw_lock; - break; - } - next = DRI2_SAREA_BLOCK_NEXT(p); - if (next <= p || end < next) { - DRM_ERROR("malformed dri2 sarea: next is %p should be within %p-%p\n", - next, p, end); - return -EINVAL; - } - p = next; - } - - return 0; -} -#endif - -static int i915_initialize(struct drm_device * dev, - struct drm_file *file_priv, - drm_i915_init_t * init) -{ - drm_i915_private_t *dev_priv = dev->dev_private; -#if defined(I915_HAVE_BUFFER) - int ret; -#endif dev_priv->sarea = drm_getsarea(dev); if (!dev_priv->sarea) { DRM_ERROR("can not find sarea!\n"); @@ -255,20 +173,17 @@ static int i915_initialize(struct drm_de return -EINVAL; } -#ifdef I915_HAVE_BUFFER - dev_priv->max_validate_buffers = I915_MAX_VALIDATE_BUFFERS; -#endif - - if (init->sarea_priv_offset) - dev_priv->sarea_priv = (drm_i915_sarea_t *) - ((u8 *) dev_priv->sarea->handle + - init->sarea_priv_offset); - else { - /* No sarea_priv for you! */ - dev_priv->sarea_priv = NULL; - } + dev_priv->sarea_priv = (drm_i915_sarea_t *) + ((u8 *) dev_priv->sarea->handle + init->sarea_priv_offset); if (init->ring_size != 0) { + if (dev_priv->ring.ring_obj != NULL) { + i915_dma_cleanup(dev); + DRM_ERROR("Client tried to initialize ringbuffer in " + "GEM mode\n"); + return -EINVAL; + } + dev_priv->ring.Size = init->ring_size; dev_priv->ring.tail_mask = dev_priv->ring.Size - 1; @@ -286,41 +201,20 @@ static int i915_initialize(struct drm_de " ring buffer\n"); return -ENOMEM; } - - dev_priv->ring.virtual_start = dev_priv->ring.map.handle; } - dev_priv->cpp = init->cpp; - - if (dev_priv->sarea_priv) - dev_priv->sarea_priv->pf_current_page = 0; + dev_priv->ring.virtual_start = dev_priv->ring.map.handle; - /* We are using separate values as placeholders for mechanisms for - * private backbuffer/depthbuffer usage. - */ + dev_priv->cpp = init->cpp; + 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 = dev_priv->current_page; /* Allow hardware batchbuffers unless told otherwise. */ dev_priv->allow_batchbuffer = 1; - /* Enable vblank on pipe A for older X servers - */ - dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A; - -#ifdef I915_HAVE_BUFFER - mutex_init(&dev_priv->cmdbuf_mutex); -#endif -#if defined(I915_HAVE_BUFFER) - if (init->func == I915_INIT_DMA2) { - ret = setup_dri2_sarea(dev, file_priv, init); - if (ret) { - i915_dma_cleanup(dev); - DRM_ERROR("could not set up dri2 sarea\n"); - return ret; - } - } -#endif - return 0; } @@ -349,9 +243,9 @@ static int i915_dma_resume(struct drm_de DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page); if (dev_priv->status_gfx_addr != 0) - I915_WRITE(0x02080, dev_priv->status_gfx_addr); + I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr); else - I915_WRITE(0x02080, dev_priv->dma_status_page); + I915_WRITE(HWS_PGA, dev_priv->dma_status_page); DRM_DEBUG("Enabled hardware status page\n"); return 0; @@ -365,8 +259,7 @@ static int i915_dma_init(struct drm_devi switch (init->func) { case I915_INIT_DMA: - case I915_INIT_DMA2: - retcode = i915_initialize(dev, file_priv, init); + retcode = i915_initialize(dev, init); break; case I915_CLEANUP_DMA: retcode = i915_dma_cleanup(dev); @@ -541,55 +434,28 @@ int i915_emit_box(struct drm_device * de * emit. For now, do it in both places: */ -void i915_emit_breadcrumb(struct drm_device *dev) +static void i915_emit_breadcrumb(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; RING_LOCALS; - if (++dev_priv->counter > BREADCRUMB_MASK) { - dev_priv->counter = 1; - DRM_DEBUG("Breadcrumb counter wrapped around\n"); - } - + dev_priv->counter++; + if (dev_priv->counter > 0x7FFFFFFFUL) + dev_priv->counter = 0; if (dev_priv->sarea_priv) dev_priv->sarea_priv->last_enqueue = dev_priv->counter; BEGIN_LP_RING(4); OUT_RING(MI_STORE_DWORD_INDEX); - OUT_RING(5 << MI_STORE_DWORD_INDEX_SHIFT); + OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT); OUT_RING(dev_priv->counter); OUT_RING(0); ADVANCE_LP_RING(); } - -int i915_emit_mi_flush(struct drm_device *dev, uint32_t flush) -{ - drm_i915_private_t *dev_priv = dev->dev_private; - uint32_t flush_cmd = MI_FLUSH; - RING_LOCALS; - - flush_cmd |= flush; - - i915_kernel_lost_context(dev); - - BEGIN_LP_RING(4); - OUT_RING(flush_cmd); - OUT_RING(0); - OUT_RING(0); - OUT_RING(0); - ADVANCE_LP_RING(); - - return 0; -} - - static int i915_dispatch_cmdbuffer(struct drm_device * dev, drm_i915_cmdbuffer_t * cmd) { -#ifdef I915_HAVE_FENCE - drm_i915_private_t *dev_priv = dev->dev_private; -#endif int nbox = cmd->num_cliprects; int i = 0, count, ret; @@ -616,15 +482,11 @@ static int i915_dispatch_cmdbuffer(struc } i915_emit_breadcrumb(dev); -#ifdef I915_HAVE_FENCE - if (unlikely((dev_priv->counter & 0xFF) == 0)) - drm_fence_flush_old(dev, 0, dev_priv->counter); -#endif return 0; } -int i915_dispatch_batchbuffer(struct drm_device * dev, - drm_i915_batchbuffer_t * batch) +static int i915_dispatch_batchbuffer(struct drm_device * dev, + drm_i915_batchbuffer_t * batch) { drm_i915_private_t *dev_priv = dev->dev_private; struct drm_clip_rect __user *boxes = batch->cliprects; @@ -649,14 +511,7 @@ int i915_dispatch_batchbuffer(struct drm return ret; } - if (IS_I830(dev) || IS_845G(dev)) { - BEGIN_LP_RING(4); - OUT_RING(MI_BATCH_BUFFER); - OUT_RING(batch->start | MI_BATCH_NON_SECURE); - OUT_RING(batch->start + batch->used - 4); - OUT_RING(0); - ADVANCE_LP_RING(); - } else { + if (!IS_I830(dev) && !IS_845G(dev)) { BEGIN_LP_RING(2); if (IS_I965G(dev)) { OUT_RING(MI_BATCH_BUFFER_START | (2 << 6) | MI_BATCH_NON_SECURE_I965); @@ -666,115 +521,90 @@ int i915_dispatch_batchbuffer(struct drm OUT_RING(batch->start | MI_BATCH_NON_SECURE); } ADVANCE_LP_RING(); + } else { + BEGIN_LP_RING(4); + OUT_RING(MI_BATCH_BUFFER); + OUT_RING(batch->start | MI_BATCH_NON_SECURE); + OUT_RING(batch->start + batch->used - 4); + OUT_RING(0); + ADVANCE_LP_RING(); } } i915_emit_breadcrumb(dev); -#ifdef I915_HAVE_FENCE - if (unlikely((dev_priv->counter & 0xFF) == 0)) - drm_fence_flush_old(dev, 0, dev_priv->counter); -#endif + return 0; } -static void i915_do_dispatch_flip(struct drm_device * dev, int plane, int sync) +static int i915_dispatch_flip(struct drm_device * dev) { drm_i915_private_t *dev_priv = dev->dev_private; - u32 num_pages, current_page, next_page, dspbase; - int shift = 2 * plane, x, y; RING_LOCALS; - /* Calculate display base offset */ - num_pages = dev_priv->sarea_priv->third_handle ? 3 : 2; - current_page = (dev_priv->sarea_priv->pf_current_page >> shift) & 0x3; - next_page = (current_page + 1) % num_pages; + if (!dev_priv->sarea_priv) + return -EINVAL; - switch (next_page) { - default: - case 0: - dspbase = dev_priv->sarea_priv->front_offset; - break; - case 1: - dspbase = dev_priv->sarea_priv->back_offset; - break; - case 2: - dspbase = dev_priv->sarea_priv->third_offset; - break; - } + DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n", + __func__, + dev_priv->current_page, + dev_priv->sarea_priv->pf_current_page); + + i915_kernel_lost_context(dev); - if (plane == 0) { - x = dev_priv->sarea_priv->planeA_x; - y = dev_priv->sarea_priv->planeA_y; + BEGIN_LP_RING(2); + OUT_RING(MI_FLUSH | MI_READ_FLUSH); + OUT_RING(0); + ADVANCE_LP_RING(); + *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200902281756.n1SHuBak017020>