OSDN Git Service

nouveau: Allow GART notifiers when using sgdma code.
authorBen Skeggs <skeggsb@gmail.com>
Wed, 15 Aug 2007 03:36:54 +0000 (13:36 +1000)
committerBen Skeggs <skeggsb@gmail.com>
Wed, 15 Aug 2007 03:36:54 +0000 (13:36 +1000)
linux-core/nouveau_sgdma.c
shared-core/nouveau_drv.h
shared-core/nouveau_notifier.c

index df970d1..97d5330 100644 (file)
@@ -316,3 +316,20 @@ nouveau_sgdma_nottm_hack_takedown(struct drm_device *dev)
 {
 }
 
+int
+nouveau_sgdma_get_page(struct drm_device *dev, uint32_t offset, uint32_t *page)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma;
+       int pte;
+
+       pte = (offset >> NV_CTXDMA_PAGE_SHIFT);
+       if (dev_priv->card_type < NV_50) {
+               *page = INSTANCE_RD(gpuobj, (pte + 2)) & ~NV_CTXDMA_PAGE_MASK;
+               return 0;
+       }
+
+       DRM_ERROR("Unimplemented on NV50\n");
+       return -EINVAL;
+}
+
index b7459b1..e96c8fa 100644 (file)
@@ -421,6 +421,8 @@ extern void        nouveau_irq_uninstall(struct drm_device *);
 /* nouveau_sgdma.c */
 extern int nouveau_sgdma_init(struct drm_device *);
 extern void nouveau_sgdma_takedown(struct drm_device *);
+extern int nouveau_sgdma_get_page(struct drm_device *, uint32_t offset,
+                                 uint32_t *page);
 extern struct drm_ttm_backend *nouveau_sgdma_init_ttm(struct drm_device *);
 extern int nouveau_sgdma_nottm_hack_init(struct drm_device *);
 extern void nouveau_sgdma_nottm_hack_takedown(struct drm_device *);
index 31547aa..91f605e 100644 (file)
@@ -37,14 +37,13 @@ nouveau_notifier_init_channel(struct nouveau_channel *chan)
        int flags, ret;
 
        /*TODO: PCI notifier blocks */
-       if (dev_priv->agp_heap &&
-           dev_priv->gart_info.type != NOUVEAU_GART_SGDMA)
-               flags = NOUVEAU_MEM_AGP | NOUVEAU_MEM_FB_ACCEPTABLE;
-       else if ( dev_priv->pci_heap )
+       if (dev_priv->agp_heap)
+               flags = NOUVEAU_MEM_AGP;
+       else if (dev_priv->pci_heap)
                flags = NOUVEAU_MEM_PCI;
        else
                flags = NOUVEAU_MEM_FB;
-       flags |= NOUVEAU_MEM_MAPPED;
+       flags |= (NOUVEAU_MEM_MAPPED | NOUVEAU_MEM_FB_ACCEPTABLE);
 
        DRM_DEBUG("Allocating notifier block in %d\n", flags);
        chan->notifier_block = nouveau_mem_alloc(dev, 0, PAGE_SIZE, flags,
@@ -88,6 +87,7 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle,
                       int count, uint32_t *b_offset)
 {
        struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_gpuobj *nobj = NULL;
        struct mem_block *mem;
        uint32_t offset;
@@ -107,18 +107,29 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle,
        }
        mem->flags = NOUVEAU_MEM_NOTIFIER;
 
-       offset = chan->notifier_block->start + mem->start;
+       offset = chan->notifier_block->start;
        if (chan->notifier_block->flags & NOUVEAU_MEM_FB) {
                target = NV_DMA_TARGET_VIDMEM;
-       } else if (chan->notifier_block->flags & NOUVEAU_MEM_AGP) {
-               target = NV_DMA_TARGET_AGP;
-       } else if (chan->notifier_block->flags & NOUVEAU_MEM_PCI) {
+       } else
+       if (chan->notifier_block->flags & NOUVEAU_MEM_AGP) {
+               if (dev_priv->gart_info.type == NOUVEAU_GART_SGDMA &&
+                   dev_priv->card_type < NV_50) {
+                       ret = nouveau_sgdma_get_page(dev, offset, &offset);
+                       if (ret)
+                               return ret;
+                       target = NV_DMA_TARGET_PCI;
+               } else {
+                       target = NV_DMA_TARGET_AGP;
+               }
+       } else 
+       if (chan->notifier_block->flags & NOUVEAU_MEM_PCI) {
                target = NV_DMA_TARGET_PCI_NONLINEAR;
        } else {
                DRM_ERROR("Bad DMA target, flags 0x%08x!\n",
                          chan->notifier_block->flags);
                return -EINVAL;
        }
+       offset += mem->start;
 
        if ((ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
                                          offset, mem->size,