applied patch from Ian Romanick fixing PCI DMA object creation code

main
Arthur Huillet 2007-07-13 20:51:52 +02:00
parent 00a5ab760b
commit aa6d9199fa
1 changed files with 37 additions and 40 deletions

View File

@ -585,6 +585,11 @@ nouveau_gpuobj_dma_new(struct drm_device *dev, int channel, int class,
int ret; int ret;
uint32_t is_scatter_gather = 0; uint32_t is_scatter_gather = 0;
/* Total number of pages covered by the request.
*/
const unsigned int page_count = (size + PAGE_SIZE - 1) / PAGE_SIZE;
DRM_DEBUG("ch%d class=0x%04x offset=0x%llx size=0x%llx\n", DRM_DEBUG("ch%d class=0x%04x offset=0x%llx size=0x%llx\n",
channel, class, offset, size); channel, class, offset, size);
DRM_DEBUG("access=%d target=%d\n", access, target); DRM_DEBUG("access=%d target=%d\n", access, target);
@ -604,7 +609,7 @@ nouveau_gpuobj_dma_new(struct drm_device *dev, int channel, int class,
} }
ret = nouveau_gpuobj_new(dev, channel, ret = nouveau_gpuobj_new(dev, channel,
is_scatter_gather ? ((((size + PAGE_SIZE - 1) / PAGE_SIZE) << 2) + 12) : nouveau_gpuobj_class_instmem_size(dev, class), is_scatter_gather ? ((page_count << 2) + 12) : nouveau_gpuobj_class_instmem_size(dev, class),
16, 16,
NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE, NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE,
gpuobj); gpuobj);
@ -634,9 +639,19 @@ nouveau_gpuobj_dma_new(struct drm_device *dev, int channel, int class,
} }
else else
{ {
/* Intial page entry in the scatter-gather area that
* corresponds to the base offset
*/
unsigned int idx = offset / PAGE_SIZE;
uint32_t instance_offset; uint32_t instance_offset;
uint64_t bus_addr; unsigned int i;
size = (uint32_t) size;
if ((idx + page_count) > dev->sg->pages) {
DRM_ERROR("Requested page range exceedes "
"allocated scatter-gather range!");
return DRM_ERR(E2BIG);
}
DRM_DEBUG("Creating PCI DMA object using virtual zone starting at %#llx, size %d\n", offset, (uint32_t)size); DRM_DEBUG("Creating PCI DMA object using virtual zone starting at %#llx, size %d\n", offset, (uint32_t)size);
INSTANCE_WR(*gpuobj, 0, ((1<<12) | (0<<13) | INSTANCE_WR(*gpuobj, 0, ((1<<12) | (0<<13) |
@ -644,52 +659,34 @@ nouveau_gpuobj_dma_new(struct drm_device *dev, int channel, int class,
(access << 14) | (access << 14) |
(target << 16) | (target << 16) |
class)); class));
INSTANCE_WR(*gpuobj, 1, size-1); INSTANCE_WR(*gpuobj, 1, (uint32_t) size-1);
offset += dev->sg->virtual;
/*write starting at the third dword*/ /*write starting at the third dword*/
instance_offset = 2; instance_offset = 2;
/*for each PAGE, get its bus address, fill in the page table entry, and advance*/ /*for each PAGE, get its bus address, fill in the page table entry, and advance*/
while ( size > 0 ) { for (i = 0; i < page_count; i++) {
bus_addr = vmalloc_to_page(offset); if (dev->sg->busaddr[idx] == 0) {
if ( ! bus_addr ) dev->sg->busaddr[idx] =
{ pci_map_page(dev->pdev,
DRM_ERROR("Couldn't map virtual address %#llx to a page number\n", offset); dev->sg->pagelist[idx],
nouveau_gpuobj_del(dev, gpuobj); 0,
return DRM_ERR(ENOMEM); DMA_31BIT_MASK,
} DMA_BIDIRECTIONAL);
bus_addr = (uint64_t) page_address(bus_addr);
if ( ! bus_addr )
{
DRM_ERROR("Couldn't find page address for address %#llx\n", offset);
nouveau_gpuobj_del(dev, gpuobj);
return DRM_ERR(ENOMEM);
}
bus_addr |= (offset & ~PAGE_MASK);
bus_addr = virt_to_bus((void *)bus_addr);
if ( ! bus_addr )
{
DRM_ERROR("Couldn't get bus address for %#llx\n", offset);
nouveau_gpuobj_del(dev, gpuobj);
return DRM_ERR(ENOMEM);
}
/*if ( bus_addr >= 1 << 32 ) if (dev->sg->busaddr[idx] == 0) {
{ return DRM_ERR(ENOMEM);
DRM_ERROR("Bus address %#llx is over 32 bits, Nvidia cards cannot address it !\n", bus_addr); }
nouveau_gpuobj_del(dev, gpuobj);
return DRM_ERR(EINVAL);
}*/
frame = (uint32_t) bus_addr & ~0x00000FFF;
INSTANCE_WR(*gpuobj, instance_offset, frame | pte_flags);
offset += PAGE_SIZE;
instance_offset ++;
size -= PAGE_SIZE;
} }
frame = (uint32_t) dev->sg->busaddr[idx];
INSTANCE_WR(*gpuobj, instance_offset,
frame | pte_flags);
idx++;
instance_offset ++;
}
} }
} else { } else {
INSTANCE_WR(*gpuobj, 0, 0x00190000 | class); INSTANCE_WR(*gpuobj, 0, 0x00190000 | class);