summaryrefslogtreecommitdiff
path: root/shared-core/i915_irq.c
AgeCommit message (Expand)Author
2008-08-24i915: Fix i915 build on FreeBSDRobert Noland
2008-08-24i915: Convert vblank on disabled pipe DRM_ERROR to DRM_DEBUG.Robert Noland
2008-08-24i915: Move spinlock init / destroy to load / unload time.Robert Noland
2008-08-08Merge branch 'drm-gem'Eric Anholt
2008-08-01Revert "i915: Move all of the irq install/uninstall to load time."Dave Airlie
2008-07-30i915: more version checksDave Airlie
2008-07-28Merge commit 'origin/master' into drm-gemEric Anholt
2008-07-23i915: Move all of the irq install/uninstall to load time.Robert Noland
2008-07-19i915: convert to using drm_vblank_get/put around vblank counter usageJesse Barnes
2008-07-17i915: remove old broken vblank codeJesse Barnes
2008-07-15This is a modified version of Hong's patch from last month, with a fewHong Liu
2008-07-01i915: only use tiled blits on 965+Jesse Barnes
2008-06-24[intel] Get vblank pipe from irq_mask_reg instead of hardware enable regKeith Packard
2008-06-24[intel] Create functions to enable/disable interruptsKeith Packard
2008-06-24i915: register definition & header file cleanupJesse Barnes
2008-06-21[intel] Use IMR instead of IER to pend interrupts during ISRKeith Packard
2008-06-21[intel] Count received interruptsKeith Packard
2008-06-20[intel-gem] Add intel-specific /proc entries to help monitor gem operationKeith Packard
2008-06-13[intel] Enable MSI for i915 IRQKeith Packard
2008-06-13[intel] Restructure irq to pend all work until after iir write.Keith Packard
2008-06-13Fix i915_wait_irq in the presence of interrupt masking.Eric Anholt
2008-06-13[gem] Remove the interrupt handler for retiring requests.Eric Anholt
2008-06-12Don't clear USER_INTERRUPT if we're not handling it.Eric Anholt
2008-06-10[intel] Fix BUG_ON trigger in irq masking if you did on/off with irqs disabled.Eric Anholt
2008-06-10[gem] Manage the ringbuffer from the kernel in the GEM case.Eric Anholt
2008-05-30Merge commit 'origin/master' into drm-gemEric Anholt
2008-05-27[FreeBSD] Add vblank-rework support and get drivers building.Robert Noland
2008-05-26[i915] leave interrupts masked off when not in use.Keith Packard
2008-05-22[gem] Release GEM buffers from work task scheduled from IRQ.Eric Anholt
2008-05-06GEM: Use irq-based fencing rather than syncing and evicting every exec.Eric Anholt
2008-04-20[I915] Handle tiled buffers in vblank taskletKeith Packard
2008-04-20On I965, use correct 3DSTATE_DRAWING_RECTANGLE command in vblankKeith Packard
2008-03-08Switch from PIPE_VBLANK to PIPE_EVENT interrupts.Keith Packard
2008-03-03 [i915] 2D driver may reset Frame count value, this may lead driverZou Nan hai
2008-02-13i915: Make sarea_priv setup optional.Kristian Høgsberg
2008-01-24Remove broken 'in vblank' accountingJesse Barnes
2008-01-23Fix thinko in get_vblank_counterJesse Barnes
2008-01-22Correct vblank count valueJesse Barnes
2008-01-22i915 irq fixesJesse Barnes
2008-01-22Merge branch 'master' into vblank-rework, including mach64 supportJesse Barnes
2008-01-22Revert "Fix pipe<->plane mapping vs. vblank handling (again)"Dave Airlie
2008-01-03drm: cleanup DRM_DEBUG() parametersMárton Németh
2007-12-17drm: don't cast a pointer to pointer of list_headLi Zefan
2007-12-07Fix pipe<->plane mapping vs. vblank handling (again)Jesse Barnes
2007-12-05Remove references to the sarea_priv perf_boxes field.Kristian Høgsberg
2007-11-06i915: cleanup most of the whitespaceDave Airlie
2007-11-05drm: remove lots of spurious whitespace.Dave Airlie
2007-10-30Merge branch 'master' into vblank-rework, fixup remaining driversJesse Barnes
2007-10-14i915: fix vbl_swap allocationDave Airlie
2007-09-18i915: Reinstate check that drawable has valid information in i915_vblank_swap.Michel Dänzer
">, int start, int size, struct drm_file *file_priv) { /* Maybe cut off the start of an existing block */ if (start > p->start) { struct mem_block *newblock = drm_alloc(sizeof(*newblock), DRM_MEM_BUFS); if (!newblock) goto out; newblock->start = start; newblock->size = p->size - (start - p->start); newblock->file_priv = NULL; newblock->next = p->next; newblock->prev = p; p->next->prev = newblock; p->next = newblock; p->size -= newblock->size; p = newblock; } /* Maybe cut off the end of an existing block */ if (size < p->size) { struct mem_block *newblock = drm_alloc(sizeof(*newblock), DRM_MEM_BUFS); if (!newblock) goto out; newblock->start = start + size; newblock->size = p->size - size; newblock->file_priv = NULL; newblock->next = p->next; newblock->prev = p; p->next->prev = newblock; p->next = newblock; p->size = size; } out: /* Our block is in the middle */ p->file_priv = file_priv; return p; } static struct mem_block *alloc_block(struct mem_block *heap, int size, int align2, struct drm_file *file_priv) { struct mem_block *p; int mask = (1 << align2) - 1; list_for_each(p, heap) { int start = (p->start + mask) & ~mask; if (p->file_priv == 0 && start + size <= p->start + p->size) return split_block(p, start, size, file_priv); } return NULL; } static struct mem_block *find_block(struct mem_block *heap, int start) { struct mem_block *p; list_for_each(p, heap) if (p->start == start) return p; return NULL; } static void free_block(struct mem_block *p) { p->file_priv = NULL; /* Assumes a single contiguous range. Needs a special file_priv in * 'heap' to stop it being subsumed. */ if (p->next->file_priv == 0) { struct mem_block *q = p->next; p->size += q->size; p->next = q->next; p->next->prev = p; drm_free(q, sizeof(*q), DRM_MEM_BUFS); } if (p->prev->file_priv == 0) { struct mem_block *q = p->prev; q->size += p->size; q->next = p->next; q->next->prev = q; drm_free(p, sizeof(*q), DRM_MEM_BUFS); } } /* Initialize. How to check for an uninitialized heap? */ static int init_heap(struct mem_block **heap, int start, int size) { struct mem_block *blocks = drm_alloc(sizeof(*blocks), DRM_MEM_BUFS); if (!blocks) return -ENOMEM; *heap = drm_alloc(sizeof(**heap), DRM_MEM_BUFS); if (!*heap) { drm_free(blocks, sizeof(*blocks), DRM_MEM_BUFS); return -ENOMEM; } blocks->start = start; blocks->size = size; blocks->file_priv = NULL; blocks->next = blocks->prev = *heap; memset(*heap, 0, sizeof(**heap)); (*heap)->file_priv = (struct drm_file *) - 1; (*heap)->next = (*heap)->prev = blocks; return 0; } /* Free all blocks associated with the releasing file. */ void radeon_mem_release(struct drm_file *file_priv, struct mem_block *heap) { struct mem_block *p; if (!heap || !heap->next) return; list_for_each(p, heap) { if (p->file_priv == file_priv) p->file_priv = NULL; } /* Assumes a single contiguous range. Needs a special file_priv in * 'heap' to stop it being subsumed. */ list_for_each(p, heap) { while (p->file_priv == 0 && p->next->file_priv == 0) { struct mem_block *q = p->next; p->size += q->size; p->next = q->next; p->next->prev = p; drm_free(q, sizeof(*q), DRM_MEM_DRIVER); } } } /* Shutdown. */ void radeon_mem_takedown(struct mem_block **heap) { struct mem_block *p; if (!*heap) return; for (p = (*heap)->next; p != *heap;) { struct mem_block *q = p; p = p->next; drm_free(q, sizeof(*q), DRM_MEM_DRIVER); } drm_free(*heap, sizeof(**heap), DRM_MEM_DRIVER); *heap = NULL; } /* IOCTL HANDLERS */ static struct mem_block **get_heap(drm_radeon_private_t * dev_priv, int region) { switch (region) { case RADEON_MEM_REGION_GART: return &dev_priv->gart_heap; case RADEON_MEM_REGION_FB: return &dev_priv->fb_heap; default: return NULL; } } int radeon_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv) { drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_mem_alloc_t *alloc = data; struct mem_block *block, **heap; if (!dev_priv) { DRM_ERROR("called with no initialization\n"); return -EINVAL; } heap = get_heap(dev_priv, alloc->region); if (!heap || !*heap) return -EFAULT; /* Make things easier on ourselves: all allocations at least * 4k aligned. */ if (alloc->alignment < 12) alloc->alignment = 12; block = alloc_block(*heap, alloc->size, alloc->alignment, file_priv); if (!block) return -ENOMEM; if (DRM_COPY_TO_USER(alloc->region_offset, &block->start, sizeof(int))) { DRM_ERROR("copy_to_user\n"); return -EFAULT; } return 0; } int radeon_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv) { drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_mem_free_t *memfree = data; struct mem_block *block, **heap; if (!dev_priv) { DRM_ERROR("called with no initialization\n"); return -EINVAL; } heap = get_heap(dev_priv, memfree->region); if (!heap || !*heap) return -EFAULT; block = find_block(*heap, memfree->region_offset); if (!block) return -EFAULT; if (block->file_priv != file_priv) return -EPERM; free_block(block); return 0; } int radeon_mem_init_heap(struct drm_device *dev, void *data, struct drm_file *file_priv) { drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_mem_init_heap_t *initheap = data; struct mem_block **heap; if (!dev_priv) { DRM_ERROR("called with no initialization\n"); return -EINVAL; } heap = get_heap(dev_priv, initheap->region); if (!heap) return -EFAULT; if (*heap) { DRM_ERROR("heap already initialized?"); return -EFAULT; } return init_heap(heap, initheap->start, initheap->size); }