Merge branch 'drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6
* 'drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6: drm/ati_pcigart: fix the PCIGART to use drm_pci to allocate GART table. drm/radeon: fixup RV550 chip family drm/via: attempt again to stabilise the AGP DMA command submission. drm: Fix race that can lockup the kernel
This commit is contained in:
Коммит
ff69c00f0a
|
@ -35,42 +35,23 @@
|
|||
|
||||
# define ATI_PCIGART_PAGE_SIZE 4096 /**< PCI GART page size */
|
||||
|
||||
static void *drm_ati_alloc_pcigart_table(int order)
|
||||
static int drm_ati_alloc_pcigart_table(struct drm_device *dev,
|
||||
struct drm_ati_pcigart_info *gart_info)
|
||||
{
|
||||
unsigned long address;
|
||||
struct page *page;
|
||||
int i;
|
||||
gart_info->table_handle = drm_pci_alloc(dev, gart_info->table_size,
|
||||
PAGE_SIZE,
|
||||
gart_info->table_mask);
|
||||
if (gart_info->table_handle == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
DRM_DEBUG("%d order\n", order);
|
||||
|
||||
address = __get_free_pages(GFP_KERNEL | __GFP_COMP,
|
||||
order);
|
||||
if (address == 0UL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
page = virt_to_page(address);
|
||||
|
||||
for (i = 0; i < order; i++, page++)
|
||||
SetPageReserved(page);
|
||||
|
||||
DRM_DEBUG("returning 0x%08lx\n", address);
|
||||
return (void *)address;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void drm_ati_free_pcigart_table(void *address, int order)
|
||||
static void drm_ati_free_pcigart_table(struct drm_device *dev,
|
||||
struct drm_ati_pcigart_info *gart_info)
|
||||
{
|
||||
struct page *page;
|
||||
int i;
|
||||
int num_pages = 1 << order;
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
page = virt_to_page((unsigned long)address);
|
||||
|
||||
for (i = 0; i < num_pages; i++, page++)
|
||||
ClearPageReserved(page);
|
||||
|
||||
free_pages((unsigned long)address, order);
|
||||
drm_pci_free(dev, gart_info->table_handle);
|
||||
gart_info->table_handle = NULL;
|
||||
}
|
||||
|
||||
int drm_ati_pcigart_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info *gart_info)
|
||||
|
@ -78,8 +59,7 @@ int drm_ati_pcigart_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info
|
|||
struct drm_sg_mem *entry = dev->sg;
|
||||
unsigned long pages;
|
||||
int i;
|
||||
int order;
|
||||
int num_pages, max_pages;
|
||||
int max_pages;
|
||||
|
||||
/* we need to support large memory configurations */
|
||||
if (!entry) {
|
||||
|
@ -87,15 +67,7 @@ int drm_ati_pcigart_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info
|
|||
return 0;
|
||||
}
|
||||
|
||||
order = drm_order((gart_info->table_size + (PAGE_SIZE-1)) / PAGE_SIZE);
|
||||
num_pages = 1 << order;
|
||||
|
||||
if (gart_info->bus_addr) {
|
||||
if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) {
|
||||
pci_unmap_single(dev->pdev, gart_info->bus_addr,
|
||||
num_pages * PAGE_SIZE,
|
||||
PCI_DMA_TODEVICE);
|
||||
}
|
||||
|
||||
max_pages = (gart_info->table_size / sizeof(u32));
|
||||
pages = (entry->pages <= max_pages)
|
||||
|
@ -112,10 +84,9 @@ int drm_ati_pcigart_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info
|
|||
gart_info->bus_addr = 0;
|
||||
}
|
||||
|
||||
if (gart_info->gart_table_location == DRM_ATI_GART_MAIN
|
||||
&& gart_info->addr) {
|
||||
drm_ati_free_pcigart_table(gart_info->addr, order);
|
||||
gart_info->addr = NULL;
|
||||
if (gart_info->gart_table_location == DRM_ATI_GART_MAIN &&
|
||||
gart_info->table_handle) {
|
||||
drm_ati_free_pcigart_table(dev, gart_info);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
@ -127,11 +98,10 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga
|
|||
struct drm_sg_mem *entry = dev->sg;
|
||||
void *address = NULL;
|
||||
unsigned long pages;
|
||||
u32 *pci_gart, page_base, bus_address = 0;
|
||||
u32 *pci_gart, page_base;
|
||||
dma_addr_t bus_address = 0;
|
||||
int i, j, ret = 0;
|
||||
int order;
|
||||
int max_pages;
|
||||
int num_pages;
|
||||
|
||||
if (!entry) {
|
||||
DRM_ERROR("no scatter/gather memory!\n");
|
||||
|
@ -141,31 +111,14 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga
|
|||
if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) {
|
||||
DRM_DEBUG("PCI: no table in VRAM: using normal RAM\n");
|
||||
|
||||
order = drm_order((gart_info->table_size +
|
||||
(PAGE_SIZE-1)) / PAGE_SIZE);
|
||||
num_pages = 1 << order;
|
||||
address = drm_ati_alloc_pcigart_table(order);
|
||||
if (!address) {
|
||||
ret = drm_ati_alloc_pcigart_table(dev, gart_info);
|
||||
if (ret) {
|
||||
DRM_ERROR("cannot allocate PCI GART page!\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!dev->pdev) {
|
||||
DRM_ERROR("PCI device unknown!\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
bus_address = pci_map_single(dev->pdev, address,
|
||||
num_pages * PAGE_SIZE,
|
||||
PCI_DMA_TODEVICE);
|
||||
if (bus_address == 0) {
|
||||
DRM_ERROR("unable to map PCIGART pages!\n");
|
||||
order = drm_order((gart_info->table_size +
|
||||
(PAGE_SIZE-1)) / PAGE_SIZE);
|
||||
drm_ati_free_pcigart_table(address, order);
|
||||
address = NULL;
|
||||
goto done;
|
||||
}
|
||||
address = gart_info->table_handle->vaddr;
|
||||
bus_address = gart_info->table_handle->busaddr;
|
||||
} else {
|
||||
address = gart_info->addr;
|
||||
bus_address = gart_info->bus_addr;
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
#include <linux/pci.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/smp_lock.h> /* For (un)lock_kernel */
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/mutex.h>
|
||||
|
@ -551,6 +552,8 @@ struct drm_ati_pcigart_info {
|
|||
int gart_reg_if;
|
||||
void *addr;
|
||||
dma_addr_t bus_addr;
|
||||
dma_addr_t table_mask;
|
||||
struct drm_dma_handle *table_handle;
|
||||
drm_local_map_t mapping;
|
||||
int table_size;
|
||||
};
|
||||
|
|
|
@ -326,6 +326,7 @@ int drm_release(struct inode *inode, struct file *filp)
|
|||
struct drm_file *file_priv = filp->private_data;
|
||||
struct drm_device *dev = file_priv->head->dev;
|
||||
int retcode = 0;
|
||||
unsigned long irqflags;
|
||||
|
||||
lock_kernel();
|
||||
|
||||
|
@ -357,9 +358,11 @@ int drm_release(struct inode *inode, struct file *filp)
|
|||
*/
|
||||
|
||||
do{
|
||||
spin_lock(&dev->lock.spinlock);
|
||||
spin_lock_irqsave(&dev->lock.spinlock,
|
||||
irqflags);
|
||||
locked = dev->lock.idle_has_lock;
|
||||
spin_unlock(&dev->lock.spinlock);
|
||||
spin_unlock_irqrestore(&dev->lock.spinlock,
|
||||
irqflags);
|
||||
if (locked)
|
||||
break;
|
||||
schedule();
|
||||
|
|
|
@ -53,6 +53,7 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
|||
DECLARE_WAITQUEUE(entry, current);
|
||||
struct drm_lock *lock = data;
|
||||
int ret = 0;
|
||||
unsigned long irqflags;
|
||||
|
||||
++file_priv->lock_count;
|
||||
|
||||
|
@ -71,9 +72,9 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
|||
return -EINVAL;
|
||||
|
||||
add_wait_queue(&dev->lock.lock_queue, &entry);
|
||||
spin_lock(&dev->lock.spinlock);
|
||||
spin_lock_irqsave(&dev->lock.spinlock, irqflags);
|
||||
dev->lock.user_waiters++;
|
||||
spin_unlock(&dev->lock.spinlock);
|
||||
spin_unlock_irqrestore(&dev->lock.spinlock, irqflags);
|
||||
for (;;) {
|
||||
__set_current_state(TASK_INTERRUPTIBLE);
|
||||
if (!dev->lock.hw_lock) {
|
||||
|
@ -95,9 +96,9 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
|||
break;
|
||||
}
|
||||
}
|
||||
spin_lock(&dev->lock.spinlock);
|
||||
spin_lock_irqsave(&dev->lock.spinlock, irqflags);
|
||||
dev->lock.user_waiters--;
|
||||
spin_unlock(&dev->lock.spinlock);
|
||||
spin_unlock_irqrestore(&dev->lock.spinlock, irqflags);
|
||||
__set_current_state(TASK_RUNNING);
|
||||
remove_wait_queue(&dev->lock.lock_queue, &entry);
|
||||
|
||||
|
@ -198,8 +199,9 @@ int drm_lock_take(struct drm_lock_data *lock_data,
|
|||
{
|
||||
unsigned int old, new, prev;
|
||||
volatile unsigned int *lock = &lock_data->hw_lock->lock;
|
||||
unsigned long irqflags;
|
||||
|
||||
spin_lock(&lock_data->spinlock);
|
||||
spin_lock_irqsave(&lock_data->spinlock, irqflags);
|
||||
do {
|
||||
old = *lock;
|
||||
if (old & _DRM_LOCK_HELD)
|
||||
|
@ -211,7 +213,7 @@ int drm_lock_take(struct drm_lock_data *lock_data,
|
|||
}
|
||||
prev = cmpxchg(lock, old, new);
|
||||
} while (prev != old);
|
||||
spin_unlock(&lock_data->spinlock);
|
||||
spin_unlock_irqrestore(&lock_data->spinlock, irqflags);
|
||||
|
||||
if (_DRM_LOCKING_CONTEXT(old) == context) {
|
||||
if (old & _DRM_LOCK_HELD) {
|
||||
|
@ -272,15 +274,16 @@ int drm_lock_free(struct drm_lock_data *lock_data, unsigned int context)
|
|||
{
|
||||
unsigned int old, new, prev;
|
||||
volatile unsigned int *lock = &lock_data->hw_lock->lock;
|
||||
unsigned long irqflags;
|
||||
|
||||
spin_lock(&lock_data->spinlock);
|
||||
spin_lock_irqsave(&lock_data->spinlock, irqflags);
|
||||
if (lock_data->kernel_waiters != 0) {
|
||||
drm_lock_transfer(lock_data, 0);
|
||||
lock_data->idle_has_lock = 1;
|
||||
spin_unlock(&lock_data->spinlock);
|
||||
spin_unlock_irqrestore(&lock_data->spinlock, irqflags);
|
||||
return 1;
|
||||
}
|
||||
spin_unlock(&lock_data->spinlock);
|
||||
spin_unlock_irqrestore(&lock_data->spinlock, irqflags);
|
||||
|
||||
do {
|
||||
old = *lock;
|
||||
|
@ -344,19 +347,20 @@ static int drm_notifier(void *priv)
|
|||
void drm_idlelock_take(struct drm_lock_data *lock_data)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long irqflags;
|
||||
|
||||
spin_lock(&lock_data->spinlock);
|
||||
spin_lock_irqsave(&lock_data->spinlock, irqflags);
|
||||
lock_data->kernel_waiters++;
|
||||
if (!lock_data->idle_has_lock) {
|
||||
|
||||
spin_unlock(&lock_data->spinlock);
|
||||
spin_unlock_irqrestore(&lock_data->spinlock, irqflags);
|
||||
ret = drm_lock_take(lock_data, DRM_KERNEL_CONTEXT);
|
||||
spin_lock(&lock_data->spinlock);
|
||||
spin_lock_irqsave(&lock_data->spinlock, irqflags);
|
||||
|
||||
if (ret == 1)
|
||||
lock_data->idle_has_lock = 1;
|
||||
}
|
||||
spin_unlock(&lock_data->spinlock);
|
||||
spin_unlock_irqrestore(&lock_data->spinlock, irqflags);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_idlelock_take);
|
||||
|
||||
|
@ -364,8 +368,9 @@ void drm_idlelock_release(struct drm_lock_data *lock_data)
|
|||
{
|
||||
unsigned int old, prev;
|
||||
volatile unsigned int *lock = &lock_data->hw_lock->lock;
|
||||
unsigned long irqflags;
|
||||
|
||||
spin_lock(&lock_data->spinlock);
|
||||
spin_lock_irqsave(&lock_data->spinlock, irqflags);
|
||||
if (--lock_data->kernel_waiters == 0) {
|
||||
if (lock_data->idle_has_lock) {
|
||||
do {
|
||||
|
@ -376,7 +381,7 @@ void drm_idlelock_release(struct drm_lock_data *lock_data)
|
|||
lock_data->idle_has_lock = 0;
|
||||
}
|
||||
}
|
||||
spin_unlock(&lock_data->spinlock);
|
||||
spin_unlock_irqrestore(&lock_data->spinlock, irqflags);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_idlelock_release);
|
||||
|
||||
|
|
|
@ -205,9 +205,9 @@
|
|||
{0x1002, 0x71D6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x71DA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x71DE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x7200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x7210, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x7211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x7200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x7210, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x7211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x7240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x7243, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x7244, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
|
||||
|
@ -238,6 +238,7 @@
|
|||
{0x1002, 0x7834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x7835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
|
||||
{0x1002, 0x791e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS690|RADEON_IS_IGP|RADEON_NEW_MEMMAP|RADEON_IS_IGPGART}, \
|
||||
{0x1002, 0x791f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS690|RADEON_IS_IGP|RADEON_NEW_MEMMAP|RADEON_IS_IGPGART}, \
|
||||
{0, 0, 0}
|
||||
|
||||
#define r128_PCI_IDS \
|
||||
|
|
|
@ -558,6 +558,7 @@ static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init)
|
|||
#if __OS_HAS_AGP
|
||||
if (dev_priv->is_pci) {
|
||||
#endif
|
||||
dev_priv->gart_info.table_mask = DMA_BIT_MASK(32);
|
||||
dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN;
|
||||
dev_priv->gart_info.table_size = R128_PCIGART_TABLE_SIZE;
|
||||
dev_priv->gart_info.addr = NULL;
|
||||
|
|
|
@ -1807,6 +1807,7 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init)
|
|||
} else
|
||||
#endif
|
||||
{
|
||||
dev_priv->gart_info.table_mask = DMA_BIT_MASK(32);
|
||||
/* if we have an offset set from userspace */
|
||||
if (dev_priv->pcigart_offset_set) {
|
||||
dev_priv->gart_info.bus_addr =
|
||||
|
|
|
@ -126,6 +126,8 @@ via_cmdbuf_wait(drm_via_private_t * dev_priv, unsigned int size)
|
|||
hw_addr, cur_addr, next_addr);
|
||||
return -1;
|
||||
}
|
||||
if ((cur_addr < hw_addr) && (next_addr >= hw_addr))
|
||||
msleep(1);
|
||||
} while ((cur_addr < hw_addr) && (next_addr >= hw_addr));
|
||||
return 0;
|
||||
}
|
||||
|
@ -416,27 +418,50 @@ static int via_hook_segment(drm_via_private_t * dev_priv,
|
|||
int paused, count;
|
||||
volatile uint32_t *paused_at = dev_priv->last_pause_ptr;
|
||||
uint32_t reader,ptr;
|
||||
uint32_t diff;
|
||||
|
||||
paused = 0;
|
||||
via_flush_write_combine();
|
||||
(void) *(volatile uint32_t *)(via_get_dma(dev_priv) -1);
|
||||
|
||||
*paused_at = pause_addr_lo;
|
||||
via_flush_write_combine();
|
||||
(void) *paused_at;
|
||||
|
||||
reader = *(dev_priv->hw_addr_ptr);
|
||||
ptr = ((volatile char *)paused_at - dev_priv->dma_ptr) +
|
||||
dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4;
|
||||
|
||||
dev_priv->last_pause_ptr = via_get_dma(dev_priv) - 1;
|
||||
|
||||
if ((ptr - reader) <= dev_priv->dma_diff ) {
|
||||
count = 10000000;
|
||||
while (!(paused = (VIA_READ(0x41c) & 0x80000000)) && count--);
|
||||
/*
|
||||
* If there is a possibility that the command reader will
|
||||
* miss the new pause address and pause on the old one,
|
||||
* In that case we need to program the new start address
|
||||
* using PCI.
|
||||
*/
|
||||
|
||||
diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff;
|
||||
count = 10000000;
|
||||
while(diff == 0 && count--) {
|
||||
paused = (VIA_READ(0x41c) & 0x80000000);
|
||||
if (paused)
|
||||
break;
|
||||
reader = *(dev_priv->hw_addr_ptr);
|
||||
diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff;
|
||||
}
|
||||
|
||||
paused = VIA_READ(0x41c) & 0x80000000;
|
||||
|
||||
if (paused && !no_pci_fire) {
|
||||
reader = *(dev_priv->hw_addr_ptr);
|
||||
if ((ptr - reader) == dev_priv->dma_diff) {
|
||||
|
||||
diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff;
|
||||
diff &= (dev_priv->dma_high - 1);
|
||||
if (diff != 0 && diff < (dev_priv->dma_high >> 1)) {
|
||||
DRM_ERROR("Paused at incorrect address. "
|
||||
"0x%08x, 0x%08x 0x%08x\n",
|
||||
ptr, reader, dev_priv->dma_diff);
|
||||
} else if (diff == 0) {
|
||||
/*
|
||||
* There is a concern that these writes may stall the PCI bus
|
||||
* if the GPU is not idle. However, idling the GPU first
|
||||
|
@ -577,6 +602,7 @@ static void via_cmdbuf_jump(drm_via_private_t * dev_priv)
|
|||
uint32_t pause_addr_lo, pause_addr_hi;
|
||||
uint32_t jump_addr_lo, jump_addr_hi;
|
||||
volatile uint32_t *last_pause_ptr;
|
||||
uint32_t dma_low_save1, dma_low_save2;
|
||||
|
||||
agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
|
||||
via_align_cmd(dev_priv, HC_HAGPBpID_JUMP, 0, &jump_addr_hi,
|
||||
|
@ -603,8 +629,29 @@ static void via_cmdbuf_jump(drm_via_private_t * dev_priv)
|
|||
&pause_addr_lo, 0);
|
||||
|
||||
*last_pause_ptr = pause_addr_lo;
|
||||
dma_low_save1 = dev_priv->dma_low;
|
||||
|
||||
via_hook_segment( dev_priv, jump_addr_hi, jump_addr_lo, 0);
|
||||
/*
|
||||
* Now, set a trap that will pause the regulator if it tries to rerun the old
|
||||
* command buffer. (Which may happen if via_hook_segment detecs a command regulator pause
|
||||
* and reissues the jump command over PCI, while the regulator has already taken the jump
|
||||
* and actually paused at the current buffer end).
|
||||
* There appears to be no other way to detect this condition, since the hw_addr_pointer
|
||||
* does not seem to get updated immediately when a jump occurs.
|
||||
*/
|
||||
|
||||
last_pause_ptr =
|
||||
via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
|
||||
&pause_addr_lo, 0) - 1;
|
||||
via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
|
||||
&pause_addr_lo, 0);
|
||||
*last_pause_ptr = pause_addr_lo;
|
||||
|
||||
dma_low_save2 = dev_priv->dma_low;
|
||||
dev_priv->dma_low = dma_low_save1;
|
||||
via_hook_segment(dev_priv, jump_addr_hi, jump_addr_lo, 0);
|
||||
dev_priv->dma_low = dma_low_save2;
|
||||
via_hook_segment(dev_priv, pause_addr_hi, pause_addr_lo, 0);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -603,7 +603,7 @@ via_build_sg_info(struct drm_device *dev, drm_via_sg_info_t *vsg, drm_via_dmabli
|
|||
* (Not a big limitation anyway.)
|
||||
*/
|
||||
|
||||
if ((xfer->mem_stride - xfer->line_length) >= PAGE_SIZE) {
|
||||
if ((xfer->mem_stride - xfer->line_length) > 2*PAGE_SIZE) {
|
||||
DRM_ERROR("Too large system memory stride. Stride: %d, "
|
||||
"Length: %d\n", xfer->mem_stride, xfer->line_length);
|
||||
return -EINVAL;
|
||||
|
|
Загрузка…
Ссылка в новой задаче