summaryrefslogtreecommitdiff
path: root/shared-core/savage_bci.c
diff options
context:
space:
mode:
Diffstat (limited to 'shared-core/savage_bci.c')
-rw-r--r--shared-core/savage_bci.c70
1 files changed, 46 insertions, 24 deletions
diff --git a/shared-core/savage_bci.c b/shared-core/savage_bci.c
index 3bf865dd..ce7139ad 100644
--- a/shared-core/savage_bci.c
+++ b/shared-core/savage_bci.c
@@ -305,6 +305,7 @@ static int savage_dma_init(drm_savage_private_t *dev_priv)
for (i = 0; i < dev_priv->nr_dma_pages; ++i) {
SET_AGE(&dev_priv->dma_pages[i].age, 0, 0);
dev_priv->dma_pages[i].used = 0;
+ dev_priv->dma_pages[i].flushed = 0;
}
SET_AGE(&dev_priv->last_dma_age, 0, 0);
@@ -323,6 +324,7 @@ void savage_dma_reset(drm_savage_private_t *dev_priv)
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;
@@ -384,6 +386,7 @@ uint32_t *savage_dma_alloc(drm_savage_private_t *dev_priv, unsigned int n)
for (i = cur; i < dev_priv->nr_dma_pages; ++i) {
dev_priv->dma_pages[i].age = dev_priv->last_dma_age;
dev_priv->dma_pages[i].used = 0;
+ dev_priv->dma_pages[i].flushed = 0;
}
dma_ptr = (uint32_t *)dev_priv->cmd_dma->handle;
dev_priv->first_dma_page = cur = 0;
@@ -414,21 +417,27 @@ uint32_t *savage_dma_alloc(drm_savage_private_t *dev_priv, unsigned int n)
static void savage_dma_flush(drm_savage_private_t *dev_priv)
{
BCI_LOCALS;
+ unsigned int first = dev_priv->first_dma_page;
unsigned int cur = dev_priv->current_dma_page;
uint16_t event;
- unsigned int wrap, pad, len, i;
+ unsigned int wrap, pad, align, len, i;
unsigned long phys_addr;
- if (dev_priv->first_dma_page == dev_priv->current_dma_page &&
- dev_priv->dma_pages[dev_priv->current_dma_page].used == 0)
+ if (first == cur &&
+ dev_priv->dma_pages[cur].used == dev_priv->dma_pages[cur].flushed)
return;
- /* pad to multiples of 8 entries (really needed? 2 should do it) */
- pad = -dev_priv->dma_pages[cur].used & 7;
- DRM_DEBUG("first=%u, cur=%u, cur->used=%u, pad=%u\n",
- dev_priv->first_dma_page, cur, dev_priv->dma_pages[cur].used,
- pad);
+ /* 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 +
@@ -444,9 +453,11 @@ static void savage_dma_flush(drm_savage_private_t *dev_priv)
/* do flush ... */
phys_addr = dev_priv->cmd_dma->offset +
- dev_priv->first_dma_page * SAVAGE_DMA_PAGE_SIZE*4;
- len = (cur - dev_priv->first_dma_page) * SAVAGE_DMA_PAGE_SIZE +
- dev_priv->dma_pages[cur].used;
+ (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);
@@ -456,23 +467,36 @@ static void savage_dma_flush(drm_savage_private_t *dev_priv)
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 = dev_priv->first_dma_page;
- i <= dev_priv->current_dma_page; ++i) {
+ 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);
- /* advance to next page */
- if (i == dev_priv->nr_dma_pages)
- i = 0;
- dev_priv->first_dma_page = dev_priv->current_dma_page = i;
-
- DRM_DEBUG("first=cur=%u, cur->used=%u\n", i,
- dev_priv->dma_pages[i].used);
+ 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);
}
static void savage_fake_dma_flush(drm_savage_private_t *dev_priv)
@@ -507,10 +531,8 @@ static void savage_fake_dma_flush(drm_savage_private_t *dev_priv)
dev_priv->dma_pages[i].used = 0;
}
- /* advance to next page */
- if (i == dev_priv->nr_dma_pages)
- i = 0;
- dev_priv->first_dma_page = dev_priv->current_dma_page = i;
+ /* reset to first page */
+ dev_priv->first_dma_page = dev_priv->current_dma_page = 0;
}
/*