diff options
52 files changed, 831 insertions, 296 deletions
diff --git a/Documentation/io-mapping.txt b/Documentation/io-mapping.txt new file mode 100644 index 000000000000..473e43b2d588 --- /dev/null +++ b/Documentation/io-mapping.txt | |||
| @@ -0,0 +1,82 @@ | |||
| 1 | The io_mapping functions in linux/io-mapping.h provide an abstraction for | ||
| 2 | efficiently mapping small regions of an I/O device to the CPU. The initial | ||
| 3 | usage is to support the large graphics aperture on 32-bit processors where | ||
| 4 | ioremap_wc cannot be used to statically map the entire aperture to the CPU | ||
| 5 | as it would consume too much of the kernel address space. | ||
| 6 | |||
| 7 | A mapping object is created during driver initialization using | ||
| 8 | |||
| 9 | struct io_mapping *io_mapping_create_wc(unsigned long base, | ||
| 10 | unsigned long size) | ||
| 11 | |||
| 12 | 'base' is the bus address of the region to be made | ||
| 13 | mappable, while 'size' indicates how large a mapping region to | ||
| 14 | enable. Both are in bytes. | ||
| 15 | |||
| 16 | This _wc variant provides a mapping which may only be used | ||
| 17 | with the io_mapping_map_atomic_wc or io_mapping_map_wc. | ||
| 18 | |||
| 19 | With this mapping object, individual pages can be mapped either atomically | ||
| 20 | or not, depending on the necessary scheduling environment. Of course, atomic | ||
| 21 | maps are more efficient: | ||
| 22 | |||
| 23 | void *io_mapping_map_atomic_wc(struct io_mapping *mapping, | ||
| 24 | unsigned long offset) | ||
| 25 | |||
| 26 | 'offset' is the offset within the defined mapping region. | ||
| 27 | Accessing addresses beyond the region specified in the | ||
| 28 | creation function yields undefined results. Using an offset | ||
| 29 | which is not page aligned yields an undefined result. The | ||
| 30 | return value points to a single page in CPU address space. | ||
| 31 | |||
| 32 | This _wc variant returns a write-combining map to the | ||
| 33 | page and may only be used with mappings created by | ||
| 34 | io_mapping_create_wc | ||
| 35 | |||
| 36 | Note that the task may not sleep while holding this page | ||
| 37 | mapped. | ||
| 38 | |||
| 39 | void io_mapping_unmap_atomic(void *vaddr) | ||
| 40 | |||
| 41 | 'vaddr' must be the the value returned by the last | ||
| 42 | io_mapping_map_atomic_wc call. This unmaps the specified | ||
| 43 | page and allows the task to sleep once again. | ||
| 44 | |||
| 45 | If you need to sleep while holding the lock, you can use the non-atomic | ||
| 46 | variant, although they may be significantly slower. | ||
| 47 | |||
| 48 | void *io_mapping_map_wc(struct io_mapping *mapping, | ||
| 49 | unsigned long offset) | ||
| 50 | |||
| 51 | This works like io_mapping_map_atomic_wc except it allows | ||
| 52 | the task to sleep while holding the page mapped. | ||
| 53 | |||
| 54 | void io_mapping_unmap(void *vaddr) | ||
| 55 | |||
| 56 | This works like io_mapping_unmap_atomic, except it is used | ||
| 57 | for pages mapped with io_mapping_map_wc. | ||
| 58 | |||
| 59 | At driver close time, the io_mapping object must be freed: | ||
| 60 | |||
| 61 | void io_mapping_free(struct io_mapping *mapping) | ||
| 62 | |||
| 63 | Current Implementation: | ||
| 64 | |||
| 65 | The initial implementation of these functions uses existing mapping | ||
| 66 | mechanisms and so provides only an abstraction layer and no new | ||
| 67 | functionality. | ||
| 68 | |||
| 69 | On 64-bit processors, io_mapping_create_wc calls ioremap_wc for the whole | ||
| 70 | range, creating a permanent kernel-visible mapping to the resource. The | ||
| 71 | map_atomic and map functions add the requested offset to the base of the | ||
| 72 | virtual address returned by ioremap_wc. | ||
| 73 | |||
| 74 | On 32-bit processors with HIGHMEM defined, io_mapping_map_atomic_wc uses | ||
| 75 | kmap_atomic_pfn to map the specified page in an atomic fashion; | ||
| 76 | kmap_atomic_pfn isn't really supposed to be used with device pages, but it | ||
| 77 | provides an efficient mapping for this usage. | ||
| 78 | |||
| 79 | On 32-bit processors without HIGHMEM defined, io_mapping_map_atomic_wc and | ||
| 80 | io_mapping_map_wc both use ioremap_wc, a terribly inefficient function which | ||
| 81 | performs an IPI to inform all processors about the new mapping. This results | ||
| 82 | in a significant performance penalty. | ||
diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h index 809ff9ab853a..77764301844b 100644 --- a/arch/arm/include/asm/memory.h +++ b/arch/arm/include/asm/memory.h | |||
| @@ -44,10 +44,10 @@ | |||
| 44 | * The module space lives between the addresses given by TASK_SIZE | 44 | * The module space lives between the addresses given by TASK_SIZE |
| 45 | * and PAGE_OFFSET - it must be within 32MB of the kernel text. | 45 | * and PAGE_OFFSET - it must be within 32MB of the kernel text. |
| 46 | */ | 46 | */ |
| 47 | #define MODULE_END (PAGE_OFFSET) | 47 | #define MODULES_END (PAGE_OFFSET) |
| 48 | #define MODULE_START (MODULE_END - 16*1048576) | 48 | #define MODULES_VADDR (MODULES_END - 16*1048576) |
| 49 | 49 | ||
| 50 | #if TASK_SIZE > MODULE_START | 50 | #if TASK_SIZE > MODULES_VADDR |
| 51 | #error Top of user space clashes with start of module space | 51 | #error Top of user space clashes with start of module space |
| 52 | #endif | 52 | #endif |
| 53 | 53 | ||
| @@ -56,7 +56,7 @@ | |||
| 56 | * Since we use sections to map it, this macro replaces the physical address | 56 | * Since we use sections to map it, this macro replaces the physical address |
| 57 | * with its virtual address while keeping offset from the base section. | 57 | * with its virtual address while keeping offset from the base section. |
| 58 | */ | 58 | */ |
| 59 | #define XIP_VIRT_ADDR(physaddr) (MODULE_START + ((physaddr) & 0x000fffff)) | 59 | #define XIP_VIRT_ADDR(physaddr) (MODULES_VADDR + ((physaddr) & 0x000fffff)) |
| 60 | 60 | ||
| 61 | /* | 61 | /* |
| 62 | * Allow 16MB-aligned ioremap pages | 62 | * Allow 16MB-aligned ioremap pages |
| @@ -94,8 +94,8 @@ | |||
| 94 | /* | 94 | /* |
| 95 | * The module can be at any place in ram in nommu mode. | 95 | * The module can be at any place in ram in nommu mode. |
| 96 | */ | 96 | */ |
| 97 | #define MODULE_END (END_MEM) | 97 | #define MODULES_END (END_MEM) |
| 98 | #define MODULE_START (PHYS_OFFSET) | 98 | #define MODULES_VADDR (PHYS_OFFSET) |
| 99 | 99 | ||
| 100 | #endif /* !CONFIG_MMU */ | 100 | #endif /* !CONFIG_MMU */ |
| 101 | 101 | ||
diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 7aad78420f18..568020b34e3e 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h | |||
| @@ -42,6 +42,10 @@ | |||
| 42 | #define CR_U (1 << 22) /* Unaligned access operation */ | 42 | #define CR_U (1 << 22) /* Unaligned access operation */ |
| 43 | #define CR_XP (1 << 23) /* Extended page tables */ | 43 | #define CR_XP (1 << 23) /* Extended page tables */ |
| 44 | #define CR_VE (1 << 24) /* Vectored interrupts */ | 44 | #define CR_VE (1 << 24) /* Vectored interrupts */ |
| 45 | #define CR_EE (1 << 25) /* Exception (Big) Endian */ | ||
| 46 | #define CR_TRE (1 << 28) /* TEX remap enable */ | ||
| 47 | #define CR_AFE (1 << 29) /* Access flag enable */ | ||
| 48 | #define CR_TE (1 << 30) /* Thumb exception enable */ | ||
| 45 | 49 | ||
| 46 | /* | 50 | /* |
| 47 | * This is used to ensure the compiler did actually allocate the register we | 51 | * This is used to ensure the compiler did actually allocate the register we |
diff --git a/arch/arm/kernel/elf.c b/arch/arm/kernel/elf.c index 513f332f040d..84849098c8e8 100644 --- a/arch/arm/kernel/elf.c +++ b/arch/arm/kernel/elf.c | |||
| @@ -21,12 +21,16 @@ int elf_check_arch(const struct elf32_hdr *x) | |||
| 21 | 21 | ||
| 22 | eflags = x->e_flags; | 22 | eflags = x->e_flags; |
| 23 | if ((eflags & EF_ARM_EABI_MASK) == EF_ARM_EABI_UNKNOWN) { | 23 | if ((eflags & EF_ARM_EABI_MASK) == EF_ARM_EABI_UNKNOWN) { |
| 24 | unsigned int flt_fmt; | ||
| 25 | |||
| 24 | /* APCS26 is only allowed if the CPU supports it */ | 26 | /* APCS26 is only allowed if the CPU supports it */ |
| 25 | if ((eflags & EF_ARM_APCS_26) && !(elf_hwcap & HWCAP_26BIT)) | 27 | if ((eflags & EF_ARM_APCS_26) && !(elf_hwcap & HWCAP_26BIT)) |
| 26 | return 0; | 28 | return 0; |
| 27 | 29 | ||
| 30 | flt_fmt = eflags & (EF_ARM_VFP_FLOAT | EF_ARM_SOFT_FLOAT); | ||
| 31 | |||
| 28 | /* VFP requires the supporting code */ | 32 | /* VFP requires the supporting code */ |
| 29 | if ((eflags & EF_ARM_VFP_FLOAT) && !(elf_hwcap & HWCAP_VFP)) | 33 | if (flt_fmt == EF_ARM_VFP_FLOAT && !(elf_hwcap & HWCAP_VFP)) |
| 30 | return 0; | 34 | return 0; |
| 31 | } | 35 | } |
| 32 | return 1; | 36 | return 1; |
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index 9203ba7d58ee..b8d965dcd6fd 100644 --- a/arch/arm/kernel/module.c +++ b/arch/arm/kernel/module.c | |||
| @@ -26,12 +26,12 @@ | |||
| 26 | /* | 26 | /* |
| 27 | * The XIP kernel text is mapped in the module area for modules and | 27 | * The XIP kernel text is mapped in the module area for modules and |
| 28 | * some other stuff to work without any indirect relocations. | 28 | * some other stuff to work without any indirect relocations. |
| 29 | * MODULE_START is redefined here and not in asm/memory.h to avoid | 29 | * MODULES_VADDR is redefined here and not in asm/memory.h to avoid |
| 30 | * recompiling the whole kernel when CONFIG_XIP_KERNEL is turned on/off. | 30 | * recompiling the whole kernel when CONFIG_XIP_KERNEL is turned on/off. |
| 31 | */ | 31 | */ |
| 32 | extern void _etext; | 32 | extern void _etext; |
| 33 | #undef MODULE_START | 33 | #undef MODULES_VADDR |
| 34 | #define MODULE_START (((unsigned long)&_etext + ~PGDIR_MASK) & PGDIR_MASK) | 34 | #define MODULES_VADDR (((unsigned long)&_etext + ~PGDIR_MASK) & PGDIR_MASK) |
| 35 | #endif | 35 | #endif |
| 36 | 36 | ||
| 37 | #ifdef CONFIG_MMU | 37 | #ifdef CONFIG_MMU |
| @@ -43,7 +43,7 @@ void *module_alloc(unsigned long size) | |||
| 43 | if (!size) | 43 | if (!size) |
| 44 | return NULL; | 44 | return NULL; |
| 45 | 45 | ||
| 46 | area = __get_vm_area(size, VM_ALLOC, MODULE_START, MODULE_END); | 46 | area = __get_vm_area(size, VM_ALLOC, MODULES_VADDR, MODULES_END); |
| 47 | if (!area) | 47 | if (!area) |
| 48 | return NULL; | 48 | return NULL; |
| 49 | 49 | ||
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 8ba754064559..e63db11f16a8 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c | |||
| @@ -180,20 +180,20 @@ void adjust_cr(unsigned long mask, unsigned long set) | |||
| 180 | #endif | 180 | #endif |
| 181 | 181 | ||
| 182 | #define PROT_PTE_DEVICE L_PTE_PRESENT|L_PTE_YOUNG|L_PTE_DIRTY|L_PTE_WRITE | 182 | #define PROT_PTE_DEVICE L_PTE_PRESENT|L_PTE_YOUNG|L_PTE_DIRTY|L_PTE_WRITE |
| 183 | #define PROT_SECT_DEVICE PMD_TYPE_SECT|PMD_SECT_XN|PMD_SECT_AP_WRITE | 183 | #define PROT_SECT_DEVICE PMD_TYPE_SECT|PMD_SECT_AP_WRITE |
| 184 | 184 | ||
| 185 | static struct mem_type mem_types[] = { | 185 | static struct mem_type mem_types[] = { |
| 186 | [MT_DEVICE] = { /* Strongly ordered / ARMv6 shared device */ | 186 | [MT_DEVICE] = { /* Strongly ordered / ARMv6 shared device */ |
| 187 | .prot_pte = PROT_PTE_DEVICE | L_PTE_MT_DEV_SHARED | | 187 | .prot_pte = PROT_PTE_DEVICE | L_PTE_MT_DEV_SHARED | |
| 188 | L_PTE_SHARED, | 188 | L_PTE_SHARED, |
| 189 | .prot_l1 = PMD_TYPE_TABLE, | 189 | .prot_l1 = PMD_TYPE_TABLE, |
| 190 | .prot_sect = PROT_SECT_DEVICE | PMD_SECT_UNCACHED, | 190 | .prot_sect = PROT_SECT_DEVICE | PMD_SECT_S, |
| 191 | .domain = DOMAIN_IO, | 191 | .domain = DOMAIN_IO, |
| 192 | }, | 192 | }, |
| 193 | [MT_DEVICE_NONSHARED] = { /* ARMv6 non-shared device */ | 193 | [MT_DEVICE_NONSHARED] = { /* ARMv6 non-shared device */ |
| 194 | .prot_pte = PROT_PTE_DEVICE | L_PTE_MT_DEV_NONSHARED, | 194 | .prot_pte = PROT_PTE_DEVICE | L_PTE_MT_DEV_NONSHARED, |
| 195 | .prot_l1 = PMD_TYPE_TABLE, | 195 | .prot_l1 = PMD_TYPE_TABLE, |
| 196 | .prot_sect = PROT_SECT_DEVICE | PMD_SECT_TEX(2), | 196 | .prot_sect = PROT_SECT_DEVICE, |
| 197 | .domain = DOMAIN_IO, | 197 | .domain = DOMAIN_IO, |
| 198 | }, | 198 | }, |
| 199 | [MT_DEVICE_CACHED] = { /* ioremap_cached */ | 199 | [MT_DEVICE_CACHED] = { /* ioremap_cached */ |
| @@ -205,7 +205,7 @@ static struct mem_type mem_types[] = { | |||
| 205 | [MT_DEVICE_WC] = { /* ioremap_wc */ | 205 | [MT_DEVICE_WC] = { /* ioremap_wc */ |
| 206 | .prot_pte = PROT_PTE_DEVICE | L_PTE_MT_DEV_WC, | 206 | .prot_pte = PROT_PTE_DEVICE | L_PTE_MT_DEV_WC, |
| 207 | .prot_l1 = PMD_TYPE_TABLE, | 207 | .prot_l1 = PMD_TYPE_TABLE, |
| 208 | .prot_sect = PROT_SECT_DEVICE | PMD_SECT_BUFFERABLE, | 208 | .prot_sect = PROT_SECT_DEVICE, |
| 209 | .domain = DOMAIN_IO, | 209 | .domain = DOMAIN_IO, |
| 210 | }, | 210 | }, |
| 211 | [MT_CACHECLEAN] = { | 211 | [MT_CACHECLEAN] = { |
| @@ -273,22 +273,23 @@ static void __init build_mem_type_table(void) | |||
| 273 | #endif | 273 | #endif |
| 274 | 274 | ||
| 275 | /* | 275 | /* |
| 276 | * On non-Xscale3 ARMv5-and-older systems, use CB=01 | 276 | * Strip out features not present on earlier architectures. |
| 277 | * (Uncached/Buffered) for ioremap_wc() mappings. On XScale3 | 277 | * Pre-ARMv5 CPUs don't have TEX bits. Pre-ARMv6 CPUs or those |
| 278 | * and ARMv6+, use TEXCB=00100 mappings (Inner/Outer Uncacheable | 278 | * without extended page tables don't have the 'Shared' bit. |
| 279 | * in xsc3 parlance, Uncached Normal in ARMv6 parlance). | ||
| 280 | */ | 279 | */ |
| 281 | if (cpu_is_xsc3() || cpu_arch >= CPU_ARCH_ARMv6) { | 280 | if (cpu_arch < CPU_ARCH_ARMv5) |
| 282 | mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_TEX(1); | 281 | for (i = 0; i < ARRAY_SIZE(mem_types); i++) |
| 283 | mem_types[MT_DEVICE_WC].prot_sect &= ~PMD_SECT_BUFFERABLE; | 282 | mem_types[i].prot_sect &= ~PMD_SECT_TEX(7); |
| 284 | } | 283 | if ((cpu_arch < CPU_ARCH_ARMv6 || !(cr & CR_XP)) && !cpu_is_xsc3()) |
| 284 | for (i = 0; i < ARRAY_SIZE(mem_types); i++) | ||
| 285 | mem_types[i].prot_sect &= ~PMD_SECT_S; | ||
| 285 | 286 | ||
| 286 | /* | 287 | /* |
| 287 | * ARMv5 and lower, bit 4 must be set for page tables. | 288 | * ARMv5 and lower, bit 4 must be set for page tables (was: cache |
| 288 | * (was: cache "update-able on write" bit on ARM610) | 289 | * "update-able on write" bit on ARM610). However, Xscale and |
| 289 | * However, Xscale cores require this bit to be cleared. | 290 | * Xscale3 require this bit to be cleared. |
| 290 | */ | 291 | */ |
| 291 | if (cpu_is_xscale()) { | 292 | if (cpu_is_xscale() || cpu_is_xsc3()) { |
| 292 | for (i = 0; i < ARRAY_SIZE(mem_types); i++) { | 293 | for (i = 0; i < ARRAY_SIZE(mem_types); i++) { |
| 293 | mem_types[i].prot_sect &= ~PMD_BIT4; | 294 | mem_types[i].prot_sect &= ~PMD_BIT4; |
| 294 | mem_types[i].prot_l1 &= ~PMD_BIT4; | 295 | mem_types[i].prot_l1 &= ~PMD_BIT4; |
| @@ -302,6 +303,64 @@ static void __init build_mem_type_table(void) | |||
| 302 | } | 303 | } |
| 303 | } | 304 | } |
| 304 | 305 | ||
| 306 | /* | ||
| 307 | * Mark the device areas according to the CPU/architecture. | ||
| 308 | */ | ||
| 309 | if (cpu_is_xsc3() || (cpu_arch >= CPU_ARCH_ARMv6 && (cr & CR_XP))) { | ||
| 310 | if (!cpu_is_xsc3()) { | ||
| 311 | /* | ||
| 312 | * Mark device regions on ARMv6+ as execute-never | ||
| 313 | * to prevent speculative instruction fetches. | ||
| 314 | */ | ||
| 315 | mem_types[MT_DEVICE].prot_sect |= PMD_SECT_XN; | ||
| 316 | mem_types[MT_DEVICE_NONSHARED].prot_sect |= PMD_SECT_XN; | ||
| 317 | mem_types[MT_DEVICE_CACHED].prot_sect |= PMD_SECT_XN; | ||
| 318 | mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_XN; | ||
| 319 | } | ||
| 320 | if (cpu_arch >= CPU_ARCH_ARMv7 && (cr & CR_TRE)) { | ||
| 321 | /* | ||
| 322 | * For ARMv7 with TEX remapping, | ||
| 323 | * - shared device is SXCB=1100 | ||
| 324 | * - nonshared device is SXCB=0100 | ||
| 325 | * - write combine device mem is SXCB=0001 | ||
| 326 | * (Uncached Normal memory) | ||
| 327 | */ | ||
| 328 | mem_types[MT_DEVICE].prot_sect |= PMD_SECT_TEX(1); | ||
| 329 | mem_types[MT_DEVICE_NONSHARED].prot_sect |= PMD_SECT_TEX(1); | ||
| 330 | mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_BUFFERABLE; | ||
| 331 | } else if (cpu_is_xsc3()) { | ||
| 332 | /* | ||
| 333 | * For Xscale3, | ||
| 334 | * - shared device is TEXCB=00101 | ||
| 335 | * - nonshared device is TEXCB=01000 | ||
| 336 | * - write combine device mem is TEXCB=00100 | ||
| 337 | * (Inner/Outer Uncacheable in xsc3 parlance) | ||
| 338 | */ | ||
| 339 | mem_types[MT_DEVICE].prot_sect |= PMD_SECT_TEX(1) | PMD_SECT_BUFFERED; | ||
| 340 | mem_types[MT_DEVICE_NONSHARED].prot_sect |= PMD_SECT_TEX(2); | ||
| 341 | mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_TEX(1); | ||
| 342 | } else { | ||
| 343 | /* | ||
| 344 | * For ARMv6 and ARMv7 without TEX remapping, | ||
| 345 | * - shared device is TEXCB=00001 | ||
| 346 | * - nonshared device is TEXCB=01000 | ||
| 347 | * - write combine device mem is TEXCB=00100 | ||
| 348 | * (Uncached Normal in ARMv6 parlance). | ||
| 349 | */ | ||
| 350 | mem_types[MT_DEVICE].prot_sect |= PMD_SECT_BUFFERED; | ||
| 351 | mem_types[MT_DEVICE_NONSHARED].prot_sect |= PMD_SECT_TEX(2); | ||
| 352 | mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_TEX(1); | ||
| 353 | } | ||
| 354 | } else { | ||
| 355 | /* | ||
| 356 | * On others, write combining is "Uncached/Buffered" | ||
| 357 | */ | ||
| 358 | mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_BUFFERABLE; | ||
| 359 | } | ||
| 360 | |||
| 361 | /* | ||
| 362 | * Now deal with the memory-type mappings | ||
| 363 | */ | ||
| 305 | cp = &cache_policies[cachepolicy]; | 364 | cp = &cache_policies[cachepolicy]; |
| 306 | vecs_pgprot = kern_pgprot = user_pgprot = cp->pte; | 365 | vecs_pgprot = kern_pgprot = user_pgprot = cp->pte; |
| 307 | 366 | ||
| @@ -317,12 +376,8 @@ static void __init build_mem_type_table(void) | |||
| 317 | * Enable CPU-specific coherency if supported. | 376 | * Enable CPU-specific coherency if supported. |
| 318 | * (Only available on XSC3 at the moment.) | 377 | * (Only available on XSC3 at the moment.) |
| 319 | */ | 378 | */ |
| 320 | if (arch_is_coherent()) { | 379 | if (arch_is_coherent() && cpu_is_xsc3()) |
| 321 | if (cpu_is_xsc3()) { | 380 | mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S; |
| 322 | mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S; | ||
| 323 | mem_types[MT_MEMORY].prot_pte |= L_PTE_SHARED; | ||
| 324 | } | ||
| 325 | } | ||
| 326 | 381 | ||
| 327 | /* | 382 | /* |
| 328 | * ARMv6 and above have extended page tables. | 383 | * ARMv6 and above have extended page tables. |
| @@ -336,11 +391,6 @@ static void __init build_mem_type_table(void) | |||
| 336 | mem_types[MT_MINICLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE; | 391 | mem_types[MT_MINICLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE; |
| 337 | mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE; | 392 | mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE; |
| 338 | 393 | ||
| 339 | /* | ||
| 340 | * Mark the device area as "shared device" | ||
| 341 | */ | ||
| 342 | mem_types[MT_DEVICE].prot_sect |= PMD_SECT_BUFFERED; | ||
| 343 | |||
| 344 | #ifdef CONFIG_SMP | 394 | #ifdef CONFIG_SMP |
| 345 | /* | 395 | /* |
| 346 | * Mark memory with the "shared" attribute for SMP systems | 396 | * Mark memory with the "shared" attribute for SMP systems |
| @@ -360,9 +410,6 @@ static void __init build_mem_type_table(void) | |||
| 360 | mem_types[MT_LOW_VECTORS].prot_pte |= vecs_pgprot; | 410 | mem_types[MT_LOW_VECTORS].prot_pte |= vecs_pgprot; |
| 361 | mem_types[MT_HIGH_VECTORS].prot_pte |= vecs_pgprot; | 411 | mem_types[MT_HIGH_VECTORS].prot_pte |= vecs_pgprot; |
| 362 | 412 | ||
| 363 | if (cpu_arch < CPU_ARCH_ARMv5) | ||
| 364 | mem_types[MT_MINICLEAN].prot_sect &= ~PMD_SECT_TEX(1); | ||
| 365 | |||
| 366 | pgprot_user = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | user_pgprot); | 413 | pgprot_user = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | user_pgprot); |
| 367 | pgprot_kernel = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | | 414 | pgprot_kernel = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | |
| 368 | L_PTE_DIRTY | L_PTE_WRITE | | 415 | L_PTE_DIRTY | L_PTE_WRITE | |
| @@ -654,7 +701,7 @@ static inline void prepare_page_table(struct meminfo *mi) | |||
| 654 | /* | 701 | /* |
| 655 | * Clear out all the mappings below the kernel image. | 702 | * Clear out all the mappings below the kernel image. |
| 656 | */ | 703 | */ |
| 657 | for (addr = 0; addr < MODULE_START; addr += PGDIR_SIZE) | 704 | for (addr = 0; addr < MODULES_VADDR; addr += PGDIR_SIZE) |
| 658 | pmd_clear(pmd_off_k(addr)); | 705 | pmd_clear(pmd_off_k(addr)); |
| 659 | 706 | ||
| 660 | #ifdef CONFIG_XIP_KERNEL | 707 | #ifdef CONFIG_XIP_KERNEL |
| @@ -766,7 +813,7 @@ static void __init devicemaps_init(struct machine_desc *mdesc) | |||
| 766 | */ | 813 | */ |
| 767 | #ifdef CONFIG_XIP_KERNEL | 814 | #ifdef CONFIG_XIP_KERNEL |
| 768 | map.pfn = __phys_to_pfn(CONFIG_XIP_PHYS_ADDR & SECTION_MASK); | 815 | map.pfn = __phys_to_pfn(CONFIG_XIP_PHYS_ADDR & SECTION_MASK); |
| 769 | map.virtual = MODULE_START; | 816 | map.virtual = MODULES_VADDR; |
| 770 | map.length = ((unsigned long)&_etext - map.virtual + ~SECTION_MASK) & SECTION_MASK; | 817 | map.length = ((unsigned long)&_etext - map.virtual + ~SECTION_MASK) & SECTION_MASK; |
| 771 | map.type = MT_ROM; | 818 | map.type = MT_ROM; |
| 772 | create_mapping(&map); | 819 | create_mapping(&map); |
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index 07f82db70945..4d3c0a73e7fb 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S | |||
| @@ -115,7 +115,7 @@ ENTRY(cpu_v7_set_pte_ext) | |||
| 115 | orr r3, r3, r2 | 115 | orr r3, r3, r2 |
| 116 | orr r3, r3, #PTE_EXT_AP0 | 2 | 116 | orr r3, r3, #PTE_EXT_AP0 | 2 |
| 117 | 117 | ||
| 118 | tst r2, #1 << 4 | 118 | tst r1, #1 << 4 |
| 119 | orrne r3, r3, #PTE_EXT_TEX(1) | 119 | orrne r3, r3, #PTE_EXT_TEX(1) |
| 120 | 120 | ||
| 121 | tst r1, #L_PTE_WRITE | 121 | tst r1, #L_PTE_WRITE |
| @@ -192,11 +192,11 @@ __v7_setup: | |||
| 192 | mov pc, lr @ return to head.S:__ret | 192 | mov pc, lr @ return to head.S:__ret |
| 193 | ENDPROC(__v7_setup) | 193 | ENDPROC(__v7_setup) |
| 194 | 194 | ||
| 195 | /* | 195 | /* AT |
| 196 | * V X F I D LR | 196 | * TFR EV X F I D LR |
| 197 | * .... ...E PUI. .T.T 4RVI ZFRS BLDP WCAM | 197 | * .EEE ..EE PUI. .T.T 4RVI ZFRS BLDP WCAM |
| 198 | * rrrr rrrx xxx0 0101 xxxx xxxx x111 xxxx < forced | 198 | * rxxx rrxx xxx0 0101 xxxx xxxx x111 xxxx < forced |
| 199 | * 0 110 0011 1.00 .111 1101 < we want | 199 | * 1 0 110 0011 1.00 .111 1101 < we want |
| 200 | */ | 200 | */ |
| 201 | .type v7_crval, #object | 201 | .type v7_crval, #object |
| 202 | v7_crval: | 202 | v7_crval: |
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 6f20718d3156..e60c59b81bdd 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
| @@ -1894,6 +1894,10 @@ config SYSVIPC_COMPAT | |||
| 1894 | endmenu | 1894 | endmenu |
| 1895 | 1895 | ||
| 1896 | 1896 | ||
| 1897 | config HAVE_ATOMIC_IOMAP | ||
| 1898 | def_bool y | ||
| 1899 | depends on X86_32 | ||
| 1900 | |||
| 1897 | source "net/Kconfig" | 1901 | source "net/Kconfig" |
| 1898 | 1902 | ||
| 1899 | source "drivers/Kconfig" | 1903 | source "drivers/Kconfig" |
diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h index 8668a94f850e..23696d44a0af 100644 --- a/arch/x86/include/asm/fixmap.h +++ b/arch/x86/include/asm/fixmap.h | |||
| @@ -9,6 +9,10 @@ | |||
| 9 | 9 | ||
| 10 | extern int fixmaps_set; | 10 | extern int fixmaps_set; |
| 11 | 11 | ||
| 12 | extern pte_t *kmap_pte; | ||
| 13 | extern pgprot_t kmap_prot; | ||
| 14 | extern pte_t *pkmap_page_table; | ||
| 15 | |||
| 12 | void __native_set_fixmap(enum fixed_addresses idx, pte_t pte); | 16 | void __native_set_fixmap(enum fixed_addresses idx, pte_t pte); |
| 13 | void native_set_fixmap(enum fixed_addresses idx, | 17 | void native_set_fixmap(enum fixed_addresses idx, |
| 14 | unsigned long phys, pgprot_t flags); | 18 | unsigned long phys, pgprot_t flags); |
diff --git a/arch/x86/include/asm/fixmap_32.h b/arch/x86/include/asm/fixmap_32.h index 09f29ab5c139..c7115c1d7217 100644 --- a/arch/x86/include/asm/fixmap_32.h +++ b/arch/x86/include/asm/fixmap_32.h | |||
| @@ -28,10 +28,8 @@ extern unsigned long __FIXADDR_TOP; | |||
| 28 | #include <asm/acpi.h> | 28 | #include <asm/acpi.h> |
| 29 | #include <asm/apicdef.h> | 29 | #include <asm/apicdef.h> |
| 30 | #include <asm/page.h> | 30 | #include <asm/page.h> |
| 31 | #ifdef CONFIG_HIGHMEM | ||
| 32 | #include <linux/threads.h> | 31 | #include <linux/threads.h> |
| 33 | #include <asm/kmap_types.h> | 32 | #include <asm/kmap_types.h> |
| 34 | #endif | ||
| 35 | 33 | ||
| 36 | /* | 34 | /* |
| 37 | * Here we define all the compile-time 'special' virtual | 35 | * Here we define all the compile-time 'special' virtual |
| @@ -75,10 +73,8 @@ enum fixed_addresses { | |||
| 75 | #ifdef CONFIG_X86_CYCLONE_TIMER | 73 | #ifdef CONFIG_X86_CYCLONE_TIMER |
| 76 | FIX_CYCLONE_TIMER, /*cyclone timer register*/ | 74 | FIX_CYCLONE_TIMER, /*cyclone timer register*/ |
| 77 | #endif | 75 | #endif |
| 78 | #ifdef CONFIG_HIGHMEM | ||
| 79 | FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */ | 76 | FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */ |
| 80 | FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1, | 77 | FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1, |
| 81 | #endif | ||
| 82 | #ifdef CONFIG_PCI_MMCONFIG | 78 | #ifdef CONFIG_PCI_MMCONFIG |
| 83 | FIX_PCIE_MCFG, | 79 | FIX_PCIE_MCFG, |
| 84 | #endif | 80 | #endif |
diff --git a/arch/x86/include/asm/highmem.h b/arch/x86/include/asm/highmem.h index a3b3b7c3027b..bf9276bea660 100644 --- a/arch/x86/include/asm/highmem.h +++ b/arch/x86/include/asm/highmem.h | |||
| @@ -25,14 +25,11 @@ | |||
| 25 | #include <asm/kmap_types.h> | 25 | #include <asm/kmap_types.h> |
| 26 | #include <asm/tlbflush.h> | 26 | #include <asm/tlbflush.h> |
| 27 | #include <asm/paravirt.h> | 27 | #include <asm/paravirt.h> |
| 28 | #include <asm/fixmap.h> | ||
| 28 | 29 | ||
| 29 | /* declarations for highmem.c */ | 30 | /* declarations for highmem.c */ |
| 30 | extern unsigned long highstart_pfn, highend_pfn; | 31 | extern unsigned long highstart_pfn, highend_pfn; |
| 31 | 32 | ||
| 32 | extern pte_t *kmap_pte; | ||
| 33 | extern pgprot_t kmap_prot; | ||
| 34 | extern pte_t *pkmap_page_table; | ||
| 35 | |||
| 36 | /* | 33 | /* |
| 37 | * Right now we initialize only a single pte table. It can be extended | 34 | * Right now we initialize only a single pte table. It can be extended |
| 38 | * easily, subsequent pte tables have to be allocated in one physical | 35 | * easily, subsequent pte tables have to be allocated in one physical |
diff --git a/arch/x86/mm/Makefile b/arch/x86/mm/Makefile index 59f89b434b45..fea4565ff576 100644 --- a/arch/x86/mm/Makefile +++ b/arch/x86/mm/Makefile | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | obj-y := init_$(BITS).o fault.o ioremap.o extable.o pageattr.o mmap.o \ | 1 | obj-y := init_$(BITS).o fault.o ioremap.o extable.o pageattr.o mmap.o \ |
| 2 | pat.o pgtable.o gup.o | 2 | pat.o pgtable.o gup.o |
| 3 | 3 | ||
| 4 | obj-$(CONFIG_X86_32) += pgtable_32.o | 4 | obj-$(CONFIG_X86_32) += pgtable_32.o iomap_32.o |
| 5 | 5 | ||
| 6 | obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o | 6 | obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o |
| 7 | obj-$(CONFIG_X86_PTDUMP) += dump_pagetables.o | 7 | obj-$(CONFIG_X86_PTDUMP) += dump_pagetables.o |
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index 8396868e82c5..c483f4242079 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c | |||
| @@ -334,7 +334,6 @@ int devmem_is_allowed(unsigned long pagenr) | |||
| 334 | return 0; | 334 | return 0; |
| 335 | } | 335 | } |
| 336 | 336 | ||
| 337 | #ifdef CONFIG_HIGHMEM | ||
| 338 | pte_t *kmap_pte; | 337 | pte_t *kmap_pte; |
| 339 | pgprot_t kmap_prot; | 338 | pgprot_t kmap_prot; |
| 340 | 339 | ||
| @@ -357,6 +356,7 @@ static void __init kmap_init(void) | |||
| 357 | kmap_prot = PAGE_KERNEL; | 356 | kmap_prot = PAGE_KERNEL; |
| 358 | } | 357 | } |
| 359 | 358 | ||
| 359 | #ifdef CONFIG_HIGHMEM | ||
| 360 | static void __init permanent_kmaps_init(pgd_t *pgd_base) | 360 | static void __init permanent_kmaps_init(pgd_t *pgd_base) |
| 361 | { | 361 | { |
| 362 | unsigned long vaddr; | 362 | unsigned long vaddr; |
| @@ -436,7 +436,6 @@ static void __init set_highmem_pages_init(void) | |||
| 436 | #endif /* !CONFIG_NUMA */ | 436 | #endif /* !CONFIG_NUMA */ |
| 437 | 437 | ||
| 438 | #else | 438 | #else |
| 439 | # define kmap_init() do { } while (0) | ||
| 440 | # define permanent_kmaps_init(pgd_base) do { } while (0) | 439 | # define permanent_kmaps_init(pgd_base) do { } while (0) |
| 441 | # define set_highmem_pages_init() do { } while (0) | 440 | # define set_highmem_pages_init() do { } while (0) |
| 442 | #endif /* CONFIG_HIGHMEM */ | 441 | #endif /* CONFIG_HIGHMEM */ |
diff --git a/arch/x86/mm/iomap_32.c b/arch/x86/mm/iomap_32.c new file mode 100644 index 000000000000..d0151d8ce452 --- /dev/null +++ b/arch/x86/mm/iomap_32.c | |||
| @@ -0,0 +1,59 @@ | |||
| 1 | /* | ||
| 2 | * Copyright © 2008 Ingo Molnar | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License as published by | ||
| 6 | * the Free Software Foundation; either version 2 of the License, or | ||
| 7 | * (at your option) any later version. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope that it will be useful, but | ||
| 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 12 | * General Public License for more details. | ||
| 13 | * | ||
| 14 | * You should have received a copy of the GNU General Public License along | ||
| 15 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 16 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. | ||
| 17 | */ | ||
| 18 | |||
| 19 | #include <asm/iomap.h> | ||
| 20 | #include <linux/module.h> | ||
| 21 | |||
| 22 | /* Map 'pfn' using fixed map 'type' and protections 'prot' | ||
| 23 | */ | ||
| 24 | void * | ||
| 25 | iomap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot) | ||
| 26 | { | ||
| 27 | enum fixed_addresses idx; | ||
| 28 | unsigned long vaddr; | ||
| 29 | |||
| 30 | pagefault_disable(); | ||
| 31 | |||
| 32 | idx = type + KM_TYPE_NR*smp_processor_id(); | ||
| 33 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); | ||
| 34 | set_pte(kmap_pte-idx, pfn_pte(pfn, prot)); | ||
| 35 | arch_flush_lazy_mmu_mode(); | ||
| 36 | |||
| 37 | return (void*) vaddr; | ||
| 38 | } | ||
| 39 | EXPORT_SYMBOL_GPL(iomap_atomic_prot_pfn); | ||
| 40 | |||
| 41 | void | ||
| 42 | iounmap_atomic(void *kvaddr, enum km_type type) | ||
| 43 | { | ||
| 44 | unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; | ||
| 45 | enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id(); | ||
| 46 | |||
| 47 | /* | ||
| 48 | * Force other mappings to Oops if they'll try to access this pte | ||
| 49 | * without first remap it. Keeping stale mappings around is a bad idea | ||
| 50 | * also, in case the page changes cacheability attributes or becomes | ||
| 51 | * a protected page in a hypervisor. | ||
| 52 | */ | ||
| 53 | if (vaddr == __fix_to_virt(FIX_KMAP_BEGIN+idx)) | ||
| 54 | kpte_clear_flush(kmap_pte-idx, vaddr); | ||
| 55 | |||
| 56 | arch_flush_lazy_mmu_mode(); | ||
| 57 | pagefault_enable(); | ||
| 58 | } | ||
| 59 | EXPORT_SYMBOL_GPL(iounmap_atomic); | ||
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 5ba78e4fd2b5..d8fb5d8ee7ea 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile | |||
| @@ -3,13 +3,14 @@ | |||
| 3 | # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. | 3 | # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. |
| 4 | 4 | ||
| 5 | ccflags-y := -Iinclude/drm | 5 | ccflags-y := -Iinclude/drm |
| 6 | i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o i915_opregion.o \ | 6 | i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \ |
| 7 | i915_suspend.o \ | 7 | i915_suspend.o \ |
| 8 | i915_gem.o \ | 8 | i915_gem.o \ |
| 9 | i915_gem_debug.o \ | 9 | i915_gem_debug.o \ |
| 10 | i915_gem_proc.o \ | 10 | i915_gem_proc.o \ |
| 11 | i915_gem_tiling.o | 11 | i915_gem_tiling.o |
| 12 | 12 | ||
| 13 | i915-$(CONFIG_ACPI) += i915_opregion.o | ||
| 13 | i915-$(CONFIG_COMPAT) += i915_ioc32.o | 14 | i915-$(CONFIG_COMPAT) += i915_ioc32.o |
| 14 | 15 | ||
| 15 | obj-$(CONFIG_DRM_I915) += i915.o | 16 | obj-$(CONFIG_DRM_I915) += i915.o |
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 01de536e0211..256e22963ae4 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c | |||
| @@ -960,6 +960,7 @@ struct drm_ioctl_desc i915_ioctls[] = { | |||
| 960 | DRM_IOCTL_DEF(DRM_I915_GEM_SW_FINISH, i915_gem_sw_finish_ioctl, 0), | 960 | DRM_IOCTL_DEF(DRM_I915_GEM_SW_FINISH, i915_gem_sw_finish_ioctl, 0), |
| 961 | DRM_IOCTL_DEF(DRM_I915_GEM_SET_TILING, i915_gem_set_tiling, 0), | 961 | DRM_IOCTL_DEF(DRM_I915_GEM_SET_TILING, i915_gem_set_tiling, 0), |
| 962 | DRM_IOCTL_DEF(DRM_I915_GEM_GET_TILING, i915_gem_get_tiling, 0), | 962 | DRM_IOCTL_DEF(DRM_I915_GEM_GET_TILING, i915_gem_get_tiling, 0), |
| 963 | DRM_IOCTL_DEF(DRM_I915_GEM_GET_APERTURE, i915_gem_get_aperture_ioctl, 0), | ||
| 963 | }; | 964 | }; |
| 964 | 965 | ||
| 965 | int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); | 966 | int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); |
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f20ffe17df71..572dcd0e3e0d 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #define _I915_DRV_H_ | 31 | #define _I915_DRV_H_ |
| 32 | 32 | ||
| 33 | #include "i915_reg.h" | 33 | #include "i915_reg.h" |
| 34 | #include <linux/io-mapping.h> | ||
| 34 | 35 | ||
| 35 | /* General customization: | 36 | /* General customization: |
| 36 | */ | 37 | */ |
| @@ -246,6 +247,8 @@ typedef struct drm_i915_private { | |||
| 246 | struct { | 247 | struct { |
| 247 | struct drm_mm gtt_space; | 248 | struct drm_mm gtt_space; |
| 248 | 249 | ||
| 250 | struct io_mapping *gtt_mapping; | ||
| 251 | |||
| 249 | /** | 252 | /** |
| 250 | * List of objects currently involved in rendering from the | 253 | * List of objects currently involved in rendering from the |
| 251 | * ringbuffer. | 254 | * ringbuffer. |
| @@ -502,6 +505,8 @@ int i915_gem_set_tiling(struct drm_device *dev, void *data, | |||
| 502 | struct drm_file *file_priv); | 505 | struct drm_file *file_priv); |
| 503 | int i915_gem_get_tiling(struct drm_device *dev, void *data, | 506 | int i915_gem_get_tiling(struct drm_device *dev, void *data, |
| 504 | struct drm_file *file_priv); | 507 | struct drm_file *file_priv); |
| 508 | int i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, | ||
| 509 | struct drm_file *file_priv); | ||
| 505 | void i915_gem_load(struct drm_device *dev); | 510 | void i915_gem_load(struct drm_device *dev); |
| 506 | int i915_gem_proc_init(struct drm_minor *minor); | 511 | int i915_gem_proc_init(struct drm_minor *minor); |
| 507 | void i915_gem_proc_cleanup(struct drm_minor *minor); | 512 | void i915_gem_proc_cleanup(struct drm_minor *minor); |
| @@ -539,11 +544,18 @@ extern int i915_restore_state(struct drm_device *dev); | |||
| 539 | extern int i915_save_state(struct drm_device *dev); | 544 | extern int i915_save_state(struct drm_device *dev); |
| 540 | extern int i915_restore_state(struct drm_device *dev); | 545 | extern int i915_restore_state(struct drm_device *dev); |
| 541 | 546 | ||
| 547 | #ifdef CONFIG_ACPI | ||
| 542 | /* i915_opregion.c */ | 548 | /* i915_opregion.c */ |
| 543 | extern int intel_opregion_init(struct drm_device *dev); | 549 | extern int intel_opregion_init(struct drm_device *dev); |
| 544 | extern void intel_opregion_free(struct drm_device *dev); | 550 | extern void intel_opregion_free(struct drm_device *dev); |
| 545 | extern void opregion_asle_intr(struct drm_device *dev); | 551 | extern void opregion_asle_intr(struct drm_device *dev); |
| 546 | extern void opregion_enable_asle(struct drm_device *dev); | 552 | extern void opregion_enable_asle(struct drm_device *dev); |
| 553 | #else | ||
| 554 | static inline int intel_opregion_init(struct drm_device *dev) { return 0; } | ||
| 555 | static inline void intel_opregion_free(struct drm_device *dev) { return; } | ||
| 556 | static inline void opregion_asle_intr(struct drm_device *dev) { return; } | ||
| 557 | static inline void opregion_enable_asle(struct drm_device *dev) { return; } | ||
| 558 | #endif | ||
| 547 | 559 | ||
| 548 | /** | 560 | /** |
| 549 | * Lock test for when it's just for synchronization of ring access. | 561 | * Lock test for when it's just for synchronization of ring access. |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 17ae330ff269..b0ec73fa6a93 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
| @@ -79,6 +79,28 @@ i915_gem_init_ioctl(struct drm_device *dev, void *data, | |||
| 79 | return 0; | 79 | return 0; |
| 80 | } | 80 | } |
| 81 | 81 | ||
| 82 | int | ||
| 83 | i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, | ||
| 84 | struct drm_file *file_priv) | ||
| 85 | { | ||
| 86 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
| 87 | struct drm_i915_gem_get_aperture *args = data; | ||
| 88 | struct drm_i915_gem_object *obj_priv; | ||
| 89 | |||
| 90 | if (!(dev->driver->driver_features & DRIVER_GEM)) | ||
| 91 | return -ENODEV; | ||
| 92 | |||
| 93 | args->aper_size = dev->gtt_total; | ||
| 94 | args->aper_available_size = args->aper_size; | ||
| 95 | |||
| 96 | list_for_each_entry(obj_priv, &dev_priv->mm.active_list, list) { | ||
| 97 | if (obj_priv->pin_count > 0) | ||
| 98 | args->aper_available_size -= obj_priv->obj->size; | ||
| 99 | } | ||
| 100 | |||
| 101 | return 0; | ||
| 102 | } | ||
| 103 | |||
| 82 | 104 | ||
| 83 | /** | 105 | /** |
| 84 | * Creates a new mm object and returns a handle to it. | 106 | * Creates a new mm object and returns a handle to it. |
| @@ -171,35 +193,50 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data, | |||
| 171 | return 0; | 193 | return 0; |
| 172 | } | 194 | } |
| 173 | 195 | ||
| 174 | /* | 196 | /* This is the fast write path which cannot handle |
| 175 | * Try to write quickly with an atomic kmap. Return true on success. | 197 | * page faults in the source data |
| 176 | * | ||
| 177 | * If this fails (which includes a partial write), we'll redo the whole | ||
| 178 | * thing with the slow version. | ||
| 179 | * | ||
| 180 | * This is a workaround for the low performance of iounmap (approximate | ||
| 181 | * 10% cpu cost on normal 3D workloads). kmap_atomic on HIGHMEM kernels | ||
| 182 | * happens to let us map card memory without taking IPIs. When the vmap | ||
| 183 | * rework lands we should be able to dump this hack. | ||
| 184 | */ | 198 | */ |
| 185 | static inline int fast_user_write(unsigned long pfn, char __user *user_data, | 199 | |
| 186 | int l, int o) | 200 | static inline int |
| 201 | fast_user_write(struct io_mapping *mapping, | ||
| 202 | loff_t page_base, int page_offset, | ||
| 203 | char __user *user_data, | ||
| 204 | int length) | ||
| 187 | { | 205 | { |
| 188 | #ifdef CONFIG_HIGHMEM | ||
| 189 | unsigned long unwritten; | ||
| 190 | char *vaddr_atomic; | 206 | char *vaddr_atomic; |
| 207 | unsigned long unwritten; | ||
| 191 | 208 | ||
| 192 | vaddr_atomic = kmap_atomic_pfn(pfn, KM_USER0); | 209 | vaddr_atomic = io_mapping_map_atomic_wc(mapping, page_base); |
| 193 | #if WATCH_PWRITE | 210 | unwritten = __copy_from_user_inatomic_nocache(vaddr_atomic + page_offset, |
| 194 | DRM_INFO("pwrite i %d o %d l %d pfn %ld vaddr %p\n", | 211 | user_data, length); |
| 195 | i, o, l, pfn, vaddr_atomic); | 212 | io_mapping_unmap_atomic(vaddr_atomic); |
| 196 | #endif | 213 | if (unwritten) |
| 197 | unwritten = __copy_from_user_inatomic_nocache(vaddr_atomic + o, user_data, l); | 214 | return -EFAULT; |
| 198 | kunmap_atomic(vaddr_atomic, KM_USER0); | 215 | return 0; |
| 199 | return !unwritten; | 216 | } |
| 200 | #else | 217 | |
| 218 | /* Here's the write path which can sleep for | ||
| 219 | * page faults | ||
| 220 | */ | ||
| 221 | |||
| 222 | static inline int | ||
| 223 | slow_user_write(struct io_mapping *mapping, | ||
| 224 | loff_t page_base, int page_offset, | ||
| 225 | char __user *user_data, | ||
| 226 | int length) | ||
| 227 | { | ||
| 228 | char __iomem *vaddr; | ||
| 229 | unsigned long unwritten; | ||
| 230 | |||
| 231 | vaddr = io_mapping_map_wc(mapping, page_base); | ||
| 232 | if (vaddr == NULL) | ||
| 233 | return -EFAULT; | ||
| 234 | unwritten = __copy_from_user(vaddr + page_offset, | ||
| 235 | user_data, length); | ||
| 236 | io_mapping_unmap(vaddr); | ||
| 237 | if (unwritten) | ||
| 238 | return -EFAULT; | ||
| 201 | return 0; | 239 | return 0; |
| 202 | #endif | ||
| 203 | } | 240 | } |
| 204 | 241 | ||
| 205 | static int | 242 | static int |
| @@ -208,10 +245,12 @@ i915_gem_gtt_pwrite(struct drm_device *dev, struct drm_gem_object *obj, | |||
| 208 | struct drm_file *file_priv) | 245 | struct drm_file *file_priv) |
| 209 | { | 246 | { |
| 210 | struct drm_i915_gem_object *obj_priv = obj->driver_private; | 247 | struct drm_i915_gem_object *obj_priv = obj->driver_private; |
| 248 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
| 211 | ssize_t remain; | 249 | ssize_t remain; |
| 212 | loff_t offset; | 250 | loff_t offset, page_base; |
| 213 | char __user *user_data; | 251 | char __user *user_data; |
| 214 | int ret = 0; | 252 | int page_offset, page_length; |
| 253 | int ret; | ||
| 215 | 254 | ||
| 216 | user_data = (char __user *) (uintptr_t) args->data_ptr; | 255 | user_data = (char __user *) (uintptr_t) args->data_ptr; |
| 217 | remain = args->size; | 256 | remain = args->size; |
| @@ -235,57 +274,37 @@ i915_gem_gtt_pwrite(struct drm_device *dev, struct drm_gem_object *obj, | |||
| 235 | obj_priv->dirty = 1; | 274 | obj_priv->dirty = 1; |
| 236 | 275 | ||
| 237 | while (remain > 0) { | 276 | while (remain > 0) { |
| 238 | unsigned long pfn; | ||
| 239 | int i, o, l; | ||
| 240 | |||
| 241 | /* Operation in this page | 277 | /* Operation in this page |
| 242 | * | 278 | * |
| 243 | * i = page number | 279 | * page_base = page offset within aperture |
| 244 | * o = offset within page | 280 | * page_offset = offset within page |
| 245 | * l = bytes to copy | 281 | * page_length = bytes to copy for this page |
| 246 | */ | 282 | */ |
| 247 | i = offset >> PAGE_SHIFT; | 283 | page_base = (offset & ~(PAGE_SIZE-1)); |
| 248 | o = offset & (PAGE_SIZE-1); | 284 | page_offset = offset & (PAGE_SIZE-1); |
| 249 | l = remain; | 285 | page_length = remain; |
| 250 | if ((o + l) > PAGE_SIZE) | 286 | if ((page_offset + remain) > PAGE_SIZE) |
| 251 | l = PAGE_SIZE - o; | 287 | page_length = PAGE_SIZE - page_offset; |
| 252 | 288 | ||
| 253 | pfn = (dev->agp->base >> PAGE_SHIFT) + i; | 289 | ret = fast_user_write (dev_priv->mm.gtt_mapping, page_base, |
| 254 | 290 | page_offset, user_data, page_length); | |
| 255 | if (!fast_user_write(pfn, user_data, l, o)) { | 291 | |
| 256 | unsigned long unwritten; | 292 | /* If we get a fault while copying data, then (presumably) our |
| 257 | char __iomem *vaddr; | 293 | * source page isn't available. In this case, use the |
| 258 | 294 | * non-atomic function | |
| 259 | vaddr = ioremap_wc(pfn << PAGE_SHIFT, PAGE_SIZE); | 295 | */ |
| 260 | #if WATCH_PWRITE | 296 | if (ret) { |
| 261 | DRM_INFO("pwrite slow i %d o %d l %d " | 297 | ret = slow_user_write (dev_priv->mm.gtt_mapping, |
| 262 | "pfn %ld vaddr %p\n", | 298 | page_base, page_offset, |
| 263 | i, o, l, pfn, vaddr); | 299 | user_data, page_length); |
| 264 | #endif | 300 | if (ret) |
| 265 | if (vaddr == NULL) { | ||
| 266 | ret = -EFAULT; | ||
| 267 | goto fail; | ||
| 268 | } | ||
| 269 | unwritten = __copy_from_user(vaddr + o, user_data, l); | ||
| 270 | #if WATCH_PWRITE | ||
| 271 | DRM_INFO("unwritten %ld\n", unwritten); | ||
| 272 | #endif | ||
| 273 | iounmap(vaddr); | ||
| 274 | if (unwritten) { | ||
| 275 | ret = -EFAULT; | ||
| 276 | goto fail; | 301 | goto fail; |
| 277 | } | ||
| 278 | } | 302 | } |
| 279 | 303 | ||
| 280 | remain -= l; | 304 | remain -= page_length; |
| 281 | user_data += l; | 305 | user_data += page_length; |
| 282 | offset += l; | 306 | offset += page_length; |
| 283 | } | 307 | } |
| 284 | #if WATCH_PWRITE && 1 | ||
| 285 | i915_gem_clflush_object(obj); | ||
| 286 | i915_gem_dump_object(obj, args->offset + args->size, __func__, ~0); | ||
| 287 | i915_gem_clflush_object(obj); | ||
| 288 | #endif | ||
| 289 | 308 | ||
| 290 | fail: | 309 | fail: |
| 291 | i915_gem_object_unpin(obj); | 310 | i915_gem_object_unpin(obj); |
| @@ -1503,12 +1522,12 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, | |||
| 1503 | struct drm_i915_gem_exec_object *entry) | 1522 | struct drm_i915_gem_exec_object *entry) |
| 1504 | { | 1523 | { |
| 1505 | struct drm_device *dev = obj->dev; | 1524 | struct drm_device *dev = obj->dev; |
| 1525 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
| 1506 | struct drm_i915_gem_relocation_entry reloc; | 1526 | struct drm_i915_gem_relocation_entry reloc; |
| 1507 | struct drm_i915_gem_relocation_entry __user *relocs; | 1527 | struct drm_i915_gem_relocation_entry __user *relocs; |
| 1508 | struct drm_i915_gem_object *obj_priv = obj->driver_private; | 1528 | struct drm_i915_gem_object *obj_priv = obj->driver_private; |
| 1509 | int i, ret; | 1529 | int i, ret; |
| 1510 | uint32_t last_reloc_offset = -1; | 1530 | void __iomem *reloc_page; |
| 1511 | void __iomem *reloc_page = NULL; | ||
| 1512 | 1531 | ||
| 1513 | /* Choose the GTT offset for our buffer and put it there. */ | 1532 | /* Choose the GTT offset for our buffer and put it there. */ |
| 1514 | ret = i915_gem_object_pin(obj, (uint32_t) entry->alignment); | 1533 | ret = i915_gem_object_pin(obj, (uint32_t) entry->alignment); |
| @@ -1631,26 +1650,11 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, | |||
| 1631 | * perform. | 1650 | * perform. |
| 1632 | */ | 1651 | */ |
| 1633 | reloc_offset = obj_priv->gtt_offset + reloc.offset; | 1652 | reloc_offset = obj_priv->gtt_offset + reloc.offset; |
| 1634 | if (reloc_page == NULL || | 1653 | reloc_page = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping, |
| 1635 | (last_reloc_offset & ~(PAGE_SIZE - 1)) != | 1654 | (reloc_offset & |
| 1636 | (reloc_offset & ~(PAGE_SIZE - 1))) { | 1655 | ~(PAGE_SIZE - 1))); |
| 1637 | if (reloc_page != NULL) | ||
| 1638 | iounmap(reloc_page); | ||
| 1639 | |||
| 1640 | reloc_page = ioremap_wc(dev->agp->base + | ||
| 1641 | (reloc_offset & | ||
| 1642 | ~(PAGE_SIZE - 1)), | ||
| 1643 | PAGE_SIZE); | ||
| 1644 | last_reloc_offset = reloc_offset; | ||
| 1645 | if (reloc_page == NULL) { | ||
| 1646 | drm_gem_object_unreference(target_obj); | ||
| 1647 | i915_gem_object_unpin(obj); | ||
| 1648 | return -ENOMEM; | ||
| 1649 | } | ||
| 1650 | } | ||
| 1651 | |||
| 1652 | reloc_entry = (uint32_t __iomem *)(reloc_page + | 1656 | reloc_entry = (uint32_t __iomem *)(reloc_page + |
| 1653 | (reloc_offset & (PAGE_SIZE - 1))); | 1657 | (reloc_offset & (PAGE_SIZE - 1))); |
| 1654 | reloc_val = target_obj_priv->gtt_offset + reloc.delta; | 1658 | reloc_val = target_obj_priv->gtt_offset + reloc.delta; |
| 1655 | 1659 | ||
| 1656 | #if WATCH_BUF | 1660 | #if WATCH_BUF |
| @@ -1659,6 +1663,7 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, | |||
| 1659 | readl(reloc_entry), reloc_val); | 1663 | readl(reloc_entry), reloc_val); |
| 1660 | #endif | 1664 | #endif |
| 1661 | writel(reloc_val, reloc_entry); | 1665 | writel(reloc_val, reloc_entry); |
| 1666 | io_mapping_unmap_atomic(reloc_page); | ||
| 1662 | 1667 | ||
| 1663 | /* Write the updated presumed offset for this entry back out | 1668 | /* Write the updated presumed offset for this entry back out |
| 1664 | * to the user. | 1669 | * to the user. |
| @@ -1674,9 +1679,6 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, | |||
| 1674 | drm_gem_object_unreference(target_obj); | 1679 | drm_gem_object_unreference(target_obj); |
| 1675 | } | 1680 | } |
| 1676 | 1681 | ||
| 1677 | if (reloc_page != NULL) | ||
| 1678 | iounmap(reloc_page); | ||
| 1679 | |||
| 1680 | #if WATCH_BUF | 1682 | #if WATCH_BUF |
| 1681 | if (0) | 1683 | if (0) |
| 1682 | i915_gem_dump_object(obj, 128, __func__, ~0); | 1684 | i915_gem_dump_object(obj, 128, __func__, ~0); |
| @@ -2518,6 +2520,10 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data, | |||
| 2518 | if (ret != 0) | 2520 | if (ret != 0) |
| 2519 | return ret; | 2521 | return ret; |
| 2520 | 2522 | ||
| 2523 | dev_priv->mm.gtt_mapping = io_mapping_create_wc(dev->agp->base, | ||
| 2524 | dev->agp->agp_info.aper_size | ||
| 2525 | * 1024 * 1024); | ||
| 2526 | |||
| 2521 | mutex_lock(&dev->struct_mutex); | 2527 | mutex_lock(&dev->struct_mutex); |
| 2522 | BUG_ON(!list_empty(&dev_priv->mm.active_list)); | 2528 | BUG_ON(!list_empty(&dev_priv->mm.active_list)); |
| 2523 | BUG_ON(!list_empty(&dev_priv->mm.flushing_list)); | 2529 | BUG_ON(!list_empty(&dev_priv->mm.flushing_list)); |
| @@ -2535,11 +2541,13 @@ int | |||
| 2535 | i915_gem_leavevt_ioctl(struct drm_device *dev, void *data, | 2541 | i915_gem_leavevt_ioctl(struct drm_device *dev, void *data, |
| 2536 | struct drm_file *file_priv) | 2542 | struct drm_file *file_priv) |
| 2537 | { | 2543 | { |
| 2544 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
| 2538 | int ret; | 2545 | int ret; |
| 2539 | 2546 | ||
| 2540 | ret = i915_gem_idle(dev); | 2547 | ret = i915_gem_idle(dev); |
| 2541 | drm_irq_uninstall(dev); | 2548 | drm_irq_uninstall(dev); |
| 2542 | 2549 | ||
| 2550 | io_mapping_free(dev_priv->mm.gtt_mapping); | ||
| 2543 | return ret; | 2551 | return ret; |
| 2544 | } | 2552 | } |
| 2545 | 2553 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c index 59a2132a8f57..073894824e6b 100644 --- a/drivers/gpu/drm/radeon/radeon_cp.c +++ b/drivers/gpu/drm/radeon/radeon_cp.c | |||
| @@ -653,15 +653,16 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev, | |||
| 653 | RADEON_WRITE(RADEON_SCRATCH_UMSK, 0x7); | 653 | RADEON_WRITE(RADEON_SCRATCH_UMSK, 0x7); |
| 654 | 654 | ||
| 655 | /* Turn on bus mastering */ | 655 | /* Turn on bus mastering */ |
| 656 | if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS400) || | 656 | if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) || |
| 657 | ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) || | ||
| 658 | ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) { | 657 | ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) { |
| 659 | /* rs400, rs690/rs740 */ | 658 | /* rs600/rs690/rs740 */ |
| 660 | tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RS400_BUS_MASTER_DIS; | 659 | tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RS600_BUS_MASTER_DIS; |
| 661 | RADEON_WRITE(RADEON_BUS_CNTL, tmp); | 660 | RADEON_WRITE(RADEON_BUS_CNTL, tmp); |
| 662 | } else if (!(((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV380) || | 661 | } else if (((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV350) || |
| 663 | ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R423))) { | 662 | ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) || |
| 664 | /* r1xx, r2xx, r300, r(v)350, r420/r481, rs480 */ | 663 | ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS400) || |
| 664 | ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS480)) { | ||
| 665 | /* r1xx, r2xx, r300, r(v)350, r420/r481, rs400/rs480 */ | ||
| 665 | tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; | 666 | tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; |
| 666 | RADEON_WRITE(RADEON_BUS_CNTL, tmp); | 667 | RADEON_WRITE(RADEON_BUS_CNTL, tmp); |
| 667 | } /* PCIE cards appears to not need this */ | 668 | } /* PCIE cards appears to not need this */ |
diff --git a/drivers/gpu/drm/radeon/radeon_drv.h b/drivers/gpu/drm/radeon/radeon_drv.h index 4dbb813910c3..02f5575ba395 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.h +++ b/drivers/gpu/drm/radeon/radeon_drv.h | |||
| @@ -447,12 +447,12 @@ extern int r300_do_cp_cmdbuf(struct drm_device *dev, | |||
| 447 | * handling, not bus mastering itself. | 447 | * handling, not bus mastering itself. |
| 448 | */ | 448 | */ |
| 449 | #define RADEON_BUS_CNTL 0x0030 | 449 | #define RADEON_BUS_CNTL 0x0030 |
| 450 | /* r1xx, r2xx, r300, r(v)350, r420/r481, rs480 */ | 450 | /* r1xx, r2xx, r300, r(v)350, r420/r481, rs400/rs480 */ |
| 451 | # define RADEON_BUS_MASTER_DIS (1 << 6) | 451 | # define RADEON_BUS_MASTER_DIS (1 << 6) |
| 452 | /* rs400, rs690/rs740 */ | 452 | /* rs600/rs690/rs740 */ |
| 453 | # define RS400_BUS_MASTER_DIS (1 << 14) | 453 | # define RS600_BUS_MASTER_DIS (1 << 14) |
| 454 | # define RS400_MSI_REARM (1 << 20) | 454 | # define RS600_MSI_REARM (1 << 20) |
| 455 | /* see RS480_MSI_REARM in AIC_CNTL for rs480 */ | 455 | /* see RS400_MSI_REARM in AIC_CNTL for rs480 */ |
| 456 | 456 | ||
| 457 | #define RADEON_BUS_CNTL1 0x0034 | 457 | #define RADEON_BUS_CNTL1 0x0034 |
| 458 | # define RADEON_PMI_BM_DIS (1 << 2) | 458 | # define RADEON_PMI_BM_DIS (1 << 2) |
| @@ -937,7 +937,7 @@ extern int r300_do_cp_cmdbuf(struct drm_device *dev, | |||
| 937 | 937 | ||
| 938 | #define RADEON_AIC_CNTL 0x01d0 | 938 | #define RADEON_AIC_CNTL 0x01d0 |
| 939 | # define RADEON_PCIGART_TRANSLATE_EN (1 << 0) | 939 | # define RADEON_PCIGART_TRANSLATE_EN (1 << 0) |
| 940 | # define RS480_MSI_REARM (1 << 3) | 940 | # define RS400_MSI_REARM (1 << 3) |
| 941 | #define RADEON_AIC_STAT 0x01d4 | 941 | #define RADEON_AIC_STAT 0x01d4 |
| 942 | #define RADEON_AIC_PT_BASE 0x01d8 | 942 | #define RADEON_AIC_PT_BASE 0x01d8 |
| 943 | #define RADEON_AIC_LO_ADDR 0x01dc | 943 | #define RADEON_AIC_LO_ADDR 0x01dc |
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 8f528ea24c48..8855331b2fba 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES | |||
| @@ -4,7 +4,11 @@ Various fixes to make delete of open files behavior more predictable | |||
| 4 | (when delete of an open file fails we mark the file as "delete-on-close" | 4 | (when delete of an open file fails we mark the file as "delete-on-close" |
| 5 | in a way that more servers accept, but only if we can first rename the | 5 | in a way that more servers accept, but only if we can first rename the |
| 6 | file to a temporary name). Add experimental support for more safely | 6 | file to a temporary name). Add experimental support for more safely |
| 7 | handling fcntl(F_SETLEASE). | 7 | handling fcntl(F_SETLEASE). Convert cifs to using blocking tcp |
| 8 | sends, and also let tcp autotune the socket send and receive buffers. | ||
| 9 | This reduces the number of EAGAIN errors returned by TCP/IP in | ||
| 10 | high stress workloads (and the number of retries on socket writes | ||
| 11 | when sending large SMBWriteX requests). | ||
| 8 | 12 | ||
| 9 | Version 1.54 | 13 | Version 1.54 |
| 10 | ------------ | 14 | ------------ |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index c791e5b5a914..1cb1189f24e0 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
| @@ -141,6 +141,8 @@ struct TCP_Server_Info { | |||
| 141 | char versionMajor; | 141 | char versionMajor; |
| 142 | char versionMinor; | 142 | char versionMinor; |
| 143 | bool svlocal:1; /* local server or remote */ | 143 | bool svlocal:1; /* local server or remote */ |
| 144 | bool noblocksnd; /* use blocking sendmsg */ | ||
| 145 | bool noautotune; /* do not autotune send buf sizes */ | ||
| 144 | atomic_t socketUseCount; /* number of open cifs sessions on socket */ | 146 | atomic_t socketUseCount; /* number of open cifs sessions on socket */ |
| 145 | atomic_t inFlight; /* number of requests on the wire to server */ | 147 | atomic_t inFlight; /* number of requests on the wire to server */ |
| 146 | #ifdef CONFIG_CIFS_STATS2 | 148 | #ifdef CONFIG_CIFS_STATS2 |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 0cff7fe986e8..6f21ecb85ce5 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
| @@ -36,7 +36,7 @@ extern void cifs_buf_release(void *); | |||
| 36 | extern struct smb_hdr *cifs_small_buf_get(void); | 36 | extern struct smb_hdr *cifs_small_buf_get(void); |
| 37 | extern void cifs_small_buf_release(void *); | 37 | extern void cifs_small_buf_release(void *); |
| 38 | extern int smb_send(struct socket *, struct smb_hdr *, | 38 | extern int smb_send(struct socket *, struct smb_hdr *, |
| 39 | unsigned int /* length */ , struct sockaddr *); | 39 | unsigned int /* length */ , struct sockaddr *, bool); |
| 40 | extern unsigned int _GetXid(void); | 40 | extern unsigned int _GetXid(void); |
| 41 | extern void _FreeXid(unsigned int); | 41 | extern void _FreeXid(unsigned int); |
| 42 | #define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__func__, xid,current->fsuid)); | 42 | #define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__func__, xid,current->fsuid)); |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 843a85fb8b9a..d5eac48fc415 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
| @@ -1536,7 +1536,7 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, | |||
| 1536 | __u32 bytes_sent; | 1536 | __u32 bytes_sent; |
| 1537 | __u16 byte_count; | 1537 | __u16 byte_count; |
| 1538 | 1538 | ||
| 1539 | /* cFYI(1,("write at %lld %d bytes",offset,count));*/ | 1539 | /* cFYI(1, ("write at %lld %d bytes", offset, count));*/ |
| 1540 | if (tcon->ses == NULL) | 1540 | if (tcon->ses == NULL) |
| 1541 | return -ECONNABORTED; | 1541 | return -ECONNABORTED; |
| 1542 | 1542 | ||
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 71b7661e2260..e9f9248cb3fe 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
| @@ -92,6 +92,8 @@ struct smb_vol { | |||
| 92 | bool seal:1; /* request transport encryption on share */ | 92 | bool seal:1; /* request transport encryption on share */ |
| 93 | bool nodfs:1; /* Do not request DFS, even if available */ | 93 | bool nodfs:1; /* Do not request DFS, even if available */ |
| 94 | bool local_lease:1; /* check leases only on local system, not remote */ | 94 | bool local_lease:1; /* check leases only on local system, not remote */ |
| 95 | bool noblocksnd:1; | ||
| 96 | bool noautotune:1; | ||
| 95 | unsigned int rsize; | 97 | unsigned int rsize; |
| 96 | unsigned int wsize; | 98 | unsigned int wsize; |
| 97 | unsigned int sockopt; | 99 | unsigned int sockopt; |
| @@ -102,9 +104,11 @@ struct smb_vol { | |||
| 102 | static int ipv4_connect(struct sockaddr_in *psin_server, | 104 | static int ipv4_connect(struct sockaddr_in *psin_server, |
| 103 | struct socket **csocket, | 105 | struct socket **csocket, |
| 104 | char *netb_name, | 106 | char *netb_name, |
| 105 | char *server_netb_name); | 107 | char *server_netb_name, |
| 108 | bool noblocksnd, | ||
| 109 | bool nosndbuf); /* ipv6 never set sndbuf size */ | ||
| 106 | static int ipv6_connect(struct sockaddr_in6 *psin_server, | 110 | static int ipv6_connect(struct sockaddr_in6 *psin_server, |
| 107 | struct socket **csocket); | 111 | struct socket **csocket, bool noblocksnd); |
| 108 | 112 | ||
| 109 | 113 | ||
| 110 | /* | 114 | /* |
| @@ -191,12 +195,13 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
| 191 | try_to_freeze(); | 195 | try_to_freeze(); |
| 192 | if (server->protocolType == IPV6) { | 196 | if (server->protocolType == IPV6) { |
| 193 | rc = ipv6_connect(&server->addr.sockAddr6, | 197 | rc = ipv6_connect(&server->addr.sockAddr6, |
| 194 | &server->ssocket); | 198 | &server->ssocket, server->noautotune); |
| 195 | } else { | 199 | } else { |
| 196 | rc = ipv4_connect(&server->addr.sockAddr, | 200 | rc = ipv4_connect(&server->addr.sockAddr, |
| 197 | &server->ssocket, | 201 | &server->ssocket, |
| 198 | server->workstation_RFC1001_name, | 202 | server->workstation_RFC1001_name, |
| 199 | server->server_RFC1001_name); | 203 | server->server_RFC1001_name, |
| 204 | server->noblocksnd, server->noautotune); | ||
| 200 | } | 205 | } |
| 201 | if (rc) { | 206 | if (rc) { |
| 202 | cFYI(1, ("reconnect error %d", rc)); | 207 | cFYI(1, ("reconnect error %d", rc)); |
| @@ -1192,6 +1197,10 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
| 1192 | /* ignore */ | 1197 | /* ignore */ |
| 1193 | } else if (strnicmp(data, "rw", 2) == 0) { | 1198 | } else if (strnicmp(data, "rw", 2) == 0) { |
| 1194 | vol->rw = true; | 1199 | vol->rw = true; |
| 1200 | } else if (strnicmp(data, "noblocksend", 11) == 0) { | ||
| 1201 | vol->noblocksnd = 1; | ||
| 1202 | } else if (strnicmp(data, "noautotune", 10) == 0) { | ||
| 1203 | vol->noautotune = 1; | ||
| 1195 | } else if ((strnicmp(data, "suid", 4) == 0) || | 1204 | } else if ((strnicmp(data, "suid", 4) == 0) || |
| 1196 | (strnicmp(data, "nosuid", 6) == 0) || | 1205 | (strnicmp(data, "nosuid", 6) == 0) || |
| 1197 | (strnicmp(data, "exec", 4) == 0) || | 1206 | (strnicmp(data, "exec", 4) == 0) || |
| @@ -1518,7 +1527,8 @@ static void rfc1002mangle(char *target, char *source, unsigned int length) | |||
| 1518 | 1527 | ||
| 1519 | static int | 1528 | static int |
| 1520 | ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, | 1529 | ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, |
| 1521 | char *netbios_name, char *target_name) | 1530 | char *netbios_name, char *target_name, |
| 1531 | bool noblocksnd, bool noautotune) | ||
| 1522 | { | 1532 | { |
| 1523 | int rc = 0; | 1533 | int rc = 0; |
| 1524 | int connected = 0; | 1534 | int connected = 0; |
| @@ -1590,11 +1600,16 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, | |||
| 1590 | (*csocket)->sk->sk_sndbuf, | 1600 | (*csocket)->sk->sk_sndbuf, |
| 1591 | (*csocket)->sk->sk_rcvbuf, (*csocket)->sk->sk_rcvtimeo)); | 1601 | (*csocket)->sk->sk_rcvbuf, (*csocket)->sk->sk_rcvtimeo)); |
| 1592 | (*csocket)->sk->sk_rcvtimeo = 7 * HZ; | 1602 | (*csocket)->sk->sk_rcvtimeo = 7 * HZ; |
| 1603 | if (!noblocksnd) | ||
| 1604 | (*csocket)->sk->sk_sndtimeo = 3 * HZ; | ||
| 1605 | |||
| 1593 | /* make the bufsizes depend on wsize/rsize and max requests */ | 1606 | /* make the bufsizes depend on wsize/rsize and max requests */ |
| 1594 | if ((*csocket)->sk->sk_sndbuf < (200 * 1024)) | 1607 | if (noautotune) { |
| 1595 | (*csocket)->sk->sk_sndbuf = 200 * 1024; | 1608 | if ((*csocket)->sk->sk_sndbuf < (200 * 1024)) |
| 1596 | if ((*csocket)->sk->sk_rcvbuf < (140 * 1024)) | 1609 | (*csocket)->sk->sk_sndbuf = 200 * 1024; |
| 1597 | (*csocket)->sk->sk_rcvbuf = 140 * 1024; | 1610 | if ((*csocket)->sk->sk_rcvbuf < (140 * 1024)) |
| 1611 | (*csocket)->sk->sk_rcvbuf = 140 * 1024; | ||
| 1612 | } | ||
| 1598 | 1613 | ||
| 1599 | /* send RFC1001 sessinit */ | 1614 | /* send RFC1001 sessinit */ |
| 1600 | if (psin_server->sin_port == htons(RFC1001_PORT)) { | 1615 | if (psin_server->sin_port == htons(RFC1001_PORT)) { |
| @@ -1631,7 +1646,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, | |||
| 1631 | /* sizeof RFC1002_SESSION_REQUEST with no scope */ | 1646 | /* sizeof RFC1002_SESSION_REQUEST with no scope */ |
| 1632 | smb_buf->smb_buf_length = 0x81000044; | 1647 | smb_buf->smb_buf_length = 0x81000044; |
| 1633 | rc = smb_send(*csocket, smb_buf, 0x44, | 1648 | rc = smb_send(*csocket, smb_buf, 0x44, |
| 1634 | (struct sockaddr *)psin_server); | 1649 | (struct sockaddr *)psin_server, noblocksnd); |
| 1635 | kfree(ses_init_buf); | 1650 | kfree(ses_init_buf); |
| 1636 | msleep(1); /* RFC1001 layer in at least one server | 1651 | msleep(1); /* RFC1001 layer in at least one server |
| 1637 | requires very short break before negprot | 1652 | requires very short break before negprot |
| @@ -1651,7 +1666,8 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, | |||
| 1651 | } | 1666 | } |
| 1652 | 1667 | ||
| 1653 | static int | 1668 | static int |
| 1654 | ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket) | 1669 | ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket, |
| 1670 | bool noblocksnd) | ||
| 1655 | { | 1671 | { |
| 1656 | int rc = 0; | 1672 | int rc = 0; |
| 1657 | int connected = 0; | 1673 | int connected = 0; |
| @@ -1720,6 +1736,9 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket) | |||
| 1720 | the default. sock_setsockopt not used because it expects | 1736 | the default. sock_setsockopt not used because it expects |
| 1721 | user space buffer */ | 1737 | user space buffer */ |
| 1722 | (*csocket)->sk->sk_rcvtimeo = 7 * HZ; | 1738 | (*csocket)->sk->sk_rcvtimeo = 7 * HZ; |
| 1739 | if (!noblocksnd) | ||
| 1740 | (*csocket)->sk->sk_sndtimeo = 3 * HZ; | ||
| 1741 | |||
| 1723 | 1742 | ||
| 1724 | return rc; | 1743 | return rc; |
| 1725 | } | 1744 | } |
| @@ -1983,11 +2002,14 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
| 1983 | cFYI(1, ("attempting ipv6 connect")); | 2002 | cFYI(1, ("attempting ipv6 connect")); |
| 1984 | /* BB should we allow ipv6 on port 139? */ | 2003 | /* BB should we allow ipv6 on port 139? */ |
| 1985 | /* other OS never observed in Wild doing 139 with v6 */ | 2004 | /* other OS never observed in Wild doing 139 with v6 */ |
| 1986 | rc = ipv6_connect(&sin_server6, &csocket); | 2005 | rc = ipv6_connect(&sin_server6, &csocket, |
| 2006 | volume_info.noblocksnd); | ||
| 1987 | } else | 2007 | } else |
| 1988 | rc = ipv4_connect(&sin_server, &csocket, | 2008 | rc = ipv4_connect(&sin_server, &csocket, |
| 1989 | volume_info.source_rfc1001_name, | 2009 | volume_info.source_rfc1001_name, |
| 1990 | volume_info.target_rfc1001_name); | 2010 | volume_info.target_rfc1001_name, |
| 2011 | volume_info.noblocksnd, | ||
| 2012 | volume_info.noautotune); | ||
| 1991 | if (rc < 0) { | 2013 | if (rc < 0) { |
| 1992 | cERROR(1, ("Error connecting to IPv4 socket. " | 2014 | cERROR(1, ("Error connecting to IPv4 socket. " |
| 1993 | "Aborting operation")); | 2015 | "Aborting operation")); |
| @@ -2002,6 +2024,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
| 2002 | sock_release(csocket); | 2024 | sock_release(csocket); |
| 2003 | goto out; | 2025 | goto out; |
| 2004 | } else { | 2026 | } else { |
| 2027 | srvTcp->noblocksnd = volume_info.noblocksnd; | ||
| 2028 | srvTcp->noautotune = volume_info.noautotune; | ||
| 2005 | memcpy(&srvTcp->addr.sockAddr, &sin_server, | 2029 | memcpy(&srvTcp->addr.sockAddr, &sin_server, |
| 2006 | sizeof(struct sockaddr_in)); | 2030 | sizeof(struct sockaddr_in)); |
| 2007 | atomic_set(&srvTcp->inFlight, 0); | 2031 | atomic_set(&srvTcp->inFlight, 0); |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 62d8bd8f14c0..ead1a3bb0256 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
| @@ -1824,7 +1824,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, | |||
| 1824 | pTcon = cifs_sb->tcon; | 1824 | pTcon = cifs_sb->tcon; |
| 1825 | 1825 | ||
| 1826 | pagevec_init(&lru_pvec, 0); | 1826 | pagevec_init(&lru_pvec, 0); |
| 1827 | cFYI(DBG2, ("rpages: num pages %d", num_pages)); | 1827 | cFYI(DBG2, ("rpages: num pages %d", num_pages)); |
| 1828 | for (i = 0; i < num_pages; ) { | 1828 | for (i = 0; i < num_pages; ) { |
| 1829 | unsigned contig_pages; | 1829 | unsigned contig_pages; |
| 1830 | struct page *tmp_page; | 1830 | struct page *tmp_page; |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index d54fa8aeaea9..ff8c68de4a92 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
| @@ -1361,9 +1361,11 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry, | |||
| 1361 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1361 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
| 1362 | 1362 | ||
| 1363 | if (tmprc == 0 && (info_buf_source->UniqueId == | 1363 | if (tmprc == 0 && (info_buf_source->UniqueId == |
| 1364 | info_buf_target->UniqueId)) | 1364 | info_buf_target->UniqueId)) { |
| 1365 | /* same file, POSIX says that this is a noop */ | 1365 | /* same file, POSIX says that this is a noop */ |
| 1366 | rc = 0; | ||
| 1366 | goto cifs_rename_exit; | 1367 | goto cifs_rename_exit; |
| 1368 | } | ||
| 1367 | } /* else ... BB we could add the same check for Windows by | 1369 | } /* else ... BB we could add the same check for Windows by |
| 1368 | checking the UniqueId via FILE_INTERNAL_INFO */ | 1370 | checking the UniqueId via FILE_INTERNAL_INFO */ |
| 1369 | 1371 | ||
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index bf0e6d8e382a..ff8243a8fe3e 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c | |||
| @@ -161,7 +161,7 @@ void DeleteTconOplockQEntries(struct cifsTconInfo *tcon) | |||
| 161 | 161 | ||
| 162 | int | 162 | int |
| 163 | smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer, | 163 | smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer, |
| 164 | unsigned int smb_buf_length, struct sockaddr *sin) | 164 | unsigned int smb_buf_length, struct sockaddr *sin, bool noblocksnd) |
| 165 | { | 165 | { |
| 166 | int rc = 0; | 166 | int rc = 0; |
| 167 | int i = 0; | 167 | int i = 0; |
| @@ -178,7 +178,10 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer, | |||
| 178 | smb_msg.msg_namelen = sizeof(struct sockaddr); | 178 | smb_msg.msg_namelen = sizeof(struct sockaddr); |
| 179 | smb_msg.msg_control = NULL; | 179 | smb_msg.msg_control = NULL; |
| 180 | smb_msg.msg_controllen = 0; | 180 | smb_msg.msg_controllen = 0; |
| 181 | smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/ | 181 | if (noblocksnd) |
| 182 | smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; | ||
| 183 | else | ||
| 184 | smb_msg.msg_flags = MSG_NOSIGNAL; | ||
| 182 | 185 | ||
| 183 | /* smb header is converted in header_assemble. bcc and rest of SMB word | 186 | /* smb header is converted in header_assemble. bcc and rest of SMB word |
| 184 | area, and byte area if necessary, is converted to littleendian in | 187 | area, and byte area if necessary, is converted to littleendian in |
| @@ -229,8 +232,8 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer, | |||
| 229 | } | 232 | } |
| 230 | 233 | ||
| 231 | static int | 234 | static int |
| 232 | smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec, | 235 | smb_send2(struct TCP_Server_Info *server, struct kvec *iov, int n_vec, |
| 233 | struct sockaddr *sin) | 236 | struct sockaddr *sin, bool noblocksnd) |
| 234 | { | 237 | { |
| 235 | int rc = 0; | 238 | int rc = 0; |
| 236 | int i = 0; | 239 | int i = 0; |
| @@ -240,6 +243,7 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec, | |||
| 240 | unsigned int total_len; | 243 | unsigned int total_len; |
| 241 | int first_vec = 0; | 244 | int first_vec = 0; |
| 242 | unsigned int smb_buf_length = smb_buffer->smb_buf_length; | 245 | unsigned int smb_buf_length = smb_buffer->smb_buf_length; |
| 246 | struct socket *ssocket = server->ssocket; | ||
| 243 | 247 | ||
| 244 | if (ssocket == NULL) | 248 | if (ssocket == NULL) |
| 245 | return -ENOTSOCK; /* BB eventually add reconnect code here */ | 249 | return -ENOTSOCK; /* BB eventually add reconnect code here */ |
| @@ -248,7 +252,10 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec, | |||
| 248 | smb_msg.msg_namelen = sizeof(struct sockaddr); | 252 | smb_msg.msg_namelen = sizeof(struct sockaddr); |
| 249 | smb_msg.msg_control = NULL; | 253 | smb_msg.msg_control = NULL; |
| 250 | smb_msg.msg_controllen = 0; | 254 | smb_msg.msg_controllen = 0; |
| 251 | smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/ | 255 | if (noblocksnd) |
| 256 | smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; | ||
| 257 | else | ||
| 258 | smb_msg.msg_flags = MSG_NOSIGNAL; | ||
| 252 | 259 | ||
| 253 | /* smb header is converted in header_assemble. bcc and rest of SMB word | 260 | /* smb header is converted in header_assemble. bcc and rest of SMB word |
| 254 | area, and byte area if necessary, is converted to littleendian in | 261 | area, and byte area if necessary, is converted to littleendian in |
| @@ -283,8 +290,11 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec, | |||
| 283 | if (rc < 0) | 290 | if (rc < 0) |
| 284 | break; | 291 | break; |
| 285 | 292 | ||
| 286 | if (rc >= total_len) { | 293 | if (rc == total_len) { |
| 287 | WARN_ON(rc > total_len); | 294 | total_len = 0; |
| 295 | break; | ||
| 296 | } else if (rc > total_len) { | ||
| 297 | cERROR(1, ("sent %d requested %d", rc, total_len)); | ||
| 288 | break; | 298 | break; |
| 289 | } | 299 | } |
| 290 | if (rc == 0) { | 300 | if (rc == 0) { |
| @@ -312,6 +322,16 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec, | |||
| 312 | i = 0; /* in case we get ENOSPC on the next send */ | 322 | i = 0; /* in case we get ENOSPC on the next send */ |
| 313 | } | 323 | } |
| 314 | 324 | ||
| 325 | if ((total_len > 0) && (total_len != smb_buf_length + 4)) { | ||
| 326 | cFYI(1, ("partial send (%d remaining), terminating session", | ||
| 327 | total_len)); | ||
| 328 | /* If we have only sent part of an SMB then the next SMB | ||
| 329 | could be taken as the remainder of this one. We need | ||
| 330 | to kill the socket so the server throws away the partial | ||
| 331 | SMB */ | ||
| 332 | server->tcpStatus = CifsNeedReconnect; | ||
| 333 | } | ||
| 334 | |||
| 315 | if (rc < 0) { | 335 | if (rc < 0) { |
| 316 | cERROR(1, ("Error %d sending data on socket to server", rc)); | 336 | cERROR(1, ("Error %d sending data on socket to server", rc)); |
| 317 | } else | 337 | } else |
| @@ -518,8 +538,9 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, | |||
| 518 | #ifdef CONFIG_CIFS_STATS2 | 538 | #ifdef CONFIG_CIFS_STATS2 |
| 519 | atomic_inc(&ses->server->inSend); | 539 | atomic_inc(&ses->server->inSend); |
| 520 | #endif | 540 | #endif |
| 521 | rc = smb_send2(ses->server->ssocket, iov, n_vec, | 541 | rc = smb_send2(ses->server, iov, n_vec, |
| 522 | (struct sockaddr *) &(ses->server->addr.sockAddr)); | 542 | (struct sockaddr *) &(ses->server->addr.sockAddr), |
| 543 | ses->server->noblocksnd); | ||
| 523 | #ifdef CONFIG_CIFS_STATS2 | 544 | #ifdef CONFIG_CIFS_STATS2 |
| 524 | atomic_dec(&ses->server->inSend); | 545 | atomic_dec(&ses->server->inSend); |
| 525 | midQ->when_sent = jiffies; | 546 | midQ->when_sent = jiffies; |
| @@ -711,7 +732,8 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, | |||
| 711 | atomic_inc(&ses->server->inSend); | 732 | atomic_inc(&ses->server->inSend); |
| 712 | #endif | 733 | #endif |
| 713 | rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, | 734 | rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, |
| 714 | (struct sockaddr *) &(ses->server->addr.sockAddr)); | 735 | (struct sockaddr *) &(ses->server->addr.sockAddr), |
| 736 | ses->server->noblocksnd); | ||
| 715 | #ifdef CONFIG_CIFS_STATS2 | 737 | #ifdef CONFIG_CIFS_STATS2 |
| 716 | atomic_dec(&ses->server->inSend); | 738 | atomic_dec(&ses->server->inSend); |
| 717 | midQ->when_sent = jiffies; | 739 | midQ->when_sent = jiffies; |
| @@ -851,7 +873,8 @@ send_nt_cancel(struct cifsTconInfo *tcon, struct smb_hdr *in_buf, | |||
| 851 | return rc; | 873 | return rc; |
| 852 | } | 874 | } |
| 853 | rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, | 875 | rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, |
| 854 | (struct sockaddr *) &(ses->server->addr.sockAddr)); | 876 | (struct sockaddr *) &(ses->server->addr.sockAddr), |
| 877 | ses->server->noblocksnd); | ||
| 855 | up(&ses->server->tcpSem); | 878 | up(&ses->server->tcpSem); |
| 856 | return rc; | 879 | return rc; |
| 857 | } | 880 | } |
| @@ -941,7 +964,8 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, | |||
| 941 | atomic_inc(&ses->server->inSend); | 964 | atomic_inc(&ses->server->inSend); |
| 942 | #endif | 965 | #endif |
| 943 | rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, | 966 | rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, |
| 944 | (struct sockaddr *) &(ses->server->addr.sockAddr)); | 967 | (struct sockaddr *) &(ses->server->addr.sockAddr), |
| 968 | ses->server->noblocksnd); | ||
| 945 | #ifdef CONFIG_CIFS_STATS2 | 969 | #ifdef CONFIG_CIFS_STATS2 |
| 946 | atomic_dec(&ses->server->inSend); | 970 | atomic_dec(&ses->server->inSend); |
| 947 | midQ->when_sent = jiffies; | 971 | midQ->when_sent = jiffies; |
diff --git a/fs/proc/uptime.c b/fs/proc/uptime.c index 0c10a0b3f146..df26aa88fa47 100644 --- a/fs/proc/uptime.c +++ b/fs/proc/uptime.c | |||
| @@ -1,43 +1,45 @@ | |||
| 1 | #include <linux/fs.h> | ||
| 2 | #include <linux/init.h> | 1 | #include <linux/init.h> |
| 3 | #include <linux/proc_fs.h> | 2 | #include <linux/proc_fs.h> |
| 4 | #include <linux/sched.h> | 3 | #include <linux/sched.h> |
| 5 | #include <linux/seq_file.h> | ||
| 6 | #include <linux/time.h> | 4 | #include <linux/time.h> |
| 7 | #include <asm/cputime.h> | 5 | #include <asm/cputime.h> |
| 8 | 6 | ||
| 9 | static int uptime_proc_show(struct seq_file *m, void *v) | 7 | static int proc_calc_metrics(char *page, char **start, off_t off, |
| 8 | int count, int *eof, int len) | ||
| 9 | { | ||
| 10 | if (len <= off + count) | ||
| 11 | *eof = 1; | ||
| 12 | *start = page + off; | ||
| 13 | len -= off; | ||
| 14 | if (len > count) | ||
| 15 | len = count; | ||
| 16 | if (len < 0) | ||
| 17 | len = 0; | ||
| 18 | return len; | ||
| 19 | } | ||
| 20 | |||
| 21 | static int uptime_read_proc(char *page, char **start, off_t off, int count, | ||
| 22 | int *eof, void *data) | ||
| 10 | { | 23 | { |
| 11 | struct timespec uptime; | 24 | struct timespec uptime; |
| 12 | struct timespec idle; | 25 | struct timespec idle; |
| 26 | int len; | ||
| 13 | cputime_t idletime = cputime_add(init_task.utime, init_task.stime); | 27 | cputime_t idletime = cputime_add(init_task.utime, init_task.stime); |
| 14 | 28 | ||
| 15 | do_posix_clock_monotonic_gettime(&uptime); | 29 | do_posix_clock_monotonic_gettime(&uptime); |
| 16 | monotonic_to_bootbased(&uptime); | 30 | monotonic_to_bootbased(&uptime); |
| 17 | cputime_to_timespec(idletime, &idle); | 31 | cputime_to_timespec(idletime, &idle); |
| 18 | seq_printf(m, "%lu.%02lu %lu.%02lu\n", | 32 | len = sprintf(page, "%lu.%02lu %lu.%02lu\n", |
| 19 | (unsigned long) uptime.tv_sec, | 33 | (unsigned long) uptime.tv_sec, |
| 20 | (uptime.tv_nsec / (NSEC_PER_SEC / 100)), | 34 | (uptime.tv_nsec / (NSEC_PER_SEC / 100)), |
| 21 | (unsigned long) idle.tv_sec, | 35 | (unsigned long) idle.tv_sec, |
| 22 | (idle.tv_nsec / (NSEC_PER_SEC / 100))); | 36 | (idle.tv_nsec / (NSEC_PER_SEC / 100))); |
| 23 | return 0; | 37 | return proc_calc_metrics(page, start, off, count, eof, len); |
| 24 | } | 38 | } |
| 25 | 39 | ||
| 26 | static int uptime_proc_open(struct inode *inode, struct file *file) | ||
| 27 | { | ||
| 28 | return single_open(file, uptime_proc_show, NULL); | ||
| 29 | } | ||
| 30 | |||
| 31 | static const struct file_operations uptime_proc_fops = { | ||
| 32 | .open = uptime_proc_open, | ||
| 33 | .read = seq_read, | ||
| 34 | .llseek = seq_lseek, | ||
| 35 | .release = single_release, | ||
| 36 | }; | ||
| 37 | |||
| 38 | static int __init proc_uptime_init(void) | 40 | static int __init proc_uptime_init(void) |
| 39 | { | 41 | { |
| 40 | proc_create("uptime", 0, NULL, &uptime_proc_fops); | 42 | create_proc_read_entry("uptime", 0, NULL, uptime_read_proc, NULL); |
| 41 | return 0; | 43 | return 0; |
| 42 | } | 44 | } |
| 43 | module_init(proc_uptime_init); | 45 | module_init(proc_uptime_init); |
diff --git a/include/asm-x86/iomap.h b/include/asm-x86/iomap.h new file mode 100644 index 000000000000..c1f06289b14b --- /dev/null +++ b/include/asm-x86/iomap.h | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | /* | ||
| 2 | * Copyright © 2008 Ingo Molnar | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License as published by | ||
| 6 | * the Free Software Foundation; either version 2 of the License, or | ||
| 7 | * (at your option) any later version. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope that it will be useful, but | ||
| 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 12 | * General Public License for more details. | ||
| 13 | * | ||
| 14 | * You should have received a copy of the GNU General Public License along | ||
| 15 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 16 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. | ||
| 17 | */ | ||
| 18 | |||
| 19 | #include <linux/fs.h> | ||
| 20 | #include <linux/mm.h> | ||
| 21 | #include <linux/uaccess.h> | ||
| 22 | #include <asm/cacheflush.h> | ||
| 23 | #include <asm/pgtable.h> | ||
| 24 | #include <asm/tlbflush.h> | ||
| 25 | |||
| 26 | void * | ||
| 27 | iomap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot); | ||
| 28 | |||
| 29 | void | ||
| 30 | iounmap_atomic(void *kvaddr, enum km_type type); | ||
diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h index eb4b35031a55..152b34da927c 100644 --- a/include/drm/i915_drm.h +++ b/include/drm/i915_drm.h | |||
| @@ -159,6 +159,7 @@ typedef struct _drm_i915_sarea { | |||
| 159 | #define DRM_I915_GEM_SW_FINISH 0x20 | 159 | #define DRM_I915_GEM_SW_FINISH 0x20 |
| 160 | #define DRM_I915_GEM_SET_TILING 0x21 | 160 | #define DRM_I915_GEM_SET_TILING 0x21 |
| 161 | #define DRM_I915_GEM_GET_TILING 0x22 | 161 | #define DRM_I915_GEM_GET_TILING 0x22 |
| 162 | #define DRM_I915_GEM_GET_APERTURE 0x23 | ||
| 162 | 163 | ||
| 163 | #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) | 164 | #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) |
| 164 | #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) | 165 | #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) |
| @@ -190,6 +191,7 @@ typedef struct _drm_i915_sarea { | |||
| 190 | #define DRM_IOCTL_I915_GEM_SW_FINISH DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SW_FINISH, struct drm_i915_gem_sw_finish) | 191 | #define DRM_IOCTL_I915_GEM_SW_FINISH DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SW_FINISH, struct drm_i915_gem_sw_finish) |
| 191 | #define DRM_IOCTL_I915_GEM_SET_TILING DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_SET_TILING, struct drm_i915_gem_set_tiling) | 192 | #define DRM_IOCTL_I915_GEM_SET_TILING DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_SET_TILING, struct drm_i915_gem_set_tiling) |
| 192 | #define DRM_IOCTL_I915_GEM_GET_TILING DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_GET_TILING, struct drm_i915_gem_get_tiling) | 193 | #define DRM_IOCTL_I915_GEM_GET_TILING DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_GET_TILING, struct drm_i915_gem_get_tiling) |
| 194 | #define DRM_IOCTL_I915_GEM_GET_APERTURE DRM_IOR (DRM_COMMAND_BASE + DRM_I915_GEM_GET_APERTURE, struct drm_i915_gem_get_aperture) | ||
| 193 | 195 | ||
| 194 | /* Allow drivers to submit batchbuffers directly to hardware, relying | 196 | /* Allow drivers to submit batchbuffers directly to hardware, relying |
| 195 | * on the security mechanisms provided by hardware. | 197 | * on the security mechanisms provided by hardware. |
| @@ -600,4 +602,15 @@ struct drm_i915_gem_get_tiling { | |||
| 600 | uint32_t swizzle_mode; | 602 | uint32_t swizzle_mode; |
| 601 | }; | 603 | }; |
| 602 | 604 | ||
| 605 | struct drm_i915_gem_get_aperture { | ||
| 606 | /** Total size of the aperture used by i915_gem_execbuffer, in bytes */ | ||
| 607 | uint64_t aper_size; | ||
| 608 | |||
| 609 | /** | ||
| 610 | * Available space in the aperture used by i915_gem_execbuffer, in | ||
| 611 | * bytes | ||
| 612 | */ | ||
| 613 | uint64_t aper_available_size; | ||
| 614 | }; | ||
| 615 | |||
| 603 | #endif /* _I915_DRM_H_ */ | 616 | #endif /* _I915_DRM_H_ */ |
diff --git a/include/linux/io-mapping.h b/include/linux/io-mapping.h new file mode 100644 index 000000000000..82df31726a54 --- /dev/null +++ b/include/linux/io-mapping.h | |||
| @@ -0,0 +1,125 @@ | |||
| 1 | /* | ||
| 2 | * Copyright © 2008 Keith Packard <keithp@keithp.com> | ||
| 3 | * | ||
| 4 | * This file is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of version 2 of the GNU General Public License | ||
| 6 | * as published by the Free Software Foundation. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program; if not, write to the Free Software Foundation, | ||
| 15 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #ifndef _LINUX_IO_MAPPING_H | ||
| 19 | #define _LINUX_IO_MAPPING_H | ||
| 20 | |||
| 21 | #include <linux/types.h> | ||
| 22 | #include <asm/io.h> | ||
| 23 | #include <asm/page.h> | ||
| 24 | #include <asm/iomap.h> | ||
| 25 | |||
| 26 | /* | ||
| 27 | * The io_mapping mechanism provides an abstraction for mapping | ||
| 28 | * individual pages from an io device to the CPU in an efficient fashion. | ||
| 29 | * | ||
| 30 | * See Documentation/io_mapping.txt | ||
| 31 | */ | ||
| 32 | |||
| 33 | /* this struct isn't actually defined anywhere */ | ||
| 34 | struct io_mapping; | ||
| 35 | |||
| 36 | #ifdef CONFIG_HAVE_ATOMIC_IOMAP | ||
| 37 | |||
| 38 | /* | ||
| 39 | * For small address space machines, mapping large objects | ||
| 40 | * into the kernel virtual space isn't practical. Where | ||
| 41 | * available, use fixmap support to dynamically map pages | ||
| 42 | * of the object at run time. | ||
| 43 | */ | ||
| 44 | |||
| 45 | static inline struct io_mapping * | ||
| 46 | io_mapping_create_wc(unsigned long base, unsigned long size) | ||
| 47 | { | ||
| 48 | return (struct io_mapping *) base; | ||
| 49 | } | ||
| 50 | |||
| 51 | static inline void | ||
| 52 | io_mapping_free(struct io_mapping *mapping) | ||
| 53 | { | ||
| 54 | } | ||
| 55 | |||
| 56 | /* Atomic map/unmap */ | ||
| 57 | static inline void * | ||
| 58 | io_mapping_map_atomic_wc(struct io_mapping *mapping, unsigned long offset) | ||
| 59 | { | ||
| 60 | offset += (unsigned long) mapping; | ||
| 61 | return iomap_atomic_prot_pfn(offset >> PAGE_SHIFT, KM_USER0, | ||
| 62 | __pgprot(__PAGE_KERNEL_WC)); | ||
| 63 | } | ||
| 64 | |||
| 65 | static inline void | ||
| 66 | io_mapping_unmap_atomic(void *vaddr) | ||
| 67 | { | ||
| 68 | iounmap_atomic(vaddr, KM_USER0); | ||
| 69 | } | ||
| 70 | |||
| 71 | static inline void * | ||
| 72 | io_mapping_map_wc(struct io_mapping *mapping, unsigned long offset) | ||
| 73 | { | ||
| 74 | offset += (unsigned long) mapping; | ||
| 75 | return ioremap_wc(offset, PAGE_SIZE); | ||
| 76 | } | ||
| 77 | |||
| 78 | static inline void | ||
| 79 | io_mapping_unmap(void *vaddr) | ||
| 80 | { | ||
| 81 | iounmap(vaddr); | ||
| 82 | } | ||
| 83 | |||
| 84 | #else | ||
| 85 | |||
| 86 | /* Create the io_mapping object*/ | ||
| 87 | static inline struct io_mapping * | ||
| 88 | io_mapping_create_wc(unsigned long base, unsigned long size) | ||
| 89 | { | ||
| 90 | return (struct io_mapping *) ioremap_wc(base, size); | ||
| 91 | } | ||
| 92 | |||
| 93 | static inline void | ||
| 94 | io_mapping_free(struct io_mapping *mapping) | ||
| 95 | { | ||
| 96 | iounmap(mapping); | ||
| 97 | } | ||
| 98 | |||
| 99 | /* Atomic map/unmap */ | ||
| 100 | static inline void * | ||
| 101 | io_mapping_map_atomic_wc(struct io_mapping *mapping, unsigned long offset) | ||
| 102 | { | ||
| 103 | return ((char *) mapping) + offset; | ||
| 104 | } | ||
| 105 | |||
| 106 | static inline void | ||
| 107 | io_mapping_unmap_atomic(void *vaddr) | ||
| 108 | { | ||
| 109 | } | ||
| 110 | |||
| 111 | /* Non-atomic map/unmap */ | ||
| 112 | static inline void * | ||
| 113 | io_mapping_map_wc(struct io_mapping *mapping, unsigned long offset) | ||
| 114 | { | ||
| 115 | return ((char *) mapping) + offset; | ||
| 116 | } | ||
| 117 | |||
| 118 | static inline void | ||
| 119 | io_mapping_unmap(void *vaddr) | ||
| 120 | { | ||
| 121 | } | ||
| 122 | |||
| 123 | #endif /* HAVE_ATOMIC_IOMAP */ | ||
| 124 | |||
| 125 | #endif /* _LINUX_IO_MAPPING_H */ | ||
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig index b58f43bec363..33dbefd471e8 100644 --- a/kernel/trace/Kconfig +++ b/kernel/trace/Kconfig | |||
| @@ -25,7 +25,7 @@ config TRACING | |||
| 25 | bool | 25 | bool |
| 26 | select DEBUG_FS | 26 | select DEBUG_FS |
| 27 | select RING_BUFFER | 27 | select RING_BUFFER |
| 28 | select STACKTRACE | 28 | select STACKTRACE if STACKTRACE_SUPPORT |
| 29 | select TRACEPOINTS | 29 | select TRACEPOINTS |
| 30 | select NOP_TRACER | 30 | select NOP_TRACER |
| 31 | 31 | ||
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index cedf4e268285..3f3380638646 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c | |||
| @@ -1022,8 +1022,23 @@ rb_reserve_next_event(struct ring_buffer_per_cpu *cpu_buffer, | |||
| 1022 | struct ring_buffer_event *event; | 1022 | struct ring_buffer_event *event; |
| 1023 | u64 ts, delta; | 1023 | u64 ts, delta; |
| 1024 | int commit = 0; | 1024 | int commit = 0; |
| 1025 | int nr_loops = 0; | ||
| 1025 | 1026 | ||
| 1026 | again: | 1027 | again: |
| 1028 | /* | ||
| 1029 | * We allow for interrupts to reenter here and do a trace. | ||
| 1030 | * If one does, it will cause this original code to loop | ||
| 1031 | * back here. Even with heavy interrupts happening, this | ||
| 1032 | * should only happen a few times in a row. If this happens | ||
| 1033 | * 1000 times in a row, there must be either an interrupt | ||
| 1034 | * storm or we have something buggy. | ||
| 1035 | * Bail! | ||
| 1036 | */ | ||
| 1037 | if (unlikely(++nr_loops > 1000)) { | ||
| 1038 | RB_WARN_ON(cpu_buffer, 1); | ||
| 1039 | return NULL; | ||
| 1040 | } | ||
| 1041 | |||
| 1027 | ts = ring_buffer_time_stamp(cpu_buffer->cpu); | 1042 | ts = ring_buffer_time_stamp(cpu_buffer->cpu); |
| 1028 | 1043 | ||
| 1029 | /* | 1044 | /* |
| @@ -1532,10 +1547,23 @@ rb_get_reader_page(struct ring_buffer_per_cpu *cpu_buffer) | |||
| 1532 | { | 1547 | { |
| 1533 | struct buffer_page *reader = NULL; | 1548 | struct buffer_page *reader = NULL; |
| 1534 | unsigned long flags; | 1549 | unsigned long flags; |
| 1550 | int nr_loops = 0; | ||
| 1535 | 1551 | ||
| 1536 | spin_lock_irqsave(&cpu_buffer->lock, flags); | 1552 | spin_lock_irqsave(&cpu_buffer->lock, flags); |
| 1537 | 1553 | ||
| 1538 | again: | 1554 | again: |
| 1555 | /* | ||
| 1556 | * This should normally only loop twice. But because the | ||
| 1557 | * start of the reader inserts an empty page, it causes | ||
| 1558 | * a case where we will loop three times. There should be no | ||
| 1559 | * reason to loop four times (that I know of). | ||
| 1560 | */ | ||
| 1561 | if (unlikely(++nr_loops > 3)) { | ||
| 1562 | RB_WARN_ON(cpu_buffer, 1); | ||
| 1563 | reader = NULL; | ||
| 1564 | goto out; | ||
| 1565 | } | ||
| 1566 | |||
| 1539 | reader = cpu_buffer->reader_page; | 1567 | reader = cpu_buffer->reader_page; |
| 1540 | 1568 | ||
| 1541 | /* If there's more to read, return this page */ | 1569 | /* If there's more to read, return this page */ |
| @@ -1665,6 +1693,7 @@ ring_buffer_peek(struct ring_buffer *buffer, int cpu, u64 *ts) | |||
| 1665 | struct ring_buffer_per_cpu *cpu_buffer; | 1693 | struct ring_buffer_per_cpu *cpu_buffer; |
| 1666 | struct ring_buffer_event *event; | 1694 | struct ring_buffer_event *event; |
| 1667 | struct buffer_page *reader; | 1695 | struct buffer_page *reader; |
| 1696 | int nr_loops = 0; | ||
| 1668 | 1697 | ||
| 1669 | if (!cpu_isset(cpu, buffer->cpumask)) | 1698 | if (!cpu_isset(cpu, buffer->cpumask)) |
| 1670 | return NULL; | 1699 | return NULL; |
| @@ -1672,6 +1701,19 @@ ring_buffer_peek(struct ring_buffer *buffer, int cpu, u64 *ts) | |||
| 1672 | cpu_buffer = buffer->buffers[cpu]; | 1701 | cpu_buffer = buffer->buffers[cpu]; |
| 1673 | 1702 | ||
| 1674 | again: | 1703 | again: |
| 1704 | /* | ||
| 1705 | * We repeat when a timestamp is encountered. It is possible | ||
| 1706 | * to get multiple timestamps from an interrupt entering just | ||
| 1707 | * as one timestamp is about to be written. The max times | ||
| 1708 | * that this can happen is the number of nested interrupts we | ||
| 1709 | * can have. Nesting 10 deep of interrupts is clearly | ||
| 1710 | * an anomaly. | ||
| 1711 | */ | ||
| 1712 | if (unlikely(++nr_loops > 10)) { | ||
| 1713 | RB_WARN_ON(cpu_buffer, 1); | ||
| 1714 | return NULL; | ||
| 1715 | } | ||
| 1716 | |||
| 1675 | reader = rb_get_reader_page(cpu_buffer); | 1717 | reader = rb_get_reader_page(cpu_buffer); |
| 1676 | if (!reader) | 1718 | if (!reader) |
| 1677 | return NULL; | 1719 | return NULL; |
| @@ -1722,6 +1764,7 @@ ring_buffer_iter_peek(struct ring_buffer_iter *iter, u64 *ts) | |||
| 1722 | struct ring_buffer *buffer; | 1764 | struct ring_buffer *buffer; |
| 1723 | struct ring_buffer_per_cpu *cpu_buffer; | 1765 | struct ring_buffer_per_cpu *cpu_buffer; |
| 1724 | struct ring_buffer_event *event; | 1766 | struct ring_buffer_event *event; |
| 1767 | int nr_loops = 0; | ||
| 1725 | 1768 | ||
| 1726 | if (ring_buffer_iter_empty(iter)) | 1769 | if (ring_buffer_iter_empty(iter)) |
| 1727 | return NULL; | 1770 | return NULL; |
| @@ -1730,6 +1773,19 @@ ring_buffer_iter_peek(struct ring_buffer_iter *iter, u64 *ts) | |||
| 1730 | buffer = cpu_buffer->buffer; | 1773 | buffer = cpu_buffer->buffer; |
| 1731 | 1774 | ||
| 1732 | again: | 1775 | again: |
| 1776 | /* | ||
| 1777 | * We repeat when a timestamp is encountered. It is possible | ||
| 1778 | * to get multiple timestamps from an interrupt entering just | ||
| 1779 | * as one timestamp is about to be written. The max times | ||
| 1780 | * that this can happen is the number of nested interrupts we | ||
| 1781 | * can have. Nesting 10 deep of interrupts is clearly | ||
| 1782 | * an anomaly. | ||
| 1783 | */ | ||
| 1784 | if (unlikely(++nr_loops > 10)) { | ||
| 1785 | RB_WARN_ON(cpu_buffer, 1); | ||
| 1786 | return NULL; | ||
| 1787 | } | ||
| 1788 | |||
| 1733 | if (rb_per_cpu_empty(cpu_buffer)) | 1789 | if (rb_per_cpu_empty(cpu_buffer)) |
| 1734 | return NULL; | 1790 | return NULL; |
| 1735 | 1791 | ||
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 8a499e2adaec..9f3b478f9171 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
| @@ -705,6 +705,7 @@ static void ftrace_trace_stack(struct trace_array *tr, | |||
| 705 | unsigned long flags, | 705 | unsigned long flags, |
| 706 | int skip, int pc) | 706 | int skip, int pc) |
| 707 | { | 707 | { |
| 708 | #ifdef CONFIG_STACKTRACE | ||
| 708 | struct ring_buffer_event *event; | 709 | struct ring_buffer_event *event; |
| 709 | struct stack_entry *entry; | 710 | struct stack_entry *entry; |
| 710 | struct stack_trace trace; | 711 | struct stack_trace trace; |
| @@ -730,6 +731,7 @@ static void ftrace_trace_stack(struct trace_array *tr, | |||
| 730 | 731 | ||
| 731 | save_stack_trace(&trace); | 732 | save_stack_trace(&trace); |
| 732 | ring_buffer_unlock_commit(tr->buffer, event, irq_flags); | 733 | ring_buffer_unlock_commit(tr->buffer, event, irq_flags); |
| 734 | #endif | ||
| 733 | } | 735 | } |
| 734 | 736 | ||
| 735 | void __trace_stack(struct trace_array *tr, | 737 | void __trace_stack(struct trace_array *tr, |
| @@ -1086,17 +1088,20 @@ static void s_stop(struct seq_file *m, void *p) | |||
| 1086 | mutex_unlock(&trace_types_lock); | 1088 | mutex_unlock(&trace_types_lock); |
| 1087 | } | 1089 | } |
| 1088 | 1090 | ||
| 1089 | #define KRETPROBE_MSG "[unknown/kretprobe'd]" | ||
| 1090 | |||
| 1091 | #ifdef CONFIG_KRETPROBES | 1091 | #ifdef CONFIG_KRETPROBES |
| 1092 | static inline int kretprobed(unsigned long addr) | 1092 | static inline const char *kretprobed(const char *name) |
| 1093 | { | 1093 | { |
| 1094 | return addr == (unsigned long)kretprobe_trampoline; | 1094 | static const char tramp_name[] = "kretprobe_trampoline"; |
| 1095 | int size = sizeof(tramp_name); | ||
| 1096 | |||
| 1097 | if (strncmp(tramp_name, name, size) == 0) | ||
| 1098 | return "[unknown/kretprobe'd]"; | ||
| 1099 | return name; | ||
| 1095 | } | 1100 | } |
| 1096 | #else | 1101 | #else |
| 1097 | static inline int kretprobed(unsigned long addr) | 1102 | static inline const char *kretprobed(const char *name) |
| 1098 | { | 1103 | { |
| 1099 | return 0; | 1104 | return name; |
| 1100 | } | 1105 | } |
| 1101 | #endif /* CONFIG_KRETPROBES */ | 1106 | #endif /* CONFIG_KRETPROBES */ |
| 1102 | 1107 | ||
| @@ -1105,10 +1110,13 @@ seq_print_sym_short(struct trace_seq *s, const char *fmt, unsigned long address) | |||
| 1105 | { | 1110 | { |
| 1106 | #ifdef CONFIG_KALLSYMS | 1111 | #ifdef CONFIG_KALLSYMS |
| 1107 | char str[KSYM_SYMBOL_LEN]; | 1112 | char str[KSYM_SYMBOL_LEN]; |
| 1113 | const char *name; | ||
| 1108 | 1114 | ||
| 1109 | kallsyms_lookup(address, NULL, NULL, NULL, str); | 1115 | kallsyms_lookup(address, NULL, NULL, NULL, str); |
| 1110 | 1116 | ||
| 1111 | return trace_seq_printf(s, fmt, str); | 1117 | name = kretprobed(str); |
| 1118 | |||
| 1119 | return trace_seq_printf(s, fmt, name); | ||
| 1112 | #endif | 1120 | #endif |
| 1113 | return 1; | 1121 | return 1; |
| 1114 | } | 1122 | } |
| @@ -1119,9 +1127,12 @@ seq_print_sym_offset(struct trace_seq *s, const char *fmt, | |||
| 1119 | { | 1127 | { |
| 1120 | #ifdef CONFIG_KALLSYMS | 1128 | #ifdef CONFIG_KALLSYMS |
| 1121 | char str[KSYM_SYMBOL_LEN]; | 1129 | char str[KSYM_SYMBOL_LEN]; |
| 1130 | const char *name; | ||
| 1122 | 1131 | ||
| 1123 | sprint_symbol(str, address); | 1132 | sprint_symbol(str, address); |
| 1124 | return trace_seq_printf(s, fmt, str); | 1133 | name = kretprobed(str); |
| 1134 | |||
| 1135 | return trace_seq_printf(s, fmt, name); | ||
| 1125 | #endif | 1136 | #endif |
| 1126 | return 1; | 1137 | return 1; |
| 1127 | } | 1138 | } |
| @@ -1375,10 +1386,7 @@ print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu) | |||
| 1375 | 1386 | ||
| 1376 | seq_print_ip_sym(s, field->ip, sym_flags); | 1387 | seq_print_ip_sym(s, field->ip, sym_flags); |
| 1377 | trace_seq_puts(s, " ("); | 1388 | trace_seq_puts(s, " ("); |
| 1378 | if (kretprobed(field->parent_ip)) | 1389 | seq_print_ip_sym(s, field->parent_ip, sym_flags); |
| 1379 | trace_seq_puts(s, KRETPROBE_MSG); | ||
| 1380 | else | ||
| 1381 | seq_print_ip_sym(s, field->parent_ip, sym_flags); | ||
| 1382 | trace_seq_puts(s, ")\n"); | 1390 | trace_seq_puts(s, ")\n"); |
| 1383 | break; | 1391 | break; |
| 1384 | } | 1392 | } |
| @@ -1494,12 +1502,9 @@ static enum print_line_t print_trace_fmt(struct trace_iterator *iter) | |||
| 1494 | ret = trace_seq_printf(s, " <-"); | 1502 | ret = trace_seq_printf(s, " <-"); |
| 1495 | if (!ret) | 1503 | if (!ret) |
| 1496 | return TRACE_TYPE_PARTIAL_LINE; | 1504 | return TRACE_TYPE_PARTIAL_LINE; |
| 1497 | if (kretprobed(field->parent_ip)) | 1505 | ret = seq_print_ip_sym(s, |
| 1498 | ret = trace_seq_puts(s, KRETPROBE_MSG); | 1506 | field->parent_ip, |
| 1499 | else | 1507 | sym_flags); |
| 1500 | ret = seq_print_ip_sym(s, | ||
| 1501 | field->parent_ip, | ||
| 1502 | sym_flags); | ||
| 1503 | if (!ret) | 1508 | if (!ret) |
| 1504 | return TRACE_TYPE_PARTIAL_LINE; | 1509 | return TRACE_TYPE_PARTIAL_LINE; |
| 1505 | } | 1510 | } |
diff --git a/mm/vmalloc.c b/mm/vmalloc.c index f1cc03bbf6ac..66fad3fc02b1 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c | |||
| @@ -178,7 +178,7 @@ static int vmap_page_range(unsigned long addr, unsigned long end, | |||
| 178 | static inline int is_vmalloc_or_module_addr(const void *x) | 178 | static inline int is_vmalloc_or_module_addr(const void *x) |
| 179 | { | 179 | { |
| 180 | /* | 180 | /* |
| 181 | * x86-64 and sparc64 put modules in a special place, | 181 | * ARM, x86-64 and sparc64 put modules in a special place, |
| 182 | * and fall back on vmalloc() if that fails. Others | 182 | * and fall back on vmalloc() if that fails. Others |
| 183 | * just put it in the vmalloc space. | 183 | * just put it in the vmalloc space. |
| 184 | */ | 184 | */ |
diff --git a/sound/aoa/soundbus/core.c b/sound/aoa/soundbus/core.c index f84f3e505788..fa8ab2815a98 100644 --- a/sound/aoa/soundbus/core.c +++ b/sound/aoa/soundbus/core.c | |||
| @@ -176,7 +176,7 @@ int soundbus_add_one(struct soundbus_dev *dev) | |||
| 176 | return -EINVAL; | 176 | return -EINVAL; |
| 177 | } | 177 | } |
| 178 | 178 | ||
| 179 | snprintf(dev->ofdev.dev.bus_id, BUS_ID_SIZE, "soundbus:%x", ++devcount); | 179 | dev_set_name(&dev->ofdev.dev, "soundbus:%x", ++devcount); |
| 180 | dev->ofdev.dev.bus = &soundbus_bus_type; | 180 | dev->ofdev.dev.bus = &soundbus_bus_type; |
| 181 | return of_device_register(&dev->ofdev); | 181 | return of_device_register(&dev->ofdev); |
| 182 | } | 182 | } |
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index c4995c9f5730..39672f68ce5d 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c | |||
| @@ -148,6 +148,8 @@ static int snd_rawmidi_runtime_free(struct snd_rawmidi_substream *substream) | |||
| 148 | 148 | ||
| 149 | static inline void snd_rawmidi_output_trigger(struct snd_rawmidi_substream *substream,int up) | 149 | static inline void snd_rawmidi_output_trigger(struct snd_rawmidi_substream *substream,int up) |
| 150 | { | 150 | { |
| 151 | if (!substream->opened) | ||
| 152 | return; | ||
| 151 | if (up) { | 153 | if (up) { |
| 152 | tasklet_hi_schedule(&substream->runtime->tasklet); | 154 | tasklet_hi_schedule(&substream->runtime->tasklet); |
| 153 | } else { | 155 | } else { |
| @@ -158,6 +160,8 @@ static inline void snd_rawmidi_output_trigger(struct snd_rawmidi_substream *subs | |||
| 158 | 160 | ||
| 159 | static void snd_rawmidi_input_trigger(struct snd_rawmidi_substream *substream, int up) | 161 | static void snd_rawmidi_input_trigger(struct snd_rawmidi_substream *substream, int up) |
| 160 | { | 162 | { |
| 163 | if (!substream->opened) | ||
| 164 | return; | ||
| 161 | substream->ops->trigger(substream, up); | 165 | substream->ops->trigger(substream, up); |
| 162 | if (!up && substream->runtime->event) | 166 | if (!up && substream->runtime->event) |
| 163 | tasklet_kill(&substream->runtime->tasklet); | 167 | tasklet_kill(&substream->runtime->tasklet); |
| @@ -857,6 +861,8 @@ int snd_rawmidi_receive(struct snd_rawmidi_substream *substream, | |||
| 857 | int result = 0, count1; | 861 | int result = 0, count1; |
| 858 | struct snd_rawmidi_runtime *runtime = substream->runtime; | 862 | struct snd_rawmidi_runtime *runtime = substream->runtime; |
| 859 | 863 | ||
| 864 | if (!substream->opened) | ||
| 865 | return -EBADFD; | ||
| 860 | if (runtime->buffer == NULL) { | 866 | if (runtime->buffer == NULL) { |
| 861 | snd_printd("snd_rawmidi_receive: input is not active!!!\n"); | 867 | snd_printd("snd_rawmidi_receive: input is not active!!!\n"); |
| 862 | return -EINVAL; | 868 | return -EINVAL; |
| @@ -1126,6 +1132,8 @@ int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count) | |||
| 1126 | int snd_rawmidi_transmit(struct snd_rawmidi_substream *substream, | 1132 | int snd_rawmidi_transmit(struct snd_rawmidi_substream *substream, |
| 1127 | unsigned char *buffer, int count) | 1133 | unsigned char *buffer, int count) |
| 1128 | { | 1134 | { |
| 1135 | if (!substream->opened) | ||
| 1136 | return -EBADFD; | ||
| 1129 | count = snd_rawmidi_transmit_peek(substream, buffer, count); | 1137 | count = snd_rawmidi_transmit_peek(substream, buffer, count); |
| 1130 | if (count < 0) | 1138 | if (count < 0) |
| 1131 | return count; | 1139 | return count; |
diff --git a/sound/drivers/ml403-ac97cr.c b/sound/drivers/ml403-ac97cr.c index ecdbeb6d3603..7783843ca9ae 100644 --- a/sound/drivers/ml403-ac97cr.c +++ b/sound/drivers/ml403-ac97cr.c | |||
| @@ -1153,7 +1153,7 @@ snd_ml403_ac97cr_create(struct snd_card *card, struct platform_device *pfdev, | |||
| 1153 | /* get irq */ | 1153 | /* get irq */ |
| 1154 | irq = platform_get_irq(pfdev, 0); | 1154 | irq = platform_get_irq(pfdev, 0); |
| 1155 | if (request_irq(irq, snd_ml403_ac97cr_irq, IRQF_DISABLED, | 1155 | if (request_irq(irq, snd_ml403_ac97cr_irq, IRQF_DISABLED, |
| 1156 | pfdev->dev.bus_id, (void *)ml403_ac97cr)) { | 1156 | dev_name(&pfdev->dev), (void *)ml403_ac97cr)) { |
| 1157 | snd_printk(KERN_ERR SND_ML403_AC97CR_DRIVER ": " | 1157 | snd_printk(KERN_ERR SND_ML403_AC97CR_DRIVER ": " |
| 1158 | "unable to grab IRQ %d\n", | 1158 | "unable to grab IRQ %d\n", |
| 1159 | irq); | 1159 | irq); |
| @@ -1166,7 +1166,7 @@ snd_ml403_ac97cr_create(struct snd_card *card, struct platform_device *pfdev, | |||
| 1166 | ml403_ac97cr->irq); | 1166 | ml403_ac97cr->irq); |
| 1167 | irq = platform_get_irq(pfdev, 1); | 1167 | irq = platform_get_irq(pfdev, 1); |
| 1168 | if (request_irq(irq, snd_ml403_ac97cr_irq, IRQF_DISABLED, | 1168 | if (request_irq(irq, snd_ml403_ac97cr_irq, IRQF_DISABLED, |
| 1169 | pfdev->dev.bus_id, (void *)ml403_ac97cr)) { | 1169 | dev_name(&pfdev->dev), (void *)ml403_ac97cr)) { |
| 1170 | snd_printk(KERN_ERR SND_ML403_AC97CR_DRIVER ": " | 1170 | snd_printk(KERN_ERR SND_ML403_AC97CR_DRIVER ": " |
| 1171 | "unable to grab IRQ %d\n", | 1171 | "unable to grab IRQ %d\n", |
| 1172 | irq); | 1172 | irq); |
diff --git a/sound/drivers/pcsp/pcsp_input.c b/sound/drivers/pcsp/pcsp_input.c index cd9b83e7f7d1..0444cdeb4bec 100644 --- a/sound/drivers/pcsp/pcsp_input.c +++ b/sound/drivers/pcsp/pcsp_input.c | |||
| @@ -24,13 +24,13 @@ static void pcspkr_do_sound(unsigned int count) | |||
| 24 | spin_lock_irqsave(&i8253_lock, flags); | 24 | spin_lock_irqsave(&i8253_lock, flags); |
| 25 | 25 | ||
| 26 | if (count) { | 26 | if (count) { |
| 27 | /* enable counter 2 */ | ||
| 28 | outb_p(inb_p(0x61) | 3, 0x61); | ||
| 29 | /* set command for counter 2, 2 byte write */ | 27 | /* set command for counter 2, 2 byte write */ |
| 30 | outb_p(0xB6, 0x43); | 28 | outb_p(0xB6, 0x43); |
| 31 | /* select desired HZ */ | 29 | /* select desired HZ */ |
| 32 | outb_p(count & 0xff, 0x42); | 30 | outb_p(count & 0xff, 0x42); |
| 33 | outb((count >> 8) & 0xff, 0x42); | 31 | outb((count >> 8) & 0xff, 0x42); |
| 32 | /* enable counter 2 */ | ||
| 33 | outb_p(inb_p(0x61) | 3, 0x61); | ||
| 34 | } else { | 34 | } else { |
| 35 | /* disable counter 2 */ | 35 | /* disable counter 2 */ |
| 36 | outb(inb_p(0x61) & 0xFC, 0x61); | 36 | outb(inb_p(0x61) & 0xFC, 0x61); |
diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c index b68d20edc20f..223a6c038819 100644 --- a/sound/isa/ad1848/ad1848.c +++ b/sound/isa/ad1848/ad1848.c | |||
| @@ -70,15 +70,15 @@ static int __devinit snd_ad1848_match(struct device *dev, unsigned int n) | |||
| 70 | return 0; | 70 | return 0; |
| 71 | 71 | ||
| 72 | if (port[n] == SNDRV_AUTO_PORT) { | 72 | if (port[n] == SNDRV_AUTO_PORT) { |
| 73 | snd_printk(KERN_ERR "%s: please specify port\n", dev->bus_id); | 73 | dev_err(dev, "please specify port\n"); |
| 74 | return 0; | 74 | return 0; |
| 75 | } | 75 | } |
| 76 | if (irq[n] == SNDRV_AUTO_IRQ) { | 76 | if (irq[n] == SNDRV_AUTO_IRQ) { |
| 77 | snd_printk(KERN_ERR "%s: please specify irq\n", dev->bus_id); | 77 | dev_err(dev, "please specify irq\n"); |
| 78 | return 0; | 78 | return 0; |
| 79 | } | 79 | } |
| 80 | if (dma1[n] == SNDRV_AUTO_DMA) { | 80 | if (dma1[n] == SNDRV_AUTO_DMA) { |
| 81 | snd_printk(KERN_ERR "%s: please specify dma1\n", dev->bus_id); | 81 | dev_err(dev, "please specify dma1\n"); |
| 82 | return 0; | 82 | return 0; |
| 83 | } | 83 | } |
| 84 | return 1; | 84 | return 1; |
diff --git a/sound/isa/adlib.c b/sound/isa/adlib.c index efa8c80d05b6..374b7177e111 100644 --- a/sound/isa/adlib.c +++ b/sound/isa/adlib.c | |||
| @@ -36,7 +36,7 @@ static int __devinit snd_adlib_match(struct device *dev, unsigned int n) | |||
| 36 | return 0; | 36 | return 0; |
| 37 | 37 | ||
| 38 | if (port[n] == SNDRV_AUTO_PORT) { | 38 | if (port[n] == SNDRV_AUTO_PORT) { |
| 39 | snd_printk(KERN_ERR "%s: please specify port\n", dev->bus_id); | 39 | dev_err(dev, "please specify port\n"); |
| 40 | return 0; | 40 | return 0; |
| 41 | } | 41 | } |
| 42 | return 1; | 42 | return 1; |
| @@ -55,13 +55,13 @@ static int __devinit snd_adlib_probe(struct device *dev, unsigned int n) | |||
| 55 | 55 | ||
| 56 | card = snd_card_new(index[n], id[n], THIS_MODULE, 0); | 56 | card = snd_card_new(index[n], id[n], THIS_MODULE, 0); |
| 57 | if (!card) { | 57 | if (!card) { |
| 58 | snd_printk(KERN_ERR "%s: could not create card\n", dev->bus_id); | 58 | dev_err(dev, "could not create card\n"); |
| 59 | return -EINVAL; | 59 | return -EINVAL; |
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | card->private_data = request_region(port[n], 4, CRD_NAME); | 62 | card->private_data = request_region(port[n], 4, CRD_NAME); |
| 63 | if (!card->private_data) { | 63 | if (!card->private_data) { |
| 64 | snd_printk(KERN_ERR "%s: could not grab ports\n", dev->bus_id); | 64 | dev_err(dev, "could not grab ports\n"); |
| 65 | error = -EBUSY; | 65 | error = -EBUSY; |
| 66 | goto out; | 66 | goto out; |
| 67 | } | 67 | } |
| @@ -73,13 +73,13 @@ static int __devinit snd_adlib_probe(struct device *dev, unsigned int n) | |||
| 73 | 73 | ||
| 74 | error = snd_opl3_create(card, port[n], port[n] + 2, OPL3_HW_AUTO, 1, &opl3); | 74 | error = snd_opl3_create(card, port[n], port[n] + 2, OPL3_HW_AUTO, 1, &opl3); |
| 75 | if (error < 0) { | 75 | if (error < 0) { |
| 76 | snd_printk(KERN_ERR "%s: could not create OPL\n", dev->bus_id); | 76 | dev_err(dev, "could not create OPL\n"); |
| 77 | goto out; | 77 | goto out; |
| 78 | } | 78 | } |
| 79 | 79 | ||
| 80 | error = snd_opl3_hwdep_new(opl3, 0, 0, NULL); | 80 | error = snd_opl3_hwdep_new(opl3, 0, 0, NULL); |
| 81 | if (error < 0) { | 81 | if (error < 0) { |
| 82 | snd_printk(KERN_ERR "%s: could not create FM\n", dev->bus_id); | 82 | dev_err(dev, "could not create FM\n"); |
| 83 | goto out; | 83 | goto out; |
| 84 | } | 84 | } |
| 85 | 85 | ||
| @@ -87,7 +87,7 @@ static int __devinit snd_adlib_probe(struct device *dev, unsigned int n) | |||
| 87 | 87 | ||
| 88 | error = snd_card_register(card); | 88 | error = snd_card_register(card); |
| 89 | if (error < 0) { | 89 | if (error < 0) { |
| 90 | snd_printk(KERN_ERR "%s: could not register card\n", dev->bus_id); | 90 | dev_err(dev, "could not register card\n"); |
| 91 | goto out; | 91 | goto out; |
| 92 | } | 92 | } |
| 93 | 93 | ||
diff --git a/sound/isa/cs423x/cs4231.c b/sound/isa/cs423x/cs4231.c index ddd289120aa8..f019d449e2d6 100644 --- a/sound/isa/cs423x/cs4231.c +++ b/sound/isa/cs423x/cs4231.c | |||
| @@ -74,15 +74,15 @@ static int __devinit snd_cs4231_match(struct device *dev, unsigned int n) | |||
| 74 | return 0; | 74 | return 0; |
| 75 | 75 | ||
| 76 | if (port[n] == SNDRV_AUTO_PORT) { | 76 | if (port[n] == SNDRV_AUTO_PORT) { |
| 77 | snd_printk(KERN_ERR "%s: please specify port\n", dev->bus_id); | 77 | dev_err(dev, "please specify port\n"); |
| 78 | return 0; | 78 | return 0; |
| 79 | } | 79 | } |
| 80 | if (irq[n] == SNDRV_AUTO_IRQ) { | 80 | if (irq[n] == SNDRV_AUTO_IRQ) { |
| 81 | snd_printk(KERN_ERR "%s: please specify irq\n", dev->bus_id); | 81 | dev_err(dev, "please specify irq\n"); |
| 82 | return 0; | 82 | return 0; |
| 83 | } | 83 | } |
| 84 | if (dma1[n] == SNDRV_AUTO_DMA) { | 84 | if (dma1[n] == SNDRV_AUTO_DMA) { |
| 85 | snd_printk(KERN_ERR "%s: please specify dma1\n", dev->bus_id); | 85 | dev_err(dev, "please specify dma1\n"); |
| 86 | return 0; | 86 | return 0; |
| 87 | } | 87 | } |
| 88 | return 1; | 88 | return 1; |
| @@ -133,7 +133,7 @@ static int __devinit snd_cs4231_probe(struct device *dev, unsigned int n) | |||
| 133 | mpu_port[n], 0, mpu_irq[n], | 133 | mpu_port[n], 0, mpu_irq[n], |
| 134 | mpu_irq[n] >= 0 ? IRQF_DISABLED : 0, | 134 | mpu_irq[n] >= 0 ? IRQF_DISABLED : 0, |
| 135 | NULL) < 0) | 135 | NULL) < 0) |
| 136 | printk(KERN_WARNING "%s: MPU401 not detected\n", dev->bus_id); | 136 | dev_warn(dev, "MPU401 not detected\n"); |
| 137 | } | 137 | } |
| 138 | 138 | ||
| 139 | snd_card_set_dev(card, dev); | 139 | snd_card_set_dev(card, dev); |
diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c index 91f9c15d3e30..019c9401663e 100644 --- a/sound/isa/cs423x/cs4236.c +++ b/sound/isa/cs423x/cs4236.c | |||
| @@ -488,19 +488,19 @@ static int __devinit snd_cs423x_isa_match(struct device *pdev, | |||
| 488 | return 0; | 488 | return 0; |
| 489 | 489 | ||
| 490 | if (port[dev] == SNDRV_AUTO_PORT) { | 490 | if (port[dev] == SNDRV_AUTO_PORT) { |
| 491 | snd_printk(KERN_ERR "%s: please specify port\n", pdev->bus_id); | 491 | dev_err(pdev, "please specify port\n"); |
| 492 | return 0; | 492 | return 0; |
| 493 | } | 493 | } |
| 494 | if (cport[dev] == SNDRV_AUTO_PORT) { | 494 | if (cport[dev] == SNDRV_AUTO_PORT) { |
| 495 | snd_printk(KERN_ERR "%s: please specify cport\n", pdev->bus_id); | 495 | dev_err(pdev, "please specify cport\n"); |
| 496 | return 0; | 496 | return 0; |
| 497 | } | 497 | } |
| 498 | if (irq[dev] == SNDRV_AUTO_IRQ) { | 498 | if (irq[dev] == SNDRV_AUTO_IRQ) { |
| 499 | snd_printk(KERN_ERR "%s: please specify irq\n", pdev->bus_id); | 499 | dev_err(pdev, "please specify irq\n"); |
| 500 | return 0; | 500 | return 0; |
| 501 | } | 501 | } |
| 502 | if (dma1[dev] == SNDRV_AUTO_DMA) { | 502 | if (dma1[dev] == SNDRV_AUTO_DMA) { |
| 503 | snd_printk(KERN_ERR "%s: please specify dma1\n", pdev->bus_id); | 503 | dev_err(pdev, "please specify dma1\n"); |
| 504 | return 0; | 504 | return 0; |
| 505 | } | 505 | } |
| 506 | return 1; | 506 | return 1; |
diff --git a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c index f88639ea64b2..b46377139cf8 100644 --- a/sound/isa/es1688/es1688.c +++ b/sound/isa/es1688/es1688.c | |||
| @@ -88,16 +88,14 @@ static int __devinit snd_es1688_legacy_create(struct snd_card *card, | |||
| 88 | if (irq[n] == SNDRV_AUTO_IRQ) { | 88 | if (irq[n] == SNDRV_AUTO_IRQ) { |
| 89 | irq[n] = snd_legacy_find_free_irq(possible_irqs); | 89 | irq[n] = snd_legacy_find_free_irq(possible_irqs); |
| 90 | if (irq[n] < 0) { | 90 | if (irq[n] < 0) { |
| 91 | snd_printk(KERN_ERR "%s: unable to find a free IRQ\n", | 91 | dev_err(dev, "unable to find a free IRQ\n"); |
| 92 | dev->bus_id); | ||
| 93 | return -EBUSY; | 92 | return -EBUSY; |
| 94 | } | 93 | } |
| 95 | } | 94 | } |
| 96 | if (dma8[n] == SNDRV_AUTO_DMA) { | 95 | if (dma8[n] == SNDRV_AUTO_DMA) { |
| 97 | dma8[n] = snd_legacy_find_free_dma(possible_dmas); | 96 | dma8[n] = snd_legacy_find_free_dma(possible_dmas); |
| 98 | if (dma8[n] < 0) { | 97 | if (dma8[n] < 0) { |
| 99 | snd_printk(KERN_ERR "%s: unable to find a free DMA\n", | 98 | dev_err(dev, "unable to find a free DMA\n"); |
| 100 | dev->bus_id); | ||
| 101 | return -EBUSY; | 99 | return -EBUSY; |
| 102 | } | 100 | } |
| 103 | } | 101 | } |
| @@ -147,8 +145,7 @@ static int __devinit snd_es1688_probe(struct device *dev, unsigned int n) | |||
| 147 | 145 | ||
| 148 | if (snd_opl3_create(card, chip->port, chip->port + 2, | 146 | if (snd_opl3_create(card, chip->port, chip->port + 2, |
| 149 | OPL3_HW_OPL3, 0, &opl3) < 0) | 147 | OPL3_HW_OPL3, 0, &opl3) < 0) |
| 150 | printk(KERN_WARNING "%s: opl3 not detected at 0x%lx\n", | 148 | dev_warn(dev, "opl3 not detected at 0x%lx\n", chip->port); |
| 151 | dev->bus_id, chip->port); | ||
| 152 | else { | 149 | else { |
| 153 | error = snd_opl3_hwdep_new(opl3, 0, 1, NULL); | 150 | error = snd_opl3_hwdep_new(opl3, 0, 1, NULL); |
| 154 | if (error < 0) | 151 | if (error < 0) |
diff --git a/sound/isa/gus/gusclassic.c b/sound/isa/gus/gusclassic.c index 8f914b37bf89..426532a4d730 100644 --- a/sound/isa/gus/gusclassic.c +++ b/sound/isa/gus/gusclassic.c | |||
| @@ -90,24 +90,21 @@ static int __devinit snd_gusclassic_create(struct snd_card *card, | |||
| 90 | if (irq[n] == SNDRV_AUTO_IRQ) { | 90 | if (irq[n] == SNDRV_AUTO_IRQ) { |
| 91 | irq[n] = snd_legacy_find_free_irq(possible_irqs); | 91 | irq[n] = snd_legacy_find_free_irq(possible_irqs); |
| 92 | if (irq[n] < 0) { | 92 | if (irq[n] < 0) { |
| 93 | snd_printk(KERN_ERR "%s: unable to find a free IRQ\n", | 93 | dev_err(dev, "unable to find a free IRQ\n"); |
| 94 | dev->bus_id); | ||
| 95 | return -EBUSY; | 94 | return -EBUSY; |
| 96 | } | 95 | } |
| 97 | } | 96 | } |
| 98 | if (dma1[n] == SNDRV_AUTO_DMA) { | 97 | if (dma1[n] == SNDRV_AUTO_DMA) { |
| 99 | dma1[n] = snd_legacy_find_free_dma(possible_dmas); | 98 | dma1[n] = snd_legacy_find_free_dma(possible_dmas); |
| 100 | if (dma1[n] < 0) { | 99 | if (dma1[n] < 0) { |
| 101 | snd_printk(KERN_ERR "%s: unable to find a free DMA1\n", | 100 | dev_err(dev, "unable to find a free DMA1\n"); |
| 102 | dev->bus_id); | ||
| 103 | return -EBUSY; | 101 | return -EBUSY; |
| 104 | } | 102 | } |
| 105 | } | 103 | } |
| 106 | if (dma2[n] == SNDRV_AUTO_DMA) { | 104 | if (dma2[n] == SNDRV_AUTO_DMA) { |
| 107 | dma2[n] = snd_legacy_find_free_dma(possible_dmas); | 105 | dma2[n] = snd_legacy_find_free_dma(possible_dmas); |
| 108 | if (dma2[n] < 0) { | 106 | if (dma2[n] < 0) { |
| 109 | snd_printk(KERN_ERR "%s: unable to find a free DMA2\n", | 107 | dev_err(dev, "unable to find a free DMA2\n"); |
| 110 | dev->bus_id); | ||
| 111 | return -EBUSY; | 108 | return -EBUSY; |
| 112 | } | 109 | } |
| 113 | } | 110 | } |
| @@ -174,8 +171,8 @@ static int __devinit snd_gusclassic_probe(struct device *dev, unsigned int n) | |||
| 174 | 171 | ||
| 175 | error = -ENODEV; | 172 | error = -ENODEV; |
| 176 | if (gus->max_flag || gus->ess_flag) { | 173 | if (gus->max_flag || gus->ess_flag) { |
| 177 | snd_printk(KERN_ERR "%s: GUS Classic or ACE soundcard was " | 174 | dev_err(dev, "GUS Classic or ACE soundcard was " |
| 178 | "not detected at 0x%lx\n", dev->bus_id, gus->gf1.port); | 175 | "not detected at 0x%lx\n", gus->gf1.port); |
| 179 | goto out; | 176 | goto out; |
| 180 | } | 177 | } |
| 181 | 178 | ||
diff --git a/sound/isa/gus/gusextreme.c b/sound/isa/gus/gusextreme.c index da13185eb0a0..7ad4c3b41a84 100644 --- a/sound/isa/gus/gusextreme.c +++ b/sound/isa/gus/gusextreme.c | |||
| @@ -106,16 +106,14 @@ static int __devinit snd_gusextreme_es1688_create(struct snd_card *card, | |||
| 106 | if (irq[n] == SNDRV_AUTO_IRQ) { | 106 | if (irq[n] == SNDRV_AUTO_IRQ) { |
| 107 | irq[n] = snd_legacy_find_free_irq(possible_irqs); | 107 | irq[n] = snd_legacy_find_free_irq(possible_irqs); |
| 108 | if (irq[n] < 0) { | 108 | if (irq[n] < 0) { |
| 109 | snd_printk(KERN_ERR "%s: unable to find a free IRQ " | 109 | dev_err(dev, "unable to find a free IRQ for ES1688\n"); |
| 110 | "for ES1688\n", dev->bus_id); | ||
| 111 | return -EBUSY; | 110 | return -EBUSY; |
| 112 | } | 111 | } |
| 113 | } | 112 | } |
| 114 | if (dma8[n] == SNDRV_AUTO_DMA) { | 113 | if (dma8[n] == SNDRV_AUTO_DMA) { |
| 115 | dma8[n] = snd_legacy_find_free_dma(possible_dmas); | 114 | dma8[n] = snd_legacy_find_free_dma(possible_dmas); |
| 116 | if (dma8[n] < 0) { | 115 | if (dma8[n] < 0) { |
| 117 | snd_printk(KERN_ERR "%s: unable to find a free DMA " | 116 | dev_err(dev, "unable to find a free DMA for ES1688\n"); |
| 118 | "for ES1688\n", dev->bus_id); | ||
| 119 | return -EBUSY; | 117 | return -EBUSY; |
| 120 | } | 118 | } |
| 121 | } | 119 | } |
| @@ -143,16 +141,14 @@ static int __devinit snd_gusextreme_gus_card_create(struct snd_card *card, | |||
| 143 | if (gf1_irq[n] == SNDRV_AUTO_IRQ) { | 141 | if (gf1_irq[n] == SNDRV_AUTO_IRQ) { |
| 144 | gf1_irq[n] = snd_legacy_find_free_irq(possible_irqs); | 142 | gf1_irq[n] = snd_legacy_find_free_irq(possible_irqs); |
| 145 | if (gf1_irq[n] < 0) { | 143 | if (gf1_irq[n] < 0) { |
| 146 | snd_printk(KERN_ERR "%s: unable to find a free IRQ " | 144 | dev_err(dev, "unable to find a free IRQ for GF1\n"); |
| 147 | "for GF1\n", dev->bus_id); | ||
| 148 | return -EBUSY; | 145 | return -EBUSY; |
| 149 | } | 146 | } |
| 150 | } | 147 | } |
| 151 | if (dma1[n] == SNDRV_AUTO_DMA) { | 148 | if (dma1[n] == SNDRV_AUTO_DMA) { |
| 152 | dma1[n] = snd_legacy_find_free_dma(possible_dmas); | 149 | dma1[n] = snd_legacy_find_free_dma(possible_dmas); |
| 153 | if (dma1[n] < 0) { | 150 | if (dma1[n] < 0) { |
| 154 | snd_printk(KERN_ERR "%s: unable to find a free DMA " | 151 | dev_err(dev, "unable to find a free DMA for GF1\n"); |
| 155 | "for GF1\n", dev->bus_id); | ||
| 156 | return -EBUSY; | 152 | return -EBUSY; |
| 157 | } | 153 | } |
| 158 | } | 154 | } |
| @@ -278,8 +274,8 @@ static int __devinit snd_gusextreme_probe(struct device *dev, unsigned int n) | |||
| 278 | 274 | ||
| 279 | error = -ENODEV; | 275 | error = -ENODEV; |
| 280 | if (!gus->ess_flag) { | 276 | if (!gus->ess_flag) { |
| 281 | snd_printk(KERN_ERR "%s: GUS Extreme soundcard was not " | 277 | dev_err(dev, "GUS Extreme soundcard was not " |
| 282 | "detected at 0x%lx\n", dev->bus_id, gus->gf1.port); | 278 | "detected at 0x%lx\n", gus->gf1.port); |
| 283 | goto out; | 279 | goto out; |
| 284 | } | 280 | } |
| 285 | gus->codec_flag = 1; | 281 | gus->codec_flag = 1; |
| @@ -310,8 +306,7 @@ static int __devinit snd_gusextreme_probe(struct device *dev, unsigned int n) | |||
| 310 | 306 | ||
| 311 | if (snd_opl3_create(card, es1688->port, es1688->port + 2, | 307 | if (snd_opl3_create(card, es1688->port, es1688->port + 2, |
| 312 | OPL3_HW_OPL3, 0, &opl3) < 0) | 308 | OPL3_HW_OPL3, 0, &opl3) < 0) |
| 313 | printk(KERN_ERR "%s: opl3 not detected at 0x%lx\n", | 309 | dev_warn(dev, "opl3 not detected at 0x%lx\n", es1688->port); |
| 314 | dev->bus_id, es1688->port); | ||
| 315 | else { | 310 | else { |
| 316 | error = snd_opl3_hwdep_new(opl3, 0, 2, NULL); | 311 | error = snd_opl3_hwdep_new(opl3, 0, 2, NULL); |
| 317 | if (error < 0) | 312 | if (error < 0) |
diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c index 336a34277907..667eccc676a4 100644 --- a/sound/isa/sb/sb8.c +++ b/sound/isa/sb/sb8.c | |||
| @@ -85,11 +85,11 @@ static int __devinit snd_sb8_match(struct device *pdev, unsigned int dev) | |||
| 85 | if (!enable[dev]) | 85 | if (!enable[dev]) |
| 86 | return 0; | 86 | return 0; |
| 87 | if (irq[dev] == SNDRV_AUTO_IRQ) { | 87 | if (irq[dev] == SNDRV_AUTO_IRQ) { |
| 88 | snd_printk(KERN_ERR "%s: please specify irq\n", pdev->bus_id); | 88 | dev_err(pdev, "please specify irq\n"); |
| 89 | return 0; | 89 | return 0; |
| 90 | } | 90 | } |
| 91 | if (dma8[dev] == SNDRV_AUTO_DMA) { | 91 | if (dma8[dev] == SNDRV_AUTO_DMA) { |
| 92 | snd_printk(KERN_ERR "%s: please specify dma8\n", pdev->bus_id); | 92 | dev_err(pdev, "please specify dma8\n"); |
| 93 | return 0; | 93 | return 0; |
| 94 | } | 94 | } |
| 95 | return 1; | 95 | return 1; |
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index 2f283ea6ad9a..de5ee8f097f6 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c | |||
| @@ -1464,6 +1464,7 @@ static struct snd_emu_chip_details emu_chip_details[] = { | |||
| 1464 | .ca0151_chip = 1, | 1464 | .ca0151_chip = 1, |
| 1465 | .spk71 = 1, | 1465 | .spk71 = 1, |
| 1466 | .spdif_bug = 1, | 1466 | .spdif_bug = 1, |
| 1467 | .invert_shared_spdif = 1, /* digital/analog switch swapped */ | ||
| 1467 | .ac97_chip = 1} , | 1468 | .ac97_chip = 1} , |
| 1468 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20021102, | 1469 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20021102, |
| 1469 | .driver = "Audigy2", .name = "Audigy 2 ZS [SB0350]", | 1470 | .driver = "Audigy2", .name = "Audigy 2 ZS [SB0350]", |
| @@ -1473,6 +1474,7 @@ static struct snd_emu_chip_details emu_chip_details[] = { | |||
| 1473 | .ca0151_chip = 1, | 1474 | .ca0151_chip = 1, |
| 1474 | .spk71 = 1, | 1475 | .spk71 = 1, |
| 1475 | .spdif_bug = 1, | 1476 | .spdif_bug = 1, |
| 1477 | .invert_shared_spdif = 1, /* digital/analog switch swapped */ | ||
| 1476 | .ac97_chip = 1} , | 1478 | .ac97_chip = 1} , |
| 1477 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20011102, | 1479 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20011102, |
| 1478 | .driver = "Audigy2", .name = "Audigy 2 ZS [2001]", | 1480 | .driver = "Audigy2", .name = "Audigy 2 ZS [2001]", |
| @@ -1482,6 +1484,7 @@ static struct snd_emu_chip_details emu_chip_details[] = { | |||
| 1482 | .ca0151_chip = 1, | 1484 | .ca0151_chip = 1, |
| 1483 | .spk71 = 1, | 1485 | .spk71 = 1, |
| 1484 | .spdif_bug = 1, | 1486 | .spdif_bug = 1, |
| 1487 | .invert_shared_spdif = 1, /* digital/analog switch swapped */ | ||
| 1485 | .ac97_chip = 1} , | 1488 | .ac97_chip = 1} , |
| 1486 | /* Audigy 2 */ | 1489 | /* Audigy 2 */ |
| 1487 | /* Tested by James@superbug.co.uk 3rd July 2005 */ | 1490 | /* Tested by James@superbug.co.uk 3rd July 2005 */ |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 4eceab9bd109..a4666c96a44f 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
| @@ -829,6 +829,7 @@ static void alc_sku_automute(struct hda_codec *codec) | |||
| 829 | spec->jack_present ? 0 : PIN_OUT); | 829 | spec->jack_present ? 0 : PIN_OUT); |
| 830 | } | 830 | } |
| 831 | 831 | ||
| 832 | #if 0 /* it's broken in some acses -- temporarily disabled */ | ||
| 832 | static void alc_mic_automute(struct hda_codec *codec) | 833 | static void alc_mic_automute(struct hda_codec *codec) |
| 833 | { | 834 | { |
| 834 | struct alc_spec *spec = codec->spec; | 835 | struct alc_spec *spec = codec->spec; |
| @@ -849,6 +850,9 @@ static void alc_mic_automute(struct hda_codec *codec) | |||
| 849 | snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, capsrc_idx_fmic, | 850 | snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, capsrc_idx_fmic, |
| 850 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); | 851 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); |
| 851 | } | 852 | } |
| 853 | #else | ||
| 854 | #define alc_mic_automute(codec) /* NOP */ | ||
| 855 | #endif /* disabled */ | ||
| 852 | 856 | ||
| 853 | /* unsolicited event for HP jack sensing */ | 857 | /* unsolicited event for HP jack sensing */ |
| 854 | static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res) | 858 | static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res) |
| @@ -1058,12 +1062,14 @@ do_sku: | |||
| 1058 | AC_VERB_SET_UNSOLICITED_ENABLE, | 1062 | AC_VERB_SET_UNSOLICITED_ENABLE, |
| 1059 | AC_USRSP_EN | ALC880_HP_EVENT); | 1063 | AC_USRSP_EN | ALC880_HP_EVENT); |
| 1060 | 1064 | ||
| 1065 | #if 0 /* it's broken in some acses -- temporarily disabled */ | ||
| 1061 | if (spec->autocfg.input_pins[AUTO_PIN_MIC] && | 1066 | if (spec->autocfg.input_pins[AUTO_PIN_MIC] && |
| 1062 | spec->autocfg.input_pins[AUTO_PIN_FRONT_MIC]) | 1067 | spec->autocfg.input_pins[AUTO_PIN_FRONT_MIC]) |
| 1063 | snd_hda_codec_write(codec, | 1068 | snd_hda_codec_write(codec, |
| 1064 | spec->autocfg.input_pins[AUTO_PIN_MIC], 0, | 1069 | spec->autocfg.input_pins[AUTO_PIN_MIC], 0, |
| 1065 | AC_VERB_SET_UNSOLICITED_ENABLE, | 1070 | AC_VERB_SET_UNSOLICITED_ENABLE, |
| 1066 | AC_USRSP_EN | ALC880_MIC_EVENT); | 1071 | AC_USRSP_EN | ALC880_MIC_EVENT); |
| 1072 | #endif /* disabled */ | ||
| 1067 | 1073 | ||
| 1068 | spec->unsol_event = alc_sku_unsol_event; | 1074 | spec->unsol_event = alc_sku_unsol_event; |
| 1069 | } | 1075 | } |
| @@ -8408,6 +8414,7 @@ static const char *alc883_models[ALC883_MODEL_LAST] = { | |||
| 8408 | static struct snd_pci_quirk alc883_cfg_tbl[] = { | 8414 | static struct snd_pci_quirk alc883_cfg_tbl[] = { |
| 8409 | SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC883_3ST_6ch_DIG), | 8415 | SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC883_3ST_6ch_DIG), |
| 8410 | SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_ACER_ASPIRE), | 8416 | SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_ACER_ASPIRE), |
| 8417 | SND_PCI_QUIRK(0x1025, 0x0090, "Acer Aspire", ALC883_ACER_ASPIRE), | ||
| 8411 | SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_ACER_ASPIRE), | 8418 | SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_ACER_ASPIRE), |
| 8412 | SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_ACER_ASPIRE), | 8419 | SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_ACER_ASPIRE), |
| 8413 | SND_PCI_QUIRK(0x1025, 0x0121, "Acer Aspire 5920G", ALC883_ACER_ASPIRE), | 8420 | SND_PCI_QUIRK(0x1025, 0x0121, "Acer Aspire 5920G", ALC883_ACER_ASPIRE), |
| @@ -12238,8 +12245,26 @@ static int alc269_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
| 12238 | return 0; | 12245 | return 0; |
| 12239 | } | 12246 | } |
| 12240 | 12247 | ||
| 12241 | #define alc269_auto_create_analog_input_ctls \ | 12248 | static int alc269_auto_create_analog_input_ctls(struct alc_spec *spec, |
| 12242 | alc880_auto_create_analog_input_ctls | 12249 | const struct auto_pin_cfg *cfg) |
| 12250 | { | ||
| 12251 | int err; | ||
| 12252 | |||
| 12253 | err = alc880_auto_create_analog_input_ctls(spec, cfg); | ||
| 12254 | if (err < 0) | ||
| 12255 | return err; | ||
| 12256 | /* digital-mic input pin is excluded in alc880_auto_create..() | ||
| 12257 | * because it's under 0x18 | ||
| 12258 | */ | ||
| 12259 | if (cfg->input_pins[AUTO_PIN_MIC] == 0x12 || | ||
| 12260 | cfg->input_pins[AUTO_PIN_FRONT_MIC] == 0x12) { | ||
| 12261 | struct hda_input_mux *imux = &spec->private_imux; | ||
| 12262 | imux->items[imux->num_items].label = "Int Mic"; | ||
| 12263 | imux->items[imux->num_items].index = 0x05; | ||
| 12264 | imux->num_items++; | ||
| 12265 | } | ||
| 12266 | return 0; | ||
| 12267 | } | ||
| 12243 | 12268 | ||
| 12244 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 12269 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
| 12245 | #define alc269_loopbacks alc880_loopbacks | 12270 | #define alc269_loopbacks alc880_loopbacks |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index df9b0bc7f878..e6085915d86d 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
| @@ -69,6 +69,7 @@ enum { | |||
| 69 | enum { | 69 | enum { |
| 70 | STAC_92HD73XX_REF, | 70 | STAC_92HD73XX_REF, |
| 71 | STAC_DELL_M6, | 71 | STAC_DELL_M6, |
| 72 | STAC_DELL_EQ, | ||
| 72 | STAC_92HD73XX_MODELS | 73 | STAC_92HD73XX_MODELS |
| 73 | }; | 74 | }; |
| 74 | 75 | ||
| @@ -773,9 +774,7 @@ static struct hda_verb dell_eq_core_init[] = { | |||
| 773 | }; | 774 | }; |
| 774 | 775 | ||
| 775 | static struct hda_verb dell_m6_core_init[] = { | 776 | static struct hda_verb dell_m6_core_init[] = { |
| 776 | /* set master volume to max value without distortion | 777 | { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, |
| 777 | * and direct control */ | ||
| 778 | { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xec}, | ||
| 779 | /* setup audio connections */ | 778 | /* setup audio connections */ |
| 780 | { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00}, | 779 | { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00}, |
| 781 | { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x01}, | 780 | { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x01}, |
| @@ -1600,11 +1599,13 @@ static unsigned int dell_m6_pin_configs[13] = { | |||
| 1600 | static unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = { | 1599 | static unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = { |
| 1601 | [STAC_92HD73XX_REF] = ref92hd73xx_pin_configs, | 1600 | [STAC_92HD73XX_REF] = ref92hd73xx_pin_configs, |
| 1602 | [STAC_DELL_M6] = dell_m6_pin_configs, | 1601 | [STAC_DELL_M6] = dell_m6_pin_configs, |
| 1602 | [STAC_DELL_EQ] = dell_m6_pin_configs, | ||
| 1603 | }; | 1603 | }; |
| 1604 | 1604 | ||
| 1605 | static const char *stac92hd73xx_models[STAC_92HD73XX_MODELS] = { | 1605 | static const char *stac92hd73xx_models[STAC_92HD73XX_MODELS] = { |
| 1606 | [STAC_92HD73XX_REF] = "ref", | 1606 | [STAC_92HD73XX_REF] = "ref", |
| 1607 | [STAC_DELL_M6] = "dell-m6", | 1607 | [STAC_DELL_M6] = "dell-m6", |
| 1608 | [STAC_DELL_EQ] = "dell-eq", | ||
| 1608 | }; | 1609 | }; |
| 1609 | 1610 | ||
| 1610 | static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = { | 1611 | static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = { |
| @@ -4131,12 +4132,17 @@ again: | |||
| 4131 | sizeof(stac92hd73xx_dmux)); | 4132 | sizeof(stac92hd73xx_dmux)); |
| 4132 | 4133 | ||
| 4133 | switch (spec->board_config) { | 4134 | switch (spec->board_config) { |
| 4134 | case STAC_DELL_M6: | 4135 | case STAC_DELL_EQ: |
| 4135 | spec->init = dell_eq_core_init; | 4136 | spec->init = dell_eq_core_init; |
| 4137 | /* fallthru */ | ||
| 4138 | case STAC_DELL_M6: | ||
| 4136 | spec->num_smuxes = 0; | 4139 | spec->num_smuxes = 0; |
| 4137 | spec->mixer = &stac92hd73xx_6ch_mixer[DELL_M6_MIXER]; | 4140 | spec->mixer = &stac92hd73xx_6ch_mixer[DELL_M6_MIXER]; |
| 4138 | spec->amp_nids = &stac92hd73xx_amp_nids[DELL_M6_AMP]; | 4141 | spec->amp_nids = &stac92hd73xx_amp_nids[DELL_M6_AMP]; |
| 4139 | spec->num_amps = 1; | 4142 | spec->num_amps = 1; |
| 4143 | |||
| 4144 | if (!spec->init) | ||
| 4145 | spec->init = dell_m6_core_init; | ||
| 4140 | switch (codec->subsystem_id) { | 4146 | switch (codec->subsystem_id) { |
| 4141 | case 0x1028025e: /* Analog Mics */ | 4147 | case 0x1028025e: /* Analog Mics */ |
| 4142 | case 0x1028025f: | 4148 | case 0x1028025f: |
| @@ -4146,8 +4152,6 @@ again: | |||
| 4146 | break; | 4152 | break; |
| 4147 | case 0x10280271: /* Digital Mics */ | 4153 | case 0x10280271: /* Digital Mics */ |
| 4148 | case 0x10280272: | 4154 | case 0x10280272: |
| 4149 | spec->init = dell_m6_core_init; | ||
| 4150 | /* fall-through */ | ||
| 4151 | case 0x10280254: | 4155 | case 0x10280254: |
| 4152 | case 0x10280255: | 4156 | case 0x10280255: |
| 4153 | stac92xx_set_config_reg(codec, 0x13, 0x90A60160); | 4157 | stac92xx_set_config_reg(codec, 0x13, 0x90A60160); |
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index a3adbf06b1e5..16c7453f4946 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
| @@ -95,8 +95,8 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec) | |||
| 95 | codec->ac97->dev.parent = NULL; | 95 | codec->ac97->dev.parent = NULL; |
| 96 | codec->ac97->dev.release = soc_ac97_device_release; | 96 | codec->ac97->dev.release = soc_ac97_device_release; |
| 97 | 97 | ||
| 98 | snprintf(codec->ac97->dev.bus_id, BUS_ID_SIZE, "%d-%d:%s", | 98 | dev_set_name(&codec->ac97->dev, "%d-%d:%s", |
| 99 | codec->card->number, 0, codec->name); | 99 | codec->card->number, 0, codec->name); |
| 100 | err = device_register(&codec->ac97->dev); | 100 | err = device_register(&codec->ac97->dev); |
| 101 | if (err < 0) { | 101 | if (err < 0) { |
| 102 | snd_printk(KERN_ERR "Can't register ac97 bus\n"); | 102 | snd_printk(KERN_ERR "Can't register ac97 bus\n"); |
