void savage_reclaim_buffers(struct drm_device *dev, struct drm_file *file_priv) { struct drm_device_dma *dma = dev->dma; drm_savage_private_t *dev_priv = dev->dev_private; int i; if (!dma) return; if (!dev_priv) return; if (!dma->buflist) return; /*i830_flush_queue(dev); */ for (i = 0; i < dma->buf_count; i++) { struct drm_buf *buf = dma->buflist[i]; drm_savage_buf_priv_t *buf_priv = buf->dev_private; if (buf->file_priv == file_priv && buf_priv && buf_priv->next == NULL && buf_priv->prev == NULL) { uint16_t event; DRM_DEBUG("reclaimed from client\n"); event = savage_bci_emit_event(dev_priv, SAVAGE_WAIT_3D); SET_AGE(&buf_priv->age, event, dev_priv->event_wrap); savage_freelist_put(dev, buf); } } drm_core_reclaim_buffers(dev, file_priv); }
static int savage_bci_event_emit(struct drm_device *dev, void *data, struct drm_file *file_priv) { drm_savage_private_t *dev_priv = dev->dev_private; drm_savage_event_emit_t *event = data; DRM_DEBUG("\n"); LOCK_TEST_WITH_RETURN(dev, file_priv); event->count = savage_bci_emit_event(dev_priv, event->flags); event->count |= dev_priv->event_wrap << 16; return 0; }
void savage_dma_reset(drm_savage_private_t * dev_priv) { uint16_t event; unsigned int wrap, i; event = savage_bci_emit_event(dev_priv, 0); wrap = dev_priv->event_wrap; for (i = 0; i < dev_priv->nr_dma_pages; ++i) { SET_AGE(&dev_priv->dma_pages[i].age, event, wrap); dev_priv->dma_pages[i].used = 0; dev_priv->dma_pages[i].flushed = 0; } SET_AGE(&dev_priv->last_dma_age, event, wrap); dev_priv->first_dma_page = dev_priv->current_dma_page = 0; }
static int savage_bci_event_emit(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_savage_private_t *dev_priv = dev->dev_private; drm_savage_event_emit_t event; DRM_DEBUG("\n"); LOCK_TEST_WITH_RETURN(dev, filp); DRM_COPY_FROM_USER_IOCTL(event, (drm_savage_event_emit_t __user *)data, sizeof(event)); event.count = savage_bci_emit_event(dev_priv, event.flags); event.count |= dev_priv->event_wrap << 16; DRM_COPY_TO_USER_IOCTL(&((drm_savage_event_emit_t __user *)data)->count, event.count, sizeof(event.count)); return 0; }
void savage_reclaim_buffers(struct drm_device *dev, struct drm_file *file_priv) { struct drm_device_dma *dma = dev->dma; drm_savage_private_t *dev_priv = dev->dev_private; int release_idlelock = 0; int i; if (!dma) return; if (!dev_priv) return; if (!dma->buflist) return; if (file_priv->master && file_priv->master->lock.hw_lock) { drm_idlelock_take(&file_priv->master->lock); release_idlelock = 1; } for (i = 0; i < dma->buf_count; i++) { struct drm_buf *buf = dma->buflist[i]; drm_savage_buf_priv_t *buf_priv = buf->dev_private; if (buf->file_priv == file_priv && buf_priv && buf_priv->next == NULL && buf_priv->prev == NULL) { uint16_t event; DRM_DEBUG("reclaimed from client\n"); event = savage_bci_emit_event(dev_priv, SAVAGE_WAIT_3D); SET_AGE(&buf_priv->age, event, dev_priv->event_wrap); savage_freelist_put(dev, buf); } } if (release_idlelock) drm_idlelock_release(&file_priv->master->lock); }
static void savage_dma_flush(drm_savage_private_t * dev_priv) { unsigned int first = dev_priv->first_dma_page; unsigned int cur = dev_priv->current_dma_page; uint16_t event; unsigned int wrap, pad, align, len, i; unsigned long phys_addr; BCI_LOCALS; if (first == cur && dev_priv->dma_pages[cur].used == dev_priv->dma_pages[cur].flushed) return; /* pad length to multiples of 2 entries * align start of next DMA block to multiles of 8 entries */ pad = -dev_priv->dma_pages[cur].used & 1; align = -(dev_priv->dma_pages[cur].used + pad) & 7; DRM_DEBUG("first=%u, cur=%u, first->flushed=%u, cur->used=%u, " "pad=%u, align=%u\n", first, cur, dev_priv->dma_pages[first].flushed, dev_priv->dma_pages[cur].used, pad, align); /* pad with noops */ if (pad) { uint32_t *dma_ptr = (uint32_t *) dev_priv->cmd_dma->handle + cur * SAVAGE_DMA_PAGE_SIZE + dev_priv->dma_pages[cur].used; dev_priv->dma_pages[cur].used += pad; while (pad != 0) { *dma_ptr++ = BCI_CMD_WAIT; pad--; } } DRM_MEMORYBARRIER(); /* do flush ... */ phys_addr = dev_priv->cmd_dma->offset + (first * SAVAGE_DMA_PAGE_SIZE + dev_priv->dma_pages[first].flushed) * 4; len = (cur - first) * SAVAGE_DMA_PAGE_SIZE + dev_priv->dma_pages[cur].used - dev_priv->dma_pages[first].flushed; DRM_DEBUG("phys_addr=%lx, len=%u\n", phys_addr | dev_priv->dma_type, len); BEGIN_BCI(3); BCI_SET_REGISTERS(SAVAGE_DMABUFADDR, 1); BCI_WRITE(phys_addr | dev_priv->dma_type); BCI_DMA(len); /* fix alignment of the start of the next block */ dev_priv->dma_pages[cur].used += align; /* age DMA pages */ event = savage_bci_emit_event(dev_priv, 0); wrap = dev_priv->event_wrap; for (i = first; i < cur; ++i) { SET_AGE(&dev_priv->dma_pages[i].age, event, wrap); dev_priv->dma_pages[i].used = 0; dev_priv->dma_pages[i].flushed = 0; } /* age the current page only when it's full */ if (dev_priv->dma_pages[cur].used == SAVAGE_DMA_PAGE_SIZE) { SET_AGE(&dev_priv->dma_pages[cur].age, event, wrap); dev_priv->dma_pages[cur].used = 0; dev_priv->dma_pages[cur].flushed = 0; /* advance to next page */ cur++; if (cur == dev_priv->nr_dma_pages) cur = 0; dev_priv->first_dma_page = dev_priv->current_dma_page = cur; } else { dev_priv->first_dma_page = cur; dev_priv->dma_pages[cur].flushed = dev_priv->dma_pages[i].used; } SET_AGE(&dev_priv->last_dma_age, event, wrap); DRM_DEBUG("first=cur=%u, cur->used=%u, cur->flushed=%u\n", cur, dev_priv->dma_pages[cur].used, dev_priv->dma_pages[cur].flushed); }