Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1750701AbWKDCL0 (ORCPT ); Fri, 3 Nov 2006 21:11:26 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1751321AbWKDCL0 (ORCPT ); Fri, 3 Nov 2006 21:11:26 -0500 Received: from 216-99-217-87.dsl.aracnet.com ([216.99.217.87]:52638 "EHLO sous-sol.org") by vger.kernel.org with ESMTP id S1750701AbWKDCLW (ORCPT ); Fri, 3 Nov 2006 21:11:22 -0500 Date: Fri, 3 Nov 2006 18:12:46 -0800 From: Chris Wright To: linux-kernel@vger.kernel.org Cc: Andrew Morton , torvalds@osdl.org, stable@kernel.org Subject: Re: Linux 2.6.18.2 Message-ID: <20061104021245.GY5881@sequoia.sous-sol.org> References: <20061104021118.GX5881@sequoia.sous-sol.org> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20061104021118.GX5881@sequoia.sous-sol.org> User-Agent: Mutt/1.4.2.2i Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 90751 Lines: 2925 diff --git a/Makefile b/Makefile index b803595..9e54c3a 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 18 -EXTRAVERSION = .1 +EXTRAVERSION = .2 NAME=Avast! A bilge rat! # *DOCUMENTATION* diff --git a/arch/i386/Kconfig.cpu b/arch/i386/Kconfig.cpu index 21c9a4e..fc4f2ab 100644 --- a/arch/i386/Kconfig.cpu +++ b/arch/i386/Kconfig.cpu @@ -7,6 +7,7 @@ choice config M386 bool "386" + depends on !UML ---help--- This is the processor type of your CPU. This information is used for optimizing purposes. In order to compile a kernel that can run on @@ -301,7 +302,7 @@ config X86_USE_PPRO_CHECKSUM config X86_USE_3DNOW bool - depends on MCYRIXIII || MK7 || MGEODE_LX + depends on (MCYRIXIII || MK7 || MGEODE_LX) && !UML default y config X86_OOSTORE diff --git a/arch/i386/kernel/alternative.c b/arch/i386/kernel/alternative.c index 28ab806..583c238 100644 --- a/arch/i386/kernel/alternative.c +++ b/arch/i386/kernel/alternative.c @@ -344,6 +344,7 @@ #endif void __init alternative_instructions(void) { + unsigned long flags; if (no_replacement) { printk(KERN_INFO "(SMP-)alternatives turned off\n"); free_init_pages("SMP alternatives", @@ -351,6 +352,8 @@ void __init alternative_instructions(voi (unsigned long)__smp_alt_end); return; } + + local_irq_save(flags); apply_alternatives(__alt_instructions, __alt_instructions_end); /* switch to patch-once-at-boottime-only mode and free the @@ -386,4 +389,5 @@ #ifdef CONFIG_SMP alternatives_smp_switch(0); } #endif + local_irq_restore(flags); } diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 694b0c6..f35bb14 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -729,6 +729,15 @@ config ARCH_MEMORY_PROBE def_bool y depends on MEMORY_HOTPLUG +# Some NUMA nodes have memory ranges that span +# other nodes. Even though a pfn is valid and +# between a node's start and end pfns, it may not +# reside on that node. See memmap_init_zone() +# for details. +config NODES_SPAN_OTHER_NODES + def_bool y + depends on NEED_MULTIPLE_NODES + config PPC_64K_PAGES bool "64k page size" depends on PPC64 diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig index a8cdf31..40782c0 100644 --- a/arch/powerpc/configs/pseries_defconfig +++ b/arch/powerpc/configs/pseries_defconfig @@ -184,6 +184,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 CONFIG_MIGRATION=y CONFIG_RESOURCES_64BIT=y CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y +CONFIG_NODES_SPAN_OTHER_NODES=y # CONFIG_PPC_64K_PAGES is not set CONFIG_SCHED_SMT=y CONFIG_PROC_DEVICETREE=y diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 2f4f70c..bf25932 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -51,6 +51,10 @@ config 64BIT Select this option if you have a 64 bit IBM zSeries machine and want to use the 64 bit addressing mode. +config 32BIT + bool + default y if !64BIT + config SMP bool "Symmetric multi-processing support" ---help--- diff --git a/arch/s390/lib/Makefile b/arch/s390/lib/Makefile index e05d087..1400141 100644 --- a/arch/s390/lib/Makefile +++ b/arch/s390/lib/Makefile @@ -7,3 +7,4 @@ EXTRA_AFLAGS := -traditional lib-y += delay.o string.o lib-y += $(if $(CONFIG_64BIT),uaccess64.o,uaccess.o) lib-$(CONFIG_SMP) += spinlock.o +lib-$(CONFIG_32BIT) += div64.o diff --git a/arch/s390/lib/div64.c b/arch/s390/lib/div64.c new file mode 100644 index 0000000..0481f34 --- /dev/null +++ b/arch/s390/lib/div64.c @@ -0,0 +1,151 @@ +/* + * arch/s390/lib/div64.c + * + * __div64_32 implementation for 31 bit. + * + * Copyright (C) IBM Corp. 2006 + * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), + */ + +#include +#include + +#ifdef CONFIG_MARCH_G5 + +/* + * Function to divide an unsigned 64 bit integer by an unsigned + * 31 bit integer using signed 64/32 bit division. + */ +static uint32_t __div64_31(uint64_t *n, uint32_t base) +{ + register uint32_t reg2 asm("2"); + register uint32_t reg3 asm("3"); + uint32_t *words = (uint32_t *) n; + uint32_t tmp; + + /* Special case base==1, remainder = 0, quotient = n */ + if (base == 1) + return 0; + /* + * Special case base==0 will cause a fixed point divide exception + * on the dr instruction and may not happen anyway. For the + * following calculation we can assume base > 1. The first + * signed 64 / 32 bit division with an upper half of 0 will + * give the correct upper half of the 64 bit quotient. + */ + reg2 = 0UL; + reg3 = words[0]; + asm volatile( + " dr %0,%2\n" + : "+d" (reg2), "+d" (reg3) : "d" (base) : "cc" ); + words[0] = reg3; + reg3 = words[1]; + /* + * To get the lower half of the 64 bit quotient and the 32 bit + * remainder we have to use a little trick. Since we only have + * a signed division the quotient can get too big. To avoid this + * the 64 bit dividend is halved, then the signed division will + * work. Afterwards the quotient and the remainder are doubled. + * If the last bit of the dividend has been one the remainder + * is increased by one then checked against the base. If the + * remainder has overflown subtract base and increase the + * quotient. Simple, no ? + */ + asm volatile( + " nr %2,%1\n" + " srdl %0,1\n" + " dr %0,%3\n" + " alr %0,%0\n" + " alr %1,%1\n" + " alr %0,%2\n" + " clr %0,%3\n" + " jl 0f\n" + " slr %0,%3\n" + " alr %1,%2\n" + "0:\n" + : "+d" (reg2), "+d" (reg3), "=d" (tmp) + : "d" (base), "2" (1UL) : "cc" ); + words[1] = reg3; + return reg2; +} + +/* + * Function to divide an unsigned 64 bit integer by an unsigned + * 32 bit integer using the unsigned 64/31 bit division. + */ +uint32_t __div64_32(uint64_t *n, uint32_t base) +{ + uint32_t r; + + /* + * If the most significant bit of base is set, divide n by + * (base/2). That allows to use 64/31 bit division and gives a + * good approximation of the result: n = (base/2)*q + r. The + * result needs to be corrected with two simple transformations. + * If base is already < 2^31-1 __div64_31 can be used directly. + */ + r = __div64_31(n, ((signed) base < 0) ? (base/2) : base); + if ((signed) base < 0) { + uint64_t q = *n; + /* + * First transformation: + * n = (base/2)*q + r + * = ((base/2)*2)*(q/2) + ((q&1) ? (base/2) : 0) + r + * Since r < (base/2), r + (base/2) < base. + * With q1 = (q/2) and r1 = r + ((q&1) ? (base/2) : 0) + * n = ((base/2)*2)*q1 + r1 with r1 < base. + */ + if (q & 1) + r += base/2; + q >>= 1; + /* + * Second transformation. ((base/2)*2) could have lost the + * last bit. + * n = ((base/2)*2)*q1 + r1 + * = base*q1 - ((base&1) ? q1 : 0) + r1 + */ + if (base & 1) { + int64_t rx = r - q; + /* + * base is >= 2^31. The worst case for the while + * loop is n=2^64-1 base=2^31+1. That gives a + * maximum for q=(2^64-1)/2^31 = 0x1ffffffff. Since + * base >= 2^31 the loop is finished after a maximum + * of three iterations. + */ + while (rx < 0) { + rx += base; + q--; + } + r = rx; + } + *n = q; + } + return r; +} + +#else /* MARCH_G5 */ + +uint32_t __div64_32(uint64_t *n, uint32_t base) +{ + register uint32_t reg2 asm("2"); + register uint32_t reg3 asm("3"); + uint32_t *words = (uint32_t *) n; + + reg2 = 0UL; + reg3 = words[0]; + asm volatile( + " dlr %0,%2\n" + : "+d" (reg2), "+d" (reg3) : "d" (base) : "cc" ); + words[0] = reg3; + reg3 = words[1]; + asm volatile( + " dlr %0,%2\n" + : "+d" (reg2), "+d" (reg3) : "d" (base) : "cc" ); + words[1] = reg3; + return reg2; +} + +#endif /* MARCH_G5 */ + +EXPORT_SYMBOL(__div64_32); diff --git a/arch/sparc64/kernel/central.c b/arch/sparc64/kernel/central.c index b66336d..e724c54 100644 --- a/arch/sparc64/kernel/central.c +++ b/arch/sparc64/kernel/central.c @@ -126,6 +126,10 @@ static void probe_other_fhcs(void) int board; u32 tmp; + if (dp->parent && + dp->parent->parent != NULL) + continue; + fhc = (struct linux_fhc *) central_alloc_bootmem(sizeof(struct linux_fhc)); if (fhc == NULL) diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c index 238bbf6..c7bbd7a 100644 --- a/arch/sparc64/kernel/of_device.c +++ b/arch/sparc64/kernel/of_device.c @@ -398,16 +398,22 @@ static void of_bus_sbus_count_cells(stru *sizec = 1; } -static int of_bus_sbus_map(u32 *addr, const u32 *range, int na, int ns, int pna) -{ - return of_bus_default_map(addr, range, na, ns, pna); -} - -static unsigned int of_bus_sbus_get_flags(u32 *addr) +/* + * FHC/Central bus specific translator. + * + * This is just needed to hard-code the address and size cell + * counts. 'fhc' and 'central' nodes lack the #address-cells and + * #size-cells properties, and if you walk to the root on such + * Enterprise boxes all you'll get is a #size-cells of 2 which is + * not what we want to use. + */ +static int of_bus_fhc_match(struct device_node *np) { - return IORESOURCE_MEM; + return !strcmp(np->name, "fhc") || + !strcmp(np->name, "central"); } +#define of_bus_fhc_count_cells of_bus_sbus_count_cells /* * Array of bus specific translators @@ -429,8 +435,17 @@ static struct of_bus of_busses[] = { .addr_prop_name = "reg", .match = of_bus_sbus_match, .count_cells = of_bus_sbus_count_cells, - .map = of_bus_sbus_map, - .get_flags = of_bus_sbus_get_flags, + .map = of_bus_default_map, + .get_flags = of_bus_default_get_flags, + }, + /* FHC */ + { + .name = "fhc", + .addr_prop_name = "reg", + .match = of_bus_fhc_match, + .count_cells = of_bus_fhc_count_cells, + .map = of_bus_default_map, + .get_flags = of_bus_default_get_flags, }, /* Default */ { diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c index 7a59cc7..827ae30 100644 --- a/arch/sparc64/kernel/pci_common.c +++ b/arch/sparc64/kernel/pci_common.c @@ -330,19 +330,6 @@ #endif return res; } -static int __init pdev_resource_collisions_expected(struct pci_dev *pdev) -{ - if (pdev->vendor != PCI_VENDOR_ID_SUN) - return 0; - - if (pdev->device == PCI_DEVICE_ID_SUN_RIO_EBUS || - pdev->device == PCI_DEVICE_ID_SUN_RIO_1394 || - pdev->device == PCI_DEVICE_ID_SUN_RIO_USB) - return 1; - - return 0; -} - static void __init pdev_record_assignments(struct pci_pbm_info *pbm, struct pci_dev *pdev) { @@ -400,19 +387,23 @@ static void __init pdev_record_assignmen pbm->parent->resource_adjust(pdev, res, root); if (request_resource(root, res) < 0) { + int rnum; + /* OK, there is some conflict. But this is fine * since we'll reassign it in the fixup pass. * - * We notify the user that OBP made an error if it - * is a case we don't expect. + * Do not print the warning for ROM resources + * as such a conflict is quite common and + * harmless as the ROM bar is disabled. */ - if (!pdev_resource_collisions_expected(pdev)) { - printk(KERN_ERR "PCI: Address space collision on region %ld " + rnum = (res - &pdev->resource[0]); + if (rnum != PCI_ROM_RESOURCE) + printk(KERN_ERR "PCI: Resource collision, " + "region %d " "[%016lx:%016lx] of device %s\n", - (res - &pdev->resource[0]), + rnum, res->start, res->end, pci_name(pdev)); - } } } } diff --git a/arch/sparc64/kernel/pci_iommu.c b/arch/sparc64/kernel/pci_iommu.c index 82e5455..2e7f142 100644 --- a/arch/sparc64/kernel/pci_iommu.c +++ b/arch/sparc64/kernel/pci_iommu.c @@ -281,7 +281,7 @@ static void pci_4u_free_consistent(struc spin_lock_irqsave(&iommu->lock, flags); - free_npages(iommu, dvma, npages); + free_npages(iommu, dvma - iommu->page_table_map_base, npages); spin_unlock_irqrestore(&iommu->lock, flags); diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index 4589185..f04c6d2 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -1196,7 +1196,7 @@ static void pbm_register_toplevel_resour &pbm->mem_space); } -static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 dma_begin) +static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 dma_start, u32 dma_end) { struct pci_pbm_info *pbm; struct device_node *node; @@ -1261,6 +1261,8 @@ static void sabre_pbm_init(struct pci_co node = node->sibling; } if (simbas_found == 0) { + struct resource *rp; + /* No APBs underneath, probably this is a hummingbird * system. */ @@ -1302,8 +1304,10 @@ static void sabre_pbm_init(struct pci_co pbm->io_space.end = pbm->io_space.start + (1UL << 24) - 1UL; pbm->io_space.flags = IORESOURCE_IO; - pbm->mem_space.start = p->pbm_A.controller_regs + SABRE_MEMSPACE; - pbm->mem_space.end = pbm->mem_space.start + (unsigned long)dma_begin - 1UL; + pbm->mem_space.start = + (p->pbm_A.controller_regs + SABRE_MEMSPACE); + pbm->mem_space.end = + (pbm->mem_space.start + ((1UL << 32UL) - 1UL)); pbm->mem_space.flags = IORESOURCE_MEM; if (request_resource(&ioport_resource, &pbm->io_space) < 0) { @@ -1315,6 +1319,17 @@ static void sabre_pbm_init(struct pci_co prom_halt(); } + rp = kmalloc(sizeof(*rp), GFP_KERNEL); + if (!rp) { + prom_printf("Cannot allocate IOMMU resource.\n"); + prom_halt(); + } + rp->name = "IOMMU"; + rp->start = pbm->mem_space.start + (unsigned long) dma_start; + rp->end = pbm->mem_space.start + (unsigned long) dma_end - 1UL; + rp->flags = IORESOURCE_BUSY; + request_resource(&pbm->mem_space, rp); + pci_register_legacy_regions(&pbm->io_space, &pbm->mem_space); } @@ -1450,5 +1465,5 @@ void sabre_init(struct device_node *dp, /* * Look for APB underneath. */ - sabre_pbm_init(p, dp, vdma[0]); + sabre_pbm_init(p, dp, vdma[0], vdma[0] + vdma[1]); } diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c index 5cc5ab6..03d6be8 100644 --- a/arch/sparc64/kernel/prom.c +++ b/arch/sparc64/kernel/prom.c @@ -1080,23 +1080,22 @@ static void sun4v_vdev_irq_trans_init(st static void irq_trans_init(struct device_node *dp) { - const char *model; #ifdef CONFIG_PCI + const char *model; int i; #endif +#ifdef CONFIG_PCI model = of_get_property(dp, "model", NULL); if (!model) model = of_get_property(dp, "compatible", NULL); - if (!model) - return; - -#ifdef CONFIG_PCI - for (i = 0; i < ARRAY_SIZE(pci_irq_trans_table); i++) { - struct irq_trans *t = &pci_irq_trans_table[i]; + if (model) { + for (i = 0; i < ARRAY_SIZE(pci_irq_trans_table); i++) { + struct irq_trans *t = &pci_irq_trans_table[i]; - if (!strcmp(model, t->name)) - return t->init(dp); + if (!strcmp(model, t->name)) + return t->init(dp); + } } #endif #ifdef CONFIG_SBUS @@ -1104,8 +1103,9 @@ #ifdef CONFIG_SBUS !strcmp(dp->name, "sbi")) return sbus_irq_trans_init(dp); #endif - if (!strcmp(dp->name, "central")) - return central_irq_trans_init(dp->child); + if (!strcmp(dp->name, "fhc") && + !strcmp(dp->parent->name, "central")) + return central_irq_trans_init(dp); if (!strcmp(dp->name, "virtual-devices")) return sun4v_vdev_irq_trans_init(dp); } @@ -1517,7 +1517,7 @@ static char * __init get_one_property(ph return buf; } -static struct device_node * __init create_node(phandle node) +static struct device_node * __init create_node(phandle node, struct device_node *parent) { struct device_node *dp; @@ -1526,6 +1526,7 @@ static struct device_node * __init creat dp = prom_early_alloc(sizeof(*dp)); dp->unique_id = unique_id++; + dp->parent = parent; kref_init(&dp->kref); @@ -1544,12 +1545,11 @@ static struct device_node * __init build { struct device_node *dp; - dp = create_node(node); + dp = create_node(node, parent); if (dp) { *(*nextp) = dp; *nextp = &dp->allnext; - dp->parent = parent; dp->path_component_name = build_path_component(dp); dp->full_name = build_full_name(dp); @@ -1565,7 +1565,7 @@ void __init prom_build_devicetree(void) { struct device_node **nextp; - allnodes = create_node(prom_root_node); + allnodes = create_node(prom_root_node, NULL); allnodes->path_component_name = ""; allnodes->full_name = "/"; diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h index b98bdd8..ab9c0b7 100644 --- a/arch/um/include/kern_util.h +++ b/arch/um/include/kern_util.h @@ -6,7 +6,6 @@ #ifndef __KERN_UTIL_H__ #define __KERN_UTIL_H__ -#include "linux/threads.h" #include "sysdep/ptrace.h" #include "sysdep/faultinfo.h" diff --git a/arch/um/os-Linux/sys-i386/tls.c b/arch/um/os-Linux/sys-i386/tls.c index 64f547f..8dc6a49 100644 --- a/arch/um/os-Linux/sys-i386/tls.c +++ b/arch/um/os-Linux/sys-i386/tls.c @@ -1,4 +1,6 @@ #include +#include +#include #include #include "sysdep/tls.h" #include "user_util.h" diff --git a/arch/um/os-Linux/tls.c b/arch/um/os-Linux/tls.c index 297f263..3385784 100644 --- a/arch/um/os-Linux/tls.c +++ b/arch/um/os-Linux/tls.c @@ -1,6 +1,8 @@ #include #include +#include #include +#include #include "sysdep/tls.h" #include "uml-config.h" diff --git a/arch/um/sys-x86_64/stub_segv.c b/arch/um/sys-x86_64/stub_segv.c index 1c96702..652fa34 100644 --- a/arch/um/sys-x86_64/stub_segv.c +++ b/arch/um/sys-x86_64/stub_segv.c @@ -5,7 +5,6 @@ #include #include -#include #include #include "uml-config.h" #include "sysdep/sigcontext.h" diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c index 7a9b182..ffd1cb8 100644 --- a/arch/x86_64/kernel/time.c +++ b/arch/x86_64/kernel/time.c @@ -960,7 +960,7 @@ #endif if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) { #ifdef CONFIG_ACPI /* But TSC doesn't tick in C3 so don't use it there */ - if (acpi_fadt.length > 0 && acpi_fadt.plvl3_lat < 100) + if (acpi_fadt.length > 0 && acpi_fadt.plvl3_lat < 1000) return 1; #endif return 0; diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index ddd9253..3ecdb34 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -3021,6 +3021,7 @@ void generic_make_request(struct bio *bi { request_queue_t *q; sector_t maxsector; + sector_t old_sector; int ret, nr_sectors = bio_sectors(bio); dev_t old_dev; @@ -3049,7 +3050,7 @@ void generic_make_request(struct bio *bi * NOTE: we don't repeat the blk_size check for each new device. * Stacking drivers are expected to know what they are doing. */ - maxsector = -1; + old_sector = -1; old_dev = 0; do { char b[BDEVNAME_SIZE]; @@ -3083,15 +3084,30 @@ end_io: */ blk_partition_remap(bio); - if (maxsector != -1) + if (old_sector != -1) blk_add_trace_remap(q, bio, old_dev, bio->bi_sector, - maxsector); + old_sector); blk_add_trace_bio(q, bio, BLK_TA_QUEUE); - maxsector = bio->bi_sector; + old_sector = bio->bi_sector; old_dev = bio->bi_bdev->bd_dev; + maxsector = bio->bi_bdev->bd_inode->i_size >> 9; + if (maxsector) { + sector_t sector = bio->bi_sector; + + if (maxsector < nr_sectors || maxsector - nr_sectors < sector) { + /* + * This may well happen - partitions are not checked + * to make sure they are within the size of the + * whole device. + */ + handle_bad_sector(bio); + goto end_io; + } + } + ret = q->make_request_fn(q, bio); } while (ret); } diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c index 4cd23c3..a360215 100644 --- a/drivers/block/DAC960.c +++ b/drivers/block/DAC960.c @@ -7115,7 +7115,7 @@ static struct pci_device_id DAC960_id_ta { .vendor = PCI_VENDOR_ID_MYLEX, .device = PCI_DEVICE_ID_MYLEX_DAC960_GEM, - .subvendor = PCI_ANY_ID, + .subvendor = PCI_VENDOR_ID_MYLEX, .subdevice = PCI_ANY_ID, .driver_data = (unsigned long) &DAC960_GEM_privdata, }, diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c index ccd7e71..8efbc9c 100644 --- a/drivers/char/hw_random/intel-rng.c +++ b/drivers/char/hw_random/intel-rng.c @@ -50,6 +50,43 @@ #define INTEL_RNG_ADDR 0xFFBC015F #define INTEL_RNG_ADDR_LEN 3 /* + * LPC bridge PCI config space registers + */ +#define FWH_DEC_EN1_REG_OLD 0xe3 +#define FWH_DEC_EN1_REG_NEW 0xd9 /* high byte of 16-bit register */ +#define FWH_F8_EN_MASK 0x80 + +#define BIOS_CNTL_REG_OLD 0x4e +#define BIOS_CNTL_REG_NEW 0xdc +#define BIOS_CNTL_WRITE_ENABLE_MASK 0x01 +#define BIOS_CNTL_LOCK_ENABLE_MASK 0x02 + +/* + * Magic address at which Intel Firmware Hubs get accessed + */ +#define INTEL_FWH_ADDR 0xffff0000 +#define INTEL_FWH_ADDR_LEN 2 + +/* + * Intel Firmware Hub command codes (write to any address inside the device) + */ +#define INTEL_FWH_RESET_CMD 0xff /* aka READ_ARRAY */ +#define INTEL_FWH_READ_ID_CMD 0x90 + +/* + * Intel Firmware Hub Read ID command result addresses + */ +#define INTEL_FWH_MANUFACTURER_CODE_ADDRESS 0x000000 +#define INTEL_FWH_DEVICE_CODE_ADDRESS 0x000001 + +/* + * Intel Firmware Hub Read ID command result values + */ +#define INTEL_FWH_MANUFACTURER_CODE 0x89 +#define INTEL_FWH_DEVICE_CODE_8M 0xac +#define INTEL_FWH_DEVICE_CODE_4M 0xad + +/* * Data for PCI driver interface * * This data only exists for exporting the supported @@ -58,12 +95,50 @@ #define INTEL_RNG_ADDR_LEN 3 * want to register another driver on the same PCI id. */ static const struct pci_device_id pci_tbl[] = { - { 0x8086, 0x2418, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, - { 0x8086, 0x2428, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, - { 0x8086, 0x2430, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, - { 0x8086, 0x2448, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, - { 0x8086, 0x244e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, - { 0x8086, 0x245e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, +/* AA + { 0x8086, 0x2418, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */ + { 0x8086, 0x2410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* AA */ +/* AB + { 0x8086, 0x2428, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */ + { 0x8086, 0x2420, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* AB */ +/* ?? + { 0x8086, 0x2430, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */ +/* BAM, CAM, DBM, FBM, GxM + { 0x8086, 0x2448, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */ + { 0x8086, 0x244c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* BAM */ + { 0x8086, 0x248c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* CAM */ + { 0x8086, 0x24cc, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* DBM */ + { 0x8086, 0x2641, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* FBM */ + { 0x8086, 0x27b9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* GxM */ + { 0x8086, 0x27bd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* GxM DH */ +/* BA, CA, DB, Ex, 6300, Fx, 631x/632x, Gx + { 0x8086, 0x244e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */ + { 0x8086, 0x2440, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* BA */ + { 0x8086, 0x2480, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* CA */ + { 0x8086, 0x24c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* DB */ + { 0x8086, 0x24d0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Ex */ + { 0x8086, 0x25a1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 6300 */ + { 0x8086, 0x2640, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Fx */ + { 0x8086, 0x2670, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ + { 0x8086, 0x2671, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ + { 0x8086, 0x2672, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ + { 0x8086, 0x2673, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ + { 0x8086, 0x2674, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ + { 0x8086, 0x2675, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ + { 0x8086, 0x2676, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ + { 0x8086, 0x2677, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ + { 0x8086, 0x2678, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ + { 0x8086, 0x2679, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ + { 0x8086, 0x267a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ + { 0x8086, 0x267b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ + { 0x8086, 0x267c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ + { 0x8086, 0x267d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ + { 0x8086, 0x267e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ + { 0x8086, 0x267f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ + { 0x8086, 0x27b8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Gx */ +/* E + { 0x8086, 0x245e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */ + { 0x8086, 0x2450, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* E */ { 0, }, /* terminate list */ }; MODULE_DEVICE_TABLE(pci, pci_tbl); @@ -138,22 +213,115 @@ static struct hwrng intel_rng = { }; +#ifdef CONFIG_SMP +static char __initdata waitflag; + +static void __init intel_init_wait(void *unused) +{ + while (waitflag) + cpu_relax(); +} +#endif + static int __init mod_init(void) { int err = -ENODEV; + unsigned i; + struct pci_dev *dev = NULL; void __iomem *mem; - u8 hw_status; + unsigned long flags; + u8 bios_cntl_off, fwh_dec_en1_off; + u8 bios_cntl_val = 0xff, fwh_dec_en1_val = 0xff; + u8 hw_status, mfc, dvc; - if (!pci_dev_present(pci_tbl)) + for (i = 0; !dev && pci_tbl[i].vendor; ++i) + dev = pci_get_device(pci_tbl[i].vendor, pci_tbl[i].device, NULL); + + if (!dev) goto out; /* Device not found. */ + /* Check for Intel 82802 */ + if (dev->device < 0x2640) { + fwh_dec_en1_off = FWH_DEC_EN1_REG_OLD; + bios_cntl_off = BIOS_CNTL_REG_OLD; + } else { + fwh_dec_en1_off = FWH_DEC_EN1_REG_NEW; + bios_cntl_off = BIOS_CNTL_REG_NEW; + } + + pci_read_config_byte(dev, fwh_dec_en1_off, &fwh_dec_en1_val); + pci_read_config_byte(dev, bios_cntl_off, &bios_cntl_val); + + mem = ioremap_nocache(INTEL_FWH_ADDR, INTEL_FWH_ADDR_LEN); + if (mem == NULL) { + pci_dev_put(dev); + err = -EBUSY; + goto out; + } + + /* + * Since the BIOS code/data is going to disappear from its normal + * location with the Read ID command, all activity on the system + * must be stopped until the state is back to normal. + */ +#ifdef CONFIG_SMP + set_mb(waitflag, 1); + if (smp_call_function(intel_init_wait, NULL, 1, 0) != 0) { + set_mb(waitflag, 0); + pci_dev_put(dev); + printk(KERN_ERR PFX "cannot run on all processors\n"); + err = -EAGAIN; + goto err_unmap; + } +#endif + local_irq_save(flags); + + if (!(fwh_dec_en1_val & FWH_F8_EN_MASK)) + pci_write_config_byte(dev, + fwh_dec_en1_off, + fwh_dec_en1_val | FWH_F8_EN_MASK); + if (!(bios_cntl_val & + (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK))) + pci_write_config_byte(dev, + bios_cntl_off, + bios_cntl_val | BIOS_CNTL_WRITE_ENABLE_MASK); + + writeb(INTEL_FWH_RESET_CMD, mem); + writeb(INTEL_FWH_READ_ID_CMD, mem); + mfc = readb(mem + INTEL_FWH_MANUFACTURER_CODE_ADDRESS); + dvc = readb(mem + INTEL_FWH_DEVICE_CODE_ADDRESS); + writeb(INTEL_FWH_RESET_CMD, mem); + + if (!(bios_cntl_val & + (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK))) + pci_write_config_byte(dev, bios_cntl_off, bios_cntl_val); + if (!(fwh_dec_en1_val & FWH_F8_EN_MASK)) + pci_write_config_byte(dev, fwh_dec_en1_off, fwh_dec_en1_val); + + local_irq_restore(flags); +#ifdef CONFIG_SMP + /* Tell other CPUs to resume. */ + set_mb(waitflag, 0); +#endif + + iounmap(mem); + pci_dev_put(dev); + + if (mfc != INTEL_FWH_MANUFACTURER_CODE || + (dvc != INTEL_FWH_DEVICE_CODE_8M && + dvc != INTEL_FWH_DEVICE_CODE_4M)) { + printk(KERN_ERR PFX "FWH not detected\n"); + err = -ENODEV; + goto out; + } + err = -ENOMEM; mem = ioremap(INTEL_RNG_ADDR, INTEL_RNG_ADDR_LEN); if (!mem) goto out; intel_rng.priv = (unsigned long)mem; - /* Check for Intel 82802 */ + /* Check for Random Number Generator */ err = -ENODEV; hw_status = hwstatus_get(mem); if ((hw_status & INTEL_RNG_PRESENT) == 0) diff --git a/drivers/char/watchdog/sc1200wdt.c b/drivers/char/watchdog/sc1200wdt.c index 7c3cf29..cb92a1b 100644 --- a/drivers/char/watchdog/sc1200wdt.c +++ b/drivers/char/watchdog/sc1200wdt.c @@ -392,7 +392,7 @@ #endif if (io == -1) { printk(KERN_ERR PFX "io parameter must be specified\n"); ret = -EINVAL; - goto out_clean; + goto out_pnp; } #if defined CONFIG_PNP @@ -405,7 +405,7 @@ #endif if (!request_region(io, io_len, SC1200_MODULE_NAME)) { printk(KERN_ERR PFX "Unable to register IO port %#x\n", io); ret = -EBUSY; - goto out_clean; + goto out_pnp; } ret = sc1200wdt_probe(); @@ -435,6 +435,11 @@ out_rbt: out_io: release_region(io, io_len); +out_pnp: +#if defined CONFIG_PNP + if (isapnp) + pnp_unregister_driver(&scl200wdt_pnp_driver); +#endif goto out_clean; } diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c index 6a1ddad..58e8efa 100644 --- a/drivers/ide/pci/generic.c +++ b/drivers/ide/pci/generic.c @@ -242,8 +242,10 @@ static int __devinit generic_init_one(st (!(PCI_FUNC(dev->devfn) & 1))) goto out; - if (dev->vendor == PCI_VENDOR_ID_JMICRON && PCI_FUNC(dev->devfn) != 1) - goto out; + if (dev->vendor == PCI_VENDOR_ID_JMICRON) { + if (dev->device != PCI_DEVICE_ID_JMICRON_JMB368 && PCI_FUNC(dev->devfn) != 1) + goto out; + } if (dev->vendor != PCI_VENDOR_ID_JMICRON) { pci_read_config_word(dev, PCI_COMMAND, &command); diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c index 3e27a08..8030d6a 100644 --- a/drivers/infiniband/hw/mthca/mthca_cq.c +++ b/drivers/infiniband/hw/mthca/mthca_cq.c @@ -39,6 +39,8 @@ #include #include +#include + #include #include "mthca_dev.h" @@ -210,6 +212,11 @@ static inline void update_cons_index(str mthca_write64(doorbell, dev->kar + MTHCA_CQ_DOORBELL, MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock)); + /* + * Make sure doorbells don't leak out of CQ spinlock + * and reach the HCA out of order: + */ + mmiowb(); } } diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index 2e8f6f3..b66aa49 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c @@ -39,6 +39,8 @@ #include #include #include +#include + #include #include #include @@ -1730,6 +1732,11 @@ out: mthca_write64(doorbell, dev->kar + MTHCA_SEND_DOORBELL, MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock)); + /* + * Make sure doorbells don't leak out of SQ spinlock + * and reach the HCA out of order: + */ + mmiowb(); } qp->sq.next_ind = ind; @@ -1849,6 +1856,12 @@ out: qp->rq.next_ind = ind; qp->rq.head += nreq; + /* + * Make sure doorbells don't leak out of RQ spinlock and reach + * the HCA out of order: + */ + mmiowb(); + spin_unlock_irqrestore(&qp->rq.lock, flags); return err; } @@ -2110,6 +2123,12 @@ out: MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock)); } + /* + * Make sure doorbells don't leak out of SQ spinlock and reach + * the HCA out of order: + */ + mmiowb(); + spin_unlock_irqrestore(&qp->sq.lock, flags); return err; } diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c index b60a9d7..a01f1a8 100644 --- a/drivers/infiniband/hw/mthca/mthca_srq.c +++ b/drivers/infiniband/hw/mthca/mthca_srq.c @@ -35,6 +35,8 @@ #include #include +#include + #include "mthca_dev.h" #include "mthca_cmd.h" #include "mthca_memfree.h" @@ -593,6 +595,12 @@ int mthca_tavor_post_srq_recv(struct ib_ MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock)); } + /* + * Make sure doorbells don't leak out of SRQ spinlock and + * reach the HCA out of order: + */ + mmiowb(); + spin_unlock_irqrestore(&srq->lock, flags); return err; } diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index 5033666..dcd996b 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c @@ -619,8 +619,10 @@ void ipoib_ib_dev_flush(void *_dev) * The device could have been brought down between the start and when * we get here, don't bring it back up if it's not configured up */ - if (test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)) + if (test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)) { ipoib_ib_dev_up(dev); + ipoib_mcast_restart_task(dev); + } mutex_lock(&priv->vlan_mutex); diff --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c index d10c8b8..b6f9476 100644 --- a/drivers/isdn/capi/capidrv.c +++ b/drivers/isdn/capi/capidrv.c @@ -1907,7 +1907,8 @@ static int if_readstat(u8 __user *buf, i } for (p=buf, count=0; count < len; p++, count++) { - put_user(*card->q931_read++, p); + if (put_user(*card->q931_read++, p)) + return -EFAULT; if (card->q931_read > card->q931_end) card->q931_read = card->q931_buf; } diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c index e103503..9280b58 100644 --- a/drivers/isdn/hisax/config.c +++ b/drivers/isdn/hisax/config.c @@ -631,7 +631,8 @@ static int HiSax_readstatus(u_char __use count = cs->status_end - cs->status_read + 1; if (count >= len) count = len; - copy_to_user(p, cs->status_read, count); + if (copy_to_user(p, cs->status_read, count)) + return -EFAULT; cs->status_read += count; if (cs->status_read > cs->status_end) cs->status_read = cs->status_buf; @@ -642,7 +643,8 @@ static int HiSax_readstatus(u_char __use cnt = HISAX_STATUS_BUFSIZE; else cnt = count; - copy_to_user(p, cs->status_read, cnt); + if (copy_to_user(p, cs->status_read, cnt)) + return -EFAULT; p += cnt; cs->status_read += cnt % HISAX_STATUS_BUFSIZE; count -= cnt; diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c index c3d79ee..69aee26 100644 --- a/drivers/isdn/i4l/isdn_common.c +++ b/drivers/isdn/i4l/isdn_common.c @@ -1134,9 +1134,12 @@ isdn_read(struct file *file, char __user if (dev->drv[drvidx]->interface->readstat) { if (count > dev->drv[drvidx]->stavail) count = dev->drv[drvidx]->stavail; - len = dev->drv[drvidx]->interface-> - readstat(buf, count, drvidx, - isdn_minor2chan(minor)); + len = dev->drv[drvidx]->interface->readstat(buf, count, + drvidx, isdn_minor2chan(minor)); + if (len < 0) { + retval = len; + goto out; + } } else { len = 0; } diff --git a/drivers/isdn/icn/icn.c b/drivers/isdn/icn/icn.c index 6649f8b..730bbd0 100644 --- a/drivers/isdn/icn/icn.c +++ b/drivers/isdn/icn/icn.c @@ -1010,7 +1010,8 @@ icn_readstatus(u_char __user *buf, int l for (p = buf, count = 0; count < len; p++, count++) { if (card->msg_buf_read == card->msg_buf_write) return count; - put_user(*card->msg_buf_read++, p); + if (put_user(*card->msg_buf_read++, p)) + return -EFAULT; if (card->msg_buf_read > card->msg_buf_end) card->msg_buf_read = card->msg_buf; } diff --git a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c index fabbd46..9a66524 100644 --- a/drivers/isdn/isdnloop/isdnloop.c +++ b/drivers/isdn/isdnloop/isdnloop.c @@ -451,7 +451,8 @@ isdnloop_readstatus(u_char __user *buf, for (p = buf, count = 0; count < len; p++, count++) { if (card->msg_buf_read == card->msg_buf_write) return count; - put_user(*card->msg_buf_read++, p); + if (put_user(*card->msg_buf_read++, p)) + return -EFAULT; if (card->msg_buf_read > card->msg_buf_end) card->msg_buf_read = card->msg_buf; } diff --git a/drivers/isdn/pcbit/drv.c b/drivers/isdn/pcbit/drv.c index 94f2148..6ead5e1 100644 --- a/drivers/isdn/pcbit/drv.c +++ b/drivers/isdn/pcbit/drv.c @@ -725,23 +725,27 @@ static int pcbit_stat(u_char __user *buf if (stat_st < stat_end) { - copy_to_user(buf, statbuf + stat_st, len); + if (copy_to_user(buf, statbuf + stat_st, len)) + return -EFAULT; stat_st += len; } else { if (len > STATBUF_LEN - stat_st) { - copy_to_user(buf, statbuf + stat_st, - STATBUF_LEN - stat_st); - copy_to_user(buf, statbuf, - len - (STATBUF_LEN - stat_st)); + if (copy_to_user(buf, statbuf + stat_st, + STATBUF_LEN - stat_st)) + return -EFAULT; + if (copy_to_user(buf, statbuf, + len - (STATBUF_LEN - stat_st))) + return -EFAULT; stat_st = len - (STATBUF_LEN - stat_st); } else { - copy_to_user(buf, statbuf + stat_st, len); + if (copy_to_user(buf, statbuf + stat_st, len)) + return -EFAULT; stat_st += len; diff --git a/drivers/macintosh/via-pmu-backlight.c b/drivers/macintosh/via-pmu-backlight.c index a82f313..6c29fe7 100644 --- a/drivers/macintosh/via-pmu-backlight.c +++ b/drivers/macintosh/via-pmu-backlight.c @@ -16,7 +16,7 @@ #include #define MAX_PMU_LEVEL 0xFF static struct backlight_properties pmu_backlight_data; -static spinlock_t pmu_backlight_lock; +static DEFINE_SPINLOCK(pmu_backlight_lock); static int sleeping; static u8 bl_curve[FB_BACKLIGHT_LEVELS]; diff --git a/drivers/md/md.c b/drivers/md/md.c index c9d2919..1869e81 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1994,6 +1994,7 @@ static mdk_rdev_t *md_import_device(dev_ kobject_init(&rdev->kobj); rdev->desc_nr = -1; + rdev->saved_raid_disk = -1; rdev->flags = 0; rdev->data_offset = 0; rdev->sb_events = 0; diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index 1cc9de4..33f67ca 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c @@ -480,7 +480,7 @@ static int multipath_run (mddev_t *mddev mdname(mddev)); goto out_free_conf; } - mddev->degraded = conf->raid_disks = conf->working_disks; + mddev->degraded = conf->raid_disks - conf->working_disks; conf->pool = mempool_create_kzalloc_pool(NR_RESERVED_BUFS, sizeof(struct multipath_bh)); diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 016ddb8..115a6f8 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -2042,7 +2042,7 @@ static int run(mddev_t *mddev) disk = conf->mirrors + i; if (!disk->rdev || - !test_bit(In_sync, &rdev->flags)) { + !test_bit(In_sync, &disk->rdev->flags)) { disk->head_position = 0; mddev->degraded++; } diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c index 3be87c7..68bb56e 100644 --- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c @@ -527,7 +527,7 @@ int flexcop_frontend_init(struct flexcop /* try the air atsc 2nd generation (nxt2002) */ if ((fc->fe = nxt200x_attach(&samsung_tbmv_config, &fc->i2c_adap)) != NULL) { fc->dev_type = FC_AIR_ATSC2; - dvb_pll_attach(fc->fe, 0x61, &fc->i2c_adap, &dvb_pll_samsung_tbmv); + dvb_pll_attach(fc->fe, 0x61, NULL, &dvb_pll_samsung_tbmv); info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address); } else /* try the air atsc 3nd generation (lgdt3303) */ diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index 2be33f2..887d6f4 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -493,6 +493,9 @@ static int dvb_pll_sleep(struct dvb_fron int i; int result; + if (priv->i2c == NULL) + return -EINVAL; + for (i = 0; i < priv->pll_desc->count; i++) { if (priv->pll_desc->entries[i].limit == 0) break; diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index afde378..fd3ef4c 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -576,7 +576,7 @@ #ifdef HAVE_MT352 &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { dvb_pll_attach(dev->dvb.frontend, 0x60, - &dev->core->i2c_adap, + NULL, &dvb_pll_thomson_dtt7579); break; } @@ -587,7 +587,7 @@ #ifdef HAVE_ZL10353 &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { dvb_pll_attach(dev->dvb.frontend, 0x60, - &dev->core->i2c_adap, + NULL, &dvb_pll_thomson_dtt7579); } #endif @@ -600,7 +600,7 @@ #ifdef HAVE_MT352 &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { dvb_pll_attach(dev->dvb.frontend, 0x61, - &dev->core->i2c_adap, + NULL, &dvb_pll_thomson_dtt7579); break; } @@ -611,7 +611,7 @@ #ifdef HAVE_ZL10353 &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { dvb_pll_attach(dev->dvb.frontend, 0x61, - &dev->core->i2c_adap, + NULL, &dvb_pll_thomson_dtt7579); } #endif @@ -623,7 +623,7 @@ #ifdef HAVE_MT352 &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { dvb_pll_attach(dev->dvb.frontend, 0x61, - &dev->core->i2c_adap, + NULL, &dvb_pll_lg_z201); } break; @@ -634,7 +634,7 @@ #ifdef HAVE_MT352 &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { dvb_pll_attach(dev->dvb.frontend, 0x61, - &dev->core->i2c_adap, + NULL, &dvb_pll_unknown_1); } break; @@ -757,7 +757,7 @@ #ifdef HAVE_NXT200X &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { dvb_pll_attach(dev->dvb.frontend, 0x61, - &dev->core->i2c_adap, + NULL, &dvb_pll_tuv1236d); } break; diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 279828b..449fe23 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -1158,13 +1158,13 @@ #ifdef HAVE_NXT200X case SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180: dev->dvb.frontend = nxt200x_attach(&avertvhda180, &dev->i2c_adap); if (dev->dvb.frontend) { - dvb_pll_attach(dev->dvb.frontend, 0x61, &dev->i2c_adap, &dvb_pll_tdhu2); + dvb_pll_attach(dev->dvb.frontend, 0x61, NULL, &dvb_pll_tdhu2); } break; case SAA7134_BOARD_KWORLD_ATSC110: dev->dvb.frontend = nxt200x_attach(&kworldatsc110, &dev->i2c_adap); if (dev->dvb.frontend) { - dvb_pll_attach(dev->dvb.frontend, 0x61, &dev->i2c_adap, &dvb_pll_tuv1236d); + dvb_pll_attach(dev->dvb.frontend, 0x61, NULL, &dvb_pll_tuv1236d); } break; #endif diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index c590c2d..ebe7e25 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -678,7 +678,7 @@ static void sky2_mac_init(struct sky2_hw sky2_write16(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON); if (hw->chip_id == CHIP_ID_YUKON_EC_U) { - sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 768/8); + sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 512/8); sky2_write8(hw, SK_REG(port, RX_GMF_UP_THR), 1024/8); if (hw->dev[port]->mtu > ETH_DATA_LEN) { /* set Tx GMAC FIFO Almost Empty Threshold */ @@ -690,16 +690,10 @@ static void sky2_mac_init(struct sky2_hw } -/* Assign Ram Buffer allocation. - * start and end are in units of 4k bytes - * ram registers are in units of 64bit words - */ -static void sky2_ramset(struct sky2_hw *hw, u16 q, u8 startk, u8 endk) +/* Assign Ram Buffer allocation in units of 64bit (8 bytes) */ +static void sky2_ramset(struct sky2_hw *hw, u16 q, u32 start, u32 end) { - u32 start, end; - - start = startk * 4096/8; - end = (endk * 4096/8) - 1; + pr_debug(PFX "q %d %#x %#x\n", q, start, end); sky2_write8(hw, RB_ADDR(q, RB_CTRL), RB_RST_CLR); sky2_write32(hw, RB_ADDR(q, RB_START), start); @@ -708,7 +702,7 @@ static void sky2_ramset(struct sky2_hw * sky2_write32(hw, RB_ADDR(q, RB_RP), start); if (q == Q_R1 || q == Q_R2) { - u32 space = (endk - startk) * 4096/8; + u32 space = end - start + 1; u32 tp = space - space/4; /* On receive queue's set the thresholds @@ -1090,19 +1084,16 @@ static int sky2_up(struct net_device *de sky2_mac_init(hw, port); - /* Determine available ram buffer space (in 4K blocks). - * Note: not sure about the FE setting below yet - */ - if (hw->chip_id == CHIP_ID_YUKON_FE) - ramsize = 4; - else - ramsize = sky2_read8(hw, B2_E_0); + /* Determine available ram buffer space in qwords. */ + ramsize = sky2_read8(hw, B2_E_0) * 4096/8; - /* Give transmitter one third (rounded up) */ - rxspace = ramsize - (ramsize + 2) / 3; + if (ramsize > 6*1024/8) + rxspace = ramsize - (ramsize + 2) / 3; + else + rxspace = ramsize / 2; - sky2_ramset(hw, rxqaddr[port], 0, rxspace); - sky2_ramset(hw, txqaddr[port], rxspace, ramsize); + sky2_ramset(hw, rxqaddr[port], 0, rxspace-1); + sky2_ramset(hw, txqaddr[port], rxspace, ramsize-1); /* Make sure SyncQ is disabled */ sky2_write8(hw, RB_ADDR(port == 0 ? Q_XS1 : Q_XS2, RB_CTRL), @@ -1429,6 +1420,11 @@ static int sky2_down(struct net_device * /* Stop more packets from being queued */ netif_stop_queue(dev); + /* Disable port IRQ */ + imask = sky2_read32(hw, B0_IMSK); + imask &= ~portirq_msk[port]; + sky2_write32(hw, B0_IMSK, imask); + sky2_phy_reset(hw, port); /* Stop transmitter */ @@ -1472,11 +1468,6 @@ static int sky2_down(struct net_device * sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET); sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET); - /* Disable port IRQ */ - imask = sky2_read32(hw, B0_IMSK); - imask &= ~portirq_msk[port]; - sky2_write32(hw, B0_IMSK, imask); - /* turn off LED's */ sky2_write16(hw, B0_Y2LED, LED_STAT_OFF); @@ -1687,13 +1678,13 @@ static void sky2_phy_intr(struct sky2_hw struct sky2_port *sky2 = netdev_priv(dev); u16 istatus, phystat; + if (!netif_running(dev)) + return; + spin_lock(&sky2->phy_lock); istatus = gm_phy_read(hw, port, PHY_MARV_INT_STAT); phystat = gm_phy_read(hw, port, PHY_MARV_PHY_STAT); - if (!netif_running(dev)) - goto out; - if (netif_msg_intr(sky2)) printk(KERN_INFO PFX "%s: phy interrupt status 0x%x 0x%x\n", sky2->netdev->name, istatus, phystat); @@ -2745,6 +2736,14 @@ static int sky2_set_mac_address(struct n return 0; } +static void inline sky2_add_filter(u8 filter[8], const u8 *addr) +{ + u32 bit; + + bit = ether_crc(ETH_ALEN, addr) & 63; + filter[bit >> 3] |= 1 << (bit & 7); +} + static void sky2_set_multicast(struct net_device *dev) { struct sky2_port *sky2 = netdev_priv(dev); @@ -2753,6 +2752,7 @@ static void sky2_set_multicast(struct ne struct dev_mc_list *list = dev->mc_list; u16 reg; u8 filter[8]; + static const u8 pause_mc_addr[ETH_ALEN] = { 0x1, 0x80, 0xc2, 0x0, 0x0, 0x1 }; memset(filter, 0, sizeof(filter)); @@ -2763,16 +2763,17 @@ static void sky2_set_multicast(struct ne reg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA); else if ((dev->flags & IFF_ALLMULTI) || dev->mc_count > 16) /* all multicast */ memset(filter, 0xff, sizeof(filter)); - else if (dev->mc_count == 0) /* no multicast */ + else if (dev->mc_count == 0 && !sky2->rx_pause) reg &= ~GM_RXCR_MCF_ENA; else { int i; reg |= GM_RXCR_MCF_ENA; - for (i = 0; list && i < dev->mc_count; i++, list = list->next) { - u32 bit = ether_crc(ETH_ALEN, list->dmi_addr) & 0x3f; - filter[bit / 8] |= 1 << (bit % 8); - } + if (sky2->rx_pause) + sky2_add_filter(filter, pause_mc_addr); + + for (i = 0; list && i < dev->mc_count; i++, list = list->next) + sky2_add_filter(filter, list->dmi_addr); } gma_write16(hw, port, GM_MC_ADDR_H1, @@ -3208,6 +3209,8 @@ static int __devinit sky2_test_msi(struc struct pci_dev *pdev = hw->pdev; int err; + init_waitqueue_head (&hw->msi_wait); + sky2_write32(hw, B0_IMSK, Y2_IS_IRQ_SW); err = request_irq(pdev->irq, sky2_test_intr, IRQF_SHARED, DRV_NAME, hw); @@ -3217,18 +3220,15 @@ static int __devinit sky2_test_msi(struc return err; } - init_waitqueue_head (&hw->msi_wait); - sky2_write8(hw, B0_CTST, CS_ST_SW_IRQ); - wmb(); + sky2_read8(hw, B0_CTST); wait_event_timeout(hw->msi_wait, hw->msi_detected, HZ/10); if (!hw->msi_detected) { /* MSI test failed, go back to INTx mode */ - printk(KERN_WARNING PFX "%s: No interrupt was generated using MSI, " - "switching to INTx mode. Please report this failure to " - "the PCI maintainer and include system chipset information.\n", + printk(KERN_INFO PFX "%s: No interrupt generated using MSI, " + "switching to INTx mode.\n", pci_name(pdev)); err = -EOPNOTSUPP; @@ -3236,6 +3236,7 @@ static int __devinit sky2_test_msi(struc } sky2_write32(hw, B0_IMSK, 0); + sky2_read32(hw, B0_IMSK); free_irq(pdev->irq, hw); diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index ac5248b..7af5499 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h @@ -1566,7 +1566,7 @@ enum { GMR_FS_ANY_ERR = GMR_FS_RX_FF_OV | GMR_FS_CRC_ERR | GMR_FS_FRAGMENT | GMR_FS_LONG_ERR | - GMR_FS_MII_ERR | GMR_FS_BAD_FC | + GMR_FS_MII_ERR | GMR_FS_GOOD_FC | GMR_FS_BAD_FC | GMR_FS_UN_SIZE | GMR_FS_JABBER, }; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 3a73d89..f24ba4d 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -3165,7 +3165,15 @@ static void bcm43xx_periodic_work_handle badness = estimate_periodic_work_badness(bcm->periodic_state); mutex_lock(&bcm->mutex); + + /* We must fake a started transmission here, as we are going to + * disable TX. If we wouldn't fake a TX, it would be possible to + * trigger the netdev watchdog, if the last real TX is already + * some time on the past (slightly less than 5secs) + */ + bcm->net_dev->trans_start = jiffies; netif_tx_disable(bcm->net_dev); + spin_lock_irqsave(&bcm->irq_lock, flags); if (badness > BADNESS_LIMIT) { /* Periodic work will take a long time, so we want it to diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 17e709e..60b31ac 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -685,33 +685,6 @@ static void __devinit quirk_vt82c598_id( } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C597_0, quirk_vt82c598_id ); -#ifdef CONFIG_ACPI_SLEEP - -/* - * Some VIA systems boot with the abnormal status flag set. This can cause - * the BIOS to re-POST the system on resume rather than passing control - * back to the OS. Clear the flag on boot - */ -static void __devinit quirk_via_abnormal_poweroff(struct pci_dev *dev) -{ - u32 reg; - - acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_STATUS, - ®); - - if (reg & 0x800) { - printk("Clearing abnormal poweroff flag\n"); - acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK, - ACPI_REGISTER_PM1_STATUS, - (u16)0x800); - } -} - -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, quirk_via_abnormal_poweroff); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, quirk_via_abnormal_poweroff); - -#endif - /* * CardBus controllers have a legacy base address that enables them * to respond as i82365 pcmcia controllers. We don't want them to diff --git a/drivers/rtc/rtc-max6902.c b/drivers/rtc/rtc-max6902.c index 2c97395..b38208b 100644 --- a/drivers/rtc/rtc-max6902.c +++ b/drivers/rtc/rtc-max6902.c @@ -137,7 +137,7 @@ static int max6902_get_datetime(struct d dt->tm_min = BCD2BIN(chip->buf[2]); dt->tm_hour = BCD2BIN(chip->buf[3]); dt->tm_mday = BCD2BIN(chip->buf[4]); - dt->tm_mon = BCD2BIN(chip->buf[5] - 1); + dt->tm_mon = BCD2BIN(chip->buf[5]) - 1; dt->tm_wday = BCD2BIN(chip->buf[6]); dt->tm_year = BCD2BIN(chip->buf[7]); diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index aa4be8a..129444a 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -2539,15 +2539,28 @@ #endif static void ahc_linux_get_signalling(struct Scsi_Host *shost) { struct ahc_softc *ahc = *(struct ahc_softc **)shost->hostdata; - u8 mode = ahc_inb(ahc, SBLKCTL); + unsigned long flags; + u8 mode; - if (mode & ENAB40) - spi_signalling(shost) = SPI_SIGNAL_LVD; - else if (mode & ENAB20) + if (!(ahc->features & AHC_ULTRA2)) { + /* non-LVD chipset, may not have SBLKCTL reg */ spi_signalling(shost) = ahc->features & AHC_HVD ? SPI_SIGNAL_HVD : SPI_SIGNAL_SE; + return; + } + + ahc_lock(ahc, &flags); + ahc_pause(ahc); + mode = ahc_inb(ahc, SBLKCTL); + ahc_unpause(ahc); + ahc_unlock(ahc, &flags); + + if (mode & ENAB40) + spi_signalling(shost) = SPI_SIGNAL_LVD; + else if (mode & ENAB20) + spi_signalling(shost) = SPI_SIGNAL_SE; else spi_signalling(shost) = SPI_SIGNAL_UNKNOWN; } diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 372e47f..c59dcb7 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -1932,6 +1932,9 @@ int uart_suspend_port(struct uart_driver if (state->info && state->info->flags & UIF_INITIALIZED) { const struct uart_ops *ops = port->ops; + state->info->flags = (state->info->flags & ~UIF_INITIALIZED) + | UIF_SUSPENDED; + spin_lock_irq(&port->lock); ops->stop_tx(port); ops->set_mctrl(port, 0); @@ -1991,7 +1994,7 @@ int uart_resume_port(struct uart_driver console_start(port->cons); } - if (state->info && state->info->flags & UIF_INITIALIZED) { + if (state->info && state->info->flags & UIF_SUSPENDED) { const struct uart_ops *ops = port->ops; int ret; @@ -2003,15 +2006,17 @@ int uart_resume_port(struct uart_driver ops->set_mctrl(port, port->mctrl); ops->start_tx(port); spin_unlock_irq(&port->lock); + state->info->flags |= UIF_INITIALIZED; } else { /* * Failed to resume - maybe hardware went away? * Clear the "initialized" flag so we won't try * to call the low level drivers shutdown method. */ - state->info->flags &= ~UIF_INITIALIZED; uart_shutdown(state); } + + state->info->flags &= ~UIF_SUSPENDED; } mutex_unlock(&state->mutex); diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index cbf260b..06a246a 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -185,14 +185,12 @@ static int serial_suspend(struct pcmcia_ static int serial_resume(struct pcmcia_device *link) { - if (pcmcia_dev_present(link)) { - struct serial_info *info = link->priv; - int i; + struct serial_info *info = link->priv; + int i; - for (i = 0; i < info->ndev; i++) - serial8250_resume_port(info->line[i]); - wakeup_card(info); - } + for (i = 0; i < info->ndev; i++) + serial8250_resume_port(info->line[i]); + wakeup_card(info); return 0; } diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 218621b..ab6cc03 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -59,6 +59,9 @@ #define USB_MAXBUS 64 #define USB_DEVICE_MAX USB_MAXBUS * 128 static struct class *usb_device_class; +/* Mutual exclusion for removal, open, and release */ +DEFINE_MUTEX(usbfs_mutex); + struct async { struct list_head asynclist; struct dev_state *ps; @@ -541,15 +544,13 @@ static int usbdev_open(struct inode *ino struct dev_state *ps; int ret; - /* - * no locking necessary here, as chrdev_open has the kernel lock - * (still acquire the kernel lock for safety) - */ + /* Protect against simultaneous removal or release */ + mutex_lock(&usbfs_mutex); + ret = -ENOMEM; if (!(ps = kmalloc(sizeof(struct dev_state), GFP_KERNEL))) - goto out_nolock; + goto out; - lock_kernel(); ret = -ENOENT; /* check if we are called from a real node or usbfs */ if (imajor(inode) == USB_DEVICE_MAJOR) @@ -579,9 +580,8 @@ static int usbdev_open(struct inode *ino list_add_tail(&ps->list, &dev->filelist); file->private_data = ps; out: - unlock_kernel(); - out_nolock: - return ret; + mutex_unlock(&usbfs_mutex); + return ret; } static int usbdev_release(struct inode *inode, struct file *file) @@ -591,7 +591,12 @@ static int usbdev_release(struct inode * unsigned int ifnum; usb_lock_device(dev); + + /* Protect against simultaneous open */ + mutex_lock(&usbfs_mutex); list_del_init(&ps->list); + mutex_unlock(&usbfs_mutex); + for (ifnum = 0; ps->ifclaimed && ifnum < 8*sizeof(ps->ifclaimed); ifnum++) { if (test_bit(ifnum, &ps->ifclaimed)) @@ -600,9 +605,8 @@ static int usbdev_release(struct inode * destroy_all_async(ps); usb_unlock_device(dev); usb_put_dev(dev); - ps->dev = NULL; kfree(ps); - return 0; + return 0; } static int proc_control(struct dev_state *ps, void __user *arg) diff --git a/drivers/usb/core/notify.c b/drivers/usb/core/notify.c index b042676..6b36897 100644 --- a/drivers/usb/core/notify.c +++ b/drivers/usb/core/notify.c @@ -50,8 +50,11 @@ void usb_notify_add_device(struct usb_de void usb_notify_remove_device(struct usb_device *udev) { + /* Protect against simultaneous usbfs open */ + mutex_lock(&usbfs_mutex); blocking_notifier_call_chain(&usb_notifier_list, USB_DEVICE_REMOVE, udev); + mutex_unlock(&usbfs_mutex); } void usb_notify_add_bus(struct usb_bus *ubus) diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 49f6923..1217fbb 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -59,6 +59,7 @@ static inline int is_active(struct usb_i extern const char *usbcore_name; /* usbfs stuff */ +extern struct mutex usbfs_mutex; extern struct usb_driver usbfs_driver; extern struct file_operations usbfs_devices_fops; extern struct file_operations usbfs_device_file_operations; diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 409ce6a..5d7c726 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -935,14 +935,30 @@ static void iattr_to_fattr(struct iattr } } +static void fuse_vmtruncate(struct inode *inode, loff_t offset) +{ + struct fuse_conn *fc = get_fuse_conn(inode); + int need_trunc; + + spin_lock(&fc->lock); + need_trunc = inode->i_size > offset; + i_size_write(inode, offset); + spin_unlock(&fc->lock); + + if (need_trunc) { + struct address_space *mapping = inode->i_mapping; + unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1); + truncate_inode_pages(mapping, offset); + } +} + /* * Set attributes, and at the same time refresh them. * * Truncation is slightly complicated, because the 'truncate' request * may fail, in which case we don't want to touch the mapping. - * vmtruncate() doesn't allow for this case. So do the rlimit - * checking by hand and call vmtruncate() only after the file has - * actually been truncated. + * vmtruncate() doesn't allow for this case, so do the rlimit checking + * and the actual truncation by hand. */ static int fuse_setattr(struct dentry *entry, struct iattr *attr) { @@ -993,12 +1009,8 @@ static int fuse_setattr(struct dentry *e make_bad_inode(inode); err = -EIO; } else { - if (is_truncate) { - loff_t origsize = i_size_read(inode); - i_size_write(inode, outarg.attr.size); - if (origsize > outarg.attr.size) - vmtruncate(inode, outarg.attr.size); - } + if (is_truncate) + fuse_vmtruncate(inode, outarg.attr.size); fuse_change_attributes(inode, &outarg.attr); fi->i_time = time_to_jiffies(outarg.attr_valid, outarg.attr_valid_nsec); diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 5c4fcd1..4e174c8 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -481,8 +481,10 @@ static int fuse_commit_write(struct file err = -EIO; if (!err) { pos += count; - if (pos > i_size_read(inode)) + spin_lock(&fc->lock); + if (pos > inode->i_size) i_size_write(inode, pos); + spin_unlock(&fc->lock); if (offset == 0 && to == PAGE_CACHE_SIZE) { clear_page_dirty(page); @@ -586,8 +588,12 @@ static ssize_t fuse_direct_io(struct fil } fuse_put_request(fc, req); if (res > 0) { - if (write && pos > i_size_read(inode)) - i_size_write(inode, pos); + if (write) { + spin_lock(&fc->lock); + if (pos > inode->i_size) + i_size_write(inode, pos); + spin_unlock(&fc->lock); + } *ppos = pos; } fuse_invalidate_attr(inode); diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 7d25092..65df8a4 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -109,6 +109,7 @@ static int fuse_remount_fs(struct super_ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr) { + struct fuse_conn *fc = get_fuse_conn(inode); if (S_ISREG(inode->i_mode) && i_size_read(inode) != attr->size) invalidate_inode_pages(inode->i_mapping); @@ -117,7 +118,9 @@ void fuse_change_attributes(struct inode inode->i_nlink = attr->nlink; inode->i_uid = attr->uid; inode->i_gid = attr->gid; + spin_lock(&fc->lock); i_size_write(inode, attr->size); + spin_unlock(&fc->lock); inode->i_blksize = PAGE_CACHE_SIZE; inode->i_blocks = attr->blocks; inode->i_atime.tv_sec = attr->atime; @@ -131,7 +134,7 @@ void fuse_change_attributes(struct inode static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr) { inode->i_mode = attr->mode & S_IFMT; - i_size_write(inode, attr->size); + inode->i_size = attr->size; if (S_ISREG(inode->i_mode)) { fuse_init_common(inode); fuse_init_file_inode(inode); diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c index ccbe60a..3bdd90b 100644 --- a/fs/jfs/jfs_imap.c +++ b/fs/jfs/jfs_imap.c @@ -318,7 +318,7 @@ int diRead(struct inode *ip) struct inomap *imap; int block_offset; int inodes_left; - uint pageno; + unsigned long pageno; int rel_inode; jfs_info("diRead: ino = %ld", ip->i_ino); @@ -606,7 +606,7 @@ int diWrite(tid_t tid, struct inode *ip) int block_offset; int inodes_left; struct metapage *mp; - uint pageno; + unsigned long pageno; int rel_inode; int dioffset; struct inode *ipimap; diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index e7ffb4d..f86b9b4 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -902,9 +902,15 @@ static struct dentry *nfs_lookup(struct lock_kernel(); - /* If we're doing an exclusive create, optimize away the lookup */ - if (nfs_is_exclusive_create(dir, nd)) - goto no_entry; + /* + * If we're doing an exclusive create, optimize away the lookup + * but don't hash the dentry. + */ + if (nfs_is_exclusive_create(dir, nd)) { + d_instantiate(dentry, NULL); + res = NULL; + goto out_unlock; + } error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr); if (error == -ENOENT) @@ -1156,6 +1162,8 @@ int nfs_instantiate(struct dentry *dentr if (IS_ERR(inode)) goto out_err; d_instantiate(dentry, inode); + if (d_unhashed(dentry)) + d_rehash(dentry); return 0; out_err: d_drop(dentry); diff --git a/fs/splice.c b/fs/splice.c index 684bca3..4eed2f6 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -607,7 +607,7 @@ find_page: ret = -ENOMEM; page = page_cache_alloc_cold(mapping); if (unlikely(!page)) - goto out_nomem; + goto out_ret; /* * This will also lock the page @@ -666,7 +666,7 @@ find_page: if (sd->pos + this_len > isize) vmtruncate(mapping->host, isize); - goto out; + goto out_ret; } if (buf->page != page) { @@ -698,7 +698,7 @@ find_page: out: page_cache_release(page); unlock_page(page); -out_nomem: +out_ret: return ret; } diff --git a/include/asm-generic/audit_change_attr.h b/include/asm-generic/audit_change_attr.h index cb05bf6..5076455 100644 --- a/include/asm-generic/audit_change_attr.h +++ b/include/asm-generic/audit_change_attr.h @@ -1,16 +1,20 @@ __NR_chmod, __NR_fchmod, +#ifdef __NR_chown __NR_chown, __NR_fchown, __NR_lchown, +#endif __NR_setxattr, __NR_lsetxattr, __NR_fsetxattr, __NR_removexattr, __NR_lremovexattr, __NR_fremovexattr, +#ifdef __NR_fchownat __NR_fchownat, __NR_fchmodat, +#endif #ifdef __NR_chown32 __NR_chown32, __NR_fchown32, diff --git a/include/asm-generic/audit_dir_write.h b/include/asm-generic/audit_dir_write.h index 161a7a5..6621bd8 100644 --- a/include/asm-generic/audit_dir_write.h +++ b/include/asm-generic/audit_dir_write.h @@ -1,14 +1,18 @@ __NR_rename, __NR_mkdir, __NR_rmdir, +#ifdef __NR_creat __NR_creat, +#endif __NR_link, __NR_unlink, __NR_symlink, __NR_mknod, +#ifdef __NR_mkdirat __NR_mkdirat, __NR_mknodat, __NR_unlinkat, __NR_renameat, __NR_linkat, __NR_symlinkat, +#endif diff --git a/include/asm-s390/div64.h b/include/asm-s390/div64.h index af098dc..6cd978c 100644 --- a/include/asm-s390/div64.h +++ b/include/asm-s390/div64.h @@ -1,49 +1 @@ -#ifndef __S390_DIV64 -#define __S390_DIV64 - -#ifndef __s390x__ - -/* for do_div "base" needs to be smaller than 2^31-1 */ -#define do_div(n, base) ({ \ - unsigned long long __n = (n); \ - unsigned long __r; \ - \ - asm (" slr 0,0\n" \ - " l 1,%1\n" \ - " srdl 0,1\n" \ - " dr 0,%2\n" \ - " alr 1,1\n" \ - " alr 0,0\n" \ - " lhi 2,1\n" \ - " n 2,%1\n" \ - " alr 0,2\n" \ - " clr 0,%2\n" \ - " jl 0f\n" \ - " slr 0,%2\n" \ - " ahi 1,1\n" \ - "0: st 1,%1\n" \ - " l 1,4+%1\n" \ - " srdl 0,1\n" \ - " dr 0,%2\n" \ - " alr 1,1\n" \ - " alr 0,0\n" \ - " lhi 2,1\n" \ - " n 2,4+%1\n" \ - " alr 0,2\n" \ - " clr 0,%2\n" \ - " jl 1f\n" \ - " slr 0,%2\n" \ - " ahi 1,1\n" \ - "1: st 1,4+%1\n" \ - " lr %0,0" \ - : "=d" (__r), "=m" (__n) \ - : "d" (base), "m" (__n) : "0", "1", "2", "cc" ); \ - (n) = (__n); \ - __r; \ -}) - -#else /* __s390x__ */ #include -#endif /* __s390x__ */ - -#endif diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 5951364..5dfe111 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -200,13 +200,9 @@ #endif * under - it drives the swappiness decision: whether to unmap mapped * pages. * - * temp_priority is used to remember the scanning priority at which - * this zone was successfully refilled to free_pages == pages_high. - * - * Access to both these fields is quite racy even on uniprocessor. But + * Access to both this field is quite racy even on uniprocessor. But * it is expected to average out OK. */ - int temp_priority; int prev_priority; @@ -632,6 +628,12 @@ #define sparse_init() do {} while (0) #define sparse_index_init(_sec, _nid) do {} while (0) #endif /* CONFIG_SPARSEMEM */ +#ifdef CONFIG_NODES_SPAN_OTHER_NODES +#define early_pfn_in_nid(pfn, nid) (early_pfn_to_nid(pfn) == (nid)) +#else +#define early_pfn_in_nid(pfn, nid) (1) +#endif + #ifndef early_pfn_valid #define early_pfn_valid(pfn) (1) #endif diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 86501a3..f9fdf97 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -319,6 +319,7 @@ #define UIF_CHECK_CD ((__force uif_t) ( #define UIF_CTS_FLOW ((__force uif_t) (1 << 26)) #define UIF_NORMAL_ACTIVE ((__force uif_t) (1 << 29)) #define UIF_INITIALIZED ((__force uif_t) (1 << 31)) +#define UIF_SUSPENDED ((__force uif_t) (1 << 30)) int blocked_open; diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c index d38d9ec..0779b48 100644 --- a/kernel/posix-cpu-timers.c +++ b/kernel/posix-cpu-timers.c @@ -88,6 +88,19 @@ static inline union cpu_time_count cpu_t } /* + * Divide and limit the result to res >= 1 + * + * This is necessary to prevent signal delivery starvation, when the result of + * the division would be rounded down to 0. + */ +static inline cputime_t cputime_div_non_zero(cputime_t time, unsigned long div) +{ + cputime_t res = cputime_div(time, div); + + return max_t(cputime_t, res, 1); +} + +/* * Update expiry time from increment, and increase overrun count, * given the current clock sample. */ @@ -483,8 +496,8 @@ static void process_timer_rebalance(stru BUG(); break; case CPUCLOCK_PROF: - left = cputime_div(cputime_sub(expires.cpu, val.cpu), - nthreads); + left = cputime_div_non_zero(cputime_sub(expires.cpu, val.cpu), + nthreads); do { if (likely(!(t->flags & PF_EXITING))) { ticks = cputime_add(prof_ticks(t), left); @@ -498,8 +511,8 @@ static void process_timer_rebalance(stru } while (t != p); break; case CPUCLOCK_VIRT: - left = cputime_div(cputime_sub(expires.cpu, val.cpu), - nthreads); + left = cputime_div_non_zero(cputime_sub(expires.cpu, val.cpu), + nthreads); do { if (likely(!(t->flags & PF_EXITING))) { ticks = cputime_add(virt_ticks(t), left); @@ -515,6 +528,7 @@ static void process_timer_rebalance(stru case CPUCLOCK_SCHED: nsleft = expires.sched - val.sched; do_div(nsleft, nthreads); + nsleft = max_t(unsigned long long, nsleft, 1); do { if (likely(!(t->flags & PF_EXITING))) { ns = t->sched_time + nsleft; @@ -1159,12 +1173,13 @@ static void check_process_timers(struct prof_left = cputime_sub(prof_expires, utime); prof_left = cputime_sub(prof_left, stime); - prof_left = cputime_div(prof_left, nthreads); + prof_left = cputime_div_non_zero(prof_left, nthreads); virt_left = cputime_sub(virt_expires, utime); - virt_left = cputime_div(virt_left, nthreads); + virt_left = cputime_div_non_zero(virt_left, nthreads); if (sched_expires) { sched_left = sched_expires - sched_time; do_div(sched_left, nthreads); + sched_left = max_t(unsigned long long, sched_left, 1); } else { sched_left = 0; } diff --git a/kernel/taskstats.c b/kernel/taskstats.c index e781876..b90b2a7 100644 --- a/kernel/taskstats.c +++ b/kernel/taskstats.c @@ -229,14 +229,17 @@ static int fill_tgid(pid_t tgid, struct } else get_task_struct(first); - /* Start with stats from dead tasks */ - spin_lock_irqsave(&first->signal->stats_lock, flags); - if (first->signal->stats) - memcpy(stats, first->signal->stats, sizeof(*stats)); - spin_unlock_irqrestore(&first->signal->stats_lock, flags); tsk = first; read_lock(&tasklist_lock); + /* Start with stats from dead tasks */ + if (first->signal) { + spin_lock_irqsave(&first->signal->stats_lock, flags); + if (first->signal->stats) + memcpy(stats, first->signal->stats, sizeof(*stats)); + spin_unlock_irqrestore(&first->signal->stats_lock, flags); + } + do { if (tsk->exit_state == EXIT_ZOMBIE && thread_group_leader(tsk)) continue; @@ -256,7 +259,7 @@ static int fill_tgid(pid_t tgid, struct * Accounting subsytems can also add calls here to modify * fields of taskstats. */ - + put_task_struct(first); return 0; } diff --git a/lib/audit.c b/lib/audit.c index 8c21625..3b1289f 100644 --- a/lib/audit.c +++ b/lib/audit.c @@ -28,8 +28,10 @@ int audit_classify_syscall(int abi, unsi switch(syscall) { case __NR_open: return 2; +#ifdef __NR_openat case __NR_openat: return 3; +#endif #ifdef __NR_socketcall case __NR_socketcall: return 4; diff --git a/mm/memory.c b/mm/memory.c index 109e986..d28450c 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1551,7 +1551,14 @@ gotten: entry = mk_pte(new_page, vma->vm_page_prot); entry = maybe_mkwrite(pte_mkdirty(entry), vma); lazy_mmu_prot_update(entry); - ptep_establish(vma, address, page_table, entry); + /* + * Clear the pte entry and flush it first, before updating the + * pte with the new entry. This will avoid a race condition + * seen in the presence of one thread doing SMC and another + * thread doing COW. + */ + ptep_clear_flush(vma, address, page_table); + set_pte_at(mm, address, page_table, entry); update_mmu_cache(vma, address, entry); lru_cache_add_active(new_page); page_add_new_anon_rmap(new_page, vma, address); diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 7e92c94..128b9f5 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1673,6 +1673,8 @@ void __meminit memmap_init_zone(unsigned for (pfn = start_pfn; pfn < end_pfn; pfn++) { if (!early_pfn_valid(pfn)) continue; + if (!early_pfn_in_nid(pfn, nid)) + continue; page = pfn_to_page(pfn); set_page_links(page, zone, nid, pfn); init_page_count(page); @@ -2019,7 +2021,7 @@ #endif zone->zone_pgdat = pgdat; zone->free_pages = 0; - zone->temp_priority = zone->prev_priority = DEF_PRIORITY; + zone->prev_priority = DEF_PRIORITY; zone_pcp_init(zone); INIT_LIST_HEAD(&zone->active_list); diff --git a/mm/vmscan.c b/mm/vmscan.c index 1dad4b6..a04fb41 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -696,6 +696,20 @@ done: } /* + * We are about to scan this zone at a certain priority level. If that priority + * level is smaller (ie: more urgent) than the previous priority, then note + * that priority level within the zone. This is done so that when the next + * process comes in to scan this zone, it will immediately start out at this + * priority level rather than having to build up its own scanning priority. + * Here, this priority affects only the reclaim-mapped threshold. + */ +static inline void note_zone_scanning_priority(struct zone *zone, int priority) +{ + if (priority < zone->prev_priority) + zone->prev_priority = priority; +} + +/* * This moves pages from the active list to the inactive list. * * We move them the other way if the page is referenced by one or more @@ -713,7 +727,7 @@ done: * But we had to alter page->flags anyway. */ static void shrink_active_list(unsigned long nr_pages, struct zone *zone, - struct scan_control *sc) + struct scan_control *sc, int priority) { unsigned long pgmoved; int pgdeactivate = 0; @@ -734,7 +748,7 @@ static void shrink_active_list(unsigned * `distress' is a measure of how much trouble we're having * reclaiming pages. 0 -> no problems. 100 -> great trouble. */ - distress = 100 >> zone->prev_priority; + distress = 100 >> min(zone->prev_priority, priority); /* * The point of this algorithm is to decide when to start @@ -885,7 +899,7 @@ static unsigned long shrink_zone(int pri nr_to_scan = min(nr_active, (unsigned long)sc->swap_cluster_max); nr_active -= nr_to_scan; - shrink_active_list(nr_to_scan, zone, sc); + shrink_active_list(nr_to_scan, zone, sc, priority); } if (nr_inactive) { @@ -934,9 +948,7 @@ static unsigned long shrink_zones(int pr if (!cpuset_zone_allowed(zone, __GFP_HARDWALL)) continue; - zone->temp_priority = priority; - if (zone->prev_priority > priority) - zone->prev_priority = priority; + note_zone_scanning_priority(zone, priority); if (zone->all_unreclaimable && priority != DEF_PRIORITY) continue; /* Let kswapd poll it */ @@ -984,7 +996,6 @@ unsigned long try_to_free_pages(struct z if (!cpuset_zone_allowed(zone, __GFP_HARDWALL)) continue; - zone->temp_priority = DEF_PRIORITY; lru_pages += zone->nr_active + zone->nr_inactive; } @@ -1022,13 +1033,22 @@ unsigned long try_to_free_pages(struct z blk_congestion_wait(WRITE, HZ/10); } out: + /* + * Now that we've scanned all the zones at this priority level, note + * that level within the zone so that the next thread which performs + * scanning of this zone will immediately start out at this priority + * level. This affects only the decision whether or not to bring + * mapped pages onto the inactive list. + */ + if (priority < 0) + priority = 0; for (i = 0; zones[i] != 0; i++) { struct zone *zone = zones[i]; if (!cpuset_zone_allowed(zone, __GFP_HARDWALL)) continue; - zone->prev_priority = zone->temp_priority; + zone->prev_priority = priority; } return ret; } @@ -1068,6 +1088,11 @@ static unsigned long balance_pgdat(pg_da .swap_cluster_max = SWAP_CLUSTER_MAX, .swappiness = vm_swappiness, }; + /* + * temp_priority is used to remember the scanning priority at which + * this zone was successfully refilled to free_pages == pages_high. + */ + int temp_priority[MAX_NR_ZONES]; loop_again: total_scanned = 0; @@ -1075,11 +1100,8 @@ loop_again: sc.may_writepage = !laptop_mode; count_vm_event(PAGEOUTRUN); - for (i = 0; i < pgdat->nr_zones; i++) { - struct zone *zone = pgdat->node_zones + i; - - zone->temp_priority = DEF_PRIORITY; - } + for (i = 0; i < pgdat->nr_zones; i++) + temp_priority[i] = DEF_PRIORITY; for (priority = DEF_PRIORITY; priority >= 0; priority--) { int end_zone = 0; /* Inclusive. 0 = ZONE_DMA */ @@ -1140,10 +1162,9 @@ scan: if (!zone_watermark_ok(zone, order, zone->pages_high, end_zone, 0)) all_zones_ok = 0; - zone->temp_priority = priority; - if (zone->prev_priority > priority) - zone->prev_priority = priority; + temp_priority[i] = priority; sc.nr_scanned = 0; + note_zone_scanning_priority(zone, priority); nr_reclaimed += shrink_zone(priority, zone, &sc); reclaim_state->reclaimed_slab = 0; nr_slab = shrink_slab(sc.nr_scanned, GFP_KERNEL, @@ -1183,10 +1204,15 @@ scan: break; } out: + /* + * Note within each zone the priority level at which this zone was + * brought into a happy state. So that the next thread which scans this + * zone will start out at that priority level. + */ for (i = 0; i < pgdat->nr_zones; i++) { struct zone *zone = pgdat->node_zones + i; - zone->prev_priority = zone->temp_priority; + zone->prev_priority = temp_priority[i]; } if (!all_zones_ok) { cond_resched(); @@ -1315,7 +1341,7 @@ static unsigned long shrink_all_zones(un if (zone->nr_scan_active >= nr_pages || pass > 3) { zone->nr_scan_active = 0; nr_to_scan = min(nr_pages, zone->nr_active); - shrink_active_list(nr_to_scan, zone, sc); + shrink_active_list(nr_to_scan, zone, sc, prio); } } @@ -1570,6 +1596,7 @@ static int __zone_reclaim(struct zone *z */ priority = ZONE_RECLAIM_PRIORITY; do { + note_zone_scanning_priority(zone, priority); nr_reclaimed += shrink_zone(priority, zone, &sc); priority--; } while (priority >= 0 && nr_reclaimed < nr_pages); diff --git a/mm/vmstat.c b/mm/vmstat.c index c1b5f41..0e3f7e2 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c @@ -586,11 +586,9 @@ #endif seq_printf(m, "\n all_unreclaimable: %u" "\n prev_priority: %i" - "\n temp_priority: %i" "\n start_pfn: %lu", zone->all_unreclaimable, zone->prev_priority, - zone->temp_priority, zone->zone_start_pfn); spin_unlock_irqrestore(&zone->lock, flags); seq_putc(m, '\n'); diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index bd8d671..5d65ceb 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c @@ -748,6 +748,9 @@ static void rfcomm_tty_set_termios(struc BT_DBG("tty %p termios %p", tty, old); + if (!dev) + return; + /* Handle turning off CRTSCTS */ if ((old->c_cflag & CRTSCTS) && !(new->c_cflag & CRTSCTS)) BT_DBG("Turning off CRTSCTS unsupported"); diff --git a/net/core/skbuff.c b/net/core/skbuff.c index c54f366..7de9857 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -1945,7 +1945,7 @@ struct sk_buff *skb_segment(struct sk_bu do { struct sk_buff *nskb; skb_frag_t *frag; - int hsize, nsize; + int hsize; int k; int size; @@ -1956,11 +1956,10 @@ struct sk_buff *skb_segment(struct sk_bu hsize = skb_headlen(skb) - offset; if (hsize < 0) hsize = 0; - nsize = hsize + doffset; - if (nsize > len + doffset || !sg) - nsize = len + doffset; + if (hsize > len || !sg) + hsize = len; - nskb = alloc_skb(nsize + headroom, GFP_ATOMIC); + nskb = alloc_skb(hsize + doffset + headroom, GFP_ATOMIC); if (unlikely(!nskb)) goto err; diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c index 5486247..07d9869 100644 --- a/net/decnet/af_decnet.c +++ b/net/decnet/af_decnet.c @@ -1177,8 +1177,10 @@ static int dn_getname(struct socket *soc if (peer) { if ((sock->state != SS_CONNECTED && sock->state != SS_CONNECTING) && - scp->accept_mode == ACC_IMMED) + scp->accept_mode == ACC_IMMED) { + release_sock(sk); return -ENOTCONN; + } memcpy(sa, &scp->peer, sizeof(struct sockaddr_dn)); } else { diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c index 2be2798..c3b01b5 100644 --- a/net/ipv4/tcp_cubic.c +++ b/net/ipv4/tcp_cubic.c @@ -190,7 +190,7 @@ static inline void bictcp_update(struct */ /* change the unit from HZ to bictcp_HZ */ - t = ((tcp_time_stamp + ca->delay_min - ca->epoch_start) + t = ((tcp_time_stamp + (ca->delay_min>>3) - ca->epoch_start) << BICTCP_HZ) / HZ; if (t < ca->bic_K) /* t - K */ @@ -259,7 +259,7 @@ static inline void measure_delay(struct (s32)(tcp_time_stamp - ca->epoch_start) < HZ) return; - delay = tcp_time_stamp - tp->rx_opt.rcv_tsecr; + delay = (tcp_time_stamp - tp->rx_opt.rcv_tsecr)<<3; if (delay == 0) delay = 1; @@ -366,7 +366,7 @@ static int __init cubictcp_register(void beta_scale = 8*(BICTCP_BETA_SCALE+beta)/ 3 / (BICTCP_BETA_SCALE - beta); - cube_rtt_scale = (bic_scale << 3) / 10; /* 1024*c/rtt */ + cube_rtt_scale = (bic_scale * 10); /* 1024*c/rtt */ /* calculate the "K" for (wmax-cwnd) = c/rtt * K^3 * so K = cubic_root( (wmax-cwnd)*rtt/c ) diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index 1d672b0..062e526 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c @@ -587,6 +587,8 @@ static struct ip6_flowlabel *ip6fl_get_n while (!fl) { if (++state->bucket <= FL_HASH_MASK) fl = fl_ht[state->bucket]; + else + break; } return fl; } diff --git a/net/sctp/input.c b/net/sctp/input.c index 42b66e7..2060bbe 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -135,6 +135,9 @@ int sctp_rcv(struct sk_buff *skb) SCTP_INC_STATS_BH(SCTP_MIB_INSCTPPACKS); + if (skb_linearize(skb)) + goto discard_it; + sh = (struct sctphdr *) skb->h.raw; /* Pull up the IP and SCTP headers. */ diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index d9a9573..2544acd 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -902,7 +902,7 @@ svc_tcp_recvfrom(struct svc_rqst *rqstp) return 0; } - if (test_bit(SK_CONN, &svsk->sk_flags)) { + if (svsk->sk_sk->sk_state == TCP_LISTEN) { svc_tcp_accept(svsk); svc_sock_received(svsk); return 0; diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c index 8bd0dcc..a562f96 100644 --- a/sound/core/hwdep.c +++ b/sound/core/hwdep.c @@ -158,6 +158,7 @@ static int snd_hwdep_release(struct inod { int err = -ENXIO; struct snd_hwdep *hw = file->private_data; + struct module *mod = hw->card->module; mutex_lock(&hw->open_mutex); if (hw->ops.release) { err = hw->ops.release(hw, file); @@ -167,7 +168,7 @@ static int snd_hwdep_release(struct inod hw->used--; snd_card_file_remove(hw->card, file); mutex_unlock(&hw->open_mutex); - module_put(hw->card->module); + module_put(mod); return err; } diff --git a/sound/core/info.c b/sound/core/info.c index 340332c..57821ce 100644 --- a/sound/core/info.c +++ b/sound/core/info.c @@ -119,7 +119,10 @@ int snd_iprintf(struct snd_info_buffer * len = buffer->len - buffer->size; va_start(args, fmt); for (;;) { - res = vsnprintf(buffer->buffer + buffer->curr, len, fmt, args); + va_list ap; + va_copy(ap, args); + res = vsnprintf(buffer->buffer + buffer->curr, len, fmt, ap); + va_end(ap); if (res < len) break; err = resize_info_buffer(buffer, buffer->len + PAGE_SIZE); diff --git a/sound/core/rtctimer.c b/sound/core/rtctimer.c index 84704cc..15b6c8a 100644 --- a/sound/core/rtctimer.c +++ b/sound/core/rtctimer.c @@ -50,7 +50,9 @@ static int rtctimer_stop(struct snd_time * The hardware dependent description for this timer. */ static struct snd_timer_hardware rtc_hw = { - .flags = SNDRV_TIMER_HW_FIRST|SNDRV_TIMER_HW_AUTO, + .flags = SNDRV_TIMER_HW_AUTO | + SNDRV_TIMER_HW_FIRST | + SNDRV_TIMER_HW_TASKLET, .ticks = 100000000L, /* FIXME: XXX */ .open = rtctimer_open, .close = rtctimer_close, @@ -60,6 +62,7 @@ static struct snd_timer_hardware rtc_hw static int rtctimer_freq = RTC_FREQ; /* frequency */ static struct snd_timer *rtctimer; +static struct tasklet_struct rtc_tasklet; static rtc_task_t rtc_task; @@ -81,6 +84,7 @@ rtctimer_close(struct snd_timer *t) rtc_task_t *rtc = t->private_data; if (rtc) { rtc_unregister(rtc); + tasklet_kill(&rtc_tasklet); t->private_data = NULL; } return 0; @@ -105,12 +109,17 @@ rtctimer_stop(struct snd_timer *timer) return 0; } +static void rtctimer_tasklet(unsigned long data) +{ + snd_timer_interrupt((struct snd_timer *)data, 1); +} + /* * interrupt */ static void rtctimer_interrupt(void *private_data) { - snd_timer_interrupt(private_data, 1); + tasklet_hi_schedule(private_data); } @@ -139,9 +148,11 @@ static int __init rtctimer_init(void) timer->hw = rtc_hw; timer->hw.resolution = NANO_SEC / rtctimer_freq; + tasklet_init(&rtc_tasklet, rtctimer_tasklet, (unsigned long)timer); + /* set up RTC callback */ rtc_task.func = rtctimer_interrupt; - rtc_task.private_data = timer; + rtc_task.private_data = &rtc_tasklet; err = snd_timer_global_register(timer); if (err < 0) { diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c index ef189d7..6ed5ad5 100644 --- a/sound/pci/au88x0/au88x0.c +++ b/sound/pci/au88x0/au88x0.c @@ -128,6 +128,7 @@ static int snd_vortex_dev_free(struct sn // Take down PCI interface. synchronize_irq(vortex->irq); free_irq(vortex->irq, vortex); + iounmap(vortex->mmio); pci_release_regions(vortex->pci_dev); pci_disable_device(vortex->pci_dev); kfree(vortex); diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index 79f24cd..bc1dfdc 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c @@ -1460,8 +1460,8 @@ void snd_emu10k1_resume_regs(struct snd_ /* resore for spdif */ if (emu->audigy) - outl(emu->port + A_IOCFG, emu->saved_a_iocfg); - outl(emu->port + HCFG, emu->saved_hcfg); + outl(emu->saved_a_iocfg, emu->port + A_IOCFG); + outl(emu->saved_hcfg, emu->port + HCFG); val = emu->saved_ptr; for (reg = saved_regs; *reg != 0xff; reg++) diff --git a/sound/ppc/keywest.c b/sound/ppc/keywest.c index 59482a4..272ae38 100644 --- a/sound/ppc/keywest.c +++ b/sound/ppc/keywest.c @@ -117,6 +117,9 @@ int __init snd_pmac_tumbler_post_init(vo { int err; + if (!keywest_ctx || !keywest_ctx->client) + return -ENXIO; + if ((err = keywest_ctx->init_client(keywest_ctx)) < 0) { snd_printk(KERN_ERR "tumbler: %i :cannot initialize the MCS\n", err); return err; diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c index f6bd0de..8d2f26d 100644 --- a/sound/usb/usx2y/usbusx2yaudio.c +++ b/sound/usb/usx2y/usbusx2yaudio.c @@ -322,7 +322,7 @@ static void i_usX2Y_urb_complete(struct usX2Y_error_urb_status(usX2Y, subs, urb); return; } - if (likely((0xFFFF & urb->start_frame) == usX2Y->wait_iso_frame)) + if (likely(urb->start_frame == usX2Y->wait_iso_frame)) subs->completed_urb = urb; else { usX2Y_error_sequence(usX2Y, subs, urb); @@ -335,13 +335,9 @@ static void i_usX2Y_urb_complete(struct atomic_read(&capsubs->state) >= state_PREPARED && (playbacksubs->completed_urb || atomic_read(&playbacksubs->state) < state_PREPARED)) { - if (!usX2Y_usbframe_complete(capsubs, playbacksubs, urb->start_frame)) { - if (nr_of_packs() <= urb->start_frame && - urb->start_frame <= (2 * nr_of_packs() - 1)) // uhci and ohci - usX2Y->wait_iso_frame = urb->start_frame - nr_of_packs(); - else - usX2Y->wait_iso_frame += nr_of_packs(); - } else { + if (!usX2Y_usbframe_complete(capsubs, playbacksubs, urb->start_frame)) + usX2Y->wait_iso_frame += nr_of_packs(); + else { snd_printdd("\n"); usX2Y_clients_stop(usX2Y); } @@ -495,7 +491,6 @@ static int usX2Y_urbs_start(struct snd_u if (subs != NULL && atomic_read(&subs->state) >= state_PREPARED) goto start; } - usX2Y->wait_iso_frame = -1; start: usX2Y_subs_startup(subs); @@ -516,10 +511,9 @@ static int usX2Y_urbs_start(struct snd_u snd_printk (KERN_ERR "cannot submit datapipe for urb %d, err = %d\n", i, err); err = -EPIPE; goto cleanup; - } else { - if (0 > usX2Y->wait_iso_frame) + } else + if (i == 0) usX2Y->wait_iso_frame = urb->start_frame; - } urb->transfer_flags = 0; } else { atomic_set(&subs->state, state_STARTING1); diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c index 88b72b5..3bda17d 100644 --- a/sound/usb/usx2y/usx2yhwdeppcm.c +++ b/sound/usb/usx2y/usx2yhwdeppcm.c @@ -243,7 +243,7 @@ static void i_usX2Y_usbpcm_urb_complete( usX2Y_error_urb_status(usX2Y, subs, urb); return; } - if (likely((0xFFFF & urb->start_frame) == usX2Y->wait_iso_frame)) + if (likely(urb->start_frame == usX2Y->wait_iso_frame)) subs->completed_urb = urb; else { usX2Y_error_sequence(usX2Y, subs, urb); @@ -256,13 +256,9 @@ static void i_usX2Y_usbpcm_urb_complete( if (capsubs->completed_urb && atomic_read(&capsubs->state) >= state_PREPARED && (NULL == capsubs2 || capsubs2->completed_urb) && (playbacksubs->completed_urb || atomic_read(&playbacksubs->state) < state_PREPARED)) { - if (!usX2Y_usbpcm_usbframe_complete(capsubs, capsubs2, playbacksubs, urb->start_frame)) { - if (nr_of_packs() <= urb->start_frame && - urb->start_frame <= (2 * nr_of_packs() - 1)) // uhci and ohci - usX2Y->wait_iso_frame = urb->start_frame - nr_of_packs(); - else - usX2Y->wait_iso_frame += nr_of_packs(); - } else { + if (!usX2Y_usbpcm_usbframe_complete(capsubs, capsubs2, playbacksubs, urb->start_frame)) + usX2Y->wait_iso_frame += nr_of_packs(); + else { snd_printdd("\n"); usX2Y_clients_stop(usX2Y); } @@ -433,7 +429,6 @@ static int usX2Y_usbpcm_urbs_start(struc if (subs != NULL && atomic_read(&subs->state) >= state_PREPARED) goto start; } - usX2Y->wait_iso_frame = -1; start: usX2Y_usbpcm_subs_startup(subs); @@ -459,7 +454,7 @@ static int usX2Y_usbpcm_urbs_start(struc goto cleanup; } else { snd_printdd("%i\n", urb->start_frame); - if (0 > usX2Y->wait_iso_frame) + if (u == 0) usX2Y->wait_iso_frame = urb->start_frame; } urb->transfer_flags = 0; @@ -632,7 +627,7 @@ static int usX2Y_pcms_lock_check(struct for (s = 0; s < 2; ++s) { struct snd_pcm_substream *substream; substream = pcm->streams[s].substream; - if (SUBSTREAM_BUSY(substream)) + if (substream && SUBSTREAM_BUSY(substream)) err = -EBUSY; } } - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/