From 5a92c3dfe22fc451a814d7f9745d9be8e3da7f96 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 10 Jan 2003 11:14:35 +0000 Subject: [ARM] Remove CPU manufacturer string. The CPU ID no longer contains sufficient information to reliably determine the manufacturer of a specific part. To prevent #ifdef madness appearing in the per-CPU support files, it is better to remove the CPU manufacturer string entirely. --- include/asm-arm/procinfo.h | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'include') diff --git a/include/asm-arm/procinfo.h b/include/asm-arm/procinfo.h index fced718b32be..a762a23a7560 100644 --- a/include/asm-arm/procinfo.h +++ b/include/asm-arm/procinfo.h @@ -16,11 +16,6 @@ struct cpu_tlb_fns; struct cpu_user_fns; struct processor; -struct proc_info_item { - const char *manufacturer; - const char *cpu_name; -}; - /* * Note! struct processor is always defined if we're * using MULTI_CPU, otherwise this entry is unused, @@ -38,7 +33,7 @@ struct proc_info_list { const char *arch_name; const char *elf_name; unsigned int elf_hwcap; - struct proc_info_item *info; + const char *cpu_name; struct processor *proc; struct cpu_tlb_fns *tlb; struct cpu_user_fns *user; -- cgit v1.2.3 From 9804476ca07d30f7771dfc51fe3e2bd22d910817 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 10 Jan 2003 21:41:11 +0000 Subject: [ARM] Fix consistent_alloc() The old consistent memory allocator, which sat behind dma_coherent_alloc() and pci_consistent_alloc() was completely unable to handle allocations from interrupt context because we traditionally used ioremap, which in turn: - allocates memory using GFP_KERNEL for the vm_struct and the page tables themselves. - calls get_vm_area, which uses write_lock, and therefore is unsafe to call from interrupt context. In order to address this issue, a new consistent_alloc() which avoids the above issues has been implemented. Essentially, we set aside a section of the kernel VM space, and pre-allocate page tables to cover this area. We allocate "consistent" memory within this region. The handling of the allocation is designed to be generic; it should be possible to replace the vmalloc(), ioremap() and module_alloc() without too much hastle, but that would clearly be a 2.7 thing at this stage. --- arch/arm/mm/consistent.c | 348 +++++++++++++++++++++++++++++++++--------- drivers/video/sa1100fb.c | 2 +- include/asm-arm/dma-mapping.h | 6 +- include/asm-arm/pci.h | 4 +- 4 files changed, 285 insertions(+), 75 deletions(-) (limited to 'include') diff --git a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c index 5bf50fc12ba0..897669e0e5bf 100644 --- a/arch/arm/mm/consistent.c +++ b/arch/arm/mm/consistent.c @@ -1,48 +1,156 @@ /* * linux/arch/arm/mm/consistent.c * - * Copyright (C) 2000 Russell King + * Copyright (C) 2000-2002 Russell King * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * - * Dynamic DMA mapping support. + * DMA uncached mapping support. */ #include #include #include +#include #include -#include #include #include -#include +#include #include +#include +#include #include #include #include +#include + +#define CONSISTENT_BASE (0xffc00000) +#define CONSISTENT_END (0xffe00000) +#define CONSISTENT_OFFSET(x) (((unsigned long)(x) - CONSISTENT_BASE) >> PAGE_SHIFT) /* - * This allocates one page of cache-coherent memory space and returns - * both the virtual and a "dma" address to that space. + * This is the page table (2MB) covering uncached, DMA consistent allocations + */ +static pte_t *consistent_pte; +static spinlock_t consistent_lock = SPIN_LOCK_UNLOCKED; + +/* + * VM region handling support. * - * We should allow this function to be called from interrupt context. - * However, we call ioremap, which needs to fiddle around with various - * things (like the vmlist_lock, and allocating page tables). These - * things aren't interrupt safe (yet). + * This should become something generic, handling VM region allocations for + * vmalloc and similar (ioremap, module space, etc). * - * Note that this does *not* zero the allocated area! + * I envisage vmalloc()'s supporting vm_struct becoming: + * + * struct vm_struct { + * struct vm_region region; + * unsigned long flags; + * struct page **pages; + * unsigned int nr_pages; + * unsigned long phys_addr; + * }; + * + * get_vm_area() would then call vm_region_alloc with an appropriate + * struct vm_region head (eg): + * + * struct vm_region vmalloc_head = { + * .vm_list = LIST_HEAD_INIT(vmalloc_head.vm_list), + * .vm_start = VMALLOC_START, + * .vm_end = VMALLOC_END, + * }; + * + * However, vmalloc_head.vm_start is variable (typically, it is dependent on + * the amount of RAM found at boot time.) I would imagine that get_vm_area() + * would have to initialise this each time prior to calling vm_region_alloc(). */ -void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle) +struct vm_region { + struct list_head vm_list; + unsigned long vm_start; + unsigned long vm_end; +}; + +static struct vm_region consistent_head = { + .vm_list = LIST_HEAD_INIT(consistent_head.vm_list), + .vm_start = CONSISTENT_BASE, + .vm_end = CONSISTENT_END, +}; + +#if 0 +static void vm_region_dump(struct vm_region *head, char *fn) { - struct page *page, *end, *free; - unsigned long order; - void *ret; + struct vm_region *c; - /* FIXME */ - if (in_interrupt()) - BUG(); + printk("Consistent Allocation Map (%s):\n", fn); + list_for_each_entry(c, &head->list, vm_list) { + printk(" %p: %08lx - %08lx (0x%08x)\n", c, + c->vm_start, c->vm_end, c->vm_end - c->vm_start); + } +} +#else +#define vm_region_dump(head,fn) do { } while(0) +#endif + +static int vm_region_alloc(struct vm_region *head, struct vm_region *new, size_t size) +{ + unsigned long addr = head->vm_start, end = head->vm_end - size; + struct vm_region *c; + + list_for_each_entry(c, &head->vm_list, vm_list) { + if ((addr + size) < addr) + goto out; + if ((addr + size) <= c->vm_start) + goto found; + addr = c->vm_end; + if (addr > end) + goto out; + } + + found: + /* + * Insert this entry _before_ the one we found. + */ + list_add_tail(&new->vm_list, &c->vm_list); + new->vm_start = addr; + new->vm_end = addr + size; + + return 0; + + out: + return -ENOMEM; +} + +static struct vm_region *vm_region_find(struct vm_region *head, unsigned long addr) +{ + struct vm_region *c; + + list_for_each_entry(c, &head->vm_list, vm_list) { + if (c->vm_start == addr) + goto out; + } + c = NULL; + out: + return c; +} + +/* + * This allocates one page of cache-coherent memory space and returns + * both the virtual and a "dma" address to that space. + */ +void *consistent_alloc(int gfp, size_t size, dma_addr_t *handle, + unsigned long cache_flags) +{ + struct page *page; + struct vm_region *c; + unsigned long order, flags; + void *ret = NULL; + + if (!consistent_pte) { + printk(KERN_ERR "consistent_alloc: not initialised\n"); + dump_stack(); + return NULL; + } size = PAGE_ALIGN(size); order = get_order(size); @@ -51,74 +159,176 @@ void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle) if (!page) goto no_page; - *dma_handle = page_to_bus(page); - ret = __ioremap(page_to_pfn(page) << PAGE_SHIFT, size, 0, - PAGE_SIZE << order); - if (!ret) + /* + * Invalidate any data that might be lurking in the + * kernel direct-mapped region. + */ + { + unsigned long kaddr = (unsigned long)page_address(page); + invalidate_dcache_range(kaddr, kaddr + size); + } + + /* + * Our housekeeping doesn't need to come from DMA, + * but it must not come from highmem. + */ + c = kmalloc(sizeof(struct vm_region), + gfp & ~(__GFP_DMA | __GFP_HIGHMEM)); + if (!c) goto no_remap; -#if 0 /* ioremap_does_flush_cache_all */ - { - void *virt = page_address(page); + spin_lock_irqsave(&consistent_lock, flags); + vm_region_dump(&consistent_head, "before alloc"); + + /* + * Attempt to allocate a virtual address in the + * consistent mapping region. + */ + if (!vm_region_alloc(&consistent_head, c, size)) { + pte_t *pte = consistent_pte + CONSISTENT_OFFSET(c->vm_start); + struct page *end = page + (1 << order); + pgprot_t prot = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | + L_PTE_DIRTY | L_PTE_WRITE | + cache_flags); /* - * we need to ensure that there are no cachelines in use, or - * worse dirty in this area. Really, we don't need to do - * this since __ioremap does a flush_cache_all() anyway. --rmk + * Set the "dma handle" */ - invalidate_dcache_range(virt, virt + size); - } -#endif + *handle = page_to_bus(page); - /* - * free wasted pages. We skip the first page since we know - * that it will have count = 1 and won't require freeing. - * We also mark the pages in use as reserved so that - * remap_page_range works. - */ - free = page + (size >> PAGE_SHIFT); - end = page + (1 << order); + do { + BUG_ON(!pte_none(*pte)); - for (; page < end; page++) { - set_page_count(page, 1); - if (page >= free) - __free_page(page); - else + set_page_count(page, 1); SetPageReserved(page); + set_pte(pte, mk_pte(page, prot)); + page++; + pte++; + } while (size -= PAGE_SIZE); + + /* + * Free the otherwise unused pages. + */ + while (page < end) { + set_page_count(page, 1); + __free_page(page); + page++; + } + + ret = (void *)c->vm_start; } - return ret; -no_remap: - __free_pages(page, order); -no_page: - return NULL; + vm_region_dump(&consistent_head, "after alloc"); + spin_unlock_irqrestore(&consistent_lock, flags); + + no_remap: + if (ret == NULL) { + kfree(c); + __free_pages(page, order); + } + no_page: + return ret; } /* - * free a page as defined by the above mapping. We expressly forbid - * calling this from interrupt context. + * free a page as defined by the above mapping. */ void consistent_free(void *vaddr, size_t size, dma_addr_t handle) { - struct page *page, *end; + struct vm_region *c; + unsigned long flags; + pte_t *ptep; - if (in_interrupt()) - BUG(); - - /* - * More messing around with the MM internals. This is - * sick, but then so is remap_page_range(). - */ size = PAGE_ALIGN(size); - page = virt_to_page(bus_to_virt(handle)); - end = page + (size >> PAGE_SHIFT); - for (; page < end; page++) - ClearPageReserved(page); + spin_lock_irqsave(&consistent_lock, flags); + vm_region_dump(&consistent_head, "before free"); - __iounmap(vaddr); + c = vm_region_find(&consistent_head, (unsigned long)vaddr); + if (!c) + goto no_area; + + if ((c->vm_end - c->vm_start) != size) { + printk(KERN_ERR "consistent_free: wrong size (%ld != %d)\n", + c->vm_end - c->vm_start, size); + dump_stack(); + size = c->vm_end - c->vm_start; + } + + ptep = consistent_pte + CONSISTENT_OFFSET(c->vm_start); + do { + pte_t pte = ptep_get_and_clear(ptep); + unsigned long pfn; + + ptep++; + + if (!pte_none(pte) && pte_present(pte)) { + pfn = pte_pfn(pte); + + if (pfn_valid(pfn)) { + struct page *page = pfn_to_page(pfn); + ClearPageReserved(page); + + __free_page(page); + continue; + } + } + + printk(KERN_CRIT "consistent_free: bad page in kernel page " + "table\n"); + } while (size -= PAGE_SIZE); + + flush_tlb_kernel_range(c->vm_start, c->vm_end); + + list_del(&c->vm_list); + + vm_region_dump(&consistent_head, "after free"); + spin_unlock_irqrestore(&consistent_lock, flags); + + kfree(c); + return; + + no_area: + spin_unlock_irqrestore(&consistent_lock, flags); + printk(KERN_ERR "consistent_free: trying to free " + "invalid area: %p\n", vaddr); + dump_stack(); } +/* + * Initialise the consistent memory allocation. + */ +static int __init consistent_init(void) +{ + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + + do { + pgd = pgd_offset(&init_mm, CONSISTENT_BASE); + pmd = pmd_alloc(&init_mm, pgd, CONSISTENT_BASE); + if (!pmd) { + printk(KERN_ERR "consistent_init: out of pmd tables\n"); + return -ENOMEM; + } + if (!pmd_none(*pmd)) { + printk(KERN_ERR "consistent_init: PMD already allocated\n"); + return -EINVAL; + } + pte = pte_alloc_kernel(&init_mm, pmd, CONSISTENT_BASE); + if (!pte) { + printk(KERN_ERR "consistent_init: out of pte tables\n"); + return -ENOMEM; + } + + consistent_pte = pte; + } while (0); + + return 0; +} + +core_initcall(consistent_init); + /* * make an area consistent. */ @@ -128,16 +338,16 @@ void consistent_sync(void *vaddr, size_t size, int direction) unsigned long end = start + size; switch (direction) { - case PCI_DMA_NONE: - BUG(); - case PCI_DMA_FROMDEVICE: /* invalidate only */ + case DMA_FROM_DEVICE: /* invalidate only */ invalidate_dcache_range(start, end); break; - case PCI_DMA_TODEVICE: /* writeback only */ + case DMA_TO_DEVICE: /* writeback only */ clean_dcache_range(start, end); break; - case PCI_DMA_BIDIRECTIONAL: /* writeback and invalidate */ + case DMA_BIDIRECTIONAL: /* writeback and invalidate */ flush_dcache_range(start, end); break; + default: + BUG(); } } diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c index 6f59dfe9a3e7..8a562c320c50 100644 --- a/drivers/video/sa1100fb.c +++ b/drivers/video/sa1100fb.c @@ -1642,7 +1642,7 @@ static int __init sa1100fb_map_video_memory(struct sa1100fb_info *fbi) */ fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + PAGE_SIZE); fbi->map_cpu = consistent_alloc(GFP_KERNEL, fbi->map_size, - &fbi->map_dma); + &fbi->map_dma, PTE_BUFFERABLE); if (fbi->map_cpu) { fbi->fb.screen_base = fbi->map_cpu + PAGE_SIZE; diff --git a/include/asm-arm/dma-mapping.h b/include/asm-arm/dma-mapping.h index dd85f46611e7..e3d1dbb7bebf 100644 --- a/include/asm-arm/dma-mapping.h +++ b/include/asm-arm/dma-mapping.h @@ -14,7 +14,7 @@ * devices. This is the "generic" version. The PCI specific version * is in pci.h */ -extern void *consistent_alloc(int gfp, size_t size, dma_addr_t *handle); +extern void *consistent_alloc(int gfp, size_t size, dma_addr_t *handle, unsigned long flags); extern void consistent_free(void *vaddr, size_t size, dma_addr_t handle); extern void consistent_sync(void *kaddr, size_t size, int rw); @@ -84,12 +84,12 @@ static inline int dma_is_consistent(dma_addr_t handle) static inline void * dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle) { - int gfp = GFP_KERNEL; + int gfp = GFP_ATOMIC; if (dev == NULL || dmadev_is_sa1111(dev) || *dev->dma_mask != 0xffffffff) gfp |= GFP_DMA; - return consistent_alloc(gfp, size, handle); + return consistent_alloc(gfp, size, handle, 0); } /** diff --git a/include/asm-arm/pci.h b/include/asm-arm/pci.h index 7760592d853f..7c690a057a20 100644 --- a/include/asm-arm/pci.h +++ b/include/asm-arm/pci.h @@ -40,13 +40,13 @@ static inline void pcibios_penalize_isa_irq(int irq) static inline void * pci_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *handle) { - int gfp = GFP_KERNEL; + int gfp = GFP_ATOMIC; if (hwdev == NULL || pcidev_is_sa1111(hwdev) || hwdev->dma_mask != 0xffffffff) gfp |= GFP_DMA; - return consistent_alloc(gfp, size, handle); + return consistent_alloc(gfp, size, handle, 0); } static inline void -- cgit v1.2.3 From 322b8a8b4fe7d0447c09e4f162dfcc2befb9d737 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 10 Jan 2003 23:38:32 +0000 Subject: [ARM] __put_user, __get_user cleanups and fixups This fixes the ARM __put_user implementation. The gcc folk have agreed that the %Qn and %Rn register notation in asm() statements should become official, and have been in all compilers which can be used to build the ARM kernel. In addition, we remove some historical gunk from when put_user() and get_user() was inlined on ARM. --- include/asm-arm/proc-armv/uaccess.h | 52 +++++++------- include/asm-arm/uaccess.h | 139 ++++++++++++++---------------------- 2 files changed, 77 insertions(+), 114 deletions(-) (limited to 'include') diff --git a/include/asm-arm/proc-armv/uaccess.h b/include/asm-arm/proc-armv/uaccess.h index 1162e2f9e047..25154d53177c 100644 --- a/include/asm-arm/proc-armv/uaccess.h +++ b/include/asm-arm/proc-armv/uaccess.h @@ -12,7 +12,7 @@ * Note that this is actually 0x1,0000,0000 */ #define KERNEL_DS 0x00000000 -#define USER_DS PAGE_OFFSET +#define USER_DS TASK_SIZE static inline void set_fs (mm_segment_t fs) { @@ -50,8 +50,8 @@ static inline void set_fs (mm_segment_t fs) " .align 3\n" \ " .long 1b, 3b\n" \ " .previous" \ - : "=r" (err) \ - : "r" (x), "r" (__pu_addr), "i" (-EFAULT), "0" (err) \ + : "+r" (err) \ + : "r" (x), "r" (__pu_addr), "i" (-EFAULT) \ : "cc") #ifndef __ARMEB__ @@ -83,19 +83,18 @@ static inline void set_fs (mm_segment_t fs) " .align 3\n" \ " .long 1b, 3b\n" \ " .previous" \ - : "=r" (err) \ - : "r" (x), "r" (__pu_addr), "i" (-EFAULT), "0" (err)) + : "+r" (err) \ + : "r" (x), "r" (__pu_addr), "i" (-EFAULT) \ + : "cc") #define __put_user_asm_dword(x,__pu_addr,err) \ -({ \ - unsigned long long __temp = (unsigned long long)x; \ __asm__ __volatile__( \ - "1: strt %1, [%2], #0\n" \ - "2: strt %3, [%4], #0\n" \ + "1: strt %Q2, [%1], #4\n" \ + "2: strt %R2, [%1], #0\n" \ "3:\n" \ " .section .fixup,\"ax\"\n" \ " .align 2\n" \ - "4: mov %0, %5\n" \ + "4: mov %0, %3\n" \ " b 3b\n" \ " .previous\n" \ " .section __ex_table,\"a\"\n" \ @@ -103,12 +102,9 @@ static inline void set_fs (mm_segment_t fs) " .long 1b, 4b\n" \ " .long 2b, 4b\n" \ " .previous" \ - : "=r" (err) \ - : "r" (__temp), "r" (__pu_addr), \ - "r" (__temp >> 32), "r" (__pu_addr + 4), \ - "i" (-EFAULT), "0" (err) \ - : "cc"); \ -}) + : "+r" (err), "+r" (__pu_addr) \ + : "r" (x), "i" (-EFAULT) \ + : "cc") #define __get_user_asm_byte(x,addr,err) \ __asm__ __volatile__( \ @@ -124,23 +120,24 @@ static inline void set_fs (mm_segment_t fs) " .align 3\n" \ " .long 1b, 3b\n" \ " .previous" \ - : "=r" (err), "=&r" (x) \ - : "r" (addr), "i" (-EFAULT), "0" (err)) + : "+r" (err), "=&r" (x) \ + : "r" (addr), "i" (-EFAULT) \ + : "cc") #ifndef __ARMEB__ -#define __get_user_asm_half(x,addr,err) \ +#define __get_user_asm_half(x,__gu_addr,err) \ ({ \ - unsigned long __b1, __b2, __ptr = (unsigned long)addr; \ - __get_user_asm_byte(__b1, __ptr, err); \ - __get_user_asm_byte(__b2, __ptr + 1, err); \ + unsigned long __b1, __b2; \ + __get_user_asm_byte(__b1, __gu_addr, err); \ + __get_user_asm_byte(__b2, __gu_addr + 1, err); \ (x) = __b1 | (__b2 << 8); \ }) #else -#define __get_user_asm_half(x,addr,err) \ +#define __get_user_asm_half(x,__gu_addr,err) \ ({ \ unsigned long __b1, __b2; \ - __get_user_asm_byte(__b1, addr, err); \ - __get_user_asm_byte(__b2, (int)(addr) + 1, err); \ + __get_user_asm_byte(__b1, __gu_addr, err); \ + __get_user_asm_byte(__b2, __gu_addr + 1, err); \ (x) = (__b1 << 8) | __b2; \ }) #endif @@ -159,8 +156,9 @@ static inline void set_fs (mm_segment_t fs) " .align 3\n" \ " .long 1b, 3b\n" \ " .previous" \ - : "=r" (err), "=&r" (x) \ - : "r" (addr), "i" (-EFAULT), "0" (err)) + : "+r" (err), "=&r" (x) \ + : "r" (addr), "i" (-EFAULT) \ + : "cc") extern unsigned long __arch_copy_from_user(void *to, const void *from, unsigned long n); #define __do_copy_from_user(to,from,n) \ diff --git a/include/asm-arm/uaccess.h b/include/asm-arm/uaccess.h index d21892660de0..0534487d8ff3 100644 --- a/include/asm-arm/uaccess.h +++ b/include/asm-arm/uaccess.h @@ -74,7 +74,7 @@ extern int __get_user_bad(void); __asm__ __volatile__ ("bl __get_user_" #__s \ : "=&r" (__e), "=r" (__r1) \ : "0" (__p) \ - : __i) + : __i, "cc") #define get_user(x,p) \ ({ \ @@ -100,8 +100,31 @@ extern int __get_user_bad(void); __e; \ }) -#define __get_user(x,p) __get_user_nocheck((x),(p),sizeof(*(p))) -#define __get_user_error(x,p,e) __get_user_nocheck_error((x),(p),sizeof(*(p)),(e)) +#define __get_user(x,ptr) \ +({ \ + long __gu_err = 0; \ + __get_user_err((x),(ptr),__gu_err); \ + __gu_err; \ +}) + +#define __get_user_error(x,ptr,err) \ +({ \ + __get_user_err((x),(ptr),err); \ + (void) 0; \ +}) + +#define __get_user_err(x,ptr,err) \ +do { \ + unsigned long __gu_addr = (unsigned long)(ptr); \ + unsigned long __gu_val; \ + switch (sizeof(*(ptr))) { \ + case 1: __get_user_asm_byte(__gu_val,__gu_addr,err); break; \ + case 2: __get_user_asm_half(__gu_val,__gu_addr,err); break; \ + case 4: __get_user_asm_word(__gu_val,__gu_addr,err); break; \ + default: (__gu_val) = __get_user_bad(); \ + } \ + (x) = (__typeof__(*(ptr)))__gu_val; \ +} while (0) extern int __put_user_1(void *, unsigned int); extern int __put_user_2(void *, unsigned int); @@ -113,7 +136,7 @@ extern int __put_user_bad(void); __asm__ __volatile__ ("bl __put_user_" #__s \ : "=&r" (__e) \ : "0" (__p), "r" (__r1) \ - : __i) + : __i, "cc") #define put_user(x,p) \ ({ \ @@ -138,8 +161,31 @@ extern int __put_user_bad(void); __e; \ }) -#define __put_user(x,p) __put_user_nocheck((__typeof(*(p)))(x),(p),sizeof(*(p))) -#define __put_user_error(x,p,e) __put_user_nocheck_error((x),(p),sizeof(*(p)),(e)) +#define __put_user(x,ptr) \ +({ \ + long __pu_err = 0; \ + __put_user_err((x),(ptr),__pu_err); \ + __pu_err; \ +}) + +#define __put_user_error(x,ptr,err) \ +({ \ + __put_user_err((x),(ptr),err); \ + (void) 0; \ +}) + +#define __put_user_err(x,ptr,err) \ +do { \ + unsigned long __pu_addr = (unsigned long)(ptr); \ + __typeof__(*(ptr)) __pu_val = (x); \ + switch (sizeof(*(ptr))) { \ + case 1: __put_user_asm_byte(__pu_val,__pu_addr,err); break; \ + case 2: __put_user_asm_half(__pu_val,__pu_addr,err); break; \ + case 4: __put_user_asm_word(__pu_val,__pu_addr,err); break; \ + case 8: __put_user_asm_dword(__pu_val,__pu_addr,err); break; \ + default: __put_user_bad(); \ + } \ +} while (0) static __inline__ unsigned long copy_from_user(void *to, const void *from, unsigned long n) { @@ -209,85 +255,4 @@ static inline long strnlen_user(const char *s, long n) return res; } -/* - * These are the work horses of the get/put_user functions - */ -#if 0 -#define __get_user_check(x,ptr,size) \ -({ \ - long __gu_err = -EFAULT, __gu_val = 0; \ - const __typeof__(*(ptr)) *__gu_addr = (ptr); \ - if (access_ok(VERIFY_READ,__gu_addr,size)) { \ - __gu_err = 0; \ - __get_user_size(__gu_val,__gu_addr,(size),__gu_err); \ - } \ - (x) = (__typeof__(*(ptr)))__gu_val; \ - __gu_err; \ -}) -#endif - -#define __get_user_nocheck(x,ptr,size) \ -({ \ - long __gu_err = 0, __gu_val; \ - __get_user_size(__gu_val,(ptr),(size),__gu_err); \ - (x) = (__typeof__(*(ptr)))__gu_val; \ - __gu_err; \ -}) - -#define __get_user_nocheck_error(x,ptr,size,err) \ -({ \ - long __gu_val; \ - __get_user_size(__gu_val,(ptr),(size),(err)); \ - (x) = (__typeof__(*(ptr)))__gu_val; \ - (void) 0; \ -}) - -#define __put_user_check(x,ptr,size) \ -({ \ - long __pu_err = -EFAULT; \ - __typeof__(*(ptr)) *__pu_addr = (ptr); \ - if (access_ok(VERIFY_WRITE,__pu_addr,size)) { \ - __pu_err = 0; \ - __put_user_size((x),__pu_addr,(size),__pu_err); \ - } \ - __pu_err; \ -}) - -#define __put_user_nocheck(x,ptr,size) \ -({ \ - long __pu_err = 0; \ - unsigned long __pu_addr = (unsigned long)(ptr); \ - __put_user_size((x),__pu_addr,(size),__pu_err); \ - __pu_err; \ -}) - -#define __put_user_nocheck_error(x,ptr,size,err) \ -({ \ - unsigned long __pu_addr = (unsigned long)(ptr); \ - __put_user_size((x),__pu_addr,(size),err); \ - (void) 0; \ -}) - -#define __get_user_size(x,ptr,size,retval) \ -do { \ - switch (size) { \ - case 1: __get_user_asm_byte(x,ptr,retval); break; \ - case 2: __get_user_asm_half(x,ptr,retval); break; \ - case 4: __get_user_asm_word(x,ptr,retval); break; \ - case 8: __get_user_asm_dword(x,ptr,retval); break; \ - default: (x) = __get_user_bad(); \ - } \ -} while (0) - -#define __put_user_size(x,ptr,size,retval) \ -do { \ - switch (size) { \ - case 1: __put_user_asm_byte(x,ptr,retval); break; \ - case 2: __put_user_asm_half(x,ptr,retval); break; \ - case 4: __put_user_asm_word(x,ptr,retval); break; \ - case 8: __put_user_asm_dword(x,ptr,retval); break; \ - default: __put_user_bad(); \ - } \ -} while (0) - #endif /* _ASMARM_UACCESS_H */ -- cgit v1.2.3 From 470104435ce22b4faec6eec351ba71851e817f59 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 12 Jan 2003 14:50:41 +0000 Subject: [ARM] Ensure that dev->dma_mask is initialised for Acorn cards. --- arch/arm/kernel/ecard.c | 2 ++ include/asm-arm/ecard.h | 1 + 2 files changed, 3 insertions(+) (limited to 'include') diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c index 1206e7d9fd66..a6c0c1993306 100644 --- a/arch/arm/kernel/ecard.c +++ b/arch/arm/kernel/ecard.c @@ -978,6 +978,8 @@ ecard_probe(int slot, card_type_t type) strcpy(ec->dev.name, "fixme!"); ec->dev.parent = NULL; ec->dev.bus = &ecard_bus_type; + ec->dev.dma_mask = &ec->dma_mask; + ec->dma_mask = (u64)0xffffffff; device_register(&ec->dev); diff --git a/include/asm-arm/ecard.h b/include/asm-arm/ecard.h index 1c9ecdadecd9..602dc63b9dfa 100644 --- a/include/asm-arm/ecard.h +++ b/include/asm-arm/ecard.h @@ -160,6 +160,7 @@ struct expansion_card { const char *card_desc; /* Card description */ CONST unsigned int podaddr; /* Base Linux address for card */ CONST loader_t loader; /* loader program */ + u64 dma_mask; }; struct in_chunk_dir { -- cgit v1.2.3