diff options
Diffstat (limited to 'drivers')
34 files changed, 667 insertions, 531 deletions
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index 107df9fdba4e..edc72a6348a7 100644 --- a/drivers/char/drm/drmP.h +++ b/drivers/char/drm/drmP.h @@ -357,6 +357,12 @@ typedef struct drm_freelist { spinlock_t lock; } drm_freelist_t; +typedef struct drm_dma_handle { + dma_addr_t busaddr; + void *vaddr; + size_t size; +} drm_dma_handle_t; + /** * Buffer entry. There is one of this for each buffer size order. */ @@ -366,7 +372,7 @@ typedef struct drm_buf_entry { drm_buf_t *buflist; /**< buffer list */ int seg_count; int page_order; - unsigned long *seglist; + drm_dma_handle_t **seglist; drm_freelist_t freelist; } drm_buf_entry_t; @@ -483,12 +489,6 @@ typedef struct drm_sigdata { drm_hw_lock_t *lock; } drm_sigdata_t; -typedef struct drm_dma_handle { - dma_addr_t busaddr; - void *vaddr; - size_t size; -} drm_dma_handle_t; - /** * Mappings list */ @@ -813,8 +813,6 @@ extern void drm_mem_init(void); extern int drm_mem_info(char *buf, char **start, off_t offset, int request, int *eof, void *data); extern void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area); -extern unsigned long drm_alloc_pages(int order, int area); -extern void drm_free_pages(unsigned long address, int order, int area); extern void *drm_ioremap(unsigned long offset, unsigned long size, drm_device_t * dev); extern void *drm_ioremap_nocache(unsigned long offset, unsigned long size, diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c index e2637b4d51de..8a9cf12e6183 100644 --- a/drivers/char/drm/drm_bufs.c +++ b/drivers/char/drm/drm_bufs.c @@ -474,8 +474,7 @@ static void drm_cleanup_buf_error(drm_device_t * dev, drm_buf_entry_t * entry) if (entry->seg_count) { for (i = 0; i < entry->seg_count; i++) { if (entry->seglist[i]) { - drm_free_pages(entry->seglist[i], - entry->page_order, DRM_MEM_DMA); + drm_pci_free(dev, entry->seglist[i]); } } drm_free(entry->seglist, @@ -678,7 +677,7 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request) int total; int page_order; drm_buf_entry_t *entry; - unsigned long page; + drm_dma_handle_t *dmah; drm_buf_t *buf; int alignment; unsigned long offset; @@ -781,8 +780,10 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request) page_count = 0; while (entry->buf_count < count) { - page = drm_alloc_pages(page_order, DRM_MEM_DMA); - if (!page) { + + dmah = drm_pci_alloc(dev, PAGE_SIZE << page_order, 0x1000, 0xfffffffful); + + if (!dmah) { /* Set count correctly so we free the proper amount. */ entry->buf_count = count; entry->seg_count = count; @@ -794,13 +795,13 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request) atomic_dec(&dev->buf_alloc); return -ENOMEM; } - entry->seglist[entry->seg_count++] = page; + entry->seglist[entry->seg_count++] = dmah; for (i = 0; i < (1 << page_order); i++) { DRM_DEBUG("page %d @ 0x%08lx\n", dma->page_count + page_count, - page + PAGE_SIZE * i); + (unsigned long)dmah->vaddr + PAGE_SIZE * i); temp_pagelist[dma->page_count + page_count++] - = page + PAGE_SIZE * i; + = (unsigned long)dmah->vaddr + PAGE_SIZE * i; } for (offset = 0; offset + size <= total && entry->buf_count < count; @@ -811,7 +812,8 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request) buf->order = order; buf->used = 0; buf->offset = (dma->byte_count + byte_count + offset); - buf->address = (void *)(page + offset); + buf->address = (void *)(dmah->vaddr + offset); + buf->bus_address = dmah->busaddr + offset; buf->next = NULL; buf->waiting = 0; buf->pending = 0; diff --git a/drivers/char/drm/drm_dma.c b/drivers/char/drm/drm_dma.c index 2afab95ca036..892db7096986 100644 --- a/drivers/char/drm/drm_dma.c +++ b/drivers/char/drm/drm_dma.c @@ -85,9 +85,7 @@ void drm_dma_takedown(drm_device_t * dev) dma->bufs[i].seg_count); for (j = 0; j < dma->bufs[i].seg_count; j++) { if (dma->bufs[i].seglist[j]) { - drm_free_pages(dma->bufs[i].seglist[j], - dma->bufs[i].page_order, - DRM_MEM_DMA); + drm_pci_free(dev, dma->bufs[i].seglist[j]); } } drm_free(dma->bufs[i].seglist, diff --git a/drivers/char/drm/drm_memory.c b/drivers/char/drm/drm_memory.c index 8074771e348f..dddf8de66143 100644 --- a/drivers/char/drm/drm_memory.c +++ b/drivers/char/drm/drm_memory.c @@ -79,65 +79,6 @@ void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area) return pt; } -/** - * Allocate pages. - * - * \param order size order. - * \param area memory area. (Not used.) - * \return page address on success, or zero on failure. - * - * Allocate and reserve free pages. - */ -unsigned long drm_alloc_pages(int order, int area) -{ - unsigned long address; - unsigned long bytes = PAGE_SIZE << order; - unsigned long addr; - unsigned int sz; - - address = __get_free_pages(GFP_KERNEL|__GFP_COMP, order); - if (!address) - return 0; - - /* Zero */ - memset((void *)address, 0, bytes); - - /* Reserve */ - for (addr = address, sz = bytes; - sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) { - SetPageReserved(virt_to_page(addr)); - } - - return address; -} - -/** - * Free pages. - * - * \param address address of the pages to free. - * \param order size order. - * \param area memory area. (Not used.) - * - * Unreserve and free pages allocated by alloc_pages(). - */ -void drm_free_pages(unsigned long address, int order, int area) -{ - unsigned long bytes = PAGE_SIZE << order; - unsigned long addr; - unsigned int sz; - - if (!address) - return; - - /* Unreserve */ - for (addr = address, sz = bytes; - sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) { - ClearPageReserved(virt_to_page(addr)); - } - - free_pages(address, order); -} - #if __OS_HAS_AGP /** Wrapper around agp_allocate_memory() */ DRM_AGP_MEM *drm_alloc_agp(drm_device_t * dev, int pages, u32 type) diff --git a/drivers/char/drm/drm_memory_debug.h b/drivers/char/drm/drm_memory_debug.h index e84605fc54af..7868341817da 100644 --- a/drivers/char/drm/drm_memory_debug.h +++ b/drivers/char/drm/drm_memory_debug.h @@ -206,76 +206,6 @@ void drm_free (void *pt, size_t size, int area) { } } -unsigned long drm_alloc_pages (int order, int area) { - unsigned long address; - unsigned long bytes = PAGE_SIZE << order; - unsigned long addr; - unsigned int sz; - - spin_lock(&drm_mem_lock); - if ((drm_ram_used >> PAGE_SHIFT) - > (DRM_RAM_PERCENT * drm_ram_available) / 100) { - spin_unlock(&drm_mem_lock); - return 0; - } - spin_unlock(&drm_mem_lock); - - address = __get_free_pages(GFP_KERNEL|__GFP_COMP, order); - if (!address) { - spin_lock(&drm_mem_lock); - ++drm_mem_stats[area].fail_count; - spin_unlock(&drm_mem_lock); - return 0; - } - spin_lock(&drm_mem_lock); - ++drm_mem_stats[area].succeed_count; - drm_mem_stats[area].bytes_allocated += bytes; - drm_ram_used += bytes; - spin_unlock(&drm_mem_lock); - - /* Zero outside the lock */ - memset((void *)address, 0, bytes); - - /* Reserve */ - for (addr = address, sz = bytes; - sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) { - SetPageReserved(virt_to_page(addr)); - } - - return address; -} - -void drm_free_pages (unsigned long address, int order, int area) { - unsigned long bytes = PAGE_SIZE << order; - int alloc_count; - int free_count; - unsigned long addr; - unsigned int sz; - - if (!address) { - DRM_MEM_ERROR(area, "Attempt to free address 0\n"); - } else { - /* Unreserve */ - for (addr = address, sz = bytes; - sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) { - ClearPageReserved(virt_to_page(addr)); - } - free_pages(address, order); - } - - spin_lock(&drm_mem_lock); - free_count = ++drm_mem_stats[area].free_count; - alloc_count = drm_mem_stats[area].succeed_count; - drm_mem_stats[area].bytes_freed += bytes; - drm_ram_used -= bytes; - spin_unlock(&drm_mem_lock); - if (free_count > alloc_count) { - DRM_MEM_ERROR(area, - "Excess frees: %d frees, %d allocs\n", - free_count, alloc_count); - } -} - void *drm_ioremap (unsigned long offset, unsigned long size, drm_device_t * dev) { void *pt; diff --git a/drivers/char/drm/drm_pci.c b/drivers/char/drm/drm_pci.c index 1fd7ff164817..b28ca9cea8a2 100644 --- a/drivers/char/drm/drm_pci.c +++ b/drivers/char/drm/drm_pci.c @@ -50,6 +50,10 @@ drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align, dma_addr_t maxaddr) { drm_dma_handle_t *dmah; +#if 1 + unsigned long addr; + size_t sz; +#endif #ifdef DRM_DEBUG_MEMORY int area = DRM_MEM_DMA; @@ -79,7 +83,7 @@ drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align, return NULL; dmah->size = size; - dmah->vaddr = pci_alloc_consistent(dev->pdev, size, &dmah->busaddr); + dmah->vaddr = dma_alloc_coherent(&dev->pdev->dev, size, &dmah->busaddr, GFP_KERNEL | __GFP_COMP); #ifdef DRM_DEBUG_MEMORY if (dmah->vaddr == NULL) { @@ -104,18 +108,29 @@ drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align, memset(dmah->vaddr, 0, size); + /* XXX - Is virt_to_page() legal for consistent mem? */ + /* Reserve */ + for (addr = (unsigned long)dmah->vaddr, sz = size; + sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) { + SetPageReserved(virt_to_page(addr)); + } + return dmah; } EXPORT_SYMBOL(drm_pci_alloc); /** - * \brief Free a PCI consistent memory block with freeing its descriptor. + * \brief Free a PCI consistent memory block without freeing its descriptor. * * This function is for internal use in the Linux-specific DRM core code. */ void __drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah) { +#if 1 + unsigned long addr; + size_t sz; +#endif #ifdef DRM_DEBUG_MEMORY int area = DRM_MEM_DMA; int alloc_count; @@ -127,8 +142,14 @@ void __drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah) DRM_MEM_ERROR(area, "Attempt to free address 0\n"); #endif } else { - pci_free_consistent(dev->pdev, dmah->size, dmah->vaddr, - dmah->busaddr); + /* XXX - Is virt_to_page() legal for consistent mem? */ + /* Unreserve */ + for (addr = (unsigned long)dmah->vaddr, sz = dmah->size; + sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) { + ClearPageReserved(virt_to_page(addr)); + } + dma_free_coherent(&dev->pdev->dev, dmah->size, dmah->vaddr, + dmah->busaddr); } #ifdef DRM_DEBUG_MEMORY diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h index 2c17e88a8847..b1bb3c7b568d 100644 --- a/drivers/char/drm/drm_pciids.h +++ b/drivers/char/drm/drm_pciids.h @@ -3,49 +3,69 @@ Please contact dri-devel@lists.sf.net to add new cards to this list */ #define radeon_PCI_IDS \ - {0x1002, 0x3150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350},\ + {0x1002, 0x3150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY}, \ + {0x1002, 0x3152, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x3154, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x3E50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x3E54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \ {0x1002, 0x4136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|CHIP_IS_IGP}, \ {0x1002, 0x4137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP}, \ {0x1002, 0x4144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ {0x1002, 0x4145, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ {0x1002, 0x4146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ {0x1002, 0x4147, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ + {0x1002, 0x4148, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ + {0x1002, 0x4149, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ + {0x1002, 0x414A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ + {0x1002, 0x414B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ {0x1002, 0x4150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ {0x1002, 0x4151, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ {0x1002, 0x4152, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ {0x1002, 0x4153, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ {0x1002, 0x4154, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ + {0x1002, 0x4155, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ {0x1002, 0x4156, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ - {0x1002, 0x4237, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS250|CHIP_IS_IGP}, \ + {0x1002, 0x4237, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP}, \ {0x1002, 0x4242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ {0x1002, 0x4243, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ {0x1002, 0x4336, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \ {0x1002, 0x4337, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \ - {0x1002, 0x4437, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS250|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \ - {0x1002, 0x4964, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250}, \ - {0x1002, 0x4965, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250}, \ - {0x1002, 0x4966, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250}, \ - {0x1002, 0x4967, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250}, \ - {0x1002, 0x4A49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420}, \ - {0x1002, 0x4A4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420}, \ + {0x1002, 0x4437, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \ + {0x1002, 0x4966, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250}, \ + {0x1002, 0x4967, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250}, \ + {0x1002, 0x4A48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x4A49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x4A4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x4A4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x4A4C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x4A4D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x4A4E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x4A4F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x4A50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x4A54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x4B49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x4B4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x4B4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x4B4C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ {0x1002, 0x4C57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200|CHIP_IS_MOBILITY}, \ {0x1002, 0x4C58, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200|CHIP_IS_MOBILITY}, \ {0x1002, 0x4C59, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100|CHIP_IS_MOBILITY}, \ {0x1002, 0x4C5A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100|CHIP_IS_MOBILITY}, \ - {0x1002, 0x4C64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250|CHIP_IS_MOBILITY}, \ - {0x1002, 0x4C65, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250|CHIP_IS_MOBILITY}, \ - {0x1002, 0x4C66, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250|CHIP_IS_MOBILITY}, \ - {0x1002, 0x4C67, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250|CHIP_IS_MOBILITY}, \ + {0x1002, 0x4C64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|CHIP_IS_MOBILITY}, \ + {0x1002, 0x4C66, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|CHIP_IS_MOBILITY}, \ + {0x1002, 0x4C67, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|CHIP_IS_MOBILITY}, \ {0x1002, 0x4E44, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ {0x1002, 0x4E45, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ - {0x1002, 0x4E46, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ + {0x1002, 0x4E46, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ {0x1002, 0x4E47, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ {0x1002, 0x4E48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ {0x1002, 0x4E49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ - {0x1002, 0x4E4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ + {0x1002, 0x4E4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ {0x1002, 0x4E4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ {0x1002, 0x4E50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ {0x1002, 0x4E51, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ + {0x1002, 0x4E52, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ + {0x1002, 0x4E53, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ {0x1002, 0x4E54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ {0x1002, 0x4E56, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ {0x1002, 0x5144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \ @@ -53,44 +73,66 @@ {0x1002, 0x5146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \ {0x1002, 0x5147, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \ {0x1002, 0x5148, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ - {0x1002, 0x5149, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ - {0x1002, 0x514A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ - {0x1002, 0x514B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ {0x1002, 0x514C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ {0x1002, 0x514D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ - {0x1002, 0x514E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ - {0x1002, 0x514F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ {0x1002, 0x5157, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200}, \ {0x1002, 0x5158, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200}, \ {0x1002, 0x5159, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \ {0x1002, 0x515A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \ {0x1002, 0x515E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \ - {0x1002, 0x5168, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ - {0x1002, 0x5169, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ - {0x1002, 0x516A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ - {0x1002, 0x516B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ - {0x1002, 0x516C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ - {0x1002, 0x5460, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ - {0x1002, 0x554F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ + {0x1002, 0x5460, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY}, \ + {0x1002, 0x5462, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY}, \ + {0x1002, 0x5464, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY}, \ + {0x1002, 0x5548, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5549, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x554A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x554B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x554C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x554D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x554E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x554F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5550, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5551, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5552, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5554, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x564A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x564B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x564F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ {0x1002, 0x5834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP}, \ {0x1002, 0x5835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \ - {0x1002, 0x5836, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP}, \ - {0x1002, 0x5837, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP}, \ {0x1002, 0x5960, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ {0x1002, 0x5961, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ {0x1002, 0x5962, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ - {0x1002, 0x5963, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ {0x1002, 0x5964, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ - {0x1002, 0x5968, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ + {0x1002, 0x5965, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ {0x1002, 0x5969, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \ - {0x1002, 0x596A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ - {0x1002, 0x596B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ + {0x1002, 0x5b60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5b62, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5b63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5b64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5b65, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \ {0x1002, 0x5c61, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|CHIP_IS_MOBILITY}, \ - {0x1002, 0x5c62, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ {0x1002, 0x5c63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|CHIP_IS_MOBILITY}, \ - {0x1002, 0x5c64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ - {0x1002, 0x5d4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ - {0x1002, 0x5e4b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420}, \ + {0x1002, 0x5d48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5d49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5d4a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5d4c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5d4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5d4e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5d4f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5d50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5d52, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5d57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5e48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5e4a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5e4b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5e4c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5e4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5e4f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x7834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x7835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ {0, 0, 0} #define r128_PCI_IDS \ diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c index 1ff4c7ca0bff..9f4b8ce4c05e 100644 --- a/drivers/char/drm/i915_dma.c +++ b/drivers/char/drm/i915_dma.c @@ -495,8 +495,6 @@ static int i915_dispatch_batchbuffer(drm_device_t * dev, } } - dev_priv->sarea_priv->last_enqueue = dev_priv->counter++; - i915_emit_breadcrumb(dev); return 0; diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c index d3879ac9970f..a752afd86ab8 100644 --- a/drivers/char/drm/i915_irq.c +++ b/drivers/char/drm/i915_irq.c @@ -53,6 +53,8 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) I915_WRITE16(I915REG_INT_IDENTITY_R, temp); + dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); + if (temp & USER_INT_FLAG) DRM_WAKEUP(&dev_priv->irq_queue); diff --git a/drivers/char/drm/r300_cmdbuf.c b/drivers/char/drm/r300_cmdbuf.c index c08fa5076f05..b108c7f913b2 100644 --- a/drivers/char/drm/r300_cmdbuf.c +++ b/drivers/char/drm/r300_cmdbuf.c @@ -214,13 +214,13 @@ void r300_init_reg_flags(void) ADD_RANGE(0x4F54, 1); ADD_RANGE(R300_TX_FILTER_0, 16); - ADD_RANGE(R300_TX_UNK1_0, 16); + ADD_RANGE(R300_TX_FILTER1_0, 16); ADD_RANGE(R300_TX_SIZE_0, 16); ADD_RANGE(R300_TX_FORMAT_0, 16); ADD_RANGE(R300_TX_PITCH_0, 16); /* Texture offset is dangerous and needs more checking */ ADD_RANGE_MARK(R300_TX_OFFSET_0, 16, MARK_CHECK_OFFSET); - ADD_RANGE(R300_TX_UNK4_0, 16); + ADD_RANGE(R300_TX_CHROMA_KEY_0, 16); ADD_RANGE(R300_TX_BORDER_COLOR_0, 16); /* Sporadic registers used as primitives are emitted */ @@ -242,8 +242,10 @@ static __inline__ int r300_check_range(unsigned reg, int count) return 0; } - /* we expect offsets passed to the framebuffer to be either within video memory or - within AGP space */ +/* + * we expect offsets passed to the framebuffer to be either within video + * memory or within AGP space + */ static __inline__ int r300_check_offset(drm_radeon_private_t *dev_priv, u32 offset) { @@ -251,11 +253,11 @@ static __inline__ int r300_check_offset(drm_radeon_private_t *dev_priv, but this value is not being kept. This code is correct for now (does the same thing as the code that sets MC_FB_LOCATION) in radeon_cp.c */ - if ((offset >= dev_priv->fb_location) && - (offset < dev_priv->gart_vm_start)) + if (offset >= dev_priv->fb_location && + offset < (dev_priv->fb_location + dev_priv->fb_size)) return 0; - if ((offset >= dev_priv->gart_vm_start) && - (offset < dev_priv->gart_vm_start + dev_priv->gart_size)) + if (offset >= dev_priv->gart_vm_start && + offset < (dev_priv->gart_vm_start + dev_priv->gart_size)) return 0; return 1; } @@ -490,6 +492,7 @@ static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv, return 0; } + static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv, drm_radeon_kcmd_buffer_t *cmdbuf) { @@ -701,6 +704,64 @@ static void r300_discard_buffer(drm_device_t * dev, drm_buf_t * buf) buf->used = 0; } +static int r300_scratch(drm_radeon_private_t *dev_priv, + drm_radeon_kcmd_buffer_t *cmdbuf, + drm_r300_cmd_header_t header) +{ + u32 *ref_age_base; + u32 i, buf_idx, h_pending; + RING_LOCALS; + + if (cmdbuf->bufsz < + (sizeof(u64) + header.scratch.n_bufs * sizeof(buf_idx))) { + return DRM_ERR(EINVAL); + } + + if (header.scratch.reg >= 5) { + return DRM_ERR(EINVAL); + } + + dev_priv->scratch_ages[header.scratch.reg]++; + + ref_age_base = *(u32 **)cmdbuf->buf; + + cmdbuf->buf += sizeof(u64); + cmdbuf->bufsz -= sizeof(u64); + + for (i=0; i < header.scratch.n_bufs; i++) { + buf_idx = *(u32 *)cmdbuf->buf; + buf_idx *= 2; /* 8 bytes per buf */ + + if (DRM_COPY_TO_USER(ref_age_base + buf_idx, &dev_priv->scratch_ages[header.scratch.reg], sizeof(u32))) { + return DRM_ERR(EINVAL); + } + + if (DRM_COPY_FROM_USER(&h_pending, ref_age_base + buf_idx + 1, sizeof(u32))) { + return DRM_ERR(EINVAL); + } + + if (h_pending == 0) { + return DRM_ERR(EINVAL); + } + + h_pending--; + + if (DRM_COPY_TO_USER(ref_age_base + buf_idx + 1, &h_pending, sizeof(u32))) { + return DRM_ERR(EINVAL); + } + + cmdbuf->buf += sizeof(buf_idx); + cmdbuf->bufsz -= sizeof(buf_idx); + } + + BEGIN_RING(2); + OUT_RING(CP_PACKET0(RADEON_SCRATCH_REG0 + header.scratch.reg * 4, 0)); + OUT_RING(dev_priv->scratch_ages[header.scratch.reg]); + ADVANCE_RING(); + + return 0; +} + /** * Parses and validates a user-supplied command buffer and emits appropriate * commands on the DMA ring buffer. @@ -838,6 +899,15 @@ int r300_do_cp_cmdbuf(drm_device_t *dev, } break; + case R300_CMD_SCRATCH: + DRM_DEBUG("R300_CMD_SCRATCH\n"); + ret = r300_scratch(dev_priv, cmdbuf, header); + if (ret) { + DRM_ERROR("r300_scratch failed\n"); + goto cleanup; + } + break; + default: DRM_ERROR("bad cmd_type %i at %p\n", header.header.cmd_type, diff --git a/drivers/char/drm/r300_reg.h b/drivers/char/drm/r300_reg.h index d1e19954406b..a881f96c983e 100644 --- a/drivers/char/drm/r300_reg.h +++ b/drivers/char/drm/r300_reg.h @@ -711,8 +711,22 @@ I am fairly certain that they are correct unless stated otherwise in comments. # define R300_TX_MAX_ANISO_16_TO_1 (8 << 21) # define R300_TX_MAX_ANISO_MASK (14 << 21) -#define R300_TX_UNK1_0 0x4440 +#define R300_TX_FILTER1_0 0x4440 +# define R300_CHROMA_KEY_MODE_DISABLE 0 +# define R300_CHROMA_KEY_FORCE 1 +# define R300_CHROMA_KEY_BLEND 2 +# define R300_MC_ROUND_NORMAL (0<<2) +# define R300_MC_ROUND_MPEG4 (1<<2) # define R300_LOD_BIAS_MASK 0x1fff +# define R300_EDGE_ANISO_EDGE_DIAG (0<<13) +# define R300_EDGE_ANISO_EDGE_ONLY (1<<13) +# define R300_MC_COORD_TRUNCATE_DISABLE (0<<14) +# define R300_MC_COORD_TRUNCATE_MPEG (1<<14) +# define R300_TX_TRI_PERF_0_8 (0<<15) +# define R300_TX_TRI_PERF_1_8 (1<<15) +# define R300_TX_TRI_PERF_1_4 (2<<15) +# define R300_TX_TRI_PERF_3_8 (3<<15) +# define R300_ANISO_THRESHOLD_MASK (7<<17) #define R300_TX_SIZE_0 0x4480 # define R300_TX_WIDTHMASK_SHIFT 0 @@ -722,6 +736,8 @@ I am fairly certain that they are correct unless stated otherwise in comments. # define R300_TX_UNK23 (1 << 23) # define R300_TX_SIZE_SHIFT 26 /* largest of width, height */ # define R300_TX_SIZE_MASK (15 << 26) +# define R300_TX_SIZE_PROJECTED (1<<30) +# define R300_TX_SIZE_TXPITCH_EN (1<<31) #define R300_TX_FORMAT_0 0x44C0 /* The interpretation of the format word by Wladimir van der Laan */ /* The X, Y, Z and W refer to the layout of the components. @@ -750,7 +766,8 @@ I am fairly certain that they are correct unless stated otherwise in comments. # define R300_TX_FORMAT_B8G8_B8G8 0x14 /* no swizzle */ # define R300_TX_FORMAT_G8R8_G8B8 0x15 /* no swizzle */ /* 0x16 - some 16 bit green format.. ?? */ -# define R300_TX_FORMAT_UNK25 (1 << 25) /* no swizzle */ +# define R300_TX_FORMAT_UNK25 (1 << 25) /* no swizzle */ +# define R300_TX_FORMAT_CUBIC_MAP (1 << 26) /* gap */ /* Floating point formats */ @@ -800,18 +817,20 @@ I am fairly certain that they are correct unless stated otherwise in comments. # define R300_TX_FORMAT_YUV_MODE 0x00800000 -#define R300_TX_PITCH_0 0x4500 +#define R300_TX_PITCH_0 0x4500 /* obvious missing in gap */ #define R300_TX_OFFSET_0 0x4540 /* BEGIN: Guess from R200 */ # define R300_TXO_ENDIAN_NO_SWAP (0 << 0) # define R300_TXO_ENDIAN_BYTE_SWAP (1 << 0) # define R300_TXO_ENDIAN_WORD_SWAP (2 << 0) # define R300_TXO_ENDIAN_HALFDW_SWAP (3 << 0) +# define R300_TXO_MACRO_TILE (1 << 2) +# define R300_TXO_MICRO_TILE (1 << 3) # define R300_TXO_OFFSET_MASK 0xffffffe0 # define R300_TXO_OFFSET_SHIFT 5 /* END */ -#define R300_TX_UNK4_0 0x4580 -#define R300_TX_BORDER_COLOR_0 0x45C0 //ff00ff00 == { 0, 1.0, 0, 1.0 } +#define R300_TX_CHROMA_KEY_0 0x4580 /* 32 bit chroma key */ +#define R300_TX_BORDER_COLOR_0 0x45C0 //ff00ff00 == { 0, 1.0, 0, 1.0 } /* END */ @@ -868,7 +887,9 @@ I am fairly certain that they are correct unless stated otherwise in comments. # define R300_PFS_NODE_TEX_OFFSET_MASK (31 << 12) # define R300_PFS_NODE_TEX_END_SHIFT 17 # define R300_PFS_NODE_TEX_END_MASK (31 << 17) -# define R300_PFS_NODE_LAST_NODE (1 << 22) +/*# define R300_PFS_NODE_LAST_NODE (1 << 22) */ +# define R300_PFS_NODE_OUTPUT_COLOR (1 << 22) +# define R300_PFS_NODE_OUTPUT_DEPTH (1 << 23) /* TEX // As far as I can tell, texture instructions cannot write into output @@ -887,6 +908,7 @@ I am fairly certain that they are correct unless stated otherwise in comments. */ # define R300_FPITX_OPCODE_SHIFT 15 # define R300_FPITX_OP_TEX 1 +# define R300_FPITX_OP_KIL 2 # define R300_FPITX_OP_TXP 3 # define R300_FPITX_OP_TXB 4 @@ -962,9 +984,11 @@ I am fairly certain that they are correct unless stated otherwise in comments. # define R300_FPI1_SRC2C_CONST (1 << 17) # define R300_FPI1_DSTC_SHIFT 18 # define R300_FPI1_DSTC_MASK (31 << 18) +# define R300_FPI1_DSTC_REG_MASK_SHIFT 23 # define R300_FPI1_DSTC_REG_X (1 << 23) # define R300_FPI1_DSTC_REG_Y (1 << 24) # define R300_FPI1_DSTC_REG_Z (1 << 25) +# define R300_FPI1_DSTC_OUTPUT_MASK_SHIFT 26 # define R300_FPI1_DSTC_OUTPUT_X (1 << 26) # define R300_FPI1_DSTC_OUTPUT_Y (1 << 27) # define R300_FPI1_DSTC_OUTPUT_Z (1 << 28) @@ -983,6 +1007,7 @@ I am fairly certain that they are correct unless stated otherwise in comments. # define R300_FPI3_DSTA_MASK (31 << 18) # define R300_FPI3_DSTA_REG (1 << 23) # define R300_FPI3_DSTA_OUTPUT (1 << 24) +# define R300_FPI3_DSTA_DEPTH (1 << 27) #define R300_PFS_INSTR0_0 0x48C0 # define R300_FPI0_ARGC_SRC0C_XYZ 0 @@ -1036,7 +1061,7 @@ I am fairly certain that they are correct unless stated otherwise in comments. # define R300_FPI0_OUTC_FRC (9 << 23) # define R300_FPI0_OUTC_REPL_ALPHA (10 << 23) # define R300_FPI0_OUTC_SAT (1 << 30) -# define R300_FPI0_UNKNOWN_31 (1 << 31) +# define R300_FPI0_INSERT_NOP (1 << 31) #define R300_PFS_INSTR2_0 0x49C0 # define R300_FPI2_ARGA_SRC0C_X 0 diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c index 9bb8ae0c1c27..7f949c9c9691 100644 --- a/drivers/char/drm/radeon_cp.c +++ b/drivers/char/drm/radeon_cp.c @@ -1118,14 +1118,20 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev, { u32 ring_start, cur_read_ptr; u32 tmp; - - /* Initialize the memory controller */ - RADEON_WRITE(RADEON_MC_FB_LOCATION, - ((dev_priv->gart_vm_start - 1) & 0xffff0000) - | (dev_priv->fb_location >> 16)); + + /* Initialize the memory controller. With new memory map, the fb location + * is not changed, it should have been properly initialized already. Part + * of the problem is that the code below is bogus, assuming the GART is + * always appended to the fb which is not necessarily the case + */ + if (!dev_priv->new_memmap) + RADEON_WRITE(RADEON_MC_FB_LOCATION, + ((dev_priv->gart_vm_start - 1) & 0xffff0000) + | (dev_priv->fb_location >> 16)); #if __OS_HAS_AGP if (dev_priv->flags & CHIP_IS_AGP) { + RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev->agp->base); RADEON_WRITE(RADEON_MC_AGP_LOCATION, (((dev_priv->gart_vm_start - 1 + dev_priv->gart_size) & 0xffff0000) | @@ -1153,8 +1159,6 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev, #if __OS_HAS_AGP if (dev_priv->flags & CHIP_IS_AGP) { - /* set RADEON_AGP_BASE here instead of relying on X from user space */ - RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev->agp->base); RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR, dev_priv->ring_rptr->offset - dev->agp->base + dev_priv->gart_vm_start); @@ -1174,6 +1178,17 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev, entry->handle + tmp_ofs); } + /* Set ring buffer size */ +#ifdef __BIG_ENDIAN + RADEON_WRITE(RADEON_CP_RB_CNTL, + dev_priv->ring.size_l2qw | RADEON_BUF_SWAP_32BIT); +#else + RADEON_WRITE(RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw); +#endif + + /* Start with assuming that writeback doesn't work */ + dev_priv->writeback_works = 0; + /* Initialize the scratch register pointer. This will cause * the scratch register values to be written out to memory * whenever they are updated. @@ -1190,28 +1205,9 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev, RADEON_WRITE(RADEON_SCRATCH_UMSK, 0x7); - /* Writeback doesn't seem to work everywhere, test it first */ - DRM_WRITE32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1), 0); - RADEON_WRITE(RADEON_SCRATCH_REG1, 0xdeadbeef); - - for (tmp = 0; tmp < dev_priv->usec_timeout; tmp++) { - if (DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1)) == - 0xdeadbeef) - break; - DRM_UDELAY(1); - } - - if (tmp < dev_priv->usec_timeout) { - dev_priv->writeback_works = 1; - DRM_DEBUG("writeback test succeeded, tmp=%d\n", tmp); - } else { - dev_priv->writeback_works = 0; - DRM_DEBUG("writeback test failed\n"); - } - if (radeon_no_wb == 1) { - dev_priv->writeback_works = 0; - DRM_DEBUG("writeback forced off\n"); - } + /* Turn on bus mastering */ + tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; + RADEON_WRITE(RADEON_BUS_CNTL, tmp); dev_priv->sarea_priv->last_frame = dev_priv->scratch[0] = 0; RADEON_WRITE(RADEON_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame); @@ -1223,26 +1219,45 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev, dev_priv->sarea_priv->last_clear = dev_priv->scratch[2] = 0; RADEON_WRITE(RADEON_LAST_CLEAR_REG, dev_priv->sarea_priv->last_clear); - /* Set ring buffer size */ -#ifdef __BIG_ENDIAN - RADEON_WRITE(RADEON_CP_RB_CNTL, - dev_priv->ring.size_l2qw | RADEON_BUF_SWAP_32BIT); -#else - RADEON_WRITE(RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw); -#endif - radeon_do_wait_for_idle(dev_priv); - /* Turn on bus mastering */ - tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; - RADEON_WRITE(RADEON_BUS_CNTL, tmp); - /* Sync everything up */ RADEON_WRITE(RADEON_ISYNC_CNTL, (RADEON_ISYNC_ANY2D_IDLE3D | RADEON_ISYNC_ANY3D_IDLE2D | RADEON_ISYNC_WAIT_IDLEGUI | RADEON_ISYNC_CPSCRATCH_IDLEGUI)); + +} + +static void radeon_test_writeback(drm_radeon_private_t * dev_priv) +{ + u32 tmp; + + /* Writeback doesn't seem to work everywhere, test it here and possibly + * enable it if it appears to work + */ + DRM_WRITE32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1), 0); + RADEON_WRITE(RADEON_SCRATCH_REG1, 0xdeadbeef); + + for (tmp = 0; tmp < dev_priv->usec_timeout; tmp++) { + if (DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1)) == + 0xdeadbeef) + break; + DRM_UDELAY(1); + } + + if (tmp < dev_priv->usec_timeout) { + dev_priv->writeback_works = 1; + DRM_INFO("writeback test succeeded in %d usecs\n", tmp); + } else { + dev_priv->writeback_works = 0; + DRM_INFO("writeback test failed\n"); + } + if (radeon_no_wb == 1) { + dev_priv->writeback_works = 0; + DRM_INFO("writeback forced off\n"); + } } /* Enable or disable PCI-E GART on the chip */ @@ -1317,6 +1332,14 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) DRM_DEBUG("\n"); + /* if we require new memory map but we don't have it fail */ + if ((dev_priv->flags & CHIP_NEW_MEMMAP) && !dev_priv->new_memmap) + { + DRM_ERROR("Cannot initialise DRM on this card\nThis card requires a new X.org DDX\n"); + radeon_do_cleanup_cp(dev); + return DRM_ERR(EINVAL); + } + if (init->is_pci && (dev_priv->flags & CHIP_IS_AGP)) { DRM_DEBUG("Forcing AGP card to PCI mode\n"); @@ -1496,6 +1519,9 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) dev_priv->fb_location = (RADEON_READ(RADEON_MC_FB_LOCATION) & 0xffff) << 16; + dev_priv->fb_size = + ((RADEON_READ(RADEON_MC_FB_LOCATION) & 0xffff0000u) + 0x10000) + - dev_priv->fb_location; dev_priv->front_pitch_offset = (((dev_priv->front_pitch / 64) << 22) | ((dev_priv->front_offset @@ -1510,8 +1536,46 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) + dev_priv->fb_location) >> 10)); dev_priv->gart_size = init->gart_size; - dev_priv->gart_vm_start = dev_priv->fb_location - + RADEON_READ(RADEON_CONFIG_APER_SIZE); + + /* New let's set the memory map ... */ + if (dev_priv->new_memmap) { + u32 base = 0; + + DRM_INFO("Setting GART location based on new memory map\n"); + + /* If using AGP, try to locate the AGP aperture at the same + * location in the card and on the bus, though we have to + * align it down. + */ +#if __OS_HAS_AGP + if (dev_priv->flags & CHIP_IS_AGP) { + base = dev->agp->base; + /* Check if valid */ + if ((base + dev_priv->gart_size) > dev_priv->fb_location && + base < (dev_priv->fb_location + dev_priv->fb_size)) { + DRM_INFO("Can't use AGP base @0x%08lx, won't fit\n", + dev->agp->base); + base = 0; + } + } +#endif + /* If not or if AGP is at 0 (Macs), try to put it elsewhere */ + if (base == 0) { + base = dev_priv->fb_location + dev_priv->fb_size; + if (((base + dev_priv->gart_size) & 0xfffffffful) + < base) + base = dev_priv->fb_location + - dev_priv->gart_size; + } + dev_priv->gart_vm_start = base & 0xffc00000u; + if (dev_priv->gart_vm_start != base) + DRM_INFO("GART aligned down from 0x%08x to 0x%08x\n", + base, dev_priv->gart_vm_start); + } else { + DRM_INFO("Setting GART location based on old memory map\n"); + dev_priv->gart_vm_start = dev_priv->fb_location + + RADEON_READ(RADEON_CONFIG_APER_SIZE); + } #if __OS_HAS_AGP if (dev_priv->flags & CHIP_IS_AGP) @@ -1596,6 +1660,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) dev_priv->last_buf = 0; radeon_do_engine_reset(dev); + radeon_test_writeback(dev_priv); return 0; } diff --git a/drivers/char/drm/radeon_drm.h b/drivers/char/drm/radeon_drm.h index 9c177a6b2a4c..c8e279e89c2e 100644 --- a/drivers/char/drm/radeon_drm.h +++ b/drivers/char/drm/radeon_drm.h @@ -222,6 +222,7 @@ typedef union { # define R300_WAIT_3D 0x2 # define R300_WAIT_2D_CLEAN 0x3 # define R300_WAIT_3D_CLEAN 0x4 +#define R300_CMD_SCRATCH 8 typedef union { unsigned int u; @@ -247,6 +248,9 @@ typedef union { struct { unsigned char cmd_type, flags, pad0, pad1; } wait; + struct { + unsigned char cmd_type, reg, n_bufs, flags; + } scratch; } drm_r300_cmd_header_t; #define RADEON_FRONT 0x1 @@ -697,6 +701,7 @@ typedef struct drm_radeon_setparam { #define RADEON_SETPARAM_FB_LOCATION 1 /* determined framebuffer location */ #define RADEON_SETPARAM_SWITCH_TILING 2 /* enable/disable color tiling */ #define RADEON_SETPARAM_PCIGART_LOCATION 3 /* PCI Gart Location */ +#define RADEON_SETPARAM_NEW_MEMMAP 4 /* Use new memory map */ /* 1.14: Clients can allocate/free a surface */ diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h index 1f7d2ab8c4fc..78345cee8f8e 100644 --- a/drivers/char/drm/radeon_drv.h +++ b/drivers/char/drm/radeon_drv.h @@ -38,7 +38,7 @@ #define DRIVER_NAME "radeon" #define DRIVER_DESC "ATI Radeon" -#define DRIVER_DATE "20051229" +#define DRIVER_DATE "20060225" /* Interface history: * @@ -91,9 +91,11 @@ * 1.20- Add support for r300 texrect * 1.21- Add support for card type getparam * 1.22- Add support for texture cache flushes (R300_TX_CNTL) + * 1.23- Add new radeon memory map work from benh + * 1.24- Add general-purpose packet for manipulating scratch registers (r300) */ #define DRIVER_MAJOR 1 -#define DRIVER_MINOR 22 +#define DRIVER_MINOR 24 #define DRIVER_PATCHLEVEL 0 /* @@ -101,20 +103,21 @@ */ enum radeon_family { CHIP_R100, - CHIP_RS100, CHIP_RV100, + CHIP_RS100, CHIP_RV200, - CHIP_R200, CHIP_RS200, - CHIP_R250, - CHIP_RS250, + CHIP_R200, CHIP_RV250, + CHIP_RS300, CHIP_RV280, CHIP_R300, - CHIP_RS300, CHIP_R350, CHIP_RV350, + CHIP_RV380, CHIP_R420, + CHIP_RV410, + CHIP_RS400, CHIP_LAST, }; @@ -136,9 +139,11 @@ enum radeon_chip_flags { CHIP_IS_AGP = 0x00080000UL, CHIP_HAS_HIERZ = 0x00100000UL, CHIP_IS_PCIE = 0x00200000UL, + CHIP_NEW_MEMMAP = 0x00400000UL, }; -#define GET_RING_HEAD(dev_priv) DRM_READ32( (dev_priv)->ring_rptr, 0 ) +#define GET_RING_HEAD(dev_priv) (dev_priv->writeback_works ? \ + DRM_READ32( (dev_priv)->ring_rptr, 0 ) : RADEON_READ(RADEON_CP_RB_RPTR)) #define SET_RING_HEAD(dev_priv,val) DRM_WRITE32( (dev_priv)->ring_rptr, 0, (val) ) typedef struct drm_radeon_freelist { @@ -199,6 +204,8 @@ typedef struct drm_radeon_private { drm_radeon_sarea_t *sarea_priv; u32 fb_location; + u32 fb_size; + int new_memmap; int gart_size; u32 gart_vm_start; @@ -272,6 +279,8 @@ typedef struct drm_radeon_private { unsigned long pcigart_offset; drm_ati_pcigart_info gart_info; + u32 scratch_ages[5]; + /* starting from here on, data is preserved accross an open */ uint32_t flags; /* see radeon_chip_flags */ } drm_radeon_private_t; diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c index 7bc27516d425..c5b8f774a599 100644 --- a/drivers/char/drm/radeon_state.c +++ b/drivers/char/drm/radeon_state.c @@ -45,22 +45,53 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t * u32 off = *offset; struct drm_radeon_driver_file_fields *radeon_priv; - if (off >= dev_priv->fb_location && - off < (dev_priv->gart_vm_start + dev_priv->gart_size)) - return 0; - - radeon_priv = filp_priv->driver_priv; - off += radeon_priv->radeon_fb_delta; + /* Hrm ... the story of the offset ... So this function converts + * the various ideas of what userland clients might have for an + * offset in the card address space into an offset into the card + * address space :) So with a sane client, it should just keep + * the value intact and just do some boundary checking. However, + * not all clients are sane. Some older clients pass us 0 based + * offsets relative to the start of the framebuffer and some may + * assume the AGP aperture it appended to the framebuffer, so we + * try to detect those cases and fix them up. + * + * Note: It might be a good idea here to make sure the offset lands + * in some "allowed" area to protect things like the PCIE GART... + */ - DRM_DEBUG("offset fixed up to 0x%x\n", off); + /* First, the best case, the offset already lands in either the + * framebuffer or the GART mapped space + */ + if ((off >= dev_priv->fb_location && + off < (dev_priv->fb_location + dev_priv->fb_size)) || + (off >= dev_priv->gart_vm_start && + off < (dev_priv->gart_vm_start + dev_priv->gart_size))) + return 0; - if (off < dev_priv->fb_location || - off >= (dev_priv->gart_vm_start + dev_priv->gart_size)) - return DRM_ERR(EINVAL); + /* Ok, that didn't happen... now check if we have a zero based + * offset that fits in the framebuffer + gart space, apply the + * magic offset we get from SETPARAM or calculated from fb_location + */ + if (off < (dev_priv->fb_size + dev_priv->gart_size)) { + radeon_priv = filp_priv->driver_priv; + off += radeon_priv->radeon_fb_delta; + } - *offset = off; + /* Finally, assume we aimed at a GART offset if beyond the fb */ + if (off > (dev_priv->fb_location + dev_priv->fb_size)) + off = off - (dev_priv->fb_location + dev_priv->fb_size) + + dev_priv->gart_vm_start; - return 0; + /* Now recheck and fail if out of bounds */ + if ((off >= dev_priv->fb_location && + off < (dev_priv->fb_location + dev_priv->fb_size)) || + (off >= dev_priv->gart_vm_start && + off < (dev_priv->gart_vm_start + dev_priv->gart_size))) { + DRM_DEBUG("offset fixed up to 0x%x\n", off); + *offset = off; + return 0; + } + return DRM_ERR(EINVAL); } static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t * @@ -1939,11 +1970,6 @@ static int radeon_surface_alloc(DRM_IOCTL_ARGS) drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_surface_alloc_t alloc; - if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); - } - DRM_COPY_FROM_USER_IOCTL(alloc, (drm_radeon_surface_alloc_t __user *) data, sizeof(alloc)); @@ -1960,12 +1986,7 @@ static int radeon_surface_free(DRM_IOCTL_ARGS) drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_surface_free_t memfree; - if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); - } - - DRM_COPY_FROM_USER_IOCTL(memfree, (drm_radeon_mem_free_t __user *) data, + DRM_COPY_FROM_USER_IOCTL(memfree, (drm_radeon_surface_free_t __user *) data, sizeof(memfree)); if (free_surface(filp, dev_priv, memfree.address)) @@ -2100,11 +2121,6 @@ static int radeon_cp_vertex(DRM_IOCTL_ARGS) LOCK_TEST_WITH_RETURN(dev, filp); - if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); - } - DRM_GET_PRIV_WITH_RETURN(filp_priv, filp); DRM_COPY_FROM_USER_IOCTL(vertex, (drm_radeon_vertex_t __user *) data, @@ -2189,11 +2205,6 @@ static int radeon_cp_indices(DRM_IOCTL_ARGS) LOCK_TEST_WITH_RETURN(dev, filp); - if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); - } - DRM_GET_PRIV_WITH_RETURN(filp_priv, filp); DRM_COPY_FROM_USER_IOCTL(elts, (drm_radeon_indices_t __user *) data, @@ -2340,11 +2351,6 @@ static int radeon_cp_indirect(DRM_IOCTL_ARGS) LOCK_TEST_WITH_RETURN(dev, filp); - if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); - } - DRM_COPY_FROM_USER_IOCTL(indirect, (drm_radeon_indirect_t __user *) data, sizeof(indirect)); @@ -2417,11 +2423,6 @@ static int radeon_cp_vertex2(DRM_IOCTL_ARGS) LOCK_TEST_WITH_RETURN(dev, filp); - if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); - } - DRM_GET_PRIV_WITH_RETURN(filp_priv, filp); DRM_COPY_FROM_USER_IOCTL(vertex, (drm_radeon_vertex2_t __user *) data, @@ -2738,11 +2739,6 @@ static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS) LOCK_TEST_WITH_RETURN(dev, filp); - if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); - } - DRM_GET_PRIV_WITH_RETURN(filp_priv, filp); DRM_COPY_FROM_USER_IOCTL(cmdbuf, @@ -2897,11 +2893,6 @@ static int radeon_cp_getparam(DRM_IOCTL_ARGS) drm_radeon_getparam_t param; int value; - if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); - } - DRM_COPY_FROM_USER_IOCTL(param, (drm_radeon_getparam_t __user *) data, sizeof(param)); @@ -2981,11 +2972,6 @@ static int radeon_cp_setparam(DRM_IOCTL_ARGS) drm_radeon_setparam_t sp; struct drm_radeon_driver_file_fields *radeon_priv; - if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); - } - DRM_GET_PRIV_WITH_RETURN(filp_priv, filp); DRM_COPY_FROM_USER_IOCTL(sp, (drm_radeon_setparam_t __user *) data, @@ -3012,6 +2998,9 @@ static int radeon_cp_setparam(DRM_IOCTL_ARGS) case RADEON_SETPARAM_PCIGART_LOCATION: dev_priv->pcigart_offset = sp.value; break; + case RADEON_SETPARAM_NEW_MEMMAP: + dev_priv->new_memmap = sp.value; + break; default: DRM_DEBUG("Invalid parameter %d\n", sp.param); return DRM_ERR(EINVAL); diff --git a/drivers/char/drm/sis_mm.c b/drivers/char/drm/sis_mm.c index 6774d2fe3452..5e9936bc307f 100644 --- a/drivers/char/drm/sis_mm.c +++ b/drivers/char/drm/sis_mm.c @@ -110,7 +110,7 @@ static int sis_fb_alloc(DRM_IOCTL_ARGS) DRM_COPY_TO_USER_IOCTL(argp, fb, sizeof(fb)); - DRM_DEBUG("alloc fb, size = %d, offset = %ld\n", fb.size, req.offset); + DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size, req.offset); return retval; } diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index f7854b65fd55..ba54c856b0e5 100644 --- a/drivers/infiniband/core/mad.c +++ b/drivers/infiniband/core/mad.c @@ -227,6 +227,14 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device, if (!is_vendor_oui(mad_reg_req->oui)) goto error1; } + /* Make sure class supplied is consistent with RMPP */ + if (ib_is_mad_class_rmpp(mad_reg_req->mgmt_class)) { + if (!rmpp_version) + goto error1; + } else { + if (rmpp_version) + goto error1; + } /* Make sure class supplied is consistent with QP type */ if (qp_type == IB_QPT_SMI) { if ((mad_reg_req->mgmt_class != @@ -890,6 +898,35 @@ struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent, } EXPORT_SYMBOL(ib_create_send_mad); +int ib_get_mad_data_offset(u8 mgmt_class) +{ + if (mgmt_class == IB_MGMT_CLASS_SUBN_ADM) + return IB_MGMT_SA_HDR; + else if ((mgmt_class == IB_MGMT_CLASS_DEVICE_MGMT) || + (mgmt_class == IB_MGMT_CLASS_DEVICE_ADM) || + (mgmt_class == IB_MGMT_CLASS_BIS)) + return IB_MGMT_DEVICE_HDR; + else if ((mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) && + (mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END)) + return IB_MGMT_VENDOR_HDR; + else + return IB_MGMT_MAD_HDR; +} +EXPORT_SYMBOL(ib_get_mad_data_offset); + +int ib_is_mad_class_rmpp(u8 mgmt_class) +{ + if ((mgmt_class == IB_MGMT_CLASS_SUBN_ADM) || + (mgmt_class == IB_MGMT_CLASS_DEVICE_MGMT) || + (mgmt_class == IB_MGMT_CLASS_DEVICE_ADM) || + (mgmt_class == IB_MGMT_CLASS_BIS) || + ((mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) && + (mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END))) + return 1; + return 0; +} +EXPORT_SYMBOL(ib_is_mad_class_rmpp); + void *ib_get_rmpp_segment(struct ib_mad_send_buf *send_buf, int seg_num) { struct ib_mad_send_wr_private *mad_send_wr; @@ -1022,6 +1059,13 @@ int ib_post_send_mad(struct ib_mad_send_buf *send_buf, goto error; } + if (!ib_is_mad_class_rmpp(((struct ib_mad_hdr *) send_buf->mad)->mgmt_class)) { + if (mad_agent_priv->agent.rmpp_version) { + ret = -EINVAL; + goto error; + } + } + /* * Save pointer to next work request to post in case the * current one completes, and the user modifies the work @@ -1618,14 +1662,59 @@ static int is_data_mad(struct ib_mad_agent_private *mad_agent_priv, (rmpp_mad->rmpp_hdr.rmpp_type == IB_MGMT_RMPP_TYPE_DATA); } +static inline int rcv_has_same_class(struct ib_mad_send_wr_private *wr, + struct ib_mad_recv_wc *rwc) +{ + return ((struct ib_mad *)(wr->send_buf.mad))->mad_hdr.mgmt_class == + rwc->recv_buf.mad->mad_hdr.mgmt_class; +} + +static inline int rcv_has_same_gid(struct ib_mad_send_wr_private *wr, + struct ib_mad_recv_wc *rwc ) +{ + struct ib_ah_attr attr; + u8 send_resp, rcv_resp; + + send_resp = ((struct ib_mad *)(wr->send_buf.mad))-> + mad_hdr.method & IB_MGMT_METHOD_RESP; + rcv_resp = rwc->recv_buf.mad->mad_hdr.method & IB_MGMT_METHOD_RESP; + + if (!send_resp && rcv_resp) + /* is request/response. GID/LIDs are both local (same). */ + return 1; + + if (send_resp == rcv_resp) + /* both requests, or both responses. GIDs different */ + return 0; + + if (ib_query_ah(wr->send_buf.ah, &attr)) + /* Assume not equal, to avoid false positives. */ + return 0; + + if (!(attr.ah_flags & IB_AH_GRH) && !(rwc->wc->wc_flags & IB_WC_GRH)) + return attr.dlid == rwc->wc->slid; + else if ((attr.ah_flags & IB_AH_GRH) && + (rwc->wc->wc_flags & IB_WC_GRH)) + return memcmp(attr.grh.dgid.raw, + rwc->recv_buf.grh->sgid.raw, 16) == 0; + else + /* one has GID, other does not. Assume different */ + return 0; +} struct ib_mad_send_wr_private* -ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, __be64 tid) +ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, + struct ib_mad_recv_wc *mad_recv_wc) { struct ib_mad_send_wr_private *mad_send_wr; + struct ib_mad *mad; + + mad = (struct ib_mad *)mad_recv_wc->recv_buf.mad; list_for_each_entry(mad_send_wr, &mad_agent_priv->wait_list, agent_list) { - if (mad_send_wr->tid == tid) + if ((mad_send_wr->tid == mad->mad_hdr.tid) && + rcv_has_same_class(mad_send_wr, mad_recv_wc) && + rcv_has_same_gid(mad_send_wr, mad_recv_wc)) return mad_send_wr; } @@ -1636,7 +1725,10 @@ ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, __be64 tid) list_for_each_entry(mad_send_wr, &mad_agent_priv->send_list, agent_list) { if (is_data_mad(mad_agent_priv, mad_send_wr->send_buf.mad) && - mad_send_wr->tid == tid && mad_send_wr->timeout) { + mad_send_wr->tid == mad->mad_hdr.tid && + mad_send_wr->timeout && + rcv_has_same_class(mad_send_wr, mad_recv_wc) && + rcv_has_same_gid(mad_send_wr, mad_recv_wc)) { /* Verify request has not been canceled */ return (mad_send_wr->status == IB_WC_SUCCESS) ? mad_send_wr : NULL; @@ -1661,7 +1753,6 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv, struct ib_mad_send_wr_private *mad_send_wr; struct ib_mad_send_wc mad_send_wc; unsigned long flags; - __be64 tid; INIT_LIST_HEAD(&mad_recv_wc->rmpp_list); list_add(&mad_recv_wc->recv_buf.list, &mad_recv_wc->rmpp_list); @@ -1677,9 +1768,8 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv, /* Complete corresponding request */ if (response_mad(mad_recv_wc->recv_buf.mad)) { - tid = mad_recv_wc->recv_buf.mad->mad_hdr.tid; spin_lock_irqsave(&mad_agent_priv->lock, flags); - mad_send_wr = ib_find_send_mad(mad_agent_priv, tid); + mad_send_wr = ib_find_send_mad(mad_agent_priv, mad_recv_wc); if (!mad_send_wr) { spin_unlock_irqrestore(&mad_agent_priv->lock, flags); ib_free_recv_mad(mad_recv_wc); @@ -2408,11 +2498,11 @@ static int ib_mad_post_receive_mads(struct ib_mad_qp_info *qp_info, } } sg_list.addr = dma_map_single(qp_info->port_priv-> - device->dma_device, - &mad_priv->grh, - sizeof *mad_priv - - sizeof mad_priv->header, - DMA_FROM_DEVICE); + device->dma_device, + &mad_priv->grh, + sizeof *mad_priv - + sizeof mad_priv->header, + DMA_FROM_DEVICE); pci_unmap_addr_set(&mad_priv->header, mapping, sg_list.addr); recv_wr.wr_id = (unsigned long)&mad_priv->header.mad_list; mad_priv->header.mad_list.mad_queue = recv_queue; diff --git a/drivers/infiniband/core/mad_priv.h b/drivers/infiniband/core/mad_priv.h index a7125d4b5ccf..6c9c133d71ef 100644 --- a/drivers/infiniband/core/mad_priv.h +++ b/drivers/infiniband/core/mad_priv.h @@ -216,7 +216,8 @@ extern kmem_cache_t *ib_mad_cache; int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr); struct ib_mad_send_wr_private * -ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, __be64 tid); +ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, + struct ib_mad_recv_wc *mad_recv_wc); void ib_mad_complete_send_wr(struct ib_mad_send_wr_private *mad_send_wr, struct ib_mad_send_wc *mad_send_wc); diff --git a/drivers/infiniband/core/mad_rmpp.c b/drivers/infiniband/core/mad_rmpp.c index bacfdd5bddad..dfd4e588ce03 100644 --- a/drivers/infiniband/core/mad_rmpp.c +++ b/drivers/infiniband/core/mad_rmpp.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2005 Intel Inc. All rights reserved. - * Copyright (c) 2005 Voltaire, Inc. All rights reserved. + * Copyright (c) 2005-2006 Voltaire, Inc. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -100,17 +100,6 @@ void ib_cancel_rmpp_recvs(struct ib_mad_agent_private *agent) } } -static int data_offset(u8 mgmt_class) -{ - if (mgmt_class == IB_MGMT_CLASS_SUBN_ADM) - return IB_MGMT_SA_HDR; - else if ((mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) && - (mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END)) - return IB_MGMT_VENDOR_HDR; - else - return IB_MGMT_RMPP_HDR; -} - static void format_ack(struct ib_mad_send_buf *msg, struct ib_rmpp_mad *data, struct mad_rmpp_recv *rmpp_recv) @@ -137,7 +126,7 @@ static void ack_recv(struct mad_rmpp_recv *rmpp_recv, struct ib_mad_send_buf *msg; int ret, hdr_len; - hdr_len = data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class); + hdr_len = ib_get_mad_data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class); msg = ib_create_send_mad(&rmpp_recv->agent->agent, recv_wc->wc->src_qp, recv_wc->wc->pkey_index, 1, hdr_len, 0, GFP_KERNEL); @@ -163,7 +152,7 @@ static struct ib_mad_send_buf *alloc_response_msg(struct ib_mad_agent *agent, if (IS_ERR(ah)) return (void *) ah; - hdr_len = data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class); + hdr_len = ib_get_mad_data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class); msg = ib_create_send_mad(agent, recv_wc->wc->src_qp, recv_wc->wc->pkey_index, 1, hdr_len, 0, GFP_KERNEL); @@ -408,7 +397,7 @@ static inline int get_mad_len(struct mad_rmpp_recv *rmpp_recv) rmpp_mad = (struct ib_rmpp_mad *)rmpp_recv->cur_seg_buf->mad; - hdr_size = data_offset(rmpp_mad->mad_hdr.mgmt_class); + hdr_size = ib_get_mad_data_offset(rmpp_mad->mad_hdr.mgmt_class); data_size = sizeof(struct ib_rmpp_mad) - hdr_size; pad = IB_MGMT_RMPP_DATA - be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin); if (pad > IB_MGMT_RMPP_DATA || pad < 0) @@ -562,15 +551,15 @@ static int send_next_seg(struct ib_mad_send_wr_private *mad_send_wr) return ib_send_mad(mad_send_wr); } -static void abort_send(struct ib_mad_agent_private *agent, __be64 tid, - u8 rmpp_status) +static void abort_send(struct ib_mad_agent_private *agent, + struct ib_mad_recv_wc *mad_recv_wc, u8 rmpp_status) { struct ib_mad_send_wr_private *mad_send_wr; struct ib_mad_send_wc wc; unsigned long flags; spin_lock_irqsave(&agent->lock, flags); - mad_send_wr = ib_find_send_mad(agent, tid); + mad_send_wr = ib_find_send_mad(agent, mad_recv_wc); if (!mad_send_wr) goto out; /* Unmatched send */ @@ -612,8 +601,7 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent, rmpp_mad = (struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad; if (rmpp_mad->rmpp_hdr.rmpp_status) { - abort_send(agent, rmpp_mad->mad_hdr.tid, - IB_MGMT_RMPP_STATUS_BAD_STATUS); + abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS); nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS); return; } @@ -621,14 +609,13 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent, seg_num = be32_to_cpu(rmpp_mad->rmpp_hdr.seg_num); newwin = be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin); if (newwin < seg_num) { - abort_send(agent, rmpp_mad->mad_hdr.tid, - IB_MGMT_RMPP_STATUS_W2S); + abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_W2S); nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_W2S); return; } spin_lock_irqsave(&agent->lock, flags); - mad_send_wr = ib_find_send_mad(agent, rmpp_mad->mad_hdr.tid); + mad_send_wr = ib_find_send_mad(agent, mad_recv_wc); if (!mad_send_wr) goto out; /* Unmatched ACK */ @@ -639,8 +626,7 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent, if (seg_num > mad_send_wr->send_buf.seg_count || seg_num > mad_send_wr->newwin) { spin_unlock_irqrestore(&agent->lock, flags); - abort_send(agent, rmpp_mad->mad_hdr.tid, - IB_MGMT_RMPP_STATUS_S2B); + abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_S2B); nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_S2B); return; } @@ -728,12 +714,10 @@ static void process_rmpp_stop(struct ib_mad_agent_private *agent, rmpp_mad = (struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad; if (rmpp_mad->rmpp_hdr.rmpp_status != IB_MGMT_RMPP_STATUS_RESX) { - abort_send(agent, rmpp_mad->mad_hdr.tid, - IB_MGMT_RMPP_STATUS_BAD_STATUS); + abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS); nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS); } else - abort_send(agent, rmpp_mad->mad_hdr.tid, - rmpp_mad->rmpp_hdr.rmpp_status); + abort_send(agent, mad_recv_wc, rmpp_mad->rmpp_hdr.rmpp_status); } static void process_rmpp_abort(struct ib_mad_agent_private *agent, @@ -745,12 +729,10 @@ static void process_rmpp_abort(struct ib_mad_agent_private *agent, if (rmpp_mad->rmpp_hdr.rmpp_status < IB_MGMT_RMPP_STATUS_ABORT_MIN || rmpp_mad->rmpp_hdr.rmpp_status > IB_MGMT_RMPP_STATUS_ABORT_MAX) { - abort_send(agent, rmpp_mad->mad_hdr.tid, - IB_MGMT_RMPP_STATUS_BAD_STATUS); + abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS); nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS); } else - abort_send(agent, rmpp_mad->mad_hdr.tid, - rmpp_mad->rmpp_hdr.rmpp_status); + abort_send(agent, mad_recv_wc, rmpp_mad->rmpp_hdr.rmpp_status); } struct ib_mad_recv_wc * @@ -764,8 +746,7 @@ ib_process_rmpp_recv_wc(struct ib_mad_agent_private *agent, return mad_recv_wc; if (rmpp_mad->rmpp_hdr.rmpp_version != IB_MGMT_RMPP_VERSION) { - abort_send(agent, rmpp_mad->mad_hdr.tid, - IB_MGMT_RMPP_STATUS_UNV); + abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_UNV); nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_UNV); goto out; } @@ -783,8 +764,7 @@ ib_process_rmpp_recv_wc(struct ib_mad_agent_private *agent, process_rmpp_abort(agent, mad_recv_wc); break; default: - abort_send(agent, rmpp_mad->mad_hdr.tid, - IB_MGMT_RMPP_STATUS_BADT); + abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BADT); nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BADT); break; } diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c index fb6cd42601f9..afe70a549c2f 100644 --- a/drivers/infiniband/core/user_mad.c +++ b/drivers/infiniband/core/user_mad.c @@ -177,17 +177,6 @@ static int queue_packet(struct ib_umad_file *file, return ret; } -static int data_offset(u8 mgmt_class) -{ - if (mgmt_class == IB_MGMT_CLASS_SUBN_ADM) - return IB_MGMT_SA_HDR; - else if ((mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) && - (mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END)) - return IB_MGMT_VENDOR_HDR; - else - return IB_MGMT_RMPP_HDR; -} - static void send_handler(struct ib_mad_agent *agent, struct ib_mad_send_wc *send_wc) { @@ -283,7 +272,7 @@ static ssize_t copy_recv_mad(char __user *buf, struct ib_umad_packet *packet, */ return -ENOSPC; } - offset = data_offset(recv_buf->mad->mad_hdr.mgmt_class); + offset = ib_get_mad_data_offset(recv_buf->mad->mad_hdr.mgmt_class); max_seg_payload = sizeof (struct ib_mad) - offset; for (left = packet->length - seg_payload, buf += seg_payload; @@ -441,21 +430,14 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf, } rmpp_mad = (struct ib_rmpp_mad *) packet->mad.data; - if (rmpp_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_ADM) { - hdr_len = IB_MGMT_SA_HDR; - copy_offset = IB_MGMT_RMPP_HDR; - rmpp_active = ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & - IB_MGMT_RMPP_FLAG_ACTIVE; - } else if (rmpp_mad->mad_hdr.mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START && - rmpp_mad->mad_hdr.mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END) { - hdr_len = IB_MGMT_VENDOR_HDR; + hdr_len = ib_get_mad_data_offset(rmpp_mad->mad_hdr.mgmt_class); + if (!ib_is_mad_class_rmpp(rmpp_mad->mad_hdr.mgmt_class)) { + copy_offset = IB_MGMT_MAD_HDR; + rmpp_active = 0; + } else { copy_offset = IB_MGMT_RMPP_HDR; rmpp_active = ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & IB_MGMT_RMPP_FLAG_ACTIVE; - } else { - hdr_len = IB_MGMT_MAD_HDR; - copy_offset = IB_MGMT_MAD_HDR; - rmpp_active = 0; } data_len = count - sizeof (struct ib_user_mad) - hdr_len; diff --git a/drivers/infiniband/hw/mthca/mthca_av.c b/drivers/infiniband/hw/mthca/mthca_av.c index f023d3936518..bc5bdcbe51b5 100644 --- a/drivers/infiniband/hw/mthca/mthca_av.c +++ b/drivers/infiniband/hw/mthca/mthca_av.c @@ -265,7 +265,7 @@ int __devinit mthca_init_av_table(struct mthca_dev *dev) return -ENOMEM; } -void __devexit mthca_cleanup_av_table(struct mthca_dev *dev) +void mthca_cleanup_av_table(struct mthca_dev *dev) { if (mthca_is_memfree(dev)) return; diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c index 76aabc5bf371..312cf90731ea 100644 --- a/drivers/infiniband/hw/mthca/mthca_cq.c +++ b/drivers/infiniband/hw/mthca/mthca_cq.c @@ -973,7 +973,7 @@ int __devinit mthca_init_cq_table(struct mthca_dev *dev) return err; } -void __devexit mthca_cleanup_cq_table(struct mthca_dev *dev) +void mthca_cleanup_cq_table(struct mthca_dev *dev) { mthca_array_cleanup(&dev->cq_table.cq, dev->limits.num_cqs); mthca_alloc_cleanup(&dev->cq_table.alloc); diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c index cbdc348fb689..99f109c3815d 100644 --- a/drivers/infiniband/hw/mthca/mthca_eq.c +++ b/drivers/infiniband/hw/mthca/mthca_eq.c @@ -765,7 +765,7 @@ static int __devinit mthca_map_eq_regs(struct mthca_dev *dev) } -static void __devexit mthca_unmap_eq_regs(struct mthca_dev *dev) +static void mthca_unmap_eq_regs(struct mthca_dev *dev) { if (mthca_is_memfree(dev)) { mthca_unmap_reg(dev, (pci_resource_len(dev->pdev, 0) - 1) & @@ -821,7 +821,7 @@ int __devinit mthca_map_eq_icm(struct mthca_dev *dev, u64 icm_virt) return ret; } -void __devexit mthca_unmap_eq_icm(struct mthca_dev *dev) +void mthca_unmap_eq_icm(struct mthca_dev *dev) { u8 status; @@ -954,7 +954,7 @@ err_out_free: return err; } -void __devexit mthca_cleanup_eq_table(struct mthca_dev *dev) +void mthca_cleanup_eq_table(struct mthca_dev *dev) { u8 status; int i; diff --git a/drivers/infiniband/hw/mthca/mthca_mad.c b/drivers/infiniband/hw/mthca/mthca_mad.c index 4ace6a392f41..dfb482eac9a2 100644 --- a/drivers/infiniband/hw/mthca/mthca_mad.c +++ b/drivers/infiniband/hw/mthca/mthca_mad.c @@ -271,7 +271,7 @@ err: return PTR_ERR(agent); } -void mthca_free_agents(struct mthca_dev *dev) +void __devexit mthca_free_agents(struct mthca_dev *dev) { struct ib_mad_agent *agent; int p, q; diff --git a/drivers/infiniband/hw/mthca/mthca_mcg.c b/drivers/infiniband/hw/mthca/mthca_mcg.c index 9965bda9afed..47ca8a9b7247 100644 --- a/drivers/infiniband/hw/mthca/mthca_mcg.c +++ b/drivers/infiniband/hw/mthca/mthca_mcg.c @@ -388,7 +388,7 @@ int __devinit mthca_init_mcg_table(struct mthca_dev *dev) return 0; } -void __devexit mthca_cleanup_mcg_table(struct mthca_dev *dev) +void mthca_cleanup_mcg_table(struct mthca_dev *dev) { mthca_alloc_cleanup(&dev->mcg_table.alloc); } diff --git a/drivers/infiniband/hw/mthca/mthca_mr.c b/drivers/infiniband/hw/mthca/mthca_mr.c index 698b62125765..25e1c1db9a40 100644 --- a/drivers/infiniband/hw/mthca/mthca_mr.c +++ b/drivers/infiniband/hw/mthca/mthca_mr.c @@ -170,7 +170,7 @@ err_out: return -ENOMEM; } -static void __devexit mthca_buddy_cleanup(struct mthca_buddy *buddy) +static void mthca_buddy_cleanup(struct mthca_buddy *buddy) { int i; @@ -866,7 +866,7 @@ err_mtt_buddy: return err; } -void __devexit mthca_cleanup_mr_table(struct mthca_dev *dev) +void mthca_cleanup_mr_table(struct mthca_dev *dev) { /* XXX check if any MRs are still allocated? */ if (dev->limits.fmr_reserved_mtts) diff --git a/drivers/infiniband/hw/mthca/mthca_pd.c b/drivers/infiniband/hw/mthca/mthca_pd.c index 105fc5faaddf..59df51614c85 100644 --- a/drivers/infiniband/hw/mthca/mthca_pd.c +++ b/drivers/infiniband/hw/mthca/mthca_pd.c @@ -77,7 +77,7 @@ int __devinit mthca_init_pd_table(struct mthca_dev *dev) dev->limits.reserved_pds); } -void __devexit mthca_cleanup_pd_table(struct mthca_dev *dev) +void mthca_cleanup_pd_table(struct mthca_dev *dev) { /* XXX check if any PDs are still allocated? */ mthca_alloc_cleanup(&dev->pd_table.alloc); diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index 1bc2678c2fae..057c8e6af87b 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c @@ -2204,7 +2204,7 @@ int __devinit mthca_init_qp_table(struct mthca_dev *dev) return err; } -void __devexit mthca_cleanup_qp_table(struct mthca_dev *dev) +void mthca_cleanup_qp_table(struct mthca_dev *dev) { int i; u8 status; diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c index 0cfd15802217..2dd3aea05341 100644 --- a/drivers/infiniband/hw/mthca/mthca_srq.c +++ b/drivers/infiniband/hw/mthca/mthca_srq.c @@ -206,7 +206,7 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd, roundup_pow_of_two(sizeof (struct mthca_next_seg) + srq->max_gs * sizeof (struct mthca_data_seg))); - if (ds > dev->limits.max_desc_sz) + if (!mthca_is_memfree(dev) && (ds > dev->limits.max_desc_sz)) return -EINVAL; srq->wqe_shift = long_log2(ds); @@ -684,7 +684,7 @@ int __devinit mthca_init_srq_table(struct mthca_dev *dev) return err; } -void __devexit mthca_cleanup_srq_table(struct mthca_dev *dev) +void mthca_cleanup_srq_table(struct mthca_dev *dev) { if (!(dev->mthca_flags & MTHCA_FLAG_SRQ)) return; diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 53a32f65788d..9b0bd7c746ca 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -723,7 +723,7 @@ static int ipoib_hard_header(struct sk_buff *skb, * destination address onto the front of the skb so we can * figure out where to send the packet later. */ - if (!skb->dst || !skb->dst->neighbour) { + if ((!skb->dst || !skb->dst->neighbour) && daddr) { struct ipoib_pseudoheader *phdr = (struct ipoib_pseudoheader *) skb_push(skb, sizeof *phdr); memcpy(phdr->hwaddr, daddr, INFINIBAND_ALEN); diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 61924cc30e55..fd8a95a9c5d3 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -607,10 +607,10 @@ static void srp_unmap_data(struct scsi_cmnd *scmnd, */ if (likely(scmnd->use_sg)) { nents = scmnd->use_sg; - scat = (struct scatterlist *) scmnd->request_buffer; + scat = scmnd->request_buffer; } else { nents = 1; - scat = (struct scatterlist *) scmnd->request_buffer; + scat = &req->fake_sg; } dma_unmap_sg(target->srp_host->dev->dma_device, scat, nents, diff --git a/drivers/scsi/libata-bmdma.c b/drivers/scsi/libata-bmdma.c index 95d81d86d8b7..835dff0bafdc 100644 --- a/drivers/scsi/libata-bmdma.c +++ b/drivers/scsi/libata-bmdma.c @@ -703,6 +703,7 @@ ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int struct ata_probe_ent *probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]); int p = 0; + unsigned long bmdma; if (!probe_ent) return NULL; @@ -716,7 +717,12 @@ ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int probe_ent->port[p].altstatus_addr = probe_ent->port[p].ctl_addr = pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS; - probe_ent->port[p].bmdma_addr = pci_resource_start(pdev, 4); + bmdma = pci_resource_start(pdev, 4); + if (bmdma) { + if (inb(bmdma + 2) & 0x80) + probe_ent->host_set_flags |= ATA_HOST_SIMPLEX; + probe_ent->port[p].bmdma_addr = bmdma; + } ata_std_ports(&probe_ent->port[p]); p++; } @@ -726,7 +732,13 @@ ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int probe_ent->port[p].altstatus_addr = probe_ent->port[p].ctl_addr = pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS; - probe_ent->port[p].bmdma_addr = pci_resource_start(pdev, 4) + 8; + bmdma = pci_resource_start(pdev, 4); + if (bmdma) { + bmdma += 8; + if(inb(bmdma + 2) & 0x80) + probe_ent->host_set_flags |= ATA_HOST_SIMPLEX; + probe_ent->port[p].bmdma_addr = bmdma; + } ata_std_ports(&probe_ent->port[p]); p++; } @@ -740,6 +752,7 @@ static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev, struct ata_port_info *port, int port_num) { struct ata_probe_ent *probe_ent; + unsigned long bmdma; probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port); if (!probe_ent) @@ -766,8 +779,13 @@ static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev, break; } - probe_ent->port[0].bmdma_addr = - pci_resource_start(pdev, 4) + 8 * port_num; + bmdma = pci_resource_start(pdev, 4); + if (bmdma != 0) { + bmdma += 8 * port_num; + probe_ent->port[0].bmdma_addr = bmdma; + if (inb(bmdma + 2) & 0x80) + probe_ent->host_set_flags |= ATA_HOST_SIMPLEX; + } ata_std_ports(&probe_ent->port[0]); return probe_ent; diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index d279666dcb38..21b0ed583b8a 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -62,7 +62,9 @@ #include "libata.h" static unsigned int ata_dev_init_params(struct ata_port *ap, - struct ata_device *dev); + struct ata_device *dev, + u16 heads, + u16 sectors); static void ata_set_mode(struct ata_port *ap); static unsigned int ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev); @@ -1081,9 +1083,8 @@ unsigned int ata_pio_need_iordy(const struct ata_device *adev) * * Read ID data from the specified device. ATA_CMD_ID_ATA is * performed on ATA devices and ATA_CMD_ID_ATAPI on ATAPI - * devices. This function also takes care of EDD signature - * misreporting (to be removed once EDD support is gone) and - * issues ATA_CMD_INIT_DEV_PARAMS for pre-ATA4 drives. + * devices. This function also issues ATA_CMD_INIT_DEV_PARAMS + * for pre-ATA4 drives. * * LOCKING: * Kernel thread context (may sleep) @@ -1095,7 +1096,6 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, unsigned int *p_class, int post_reset, u16 **p_id) { unsigned int class = *p_class; - unsigned int using_edd; struct ata_taskfile tf; unsigned int err_mask = 0; u16 *id; @@ -1104,12 +1104,6 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, DPRINTK("ENTER, host %u, dev %u\n", ap->id, dev->devno); - if (ap->ops->probe_reset || - ap->flags & (ATA_FLAG_SRST | ATA_FLAG_SATA_RESET)) - using_edd = 0; - else - using_edd = 1; - ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */ id = kmalloc(sizeof(id[0]) * ATA_ID_WORDS, GFP_KERNEL); @@ -1139,39 +1133,16 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, err_mask = ata_exec_internal(ap, dev, &tf, DMA_FROM_DEVICE, id, sizeof(id[0]) * ATA_ID_WORDS); - if (err_mask) { rc = -EIO; reason = "I/O error"; - - if (err_mask & ~AC_ERR_DEV) - goto err_out; - - /* - * arg! EDD works for all test cases, but seems to return - * the ATA signature for some ATAPI devices. Until the - * reason for this is found and fixed, we fix up the mess - * here. If IDENTIFY DEVICE returns command aborted - * (as ATAPI devices do), then we issue an - * IDENTIFY PACKET DEVICE. - * - * ATA software reset (SRST, the default) does not appear - * to have this problem. - */ - if ((using_edd) && (class == ATA_DEV_ATA)) { - u8 err = tf.feature; - if (err & ATA_ABORTED) { - class = ATA_DEV_ATAPI; - goto retry; - } - } goto err_out; } swap_buf_le16(id, ATA_ID_WORDS); /* sanity check */ - if ((class == ATA_DEV_ATA) != ata_id_is_ata(id)) { + if ((class == ATA_DEV_ATA) != (ata_id_is_ata(id) | ata_id_is_cfa(id))) { rc = -EINVAL; reason = "device reports illegal type"; goto err_out; @@ -1187,7 +1158,7 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, * Some drives were very specific about that exact sequence. */ if (ata_id_major_version(id) < 4 || !ata_id_has_lba(id)) { - err_mask = ata_dev_init_params(ap, dev); + err_mask = ata_dev_init_params(ap, dev, id[3], id[6]); if (err_mask) { rc = -EIO; reason = "INIT_DEV_PARAMS failed"; @@ -1440,7 +1411,11 @@ static int ata_bus_probe(struct ata_port *ap) if (!found) goto err_out_disable; - ata_set_mode(ap); + if (ap->ops->set_mode) + ap->ops->set_mode(ap); + else + ata_set_mode(ap); + if (ap->flags & ATA_FLAG_PORT_DISABLED) goto err_out_disable; @@ -1845,7 +1820,7 @@ static void ata_host_set_dma(struct ata_port *ap) */ static void ata_set_mode(struct ata_port *ap) { - int i, rc; + int i, rc, used_dma = 0; /* step 1: calculate xfer_mask */ for (i = 0; i < ATA_MAX_DEVICES; i++) { @@ -1863,6 +1838,9 @@ static void ata_set_mode(struct ata_port *ap) dma_mask = ata_pack_xfermask(0, dev->mwdma_mask, dev->udma_mask); dev->pio_mode = ata_xfer_mask2mode(pio_mask); dev->dma_mode = ata_xfer_mask2mode(dma_mask); + + if (dev->dma_mode) + used_dma = 1; } /* step 2: always set host PIO timings */ @@ -1884,6 +1862,17 @@ static void ata_set_mode(struct ata_port *ap) goto err_out; } + /* + * Record simplex status. If we selected DMA then the other + * host channels are not permitted to do so. + */ + + if (used_dma && (ap->host_set->flags & ATA_HOST_SIMPLEX)) + ap->host_set->simplex_claimed = 1; + + /* + * Chip specific finalisation + */ if (ap->ops->post_set_mode) ap->ops->post_set_mode(ap); @@ -2005,45 +1994,6 @@ static void ata_bus_post_reset(struct ata_port *ap, unsigned int devmask) ap->ops->dev_select(ap, 0); } -/** - * ata_bus_edd - Issue EXECUTE DEVICE DIAGNOSTIC command. - * @ap: Port to reset and probe - * - * Use the EXECUTE DEVICE DIAGNOSTIC command to reset and - * probe the bus. Not often used these days. - * - * LOCKING: - * PCI/etc. bus probe sem. - * Obtains host_set lock. - * - */ - -static unsigned int ata_bus_edd(struct ata_port *ap) -{ - struct ata_taskfile tf; - unsigned long flags; - - /* set up execute-device-diag (bus reset) taskfile */ - /* also, take interrupts to a known state (disabled) */ - DPRINTK("execute-device-diag\n"); - ata_tf_init(ap, &tf, 0); - tf.ctl |= ATA_NIEN; - tf.command = ATA_CMD_EDD; - tf.protocol = ATA_PROT_NODATA; - - /* do bus reset */ - spin_lock_irqsave(&ap->host_set->lock, flags); - ata_tf_to_host(ap, &tf); - spin_unlock_irqrestore(&ap->host_set->lock, flags); - - /* spec says at least 2ms. but who knows with those - * crazy ATAPI devices... - */ - msleep(150); - - return ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT); -} - static unsigned int ata_bus_softreset(struct ata_port *ap, unsigned int devmask) { @@ -2078,13 +2028,12 @@ static unsigned int ata_bus_softreset(struct ata_port *ap, */ msleep(150); - /* Before we perform post reset processing we want to see if - the bus shows 0xFF because the odd clown forgets the D7 pulldown - resistor */ - + * the bus shows 0xFF because the odd clown forgets the D7 + * pulldown resistor. + */ if (ata_check_status(ap) == 0xFF) - return 1; /* Positive is failure for some reason */ + return AC_ERR_OTHER; ata_bus_post_reset(ap, devmask); @@ -2116,7 +2065,7 @@ void ata_bus_reset(struct ata_port *ap) struct ata_ioports *ioaddr = &ap->ioaddr; unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS; u8 err; - unsigned int dev0, dev1 = 0, rc = 0, devmask = 0; + unsigned int dev0, dev1 = 0, devmask = 0; DPRINTK("ENTER, host %u, port %u\n", ap->id, ap->port_no); @@ -2139,18 +2088,8 @@ void ata_bus_reset(struct ata_port *ap) /* issue bus reset */ if (ap->flags & ATA_FLAG_SRST) - rc = ata_bus_softreset(ap, devmask); - else if ((ap->flags & ATA_FLAG_SATA_RESET) == 0) { - /* set up device control */ - if (ap->flags & ATA_FLAG_MMIO) - writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr); - else - outb(ap->ctl, ioaddr->ctl_addr); - rc = ata_bus_edd(ap); - } - - if (rc) - goto err_out; + if (ata_bus_softreset(ap, devmask)) + goto err_out; /* * determine by signature whether we have ATA or ATAPI devices @@ -2223,9 +2162,9 @@ static int sata_phy_resume(struct ata_port *ap) * so makes reset sequence different from the original * ->phy_reset implementation and Jeff nervous. :-P */ -extern void ata_std_probeinit(struct ata_port *ap) +void ata_std_probeinit(struct ata_port *ap) { - if (ap->flags & ATA_FLAG_SATA && ap->ops->scr_read) { + if ((ap->flags & ATA_FLAG_SATA) && ap->ops->scr_read) { sata_phy_resume(ap); if (sata_dev_present(ap)) ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT); @@ -2714,18 +2653,23 @@ static int ata_dma_blacklisted(const struct ata_device *dev) * known limits including host controller limits, device * blacklist, etc... * + * FIXME: The current implementation limits all transfer modes to + * the fastest of the lowested device on the port. This is not + * required on most controllers. + * * LOCKING: * None. */ static void ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev) { + struct ata_host_set *hs = ap->host_set; unsigned long xfer_mask; int i; xfer_mask = ata_pack_xfermask(ap->pio_mask, ap->mwdma_mask, ap->udma_mask); - /* use port-wide xfermask for now */ + /* FIXME: Use port-wide xfermask for now */ for (i = 0; i < ATA_MAX_DEVICES; i++) { struct ata_device *d = &ap->device[i]; if (!ata_dev_present(d)) @@ -2735,12 +2679,23 @@ static void ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev) xfer_mask &= ata_id_xfermask(d->id); if (ata_dma_blacklisted(d)) xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); + /* Apply cable rule here. Don't apply it early because when + we handle hot plug the cable type can itself change */ + if (ap->cbl == ATA_CBL_PATA40) + xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA); } if (ata_dma_blacklisted(dev)) printk(KERN_WARNING "ata%u: dev %u is on DMA blacklist, " "disabling DMA\n", ap->id, dev->devno); + if (hs->flags & ATA_HOST_SIMPLEX) { + if (hs->simplex_claimed) + xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); + } + if (ap->ops->mode_filter) + xfer_mask = ap->ops->mode_filter(ap, dev, xfer_mask); + ata_unpack_xfermask(xfer_mask, &dev->pio_mask, &dev->mwdma_mask, &dev->udma_mask); } @@ -2795,16 +2750,16 @@ static unsigned int ata_dev_set_xfermode(struct ata_port *ap, */ static unsigned int ata_dev_init_params(struct ata_port *ap, - struct ata_device *dev) + struct ata_device *dev, + u16 heads, + u16 sectors) { struct ata_taskfile tf; unsigned int err_mask; - u16 sectors = dev->id[6]; - u16 heads = dev->id[3]; /* Number of sectors per track 1-255. Number of heads 1-16 */ if (sectors < 1 || sectors > 255 || heads < 1 || heads > 16) - return 0; + return AC_ERR_INVALID; /* set up init dev params taskfile */ DPRINTK("init dev params \n"); @@ -4536,6 +4491,14 @@ static struct ata_port * ata_host_add(const struct ata_probe_ent *ent, int rc; DPRINTK("ENTER\n"); + + if (!ent->port_ops->probe_reset && + !(ent->host_flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST))) { + printk(KERN_ERR "ata%u: no reset mechanism available\n", + port_no); + return NULL; + } + host = scsi_host_alloc(ent->sht, sizeof(struct ata_port)); if (!host) return NULL; @@ -4596,6 +4559,7 @@ int ata_device_add(const struct ata_probe_ent *ent) host_set->mmio_base = ent->mmio_base; host_set->private_data = ent->private_data; host_set->ops = ent->port_ops; + host_set->flags = ent->host_set_flags; /* register each port bound to this device */ for (i = 0; i < ent->n_ports; i++) { diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index 275ed9bd898c..fa901fd65085 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -1010,7 +1010,7 @@ static void mv_fill_sg(struct ata_queued_cmd *qc) pp->sg_tbl[i].addr = cpu_to_le32(addr & 0xffffffff); pp->sg_tbl[i].addr_hi = cpu_to_le32((addr >> 16) >> 16); - pp->sg_tbl[i].flags_size = cpu_to_le32(len); + pp->sg_tbl[i].flags_size = cpu_to_le32(len & 0xffff); sg_len -= len; addr += len; @@ -1350,7 +1350,6 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant, { void __iomem *mmio = host_set->mmio_base; void __iomem *hc_mmio = mv_hc_base(mmio, hc); - struct ata_port *ap; struct ata_queued_cmd *qc; u32 hc_irq_cause; int shift, port, port0, hard_port, handled; @@ -1373,25 +1372,32 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant, for (port = port0; port < port0 + MV_PORTS_PER_HC; port++) { u8 ata_status = 0; - ap = host_set->ports[port]; + struct ata_port *ap = host_set->ports[port]; + struct mv_port_priv *pp = ap->private_data; + hard_port = port & MV_PORT_MASK; /* range 0-3 */ handled = 0; /* ensure ata_status is set if handled++ */ - if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause) { - /* new CRPB on the queue; just one at a time until NCQ - */ - ata_status = mv_get_crpb_status(ap); - handled++; - } else if ((DEV_IRQ << hard_port) & hc_irq_cause) { - /* received ATA IRQ; read the status reg to clear INTRQ - */ - ata_status = readb((void __iomem *) + /* Note that DEV_IRQ might happen spuriously during EDMA, + * and should be ignored in such cases. We could mask it, + * but it's pretty rare and may not be worth the overhead. + */ + if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) { + /* EDMA: check for response queue interrupt */ + if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause) { + ata_status = mv_get_crpb_status(ap); + handled = 1; + } + } else { + /* PIO: check for device (drive) interrupt */ + if ((DEV_IRQ << hard_port) & hc_irq_cause) { + ata_status = readb((void __iomem *) ap->ioaddr.status_addr); - handled++; + handled = 1; + } } - if (ap && - (ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) + if (ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR)) continue; err_mask = ac_err_mask(ata_status); @@ -1403,12 +1409,12 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant, if ((PORT0_ERR << shift) & relevant) { mv_err_intr(ap); err_mask |= AC_ERR_OTHER; - handled++; + handled = 1; } - if (handled && ap) { + if (handled) { qc = ata_qc_from_tag(ap, ap->active_tag); - if (NULL != qc) { + if (qc && (qc->flags & ATA_QCFLAG_ACTIVE)) { VPRINTK("port %u IRQ found for qc, " "ata_status 0x%x\n", port,ata_status); /* mark qc status appropriately */ |