diff options
author | Owain Ainsworth <oga@cvs.openbsd.org> | 2009-03-05 23:13:20 +0000 |
---|---|---|
committer | Owain Ainsworth <oga@cvs.openbsd.org> | 2009-03-05 23:13:20 +0000 |
commit | 74bda0dc265c77d54121fd81eff2e117dd94b84f (patch) | |
tree | e37db4676fdd5bb625a63040b07b844b88f9bcff | |
parent | 858e68db6a84849e08604401cd78424b24e40935 (diff) |
Demacro the inteldrm ring macros too, making them use bus_space_write
instead of assuming BUS_SPACE_LINEAR + bus_space_vaddr while i'm at
it.
Cleans things up nicely, and shaves a little bit of space, too.
-rw-r--r-- | sys/dev/pci/drm/i915_dma.c | 144 | ||||
-rw-r--r-- | sys/dev/pci/drm/i915_drv.c | 91 | ||||
-rw-r--r-- | sys/dev/pci/drm/i915_drv.h | 75 | ||||
-rw-r--r-- | sys/dev/pci/drm/i915_irq.c | 3 |
4 files changed, 162 insertions, 151 deletions
diff --git a/sys/dev/pci/drm/i915_dma.c b/sys/dev/pci/drm/i915_dma.c index bd607a30413..c70136ec840 100644 --- a/sys/dev/pci/drm/i915_dma.c +++ b/sys/dev/pci/drm/i915_dma.c @@ -31,44 +31,6 @@ #include "i915_drm.h" #include "i915_drv.h" -/* Really want an OS-independent resettable timer. Would like to have - * this loop run for (eg) 3 sec, but have the timer reset every time - * the head pointer changes, so that EBUSY only happens if the ring - * actually stalls for (eg) 3 seconds. - */ -int i915_wait_ring(struct drm_device * dev, int n, const char *caller) -{ - drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_ring_buffer_t *ring = &(dev_priv->ring); - u_int32_t acthd_reg = IS_I965G(dev_priv) ? ACTHD_I965 : ACTHD; - u_int32_t last_acthd = I915_READ(acthd_reg); - u_int32_t acthd; - u_int32_t last_head = I915_READ(PRB0_HEAD) & HEAD_ADDR; - int i; - - for (i = 0; i < 100000; i++) { - ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR; - acthd = I915_READ(acthd_reg); - ring->space = ring->head - (ring->tail + 8); - if (ring->space < 0) - ring->space += ring->Size; - if (ring->space >= n) - return 0; - - if (ring->head != last_head) - i = 0; - if (acthd != last_acthd) - i = 0; - - last_head = ring->head; - last_acthd = acthd; - tsleep(dev_priv, PZERO | PCATCH, "i915wt", - hz / 100); - } - - return EBUSY; -} - /** * Sets up the hardware status page for devices that need a physical address * in the register. @@ -106,7 +68,8 @@ void i915_free_hws(drm_i915_private_t *dev_priv, bus_dma_tag_t dmat) if (dev_priv->status_gfx_addr) { dev_priv->status_gfx_addr = 0; - drm_core_ioremapfree(&dev_priv->hws_map); + bus_space_unmap(dev_priv->bst, dev_priv->hws_map.bsh, 4 * 1024); + dev_priv->hws_map.bsh = NULL; } /* Need to rewrite hardware status page */ @@ -114,27 +77,15 @@ void i915_free_hws(drm_i915_private_t *dev_priv, bus_dma_tag_t dmat) dev_priv->hw_status_page = NULL; } -void i915_kernel_lost_context(struct drm_device * dev) -{ - drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_ring_buffer_t *ring = &(dev_priv->ring); - - ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR; - ring->tail = I915_READ(PRB0_TAIL) & TAIL_ADDR; - ring->space = ring->head - (ring->tail + 8); - if (ring->space < 0) - ring->space += ring->Size; -} - static int i915_dma_cleanup(struct drm_device * dev) { drm_i915_private_t *dev_priv = dev->dev_private; - if (dev_priv->ring.virtual_start) { - drm_core_ioremapfree(&dev_priv->ring.map); - dev_priv->ring.virtual_start = NULL; - dev_priv->ring.map.handle = NULL; - dev_priv->ring.map.size = 0; + if (dev_priv->ring.bsh != NULL) { + bus_space_unmap(dev_priv->bst, dev_priv->ring.bsh, + dev_priv->ring.size); + dev_priv->ring.bsh = NULL; + dev_priv->ring.size = 0; } /* Clear the HWS virtual address at teardown */ @@ -146,7 +97,8 @@ 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; + drm_i915_private_t *dev_priv = dev->dev_private; + int ret; dev_priv->sarea = drm_getsarea(dev); if (!dev_priv->sarea) { @@ -164,26 +116,16 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init) dev_priv->sarea_priv = NULL; } - dev_priv->ring.Size = init->ring_size; - dev_priv->ring.tail_mask = dev_priv->ring.Size - 1; - - dev_priv->ring.map.offset = init->ring_start; - dev_priv->ring.map.size = init->ring_size; - dev_priv->ring.map.type = 0; - dev_priv->ring.map.flags = 0; - dev_priv->ring.map.mtrr = 0; - - drm_core_ioremap(&dev_priv->ring.map, dev); + dev_priv->ring.size = init->ring_size; + dev_priv->ring.tail_mask = dev_priv->ring.size - 1; - if (dev_priv->ring.map.handle == NULL) { + if ((ret = bus_space_map(dev_priv->bst, init->ring_start, + init->ring_size, 0, &dev_priv->ring.bsh)) != 0) { + DRM_INFO("can't map ringbuffer\n"); i915_dma_cleanup(dev); - DRM_ERROR("can not ioremap virtual address for" - " ring buffer\n"); - return ENOMEM; + return (ret); } - dev_priv->ring.virtual_start = dev_priv->ring.map.handle; - /* Allow hardware batchbuffers unless told otherwise. */ dev_priv->allow_batchbuffer = 1; @@ -202,9 +144,8 @@ static int i915_dma_resume(struct drm_device * dev) return EINVAL; } - if (dev_priv->ring.map.handle == NULL) { - DRM_ERROR("can not ioremap virtual address for" - " ring buffer\n"); + if (dev_priv->ring.bsh == NULL) { + DRM_ERROR("dma_resume without mapped ring buffer\n"); return ENOMEM; } @@ -333,9 +274,8 @@ static int i915_emit_cmds(struct drm_device *dev, int __user *buffer, { drm_i915_private_t *dev_priv = dev->dev_private; int i; - RING_LOCALS; - if ((dwords+1) * sizeof(int) >= dev_priv->ring.Size - 8) + if ((dwords + 1) * sizeof(u_int32_t) >= dev_priv->ring.size - 8) return EINVAL; BEGIN_LP_RING((dwords+1)&~1); @@ -374,7 +314,6 @@ static int i915_emit_box(struct drm_device * dev, { drm_i915_private_t *dev_priv = dev->dev_private; struct drm_clip_rect box; - RING_LOCALS; if (DRM_COPY_FROM_USER_UNCHECKED(&box, &boxes[i], sizeof(box))) { return EFAULT; @@ -414,7 +353,6 @@ static int i915_emit_box(struct drm_device * dev, 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; @@ -435,6 +373,7 @@ void i915_emit_breadcrumb(struct drm_device *dev) static int i915_dispatch_cmdbuffer(struct drm_device * dev, drm_i915_cmdbuffer_t * cmd) { + struct drm_i915_private *dev_priv = dev->dev_private; int nbox = cmd->num_cliprects; int i = 0, count, ret; @@ -443,7 +382,7 @@ static int i915_dispatch_cmdbuffer(struct drm_device * dev, return EINVAL; } - i915_kernel_lost_context(dev); + inteldrm_update_ring(dev_priv); count = nbox ? nbox : 1; @@ -471,14 +410,13 @@ int i915_dispatch_batchbuffer(struct drm_device * dev, struct drm_clip_rect __user *boxes = batch->cliprects; int nbox = batch->num_cliprects; int i = 0, count; - RING_LOCALS; if ((batch->start | batch->used) & 0x7) { DRM_ERROR("alignment\n"); return EINVAL; } - i915_kernel_lost_context(dev); + inteldrm_update_ring(dev_priv); count = nbox ? nbox : 1; @@ -515,23 +453,17 @@ int i915_dispatch_batchbuffer(struct drm_device * dev, return 0; } -int i915_quiescent(struct drm_device *dev) -{ - drm_i915_private_t *dev_priv = dev->dev_private; - - i915_kernel_lost_context(dev); - return i915_wait_ring(dev, dev_priv->ring.Size - 8, __func__); -} - int i915_flush_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { - int ret; + drm_i915_private_t *dev_priv = dev->dev_private; + int ret; LOCK_TEST_WITH_RETURN(dev, file_priv); DRM_LOCK(); - ret = i915_quiescent(dev); + inteldrm_update_ring(dev_priv); + ret = inteldrm_wait_ring(dev_priv, dev_priv->ring.size - 8); DRM_UNLOCK(); return (ret); @@ -678,8 +610,9 @@ int i915_setparam(struct drm_device *dev, void *data, int i915_set_status_page(struct drm_device *dev, void *data, struct drm_file *file_priv) { - drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_hws_addr_t *hws = data; + drm_i915_private_t *dev_priv = dev->dev_private; + drm_i915_hws_addr_t *hws = data; + int ret; if (!I915_NEED_GFX_HWS(dev_priv)) return EINVAL; @@ -693,20 +626,23 @@ int i915_set_status_page(struct drm_device *dev, void *data, dev_priv->status_gfx_addr = hws->addr & (0x1ffff<<12); dev_priv->hws_map.offset = dev->agp->base + hws->addr; + if (dev_priv->hws_map.offset > (dev->agp->base + + dev->agp->info.ai_aperture_size)) { + DRM_INFO("tried to map hws past end of aperture!\n"); + return (EINVAL); + } dev_priv->hws_map.size = 4*1024; - dev_priv->hws_map.type = 0; - dev_priv->hws_map.flags = 0; - dev_priv->hws_map.mtrr = 0; - drm_core_ioremap(&dev_priv->hws_map, dev); - if (dev_priv->hws_map.handle == NULL) { + if ((ret = bus_space_map(dev_priv->bst, dev_priv->hws_map.offset, + dev_priv->hws_map.size, BUS_SPACE_MAP_LINEAR, + &dev_priv->hws_map.bsh)) != 0) { + DRM_INFO("can't hws page\n"); i915_dma_cleanup(dev); dev_priv->status_gfx_addr = 0; - DRM_ERROR("can not ioremap virtual address for" - " G33 hw status page\n"); - return ENOMEM; + return (ret); } - dev_priv->hw_status_page = dev_priv->hws_map.handle; + dev_priv->hw_status_page = bus_space_vaddr(dev_priv->bst, + dev_priv->hws_map.bsh); memset(dev_priv->hw_status_page, 0, PAGE_SIZE); I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr); diff --git a/sys/dev/pci/drm/i915_drv.c b/sys/dev/pci/drm/i915_drv.c index 96ec2ce995a..5b6c53e247b 100644 --- a/sys/dev/pci/drm/i915_drv.c +++ b/sys/dev/pci/drm/i915_drv.c @@ -2,6 +2,7 @@ * Created: Wed Feb 14 17:10:04 2001 by gareth@valinux.com */ /*- + * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. * All Rights Reserved. * @@ -131,7 +132,10 @@ inteldrm_attach(struct device *parent, struct device *self, void *aux) PCI_PRODUCT(pa->pa_id), inteldrm_pciidlist); dev_priv->flags = id_entry->driver_private; dev_priv->pci_device = PCI_PRODUCT(pa->pa_id); + dev_priv->pc = pa->pa_pc; + dev_priv->dmat = pa->pa_dmat; + dev_priv->bst = pa->pa_memt; /* Add register map (needed for suspend/resume) */ bar = vga_pci_bar_info((struct vga_pci_softc *)parent, @@ -266,3 +270,90 @@ inteldrm_read_hws(struct drm_i915_private *dev_priv, int reg) PAGE_SIZE, BUS_DMASYNC_PREREAD); return (val); } + +/* + * These five ring manipulation functions are protected by dev->dev_lock. + */ +int +inteldrm_wait_ring(struct drm_i915_private *dev_priv, int n) +{ + struct inteldrm_ring *ring = &dev_priv->ring; + u_int32_t acthd_reg, acthd, last_acthd, last_head; + int i; + + acthd_reg = IS_I965G(dev_priv) ? ACTHD_I965 : ACTHD; + last_head = I915_READ(PRB0_HEAD) & HEAD_ADDR; + last_acthd = I915_READ(acthd_reg); + + /* ugh. Could really do with a proper, resettable timer here. */ + for (i = 0; i < 100000; i++) { + ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR; + acthd = I915_READ(acthd_reg); + ring->space = ring->head - (ring->tail + 8); + + INTELDRM_VPRINTF("%s: head: %x tail: %x space: %x\n", __func__, + ring->head, ring->tail, ring->space); + if (ring->space < 0) + ring->space += ring->size; + if (ring->space >= n) + return (0); + + /* Only timeout if the ring isn't chewing away on something */ + if (ring->head != last_head || acthd != last_acthd) + i = 0; + + last_head = ring->head; + last_acthd = acthd; + tsleep(dev_priv, PZERO | PCATCH, "i915wt", + hz / 100); + } + + return (EBUSY); +} + +void +inteldrm_begin_ring(struct drm_i915_private *dev_priv, int ncmd) +{ + INTELDRM_VPRINTF("%s: %d\n", __func__, ncmd); + if (dev_priv->ring.space < ncmd * 4) + inteldrm_wait_ring(dev_priv, ncmd * 4); + dev_priv->ring.wspace = 0; + dev_priv->ring.woffset = dev_priv->ring.tail; +} + +void +inteldrm_out_ring(struct drm_i915_private *dev_priv, u_int32_t cmd) +{ + INTELDRM_VPRINTF("%s: %x\n", __func__, cmd); + bus_space_write_4(dev_priv->bst, dev_priv->ring.bsh, + dev_priv->ring.woffset, cmd); + dev_priv->ring.wspace++; + /* deal with ring wrapping */ + dev_priv->ring.woffset += 4; + dev_priv->ring.woffset &= dev_priv->ring.tail_mask; +} + +void +inteldrm_advance_ring(struct drm_i915_private *dev_priv) +{ + INTELDRM_VPRINTF("%s: %x, %x\n", __func__, dev_priv->ring.wspace, + dev_priv->ring.woffset); + dev_priv->ring.tail = dev_priv->ring.woffset; + dev_priv->ring.space -= dev_priv->ring.wspace * 4; + I915_WRITE(PRB0_TAIL, dev_priv->ring.woffset); +} + +void +inteldrm_update_ring(struct drm_i915_private *dev_priv) +{ + struct inteldrm_ring *ring = &dev_priv->ring; + + ring->head = (I915_READ(PRB0_HEAD) & HEAD_ADDR); + ring->tail = (I915_READ(PRB0_TAIL) & TAIL_ADDR); + ring->space = ring->head - (ring->tail + 8); + if (ring->space < 0) + ring->space += ring->size; + INTELDRM_VPRINTF("%s: head: %x tail: %x space: %x\n", __func__, + ring->head, ring->tail, ring->space); +} + diff --git a/sys/dev/pci/drm/i915_drv.h b/sys/dev/pci/drm/i915_drv.h index e3e4cdfce81..518655c41d3 100644 --- a/sys/dev/pci/drm/i915_drv.h +++ b/sys/dev/pci/drm/i915_drv.h @@ -58,20 +58,23 @@ enum pipe { #define DRIVER_MINOR 6 #define DRIVER_PATCHLEVEL 0 -typedef struct _drm_i915_ring_buffer { - int tail_mask; - unsigned long Size; - u8 *virtual_start; - int head; - int tail; - int space; - drm_local_map_t map; -} drm_i915_ring_buffer_t; +struct inteldrm_ring { + u_int32_t *kva; + bus_space_handle_t bsh; + bus_size_t size; + u_int32_t head; + u_int32_t space; + u_int32_t tail; + u_int32_t tail_mask; + u_int32_t woffset; + u_int32_t wspace; +}; typedef struct drm_i915_private { struct device dev; struct device *drmdev; bus_dma_tag_t dmat; + bus_space_tag_t bst; u_long flags; u_int16_t pci_device; @@ -85,7 +88,7 @@ typedef struct drm_i915_private { drm_local_map_t *sarea; drm_i915_sarea_t *sarea_priv; - drm_i915_ring_buffer_t ring; + struct inteldrm_ring ring; drm_local_map_t hws_map; struct drm_dmamem *hws_dmamem; void *hw_status_page; @@ -213,9 +216,14 @@ typedef struct drm_i915_private { #define CHIP_M 0x4000 #define CHIP_HWS 0x8000 - /* i915_dma.c */ u_int32_t inteldrm_read_hws(struct drm_i915_private *, int); -extern void i915_kernel_lost_context(struct drm_device * dev); +int inteldrm_wait_ring(struct drm_i915_private *dev, int n); +void inteldrm_begin_ring(struct drm_i915_private *, int); +void inteldrm_out_ring(struct drm_i915_private *, u_int32_t); +void inteldrm_advance_ring(struct drm_i915_private *); +void inteldrm_update_ring(struct drm_i915_private *); + + /* i915_dma.c */ extern void i915_driver_lastclose(struct drm_device * dev); extern void i915_driver_close(struct drm_device *dev, struct drm_file *file_priv); @@ -226,7 +234,6 @@ extern void i915_emit_breadcrumb(struct drm_device *dev); extern int i915_driver_firstopen(struct drm_device *dev); extern int i915_dispatch_batchbuffer(struct drm_device * dev, drm_i915_batchbuffer_t * batch); -extern int i915_quiescent(struct drm_device *dev); int i915_init_phys_hws(drm_i915_private_t *, bus_dma_tag_t); void i915_free_hws(drm_i915_private_t *, bus_dma_tag_t); @@ -289,38 +296,16 @@ extern int i915_set_status_page(struct drm_device *, void *, struct drm_file *); #define I915_WRITE8(reg,val) bus_space_write_1(dev_priv->regs->bst, \ dev_priv->regs->bsh, (reg), (val)) -#define I915_VERBOSE 0 - -#define RING_LOCALS unsigned int outring, ringmask, outcount; \ - volatile char *virt; - -#define BEGIN_LP_RING(n) do { \ - if (I915_VERBOSE) \ - DRM_DEBUG("BEGIN_LP_RING(%d)\n", (n)); \ - if (dev_priv->ring.space < (n)*4) \ - i915_wait_ring(dev, (n)*4, __func__); \ - outcount = 0; \ - outring = dev_priv->ring.tail; \ - ringmask = dev_priv->ring.tail_mask; \ - virt = dev_priv->ring.virtual_start; \ -} while (0) - -#define OUT_RING(n) do { \ - if (I915_VERBOSE) DRM_DEBUG(" OUT_RING %x\n", (int)(n)); \ - *(volatile unsigned int *)(virt + outring) = (n); \ - outcount++; \ - outring += 4; \ - outring &= ringmask; \ -} while (0) - -#define ADVANCE_LP_RING() do { \ - if (I915_VERBOSE) DRM_DEBUG("ADVANCE_LP_RING %x\n", outring); \ - dev_priv->ring.tail = outring; \ - dev_priv->ring.space -= outcount * 4; \ - I915_WRITE(PRB0_TAIL, outring); \ -} while(0) - -extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); +#define INTELDRM_VERBOSE 0 +#if INTELDRM_VERBOSE > 0 +#define INTELDRM_VPRINTF(fmt, args...) DRM_INFO(fmt, ##args) +#else +#define INTELDRM_VPRINTF(fmt, args...) +#endif + +#define BEGIN_LP_RING(n) inteldrm_begin_ring(dev_priv, n) +#define OUT_RING(n) inteldrm_out_ring(dev_priv, n) +#define ADVANCE_LP_RING() inteldrm_advance_ring(dev_priv) /* * The Bridge device's PCI config space has information about the diff --git a/sys/dev/pci/drm/i915_irq.c b/sys/dev/pci/drm/i915_irq.c index 9d6960ab024..0fbebf71413 100644 --- a/sys/dev/pci/drm/i915_irq.c +++ b/sys/dev/pci/drm/i915_irq.c @@ -245,9 +245,8 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) int i915_emit_irq(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; - RING_LOCALS; - i915_kernel_lost_context(dev); + inteldrm_update_ring(dev_priv); DRM_DEBUG("\n"); |