From 3044646148cdfa83a311bf1c146a70e550280159 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Sun, 9 Nov 2008 10:07:58 -0800 Subject: [PATCH 001/107] x86: move iomap.h to the new include location a new file was accidentally added to include/asm-x86; move it to the new arch/x86/include/asm location Signed-off-by: Arjan van de Ven --- {include/asm-x86 => arch/x86/include/asm}/iomap.h | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {include/asm-x86 => arch/x86/include/asm}/iomap.h (100%) diff --git a/include/asm-x86/iomap.h b/arch/x86/include/asm/iomap.h similarity index 100% rename from include/asm-x86/iomap.h rename to arch/x86/include/asm/iomap.h From 6cd10f8db385ba547811baa5b26f672fdff232e6 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sun, 9 Nov 2008 11:53:14 -0600 Subject: [PATCH 002/107] x86, voyager: fix smp generic helper voyager breakage Impact: build/boot fix for x86/Voyager This change: | commit 3d4422332711ef48ef0f132f1fcbfcbd56c7f3d1 | Author: Jens Axboe | Date: Thu Jun 26 11:21:34 2008 +0200 | | Add generic helpers for arch IPI function calls didn't wire up the voyager smp call function correctly, so do that here. Also make CONFIG_USE_GENERIC_SMP_HELPERS a def_bool y again, since we now use the generic helpers for every x86 architecture. Signed-off-by: James Bottomley Cc: Jens Axboe Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 5 ++++- arch/x86/mach-voyager/voyager_smp.c | 16 ++++++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 4cf0ab13d187..ac22bb7719f7 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -167,9 +167,12 @@ config GENERIC_PENDING_IRQ config X86_SMP bool depends on SMP && ((X86_32 && !X86_VOYAGER) || X86_64) - select USE_GENERIC_SMP_HELPERS default y +config USE_GENERIC_SMP_HELPERS + def_bool y + depends on SMP + config X86_32_SMP def_bool y depends on X86_32 && SMP diff --git a/arch/x86/mach-voyager/voyager_smp.c b/arch/x86/mach-voyager/voyager_smp.c index 0e331652681e..52145007bd7e 100644 --- a/arch/x86/mach-voyager/voyager_smp.c +++ b/arch/x86/mach-voyager/voyager_smp.c @@ -7,6 +7,7 @@ * This file provides all the same external entries as smp.c but uses * the voyager hal to provide the functionality */ +#include #include #include #include @@ -1790,6 +1791,17 @@ void __init smp_setup_processor_id(void) x86_write_percpu(cpu_number, hard_smp_processor_id()); } +static void voyager_send_call_func(cpumask_t callmask) +{ + __u32 mask = cpus_addr(callmask)[0] & ~(1 << smp_processor_id()); + send_CPI(mask, VIC_CALL_FUNCTION_CPI); +} + +static void voyager_send_call_func_single(int cpu) +{ + send_CPI(1 << cpu, VIC_CALL_FUNCTION_SINGLE_CPI); +} + struct smp_ops smp_ops = { .smp_prepare_boot_cpu = voyager_smp_prepare_boot_cpu, .smp_prepare_cpus = voyager_smp_prepare_cpus, @@ -1799,6 +1811,6 @@ struct smp_ops smp_ops = { .smp_send_stop = voyager_smp_send_stop, .smp_send_reschedule = voyager_smp_send_reschedule, - .send_call_func_ipi = native_send_call_func_ipi, - .send_call_func_single_ipi = native_send_call_func_single_ipi, + .send_call_func_ipi = voyager_send_call_func, + .send_call_func_single_ipi = voyager_send_call_func_single, }; From 97a70e548bd97d5a46ae9d44f24aafcc013fd701 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 12 Nov 2008 23:22:35 +0100 Subject: [PATCH 003/107] x86, hibernate: fix breakage on x86_32 with CONFIG_NUMA set Impact: fix crash during hibernation on 32-bit NUMA The NUMA code on x86_32 creates special memory mapping that allows each node's pgdat to be located in this node's memory. For this purpose it allocates a memory area at the end of each node's memory and maps this area so that it is accessible with virtual addresses belonging to low memory. As a result, if there is high memory, these NUMA-allocated areas are physically located in high memory, although they are mapped to low memory addresses. Our hibernation code does not take that into account and for this reason hibernation fails on all x86_32 systems with CONFIG_NUMA=y and with high memory present. Fix this by adding a special mapping for the NUMA-allocated memory areas to the temporary page tables created during the last phase of resume. Signed-off-by: Rafael J. Wysocki Signed-off-by: Ingo Molnar --- arch/x86/include/asm/mmzone_32.h | 4 ++++ arch/x86/mm/numa_32.c | 35 ++++++++++++++++++++++++++++++++ arch/x86/power/hibernate_32.c | 4 ++++ 3 files changed, 43 insertions(+) diff --git a/arch/x86/include/asm/mmzone_32.h b/arch/x86/include/asm/mmzone_32.h index 485bdf059ffb..07f1af494ca5 100644 --- a/arch/x86/include/asm/mmzone_32.h +++ b/arch/x86/include/asm/mmzone_32.h @@ -34,10 +34,14 @@ static inline void get_memcfg_numa(void) extern int early_pfn_to_nid(unsigned long pfn); +extern void resume_map_numa_kva(pgd_t *pgd); + #else /* !CONFIG_NUMA */ #define get_memcfg_numa get_memcfg_numa_flat +static inline void resume_map_numa_kva(pgd_t *pgd) {} + #endif /* CONFIG_NUMA */ #ifdef CONFIG_DISCONTIGMEM diff --git a/arch/x86/mm/numa_32.c b/arch/x86/mm/numa_32.c index 847c164725f4..8518c678d83f 100644 --- a/arch/x86/mm/numa_32.c +++ b/arch/x86/mm/numa_32.c @@ -222,6 +222,41 @@ static void __init remap_numa_kva(void) } } +#ifdef CONFIG_HIBERNATION +/** + * resume_map_numa_kva - add KVA mapping to the temporary page tables created + * during resume from hibernation + * @pgd_base - temporary resume page directory + */ +void resume_map_numa_kva(pgd_t *pgd_base) +{ + int node; + + for_each_online_node(node) { + unsigned long start_va, start_pfn, size, pfn; + + start_va = (unsigned long)node_remap_start_vaddr[node]; + start_pfn = node_remap_start_pfn[node]; + size = node_remap_size[node]; + + printk(KERN_DEBUG "%s: node %d\n", __FUNCTION__, node); + + for (pfn = 0; pfn < size; pfn += PTRS_PER_PTE) { + unsigned long vaddr = start_va + (pfn << PAGE_SHIFT); + pgd_t *pgd = pgd_base + pgd_index(vaddr); + pud_t *pud = pud_offset(pgd, vaddr); + pmd_t *pmd = pmd_offset(pud, vaddr); + + set_pmd(pmd, pfn_pmd(start_pfn + pfn, + PAGE_KERNEL_LARGE_EXEC)); + + printk(KERN_DEBUG "%s: %08lx -> pfn %08lx\n", + __FUNCTION__, vaddr, start_pfn + pfn); + } + } +} +#endif + static unsigned long calculate_numa_remap_pages(void) { int nid; diff --git a/arch/x86/power/hibernate_32.c b/arch/x86/power/hibernate_32.c index f2b6e3f11bfc..81197c62d5b3 100644 --- a/arch/x86/power/hibernate_32.c +++ b/arch/x86/power/hibernate_32.c @@ -12,6 +12,7 @@ #include #include #include +#include /* Defined in hibernate_asm_32.S */ extern int restore_image(void); @@ -127,6 +128,9 @@ static int resume_physical_mapping_init(pgd_t *pgd_base) } } } + + resume_map_numa_kva(pgd_base); + return 0; } From 604d20554883cf03f888440d58ea7c6d36899839 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 12 Nov 2008 23:26:14 +0100 Subject: [PATCH 004/107] x86: make NUMA on 32-bit depend on EXPERIMENTAL again My previous patch to make CONFIG_NUMA on x86_32 depend on BROKEN turned out to be unnecessary, after all, since the source of the hibernation vs CONFIG_NUMA problem turned out to be the fact that we didn't take the NUMA KVA remapping into account in the hibernation code. Signed-off-by: Rafael J. Wysocki Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 93224b569187..4cf0ab13d187 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -957,7 +957,7 @@ config ARCH_PHYS_ADDR_T_64BIT config NUMA bool "Numa Memory Allocation and Scheduler Support (EXPERIMENTAL)" depends on SMP - depends on X86_64 || (X86_32 && HIGHMEM64G && (X86_NUMAQ || X86_BIGSMP || X86_SUMMIT && ACPI) && BROKEN) + depends on X86_64 || (X86_32 && HIGHMEM64G && (X86_NUMAQ || X86_BIGSMP || X86_SUMMIT && ACPI) && EXPERIMENTAL) default n if X86_PC default y if (X86_NUMAQ || X86_SUMMIT || X86_BIGSMP) help From d1f1e9c01006b4b050e090055c75278f80c2a5c5 Mon Sep 17 00:00:00 2001 From: Markus Metzger Date: Sat, 15 Nov 2008 11:00:17 +0100 Subject: [PATCH 005/107] x86, bts: fix unlock problem in ds.c Fix a problem where ds_request() returned an error without releasing the ds lock. Reported-by: Stephane Eranian Signed-off-by: Markus Metzger Cc: Signed-off-by: Ingo Molnar --- arch/x86/kernel/ds.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/ds.c b/arch/x86/kernel/ds.c index 2b69994fd3a8..ac1d5b0586ba 100644 --- a/arch/x86/kernel/ds.c +++ b/arch/x86/kernel/ds.c @@ -384,8 +384,9 @@ static int ds_request(struct task_struct *task, void *base, size_t size, spin_lock(&ds_lock); + error = -EPERM; if (!check_tracer(task)) - return -EPERM; + goto out_unlock; error = -ENOMEM; context = ds_alloc_context(task); From d3c6aa1e69f705ac3ab64584101b1d38435b1353 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sun, 16 Nov 2008 00:49:31 -0800 Subject: [PATCH 006/107] x86: fix es7000 compiling Impact: fix es7000 build CC arch/x86/kernel/es7000_32.o arch/x86/kernel/es7000_32.c: In function find_unisys_acpi_oem_table: arch/x86/kernel/es7000_32.c:255: error: implicit declaration of function acpi_get_table_with_size arch/x86/kernel/es7000_32.c:261: error: implicit declaration of function early_acpi_os_unmap_memory arch/x86/kernel/es7000_32.c: In function unmap_unisys_acpi_oem_table: arch/x86/kernel/es7000_32.c:277: error: implicit declaration of function __acpi_unmap_table make[1]: *** [arch/x86/kernel/es7000_32.o] Error 1 we applied one patch out of order... | commit a73aaedd95703bd49f4c3f9df06fb7b7373ba905 | Author: Yinghai Lu | Date: Sun Sep 14 02:33:14 2008 -0700 | | x86: check dsdt before find oem table for es7000, v2 | | v2: use __acpi_unmap_table() that patch need: x86: use early_ioremap in __acpi_map_table x86: always explicitly map acpi memory acpi: remove final __acpi_map_table mapping before setting acpi_gbl_permanent_mmap acpi/x86: introduce __apci_map_table, v4 submitted to the ACPI tree but not upstream yet. fix it until those patches applied, need to revert this one Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/es7000_32.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/arch/x86/kernel/es7000_32.c b/arch/x86/kernel/es7000_32.c index f454c78fcef6..0aa2c443d600 100644 --- a/arch/x86/kernel/es7000_32.c +++ b/arch/x86/kernel/es7000_32.c @@ -250,31 +250,24 @@ int __init find_unisys_acpi_oem_table(unsigned long *oem_addr) { struct acpi_table_header *header = NULL; int i = 0; - acpi_size tbl_size; - while (ACPI_SUCCESS(acpi_get_table_with_size("OEM1", i++, &header, &tbl_size))) { + while (ACPI_SUCCESS(acpi_get_table("OEM1", i++, &header))) { if (!memcmp((char *) &header->oem_id, "UNISYS", 6)) { struct oem_table *t = (struct oem_table *)header; oem_addrX = t->OEMTableAddr; oem_size = t->OEMTableSize; - early_acpi_os_unmap_memory(header, tbl_size); *oem_addr = (unsigned long)__acpi_map_table(oem_addrX, oem_size); return 0; } - early_acpi_os_unmap_memory(header, tbl_size); } return -1; } void __init unmap_unisys_acpi_oem_table(unsigned long oem_addr) { - if (!oem_addr) - return; - - __acpi_unmap_table((char *)oem_addr, oem_size); } #endif From 26a3e99160cfb06a0a33e25b9fb0d516e2cc680d Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Mon, 17 Nov 2008 09:35:00 -0800 Subject: [PATCH 007/107] xen: fix scrub_page() Impact: fix guest kernel crash with CONFIG_XEN_SCRUB_PAGES=y Jens noticed that scrub_page() has a buggy unmap of the wrong thing. (virtual address instead of page) Linus pointed out that the whole scrub_page() code is an unnecessary reimplementation of clear_highpage() to begin with. Just use clear_highpage() rather than reimplementing it poorly. Reported-by: Jens Axboe Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- drivers/xen/balloon.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index a0fb5eac407c..526c191e84ea 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -122,14 +122,7 @@ static struct timer_list balloon_timer; static void scrub_page(struct page *page) { #ifdef CONFIG_XEN_SCRUB_PAGES - if (PageHighMem(page)) { - void *v = kmap(page); - clear_page(v); - kunmap(v); - } else { - void *v = page_address(page); - clear_page(v); - } + clear_highpage(page); #endif } From 93ce99e849433ede4ce8b410b749dc0cad1100b2 Mon Sep 17 00:00:00 2001 From: Venki Pallipadi Date: Mon, 17 Nov 2008 14:43:58 -0800 Subject: [PATCH 008/107] x86: add rdtsc barrier to TSC sync check Impact: fix incorrectly marked unstable TSC clock Patch (commit 0d12cdd "sched: improve sched_clock() performance") has a regression on one of the test systems here. With the patch, I see: checking TSC synchronization [CPU#0 -> CPU#1]: Measured 28 cycles TSC warp between CPUs, turning off TSC clock. Marking TSC unstable due to check_tsc_sync_source failed Whereas, without the patch syncs pass fine on all CPUs: checking TSC synchronization [CPU#0 -> CPU#1]: passed. Due to this, TSC is marked unstable, when it is not actually unstable. This is because syncs in check_tsc_wrap() goes away due to this commit. As per the discussion on this thread, correct way to fix this is to add explicit syncs as below? Signed-off-by: Venkatesh Pallipadi Signed-off-by: Ingo Molnar --- arch/x86/kernel/tsc_sync.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/x86/kernel/tsc_sync.c b/arch/x86/kernel/tsc_sync.c index 9ffb01c31c40..1c0dfbca87c1 100644 --- a/arch/x86/kernel/tsc_sync.c +++ b/arch/x86/kernel/tsc_sync.c @@ -46,7 +46,9 @@ static __cpuinit void check_tsc_warp(void) cycles_t start, now, prev, end; int i; + rdtsc_barrier(); start = get_cycles(); + rdtsc_barrier(); /* * The measurement runs for 20 msecs: */ @@ -61,7 +63,9 @@ static __cpuinit void check_tsc_warp(void) */ __raw_spin_lock(&sync_lock); prev = last_tsc; + rdtsc_barrier(); now = get_cycles(); + rdtsc_barrier(); last_tsc = now; __raw_spin_unlock(&sync_lock); From 10db4ef7b9a65b86e4d047671a1886f4c101a859 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 18 Nov 2008 15:23:08 +0100 Subject: [PATCH 009/107] x86, PEBS/DS: fix code flow in ds_request() this compiler warning: arch/x86/kernel/ds.c: In function 'ds_request': arch/x86/kernel/ds.c:368: warning: 'context' may be used uninitialized in this function Shows that the code flow in ds_request() is buggy - it goes into the unlock+release-context path even when the context is not allocated yet. First allocate the context, then do the other checks. Also, take care with GFP allocations under the ds_lock spinlock. Cc: Signed-off-by: Ingo Molnar --- arch/x86/kernel/ds.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/ds.c b/arch/x86/kernel/ds.c index ac1d5b0586ba..d1a121443bde 100644 --- a/arch/x86/kernel/ds.c +++ b/arch/x86/kernel/ds.c @@ -236,17 +236,33 @@ static inline struct ds_context *ds_alloc_context(struct task_struct *task) struct ds_context *context = *p_context; if (!context) { + spin_unlock(&ds_lock); + context = kzalloc(sizeof(*context), GFP_KERNEL); - if (!context) + if (!context) { + spin_lock(&ds_lock); return NULL; + } context->ds = kzalloc(ds_cfg.sizeof_ds, GFP_KERNEL); if (!context->ds) { kfree(context); + spin_lock(&ds_lock); return NULL; } + spin_lock(&ds_lock); + /* + * Check for race - another CPU could have allocated + * it meanwhile: + */ + if (*p_context) { + kfree(context->ds); + kfree(context); + return *p_context; + } + *p_context = context; context->this = p_context; @@ -384,15 +400,15 @@ static int ds_request(struct task_struct *task, void *base, size_t size, spin_lock(&ds_lock); - error = -EPERM; - if (!check_tracer(task)) - goto out_unlock; - error = -ENOMEM; context = ds_alloc_context(task); if (!context) goto out_unlock; + error = -EPERM; + if (!check_tracer(task)) + goto out_unlock; + error = -EALREADY; if (context->owner[qual] == current) goto out_unlock; From e5e1f606ecbf67e52ebe2df5d14f8b94ec6544d0 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Mon, 17 Nov 2008 15:07:17 +0100 Subject: [PATCH 010/107] AMD IOMMU: add parameter to disable device isolation Impact: add a new AMD IOMMU kernel command line parameter Signed-off-by: Joerg Roedel --- Documentation/kernel-parameters.txt | 2 ++ arch/x86/kernel/amd_iommu_init.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 9fa6508892c2..b56ee02d2514 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -295,6 +295,8 @@ and is between 256 and 4096 characters. It is defined in the file isolate - enable device isolation (each device, as far as possible, will get its own protection domain) + share - put every device behind one IOMMU into the + same protection domain fullflush - enable flushing of IO/TLB entries when they are unmapped. Otherwise they are flushed before they will be reused, which diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index 0cdcda35a05f..838a2e1d5bb2 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -1213,6 +1213,8 @@ static int __init parse_amd_iommu_options(char *str) for (; *str; ++str) { if (strncmp(str, "isolate", 7) == 0) amd_iommu_isolate = 1; + if (strncmp(str, "share", 5) == 0) + amd_iommu_isolate = 0; if (strncmp(str, "fullflush", 11) == 0) amd_iommu_unmap_flush = true; } From 3ce1f93c6d53c3f91c3846cf66b018276c8ac2e7 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Mon, 17 Nov 2008 15:09:20 +0100 Subject: [PATCH 011/107] AMD IOMMU: enable device isolation per default Impact: makes device isolation the default for AMD IOMMU Some device drivers showed double-free bugs of DMA memory while testing them with AMD IOMMU. If all devices share the same protection domain this can lead to data corruption and data loss. Prevent this by putting each device into its own protection domain per default. Signed-off-by: Joerg Roedel --- Documentation/kernel-parameters.txt | 2 +- arch/x86/kernel/amd_iommu_init.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index b56ee02d2514..f2e1e7fc0ffd 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -294,7 +294,7 @@ and is between 256 and 4096 characters. It is defined in the file Possible values are: isolate - enable device isolation (each device, as far as possible, will get its own protection - domain) + domain) [default] share - put every device behind one IOMMU into the same protection domain fullflush - enable flushing of IO/TLB entries when diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index 838a2e1d5bb2..595edd2befc6 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -121,7 +121,7 @@ u16 amd_iommu_last_bdf; /* largest PCI device id we have LIST_HEAD(amd_iommu_unity_map); /* a list of required unity mappings we find in ACPI */ unsigned amd_iommu_aperture_order = 26; /* size of aperture in power of 2 */ -int amd_iommu_isolate; /* if 1, device isolation is enabled */ +int amd_iommu_isolate = 1; /* if 1, device isolation is enabled */ bool amd_iommu_unmap_flush; /* if true, flush on every unmap */ LIST_HEAD(amd_iommu_list); /* list of all AMD IOMMUs in the From 695b5676c727d80921a2dc8737d5b3322222db85 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Mon, 17 Nov 2008 15:16:43 +0100 Subject: [PATCH 012/107] AMD IOMMU: fix fullflush comparison length Impact: fix comparison length for 'fullflush' Signed-off-by: Joerg Roedel --- arch/x86/kernel/amd_iommu_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index 595edd2befc6..30ae2701b3df 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -1215,7 +1215,7 @@ static int __init parse_amd_iommu_options(char *str) amd_iommu_isolate = 1; if (strncmp(str, "share", 5) == 0) amd_iommu_isolate = 0; - if (strncmp(str, "fullflush", 11) == 0) + if (strncmp(str, "fullflush", 9) == 0) amd_iommu_unmap_flush = true; } From 8501c45cc32c311ae755a2d5ac8c4a5f04908d42 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Mon, 17 Nov 2008 19:11:46 +0100 Subject: [PATCH 013/107] AMD IOMMU: check for next_bit also in unmapped area Impact: fix possible use of stale IO/TLB entries Signed-off-by: Joerg Roedel --- arch/x86/kernel/amd_iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index 331b318304eb..e4899e0e8787 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -537,7 +537,7 @@ static void dma_ops_free_addresses(struct dma_ops_domain *dom, address >>= PAGE_SHIFT; iommu_area_free(dom->bitmap, address, pages); - if (address + pages >= dom->next_bit) + if (address >= dom->next_bit) dom->need_flush = true; } From 0af40a4b1050c050e62eb1dc30b82d5ab22bf221 Mon Sep 17 00:00:00 2001 From: Philipp Kohlbecher Date: Sun, 16 Nov 2008 12:11:01 +0100 Subject: [PATCH 014/107] x86: more general identifier for Phoenix BIOS Impact: widen the reach of the low-memory-protect DMI quirk Phoenix BIOSes variously identify their vendor as "Phoenix Technologies, LTD" or "Phoenix Technologies LTD" (without the comma.) This patch makes the identification string in the bad_bios_dmi_table more general (following a suggestion by Ingo Molnar), so that both versions are handled. Again, the patched file compiles cleanly and the patch has been tested successfully on my machine. Signed-off-by: Philipp Kohlbecher Cc: Signed-off-by: Ingo Molnar --- arch/x86/kernel/setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 0fa6790c1dd3..9d5674f7b6cc 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -764,7 +764,7 @@ static struct dmi_system_id __initdata bad_bios_dmi_table[] = { .callback = dmi_low_memory_corruption, .ident = "Phoenix BIOS", .matches = { - DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies, LTD"), + DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies"), }, }, #endif From 0bb943c7a2136716757a263f604d26309fd98042 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 14 Nov 2008 19:05:31 +0100 Subject: [PATCH 015/107] tracing: kernel/trace/trace.c: introduce missing kfree() Impact: fix memory leak Error handling code following a kzalloc should free the allocated data. The semantic match that finds the problem is as follows: (http://www.emn.fr/x-info/coccinelle/) // @r exists@ local idexpression x; statement S; expression E; identifier f,l; position p1,p2; expression *ptr != NULL; @@ ( if ((x@p1 = \(kmalloc\|kzalloc\|kcalloc\)(...)) == NULL) S | x@p1 = \(kmalloc\|kzalloc\|kcalloc\)(...); ... if (x == NULL) S ) <... when != x when != if (...) { <+...x...+> } x->f = E ...> ( return \(0\|<+...x...+>\|ptr\); | return@p2 ...; ) @script:python@ p1 << r.p1; p2 << r.p2; @@ print "* file: %s kmalloc %s return %s" % (p1[0].file,p1[0].line,p2[0].line) // Signed-off-by: Julia Lawall Signed-off-by: Steven Rostedt Signed-off-by: Ingo Molnar --- kernel/trace/trace.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 697eda36b86a..d86e3252f300 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -1936,6 +1936,7 @@ __tracing_open(struct inode *inode, struct file *file, int *ret) ring_buffer_read_finish(iter->buffer_iter[cpu]); } mutex_unlock(&trace_types_lock); + kfree(iter); return ERR_PTR(-ENOMEM); } From 66359f849074c55fb80d15235ea5b99f1918663c Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 18 Nov 2008 15:12:42 +0800 Subject: [PATCH 016/107] Parport driver: disable pc-style parport on Blackfin systems Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu Signed-off-by: Linus Torvalds --- drivers/parport/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig index 209b4a464bcf..855f389eea40 100644 --- a/drivers/parport/Kconfig +++ b/drivers/parport/Kconfig @@ -36,7 +36,7 @@ if PARPORT config PARPORT_PC tristate "PC-style hardware" depends on (!SPARC64 || PCI) && !SPARC32 && !M32R && !FRV && \ - (!M68K || ISA) && !MN10300 && !AVR32 + (!M68K || ISA) && !MN10300 && !AVR32 && !BLACKFIN ---help--- You should say Y here if you have a PC-style parallel port. All IBM PC compatible computers and some Alphas have PC-style From bfb59820ee46616a7bdb4af6b8f7e109646de6ec Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 18 Nov 2008 16:33:48 +0000 Subject: [PATCH 017/107] [CIFS] fix check for dead tcon in smb_init This was recently changed to check for need_reconnect, but should actually be a check for a tidStatus of CifsExiting. Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/CHANGES | 6 +++++- fs/cifs/cifssmb.c | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 8855331b2fba..e078b7aea143 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -8,7 +8,11 @@ handling fcntl(F_SETLEASE). Convert cifs to using blocking tcp sends, and also let tcp autotune the socket send and receive buffers. This reduces the number of EAGAIN errors returned by TCP/IP in high stress workloads (and the number of retries on socket writes -when sending large SMBWriteX requests). +when sending large SMBWriteX requests). Fix case in which a portion of +data can in some cases not get written to the file on the server before the +file is closed. Fix DFS parsing to properly handle path consumed field, +and to handle certain codepage conversions better. Fix mount and +umount race that can cause oops in mount or umount or reconnect. Version 1.54 ------------ diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index bdda46dd435a..2af8626ced43 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -295,7 +295,7 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, check for tcp and smb session status done differently for those three - in the calling routine */ if (tcon) { - if (tcon->need_reconnect) { + if (tcon->tidStatus == CifsExiting) { /* only tree disconnect, open, and write, (and ulogoff which does not have tcon) are allowed as we start force umount */ From 641d2f63cfe24539e154efa2f932937934c27dde Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Tue, 18 Nov 2008 19:22:13 +0100 Subject: [PATCH 018/107] trace: introduce missing mutex_unlock() Impact: fix tracing buffer mutex leak in case of allocation failure This error was spotted by this semantic patch: http://www.emn.fr/x-info/coccinelle/mut.html It looks correct as far as I can tell. Please review. Signed-off-by: Vegard Nossum Signed-off-by: Steven Rostedt Signed-off-by: Ingo Molnar --- kernel/trace/ring_buffer.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 036456cbb4f7..f780e9552f91 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -617,6 +617,7 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size) list_del_init(&page->list); free_buffer_page(page); } + mutex_unlock(&buffer->mutex); return -ENOMEM; } From 093bac154c142fa1fb31a3ac69ae1bc08930231b Mon Sep 17 00:00:00 2001 From: Steve Conklin Date: Fri, 14 Nov 2008 00:55:51 -0600 Subject: [PATCH 019/107] x86: quirk for reboot stalls on a Dell Optiplex 330 Dell Optiplex 330 appears to hang on reboot. This is resolved by adding a quirk to set bios reboot. Signed-off-by: Leann Ogasawara Signed-off-by: Steve Conklin Signed-off-by: Ingo Molnar --- arch/x86/kernel/reboot.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 724adfc63cb9..cc5a2545dd41 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -169,6 +169,15 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = { DMI_MATCH(DMI_BOARD_NAME, "0KW626"), }, }, + { /* Handle problems with rebooting on Dell Optiplex 330 with 0KP561 */ + .callback = set_bios_reboot, + .ident = "Dell OptiPlex 330", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 330"), + DMI_MATCH(DMI_BOARD_NAME, "0KP561"), + }, + }, { /* Handle problems with rebooting on Dell 2400's */ .callback = set_bios_reboot, .ident = "Dell PowerEdge 2400", From 20a4a236c7de5c915551cdc562482aa53eaff40e Mon Sep 17 00:00:00 2001 From: Hiroshi Shimamoto Date: Thu, 13 Nov 2008 18:06:04 -0800 Subject: [PATCH 020/107] x86: uaccess_64: fix return value in __copy_from_user() __copy_from_user() will return invalid value 16 when it fails to access user space and the size is 10. Signed-off-by: Hiroshi Shimamoto Signed-off-by: Ingo Molnar --- arch/x86/include/asm/uaccess_64.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/include/asm/uaccess_64.h b/arch/x86/include/asm/uaccess_64.h index 664f15280f14..f8cfd00db450 100644 --- a/arch/x86/include/asm/uaccess_64.h +++ b/arch/x86/include/asm/uaccess_64.h @@ -46,7 +46,7 @@ int __copy_from_user(void *dst, const void __user *src, unsigned size) return ret; case 10: __get_user_asm(*(u64 *)dst, (u64 __user *)src, - ret, "q", "", "=r", 16); + ret, "q", "", "=r", 10); if (unlikely(ret)) return ret; __get_user_asm(*(u16 *)(8 + (char *)dst), From 9b44fb89cab6e01816cdc05d6b59fdcf8100b8c3 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 29 Oct 2008 23:24:14 +0100 Subject: [PATCH 021/107] libertas_tf: fix skb tail pointer skb->tail can't be meant here because it's not the same across 32/64 bit compilations. This means there's no way the current driver can work on 64-bit architectures. Signed-off-by: Johannes Berg Cc: stable@kernel.org [2.6.27] Signed-off-by: John W. Linville --- drivers/net/wireless/libertas_tf/if_usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/libertas_tf/if_usb.c b/drivers/net/wireless/libertas_tf/if_usb.c index 1cc03a8dd67a..59634c33b1f9 100644 --- a/drivers/net/wireless/libertas_tf/if_usb.c +++ b/drivers/net/wireless/libertas_tf/if_usb.c @@ -331,7 +331,7 @@ static int __if_usb_submit_rx_urb(struct if_usb_card *cardp, /* Fill the receive configuration URB and initialise the Rx call back */ usb_fill_bulk_urb(cardp->rx_urb, cardp->udev, usb_rcvbulkpipe(cardp->udev, cardp->ep_in), - (void *) (skb->tail), + skb_tail_pointer(skb), MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, callbackfn, cardp); cardp->rx_urb->transfer_flags |= URB_ZERO_PACKET; From 8e3bad65a59915f2ddc40f62a180ad81695d8440 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 17 Nov 2008 10:59:59 +0100 Subject: [PATCH 022/107] mac80211: remove ieee80211_notify_mac Before ieee80211_notify_mac() was added, it was presented with the use case of using it to tell mac80211 that the association may have been lost because the firmware crashed/reset. Since then, it has also been used by iwlwifi to (slightly) speed up re-association after resume, a workaround around the fact that mac80211 has no suspend/resume handling yet. It is also not used by any other drivers, so clearly it cannot be necessary for "good enough" suspend/resume. Unfortunately, the callback suffers from a severe problem: It only works for station mode. If suspend/resume happens while in IBSS or any other mode (but station), then the callback is pointless. Recently, it has created a number of locking issues, first because it required rtnl locking rather than RCU due to calling sleeping functions within the critical section, and now because it's called by iwlwifi from the mac80211 workqueue that may not use the rtnl because it is flushed under rtnl. (cf. http://bugzilla.kernel.org/show_bug.cgi?id=12046) I think, therefore, that we should take a step back, remove it entirely for now and add the small feature it provided properly. For suspend and resume we will need to introduce new hooks, and for the case where the firmware was reset the driver will probably simply just pretend it has done a suspend/resume cycle to get mac80211 to reprogram the hardware completely, not just try to connect to the current AP again in station mode. When doing so, we will need to take into account locking issues and possibly defer to schedule_work from within mac80211 for the resume operation, while the suspend operation must be done directly. Proper suspend/resume should also not necessarily try to reconnect to the current AP, the time spent in suspend may have been short enough to not be disconnected from the AP, mac80211 will detect that the AP went out of range quickly if it did, and if the association is lost then the AP will disassoc as soon as a data frame is sent. We might also take into account WWOL then, and have mac80211 program the hardware into such a mode where it is available and requested. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 1 - drivers/net/wireless/iwlwifi/iwl3945-base.c | 1 - include/net/mac80211.h | 20 ------------------- net/mac80211/mlme.c | 22 --------------------- 4 files changed, 44 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 8d690a0eb1a9..6751bb2b8ae2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2341,7 +2341,6 @@ static void iwl_bg_alive_start(struct work_struct *data) mutex_lock(&priv->mutex); iwl_alive_start(priv); mutex_unlock(&priv->mutex); - ieee80211_notify_mac(priv->hw, IEEE80211_NOTIFY_RE_ASSOC); } static void iwl4965_bg_rf_kill(struct work_struct *work) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 285b53e7e261..45a6b0c35695 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -6012,7 +6012,6 @@ static void iwl3945_bg_alive_start(struct work_struct *data) mutex_lock(&priv->mutex); iwl3945_alive_start(priv); mutex_unlock(&priv->mutex); - ieee80211_notify_mac(priv->hw, IEEE80211_NOTIFY_RE_ASSOC); } static void iwl3945_bg_rf_kill(struct work_struct *work) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 8856e2d60e9f..73d81bc6aa75 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -73,14 +73,6 @@ * not do so then mac80211 may add this under certain circumstances. */ -/** - * enum ieee80211_notification_type - Low level driver notification - * @IEEE80211_NOTIFY_RE_ASSOC: start the re-association sequence - */ -enum ieee80211_notification_types { - IEEE80211_NOTIFY_RE_ASSOC, -}; - /** * struct ieee80211_ht_bss_info - describing BSS's HT characteristics * @@ -1797,18 +1789,6 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid); void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, const u8 *ra, u16 tid); -/** - * ieee80211_notify_mac - low level driver notification - * @hw: pointer as obtained from ieee80211_alloc_hw(). - * @notif_type: enum ieee80211_notification_types - * - * This function must be called by low level driver to inform mac80211 of - * low level driver status change or force mac80211 to re-assoc for low - * level driver internal error that require re-assoc. - */ -void ieee80211_notify_mac(struct ieee80211_hw *hw, - enum ieee80211_notification_types notif_type); - /** * ieee80211_find_sta - find a station * diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 14d165f0df75..409bb7716236 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2560,25 +2560,3 @@ void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local) ieee80211_restart_sta_timer(sdata); rcu_read_unlock(); } - -/* driver notification call */ -void ieee80211_notify_mac(struct ieee80211_hw *hw, - enum ieee80211_notification_types notif_type) -{ - struct ieee80211_local *local = hw_to_local(hw); - struct ieee80211_sub_if_data *sdata; - - switch (notif_type) { - case IEEE80211_NOTIFY_RE_ASSOC: - rtnl_lock(); - list_for_each_entry(sdata, &local->interfaces, list) { - if (sdata->vif.type != NL80211_IFTYPE_STATION) - continue; - - ieee80211_sta_req_auth(sdata, &sdata->u.sta); - } - rtnl_unlock(); - break; - } -} -EXPORT_SYMBOL(ieee80211_notify_mac); From 4018517a1a69a85c3d61b20fa02f187b80773137 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 18 Nov 2008 01:47:21 +0100 Subject: [PATCH 023/107] iwlagn: fix RX skb alignment So I dug deeper into the DMA problems I had with iwlagn and a kind soul helped me in that he said something about pci-e alignment and mentioned the iwl_rx_allocate function to check for crossing 4KB boundaries. Since there's 8KB A-MPDU support, crossing 4k boundaries didn't seem like something the device would fail with, but when I looked into the function for a minute anyway I stumbled over this little gem: BUG_ON(rxb->dma_addr & (~DMA_BIT_MASK(36) & 0xff)); Clearly, that is a totally bogus check, one would hope the compiler removes it entirely. (Think about it) After fixing it, I obviously ran into it, nothing guarantees the alignment the way you want it, because of the way skbs and their headroom are allocated. I won't explain that here nor double-check that I'm right, that goes beyond what most of the CC'ed people care about. So then I came up with the patch below, and so far my system has survived minutes with 64K pages, when it would previously fail in seconds. And I haven't seen a single instance of the TX bug either. But when you see the patch it'll be pretty obvious to you why. This should fix the following reported kernel bugs: http://bugzilla.kernel.org/show_bug.cgi?id=11596 http://bugzilla.kernel.org/show_bug.cgi?id=11393 http://bugzilla.kernel.org/show_bug.cgi?id=11983 I haven't checked if there are any elsewhere, but I suppose RHBZ will have a few instances too... I'd like to ask anyone who is CC'ed (those are people I know ran into the bug) to try this patch. I am convinced that this patch is correct in spirit, but I haven't understood why, for example, there are so many unmap calls. I'm not entirely convinced that this is the only bug leading to the TX reply errors. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 6 +++--- drivers/net/wireless/iwlwifi/iwl-dev.h | 3 ++- drivers/net/wireless/iwlwifi/iwl-rx.c | 26 +++++++++++++++++--------- 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 6751bb2b8ae2..444c5cc05f03 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1384,7 +1384,7 @@ void iwl_rx_handle(struct iwl_priv *priv) rxq->queue[i] = NULL; - pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->dma_addr, + pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->aligned_dma_addr, priv->hw_params.rx_buf_size, PCI_DMA_FROMDEVICE); pkt = (struct iwl_rx_packet *)rxb->skb->data; @@ -1436,8 +1436,8 @@ void iwl_rx_handle(struct iwl_priv *priv) rxb->skb = NULL; } - pci_unmap_single(priv->pci_dev, rxb->dma_addr, - priv->hw_params.rx_buf_size, + pci_unmap_single(priv->pci_dev, rxb->real_dma_addr, + priv->hw_params.rx_buf_size + 256, PCI_DMA_FROMDEVICE); spin_lock_irqsave(&rxq->lock, flags); list_add_tail(&rxb->list, &priv->rxq.rx_used); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index c018121085e9..9966d4e384ce 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -89,7 +89,8 @@ extern struct iwl_cfg iwl5100_abg_cfg; #define DEFAULT_LONG_RETRY_LIMIT 4U struct iwl_rx_mem_buffer { - dma_addr_t dma_addr; + dma_addr_t real_dma_addr; + dma_addr_t aligned_dma_addr; struct sk_buff *skb; struct list_head list; }; diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 7cde9d76ff5d..0509c16dbe75 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -204,7 +204,7 @@ int iwl_rx_queue_restock(struct iwl_priv *priv) list_del(element); /* Point to Rx buffer via next RBD in circular buffer */ - rxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(priv, rxb->dma_addr); + rxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(priv, rxb->aligned_dma_addr); rxq->queue[rxq->write] = rxb; rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; rxq->free_count--; @@ -251,7 +251,7 @@ void iwl_rx_allocate(struct iwl_priv *priv) rxb = list_entry(element, struct iwl_rx_mem_buffer, list); /* Alloc a new receive buffer */ - rxb->skb = alloc_skb(priv->hw_params.rx_buf_size, + rxb->skb = alloc_skb(priv->hw_params.rx_buf_size + 256, __GFP_NOWARN | GFP_ATOMIC); if (!rxb->skb) { if (net_ratelimit()) @@ -266,9 +266,17 @@ void iwl_rx_allocate(struct iwl_priv *priv) list_del(element); /* Get physical address of RB/SKB */ - rxb->dma_addr = - pci_map_single(priv->pci_dev, rxb->skb->data, - priv->hw_params.rx_buf_size, PCI_DMA_FROMDEVICE); + rxb->real_dma_addr = pci_map_single( + priv->pci_dev, + rxb->skb->data, + priv->hw_params.rx_buf_size + 256, + PCI_DMA_FROMDEVICE); + /* dma address must be no more than 36 bits */ + BUG_ON(rxb->real_dma_addr & ~DMA_BIT_MASK(36)); + /* and also 256 byte aligned! */ + rxb->aligned_dma_addr = ALIGN(rxb->real_dma_addr, 256); + skb_reserve(rxb->skb, rxb->aligned_dma_addr - rxb->real_dma_addr); + list_add_tail(&rxb->list, &rxq->rx_free); rxq->free_count++; } @@ -300,8 +308,8 @@ void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq) for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) { if (rxq->pool[i].skb != NULL) { pci_unmap_single(priv->pci_dev, - rxq->pool[i].dma_addr, - priv->hw_params.rx_buf_size, + rxq->pool[i].real_dma_addr, + priv->hw_params.rx_buf_size + 256, PCI_DMA_FROMDEVICE); dev_kfree_skb(rxq->pool[i].skb); } @@ -354,8 +362,8 @@ void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq) * to an SKB, so we need to unmap and free potential storage */ if (rxq->pool[i].skb != NULL) { pci_unmap_single(priv->pci_dev, - rxq->pool[i].dma_addr, - priv->hw_params.rx_buf_size, + rxq->pool[i].real_dma_addr, + priv->hw_params.rx_buf_size + 256, PCI_DMA_FROMDEVICE); priv->alloc_rxb_skb--; dev_kfree_skb(rxq->pool[i].skb); From f10ed36ec1118c6f9523cd7e53cb0aadb53efe9f Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Fri, 7 Nov 2008 22:36:02 -0500 Subject: [PATCH 024/107] ftrace: fix set_ftrace_filter Impact: fix of output of set_ftrace_filter The commit "ftrace: do not show freed records in available_filter_functions" Removed a bit too much from the set_ftrace_filter code, where we now see all functions in the set_ftrace_filter file even when we set a filter. Signed-off-by: Steven Rostedt Signed-off-by: Ingo Molnar --- kernel/trace/ftrace.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 4a39d24568c8..dcac7418f688 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -738,6 +738,9 @@ t_next(struct seq_file *m, void *v, loff_t *pos) ((iter->flags & FTRACE_ITER_FAILURES) && !(rec->flags & FTRACE_FL_FAILED)) || + ((iter->flags & FTRACE_ITER_FILTER) && + !(rec->flags & FTRACE_FL_FILTER)) || + ((iter->flags & FTRACE_ITER_NOTRACE) && !(rec->flags & FTRACE_FL_NOTRACE))) { rec = NULL; From 820432783190b4096499e38a4a4d7095c511913d Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Tue, 18 Nov 2008 23:57:14 -0500 Subject: [PATCH 025/107] ftrace: make filtered functions effective on setting Impact: fix filter selection to apply when set It can be confusing when the set_filter_functions is set (or cleared) and the functions being recorded by the dynamic tracer does not match. This patch causes the code to be updated if the function tracer is enabled and the filter is changed. Signed-off-by: Steven Rostedt Signed-off-by: Ingo Molnar --- kernel/trace/ftrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index dcac7418f688..5cbddb59e99f 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -1189,7 +1189,7 @@ ftrace_regex_release(struct inode *inode, struct file *file, int enable) mutex_lock(&ftrace_sysctl_lock); mutex_lock(&ftrace_start_lock); - if (iter->filtered && ftrace_start && ftrace_enabled) + if (ftrace_start && ftrace_enabled) ftrace_run_update_code(FTRACE_ENABLE_CALLS); mutex_unlock(&ftrace_start_lock); mutex_unlock(&ftrace_sysctl_lock); From 32464779a1b8c15e9aa9aa0306b2f735080df9d8 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Tue, 18 Nov 2008 20:33:02 -0500 Subject: [PATCH 026/107] ftrace: fix dyn ftrace filter selection Impact: clean up and fix for dyn ftrace filter selection The previous logic of the dynamic ftrace selection of enabling or disabling functions was complex and incorrect. This patch simplifies the code and corrects the usage. This simplification also makes the code more robust. Here is the correct logic: Given a function that can be traced by dynamic ftrace: If the function is not to be traced, disable it if it was enabled. (this is if the function is in the set_ftrace_notrace file) (filter is on if there exists any functions in set_ftrace_filter file) If the filter is on, and we are enabling functions: If the function is in set_ftrace_filter, enable it if it is not already enabled. If the function is not in set_ftrace_filter, disable it if it is not already disabled. Otherwise, if the filter is off and we are enabling function tracing: Enable the function if it is not already enabled. Otherwise, if we are disabling function tracing: Disable the function if it is not already disabled. This code now sets or clears the ENABLED flag in the record, and at the end it will enable the function if the flag is set, or disable the function if the flag is cleared. The parameters for the function that does the above logic is also simplified. Instead of passing in confusing "new" and "old" where they might be swapped if the "enabled" flag is not set. The old logic even had one of the above always NULL and had to be filled in. The new logic simply passes in one parameter called "nop". A "call" is calculated in the code, and at the end of the logic, when we know we need to either disable or enable the function, we can then use the "nop" and "call" properly. This code is more robust than the previous version. Signed-off-by: Steven Rostedt Signed-off-by: Ingo Molnar --- kernel/trace/ftrace.c | 112 ++++++++++++++++++++---------------------- 1 file changed, 52 insertions(+), 60 deletions(-) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 5cbddb59e99f..fdaab04a0282 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -327,96 +327,89 @@ ftrace_record_ip(unsigned long ip) static int __ftrace_replace_code(struct dyn_ftrace *rec, - unsigned char *old, unsigned char *new, int enable) + unsigned char *nop, int enable) { unsigned long ip, fl; + unsigned char *call, *old, *new; ip = rec->ip; - if (ftrace_filtered && enable) { - /* - * If filtering is on: - * - * If this record is set to be filtered and - * is enabled then do nothing. - * - * If this record is set to be filtered and - * it is not enabled, enable it. - * - * If this record is not set to be filtered - * and it is not enabled do nothing. - * - * If this record is set not to trace then - * do nothing. - * - * If this record is set not to trace and - * it is enabled then disable it. - * - * If this record is not set to be filtered and - * it is enabled, disable it. - */ - - fl = rec->flags & (FTRACE_FL_FILTER | FTRACE_FL_NOTRACE | - FTRACE_FL_ENABLED); - - if ((fl == (FTRACE_FL_FILTER | FTRACE_FL_ENABLED)) || - (fl == (FTRACE_FL_FILTER | FTRACE_FL_NOTRACE)) || - !fl || (fl == FTRACE_FL_NOTRACE)) + /* + * If this record is not to be traced and + * it is not enabled then do nothing. + * + * If this record is not to be traced and + * it is enabled then disabled it. + * + */ + if (rec->flags & FTRACE_FL_NOTRACE) { + if (rec->flags & FTRACE_FL_ENABLED) + rec->flags &= ~FTRACE_FL_ENABLED; + else return 0; + } else if (ftrace_filtered && enable) { /* - * If it is enabled disable it, - * otherwise enable it! + * Filtering is on: */ - if (fl & FTRACE_FL_ENABLED) { - /* swap new and old */ - new = old; - old = ftrace_call_replace(ip, FTRACE_ADDR); + + fl = rec->flags & (FTRACE_FL_FILTER | FTRACE_FL_ENABLED); + + /* Record is filtered and enabled, do nothing */ + if (fl == (FTRACE_FL_FILTER | FTRACE_FL_ENABLED)) + return 0; + + /* Record is not filtered and is not enabled do nothing */ + if (!fl) + return 0; + + /* Record is not filtered but enabled, disable it */ + if (fl == FTRACE_FL_ENABLED) rec->flags &= ~FTRACE_FL_ENABLED; - } else { - new = ftrace_call_replace(ip, FTRACE_ADDR); + else + /* Otherwise record is filtered but not enabled, enable it */ rec->flags |= FTRACE_FL_ENABLED; - } } else { + /* Disable or not filtered */ if (enable) { - /* - * If this record is set not to trace and is - * not enabled, do nothing. - */ - fl = rec->flags & (FTRACE_FL_NOTRACE | FTRACE_FL_ENABLED); - if (fl == FTRACE_FL_NOTRACE) - return 0; - - new = ftrace_call_replace(ip, FTRACE_ADDR); - } else - old = ftrace_call_replace(ip, FTRACE_ADDR); - - if (enable) { + /* if record is enabled, do nothing */ if (rec->flags & FTRACE_FL_ENABLED) return 0; + rec->flags |= FTRACE_FL_ENABLED; + } else { + + /* if record is not enabled do nothing */ if (!(rec->flags & FTRACE_FL_ENABLED)) return 0; + rec->flags &= ~FTRACE_FL_ENABLED; } } + call = ftrace_call_replace(ip, FTRACE_ADDR); + + if (rec->flags & FTRACE_FL_ENABLED) { + old = nop; + new = call; + } else { + old = call; + new = nop; + } + return ftrace_modify_code(ip, old, new); } static void ftrace_replace_code(int enable) { int i, failed; - unsigned char *new = NULL, *old = NULL; + unsigned char *nop = NULL; struct dyn_ftrace *rec; struct ftrace_page *pg; - if (enable) - old = ftrace_nop_replace(); - else - new = ftrace_nop_replace(); + nop = ftrace_nop_replace(); for (pg = ftrace_pages_start; pg; pg = pg->next) { for (i = 0; i < pg->index; i++) { @@ -434,7 +427,7 @@ static void ftrace_replace_code(int enable) unfreeze_record(rec); } - failed = __ftrace_replace_code(rec, old, new, enable); + failed = __ftrace_replace_code(rec, nop, enable); if (failed && (rec->flags & FTRACE_FL_CONVERTED)) { rec->flags |= FTRACE_FL_FAILED; if ((system_state == SYSTEM_BOOTING) || @@ -538,8 +531,7 @@ static void ftrace_startup(void) mutex_lock(&ftrace_start_lock); ftrace_start++; - if (ftrace_start == 1) - command |= FTRACE_ENABLE_CALLS; + command |= FTRACE_ENABLE_CALLS; if (saved_ftrace_func != ftrace_trace_function) { saved_ftrace_func = ftrace_trace_function; From b4e0f9eb8aeceb22c48fee005378bd19e25216fc Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Wed, 19 Nov 2008 13:53:42 +0900 Subject: [PATCH 027/107] intel-iommu: fix compile warnings Impact: cleanup I got the following warnings on IA64: linux-2.6/drivers/pci/intel-iommu.c: In function 'init_dmars': linux-2.6/drivers/pci/intel-iommu.c:1658: warning: format '%Lx' expects type 'long long unsigned int', but argument 2 has type 'u64' linux-2.6/drivers/pci/intel-iommu.c:1663: warning: format '%Lx' expects type 'long long unsigned int', but argument 2 has type 'u64' Another victim of int-ll64.h versus int-l64.h confusion between platforms. ->reg_base_addr has a type of u64 - which can only be printed out consistently if we cast its type up to LL. [ Eventually reg_base_addr should be converted to phys_addr_t, for which we have the %pR printk helper - but that is out of the scope of late -rc's. ] Signed-off-by: FUJITA Tomonori Signed-off-by: Ingo Molnar --- drivers/pci/intel-iommu.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index a2692724b68f..5c8baa43ac9c 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -1655,12 +1655,14 @@ int __init init_dmars(void) iommu->flush.flush_context = __iommu_flush_context; iommu->flush.flush_iotlb = __iommu_flush_iotlb; printk(KERN_INFO "IOMMU 0x%Lx: using Register based " - "invalidation\n", drhd->reg_base_addr); + "invalidation\n", + (unsigned long long)drhd->reg_base_addr); } else { iommu->flush.flush_context = qi_flush_context; iommu->flush.flush_iotlb = qi_flush_iotlb; printk(KERN_INFO "IOMMU 0x%Lx: using Queued " - "invalidation\n", drhd->reg_base_addr); + "invalidation\n", + (unsigned long long)drhd->reg_base_addr); } } From c3e388964baa00d8c3960f23e8c8a1fb3966759e Mon Sep 17 00:00:00 2001 From: Benjamin Thery Date: Wed, 19 Nov 2008 14:07:41 -0800 Subject: [PATCH 028/107] net: fix ip_mr_init() error path Similarly to IPv6 ip6_mr_init() (fixed last week), the order of cleanup operations in the error/exit section of ip_mr_init() is completely inversed. It should be the other way around. Also a del_timer() is missing in the error path. I should have guessed last week that this same error existed in ipmr.c too, as ip6mr.c is largely inspired by ipmr.c. Signed-off-by: Benjamin Thery Signed-off-by: David S. Miller --- net/ipv4/ipmr.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index b42e082cc170..25924b1eb2ef 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -1945,13 +1945,14 @@ int __init ip_mr_init(void) goto proc_cache_fail; #endif return 0; -reg_notif_fail: - kmem_cache_destroy(mrt_cachep); #ifdef CONFIG_PROC_FS -proc_vif_fail: - unregister_netdevice_notifier(&ip_mr_notifier); proc_cache_fail: proc_net_remove(&init_net, "ip_mr_vif"); +proc_vif_fail: + unregister_netdevice_notifier(&ip_mr_notifier); #endif +reg_notif_fail: + del_timer(&ipmr_expire_timer); + kmem_cache_destroy(mrt_cachep); return err; } From bfdbc0acadcc761b94814d78f0acec90f0d760de Mon Sep 17 00:00:00 2001 From: Robert Olsson Date: Wed, 19 Nov 2008 14:09:47 -0800 Subject: [PATCH 029/107] pktgen: fix multiple queue warning As number of TX queues in unrelated to number of CPU's we remove this test and just make sure nxtq never gets exceeded. Signed-off-by: Robert Olsson Signed-off-by: David S. Miller --- net/core/pktgen.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/net/core/pktgen.c b/net/core/pktgen.c index a47f5bad110d..8997e912aaaf 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -1973,13 +1973,7 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev) /* make sure that we don't pick a non-existing transmit queue */ ntxq = pkt_dev->odev->real_num_tx_queues; - if (ntxq > num_online_cpus() && (pkt_dev->flags & F_QUEUE_MAP_CPU)) { - printk(KERN_WARNING "pktgen: WARNING: QUEUE_MAP_CPU " - "disabled because CPU count (%d) exceeds number " - "of tx queues (%d) on %s\n", num_online_cpus(), ntxq, - pkt_dev->odev->name); - pkt_dev->flags &= ~F_QUEUE_MAP_CPU; - } + if (ntxq <= pkt_dev->queue_map_min) { printk(KERN_WARNING "pktgen: WARNING: Requested " "queue_map_min (zero-based) (%d) exceeds valid range " @@ -2202,6 +2196,7 @@ static void set_cur_queue_map(struct pktgen_dev *pkt_dev) } pkt_dev->cur_queue_map = t; } + pkt_dev->cur_queue_map = pkt_dev->cur_queue_map % pkt_dev->odev->real_num_tx_queues; } /* Increment/randomize headers according to flags and current values From 1df8fb3d5f078f9cab901b6106ef2c9b74eef7df Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Tue, 11 Nov 2008 17:17:45 +0800 Subject: [PATCH 030/107] PCI: Fix disable IRQ 0 in pci_reset_function() Before initialization, dev->irq may be zero. Make sure we don't disable it at reset time in that case. Reviewed-by: Matthew Wilcox Signed-off-by: Sheng Yang Signed-off-by: Jesse Barnes --- drivers/pci/pci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 21f2ac639cab..28af496b441e 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1832,7 +1832,7 @@ int pci_reset_function(struct pci_dev *dev) if (!(cap & PCI_EXP_DEVCAP_FLR)) return -ENOTTY; - if (!dev->msi_enabled && !dev->msix_enabled) + if (!dev->msi_enabled && !dev->msix_enabled && dev->irq != 0) disable_irq(dev->irq); pci_save_state(dev); @@ -1841,7 +1841,7 @@ int pci_reset_function(struct pci_dev *dev) r = pci_execute_reset_function(dev); pci_restore_state(dev); - if (!dev->msi_enabled && !dev->msix_enabled) + if (!dev->msi_enabled && !dev->msix_enabled && dev->irq != 0) enable_irq(dev->irq); return r; From 79aefa45b20940cbb9104464548ff74f80f2395e Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Wed, 19 Nov 2008 14:17:02 -0800 Subject: [PATCH 031/107] ixgbe: fix compilation with gcc-3.4 CC [M] drivers/net/ixgbe/ixgbe_main.o drivers/net/ixgbe/ixgbe_main.c: In function `ixgbe_intr': drivers/net/ixgbe/ixgbe_main.c:1290: sorry, unimplemented: inlining failed in call to 'ixgbe_irq_enable': function body not available drivers/net/ixgbe/ixgbe_main.c:1312: sorry, unimplemented: called from here make[4]: *** [drivers/net/ixgbe/ixgbe_main.o] Error 1 Signed-off-by: Alexey Dobriyan Acked-by: Peter P Waskiewicz Jr Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 58 ++++++++++++++++------------------ 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 7548fb7360d9..36f2bb666bf7 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -1287,7 +1287,34 @@ static void ixgbe_set_itr(struct ixgbe_adapter *adapter) return; } -static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter); +/** + * ixgbe_irq_disable - Mask off interrupt generation on the NIC + * @adapter: board private structure + **/ +static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter) +{ + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0); + IXGBE_WRITE_FLUSH(&adapter->hw); + if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { + int i; + for (i = 0; i < adapter->num_msix_vectors; i++) + synchronize_irq(adapter->msix_entries[i].vector); + } else { + synchronize_irq(adapter->pdev->irq); + } +} + +/** + * ixgbe_irq_enable - Enable default interrupt generation settings + * @adapter: board private structure + **/ +static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter) +{ + u32 mask; + mask = IXGBE_EIMS_ENABLE_MASK; + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask); + IXGBE_WRITE_FLUSH(&adapter->hw); +} /** * ixgbe_intr - legacy mode Interrupt Handler @@ -1393,35 +1420,6 @@ static void ixgbe_free_irq(struct ixgbe_adapter *adapter) } } -/** - * ixgbe_irq_disable - Mask off interrupt generation on the NIC - * @adapter: board private structure - **/ -static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter) -{ - IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0); - IXGBE_WRITE_FLUSH(&adapter->hw); - if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { - int i; - for (i = 0; i < adapter->num_msix_vectors; i++) - synchronize_irq(adapter->msix_entries[i].vector); - } else { - synchronize_irq(adapter->pdev->irq); - } -} - -/** - * ixgbe_irq_enable - Enable default interrupt generation settings - * @adapter: board private structure - **/ -static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter) -{ - u32 mask; - mask = IXGBE_EIMS_ENABLE_MASK; - IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask); - IXGBE_WRITE_FLUSH(&adapter->hw); -} - /** * ixgbe_configure_msi_and_legacy - Initialize PIN (INTA...) and MSI interrupts * From 566521d63720ab47576afb85147e5652993bf1e6 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Wed, 19 Nov 2008 14:17:41 -0800 Subject: [PATCH 032/107] phonet: fix compilation with gcc-3.4 CC [M] net/phonet/af_phonet.o net/phonet/af_phonet.c: In function `pn_socket_create': net/phonet/af_phonet.c:38: sorry, unimplemented: inlining failed in call to 'phonet_proto_put': function body not available net/phonet/af_phonet.c:99: sorry, unimplemented: called from here make[3]: *** [net/phonet/af_phonet.o] Error 1 Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- net/phonet/af_phonet.c | 52 +++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 28 deletions(-) diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c index 7ab30f668b5a..9d211f12582b 100644 --- a/net/phonet/af_phonet.c +++ b/net/phonet/af_phonet.c @@ -33,9 +33,30 @@ #include #include -static struct net_proto_family phonet_proto_family; -static struct phonet_protocol *phonet_proto_get(int protocol); -static inline void phonet_proto_put(struct phonet_protocol *pp); +/* Transport protocol registration */ +static struct phonet_protocol *proto_tab[PHONET_NPROTO] __read_mostly; +static DEFINE_SPINLOCK(proto_tab_lock); + +static struct phonet_protocol *phonet_proto_get(int protocol) +{ + struct phonet_protocol *pp; + + if (protocol >= PHONET_NPROTO) + return NULL; + + spin_lock(&proto_tab_lock); + pp = proto_tab[protocol]; + if (pp && !try_module_get(pp->prot->owner)) + pp = NULL; + spin_unlock(&proto_tab_lock); + + return pp; +} + +static inline void phonet_proto_put(struct phonet_protocol *pp) +{ + module_put(pp->prot->owner); +} /* protocol family functions */ @@ -375,10 +396,6 @@ static struct packet_type phonet_packet_type = { .func = phonet_rcv, }; -/* Transport protocol registration */ -static struct phonet_protocol *proto_tab[PHONET_NPROTO] __read_mostly; -static DEFINE_SPINLOCK(proto_tab_lock); - int __init_or_module phonet_proto_register(int protocol, struct phonet_protocol *pp) { @@ -412,27 +429,6 @@ void phonet_proto_unregister(int protocol, struct phonet_protocol *pp) } EXPORT_SYMBOL(phonet_proto_unregister); -static struct phonet_protocol *phonet_proto_get(int protocol) -{ - struct phonet_protocol *pp; - - if (protocol >= PHONET_NPROTO) - return NULL; - - spin_lock(&proto_tab_lock); - pp = proto_tab[protocol]; - if (pp && !try_module_get(pp->prot->owner)) - pp = NULL; - spin_unlock(&proto_tab_lock); - - return pp; -} - -static inline void phonet_proto_put(struct phonet_protocol *pp) -{ - module_put(pp->prot->owner); -} - /* Module registration */ static int __init phonet_init(void) { From b47300168e770b60ab96c8924854c3b0eb4260eb Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 19 Nov 2008 15:33:54 -0800 Subject: [PATCH 033/107] net: Do not fire linkwatch events until the device is registered. Several device drivers try to do things like netif_carrier_off() before register_netdev() is invoked. This is bogus, but too many drivers do this to fix them all up in one go. Reported-by: Folkert van Heusden Signed-off-by: David S. Miller --- net/sched/sch_generic.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 93cd30ce6501..cdcd16fcfeda 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -270,6 +270,8 @@ static void dev_watchdog_down(struct net_device *dev) void netif_carrier_on(struct net_device *dev) { if (test_and_clear_bit(__LINK_STATE_NOCARRIER, &dev->state)) { + if (dev->reg_state == NETREG_UNINITIALIZED) + return; linkwatch_fire_event(dev); if (netif_running(dev)) __netdev_watchdog_up(dev); @@ -285,8 +287,11 @@ EXPORT_SYMBOL(netif_carrier_on); */ void netif_carrier_off(struct net_device *dev) { - if (!test_and_set_bit(__LINK_STATE_NOCARRIER, &dev->state)) + if (!test_and_set_bit(__LINK_STATE_NOCARRIER, &dev->state)) { + if (dev->reg_state == NETREG_UNINITIALIZED) + return; linkwatch_fire_event(dev); + } } EXPORT_SYMBOL(netif_carrier_off); From 9d6ada9f4141fb8ab3c5d7dffe382f6a68b8e961 Mon Sep 17 00:00:00 2001 From: Paulius Zaleckas Date: Wed, 19 Nov 2008 15:38:24 -0800 Subject: [PATCH 034/107] phylib: fix phy name example in documentation All MDIO bus drivers currently name bus with "%x" format. There is one exception where mv643xx_eth driver is using "%d". Phy address on the bus uses format "%02x". Fixing phy name example to match all real life MDIO drivers. Signed-off-by: Paulius Zaleckas Signed-off-by: David S. Miller --- Documentation/networking/phy.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/networking/phy.txt b/Documentation/networking/phy.txt index 8df6a7b0e66c..88bb71b46da4 100644 --- a/Documentation/networking/phy.txt +++ b/Documentation/networking/phy.txt @@ -96,7 +96,7 @@ Letting the PHY Abstraction Layer do Everything static void adjust_link(struct net_device *dev); Next, you need to know the device name of the PHY connected to this device. - The name will look something like, "phy0:0", where the first number is the + The name will look something like, "0:00", where the first number is the bus id, and the second is the PHY's address on that bus. Typically, the bus is responsible for making its ID unique. From 31c221c49f92d17632e0d662eb62a27e8b425805 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Wed, 19 Nov 2008 15:50:59 -0800 Subject: [PATCH 035/107] net: jme.c rxdesc.flags is __le16, other missing endian swaps This is the minimal patch to fix endian mismatches. These are probably bugs on big-endian arches, noops on little endian. jme_rxsum_ok could be improved to directly take a __le16 and change all of the masks/sets to be in little-endian, but has not been done here to keep the patch small. Signed-off-by: Harvey Harrison Signed-off-by: David S. Miller --- drivers/net/jme.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/net/jme.c b/drivers/net/jme.c index 81c6cdc3851f..665e70d620fc 100644 --- a/drivers/net/jme.c +++ b/drivers/net/jme.c @@ -912,23 +912,23 @@ jme_alloc_and_feed_skb(struct jme_adapter *jme, int idx) skb_put(skb, framesize); skb->protocol = eth_type_trans(skb, jme->dev); - if (jme_rxsum_ok(jme, rxdesc->descwb.flags)) + if (jme_rxsum_ok(jme, le16_to_cpu(rxdesc->descwb.flags))) skb->ip_summed = CHECKSUM_UNNECESSARY; else skb->ip_summed = CHECKSUM_NONE; - if (rxdesc->descwb.flags & RXWBFLAG_TAGON) { + if (rxdesc->descwb.flags & cpu_to_le16(RXWBFLAG_TAGON)) { if (jme->vlgrp) { jme->jme_vlan_rx(skb, jme->vlgrp, - le32_to_cpu(rxdesc->descwb.vlan)); + le16_to_cpu(rxdesc->descwb.vlan)); NET_STAT(jme).rx_bytes += 4; } } else { jme->jme_rx(skb); } - if ((le16_to_cpu(rxdesc->descwb.flags) & RXWBFLAG_DEST) == - RXWBFLAG_DEST_MUL) + if ((rxdesc->descwb.flags & cpu_to_le16(RXWBFLAG_DEST)) == + cpu_to_le16(RXWBFLAG_DEST_MUL)) ++(NET_STAT(jme).multicast); jme->dev->last_rx = jiffies; @@ -961,7 +961,7 @@ jme_process_receive(struct jme_adapter *jme, int limit) rxdesc = rxring->desc; rxdesc += i; - if ((rxdesc->descwb.flags & RXWBFLAG_OWN) || + if ((rxdesc->descwb.flags & cpu_to_le16(RXWBFLAG_OWN)) || !(rxdesc->descwb.desccnt & RXWBDCNT_WBCPL)) goto out; @@ -1763,10 +1763,9 @@ jme_expand_header(struct jme_adapter *jme, struct sk_buff *skb) } static int -jme_tx_tso(struct sk_buff *skb, - u16 *mss, u8 *flags) +jme_tx_tso(struct sk_buff *skb, __le16 *mss, u8 *flags) { - *mss = skb_shinfo(skb)->gso_size << TXDESC_MSS_SHIFT; + *mss = cpu_to_le16(skb_shinfo(skb)->gso_size << TXDESC_MSS_SHIFT); if (*mss) { *flags |= TXFLAG_LSEN; @@ -1826,11 +1825,11 @@ jme_tx_csum(struct jme_adapter *jme, struct sk_buff *skb, u8 *flags) } static inline void -jme_tx_vlan(struct sk_buff *skb, u16 *vlan, u8 *flags) +jme_tx_vlan(struct sk_buff *skb, __le16 *vlan, u8 *flags) { if (vlan_tx_tag_present(skb)) { *flags |= TXFLAG_TAGON; - *vlan = vlan_tx_tag_get(skb); + *vlan = cpu_to_le16(vlan_tx_tag_get(skb)); } } From de339c2aa7fea18410b1abeab5674bfbd4073a63 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Wed, 19 Nov 2008 15:52:41 -0800 Subject: [PATCH 036/107] phylib: Fix auto-negotiation restart avoidance A previous patch, 51e2a3846eab18711f4eb59cd0a4c33054e2980a, made genphy_config_aneg() not restart aneg by calling genphy_restart_aneg() if the advertisement hadn't changed. But, genphy_restart_aneg() doesn't just restart aneg, it may also *enable* aneg or un-isolate the PHY from the MII (those functions are controlled by the same register). The code to avoid calling genphy_restart_aneg() didn't consider this. So, modify genphy_config_aneg() to also check if the PHY needs to have aneg enabled or be un-isolated before deciding not to restart aneg. This caused a problem with certain Davicom PHYs, as that driver isolates the PHY (why?) before calling genphy_config_aneg() and expects the PHY to be un-isolated by that function. Signed-off-by: Trent Piepho Reported-by: Scott Wood Signed-off-by: David S. Miller --- drivers/net/phy/phy_device.c | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 8fb1faca883a..55bc24b234e3 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -564,20 +564,32 @@ EXPORT_SYMBOL(genphy_restart_aneg); */ int genphy_config_aneg(struct phy_device *phydev) { - int result = 0; + int result; - if (AUTONEG_ENABLE == phydev->autoneg) { - int result = genphy_config_advert(phydev); + if (AUTONEG_ENABLE != phydev->autoneg) + return genphy_setup_forced(phydev); - if (result < 0) /* error */ - return result; + result = genphy_config_advert(phydev); - /* Only restart aneg if we are advertising something different - * than we were before. */ - if (result > 0) - result = genphy_restart_aneg(phydev); - } else - result = genphy_setup_forced(phydev); + if (result < 0) /* error */ + return result; + + if (result == 0) { + /* Advertisment hasn't changed, but maybe aneg was never on to + * begin with? Or maybe phy was isolated? */ + int ctl = phy_read(phydev, MII_BMCR); + + if (ctl < 0) + return ctl; + + if (!(ctl & BMCR_ANENABLE) || (ctl & BMCR_ISOLATE)) + result = 1; /* do restart aneg */ + } + + /* Only restart aneg if we are advertising something different + * than we were before. */ + if (result > 0) + result = genphy_restart_aneg(phydev); return result; } From b88ed5cc884e4c28d787cf0912b8635376f16a87 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Wed, 19 Nov 2008 15:54:38 -0800 Subject: [PATCH 037/107] net: ipg.c fix bracing on endian swapping rxfd->frag_info is a __le64, IPG_RFI_FRAGLEN is a cpu-endian constant and wants to be outside of the le64_to_cpu. Fixed in multiple places. Also an occurrence where le64_to_cpu was used instead of cpu_to_le64 Signed-off-by: Harvey Harrison Signed-off-by: David S. Miller --- drivers/net/ipg.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ipg.c b/drivers/net/ipg.c index 7373dafbb3f7..059369885be1 100644 --- a/drivers/net/ipg.c +++ b/drivers/net/ipg.c @@ -1112,7 +1112,7 @@ static void ipg_nic_rx_free_skb(struct net_device *dev) struct ipg_rx *rxfd = sp->rxd + entry; pci_unmap_single(sp->pdev, - le64_to_cpu(rxfd->frag_info & ~IPG_RFI_FRAGLEN), + le64_to_cpu(rxfd->frag_info) & ~IPG_RFI_FRAGLEN, sp->rx_buf_sz, PCI_DMA_FROMDEVICE); dev_kfree_skb_irq(sp->rx_buff[entry]); sp->rx_buff[entry] = NULL; @@ -1179,7 +1179,7 @@ static int ipg_nic_rx_check_error(struct net_device *dev) */ if (sp->rx_buff[entry]) { pci_unmap_single(sp->pdev, - le64_to_cpu(rxfd->frag_info & ~IPG_RFI_FRAGLEN), + le64_to_cpu(rxfd->frag_info) & ~IPG_RFI_FRAGLEN, sp->rx_buf_sz, PCI_DMA_FROMDEVICE); dev_kfree_skb_irq(sp->rx_buff[entry]); @@ -1246,7 +1246,7 @@ static void ipg_nic_rx_with_start(struct net_device *dev, if (jumbo->found_start) dev_kfree_skb_irq(jumbo->skb); - pci_unmap_single(pdev, le64_to_cpu(rxfd->frag_info & ~IPG_RFI_FRAGLEN), + pci_unmap_single(pdev, le64_to_cpu(rxfd->frag_info) & ~IPG_RFI_FRAGLEN, sp->rx_buf_sz, PCI_DMA_FROMDEVICE); skb_put(skb, sp->rxfrag_size); @@ -1349,7 +1349,7 @@ static int ipg_nic_rx_jumbo(struct net_device *dev) unsigned int entry = curr % IPG_RFDLIST_LENGTH; struct ipg_rx *rxfd = sp->rxd + entry; - if (!(rxfd->rfs & le64_to_cpu(IPG_RFS_RFDDONE))) + if (!(rxfd->rfs & cpu_to_le64(IPG_RFS_RFDDONE))) break; switch (ipg_nic_rx_check_frame_type(dev)) { From 9ca791bbd464d7968db1530b433cc397a4c348c1 Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Wed, 19 Nov 2008 15:36:06 -0800 Subject: [PATCH 038/107] hwmon: applesmc: Add support for iMac 6 Add temperature sensor support for iMac 6. Signed-off-by: Henrik Rydberg Tested-by: Caleb Hyde Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/hwmon/applesmc.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index 488e45cd43d7..10977b3d201c 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c @@ -128,6 +128,9 @@ static const char* temperature_sensors_sets[][36] = { /* Set 13: iMac 8,1 */ { "TA0P", "TC0D", "TC0H", "TC0P", "TG0D", "TG0H", "TG0P", "TH0P", "TL0P", "TO0P", "TW0P", "Tm0P", "Tp0P", NULL }, +/* Set 14: iMac 6,1 */ + { "TA0P", "TC0D", "TC0H", "TC0P", "TG0D", "TG0H", "TG0P", "TH0P", + "TO0P", "Tp0P", NULL }, }; /* List of keys used to read/write fan speeds */ @@ -1296,6 +1299,8 @@ static __initdata struct dmi_match_data applesmc_dmi_data[] = { { .accelerometer = 1, .light = 1, .temperature_set = 12 }, /* iMac 8: light sensor only, temperature set 13 */ { .accelerometer = 0, .light = 0, .temperature_set = 13 }, +/* iMac 6: light sensor only, temperature set 14 */ + { .accelerometer = 0, .light = 0, .temperature_set = 14 }, }; /* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1". @@ -1353,6 +1358,10 @@ static __initdata struct dmi_system_id applesmc_whitelist[] = { DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), DMI_MATCH(DMI_PRODUCT_NAME, "iMac8") }, &applesmc_dmi_data[13]}, + { applesmc_dmi_match, "Apple iMac 6", { + DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), + DMI_MATCH(DMI_PRODUCT_NAME, "iMac6") }, + &applesmc_dmi_data[14]}, { applesmc_dmi_match, "Apple iMac 5", { DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), DMI_MATCH(DMI_PRODUCT_NAME, "iMac5") }, From cf7b9a1e11993a064f445d332fecf22819b87a5e Mon Sep 17 00:00:00 2001 From: Julien Brunel Date: Wed, 19 Nov 2008 15:36:07 -0800 Subject: [PATCH 039/107] drivers/video: bad error test before a dereference The error test that follows the call to backlight_device_register semms not to concern the right variable. A simplified version of the semantic match that finds this problem is as follows: (http://www.emn.fr/x-info/coccinelle/) // @def0@ expression x; position p0; @@ x@p0 = backlight_device_register(...) @protected@ expression def0.x,E; position def0.p0; position p; statement S; @@ x@p0 ... when != x = E if (!IS_ERR(x) && ...) {<... x@p ...>} else S @unprotected@ expression def0.x; identifier fld; position def0.p0; position p != protected.p; @@ x@p0 ... when != x = E * x@p->fld // Signed-off-by: Julien Brunel Signed-off-by: Julia Lawall Acked-by: Nicolas Ferre Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/atmel_lcdfb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index f8d0a57a07cb..9a577a800db5 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c @@ -132,7 +132,7 @@ static void init_backlight(struct atmel_lcdfb_info *sinfo) bl = backlight_device_register("backlight", &sinfo->pdev->dev, sinfo, &atmel_lcdc_bl_ops); - if (IS_ERR(sinfo->backlight)) { + if (IS_ERR(bl)) { dev_err(&sinfo->pdev->dev, "error %ld on backlight register\n", PTR_ERR(bl)); return; From e00b4ff7ebf098b11b11be403921c1cf41d9e321 Mon Sep 17 00:00:00 2001 From: Nadia Derbey Date: Wed, 19 Nov 2008 15:36:08 -0800 Subject: [PATCH 040/107] sysvipc: fix the ipc structures initialization A problem was found while reviewing the code after Bugzilla bug http://bugzilla.kernel.org/show_bug.cgi?id=11796. In ipc_addid(), the newly allocated ipc structure is inserted into the ipcs tree (i.e made visible to readers) without locking it. This is not correct since its initialization continues after it has been inserted in the tree. This patch moves the ipc structure lock initialization + locking before the actual insertion. Signed-off-by: Nadia Derbey Reported-by: Clement Calmels Cc: Manfred Spraul Cc: [2.6.27.x] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- ipc/util.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/ipc/util.c b/ipc/util.c index 49b3ea615dc5..361fd1c96fcf 100644 --- a/ipc/util.c +++ b/ipc/util.c @@ -266,9 +266,17 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size) if (ids->in_use >= size) return -ENOSPC; + spin_lock_init(&new->lock); + new->deleted = 0; + rcu_read_lock(); + spin_lock(&new->lock); + err = idr_get_new(&ids->ipcs_idr, new, &id); - if (err) + if (err) { + spin_unlock(&new->lock); + rcu_read_unlock(); return err; + } ids->in_use++; @@ -280,10 +288,6 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size) ids->seq = 0; new->id = ipc_buildid(id, new->seq); - spin_lock_init(&new->lock); - new->deleted = 0; - rcu_read_lock(); - spin_lock(&new->lock); return id; } From cf7ee554f3a324e98181b0ea249d9d5be3a0acb8 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Wed, 19 Nov 2008 15:36:10 -0800 Subject: [PATCH 041/107] fbdev: clean the penguin's dirty feet When booting in a direct color mode, the penguin has dirty feet, i.e., some pixels have the wrong color. This is caused by fb_set_logo_directpalette() which does not initialize the last 32 palette entries. Signed-off-by: Clemens Ladisch Acked-by: Geert Uytterhoeven Cc: Krzysztof Helt Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/fbmem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 1d5ae39cb271..3c65b0d67617 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -230,7 +230,7 @@ static void fb_set_logo_directpalette(struct fb_info *info, greenshift = info->var.green.offset; blueshift = info->var.blue.offset; - for (i = 32; i < logo->clutsize; i++) + for (i = 32; i < 32 + logo->clutsize; i++) palette[i] = i << redshift | i << greenshift | i << blueshift; } From de11defebf00007677fb7ee91d9b089b78786fbb Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Wed, 19 Nov 2008 15:36:14 -0800 Subject: [PATCH 042/107] reintroduce accept4 Introduce a new accept4() system call. The addition of this system call matches analogous changes in 2.6.27 (dup3(), evenfd2(), signalfd4(), inotify_init1(), epoll_create1(), pipe2()) which added new system calls that differed from analogous traditional system calls in adding a flags argument that can be used to access additional functionality. The accept4() system call is exactly the same as accept(), except that it adds a flags bit-mask argument. Two flags are initially implemented. (Most of the new system calls in 2.6.27 also had both of these flags.) SOCK_CLOEXEC causes the close-on-exec (FD_CLOEXEC) flag to be enabled for the new file descriptor returned by accept4(). This is a useful security feature to avoid leaking information in a multithreaded program where one thread is doing an accept() at the same time as another thread is doing a fork() plus exec(). More details here: http://udrepper.livejournal.com/20407.html "Secure File Descriptor Handling", Ulrich Drepper). The other flag is SOCK_NONBLOCK, which causes the O_NONBLOCK flag to be enabled on the new open file description created by accept4(). (This flag is merely a convenience, saving the use of additional calls fcntl(F_GETFL) and fcntl (F_SETFL) to achieve the same result. Here's a test program. Works on x86-32. Should work on x86-64, but I (mtk) don't have a system to hand to test with. It tests accept4() with each of the four possible combinations of SOCK_CLOEXEC and SOCK_NONBLOCK set/clear in 'flags', and verifies that the appropriate flags are set on the file descriptor/open file description returned by accept4(). I tested Ulrich's patch in this thread by applying against 2.6.28-rc2, and it passes according to my test program. /* test_accept4.c Copyright (C) 2008, Linux Foundation, written by Michael Kerrisk Licensed under the GNU GPLv2 or later. */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #define PORT_NUM 33333 #define die(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0) /**********************************************************************/ /* The following is what we need until glibc gets a wrapper for accept4() */ /* Flags for socket(), socketpair(), accept4() */ #ifndef SOCK_CLOEXEC #define SOCK_CLOEXEC O_CLOEXEC #endif #ifndef SOCK_NONBLOCK #define SOCK_NONBLOCK O_NONBLOCK #endif #ifdef __x86_64__ #define SYS_accept4 288 #elif __i386__ #define USE_SOCKETCALL 1 #define SYS_ACCEPT4 18 #else #error "Sorry -- don't know the syscall # on this architecture" #endif static int accept4(int fd, struct sockaddr *sockaddr, socklen_t *addrlen, int flags) { printf("Calling accept4(): flags = %x", flags); if (flags != 0) { printf(" ("); if (flags & SOCK_CLOEXEC) printf("SOCK_CLOEXEC"); if ((flags & SOCK_CLOEXEC) && (flags & SOCK_NONBLOCK)) printf(" "); if (flags & SOCK_NONBLOCK) printf("SOCK_NONBLOCK"); printf(")"); } printf("\n"); #if USE_SOCKETCALL long args[6]; args[0] = fd; args[1] = (long) sockaddr; args[2] = (long) addrlen; args[3] = flags; return syscall(SYS_socketcall, SYS_ACCEPT4, args); #else return syscall(SYS_accept4, fd, sockaddr, addrlen, flags); #endif } /**********************************************************************/ static int do_test(int lfd, struct sockaddr_in *conn_addr, int closeonexec_flag, int nonblock_flag) { int connfd, acceptfd; int fdf, flf, fdf_pass, flf_pass; struct sockaddr_in claddr; socklen_t addrlen; printf("=======================================\n"); connfd = socket(AF_INET, SOCK_STREAM, 0); if (connfd == -1) die("socket"); if (connect(connfd, (struct sockaddr *) conn_addr, sizeof(struct sockaddr_in)) == -1) die("connect"); addrlen = sizeof(struct sockaddr_in); acceptfd = accept4(lfd, (struct sockaddr *) &claddr, &addrlen, closeonexec_flag | nonblock_flag); if (acceptfd == -1) { perror("accept4()"); close(connfd); return 0; } fdf = fcntl(acceptfd, F_GETFD); if (fdf == -1) die("fcntl:F_GETFD"); fdf_pass = ((fdf & FD_CLOEXEC) != 0) == ((closeonexec_flag & SOCK_CLOEXEC) != 0); printf("Close-on-exec flag is %sset (%s); ", (fdf & FD_CLOEXEC) ? "" : "not ", fdf_pass ? "OK" : "failed"); flf = fcntl(acceptfd, F_GETFL); if (flf == -1) die("fcntl:F_GETFD"); flf_pass = ((flf & O_NONBLOCK) != 0) == ((nonblock_flag & SOCK_NONBLOCK) !=0); printf("nonblock flag is %sset (%s)\n", (flf & O_NONBLOCK) ? "" : "not ", flf_pass ? "OK" : "failed"); close(acceptfd); close(connfd); printf("Test result: %s\n", (fdf_pass && flf_pass) ? "PASS" : "FAIL"); return fdf_pass && flf_pass; } static int create_listening_socket(int port_num) { struct sockaddr_in svaddr; int lfd; int optval; memset(&svaddr, 0, sizeof(struct sockaddr_in)); svaddr.sin_family = AF_INET; svaddr.sin_addr.s_addr = htonl(INADDR_ANY); svaddr.sin_port = htons(port_num); lfd = socket(AF_INET, SOCK_STREAM, 0); if (lfd == -1) die("socket"); optval = 1; if (setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1) die("setsockopt"); if (bind(lfd, (struct sockaddr *) &svaddr, sizeof(struct sockaddr_in)) == -1) die("bind"); if (listen(lfd, 5) == -1) die("listen"); return lfd; } int main(int argc, char *argv[]) { struct sockaddr_in conn_addr; int lfd; int port_num; int passed; passed = 1; port_num = (argc > 1) ? atoi(argv[1]) : PORT_NUM; memset(&conn_addr, 0, sizeof(struct sockaddr_in)); conn_addr.sin_family = AF_INET; conn_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); conn_addr.sin_port = htons(port_num); lfd = create_listening_socket(port_num); if (!do_test(lfd, &conn_addr, 0, 0)) passed = 0; if (!do_test(lfd, &conn_addr, SOCK_CLOEXEC, 0)) passed = 0; if (!do_test(lfd, &conn_addr, 0, SOCK_NONBLOCK)) passed = 0; if (!do_test(lfd, &conn_addr, SOCK_CLOEXEC, SOCK_NONBLOCK)) passed = 0; close(lfd); exit(passed ? EXIT_SUCCESS : EXIT_FAILURE); } [mtk.manpages@gmail.com: rewrote changelog, updated test program] Signed-off-by: Ulrich Drepper Tested-by: Michael Kerrisk Acked-by: Michael Kerrisk Cc: Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/x86/include/asm/unistd_64.h | 4 +- include/linux/net.h | 6 +-- include/linux/syscalls.h | 3 +- kernel/sys_ni.c | 2 +- net/compat.c | 50 ++------------------ net/socket.c | 80 ++++---------------------------- 6 files changed, 21 insertions(+), 124 deletions(-) diff --git a/arch/x86/include/asm/unistd_64.h b/arch/x86/include/asm/unistd_64.h index 834b2c1d89fb..d2e415e6666f 100644 --- a/arch/x86/include/asm/unistd_64.h +++ b/arch/x86/include/asm/unistd_64.h @@ -639,8 +639,8 @@ __SYSCALL(__NR_fallocate, sys_fallocate) __SYSCALL(__NR_timerfd_settime, sys_timerfd_settime) #define __NR_timerfd_gettime 287 __SYSCALL(__NR_timerfd_gettime, sys_timerfd_gettime) -#define __NR_paccept 288 -__SYSCALL(__NR_paccept, sys_paccept) +#define __NR_accept4 288 +__SYSCALL(__NR_accept4, sys_accept4) #define __NR_signalfd4 289 __SYSCALL(__NR_signalfd4, sys_signalfd4) #define __NR_eventfd2 290 diff --git a/include/linux/net.h b/include/linux/net.h index 6dc14a240042..4515efae4c39 100644 --- a/include/linux/net.h +++ b/include/linux/net.h @@ -40,7 +40,7 @@ #define SYS_GETSOCKOPT 15 /* sys_getsockopt(2) */ #define SYS_SENDMSG 16 /* sys_sendmsg(2) */ #define SYS_RECVMSG 17 /* sys_recvmsg(2) */ -#define SYS_PACCEPT 18 /* sys_paccept(2) */ +#define SYS_ACCEPT4 18 /* sys_accept4(2) */ typedef enum { SS_FREE = 0, /* not allocated */ @@ -100,7 +100,7 @@ enum sock_type { * remaining bits are used as flags. */ #define SOCK_TYPE_MASK 0xf -/* Flags for socket, socketpair, paccept */ +/* Flags for socket, socketpair, accept4 */ #define SOCK_CLOEXEC O_CLOEXEC #ifndef SOCK_NONBLOCK #define SOCK_NONBLOCK O_NONBLOCK @@ -223,8 +223,6 @@ extern int sock_map_fd(struct socket *sock, int flags); extern struct socket *sockfd_lookup(int fd, int *err); #define sockfd_put(sock) fput(sock->file) extern int net_ratelimit(void); -extern long do_accept(int fd, struct sockaddr __user *upeer_sockaddr, - int __user *upeer_addrlen, int flags); #define net_random() random32() #define net_srandom(seed) srandom32((__force u32)seed) diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index d6ff145919ca..04fb47bfb920 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -410,8 +410,7 @@ asmlinkage long sys_getsockopt(int fd, int level, int optname, asmlinkage long sys_bind(int, struct sockaddr __user *, int); asmlinkage long sys_connect(int, struct sockaddr __user *, int); asmlinkage long sys_accept(int, struct sockaddr __user *, int __user *); -asmlinkage long sys_paccept(int, struct sockaddr __user *, int __user *, - const __user sigset_t *, size_t, int); +asmlinkage long sys_accept4(int, struct sockaddr __user *, int __user *, int); asmlinkage long sys_getsockname(int, struct sockaddr __user *, int __user *); asmlinkage long sys_getpeername(int, struct sockaddr __user *, int __user *); asmlinkage long sys_send(int, void __user *, size_t, unsigned); diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c index a77b27b11b04..e14a23281707 100644 --- a/kernel/sys_ni.c +++ b/kernel/sys_ni.c @@ -31,7 +31,7 @@ cond_syscall(sys_socketpair); cond_syscall(sys_bind); cond_syscall(sys_listen); cond_syscall(sys_accept); -cond_syscall(sys_paccept); +cond_syscall(sys_accept4); cond_syscall(sys_connect); cond_syscall(sys_getsockname); cond_syscall(sys_getpeername); diff --git a/net/compat.c b/net/compat.c index 6ce1a1cadcc0..a3a2ba0fac08 100644 --- a/net/compat.c +++ b/net/compat.c @@ -725,7 +725,7 @@ EXPORT_SYMBOL(compat_mc_getsockopt); static unsigned char nas[19]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3), AL(3),AL(3),AL(4),AL(4),AL(4),AL(6), AL(6),AL(2),AL(5),AL(5),AL(3),AL(3), - AL(6)}; + AL(4)}; #undef AL asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, unsigned flags) @@ -738,52 +738,13 @@ asmlinkage long compat_sys_recvmsg(int fd, struct compat_msghdr __user *msg, uns return sys_recvmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT); } -asmlinkage long compat_sys_paccept(int fd, struct sockaddr __user *upeer_sockaddr, - int __user *upeer_addrlen, - const compat_sigset_t __user *sigmask, - compat_size_t sigsetsize, int flags) -{ - compat_sigset_t ss32; - sigset_t ksigmask, sigsaved; - int ret; - - if (sigmask) { - if (sigsetsize != sizeof(compat_sigset_t)) - return -EINVAL; - if (copy_from_user(&ss32, sigmask, sizeof(ss32))) - return -EFAULT; - sigset_from_compat(&ksigmask, &ss32); - - sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP)); - sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved); - } - - ret = do_accept(fd, upeer_sockaddr, upeer_addrlen, flags); - - if (ret == -ERESTARTNOHAND) { - /* - * Don't restore the signal mask yet. Let do_signal() deliver - * the signal on the way back to userspace, before the signal - * mask is restored. - */ - if (sigmask) { - memcpy(¤t->saved_sigmask, &sigsaved, - sizeof(sigsaved)); - set_restore_sigmask(); - } - } else if (sigmask) - sigprocmask(SIG_SETMASK, &sigsaved, NULL); - - return ret; -} - asmlinkage long compat_sys_socketcall(int call, u32 __user *args) { int ret; u32 a[6]; u32 a0, a1; - if (call < SYS_SOCKET || call > SYS_PACCEPT) + if (call < SYS_SOCKET || call > SYS_ACCEPT4) return -EINVAL; if (copy_from_user(a, args, nas[call])) return -EFAULT; @@ -804,7 +765,7 @@ asmlinkage long compat_sys_socketcall(int call, u32 __user *args) ret = sys_listen(a0, a1); break; case SYS_ACCEPT: - ret = do_accept(a0, compat_ptr(a1), compat_ptr(a[2]), 0); + ret = sys_accept4(a0, compat_ptr(a1), compat_ptr(a[2]), 0); break; case SYS_GETSOCKNAME: ret = sys_getsockname(a0, compat_ptr(a1), compat_ptr(a[2])); @@ -844,9 +805,8 @@ asmlinkage long compat_sys_socketcall(int call, u32 __user *args) case SYS_RECVMSG: ret = compat_sys_recvmsg(a0, compat_ptr(a1), a[2]); break; - case SYS_PACCEPT: - ret = compat_sys_paccept(a0, compat_ptr(a1), compat_ptr(a[2]), - compat_ptr(a[3]), a[4], a[5]); + case SYS_ACCEPT4: + ret = sys_accept4(a0, compat_ptr(a1), compat_ptr(a[2]), a[3]); break; default: ret = -EINVAL; diff --git a/net/socket.c b/net/socket.c index 57550c3bcabe..92764d836891 100644 --- a/net/socket.c +++ b/net/socket.c @@ -1426,8 +1426,8 @@ asmlinkage long sys_listen(int fd, int backlog) * clean when we restucture accept also. */ -long do_accept(int fd, struct sockaddr __user *upeer_sockaddr, - int __user *upeer_addrlen, int flags) +asmlinkage long sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr, + int __user *upeer_addrlen, int flags) { struct socket *sock, *newsock; struct file *newfile; @@ -1510,66 +1510,10 @@ out_fd: goto out_put; } -#if 0 -#ifdef HAVE_SET_RESTORE_SIGMASK -asmlinkage long sys_paccept(int fd, struct sockaddr __user *upeer_sockaddr, - int __user *upeer_addrlen, - const sigset_t __user *sigmask, - size_t sigsetsize, int flags) -{ - sigset_t ksigmask, sigsaved; - int ret; - - if (sigmask) { - /* XXX: Don't preclude handling different sized sigset_t's. */ - if (sigsetsize != sizeof(sigset_t)) - return -EINVAL; - if (copy_from_user(&ksigmask, sigmask, sizeof(ksigmask))) - return -EFAULT; - - sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP)); - sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved); - } - - ret = do_accept(fd, upeer_sockaddr, upeer_addrlen, flags); - - if (ret < 0 && signal_pending(current)) { - /* - * Don't restore the signal mask yet. Let do_signal() deliver - * the signal on the way back to userspace, before the signal - * mask is restored. - */ - if (sigmask) { - memcpy(¤t->saved_sigmask, &sigsaved, - sizeof(sigsaved)); - set_restore_sigmask(); - } - } else if (sigmask) - sigprocmask(SIG_SETMASK, &sigsaved, NULL); - - return ret; -} -#else -asmlinkage long sys_paccept(int fd, struct sockaddr __user *upeer_sockaddr, - int __user *upeer_addrlen, - const sigset_t __user *sigmask, - size_t sigsetsize, int flags) -{ - /* The platform does not support restoring the signal mask in the - * return path. So we do not allow using paccept() with a signal - * mask. */ - if (sigmask) - return -EINVAL; - - return do_accept(fd, upeer_sockaddr, upeer_addrlen, flags); -} -#endif -#endif - asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int __user *upeer_addrlen) { - return do_accept(fd, upeer_sockaddr, upeer_addrlen, 0); + return sys_accept4(fd, upeer_sockaddr, upeer_addrlen, 0); } /* @@ -2096,7 +2040,7 @@ static const unsigned char nargs[19]={ AL(0),AL(3),AL(3),AL(3),AL(2),AL(3), AL(3),AL(3),AL(4),AL(4),AL(4),AL(6), AL(6),AL(2),AL(5),AL(5),AL(3),AL(3), - AL(6) + AL(4) }; #undef AL @@ -2115,7 +2059,7 @@ asmlinkage long sys_socketcall(int call, unsigned long __user *args) unsigned long a0, a1; int err; - if (call < 1 || call > SYS_PACCEPT) + if (call < 1 || call > SYS_ACCEPT4) return -EINVAL; /* copy_from_user should be SMP safe. */ @@ -2143,9 +2087,8 @@ asmlinkage long sys_socketcall(int call, unsigned long __user *args) err = sys_listen(a0, a1); break; case SYS_ACCEPT: - err = - do_accept(a0, (struct sockaddr __user *)a1, - (int __user *)a[2], 0); + err = sys_accept4(a0, (struct sockaddr __user *)a1, + (int __user *)a[2], 0); break; case SYS_GETSOCKNAME: err = @@ -2192,12 +2135,9 @@ asmlinkage long sys_socketcall(int call, unsigned long __user *args) case SYS_RECVMSG: err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]); break; - case SYS_PACCEPT: - err = - sys_paccept(a0, (struct sockaddr __user *)a1, - (int __user *)a[2], - (const sigset_t __user *) a[3], - a[4], a[5]); + case SYS_ACCEPT4: + err = sys_accept4(a0, (struct sockaddr __user *)a1, + (int __user *)a[2], a[3]); break; default: err = -EINVAL; From f8b2256e9c11a825899345de06b39a4bdf44911d Mon Sep 17 00:00:00 2001 From: David Miller Date: Wed, 19 Nov 2008 15:36:15 -0800 Subject: [PATCH 043/107] sparc64: wire up accept4() This adds the sparc syscall hookups. Signed-off-by: David S. Miller Cc: Ulrich Drepper Cc: Michael Kerrisk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/sparc/include/asm/unistd_32.h | 3 ++- arch/sparc/include/asm/unistd_64.h | 3 ++- arch/sparc/kernel/systbls.S | 2 +- arch/sparc64/kernel/sys32.S | 13 ++++++++++++- arch/sparc64/kernel/systbls.S | 4 ++-- 5 files changed, 19 insertions(+), 6 deletions(-) diff --git a/arch/sparc/include/asm/unistd_32.h b/arch/sparc/include/asm/unistd_32.h index 648643a9f139..0d13d2a4c76f 100644 --- a/arch/sparc/include/asm/unistd_32.h +++ b/arch/sparc/include/asm/unistd_32.h @@ -338,8 +338,9 @@ #define __NR_dup3 320 #define __NR_pipe2 321 #define __NR_inotify_init1 322 +#define __NR_accept4 323 -#define NR_SYSCALLS 323 +#define NR_SYSCALLS 324 /* Sparc 32-bit only has the "setresuid32", "getresuid32" variants, * it never had the plain ones and there is no value to adding those diff --git a/arch/sparc/include/asm/unistd_64.h b/arch/sparc/include/asm/unistd_64.h index c5cc0e052321..fa5d3c0343c7 100644 --- a/arch/sparc/include/asm/unistd_64.h +++ b/arch/sparc/include/asm/unistd_64.h @@ -340,8 +340,9 @@ #define __NR_dup3 320 #define __NR_pipe2 321 #define __NR_inotify_init1 322 +#define __NR_accept4 323 -#define NR_SYSCALLS 323 +#define NR_SYSCALLS 324 #ifdef __KERNEL__ #define __ARCH_WANT_IPC_PARSE_VERSION diff --git a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S index e1b9233b90ab..7d0807586442 100644 --- a/arch/sparc/kernel/systbls.S +++ b/arch/sparc/kernel/systbls.S @@ -81,4 +81,4 @@ sys_call_table: /*305*/ .long sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait /*310*/ .long sys_utimensat, sys_signalfd, sys_timerfd_create, sys_eventfd, sys_fallocate /*315*/ .long sys_timerfd_settime, sys_timerfd_gettime, sys_signalfd4, sys_eventfd2, sys_epoll_create1 -/*320*/ .long sys_dup3, sys_pipe2, sys_inotify_init1 +/*320*/ .long sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4 diff --git a/arch/sparc64/kernel/sys32.S b/arch/sparc64/kernel/sys32.S index ade18ba0c686..f061c4dda9ef 100644 --- a/arch/sparc64/kernel/sys32.S +++ b/arch/sparc64/kernel/sys32.S @@ -150,7 +150,7 @@ sys32_mmap2: sys32_socketcall: /* %o0=call, %o1=args */ cmp %o0, 1 bl,pn %xcc, do_einval - cmp %o0, 17 + cmp %o0, 18 bg,pn %xcc, do_einval sub %o0, 1, %o0 sllx %o0, 5, %o0 @@ -319,6 +319,15 @@ do_sys_recvmsg: /* compat_sys_recvmsg(int, struct compat_msghdr *, unsigned int) nop nop nop +do_sys_accept4: /* sys_accept4(int, struct sockaddr *, int *, int) */ +63: ldswa [%o1 + 0x0] %asi, %o0 + sethi %hi(sys_accept4), %g1 +64: lduwa [%o1 + 0x8] %asi, %o2 +65: ldswa [%o1 + 0xc] %asi, %o3 + jmpl %g1 + %lo(sys_accept4), %g0 +66: lduwa [%o1 + 0x4] %asi, %o1 + nop + nop .section __ex_table,"a" .align 4 @@ -353,4 +362,6 @@ do_sys_recvmsg: /* compat_sys_recvmsg(int, struct compat_msghdr *, unsigned int) .word 57b, __retl_efault, 58b, __retl_efault .word 59b, __retl_efault, 60b, __retl_efault .word 61b, __retl_efault, 62b, __retl_efault + .word 63b, __retl_efault, 64b, __retl_efault + .word 65b, __retl_efault, 66b, __retl_efault .previous diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S index b2fa4c163638..9fc78cf354bd 100644 --- a/arch/sparc64/kernel/systbls.S +++ b/arch/sparc64/kernel/systbls.S @@ -82,7 +82,7 @@ sys_call_table32: .word compat_sys_set_mempolicy, compat_sys_kexec_load, compat_sys_move_pages, sys_getcpu, compat_sys_epoll_pwait /*310*/ .word compat_sys_utimensat, compat_sys_signalfd, sys_timerfd_create, sys_eventfd, compat_sys_fallocate .word compat_sys_timerfd_settime, compat_sys_timerfd_gettime, compat_sys_signalfd4, sys_eventfd2, sys_epoll_create1 -/*320*/ .word sys_dup3, sys_pipe2, sys_inotify_init1 +/*320*/ .word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4 #endif /* CONFIG_COMPAT */ @@ -156,4 +156,4 @@ sys_call_table: .word sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait /*310*/ .word sys_utimensat, sys_signalfd, sys_timerfd_create, sys_eventfd, sys_fallocate .word sys_timerfd_settime, sys_timerfd_gettime, sys_signalfd4, sys_eventfd2, sys_epoll_create1 -/*320*/ .word sys_dup3, sys_pipe2, sys_inotify_init1 +/*320*/ .word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4 From 1c207f952a3a39f9d07a3e9de0cf6b9a9464eeaa Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 19 Nov 2008 15:36:16 -0800 Subject: [PATCH 044/107] Documentation/kernel-parameters.txt: add min_addr, fix max_addr Add "min_addr" documentation. For "max_addr", add nn before [KMG] since a number is needed and this is consistent with other uses of [KMG]. Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/kernel-parameters.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 9fa6508892c2..899650c20cc2 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1193,8 +1193,8 @@ and is between 256 and 4096 characters. It is defined in the file it is equivalent to "nosmp", which also disables the IO APIC. - max_addr=[KMG] [KNL,BOOT,ia64] All physical memory greater than or - equal to this physical address is ignored. + max_addr=nn[KMG] [KNL,BOOT,ia64] All physical memory greater than + or equal to this physical address is ignored. max_luns= [SCSI] Maximum number of LUNs to probe. Should be between 1 and 2^32-1. @@ -1294,6 +1294,9 @@ and is between 256 and 4096 characters. It is defined in the file mga= [HW,DRM] + min_addr=nn[KMG] [KNL,BOOT,ia64] All physical memory below this + physical address is ignored. + mminit_loglevel= [KNL] When CONFIG_DEBUG_MEMORY_INIT is set, this parameter allows control of the logging verbosity for From 6e8ba729b6332f2a75572e02480936d2b51665aa Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Wed, 19 Nov 2008 15:36:17 -0800 Subject: [PATCH 045/107] gpiolib: extend gpio label column width in debugfs file There are already various drivers having bigger label than 12 bytes. Most of them fit well under 20 bytes but make column width exact so that oversized labels don't mess up output alignment. Signed-off-by: Jarkko Nikula Acked-by: David Brownell Cc: [2.6.26.x, 2.6.26.x, 2.6.27.x] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/gpio/gpiolib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index faa1cc66e9cf..82020abc329e 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1134,7 +1134,7 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip) continue; is_out = test_bit(FLAG_IS_OUT, &gdesc->flags); - seq_printf(s, " gpio-%-3d (%-12s) %s %s", + seq_printf(s, " gpio-%-3d (%-20.20s) %s %s", gpio, gdesc->label, is_out ? "out" : "in ", chip->get From 415d8cfa845ec9dac42e7b354b1f80485805455b Mon Sep 17 00:00:00 2001 From: Jack Steiner Date: Wed, 19 Nov 2008 15:36:18 -0800 Subject: [PATCH 046/107] GRU: fix for debug option Enable -D DEBUG in the GRU Makefile if CONFIG_SGI_GRU_DEBUG is selected. Signed-off-by: Jack Steiner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/misc/sgi-gru/Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/misc/sgi-gru/Makefile b/drivers/misc/sgi-gru/Makefile index d03597a521b0..9e9170b3599a 100644 --- a/drivers/misc/sgi-gru/Makefile +++ b/drivers/misc/sgi-gru/Makefile @@ -1,3 +1,7 @@ +ifdef CONFIG_SGI_GRU_DEBUG + EXTRA_CFLAGS += -DDEBUG +endif + obj-$(CONFIG_SGI_GRU) := gru.o gru-y := grufile.o grumain.o grufault.o grutlbpurge.o gruprocfs.o grukservices.o From a495a6d35a026826d54a69d01f373681e14f59ac Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Wed, 19 Nov 2008 15:36:19 -0800 Subject: [PATCH 047/107] tmiofb: fix compilation with ACCEL disabled Restore support for compiling tmiofb with acceleration disabled. Signed-off-by: Dmitry Baryshkov Cc: Krzysztof Helt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/tmiofb.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/video/tmiofb.c b/drivers/video/tmiofb.c index 2a380011e9ba..7baf2dd12d50 100644 --- a/drivers/video/tmiofb.c +++ b/drivers/video/tmiofb.c @@ -222,6 +222,9 @@ static irqreturn_t tmiofb_irq(int irq, void *__info) unsigned int bbisc = tmio_ioread16(par->lcr + LCR_BBISC); + tmio_iowrite16(bbisc, par->lcr + LCR_BBISC); + +#ifdef CONFIG_FB_TMIO_ACCELL /* * We were in polling mode and now we got correct irq. * Switch back to IRQ-based sync of command FIFO @@ -231,9 +234,6 @@ static irqreturn_t tmiofb_irq(int irq, void *__info) par->use_polling = false; } - tmio_iowrite16(bbisc, par->lcr + LCR_BBISC); - -#ifdef CONFIG_FB_TMIO_ACCELL if (bbisc & 1) wake_up(&par->wait_acc); #endif @@ -938,7 +938,9 @@ static void tmiofb_dump_regs(struct platform_device *dev) static int tmiofb_suspend(struct platform_device *dev, pm_message_t state) { struct fb_info *info = platform_get_drvdata(dev); +#ifdef CONFIG_FB_TMIO_ACCELL struct tmiofb_par *par = info->par; +#endif struct mfd_cell *cell = dev->dev.platform_data; int retval = 0; @@ -950,12 +952,14 @@ static int tmiofb_suspend(struct platform_device *dev, pm_message_t state) info->fbops->fb_sync(info); +#ifdef CONFIG_FB_TMIO_ACCELL /* * The fb should be usable even if interrupts are disabled (and they are * during suspend/resume). Switch temporary to forced polling. */ printk(KERN_INFO "tmiofb: switching to polling\n"); par->use_polling = true; +#endif tmiofb_hw_stop(dev); if (cell->suspend) From f652c521e0bec2e70cf123f47e80117a7e6ed139 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Wed, 19 Nov 2008 15:36:19 -0800 Subject: [PATCH 048/107] lib/scatterlist.c: fix kunmap() argument in sg_miter_stop() kunmap() takes as argument the struct page that orginally got kmap()'d, however the sg_miter_stop() function passed it the kernel virtual address instead, resulting in weird stuff. Somehow I ended up fixing this bug by accident while looking for a bug in the same area. Reported-by: kerneloops.org Acked-by: Tejun Heo Signed-off-by: Arjan van de Ven Cc: Hugh Dickins Cc: [2.6.27.x] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/scatterlist.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/scatterlist.c b/lib/scatterlist.c index 8d2688ff1352..b7b449dafbe5 100644 --- a/lib/scatterlist.c +++ b/lib/scatterlist.c @@ -395,7 +395,7 @@ void sg_miter_stop(struct sg_mapping_iter *miter) WARN_ON(!irqs_disabled()); kunmap_atomic(miter->addr, KM_BIO_SRC_IRQ); } else - kunmap(miter->addr); + kunmap(miter->page); miter->page = NULL; miter->addr = NULL; From 393df744e056ba24e9531d0657d09fc3c7c0dd22 Mon Sep 17 00:00:00 2001 From: Ned Forrester Date: Wed, 19 Nov 2008 15:36:21 -0800 Subject: [PATCH 049/107] pxa2xx_spi: bugfix full duplex dma data corruption Fixes a data corruption bug in pxa2xx_spi.c when operating in full duplex mode with DMA and using buffers that overlap. SPI transmit and receive buffers are allowed to be the same or to overlap. However, this driver fails if such overlap is attempted in DMA mode because it maps the rx and tx buffers in the wrong order. By mapping DMA_FROM_DEVICE (read) before DMA_TO_DEVICE (write), it invalidates the cache before flushing it, thus discarding data which should have been transmitted. The patch corrects the order of mapping. This bug exists in all versions of pxa2xx_spi.c; similar bugs are in the drivers for two other SPI controllers (au1500, imx). A version of this patch has been tested on kernel 2.6.20 using verification of loopback data with: random transfer length, random bits-per-word, random positive offsets (both larger and smaller than transfer length) between the start of the rx and tx buffers, and varying clock rates. Signed-off-by: Ned Forrester Cc: Vernon Sauder Cc: J. Scott Merritt Signed-off-by: David Brownell Cc: [2.6.27.x] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/spi/pxa2xx_spi.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c index dae87b1a4c6e..cf12f2d84be2 100644 --- a/drivers/spi/pxa2xx_spi.c +++ b/drivers/spi/pxa2xx_spi.c @@ -352,21 +352,21 @@ static int map_dma_buffers(struct driver_data *drv_data) } else drv_data->tx_map_len = drv_data->len; - /* Stream map the rx buffer */ - drv_data->rx_dma = dma_map_single(dev, drv_data->rx, - drv_data->rx_map_len, - DMA_FROM_DEVICE); - if (dma_mapping_error(dev, drv_data->rx_dma)) + /* Stream map the tx buffer. Always do DMA_TO_DEVICE first + * so we flush the cache *before* invalidating it, in case + * the tx and rx buffers overlap. + */ + drv_data->tx_dma = dma_map_single(dev, drv_data->tx, + drv_data->tx_map_len, DMA_TO_DEVICE); + if (dma_mapping_error(dev, drv_data->tx_dma)) return 0; - /* Stream map the tx buffer */ - drv_data->tx_dma = dma_map_single(dev, drv_data->tx, - drv_data->tx_map_len, - DMA_TO_DEVICE); - - if (dma_mapping_error(dev, drv_data->tx_dma)) { - dma_unmap_single(dev, drv_data->rx_dma, + /* Stream map the rx buffer */ + drv_data->rx_dma = dma_map_single(dev, drv_data->rx, drv_data->rx_map_len, DMA_FROM_DEVICE); + if (dma_mapping_error(dev, drv_data->rx_dma)) { + dma_unmap_single(dev, drv_data->tx_dma, + drv_data->tx_map_len, DMA_TO_DEVICE); return 0; } From c267fd777a478d74fa8959628538b64088f67fd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20Pr=C3=A9mont?= Date: Wed, 19 Nov 2008 15:36:23 -0800 Subject: [PATCH 050/107] viafb: fix releasing of /proc/viafb/ subtree MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When unloading viafb module it does not remove it's /proc/viafb/ subtree which causes multiple viafb directories to appear below proc when mobprobing viafb and also lets kernel WARN() on duplicate proc entries: [ 145.458387] WARNING: at /usr/src/linux-2.6.28-rc3-git6/fs/proc/generic.c:551 proc_register+0xe6/0x160() [ 145.458945] proc_dir_entry '/proc/viafb' already registered [ 145.459278] Modules linked in: viafb(+) i2c_algo_bit cfbcopyarea cfbimgblt cfbfillrect snd_hda_intel snd_pcm snd_timer snd soundcore snd_page_alloc sg via_agp agpgart [last unloaded: drm] [ 145.460647] Pid: 1904, comm: modprobe Tainted: G W 2.6.28-rc3-git6 #4 [ 145.461064] Call Trace: [ 145.461248] [] ? dump_stack+0x1/0x80 [ 145.461533] [] warn_slowpath+0x63/0x80 [ 145.461851] [] ? idr_get_empty_slot+0xe9/0x250 [ 145.462186] [] ? ida_get_new_above+0xf0/0x150 [ 145.462528] [] proc_register+0xe6/0x160 [ 145.462827] [] proc_mkdir_mode+0x36/0x50 [ 145.463135] [] proc_mkdir+0xf/0x20 [ 145.463457] [] viafb_init+0x73c/0xc86 [viafb] [ 145.463823] [] ? viafb_init+0x0/0xc86 [viafb] [ 145.464147] [] do_one_initcall+0x2d/0x160 [ 145.464460] [] ? sysfs_add_file+0x13/0x20 [ 145.464786] [] ? vfree+0x21/0x30 [ 145.465049] [] ? load_module+0x1215/0x1500 [ 145.465381] [] ? __alloc_pages_internal+0x95/0x400 [ 145.465755] [] sys_init_module+0x83/0x1a0 [ 145.466065] [] ? sys_read+0x3d/0x70 [ 145.466354] [] sysenter_do_call+0x12/0x25 [ 145.466653] ---[ end trace c84b37826e16748c ]--- Signed-off-by: Bruno Prémont Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/via/viafbdev.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index 0132eae06f55..73ac754ad801 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c @@ -2036,30 +2036,30 @@ static int viafb_vt1636_proc_write(struct file *file, return count; } -static void viafb_init_proc(struct proc_dir_entry *viafb_entry) +static void viafb_init_proc(struct proc_dir_entry **viafb_entry) { struct proc_dir_entry *entry; - viafb_entry = proc_mkdir("viafb", NULL); + *viafb_entry = proc_mkdir("viafb", NULL); if (viafb_entry) { - entry = create_proc_entry("dvp0", 0, viafb_entry); + entry = create_proc_entry("dvp0", 0, *viafb_entry); if (entry) { entry->owner = THIS_MODULE; entry->read_proc = viafb_dvp0_proc_read; entry->write_proc = viafb_dvp0_proc_write; } - entry = create_proc_entry("dvp1", 0, viafb_entry); + entry = create_proc_entry("dvp1", 0, *viafb_entry); if (entry) { entry->owner = THIS_MODULE; entry->read_proc = viafb_dvp1_proc_read; entry->write_proc = viafb_dvp1_proc_write; } - entry = create_proc_entry("dfph", 0, viafb_entry); + entry = create_proc_entry("dfph", 0, *viafb_entry); if (entry) { entry->owner = THIS_MODULE; entry->read_proc = viafb_dfph_proc_read; entry->write_proc = viafb_dfph_proc_write; } - entry = create_proc_entry("dfpl", 0, viafb_entry); + entry = create_proc_entry("dfpl", 0, *viafb_entry); if (entry) { entry->owner = THIS_MODULE; entry->read_proc = viafb_dfpl_proc_read; @@ -2068,7 +2068,7 @@ static void viafb_init_proc(struct proc_dir_entry *viafb_entry) if (VT1636_LVDS == viaparinfo->chip_info->lvds_chip_info. lvds_chip_name || VT1636_LVDS == viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) { - entry = create_proc_entry("vt1636", 0, viafb_entry); + entry = create_proc_entry("vt1636", 0, *viafb_entry); if (entry) { entry->owner = THIS_MODULE; entry->read_proc = viafb_vt1636_proc_read; @@ -2087,6 +2087,7 @@ static void viafb_remove_proc(struct proc_dir_entry *viafb_entry) remove_proc_entry("dfpl", viafb_entry); remove_proc_entry("vt1636", viafb_entry); remove_proc_entry("vt1625", viafb_entry); + remove_proc_entry("viafb", NULL); } static int __devinit via_pci_probe(void) @@ -2348,7 +2349,7 @@ static int __devinit via_pci_probe(void) viafbinfo->node, viafbinfo->fix.id, default_var.xres, default_var.yres, default_var.bits_per_pixel); - viafb_init_proc(viaparinfo->proc_entry); + viafb_init_proc(&viaparinfo->proc_entry); viafb_init_dac(IGA2); return 0; } From b3b4dc8840a8fdbe495723d35cd976d781fd42fa Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 19 Nov 2008 15:36:25 -0800 Subject: [PATCH 051/107] lcd: fix oops if driver only interested in .set_power The LCD driver core calls LCD drivers when either the blanking state or the display mode has changed, but does not make any check to see if the called driver has a .set_mode method. This means if a driver only has a .set_power method then the system will OOPS on changing mode (and with the console semaphore held so you cannot easily see the problem). Fix the problem by ensuring that either callback is valid before use. Signed-off-by: Ben Dooks Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/backlight/lcd.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c index 8e1731d3b228..680e57b616cd 100644 --- a/drivers/video/backlight/lcd.c +++ b/drivers/video/backlight/lcd.c @@ -42,10 +42,13 @@ static int fb_notifier_callback(struct notifier_block *self, mutex_lock(&ld->ops_lock); if (!ld->ops->check_fb || ld->ops->check_fb(ld, evdata->info)) { - if (event == FB_EVENT_BLANK) - ld->ops->set_power(ld, *(int *)evdata->data); - else - ld->ops->set_mode(ld, evdata->data); + if (event == FB_EVENT_BLANK) { + if (ld->ops->set_power) + ld->ops->set_power(ld, *(int *)evdata->data); + } else { + if (ld->ops->set_mode) + ld->ops->set_mode(ld, evdata->data); + } } mutex_unlock(&ld->ops_lock); return 0; From 3b45d6380c392e402adc460e4ccf7d41e0caf82a Mon Sep 17 00:00:00 2001 From: Andrea Paterniani Date: Wed, 19 Nov 2008 15:36:26 -0800 Subject: [PATCH 052/107] spi_imx: full duplex dma corruption bugfix Fix unsafe order in dma mapping operation: always flush data from the cache *BEFORE* invalidating it, to allow full duplex transfers where the same buffer may be used for both writes and reads. Signed-off-by: Andrea Paterniani Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/spi/spi_imx.c | 45 +++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/drivers/spi/spi_imx.c b/drivers/spi/spi_imx.c index 61ba147e384d..0b4db0ce78d6 100644 --- a/drivers/spi/spi_imx.c +++ b/drivers/spi/spi_imx.c @@ -506,20 +506,6 @@ static int map_dma_buffers(struct driver_data *drv_data) if (!IS_DMA_ALIGNED(drv_data->rx) || !IS_DMA_ALIGNED(drv_data->tx)) return -1; - /* NULL rx means write-only transfer and no map needed - since rx DMA will not be used */ - if (drv_data->rx) { - buf = drv_data->rx; - drv_data->rx_dma = dma_map_single( - dev, - buf, - drv_data->len, - DMA_FROM_DEVICE); - if (dma_mapping_error(dev, drv_data->rx_dma)) - return -1; - drv_data->rx_dma_needs_unmap = 1; - } - if (drv_data->tx == NULL) { /* Read only message --> use drv_data->dummy_dma_buf for dummy writes to achive reads */ @@ -533,18 +519,31 @@ static int map_dma_buffers(struct driver_data *drv_data) buf, drv_data->tx_map_len, DMA_TO_DEVICE); - if (dma_mapping_error(dev, drv_data->tx_dma)) { - if (drv_data->rx_dma) { - dma_unmap_single(dev, - drv_data->rx_dma, - drv_data->len, - DMA_FROM_DEVICE); - drv_data->rx_dma_needs_unmap = 0; - } + if (dma_mapping_error(dev, drv_data->tx_dma)) return -1; - } drv_data->tx_dma_needs_unmap = 1; + /* NULL rx means write-only transfer and no map needed + * since rx DMA will not be used */ + if (drv_data->rx) { + buf = drv_data->rx; + drv_data->rx_dma = dma_map_single(dev, + buf, + drv_data->len, + DMA_FROM_DEVICE); + if (dma_mapping_error(dev, drv_data->rx_dma)) { + if (drv_data->tx_dma) { + dma_unmap_single(dev, + drv_data->tx_dma, + drv_data->tx_map_len, + DMA_TO_DEVICE); + drv_data->tx_dma_needs_unmap = 0; + } + return -1; + } + drv_data->rx_dma_needs_unmap = 1; + } + return 0; } From ac97b9f9a2d0b83488e0bbcb8517b229d5c9b142 Mon Sep 17 00:00:00 2001 From: Michael Halcrow Date: Wed, 19 Nov 2008 15:36:28 -0800 Subject: [PATCH 053/107] eCryptfs: Allocate up to two scatterlists for crypto ops on keys I have received some reports of out-of-memory errors on some older AMD architectures. These errors are what I would expect to see if crypt_stat->key were split between two separate pages. eCryptfs should not assume that any of the memory sent through virt_to_scatterlist() is all contained in a single page, and so this patch allocates two scatterlist structs instead of one when processing keys. I have received confirmation from one person affected by this bug that this patch resolves the issue for him, and so I am submitting it for inclusion in a future stable release. Note that virt_to_scatterlist() runs sg_init_table() on the scatterlist structs passed to it, so the calls to sg_init_table() in decrypt_passphrase_encrypted_session_key() are redundant. Signed-off-by: Michael Halcrow Reported-by: Paulo J. S. Silva Cc: "Leon Woestenberg" Cc: Tim Gardner Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ecryptfs/keystore.c | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index e22bc3961345..0d713b691941 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c @@ -1037,17 +1037,14 @@ static int decrypt_passphrase_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok, struct ecryptfs_crypt_stat *crypt_stat) { - struct scatterlist dst_sg; - struct scatterlist src_sg; + struct scatterlist dst_sg[2]; + struct scatterlist src_sg[2]; struct mutex *tfm_mutex; struct blkcipher_desc desc = { .flags = CRYPTO_TFM_REQ_MAY_SLEEP }; int rc = 0; - sg_init_table(&dst_sg, 1); - sg_init_table(&src_sg, 1); - if (unlikely(ecryptfs_verbosity > 0)) { ecryptfs_printk( KERN_DEBUG, "Session key encryption key (size [%d]):\n", @@ -1066,8 +1063,8 @@ decrypt_passphrase_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok, } rc = virt_to_scatterlist(auth_tok->session_key.encrypted_key, auth_tok->session_key.encrypted_key_size, - &src_sg, 1); - if (rc != 1) { + src_sg, 2); + if (rc < 1 || rc > 2) { printk(KERN_ERR "Internal error whilst attempting to convert " "auth_tok->session_key.encrypted_key to scatterlist; " "expected rc = 1; got rc = [%d]. " @@ -1079,8 +1076,8 @@ decrypt_passphrase_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok, auth_tok->session_key.encrypted_key_size; rc = virt_to_scatterlist(auth_tok->session_key.decrypted_key, auth_tok->session_key.decrypted_key_size, - &dst_sg, 1); - if (rc != 1) { + dst_sg, 2); + if (rc < 1 || rc > 2) { printk(KERN_ERR "Internal error whilst attempting to convert " "auth_tok->session_key.decrypted_key to scatterlist; " "expected rc = 1; got rc = [%d]\n", rc); @@ -1096,7 +1093,7 @@ decrypt_passphrase_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok, rc = -EINVAL; goto out; } - rc = crypto_blkcipher_decrypt(&desc, &dst_sg, &src_sg, + rc = crypto_blkcipher_decrypt(&desc, dst_sg, src_sg, auth_tok->session_key.encrypted_key_size); mutex_unlock(tfm_mutex); if (unlikely(rc)) { @@ -1539,8 +1536,8 @@ write_tag_3_packet(char *dest, size_t *remaining_bytes, size_t i; size_t encrypted_session_key_valid = 0; char session_key_encryption_key[ECRYPTFS_MAX_KEY_BYTES]; - struct scatterlist dst_sg; - struct scatterlist src_sg; + struct scatterlist dst_sg[2]; + struct scatterlist src_sg[2]; struct mutex *tfm_mutex = NULL; u8 cipher_code; size_t packet_size_length; @@ -1619,8 +1616,8 @@ write_tag_3_packet(char *dest, size_t *remaining_bytes, ecryptfs_dump_hex(session_key_encryption_key, 16); } rc = virt_to_scatterlist(crypt_stat->key, key_rec->enc_key_size, - &src_sg, 1); - if (rc != 1) { + src_sg, 2); + if (rc < 1 || rc > 2) { ecryptfs_printk(KERN_ERR, "Error generating scatterlist " "for crypt_stat session key; expected rc = 1; " "got rc = [%d]. key_rec->enc_key_size = [%d]\n", @@ -1629,8 +1626,8 @@ write_tag_3_packet(char *dest, size_t *remaining_bytes, goto out; } rc = virt_to_scatterlist(key_rec->enc_key, key_rec->enc_key_size, - &dst_sg, 1); - if (rc != 1) { + dst_sg, 2); + if (rc < 1 || rc > 2) { ecryptfs_printk(KERN_ERR, "Error generating scatterlist " "for crypt_stat encrypted session key; " "expected rc = 1; got rc = [%d]. " @@ -1651,7 +1648,7 @@ write_tag_3_packet(char *dest, size_t *remaining_bytes, rc = 0; ecryptfs_printk(KERN_DEBUG, "Encrypting [%d] bytes of the key\n", crypt_stat->key_size); - rc = crypto_blkcipher_encrypt(&desc, &dst_sg, &src_sg, + rc = crypto_blkcipher_encrypt(&desc, dst_sg, src_sg, (*key_rec).enc_key_size); mutex_unlock(tfm_mutex); if (rc) { From f481891fdc49d3d1b8a9674a1825d183069a805f Mon Sep 17 00:00:00 2001 From: Miao Xie Date: Wed, 19 Nov 2008 15:36:30 -0800 Subject: [PATCH 054/107] cpuset: update top cpuset's mems after adding a node After adding a node into the machine, top cpuset's mems isn't updated. By reviewing the code, we found that the update function cpuset_track_online_nodes() was invoked after node_states[N_ONLINE] changes. It is wrong because N_ONLINE just means node has pgdat, and if node has/added memory, we use N_HIGH_MEMORY. So, We should invoke the update function after node_states[N_HIGH_MEMORY] changes, just like its commit says. This patch fixes it. And we use notifier of memory hotplug instead of direct calling of cpuset_track_online_nodes(). Signed-off-by: Miao Xie Acked-by: Yasunori Goto Cc: David Rientjes Cc: Paul Menage Signed-off-by: Linus Torvalds --- include/linux/cpuset.h | 4 ---- kernel/cpuset.c | 19 ++++++++++++++++--- mm/memory_hotplug.c | 3 --- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h index 2691926fb506..8e540d32c9fe 100644 --- a/include/linux/cpuset.h +++ b/include/linux/cpuset.h @@ -74,8 +74,6 @@ static inline int cpuset_do_slab_mem_spread(void) return current->flags & PF_SPREAD_SLAB; } -extern void cpuset_track_online_nodes(void); - extern int current_cpuset_is_being_rebound(void); extern void rebuild_sched_domains(void); @@ -151,8 +149,6 @@ static inline int cpuset_do_slab_mem_spread(void) return 0; } -static inline void cpuset_track_online_nodes(void) {} - static inline int current_cpuset_is_being_rebound(void) { return 0; diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 81fc6791a296..da7ff6137f37 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -2015,12 +2016,23 @@ static int cpuset_track_online_cpus(struct notifier_block *unused_nb, * Call this routine anytime after node_states[N_HIGH_MEMORY] changes. * See also the previous routine cpuset_track_online_cpus(). */ -void cpuset_track_online_nodes(void) +static int cpuset_track_online_nodes(struct notifier_block *self, + unsigned long action, void *arg) { cgroup_lock(); - top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY]; - scan_for_empty_cpusets(&top_cpuset); + switch (action) { + case MEM_ONLINE: + top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY]; + break; + case MEM_OFFLINE: + top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY]; + scan_for_empty_cpusets(&top_cpuset); + break; + default: + break; + } cgroup_unlock(); + return NOTIFY_OK; } #endif @@ -2036,6 +2048,7 @@ void __init cpuset_init_smp(void) top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY]; hotcpu_notifier(cpuset_track_online_cpus, 0); + hotplug_memory_notifier(cpuset_track_online_nodes, 10); } /** diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 6837a1014372..b5b2b15085a8 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -498,8 +497,6 @@ int add_memory(int nid, u64 start, u64 size) /* we online node here. we can't roll back from here. */ node_set_online(nid); - cpuset_track_online_nodes(); - if (new_pgdat) { ret = register_one_node(nid); /* From f011c2dae6cffc50ef67d9bd937b488ba5db8913 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Wed, 19 Nov 2008 15:36:32 -0800 Subject: [PATCH 055/107] mm: vmalloc allocator off by one Fix off by one bug in the KVA allocator that can leave gaps in the address space. Signed-off-by: Nick Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/vmalloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/vmalloc.c b/mm/vmalloc.c index ba6b0f5f7fac..46aab4dbf618 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -362,7 +362,7 @@ retry: goto found; } - while (addr + size >= first->va_start && addr + size <= vend) { + while (addr + size > first->va_start && addr + size <= vend) { addr = ALIGN(first->va_end + PAGE_SIZE, align); n = rb_next(&first->rb_node); From 496850e5f5a372029ceb2b35c811770a9bb073b6 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Wed, 19 Nov 2008 15:36:33 -0800 Subject: [PATCH 056/107] mm: vmalloc failure flush fix An initial vmalloc failure should start off a synchronous flush of lazy areas, in case someone is in progress flushing them already, which could cause us to return an allocation failure even if there is plenty of KVA free. Signed-off-by: Nick Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/vmalloc.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 46aab4dbf618..04f5e320e744 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -521,6 +521,17 @@ static void __purge_vmap_area_lazy(unsigned long *start, unsigned long *end, spin_unlock(&purge_lock); } +/* + * Kick off a purge of the outstanding lazy areas. Don't bother if somebody + * is already purging. + */ +static void try_purge_vmap_area_lazy(void) +{ + unsigned long start = ULONG_MAX, end = 0; + + __purge_vmap_area_lazy(&start, &end, 0, 0); +} + /* * Kick off a purge of the outstanding lazy areas. */ @@ -528,7 +539,7 @@ static void purge_vmap_area_lazy(void) { unsigned long start = ULONG_MAX, end = 0; - __purge_vmap_area_lazy(&start, &end, 0, 0); + __purge_vmap_area_lazy(&start, &end, 1, 0); } /* @@ -539,7 +550,7 @@ static void free_unmap_vmap_area(struct vmap_area *va) va->flags |= VM_LAZY_FREE; atomic_add((va->va_end - va->va_start) >> PAGE_SHIFT, &vmap_lazy_nr); if (unlikely(atomic_read(&vmap_lazy_nr) > lazy_max_pages())) - purge_vmap_area_lazy(); + try_purge_vmap_area_lazy(); } static struct vmap_area *find_vmap_area(unsigned long addr) From 0ae15132a4f5c758a6ffcde74495641dc3f62ba1 Mon Sep 17 00:00:00 2001 From: Glauber Costa Date: Wed, 19 Nov 2008 15:36:33 -0800 Subject: [PATCH 057/107] mm: vmalloc search restart fix Current vmalloc restart search for a free area in case we can't find one. The reason is there are areas which are lazily freed, and could be possibly freed now. However, current implementation start searching the tree from the last failing address, which is pretty much by definition at the end of address space. So, we fail. The proposal of this patch is to restart the search from the beginning of the requested vstart address. This fixes the regression in running KVM virtual machines for me, described in http://lkml.org/lkml/2008/10/28/349, caused by commit db64fe02258f1507e13fe5212a989922323685ce. Signed-off-by: Glauber Costa Signed-off-by: Nick Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/vmalloc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 04f5e320e744..30f826d484f0 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -324,14 +324,14 @@ static struct vmap_area *alloc_vmap_area(unsigned long size, BUG_ON(size & ~PAGE_MASK); - addr = ALIGN(vstart, align); - va = kmalloc_node(sizeof(struct vmap_area), gfp_mask & GFP_RECLAIM_MASK, node); if (unlikely(!va)) return ERR_PTR(-ENOMEM); retry: + addr = ALIGN(vstart, align); + spin_lock(&vmap_area_lock); /* XXX: could have a last_hole cache */ n = vmap_area_root.rb_node; From 3fa59dfbc3b223f02c26593be69ce6fc9a940405 Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Wed, 19 Nov 2008 15:36:34 -0800 Subject: [PATCH 058/107] cgroup: fix potential deadlock in pre_destroy As Balbir pointed out, memcg's pre_destroy handler has potential deadlock. It has following lock sequence. cgroup_mutex (cgroup_rmdir) -> pre_destroy -> mem_cgroup_pre_destroy-> force_empty -> cpu_hotplug.lock. (lru_add_drain_all-> schedule_work-> get_online_cpus) But, cpuset has following. cpu_hotplug.lock (call notifier) -> cgroup_mutex. (within notifier) Then, this lock sequence should be fixed. Considering how pre_destroy works, it's not necessary to holding cgroup_mutex() while calling it. As a side effect, we don't have to wait at this mutex while memcg's force_empty works.(it can be long when there are tons of pages.) Signed-off-by: KAMEZAWA Hiroyuki Acked-by: Balbir Singh Cc: Li Zefan Cc: Paul Menage Cc: Daisuke Nishimura Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/cgroup.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 358e77564e6f..1a06be61dcd0 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -2472,10 +2472,7 @@ static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry) mutex_unlock(&cgroup_mutex); return -EBUSY; } - - parent = cgrp->parent; - root = cgrp->root; - sb = root->sb; + mutex_unlock(&cgroup_mutex); /* * Call pre_destroy handlers of subsys. Notify subsystems @@ -2483,7 +2480,14 @@ static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry) */ cgroup_call_pre_destroy(cgrp); - if (cgroup_has_css_refs(cgrp)) { + mutex_lock(&cgroup_mutex); + parent = cgrp->parent; + root = cgrp->root; + sb = root->sb; + + if (atomic_read(&cgrp->count) + || !list_empty(&cgrp->children) + || cgroup_has_css_refs(cgrp)) { mutex_unlock(&cgroup_mutex); return -EBUSY; } From 966c8c12dc9e77f931e2281ba25d2f0244b06949 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Wed, 19 Nov 2008 15:36:36 -0800 Subject: [PATCH 059/107] sprint_symbol(): use less stack sprint_symbol(), itself used when dumping stacks, has been wasting 128 bytes of stack: lookup the symbol directly into the buffer supplied by the caller, instead of using a locally declared namebuf. I believe the name != buffer strcpy() is obsolete: the design here dates from when module symbol lookup pointed into a supposedly const but sadly volatile table; nowadays it copies, but an uncalled strcpy() looks better here than the risk of a recursive BUG_ON(). Signed-off-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/kallsyms.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c index 5072cf1685a2..7b8b0f21a5b1 100644 --- a/kernel/kallsyms.c +++ b/kernel/kallsyms.c @@ -304,17 +304,24 @@ int sprint_symbol(char *buffer, unsigned long address) char *modname; const char *name; unsigned long offset, size; - char namebuf[KSYM_NAME_LEN]; + int len; - name = kallsyms_lookup(address, &size, &offset, &modname, namebuf); + name = kallsyms_lookup(address, &size, &offset, &modname, buffer); if (!name) return sprintf(buffer, "0x%lx", address); + if (name != buffer) + strcpy(buffer, name); + len = strlen(buffer); + buffer += len; + if (modname) - return sprintf(buffer, "%s+%#lx/%#lx [%s]", name, offset, - size, modname); + len += sprintf(buffer, "+%#lx/%#lx [%s]", + offset, size, modname); else - return sprintf(buffer, "%s+%#lx/%#lx", name, offset, size); + len += sprintf(buffer, "+%#lx/%#lx", offset, size); + + return len; } /* Look up a kernel symbol and print it to the kernel messages. */ From bda8550deed96687f29992d711a88ea21cff4d26 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Wed, 19 Nov 2008 15:36:36 -0800 Subject: [PATCH 060/107] migration: fix writepage error Page migration's writeout() has got understandably confused by the nasty AOP_WRITEPAGE_ACTIVATE case: as in normal success, a writepage() error has unlocked the page, so writeout() then needs to relock it. Signed-off-by: Hugh Dickins Cc: KAMEZAWA Hiroyuki Cc: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/migrate.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/mm/migrate.c b/mm/migrate.c index 385db89f0c33..1e0d6b237f44 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -522,15 +522,12 @@ static int writeout(struct address_space *mapping, struct page *page) remove_migration_ptes(page, page); rc = mapping->a_ops->writepage(page, &wbc); - if (rc < 0) - /* I/O Error writing */ - return -EIO; if (rc != AOP_WRITEPAGE_ACTIVATE) /* unlocked. Relock */ lock_page(page); - return -EAGAIN; + return (rc < 0) ? -EIO : -EAGAIN; } /* From 63eb6b93ce725e4c5f38fc85dd703d49465b03cb Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Wed, 19 Nov 2008 15:36:37 -0800 Subject: [PATCH 061/107] vmscan: let GFP_NOFS go to swap again In the past, GFP_NOFS (but of course not GFP_NOIO) was allowed to reclaim by writing to swap. That got partially broken in 2.6.23, when may_enter_fs initialization was moved up before the allocation of swap, so its PageSwapCache test was failing the first time around, Fix it by setting may_enter_fs when add_to_swap() succeeds with __GFP_IO. In fact, check __GFP_IO before calling add_to_swap(): allocating swap we're not ready to use just increases disk seeking. Signed-off-by: Hugh Dickins Cc: Rik van Riel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/vmscan.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mm/vmscan.c b/mm/vmscan.c index c141b3e78071..f83a7ed5c6c4 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -623,6 +623,8 @@ static unsigned long shrink_page_list(struct list_head *page_list, * Try to allocate it some swap space here. */ if (PageAnon(page) && !PageSwapCache(page)) { + if (!(sc->gfp_mask & __GFP_IO)) + goto keep_locked; switch (try_to_munlock(page)) { case SWAP_FAIL: /* shouldn't happen */ case SWAP_AGAIN: @@ -634,6 +636,7 @@ static unsigned long shrink_page_list(struct list_head *page_list, } if (!add_to_swap(page, GFP_ATOMIC)) goto activate_locked; + may_enter_fs = 1; } #endif /* CONFIG_SWAP */ From f9454548e17cd56bad081bd7d55a09b001950cbb Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Wed, 19 Nov 2008 15:36:38 -0800 Subject: [PATCH 062/107] don't unlink an active swapfile Peter Cordes is sorry that he rm'ed his swapfiles while they were in use, he then had no pathname to swapoff. It's a curious little oversight, but not one worth a lot of hackery. Kudos to Willy Tarreau for turning this around from a discussion of synthetic pathnames to how to prevent unlink. Mimic immutable: prohibit unlinking an active swapfile in may_delete() (and don't worry my little head over the tiny race window). Signed-off-by: Hugh Dickins Cc: Willy Tarreau Acked-by: Christoph Hellwig Cc: Peter Cordes Cc: Bodo Eggert <7eggert@gmx.de> Cc: David Newall Cc: Peter Zijlstra Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/namei.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/namei.c b/fs/namei.c index 09ce58e49e72..d34e0f9681c6 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1378,7 +1378,7 @@ static int may_delete(struct inode *dir,struct dentry *victim,int isdir) if (IS_APPEND(dir)) return -EPERM; if (check_sticky(dir, victim->d_inode)||IS_APPEND(victim->d_inode)|| - IS_IMMUTABLE(victim->d_inode)) + IS_IMMUTABLE(victim->d_inode) || IS_SWAPFILE(victim->d_inode)) return -EPERM; if (isdir) { if (!S_ISDIR(victim->d_inode->i_mode)) From c0d861afa5c986f7fe23647fbe411cd300f7c927 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Wed, 19 Nov 2008 15:36:41 -0800 Subject: [PATCH 063/107] drivers/video/backlight/da903x.c: introduce missing kfree Error handling code following a kzalloc should free the allocated data. The semantic match that finds the problem is as follows: (http://www.emn.fr/x-info/coccinelle/) // @r exists@ local idexpression x; statement S; expression E; identifier f,l; position p1,p2; expression *ptr != NULL; @@ ( if ((x@p1 = \(kmalloc\|kzalloc\|kcalloc\)(...)) == NULL) S | x@p1 = \(kmalloc\|kzalloc\|kcalloc\)(...); ... if (x == NULL) S ) <... when != x when != if (...) { <+...x...+> } x->f = E ...> ( return \(0\|<+...x...+>\|ptr\); | return@p2 ...; ) @script:python@ p1 << r.p1; p2 << r.p2; @@ print "* file: %s kmalloc %s return %s" % (p1[0].file,p1[0].line,p2[0].line) // Signed-off-by: Julia Lawall Cc: Mike Rapoport Cc: Richard Purdie Cc: Eric Miao Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/backlight/da903x.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/video/backlight/da903x.c b/drivers/video/backlight/da903x.c index 242c38250166..75388b959439 100644 --- a/drivers/video/backlight/da903x.c +++ b/drivers/video/backlight/da903x.c @@ -119,6 +119,7 @@ static int da903x_backlight_probe(struct platform_device *pdev) default: dev_err(&pdev->dev, "invalid backlight device ID(%d)\n", pdev->id); + kfree(data); return -EINVAL; } From 45a3a36b6333b9ddfb0c57602d959a8d05bc47e4 Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Wed, 19 Nov 2008 15:36:42 -0800 Subject: [PATCH 064/107] drivers/hwmon/applesmc.c: add generic MacPro support In order to analyze the SMC of the newer MacPros, applesmc needs to recognize the machine. This patch adds the missing generic dmi_match entry for MacPro models. Signed-off-by: Henrik Rydberg Cc: Nicolas Boichat Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/hwmon/applesmc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index 10977b3d201c..f7dce8b9f64b 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c @@ -1354,6 +1354,10 @@ static __initdata struct dmi_system_id applesmc_whitelist[] = { DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), DMI_MATCH(DMI_PRODUCT_NAME,"MacPro2") }, &applesmc_dmi_data[4]}, + { applesmc_dmi_match, "Apple MacPro", { + DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), + DMI_MATCH(DMI_PRODUCT_NAME, "MacPro") }, + &applesmc_dmi_data[4]}, { applesmc_dmi_match, "Apple iMac 8", { DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), DMI_MATCH(DMI_PRODUCT_NAME, "iMac8") }, From 8e324c19f57cc05922e9cc0f338b58108da45539 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Wed, 19 Nov 2008 15:36:43 -0800 Subject: [PATCH 065/107] MAINTAINERS: change email address for rostedt I find that I answer my email quicker on my home email account, than I do on my work email. Not to mention that I never check my work email while traveling. Please change my email address in the MAINTAINERS file from srostedt@redhat.com to rostedt@goodmis.org. Signed-off-by: Steven Rostedt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 627e4c89328e..618c1ef4a397 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1809,7 +1809,7 @@ S: Maintained FTRACE P: Steven Rostedt -M: srostedt@redhat.com +M: rostedt@goodmis.org S: Maintained FUJITSU FR-V (FRV) PORT From 00d8089c54867053a5aae062b765f257ca419e27 Mon Sep 17 00:00:00 2001 From: Rik van Riel Date: Wed, 19 Nov 2008 15:36:44 -0800 Subject: [PATCH 066/107] vmscan: fix get_scan_ratio() comment Fix the old comment on the scan ratio calculations. Signed-off-by: Rik van Riel Cc: KOSAKI Motohiro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/vmscan.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index f83a7ed5c6c4..7ea1440b53db 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1389,9 +1389,9 @@ static void get_scan_ratio(struct zone *zone, struct scan_control *sc, file_prio = 200 - sc->swappiness; /* - * anon recent_rotated[0] - * %anon = 100 * ----------- / ----------------- * IO cost - * anon + file rotate_sum + * The amount of pressure on anon vs file pages is inversely + * proportional to the fraction of recently scanned pages on + * each list that were recently referenced and in active use. */ ap = (anon_prio + 1) * (zone->recent_scanned[0] + 1); ap /= zone->recent_rotated[0] + 1; From ee11940f8e7a2f064af22d52180cb5f9643eef61 Mon Sep 17 00:00:00 2001 From: Vlada Peric Date: Wed, 19 Nov 2008 15:36:45 -0800 Subject: [PATCH 067/107] cirrusfb: remove unused variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After commit a1d35a7a (cirrusfb: use modedb and add mode_option parameter), these variables are no longer used, so remove them to fix compilation warning. Signed-off-by: Vlada Periæ Acked-by: Krzysztof Helt Cc: Stephen Rothwell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/cirrusfb.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c index 8a8760230bc7..a2aa6ddffbe2 100644 --- a/drivers/video/cirrusfb.c +++ b/drivers/video/cirrusfb.c @@ -2462,8 +2462,7 @@ static int __init cirrusfb_init(void) #ifndef MODULE static int __init cirrusfb_setup(char *options) { - char *this_opt, s[32]; - int i; + char *this_opt; DPRINTK("ENTER\n"); From ea7e743e49b94749fc739baaf160809ed279aeda Mon Sep 17 00:00:00 2001 From: WANG Cong Date: Wed, 19 Nov 2008 15:36:46 -0800 Subject: [PATCH 068/107] hostfs: fix a duplicated global function name fs/hostfs/hostfs_user.c defines do_readlink() as non-static, and so does fs/xfs/linux-2.6/xfs_ioctl.c when CONFIG_XFS_DEBUG=y. So rename do_readlink() in hostfs to hostfs_do_readlink(). I think it's better if XFS guys will also rename their do_readlink(), it's not necessary to use such a general name. Signed-off-by: WANG Cong Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/hostfs/hostfs.h | 2 +- fs/hostfs/hostfs_kern.c | 4 ++-- fs/hostfs/hostfs_user.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/hostfs/hostfs.h b/fs/hostfs/hostfs.h index 6ae9011b95eb..2f34f8f2134b 100644 --- a/fs/hostfs/hostfs.h +++ b/fs/hostfs/hostfs.h @@ -81,7 +81,7 @@ extern int do_rmdir(const char *file); extern int do_mknod(const char *file, int mode, unsigned int major, unsigned int minor); extern int link_file(const char *from, const char *to); -extern int do_readlink(char *file, char *buf, int size); +extern int hostfs_do_readlink(char *file, char *buf, int size); extern int rename_file(char *from, char *to); extern int do_statfs(char *root, long *bsize_out, long long *blocks_out, long long *bfree_out, long long *bavail_out, diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index 7f34f4385de0..3a31451ac170 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -168,7 +168,7 @@ static char *follow_link(char *link) if (name == NULL) goto out; - n = do_readlink(link, name, len); + n = hostfs_do_readlink(link, name, len); if (n < len) break; len *= 2; @@ -943,7 +943,7 @@ int hostfs_link_readpage(struct file *file, struct page *page) name = inode_name(page->mapping->host, 0); if (name == NULL) return -ENOMEM; - err = do_readlink(name, buffer, PAGE_CACHE_SIZE); + err = hostfs_do_readlink(name, buffer, PAGE_CACHE_SIZE); kfree(name); if (err == PAGE_CACHE_SIZE) err = -E2BIG; diff --git a/fs/hostfs/hostfs_user.c b/fs/hostfs/hostfs_user.c index 53fd0a67c11a..b79424f93282 100644 --- a/fs/hostfs/hostfs_user.c +++ b/fs/hostfs/hostfs_user.c @@ -377,7 +377,7 @@ int link_file(const char *to, const char *from) return 0; } -int do_readlink(char *file, char *buf, int size) +int hostfs_do_readlink(char *file, char *buf, int size) { int n; From 33d283bef23132c48195eafc21449f8ba88fce6b Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Wed, 19 Nov 2008 15:36:48 -0800 Subject: [PATCH 069/107] cgroups: fix a serious bug in cgroupstats Try this, and you'll get oops immediately: # cd Documentation/accounting/ # gcc -o getdelays getdelays.c # mount -t cgroup -o debug xxx /mnt # ./getdelays -C /mnt/tasks Because a normal file's dentry->d_fsdata is a pointer to struct cftype, not struct cgroup. After the patch, it returns EINVAL if we try to get cgroupstats from a normal file. Cc: Balbir Singh Signed-off-by: Li Zefan Acked-by: Paul Menage Cc: [2.6.25.x, 2.6.26.x, 2.6.27.x] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/cgroup.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 1a06be61dcd0..fe00b3b983a8 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -2039,10 +2039,13 @@ int cgroupstats_build(struct cgroupstats *stats, struct dentry *dentry) struct cgroup *cgrp; struct cgroup_iter it; struct task_struct *tsk; + /* - * Validate dentry by checking the superblock operations + * Validate dentry by checking the superblock operations, + * and make sure it's a directory. */ - if (dentry->d_sb->s_op != &cgroup_ops) + if (dentry->d_sb->s_op != &cgroup_ops || + !S_ISDIR(dentry->d_inode->i_mode)) goto err; ret = 0; From f55491a4bcbe8bab337bc00830ca12d703ea2613 Mon Sep 17 00:00:00 2001 From: Mike Rapoport <[mailto:mike@compulab.co.il]> Date: Wed, 19 Nov 2008 15:36:49 -0800 Subject: [PATCH 070/107] drivers/video/backlight/da903x.c: introduce one more missing kfree One more error handling code should have kfree as well Signed-off-by: Mike Rapoport Acked-by: Eric Miao Cc: Richard Purdie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/backlight/da903x.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/video/backlight/da903x.c b/drivers/video/backlight/da903x.c index 75388b959439..93bb4340cc64 100644 --- a/drivers/video/backlight/da903x.c +++ b/drivers/video/backlight/da903x.c @@ -131,6 +131,7 @@ static int da903x_backlight_probe(struct platform_device *pdev) data, &da903x_backlight_ops); if (IS_ERR(bl)) { dev_err(&pdev->dev, "failed to register backlight\n"); + kfree(data); return PTR_ERR(bl); } From 06b0d4dc14a44dd9b57321c24f7eeb10b345abd8 Mon Sep 17 00:00:00 2001 From: "Stanley.Miao" Date: Wed, 19 Nov 2008 15:36:50 -0800 Subject: [PATCH 071/107] W1 OMAP: Fix OMAP LDP boot crash OMAP LDP boot crash. This is because w1 subsystem changed the search interface, so update omap_hdq's search interface to follow the change. Signed-off-by: Stanley.Miao Signed-off-by: Evgeniy Polyakov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/w1/masters/omap_hdq.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/w1/masters/omap_hdq.c b/drivers/w1/masters/omap_hdq.c index 1295625c4825..c973889110c8 100644 --- a/drivers/w1/masters/omap_hdq.c +++ b/drivers/w1/masters/omap_hdq.c @@ -86,8 +86,8 @@ static struct platform_driver omap_hdq_driver = { static u8 omap_w1_read_byte(void *_hdq); static void omap_w1_write_byte(void *_hdq, u8 byte); static u8 omap_w1_reset_bus(void *_hdq); -static void omap_w1_search_bus(void *_hdq, u8 search_type, - w1_slave_found_callback slave_found); +static void omap_w1_search_bus(void *_hdq, struct w1_master *master_dev, + u8 search_type, w1_slave_found_callback slave_found); static struct w1_bus_master omap_w1_master = { @@ -231,8 +231,8 @@ static u8 omap_w1_reset_bus(void *_hdq) } /* W1 search callback function */ -static void omap_w1_search_bus(void *_hdq, u8 search_type, - w1_slave_found_callback slave_found) +static void omap_w1_search_bus(void *_hdq, struct w1_master *master_dev, + u8 search_type, w1_slave_found_callback slave_found) { u64 module_id, rn_le, cs, id; @@ -249,7 +249,7 @@ static void omap_w1_search_bus(void *_hdq, u8 search_type, cs = w1_calc_crc8((u8 *)&rn_le, 7); id = (cs << 56) | module_id; - slave_found(_hdq, id); + slave_found(master_dev, id); } static int _omap_hdq_reset(struct hdq_data *hdq_data) From 9f92f4719764acf1c9185a5958200887a43e3483 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 19 Nov 2008 15:36:51 -0800 Subject: [PATCH 072/107] cciss: fix DEBUG printk formats Fix printk format warnings when CCISS_DEBUG is defined. drivers/block/cciss.c:2856: warning: format '%d' expects type 'int', but argument 2 has type 'long unsigned int' drivers/block/cciss.c:3205: warning: format '%x' expects type 'unsigned int', but argument 2 has type 'long unsigned int' drivers/block/cciss.c:3236: warning: format '%x' expects type 'unsigned int', but argument 2 has type '__u64' drivers/block/cciss.c:3246: warning: format '%x' expects type 'unsigned int', but argument 2 has type '__u64' Signed-off-by: Randy Dunlap Cc: Mike Miller Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/cciss.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 12de1fdaa6c6..9364dc554257 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -2847,7 +2847,7 @@ static void do_cciss_request(struct request_queue *q) h->maxSG = seg; #ifdef CCISS_DEBUG - printk(KERN_DEBUG "cciss: Submitting %d sectors in %d segments\n", + printk(KERN_DEBUG "cciss: Submitting %lu sectors in %d segments\n", creq->nr_sectors, seg); #endif /* CCISS_DEBUG */ @@ -3197,7 +3197,7 @@ static int __devinit cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) c->paddr = pci_resource_start(pdev, 0); /* addressing mode bits already removed */ #ifdef CCISS_DEBUG - printk("address 0 = %x\n", c->paddr); + printk("address 0 = %lx\n", c->paddr); #endif /* CCISS_DEBUG */ c->vaddr = remap_pci_mem(c->paddr, 0x250); @@ -3224,7 +3224,8 @@ static int __devinit cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) #endif /* CCISS_DEBUG */ cfg_base_addr_index = find_PCI_BAR_index(pdev, cfg_base_addr); #ifdef CCISS_DEBUG - printk("cfg base address index = %x\n", cfg_base_addr_index); + printk("cfg base address index = %llx\n", + (unsigned long long)cfg_base_addr_index); #endif /* CCISS_DEBUG */ if (cfg_base_addr_index == -1) { printk(KERN_WARNING "cciss: Cannot find cfg_base_addr_index\n"); @@ -3234,7 +3235,7 @@ static int __devinit cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) cfg_offset = readl(c->vaddr + SA5_CTMEM_OFFSET); #ifdef CCISS_DEBUG - printk("cfg offset = %x\n", cfg_offset); + printk("cfg offset = %llx\n", (unsigned long long)cfg_offset); #endif /* CCISS_DEBUG */ c->cfgtable = remap_pci_mem(pci_resource_start(pdev, cfg_base_addr_index) + From b09bc6cbae4dd3a2d35722668ef2c502a7b8b093 Mon Sep 17 00:00:00 2001 From: Andiry Xu Date: Fri, 14 Nov 2008 11:42:29 +0800 Subject: [PATCH 073/107] USB: fix SB700 usb subsystem hang bug This patch is required for AMD SB700 south bridge revision A12 and A13 to avoid USB subsystem hang symptom. The USB subsystem hang symptom is observed when the system has multiple USB devices connected to it. In some cases a USB hub may be required to observe this symptom. This patch works around the problem by correcting the internal register setting that will help by changing the behavior of the internal logic to avoid the USB subsystem hang issue. The change in the behavior of the logic does not impact the normal operation of the USB subsystem. Reported-by: Volker Armin Hemmann Tested-by: Volker Armin Hemmann Signed-off-by: Andiry Xu Signed-off-by: Libin Yang Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-pci.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index c46a58f9181d..9d0ea573aef6 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -66,6 +66,8 @@ static int ehci_pci_setup(struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); struct pci_dev *pdev = to_pci_dev(hcd->self.controller); + struct pci_dev *p_smbus; + u8 rev; u32 temp; int retval; @@ -166,6 +168,25 @@ static int ehci_pci_setup(struct usb_hcd *hcd) pci_write_config_byte(pdev, 0x4b, tmp | 0x20); } break; + case PCI_VENDOR_ID_ATI: + /* SB700 old version has a bug in EHCI controller, + * which causes usb devices lose response in some cases. + */ + if (pdev->device == 0x4396) { + p_smbus = pci_get_device(PCI_VENDOR_ID_ATI, + PCI_DEVICE_ID_ATI_SBX00_SMBUS, + NULL); + if (!p_smbus) + break; + rev = p_smbus->revision; + if ((rev == 0x3a) || (rev == 0x3b)) { + u8 tmp; + pci_read_config_byte(pdev, 0x53, &tmp); + pci_write_config_byte(pdev, 0x53, tmp | (1<<3)); + } + pci_dev_put(p_smbus); + } + break; } ehci_reset(ehci); From aa5cbbecd903e5692b64f871c385ece1c5508eac Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 17 Nov 2008 09:08:16 +0200 Subject: [PATCH 074/107] usb: musb: fix bug in musb_schedule This bug was introduced recently. Fix it before bigger problems appear. Signed-off-by: Felipe Balbi Cc: Sergei Shtylyov Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index e45e70bcc5e2..cc64462d4c4e 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -1757,7 +1757,7 @@ static int musb_schedule( } } /* use bulk reserved ep1 if no other ep is free */ - if (best_end > 0 && qh->type == USB_ENDPOINT_XFER_BULK) { + if (best_end < 0 && qh->type == USB_ENDPOINT_XFER_BULK) { hw_ep = musb->bulk_ep; if (is_in) head = &musb->in_bulk; From 9beba53dc5c330d781ecc0ad8ea081c2d100ff9f Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 17 Nov 2008 16:12:32 -0500 Subject: [PATCH 075/107] USB: storage: updates unusual_devs entry for the Nokia 6300 This patch (as1169) modifies the unusual_devs entry for the Nokia 6300. According to Maciej Gierok and David McBride , the revision limits need to be wider. This fixes Bugzilla #11768. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index d4e5fc86e43c..096a439baa37 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -240,7 +240,7 @@ UNUSUAL_DEV( 0x0421, 0x04b9, 0x0551, 0x0551, US_FL_FIX_CAPACITY ), /* Reported by Richard Nauber */ -UNUSUAL_DEV( 0x0421, 0x04fa, 0x0601, 0x0601, +UNUSUAL_DEV( 0x0421, 0x04fa, 0x0550, 0x0660, "Nokia", "6300", US_SC_DEVICE, US_PR_DEVICE, NULL, From 589afd3bec907f02c133d7b8185b8af534f14a8e Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 17 Nov 2008 14:32:16 -0500 Subject: [PATCH 076/107] USB: storage: update unusual_devs entries for Nokia 5300 and 5310 This patch (as1168) updates the unusual_devs entry for the Nokia 5300. According to Jorge Lucangeli Obes , some existing models have a revision number lower than the lower limit of the current entry. The patch also moves the entry for the Nokia 5310 to its correct place in the file. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 096a439baa37..6da9a7a962a8 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -167,6 +167,13 @@ UNUSUAL_DEV( 0x0421, 0x005d, 0x0001, 0x0600, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY ), +/* Patch for Nokia 5310 capacity */ +UNUSUAL_DEV( 0x0421, 0x006a, 0x0000, 0x0591, + "Nokia", + "5310", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_CAPACITY ), + /* Reported by Mario Rettig */ UNUSUAL_DEV( 0x0421, 0x042e, 0x0100, 0x0100, "Nokia", @@ -233,7 +240,7 @@ UNUSUAL_DEV( 0x0421, 0x0495, 0x0370, 0x0370, US_FL_MAX_SECTORS_64 ), /* Reported by Cedric Godin */ -UNUSUAL_DEV( 0x0421, 0x04b9, 0x0551, 0x0551, +UNUSUAL_DEV( 0x0421, 0x04b9, 0x0500, 0x0551, "Nokia", "5300", US_SC_DEVICE, US_PR_DEVICE, NULL, From 9c264521a9f836541c122b00f505cfd60cc5bbb5 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Sat, 15 Nov 2008 19:53:21 -0800 Subject: [PATCH 077/107] USB: gadget rndis: stop windows self-immolation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Somewhere in the conversion of the RNDIS gadget code to the new framework, the descriptor of its data interface seems to have been copied from the CDC Ethernet driver. Unfortunately that means it got a nonzero altsetting ... which is incorrect. Issue uncovered by Richard Röjfors . This patch fixes that problem, and resolves at least some cases of Windows XP bluescreening itself. Tested-by: Richard Röjfors . Signed-off-by: David Brownell Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/f_rndis.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c index 659b3d9671c4..8afb14a4a72f 100644 --- a/drivers/usb/gadget/f_rndis.c +++ b/drivers/usb/gadget/f_rndis.c @@ -172,7 +172,6 @@ static struct usb_interface_descriptor rndis_data_intf __initdata = { .bDescriptorType = USB_DT_INTERFACE, /* .bInterfaceNumber = DYNAMIC */ - .bAlternateSetting = 1, .bNumEndpoints = 2, .bInterfaceClass = USB_CLASS_CDC_DATA, .bInterfaceSubClass = 0, From ff3495052af48f7a2bf7961b131dc9e161dae19c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20R=C3=B6jfors?= Date: Sat, 15 Nov 2008 19:53:24 -0800 Subject: [PATCH 078/107] USB: gadget rndis: send notifications MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It turns out that atomic_inc_return() returns the *new* value not the original one, so the logic in rndis_response_available() kept the first RNDIS response notification from getting out. This prevented interoperation with MS-Windows (but not Linux). Fix this to make RNDIS behave again. Signed-off-by: Richard Röjfors Signed-off-by: David Brownell Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/f_rndis.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c index 8afb14a4a72f..428b5993575a 100644 --- a/drivers/usb/gadget/f_rndis.c +++ b/drivers/usb/gadget/f_rndis.c @@ -302,7 +302,7 @@ static void rndis_response_available(void *_rndis) __le32 *data = req->buf; int status; - if (atomic_inc_return(&rndis->notify_count)) + if (atomic_inc_return(&rndis->notify_count) != 1) return; /* Send RNDIS RESPONSE_AVAILABLE notification; a From f1c0a2a3aff53698f4855968d576464041d49b39 Mon Sep 17 00:00:00 2001 From: Pete Zaitcev Date: Fri, 14 Nov 2008 09:47:41 -0700 Subject: [PATCH 079/107] USB: usbmon: fix read(2) There's a bug in the usbmon binary reader: When using read() to fetch the packets and a packet's data is partially read, the next read call will once again return up to len_cap bytes of data. The b_read counter is not regarded when determining the remaining chunk size. So, when dumping USB data with "cat /dev/usbmon0 > usbmon.trace" while reading from a USB storage device and analyzing the dump file afterwards it will get out of sync after a couple of packets. Signed-off-by: Ingo van Lil Signed-off-by: Pete Zaitcev Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/mon/mon_bin.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c index c9de3f027aab..e06810aef2df 100644 --- a/drivers/usb/mon/mon_bin.c +++ b/drivers/usb/mon/mon_bin.c @@ -687,7 +687,10 @@ static ssize_t mon_bin_read(struct file *file, char __user *buf, } if (rp->b_read >= sizeof(struct mon_bin_hdr)) { - step_len = min(nbytes, (size_t)ep->len_cap); + step_len = ep->len_cap; + step_len -= rp->b_read - sizeof(struct mon_bin_hdr); + if (step_len > nbytes) + step_len = nbytes; offset = rp->b_out + PKT_SIZE; offset += rp->b_read - sizeof(struct mon_bin_hdr); if (offset >= rp->b_size) From 5091b58751d9bf51e92aa9e07f3332dcacc2af1c Mon Sep 17 00:00:00 2001 From: M Kondrin Date: Fri, 14 Nov 2008 13:02:45 +0300 Subject: [PATCH 080/107] USB: ACE1001 patch for cp2101.c The patch which adds IDs for AKTAKOM USB->RS232 cable (http://www.aktakom.ru/product/kio/ace-1001.htm) is attached. From: M Kondrin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp2101.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c index 9035d7256b03..cfaf1f085535 100644 --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp2101.c @@ -56,6 +56,7 @@ static void cp2101_shutdown(struct usb_serial *); static int debug; static struct usb_device_id id_table [] = { + { USB_DEVICE(0x0471, 0x066A) }, /* AKTAKOM ACE-1001 cable */ { USB_DEVICE(0x0489, 0xE000) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */ { USB_DEVICE(0x08e6, 0x5501) }, /* Gemalto Prox-PU/CU contactless smartcard reader */ { USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */ From a134f85c131ffd56720e38af2967ec6265480757 Mon Sep 17 00:00:00 2001 From: Balazs Scheidler Date: Thu, 20 Nov 2008 01:07:24 -0800 Subject: [PATCH 081/107] TPROXY: fill struct flowi->flags in udp_sendmsg() udp_sendmsg() didn't fill struct flowi->flags, which means that the route lookup would fail for non-local IPs even if the IP_TRANSPARENT sockopt was set. This prevents sendto() to work properly for UDP sockets, whereas bind(foreign-ip) + connect() + send() worked fine. Signed-off-by: Balazs Scheidler Signed-off-by: David S. Miller --- net/ipv4/udp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index cf02701ced48..98c1fd09be88 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -633,6 +633,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, .saddr = saddr, .tos = tos } }, .proto = sk->sk_protocol, + .flags = inet_sk_flowi_flags(sk), .uli_u = { .ports = { .sport = inet->sport, .dport = dport } } }; From c82838458200ec4167ce7083b0a17474150c5bf7 Mon Sep 17 00:00:00 2001 From: Balazs Scheidler Date: Thu, 20 Nov 2008 01:08:06 -0800 Subject: [PATCH 082/107] TPROXY: supply a struct flowi->flags argument in inet_sk_rebuild_header() inet_sk_rebuild_header() does a new route lookup if the dst_entry associated with a socket becomes stale. However inet_sk_rebuild_header() didn't use struct flowi->flags, causing the route lookup to fail for foreign-bound IP_TRANSPARENT sockets, causing an error state to be set for the sockets in question. Signed-off-by: Balazs Scheidler Signed-off-by: David S. Miller --- net/ipv4/af_inet.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 1fbff5fa4241..1aa2dc9e380e 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1117,6 +1117,7 @@ int inet_sk_rebuild_header(struct sock *sk) }, }, .proto = sk->sk_protocol, + .flags = inet_sk_flowi_flags(sk), .uli_u = { .ports = { .sport = inet->sport, From fb5e2f9b9410a4362897d12dc1ed4f7cec1b0d45 Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Mon, 17 Nov 2008 20:29:58 +0000 Subject: [PATCH 083/107] sh: sh_eth: Update to change of mii_bus Update to change of mii_bus interface and fix some warning. Signed-off-by: Nobuhiro Iwamatsu Signed-off-by: David S. Miller --- drivers/net/sh_eth.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c index a24bb68887ab..59f242a67714 100644 --- a/drivers/net/sh_eth.c +++ b/drivers/net/sh_eth.c @@ -927,7 +927,7 @@ static int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev) struct sh_eth_private *mdp = netdev_priv(ndev); struct sh_eth_txdesc *txdesc; u32 entry; - int flags; + unsigned long flags; spin_lock_irqsave(&mdp->lock, flags); if ((mdp->cur_tx - mdp->dirty_tx) >= (TX_RING_SIZE - 4)) { @@ -1141,7 +1141,7 @@ static int sh_mdio_init(struct net_device *ndev, int id) /* Hook up MII support for ethtool */ mdp->mii_bus->name = "sh_mii"; mdp->mii_bus->parent = &ndev->dev; - mdp->mii_bus->id[0] = id; + snprintf(mdp->mii_bus->id, MII_BUS_ID_SIZE, "%x", id); /* PHY IRQ */ mdp->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL); From bcb3336ce4354395e38df7e2da110fca61f86a84 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 18 Nov 2008 04:28:35 +0000 Subject: [PATCH 084/107] mv643xx_eth: fix the order of mdiobus_{unregister, free}() calls Signed-off-by: Lennert Buytenhek Signed-off-by: David S. Miller --- drivers/net/mv643xx_eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index b9dcdbd369f8..baa7e845a011 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -2435,8 +2435,8 @@ static int mv643xx_eth_shared_remove(struct platform_device *pdev) struct mv643xx_eth_shared_platform_data *pd = pdev->dev.platform_data; if (pd == NULL || pd->shared_smi == NULL) { - mdiobus_free(msp->smi_bus); mdiobus_unregister(msp->smi_bus); + mdiobus_free(msp->smi_bus); } if (msp->err_interrupt != NO_IRQ) free_irq(msp->err_interrupt, msp); From 11b4aa03b212cbaa969df25e723fbd400a6e24b9 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 18 Nov 2008 04:28:58 +0000 Subject: [PATCH 085/107] mv643xx_eth: fix recycle check bound When mv643xx_eth allocates skbuffs, it adds 'dma_get_cache_alignment() - 1' to the length it needs, so that it can align the skb's ->data pointer to a cache boundary. When checking whether a transmitted skbuff can be reused as a receive buffer, these bytes needs to be included into the minimum bound for the recycle check. Signed-off-by: Lennert Buytenhek Signed-off-by: David S. Miller --- drivers/net/mv643xx_eth.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index baa7e845a011..e513f76f2a9f 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -899,7 +899,8 @@ static int txq_reclaim(struct tx_queue *txq, int budget, int force) if (skb != NULL) { if (skb_queue_len(&mp->rx_recycle) < mp->default_rx_ring_size && - skb_recycle_check(skb, mp->skb_size)) + skb_recycle_check(skb, mp->skb_size + + dma_get_cache_alignment() - 1)) __skb_queue_head(&mp->rx_recycle, skb); else dev_kfree_skb(skb); From a7f75c0c9cfb628512b30795bcba02c8a97e03a0 Mon Sep 17 00:00:00 2001 From: Pantelis Koukousoulas Date: Thu, 20 Nov 2008 01:48:46 -0800 Subject: [PATCH 086/107] asix: Fix asix-based cards connecting to 10/100Mbs LAN. Add AX_MEDIUM_ENCK also when speed = 10/100Mbps. This allows my belkin f5d5055 to work with my 100Mbps switch and with an old 10Mbps ISA card. Without this patch, the card is recognized and the interface is brought up fine, but no packets actually flow through the interface. Signed-off-by: Pantelis Koukousoulas Acked-by: David Hollis Signed-off-by: David S. Miller --- drivers/net/usb/asix.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index e12cdb4543b4..de57490103fc 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -1102,12 +1102,14 @@ static int ax88178_link_reset(struct usbnet *dev) mode = AX88178_MEDIUM_DEFAULT; if (ecmd.speed == SPEED_1000) - mode |= AX_MEDIUM_GM | AX_MEDIUM_ENCK; + mode |= AX_MEDIUM_GM; else if (ecmd.speed == SPEED_100) mode |= AX_MEDIUM_PS; else mode &= ~(AX_MEDIUM_PS | AX_MEDIUM_GM); + mode |= AX_MEDIUM_ENCK; + if (ecmd.duplex == DUPLEX_FULL) mode |= AX_MEDIUM_FD; else From eafdcb433f854c8cb06747a80fa3df7c72147be6 Mon Sep 17 00:00:00 2001 From: Vernon Sauder Date: Thu, 20 Nov 2008 01:56:08 -0800 Subject: [PATCH 087/107] smc911x: Fix printf format typo in smc911x driver. Signed-off-by: Vernon Sauder Signed-off-by: David S. Miller --- drivers/net/smc911x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index 1f26ab0e7986..b185cd12269c 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -1813,7 +1813,7 @@ static int __init smc911x_probe(struct net_device *dev) val = SMC_GET_BYTE_TEST(lp); DBG(SMC_DEBUG_MISC, "%s: endian probe returned 0x%04x\n", CARDNAME, val); if (val != 0x87654321) { - printk(KERN_ERR "Invalid chip endian 0x08%x\n",val); + printk(KERN_ERR "Invalid chip endian 0x%08x\n",val); retval = -ENODEV; goto err_out; } From 3aa4614da741f10b09559a5675c79e2eff5cccd8 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 20 Nov 2008 04:07:14 -0800 Subject: [PATCH 088/107] pkt_sched: fix missing check for packet overrun in qdisc_dump_stab() nla_nest_start() might return NULL, causing a NULL pointer dereference. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/sched/sch_api.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index b16ad2972c6b..6ab4a2f92ca0 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -417,6 +417,8 @@ static int qdisc_dump_stab(struct sk_buff *skb, struct qdisc_size_table *stab) struct nlattr *nest; nest = nla_nest_start(skb, TCA_STAB); + if (nest == NULL) + goto nla_put_failure; NLA_PUT(skb, TCA_STAB_BASE, sizeof(stab->szopts), &stab->szopts); nla_nest_end(skb, nest); From eedd726efbc439dbed94fb8577e5533a986b341f Mon Sep 17 00:00:00 2001 From: Benjamin Thery Date: Thu, 20 Nov 2008 04:16:12 -0800 Subject: [PATCH 089/107] ipv6: use seq_release_private for ip6mr.c /proc entries In ip6mr.c, /proc entries /proc/net/ip6_mr_cache and /proc/net/ip6_mr_vif are opened with seq_open_private(), thus seq_release_private() should be used to release them. Should fix a small memory leak. Signed-off-by: Benjamin Thery Signed-off-by: David S. Miller --- net/ipv6/ip6mr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 52a7eb0e2c2c..0524769632e7 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c @@ -224,7 +224,7 @@ static struct file_operations ip6mr_vif_fops = { .open = ip6mr_vif_open, .read = seq_read, .llseek = seq_lseek, - .release = seq_release, + .release = seq_release_private, }; static void *ipmr_mfc_seq_start(struct seq_file *seq, loff_t *pos) @@ -338,7 +338,7 @@ static struct file_operations ip6mr_mfc_fops = { .open = ipmr_mfc_open, .read = seq_read, .llseek = seq_lseek, - .release = seq_release, + .release = seq_release_private, }; #endif From a849854fc7e200d5e5a437dec9c1d0e8b105e50f Mon Sep 17 00:00:00 2001 From: Alan Jenkins Date: Thu, 20 Nov 2008 04:18:25 -0800 Subject: [PATCH 090/107] atl2: don't request irq on resume if netif running If the device is suspended with the cable disconnected, then resumed with the cable connected, dev->open is called before resume. During resume, we request an IRQ, but the IRQ was already assigned during dev->open, resulting in the warning shown below. Don't request an IRQ if the device is running. Call Trace: [] warn_on_slowpath+0x40/0x59 [] raw_pci_read+0x4d/0x55 [] pci_read+0x1c/0x21 [] __pci_find_next_cap_ttl+0x44/0x70 [] __pci_find_next_cap+0x1a/0x1f [] pci_find_capability+0x28/0x2c [] pci_msi_check_device+0x53/0x62 [] pci_enable_msi+0x3a/0x1cd [] atl2_write_phy_reg+0x40/0x5f [atl2] [] dma_generic_alloc_coherent+0x0/0xd7 [] atl2_request_irq+0x15/0x49 [atl2] [] atl2_open+0x20b/0x297 [atl2] [] dev_open+0x62/0x91 [] dev_change_flags+0x93/0x141 [] do_setlink+0x238/0x2d5 [] rtnl_setlink+0xa9/0xbf [] mutex_lock+0xb/0x19 [] rtnl_dump_ifinfo+0x0/0x69 [] rtnl_setlink+0x0/0xbf [] rtnetlink_rcv_msg+0x185/0x19f [] sock_rmalloc+0x23/0x57 [] rtnetlink_rcv_msg+0x0/0x19f [] netlink_rcv_skb+0x2d/0x71 [] rtnetlink_rcv+0x14/0x1a [] netlink_unicast+0x184/0x1e4 [] netlink_sendmsg+0x233/0x240 [] sock_sendmsg+0xb7/0xd0 [] autoremove_wake_function+0x0/0x2b [] autoremove_wake_function+0x0/0x2b [] mempool_alloc+0x2d/0x9e [] scsi_pool_alloc_command+0x35/0x4f [] mutex_lock+0xb/0x19 [] unix_stream_recvmsg+0x357/0x3e2 [] copy_from_user+0x23/0x4f [] verify_iovec+0x3e/0x6c [] sys_sendmsg+0x18d/0x1f0 [] sys_recvmsg+0x146/0x1c8 [] sys_recvmsg+0x1b4/0x1c8 [] __wake_up+0xf/0x15 [] netlink_table_ungrab+0x17/0x19 [] copy_to_user+0x25/0x3b [] move_addr_to_user+0x50/0x68 [] sys_getsockname+0x6f/0x9a [] sys_getsockname+0x89/0x9a [] do_wp_page+0x3ae/0x41a [] handle_mm_fault+0x4c5/0x540 [] sys_socketcall+0x176/0x1b0 [] sysenter_do_call+0x12/0x21 Signed-off-by: Alan Jenkins Signed-off-by: Jay Cliburn Signed-off-by: David S. Miller --- drivers/net/atlx/atl2.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/atlx/atl2.c b/drivers/net/atlx/atl2.c index f5bdc92c1a65..8571e8c0bc67 100644 --- a/drivers/net/atlx/atl2.c +++ b/drivers/net/atlx/atl2.c @@ -1690,9 +1690,11 @@ static int atl2_resume(struct pci_dev *pdev) ATL2_WRITE_REG(&adapter->hw, REG_WOL_CTRL, 0); - err = atl2_request_irq(adapter); - if (netif_running(netdev) && err) - return err; + if (netif_running(netdev)) { + err = atl2_request_irq(adapter); + if (err) + return err; + } atl2_reset_hw(&adapter->hw); From 5ece6c2ddd6f7da9e95dc325c742c0f5afbcecbe Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Thu, 20 Nov 2008 04:20:10 -0800 Subject: [PATCH 091/107] net: fix tiny output corruption of /proc/net/snmp6 Because "name" is static, it can be occasionally be filled with somewhat garbage if two processes read /proc/net/snmp6. Also, remove useless casts and "-1" -- snprintf() correctly terminates it's output. Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- net/ipv6/proc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index 07f0b76e7427..97c17fdd6f75 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c @@ -132,7 +132,7 @@ static struct snmp_mib snmp6_udplite6_list[] = { static void snmp6_seq_show_icmpv6msg(struct seq_file *seq, void **mib) { - static char name[32]; + char name[32]; int i; /* print by name -- deprecated items */ @@ -144,7 +144,7 @@ static void snmp6_seq_show_icmpv6msg(struct seq_file *seq, void **mib) p = icmp6type2name[icmptype]; if (!p) /* don't print un-named types here */ continue; - (void) snprintf(name, sizeof(name)-1, "Icmp6%s%s", + snprintf(name, sizeof(name), "Icmp6%s%s", i & 0x100 ? "Out" : "In", p); seq_printf(seq, "%-32s\t%lu\n", name, snmp_fold_field(mib, i)); @@ -157,7 +157,7 @@ static void snmp6_seq_show_icmpv6msg(struct seq_file *seq, void **mib) val = snmp_fold_field(mib, i); if (!val) continue; - (void) snprintf(name, sizeof(name)-1, "Icmp6%sType%u", + snprintf(name, sizeof(name), "Icmp6%sType%u", i & 0x100 ? "Out" : "In", i & 0xff); seq_printf(seq, "%-32s\t%lu\n", name, val); } From 9e86786a4b17ad186f456dc6ac0508a17556731b Mon Sep 17 00:00:00 2001 From: David Daney Date: Sat, 20 Sep 2008 10:16:36 -0700 Subject: [PATCH 092/107] MIPS: Malta: Fix include paths in malta-amon.c On linux-queue, malta doesn't build after the include file relocation. This should fix it. There some occurrences of 'asm-mips' in the comments of quite a few files, but this is the only place I found it in any code. Signed-off-by: David Daney Signed-off-by: Ralf Baechle --- arch/mips/mti-malta/malta-amon.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/mips/mti-malta/malta-amon.c b/arch/mips/mti-malta/malta-amon.c index 96236bf33838..df9e526312a2 100644 --- a/arch/mips/mti-malta/malta-amon.c +++ b/arch/mips/mti-malta/malta-amon.c @@ -22,9 +22,9 @@ #include #include -#include -#include -#include +#include +#include +#include int amon_cpu_avail(int cpu) { From 1b432840d0a4740020e29ae7a00717ef8f44954b Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 31 Oct 2008 14:24:29 +0100 Subject: [PATCH 093/107] MIPS: RB532: GPIO register offsets are relative to GPIOBASE This patch fixes the wrong use of GPIO register offsets in devices.c. To avoid further problems, use gpio_get_value to return the NAND status instead of our own expanded code. Also define the zero offset of the alternate function register to allow consistent access. Signed-off-by: Florian Fainelli Signed-off-by: Phil Sutter Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mach-rc32434/rb.h | 14 ++++++++------ arch/mips/rb532/devices.c | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/arch/mips/include/asm/mach-rc32434/rb.h b/arch/mips/include/asm/mach-rc32434/rb.h index 79e8ef67d0d3..f25a84916703 100644 --- a/arch/mips/include/asm/mach-rc32434/rb.h +++ b/arch/mips/include/asm/mach-rc32434/rb.h @@ -40,12 +40,14 @@ #define BTCS 0x010040 #define BTCOMPARE 0x010044 #define GPIOBASE 0x050000 -#define GPIOCFG 0x050004 -#define GPIOD 0x050008 -#define GPIOILEVEL 0x05000C -#define GPIOISTAT 0x050010 -#define GPIONMIEN 0x050014 -#define IMASK6 0x038038 +/* Offsets relative to GPIOBASE */ +#define GPIOFUNC 0x00 +#define GPIOCFG 0x04 +#define GPIOD 0x08 +#define GPIOILEVEL 0x0C +#define GPIOISTAT 0x10 +#define GPIONMIEN 0x14 +#define IMASK6 0x38 #define LO_WPX (1 << 0) #define LO_ALE (1 << 1) #define LO_CLE (1 << 2) diff --git a/arch/mips/rb532/devices.c b/arch/mips/rb532/devices.c index 2f22d714d5b0..c1c29181bd46 100644 --- a/arch/mips/rb532/devices.c +++ b/arch/mips/rb532/devices.c @@ -118,7 +118,7 @@ static struct platform_device cf_slot0 = { /* Resources and device for NAND */ static int rb532_dev_ready(struct mtd_info *mtd) { - return readl(IDT434_REG_BASE + GPIOD) & GPIO_RDY; + return gpio_get_value(GPIO_RDY); } static void rb532_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) From f43909dfb39c63ce54a598cbd7921643029afdeb Mon Sep 17 00:00:00 2001 From: Dmitri Vorobiev Date: Fri, 31 Oct 2008 19:54:11 +0200 Subject: [PATCH 094/107] MIPS: IP22: Make indy_sc_ops variable static The indy_sc_ops variable in arch/mips/mm/sc-ip22.c is needlessly defined global, and this patch makes it static. Signed-off-by: Dmitri Vorobiev Signed-off-by: Ralf Baechle --- --- arch/mips/mm/sc-ip22.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/mm/sc-ip22.c b/arch/mips/mm/sc-ip22.c index 1f602a110e10..13adb5782110 100644 --- a/arch/mips/mm/sc-ip22.c +++ b/arch/mips/mm/sc-ip22.c @@ -161,7 +161,7 @@ static inline int __init indy_sc_probe(void) /* XXX Check with wje if the Indy caches can differenciate between writeback + invalidate and just invalidate. */ -struct bcache_ops indy_sc_ops = { +static struct bcache_ops indy_sc_ops = { .bc_enable = indy_sc_enable, .bc_disable = indy_sc_disable, .bc_wback_inv = indy_sc_wback_invalidate, From 2e373952cc893207a8b47a5e68c2f5155f912449 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Sat, 1 Nov 2008 15:13:21 +0100 Subject: [PATCH 095/107] MIPS: RB532: Provide functions for gpio configuration As gpiolib doesn't support pin multiplexing, it provides no way to access the GPIOFUNC register. Also there is no support for setting interrupt status and level. These functions provide access to them and are needed by the CompactFlash driver. Signed-off-by: Phil Sutter Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mach-rc32434/gpio.h | 2 + arch/mips/rb532/gpio.c | 197 ++++++++-------------- 2 files changed, 77 insertions(+), 122 deletions(-) diff --git a/arch/mips/include/asm/mach-rc32434/gpio.h b/arch/mips/include/asm/mach-rc32434/gpio.h index c8e554eafce3..b5cf6457305a 100644 --- a/arch/mips/include/asm/mach-rc32434/gpio.h +++ b/arch/mips/include/asm/mach-rc32434/gpio.h @@ -84,5 +84,7 @@ extern void set_434_reg(unsigned reg_offs, unsigned bit, unsigned len, unsigned extern unsigned get_434_reg(unsigned reg_offs); extern void set_latch_u5(unsigned char or_mask, unsigned char nand_mask); extern unsigned char get_latch_u5(void); +extern void rb532_gpio_set_ilevel(int bit, unsigned gpio); +extern void rb532_gpio_set_istat(int bit, unsigned gpio); #endif /* _RC32434_GPIO_H_ */ diff --git a/arch/mips/rb532/gpio.c b/arch/mips/rb532/gpio.c index 70c4a6726377..0e84c8ab6a39 100644 --- a/arch/mips/rb532/gpio.c +++ b/arch/mips/rb532/gpio.c @@ -39,10 +39,6 @@ struct rb532_gpio_chip { struct gpio_chip chip; void __iomem *regbase; - void (*set_int_level)(struct gpio_chip *chip, unsigned offset, int value); - int (*get_int_level)(struct gpio_chip *chip, unsigned offset); - void (*set_int_status)(struct gpio_chip *chip, unsigned offset, int value); - int (*get_int_status)(struct gpio_chip *chip, unsigned offset); }; struct mpmc_device dev3; @@ -111,15 +107,47 @@ unsigned char get_latch_u5(void) } EXPORT_SYMBOL(get_latch_u5); +/* rb532_set_bit - sanely set a bit + * + * bitval: new value for the bit + * offset: bit index in the 4 byte address range + * ioaddr: 4 byte aligned address being altered + */ +static inline void rb532_set_bit(unsigned bitval, + unsigned offset, void __iomem *ioaddr) +{ + unsigned long flags; + u32 val; + + bitval = !!bitval; /* map parameter to {0,1} */ + + local_irq_save(flags); + + val = readl(ioaddr); + val &= ~( ~bitval << offset ); /* unset bit if bitval == 0 */ + val |= ( bitval << offset ); /* set bit if bitval == 1 */ + writel(val, ioaddr); + + local_irq_restore(flags); +} + +/* rb532_get_bit - read a bit + * + * returns the boolean state of the bit, which may be > 1 + */ +static inline int rb532_get_bit(unsigned offset, void __iomem *ioaddr) +{ + return (readl(ioaddr) & (1 << offset)); +} + /* * Return GPIO level */ static int rb532_gpio_get(struct gpio_chip *chip, unsigned offset) { - u32 mask = 1 << offset; struct rb532_gpio_chip *gpch; gpch = container_of(chip, struct rb532_gpio_chip, chip); - return readl(gpch->regbase + GPIOD) & mask; + return rb532_get_bit(offset, gpch->regbase + GPIOD); } /* @@ -128,23 +156,10 @@ static int rb532_gpio_get(struct gpio_chip *chip, unsigned offset) static void rb532_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { - unsigned long flags; - u32 mask = 1 << offset; - u32 tmp; struct rb532_gpio_chip *gpch; - void __iomem *gpvr; gpch = container_of(chip, struct rb532_gpio_chip, chip); - gpvr = gpch->regbase + GPIOD; - - local_irq_save(flags); - tmp = readl(gpvr); - if (value) - tmp |= mask; - else - tmp &= ~mask; - writel(tmp, gpvr); - local_irq_restore(flags); + rb532_set_bit(value, offset, gpch->regbase + GPIOD); } /* @@ -152,21 +167,14 @@ static void rb532_gpio_set(struct gpio_chip *chip, */ static int rb532_gpio_direction_input(struct gpio_chip *chip, unsigned offset) { - unsigned long flags; - u32 mask = 1 << offset; - u32 value; struct rb532_gpio_chip *gpch; - void __iomem *gpdr; gpch = container_of(chip, struct rb532_gpio_chip, chip); - gpdr = gpch->regbase + GPIOCFG; - local_irq_save(flags); - value = readl(gpdr); - value &= ~mask; - writel(value, gpdr); - local_irq_restore(flags); + if (rb532_get_bit(offset, gpch->regbase + GPIOFUNC)) + return 1; /* alternate function, GPIOCFG is ignored */ + rb532_set_bit(0, offset, gpch->regbase + GPIOCFG); return 0; } @@ -176,99 +184,20 @@ static int rb532_gpio_direction_input(struct gpio_chip *chip, unsigned offset) static int rb532_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value) { - unsigned long flags; - u32 mask = 1 << offset; - u32 tmp; struct rb532_gpio_chip *gpch; - void __iomem *gpdr; gpch = container_of(chip, struct rb532_gpio_chip, chip); - writel(mask, gpch->regbase + GPIOD); - gpdr = gpch->regbase + GPIOCFG; - local_irq_save(flags); - tmp = readl(gpdr); - tmp |= mask; - writel(tmp, gpdr); - local_irq_restore(flags); + if (rb532_get_bit(offset, gpch->regbase + GPIOFUNC)) + return 1; /* alternate function, GPIOCFG is ignored */ + /* set the initial output value */ + rb532_set_bit(value, offset, gpch->regbase + GPIOD); + + rb532_set_bit(1, offset, gpch->regbase + GPIOCFG); return 0; } -/* - * Set the GPIO interrupt level - */ -static void rb532_gpio_set_int_level(struct gpio_chip *chip, - unsigned offset, int value) -{ - unsigned long flags; - u32 mask = 1 << offset; - u32 tmp; - struct rb532_gpio_chip *gpch; - void __iomem *gpil; - - gpch = container_of(chip, struct rb532_gpio_chip, chip); - gpil = gpch->regbase + GPIOILEVEL; - - local_irq_save(flags); - tmp = readl(gpil); - if (value) - tmp |= mask; - else - tmp &= ~mask; - writel(tmp, gpil); - local_irq_restore(flags); -} - -/* - * Get the GPIO interrupt level - */ -static int rb532_gpio_get_int_level(struct gpio_chip *chip, unsigned offset) -{ - u32 mask = 1 << offset; - struct rb532_gpio_chip *gpch; - - gpch = container_of(chip, struct rb532_gpio_chip, chip); - return readl(gpch->regbase + GPIOILEVEL) & mask; -} - -/* - * Set the GPIO interrupt status - */ -static void rb532_gpio_set_int_status(struct gpio_chip *chip, - unsigned offset, int value) -{ - unsigned long flags; - u32 mask = 1 << offset; - u32 tmp; - struct rb532_gpio_chip *gpch; - void __iomem *gpis; - - gpch = container_of(chip, struct rb532_gpio_chip, chip); - gpis = gpch->regbase + GPIOISTAT; - - local_irq_save(flags); - tmp = readl(gpis); - if (value) - tmp |= mask; - else - tmp &= ~mask; - writel(tmp, gpis); - local_irq_restore(flags); -} - -/* - * Get the GPIO interrupt status - */ -static int rb532_gpio_get_int_status(struct gpio_chip *chip, unsigned offset) -{ - u32 mask = 1 << offset; - struct rb532_gpio_chip *gpch; - - gpch = container_of(chip, struct rb532_gpio_chip, chip); - return readl(gpch->regbase + GPIOISTAT) & mask; -} - static struct rb532_gpio_chip rb532_gpio_chip[] = { [0] = { .chip = { @@ -280,13 +209,35 @@ static struct rb532_gpio_chip rb532_gpio_chip[] = { .base = 0, .ngpio = 32, }, - .get_int_level = rb532_gpio_get_int_level, - .set_int_level = rb532_gpio_set_int_level, - .get_int_status = rb532_gpio_get_int_status, - .set_int_status = rb532_gpio_set_int_status, }, }; +/* + * Set GPIO interrupt level + */ +void rb532_gpio_set_ilevel(int bit, unsigned gpio) +{ + rb532_set_bit(bit, gpio, rb532_gpio_chip->regbase + GPIOILEVEL); +} +EXPORT_SYMBOL(rb532_gpio_set_ilevel); + +/* + * Set GPIO interrupt status + */ +void rb532_gpio_set_istat(int bit, unsigned gpio) +{ + rb532_set_bit(bit, gpio, rb532_gpio_chip->regbase + GPIOISTAT); +} +EXPORT_SYMBOL(rb532_gpio_set_istat); + +/* + * Configure GPIO alternate function + */ +static void rb532_gpio_set_func(int bit, unsigned gpio) +{ + rb532_set_bit(bit, gpio, rb532_gpio_chip->regbase + GPIOFUNC); +} + int __init rb532_gpio_init(void) { struct resource *r; @@ -310,9 +261,11 @@ int __init rb532_gpio_init(void) return -ENXIO; } - /* Set the interrupt status and level for the CF pin */ - rb532_gpio_set_int_level(&rb532_gpio_chip->chip, CF_GPIO_NUM, 1); - rb532_gpio_set_int_status(&rb532_gpio_chip->chip, CF_GPIO_NUM, 0); + /* configure CF_GPIO_NUM as CFRDY IRQ source */ + rb532_gpio_set_func(0, CF_GPIO_NUM); + rb532_gpio_direction_input(&rb532_gpio_chip->chip, CF_GPIO_NUM); + rb532_gpio_set_ilevel(1, CF_GPIO_NUM); + rb532_gpio_set_istat(0, CF_GPIO_NUM); return 0; } From 664c4bbb73ec53e4f81f7d80a09571b49bad1f96 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 3 Nov 2008 11:31:54 +0000 Subject: [PATCH 096/107] MIPS: csrc-r4k: Fix spelling mistake. Signed-off-by: Ralf Baechle --- arch/mips/kernel/csrc-r4k.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/kernel/csrc-r4k.c b/arch/mips/kernel/csrc-r4k.c index 86e026f067bc..74fb74583b4e 100644 --- a/arch/mips/kernel/csrc-r4k.c +++ b/arch/mips/kernel/csrc-r4k.c @@ -27,7 +27,7 @@ int __init init_mips_clocksource(void) if (!cpu_has_counter || !mips_hpt_frequency) return -ENXIO; - /* Calclate a somewhat reasonable rating value */ + /* Calculate a somewhat reasonable rating value */ clocksource_mips.rating = 200 + mips_hpt_frequency / 10000000; clocksource_set_clock(&clocksource_mips, mips_hpt_frequency); From a24e849c019f15796984be9fe301fa9ead6f0f9e Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 3 Nov 2008 11:32:34 +0000 Subject: [PATCH 097/107] MIPS: csrc-r4k: Fix declaration depending on the wrong CONFIG_ symbol. Signed-off-by: Ralf Baechle --- arch/mips/include/asm/time.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/include/asm/time.h b/arch/mips/include/asm/time.h index d3bd5c5aa2ec..9601ea950542 100644 --- a/arch/mips/include/asm/time.h +++ b/arch/mips/include/asm/time.h @@ -63,7 +63,7 @@ static inline int mips_clockevent_init(void) /* * Initialize the count register as a clocksource */ -#ifdef CONFIG_CEVT_R4K +#ifdef CONFIG_CSRC_R4K extern int init_mips_clocksource(void); #else static inline int init_mips_clocksource(void) From ddb4cbfc53aa0913ee8da059fcbf628d14f40f63 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 20 Nov 2008 20:00:44 +0000 Subject: [PATCH 098/107] [CIFS] Do not attempt to close invalidated file handles If a connection with open file handles has gone down and come back up and reconnected without reopening the file handle yet, do not attempt to send an SMB close request for this handle in cifs_close. We were checking for the connection being invalid in cifs_close but since the connection may have been reconnected we also need to check whether the file handle was marked invalid (otherwise we could close the wrong file handle by accident). Acked-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/cifsglob.h | 10 +++++++++- fs/cifs/file.c | 21 ++++++++++++++------- fs/cifs/misc.c | 3 +++ fs/cifs/readdir.c | 5 ++++- 4 files changed, 30 insertions(+), 9 deletions(-) diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index f1ae1f57c30d..c57c0565547f 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -606,7 +606,15 @@ GLOBAL_EXTERN struct list_head cifs_tcp_ses_list; * changes to the tcon->tidStatus should be done while holding this lock. */ GLOBAL_EXTERN rwlock_t cifs_tcp_ses_lock; -GLOBAL_EXTERN rwlock_t GlobalSMBSeslock; /* protects list inserts on 3 above */ + +/* + * This lock protects the cifs_file->llist and cifs_file->flist + * list operations, and updates to some flags (cifs_file->invalidHandle) + * It will be moved to either use the tcon->stat_lock or equivalent later. + * If cifs_tcp_ses_lock and the lock below are both needed to be held, then + * the cifs_tcp_ses_lock must be grabbed first and released last. + */ +GLOBAL_EXTERN rwlock_t GlobalSMBSeslock; GLOBAL_EXTERN struct list_head GlobalOplock_Q; diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 6449e1aae621..b691b893a848 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -488,12 +488,13 @@ int cifs_close(struct inode *inode, struct file *file) pTcon = cifs_sb->tcon; if (pSMBFile) { struct cifsLockInfo *li, *tmp; - + write_lock(&GlobalSMBSeslock); pSMBFile->closePend = true; if (pTcon) { /* no sense reconnecting to close a file that is already closed */ if (!pTcon->need_reconnect) { + write_unlock(&GlobalSMBSeslock); timeout = 2; while ((atomic_read(&pSMBFile->wrtPending) != 0) && (timeout <= 2048)) { @@ -510,12 +511,15 @@ int cifs_close(struct inode *inode, struct file *file) timeout *= 4; } if (atomic_read(&pSMBFile->wrtPending)) - cERROR(1, - ("close with pending writes")); - rc = CIFSSMBClose(xid, pTcon, + cERROR(1, ("close with pending write")); + if (!pTcon->need_reconnect && + !pSMBFile->invalidHandle) + rc = CIFSSMBClose(xid, pTcon, pSMBFile->netfid); - } - } + } else + write_unlock(&GlobalSMBSeslock); + } else + write_unlock(&GlobalSMBSeslock); /* Delete any outstanding lock records. We'll lose them when the file is closed anyway. */ @@ -587,15 +591,18 @@ int cifs_closedir(struct inode *inode, struct file *file) pTcon = cifs_sb->tcon; cFYI(1, ("Freeing private data in close dir")); + write_lock(&GlobalSMBSeslock); if (!pCFileStruct->srch_inf.endOfSearch && !pCFileStruct->invalidHandle) { pCFileStruct->invalidHandle = true; + write_unlock(&GlobalSMBSeslock); rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid); cFYI(1, ("Closing uncompleted readdir with rc %d", rc)); /* not much we can do if it fails anyway, ignore rc */ rc = 0; - } + } else + write_unlock(&GlobalSMBSeslock); ptmp = pCFileStruct->srch_inf.ntwrk_buf_start; if (ptmp) { cFYI(1, ("closedir free smb buf in srch struct")); diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index addd1dcc2d79..9ee3f689c2b0 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -555,12 +555,14 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) continue; cifs_stats_inc(&tcon->num_oplock_brks); + write_lock(&GlobalSMBSeslock); list_for_each(tmp2, &tcon->openFileList) { netfile = list_entry(tmp2, struct cifsFileInfo, tlist); if (pSMB->Fid != netfile->netfid) continue; + write_unlock(&GlobalSMBSeslock); read_unlock(&cifs_tcp_ses_lock); cFYI(1, ("file id match, oplock break")); pCifsInode = CIFS_I(netfile->pInode); @@ -576,6 +578,7 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) return true; } + write_unlock(&GlobalSMBSeslock); read_unlock(&cifs_tcp_ses_lock); cFYI(1, ("No matching file for oplock break")); return true; diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 58d57299f2a0..9f51f9bf0292 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -741,11 +741,14 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon, (index_to_find < first_entry_in_buffer)) { /* close and restart search */ cFYI(1, ("search backing up - close and restart search")); + write_lock(&GlobalSMBSeslock); if (!cifsFile->srch_inf.endOfSearch && !cifsFile->invalidHandle) { cifsFile->invalidHandle = true; + write_unlock(&GlobalSMBSeslock); CIFSFindClose(xid, pTcon, cifsFile->netfid); - } + } else + write_unlock(&GlobalSMBSeslock); if (cifsFile->srch_inf.ntwrk_buf_start) { cFYI(1, ("freeing SMB ff cache buf on search rewind")); if (cifsFile->srch_inf.smallBuf) From ed79b86d8acf1f3d3bb83f04dc216c8dfa1d5970 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Thu, 20 Nov 2008 10:54:09 +0100 Subject: [PATCH 099/107] parisc: fix bug in compat_arch_ptrace Commit 81e192d6ce303b6792aa38ff35f41a1a7357f23a ("parisc: convert to generic compat_sys_ptrace") introduced a bug which segfaults the parisc 64bit kernel when stracing 32bit applications: Kernel Fault: Code=15 regs=00000000bafa42b0 (Addr=00000001baf5ab57) YZrvWESTHLNXBCVMcbcbcbcbOGFRQPDI PSW: 00001000000001101111111100001011 Tainted: G W r00-03 000000ff0806ff0b 000000004068edc0 00000000401203f8 00000000fb3e2508 r04-07 0000000040686dc0 00000000baf5a800 fffffffffffffffc fffffffffb3e2508 r08-11 00000000baf5a800 000000000004b068 00000000000402b0 0000000000040d68 r12-15 0000000000042a9c 0000000000040a9c 0000000000040d60 0000000000042e9c r16-19 000000000004b060 000000000004b058 0000000000042d9c ffffffffffffffff r20-23 000000000800000b 0000000000000000 000000000800000b fffffffffb3e2508 r24-27 00000000fffffffc 0000000000000003 00000000fffffffc 0000000040686dc0 r28-31 00000001baf5a7ff 00000000bafa4280 00000000bafa42b0 00000000000001d7 sr00-03 0000000000fca000 0000000000000000 0000000000000000 0000000000fca000 sr04-07 0000000000000000 0000000000000000 0000000000000000 0000000000000000 IASQ: 0000000000000000 0000000000000000 IAOQ: 0000000040120400 0000000040120404 IIR: 4b9a06b0 ISR: 0000000000000000 IOR: 00000001baf5ab57 CPU: 0 CR30: 00000000bafa4000 CR31: 00000000d22344e0 ORIG_R28: 00000000fb3e2248 IAOQ[0]: compat_arch_ptrace+0xb8/0x160 IAOQ[1]: compat_arch_ptrace+0xbc/0x160 RP(r2): compat_arch_ptrace+0xb0/0x160 Backtrace: [<00000000401612ac>] compat_sys_ptrace+0x15c/0x180 [<0000000040104ef8>] syscall_exit+0x0/0x14 The problem is that compat_arch_ptrace() enters with an addr value of type compat_ulong_t and calls translate_usr_offset() to translate the address offset into a struct pt_regs offset like this: addr = translate_usr_offset(addr) this means that any return value of translate_usr_offset() is stored back as compat_ulong_t type into the addr variable. But since translate_usr_offset() returns -1 for invalid offsets, addr can now get the value 0xffffffff which then fails the next return-value sanity check and thus the kernel tries to access invalid memory: if (addr < 0) break; Fix this bug by modifying translate_usr_offset() to take and return values of type compat_ulong_t, and by returning the value "sizeof(struct pt_regs)" as an error indicator. Additionally change the sanity check to check for return values for >= sizeof(struct pt_regs). This patch survived my compile and run-tests. Signed-off-by: Helge Deller Signed-off-by: Linus Torvalds --- arch/parisc/kernel/ptrace.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c index 90904f9dfc50..927db3668b6f 100644 --- a/arch/parisc/kernel/ptrace.c +++ b/arch/parisc/kernel/ptrace.c @@ -183,10 +183,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) * being 64 bit in both cases. */ -static long translate_usr_offset(long offset) +static compat_ulong_t translate_usr_offset(compat_ulong_t offset) { if (offset < 0) - return -1; + return sizeof(struct pt_regs); else if (offset <= 32*4) /* gr[0..31] */ return offset * 2 + 4; else if (offset <= 32*4+32*8) /* gr[0..31] + fr[0..31] */ @@ -194,7 +194,7 @@ static long translate_usr_offset(long offset) else if (offset < sizeof(struct pt_regs)/2 + 32*4) return offset * 2 + 4 - 32*8; else - return -1; + return sizeof(struct pt_regs); } long compat_arch_ptrace(struct task_struct *child, compat_long_t request, @@ -209,7 +209,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, if (addr & (sizeof(compat_uint_t)-1)) break; addr = translate_usr_offset(addr); - if (addr < 0) + if (addr >= sizeof(struct pt_regs)) break; tmp = *(compat_uint_t *) ((char *) task_regs(child) + addr); @@ -236,7 +236,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, if (addr & (sizeof(compat_uint_t)-1)) break; addr = translate_usr_offset(addr); - if (addr < 0) + if (addr >= sizeof(struct pt_regs)) break; if (addr >= PT_FR0 && addr <= PT_FR31 + 4) { /* Special case, fp regs are 64 bits anyway */ From 23918b03060f6e572168fdde1798a905679d2e06 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Thu, 20 Nov 2008 16:06:21 -0500 Subject: [PATCH 100/107] SUNRPC: Fix a performance regression in the RPC authentication code Fix a regression reported by Max Kellermann whereby kernel profiling showed that his clients were spending 45% of their time in rpcauth_lookup_credcache. It turns out that although his processes had identical uid/gid/groups, generic_match() was failing to detect this, because the task->group_info pointers were not shared. This again lead to the creation of a huge number of identical credentials at the RPC layer. The regression is fixed by comparing the contents of task->group_info if the actual pointers are not identical. Signed-off-by: Trond Myklebust Signed-off-by: Linus Torvalds --- net/sunrpc/auth_generic.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/net/sunrpc/auth_generic.c b/net/sunrpc/auth_generic.c index 744b79fdcb19..4028502f0528 100644 --- a/net/sunrpc/auth_generic.c +++ b/net/sunrpc/auth_generic.c @@ -133,13 +133,29 @@ static int generic_match(struct auth_cred *acred, struct rpc_cred *cred, int flags) { struct generic_cred *gcred = container_of(cred, struct generic_cred, gc_base); + int i; if (gcred->acred.uid != acred->uid || gcred->acred.gid != acred->gid || - gcred->acred.group_info != acred->group_info || gcred->acred.machine_cred != acred->machine_cred) - return 0; + goto out_nomatch; + + /* Optimisation in the case where pointers are identical... */ + if (gcred->acred.group_info == acred->group_info) + goto out_match; + + /* Slow path... */ + if (gcred->acred.group_info->ngroups != acred->group_info->ngroups) + goto out_nomatch; + for (i = 0; i < gcred->acred.group_info->ngroups; i++) { + if (GROUP_AT(gcred->acred.group_info, i) != + GROUP_AT(acred->group_info, i)) + goto out_nomatch; + } +out_match: return 1; +out_nomatch: + return 0; } void __init rpc_init_generic_auth(void) From 0ca4b6b00113b064c080d26d803d0d7c80fb5dc8 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 20 Nov 2008 14:09:33 -0700 Subject: [PATCH 101/107] x86: Fix interrupt leak due to migration When we migrate an interrupt from one CPU to another, we set the move_in_progress flag and clean up the vectors later once they're not being used. If you're unlucky and call destroy_irq() before the vectors become un-used, the move_in_progress flag is never cleared, which causes the interrupt to become unusable. This was discovered by Jesse Brandeburg for whom it manifested as an MSI-X device refusing to use MSI-X mode when the driver was unloaded and reloaded repeatedly. Signed-off-by: Matthew Wilcox Signed-off-by: Linus Torvalds --- arch/x86/kernel/io_apic.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index 7a3f2028e2eb..c9513e1ff28d 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c @@ -1140,6 +1140,20 @@ static void __clear_irq_vector(int irq) cfg->vector = 0; cpus_clear(cfg->domain); + + if (likely(!cfg->move_in_progress)) + return; + cpus_and(mask, cfg->old_domain, cpu_online_map); + for_each_cpu_mask_nr(cpu, mask) { + for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; + vector++) { + if (per_cpu(vector_irq, cpu)[vector] != irq) + continue; + per_cpu(vector_irq, cpu)[vector] = -1; + break; + } + } + cfg->move_in_progress = 0; } void __setup_vector_irq(int cpu) From b704882e70d87d7f56db5ff17e2253f3fa90e4f3 Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Thu, 20 Nov 2008 13:27:12 -0800 Subject: [PATCH 102/107] [IA64] Rationalize kernel mode alignment checking Itanium processors can handle some misaligned data accesses. They also provide a mode where all such accesses are forced to trap. The kernel was schizophrenic about use of this mode: * Base kernel code ran in permissive mode where the only traps generated were from those cases that the h/w could not handle. * Interrupt, syscall and trap code ran in strict mode where all unaligned accesses caused traps to the 0x5a00 unaligned reference vector. Use strict alignment checking throughout the kernel, but make sure that we continue to let user mode use more relaxed mode as the default. Signed-off-by: Tony Luck --- arch/ia64/kernel/entry.S | 1 + arch/ia64/kernel/head.S | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index 7ef0c594f5ed..d435f4a7a96c 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S @@ -499,6 +499,7 @@ GLOBAL_ENTRY(prefetch_stack) END(prefetch_stack) GLOBAL_ENTRY(kernel_execve) + rum psr.ac mov r15=__NR_execve // put syscall number in place break __BREAK_SYSCALL br.ret.sptk.many rp diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S index 66e491d8baac..59301c472800 100644 --- a/arch/ia64/kernel/head.S +++ b/arch/ia64/kernel/head.S @@ -260,7 +260,7 @@ start_ap: * Switch into virtual mode: */ movl r16=(IA64_PSR_IT|IA64_PSR_IC|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_DFH|IA64_PSR_BN \ - |IA64_PSR_DI) + |IA64_PSR_DI|IA64_PSR_AC) ;; mov cr.ipsr=r16 movl r17=1f From ef23cdbefc3ab7f2ee9ee6dc6d4a94d7d6ec5e2b Mon Sep 17 00:00:00 2001 From: Hidetoshi Seto Date: Mon, 17 Nov 2008 10:18:08 +0900 Subject: [PATCH 103/107] [IA64] use mprintk instead of printk, in ia64_mca_modify_original_stack Using printk from MCA/INIT context is unsafe since it can cause deadlock. The ia64_mca_modify_original_stack is called from both of mca handler and init handler, so it should use mprintk instead of printk. Signed-off-by: Hidetoshi Seto Signed-off-by: Tony Luck --- arch/ia64/kernel/mca.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index 7dd96c127177..bab1de2d2f6a 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c @@ -1139,7 +1139,7 @@ ia64_mca_modify_original_stack(struct pt_regs *regs, return previous_current; no_mod: - printk(KERN_INFO "cpu %d, %s %s, original stack not modified\n", + mprintk(KERN_INFO "cpu %d, %s %s, original stack not modified\n", smp_processor_id(), type, msg); return previous_current; } From d5964107763d7155e9bea658098a337507b3e928 Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Thu, 20 Nov 2008 13:38:16 -0800 Subject: [PATCH 104/107] [IA64] remove duplicate include iommu.h arch/ia64/kernel/pci-dma.c only needs to include iommu once. Signed-off-by: Huang Weiyi Signed-off-by: Tony Luck --- arch/ia64/kernel/pci-dma.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/ia64/kernel/pci-dma.c b/arch/ia64/kernel/pci-dma.c index dbdb778efa05..2a92f637431d 100644 --- a/arch/ia64/kernel/pci-dma.c +++ b/arch/ia64/kernel/pci-dma.c @@ -19,7 +19,6 @@ #include #include -#include dma_addr_t bad_dma_address __read_mostly; EXPORT_SYMBOL(bad_dma_address); From 93fe10b670a7a6a1dc9649c7860f452dc7bbbb9d Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Tue, 18 Nov 2008 19:19:50 +0900 Subject: [PATCH 105/107] [IA64] ia64/pv_ops/pv_cpu_ops: fix _IA64_REG_IP case. pv_cpu_ops.getreg(_IA64_REG_IP) returned constant. But the returned ip valued should be the one in the caller, not of the callee. This patch fixes that. Signed-off-by: Isaku Yamahata Signed-off-by: Tony Luck --- arch/ia64/include/asm/intrinsics.h | 2 +- arch/ia64/include/asm/paravirt_privop.h | 13 +++++++++++++ arch/ia64/kernel/paravirt.c | 2 +- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/arch/ia64/include/asm/intrinsics.h b/arch/ia64/include/asm/intrinsics.h index 47d686dba1eb..a3e44a5ed497 100644 --- a/arch/ia64/include/asm/intrinsics.h +++ b/arch/ia64/include/asm/intrinsics.h @@ -226,7 +226,7 @@ extern long ia64_cmpxchg_called_with_bad_pointer (void); /************************************************/ #define ia64_ssm IA64_INTRINSIC_MACRO(ssm) #define ia64_rsm IA64_INTRINSIC_MACRO(rsm) -#define ia64_getreg IA64_INTRINSIC_API(getreg) +#define ia64_getreg IA64_INTRINSIC_MACRO(getreg) #define ia64_setreg IA64_INTRINSIC_API(setreg) #define ia64_set_rr IA64_INTRINSIC_API(set_rr) #define ia64_get_rr IA64_INTRINSIC_API(get_rr) diff --git a/arch/ia64/include/asm/paravirt_privop.h b/arch/ia64/include/asm/paravirt_privop.h index d577aac11835..0b597424fcfc 100644 --- a/arch/ia64/include/asm/paravirt_privop.h +++ b/arch/ia64/include/asm/paravirt_privop.h @@ -78,6 +78,19 @@ extern unsigned long ia64_native_getreg_func(int regnum); ia64_native_rsm(mask); \ } while (0) +/* returned ip value should be the one in the caller, + * not in __paravirt_getreg() */ +#define paravirt_getreg(reg) \ + ({ \ + unsigned long res; \ + BUILD_BUG_ON(!__builtin_constant_p(reg)); \ + if ((reg) == _IA64_REG_IP) \ + res = ia64_native_getreg(_IA64_REG_IP); \ + else \ + res = pv_cpu_ops.getreg(reg); \ + res; \ + }) + /****************************************************************************** * replacement of hand written assembly codes. */ diff --git a/arch/ia64/kernel/paravirt.c b/arch/ia64/kernel/paravirt.c index de35d8e8b7d2..9f14c16f6369 100644 --- a/arch/ia64/kernel/paravirt.c +++ b/arch/ia64/kernel/paravirt.c @@ -130,7 +130,7 @@ ia64_native_getreg_func(int regnum) unsigned long res = -1; switch (regnum) { CASE_GET_REG(GP); - CASE_GET_REG(IP); + /*CASE_GET_REG(IP);*/ /* returned ip value shouldn't be constant */ CASE_GET_REG(PSR); CASE_GET_REG(TP); CASE_GET_REG(SP); From 0090d481ee4c5d9a54ae2c457ab3ef9111dd4a91 Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Tue, 18 Nov 2008 19:20:51 +0900 Subject: [PATCH 106/107] [IA64] xen: fix xen_get_eflags. fix xen_get_eflags. It doesn't take any argument. Signed-off-by: Isaku Yamahata Signed-off-by: Tony Luck --- arch/ia64/xen/hypercall.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/ia64/xen/hypercall.S b/arch/ia64/xen/hypercall.S index d4ff0b9e79f1..45e02bb64a92 100644 --- a/arch/ia64/xen/hypercall.S +++ b/arch/ia64/xen/hypercall.S @@ -58,7 +58,7 @@ __HCALL2(xen_set_rr, HYPERPRIVOP_SET_RR) __HCALL2(xen_set_kr, HYPERPRIVOP_SET_KR) #ifdef CONFIG_IA32_SUPPORT -__HCALL1(xen_get_eflag, HYPERPRIVOP_GET_EFLAG) +__HCALL0(xen_get_eflag, HYPERPRIVOP_GET_EFLAG) __HCALL1(xen_set_eflag, HYPERPRIVOP_SET_EFLAG) // refer SDM vol1 3.1.8 #endif /* CONFIG_IA32_SUPPORT */ From 13d428afc007fcfcd6deeb215618f54cf9c0cae6 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 20 Nov 2008 15:19:22 -0800 Subject: [PATCH 107/107] Linux 2.6.28-rc6 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a9ae5dc0aa16..7b1f2384094f 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 28 -EXTRAVERSION = -rc5 +EXTRAVERSION = -rc6 NAME = Killer Bat of Doom # *DOCUMENTATION*