diff --git a/Makefile b/Makefile index d970cb1..e5c5531 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 21 -EXTRAVERSION = +EXTRAVERSION = .4 NAME = Nocturnal Monster Puppy # *DOCUMENTATION* diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 2409560..7ed141f 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -273,6 +273,7 @@ asmlinkage void do_undefinstr(struct pt_regs *regs) struct undef_hook *hook; siginfo_t info; void __user *pc; + unsigned long flags; /* * According to the ARM ARM, PC is 2 or 4 bytes ahead, @@ -291,7 +292,7 @@ asmlinkage void do_undefinstr(struct pt_regs *regs) get_user(instr, (u32 __user *)pc); } - spin_lock_irq(&undef_lock); + spin_lock_irqsave(&undef_lock, flags); list_for_each_entry(hook, &undef_hook, node) { if ((instr & hook->instr_mask) == hook->instr_val && (regs->ARM_cpsr & hook->cpsr_mask) == hook->cpsr_val) { @@ -301,7 +302,7 @@ asmlinkage void do_undefinstr(struct pt_regs *regs) } } } - spin_unlock_irq(&undef_lock); + spin_unlock_irqrestore(&undef_lock, flags); #ifdef CONFIG_DEBUG_USER if (user_debug & UDBG_UNDEFINED) { diff --git a/arch/arm/mach-iop13xx/pci.c b/arch/arm/mach-iop13xx/pci.c index 89ec70e..d907a2a 100644 --- a/arch/arm/mach-iop13xx/pci.c +++ b/arch/arm/mach-iop13xx/pci.c @@ -1023,7 +1023,7 @@ int iop13xx_pci_setup(int nr, struct pci_sys_data *sys) << IOP13XX_ATUX_PCIXSR_FUNC_NUM; __raw_writel(pcixsr, IOP13XX_ATUX_PCIXSR); - res[0].start = IOP13XX_PCIX_LOWER_IO_PA; + res[0].start = IOP13XX_PCIX_LOWER_IO_PA + IOP13XX_PCIX_IO_BUS_OFFSET; res[0].end = IOP13XX_PCIX_UPPER_IO_PA; res[0].name = "IQ81340 ATUX PCI I/O Space"; res[0].flags = IORESOURCE_IO; @@ -1033,7 +1033,7 @@ int iop13xx_pci_setup(int nr, struct pci_sys_data *sys) res[1].name = "IQ81340 ATUX PCI Memory Space"; res[1].flags = IORESOURCE_MEM; sys->mem_offset = IOP13XX_PCIX_MEM_OFFSET; - sys->io_offset = IOP13XX_PCIX_IO_OFFSET; + sys->io_offset = IOP13XX_PCIX_LOWER_IO_PA; break; case IOP13XX_INIT_ATU_ATUE: /* Note: the function number field in the PCSR is ro */ @@ -1044,7 +1044,7 @@ int iop13xx_pci_setup(int nr, struct pci_sys_data *sys) __raw_writel(pcsr, IOP13XX_ATUE_PCSR); - res[0].start = IOP13XX_PCIE_LOWER_IO_PA; + res[0].start = IOP13XX_PCIE_LOWER_IO_PA + IOP13XX_PCIE_IO_BUS_OFFSET; res[0].end = IOP13XX_PCIE_UPPER_IO_PA; res[0].name = "IQ81340 ATUE PCI I/O Space"; res[0].flags = IORESOURCE_IO; @@ -1054,7 +1054,7 @@ int iop13xx_pci_setup(int nr, struct pci_sys_data *sys) res[1].name = "IQ81340 ATUE PCI Memory Space"; res[1].flags = IORESOURCE_MEM; sys->mem_offset = IOP13XX_PCIE_MEM_OFFSET; - sys->io_offset = IOP13XX_PCIE_IO_OFFSET; + sys->io_offset = IOP13XX_PCIE_LOWER_IO_PA; sys->map_irq = iop13xx_pcie_map_irq; break; default: diff --git a/arch/arm/plat-iop/time.c b/arch/arm/plat-iop/time.c index 16300ad..0cc26da 100644 --- a/arch/arm/plat-iop/time.c +++ b/arch/arm/plat-iop/time.c @@ -32,22 +32,22 @@ static unsigned long next_jiffy_time; unsigned long iop_gettimeoffset(void) { - unsigned long offset, temp1, temp2; + unsigned long offset, temp; /* enable cp6, if necessary, to avoid taking the overhead of an * undefined instruction trap */ asm volatile ( "mrc p15, 0, %0, c15, c1, 0\n\t" - "ands %1, %0, #(1 << 6)\n\t" + "tst %0, #(1 << 6)\n\t" "orreq %0, %0, #(1 << 6)\n\t" "mcreq p15, 0, %0, c15, c1, 0\n\t" -#ifdef CONFIG_XSCALE +#ifdef CONFIG_CPU_XSCALE "mrceq p15, 0, %0, c15, c1, 0\n\t" "moveq %0, %0\n\t" "subeq pc, pc, #4\n\t" #endif - : "=r"(temp1), "=r"(temp2) : : "cc"); + : "=r"(temp) : : "cc"); offset = next_jiffy_time - read_tcr1(); diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c index 837b041..ca3e1d3 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c @@ -341,15 +341,17 @@ static int powernow_acpi_init(void) pc.val = (unsigned long) acpi_processor_perf->states[0].control; for (i = 0; i < number_scales; i++) { u8 fid, vid; - unsigned int speed; + struct acpi_processor_px *state = + &acpi_processor_perf->states[i]; + unsigned int speed, speed_mhz; - pc.val = (unsigned long) acpi_processor_perf->states[i].control; + pc.val = (unsigned long) state->control; dprintk ("acpi: P%d: %d MHz %d mW %d uS control %08x SGTC %d\n", i, - (u32) acpi_processor_perf->states[i].core_frequency, - (u32) acpi_processor_perf->states[i].power, - (u32) acpi_processor_perf->states[i].transition_latency, - (u32) acpi_processor_perf->states[i].control, + (u32) state->core_frequency, + (u32) state->power, + (u32) state->transition_latency, + (u32) state->control, pc.bits.sgtc); vid = pc.bits.vid; @@ -360,6 +362,18 @@ static int powernow_acpi_init(void) powernow_table[i].index |= (vid << 8); /* upper 8 bits */ speed = powernow_table[i].frequency; + speed_mhz = speed / 1000; + + /* processor_perflib will multiply the MHz value by 1000 to + * get a KHz value (e.g. 1266000). However, powernow-k7 works + * with true KHz values (e.g. 1266768). To ensure that all + * powernow frequencies are available, we must ensure that + * ACPI doesn't restrict them, so we round up the MHz value + * to ensure that perflib's computed KHz value is greater than + * or equal to powernow's KHz value. + */ + if (speed % 1000 > 0) + speed_mhz++; if ((fid_codes[fid] % 10)==5) { if (have_a0 == 1) @@ -368,10 +382,16 @@ static int powernow_acpi_init(void) dprintk (" FID: 0x%x (%d.%dx [%dMHz]) " "VID: 0x%x (%d.%03dV)\n", fid, fid_codes[fid] / 10, - fid_codes[fid] % 10, speed/1000, vid, + fid_codes[fid] % 10, speed_mhz, vid, mobile_vid_table[vid]/1000, mobile_vid_table[vid]%1000); + if (state->core_frequency != speed_mhz) { + state->core_frequency = speed_mhz; + dprintk(" Corrected ACPI frequency to %d\n", + speed_mhz); + } + if (latency < pc.bits.sgtc) latency = pc.bits.sgtc; @@ -602,7 +622,7 @@ static int __init powernow_cpu_init (struct cpufreq_policy *policy) result = powernow_acpi_init(); if (result) { printk (KERN_INFO PFX "ACPI and legacy methods failed\n"); - printk (KERN_INFO PFX "See http://www.codemonkey.org.uk/projects/cpufreq/powernow-k7.shtml\n"); + printk (KERN_INFO PFX "See http://www.codemonkey.org.uk/projects/cpufreq/powernow-k7.html\n"); } } else { /* SGTC use the bus clock as timer */ diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c index fe3b670..e295d87 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c @@ -521,7 +521,7 @@ static int check_supported_cpu(unsigned int cpu) if ((eax & CPUID_XFAM) == CPUID_XFAM_K8) { if (((eax & CPUID_USE_XFAM_XMOD) != CPUID_USE_XFAM_XMOD) || - ((eax & CPUID_XMOD) > CPUID_XMOD_REV_G)) { + ((eax & CPUID_XMOD) > CPUID_XMOD_REV_MASK)) { printk(KERN_INFO PFX "Processor cpuid %x not supported\n", eax); goto out; } diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h index 0fb2a30..575541f 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h @@ -46,8 +46,8 @@ struct powernow_k8_data { #define CPUID_XFAM 0x0ff00000 /* extended family */ #define CPUID_XFAM_K8 0 #define CPUID_XMOD 0x000f0000 /* extended model */ -#define CPUID_XMOD_REV_G 0x00060000 -#define CPUID_XFAM_10H 0x00100000 /* family 0x10 */ +#define CPUID_XMOD_REV_MASK 0x00080000 +#define CPUID_XFAM_10H 0x00100000 /* family 0x10 */ #define CPUID_USE_XFAM_XMOD 0x00000f00 #define CPUID_GET_MAX_CAPABILITIES 0x80000000 #define CPUID_FREQ_VOLT_CAPABILITIES 0x80000007 diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c index fb9bf1e..f56569f 100644 --- a/arch/sparc64/kernel/of_device.c +++ b/arch/sparc64/kernel/of_device.c @@ -508,6 +508,13 @@ static int __init build_one_resource(struct device_node *parent, return 0; } + /* When we miss an I/O space match on PCI, just pass it up + * to the next PCI bridge and/or controller. + */ + if (!strcmp(bus->name, "pci") && + (addr[0] & 0x03000000) == 0x01000000) + return 0; + return 1; } diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c index 0917c24..3494adf 100644 --- a/arch/sparc64/kernel/prom.c +++ b/arch/sparc64/kernel/prom.c @@ -1555,10 +1555,21 @@ static struct device_node * __init create_node(phandle node, struct device_node static struct device_node * __init build_tree(struct device_node *parent, phandle node, struct device_node ***nextp) { + struct device_node *ret = NULL, *prev_sibling = NULL; struct device_node *dp; - dp = create_node(node, parent); - if (dp) { + while (1) { + dp = create_node(node, parent); + if (!dp) + break; + + if (prev_sibling) + prev_sibling->sibling = dp; + + if (!ret) + ret = dp; + prev_sibling = dp; + *(*nextp) = dp; *nextp = &dp->allnext; @@ -1567,10 +1578,10 @@ static struct device_node * __init build_tree(struct device_node *parent, phandl dp->child = build_tree(dp, prom_getchild(node), nextp); - dp->sibling = build_tree(parent, prom_getsibling(node), nextp); + node = prom_getsibling(node); } - return dp; + return ret; } void __init prom_build_devicetree(void) diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index fc99f7b..8ad7bdb 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c @@ -566,6 +566,9 @@ static void hypervisor_xcall_deliver(u64 data0, u64 data1, u64 data2, cpumask_t unsigned long flags, status; int cnt, retries, this_cpu, prev_sent, i; + if (cpus_empty(mask)) + return; + /* We have to do this whole thing with interrupts fully disabled. * Otherwise if we send an xcall from interrupt context it will * corrupt both our mondo block and cpu list state. diff --git a/arch/x86_64/kernel/vsyscall.c b/arch/x86_64/kernel/vsyscall.c index b43c698..fc9f042 100644 --- a/arch/x86_64/kernel/vsyscall.c +++ b/arch/x86_64/kernel/vsyscall.c @@ -132,7 +132,7 @@ static __always_inline void do_vgettimeofday(struct timeval * tv) /* convert to usecs and add to timespec: */ tv->tv_usec += nsec_delta / NSEC_PER_USEC; - while (tv->tv_usec > USEC_PER_SEC) { + while (tv->tv_usec >= USEC_PER_SEC) { tv->tv_sec += 1; tv->tv_usec -= USEC_PER_SEC; } diff --git a/crypto/api.c b/crypto/api.c index 55af8bb..33734fd 100644 --- a/crypto/api.c +++ b/crypto/api.c @@ -48,8 +48,10 @@ EXPORT_SYMBOL_GPL(crypto_mod_get); void crypto_mod_put(struct crypto_alg *alg) { + struct module *module = alg->cra_module; + crypto_alg_put(alg); - module_put(alg->cra_module); + module_put(module); } EXPORT_SYMBOL_GPL(crypto_mod_put); diff --git a/drivers/acpi/tables/tbfadt.c b/drivers/acpi/tables/tbfadt.c index 807c711..d341491 100644 --- a/drivers/acpi/tables/tbfadt.c +++ b/drivers/acpi/tables/tbfadt.c @@ -347,6 +347,20 @@ static void acpi_tb_convert_fadt(void) acpi_gbl_xpm1b_enable.space_id = acpi_gbl_FADT.xpm1a_event_block.space_id; } + /* + * _CST object and C States change notification start with + * ACPI 2.0 (FADT r3). Although the field should be Reserved + * and 0 before then, some pre-r3 FADT set this field and + * it results in SMM-related boot failures. For them, clear it. + */ + if ((acpi_gbl_FADT.header.revision < 3) && + (acpi_gbl_FADT.cst_control != 0)) { + ACPI_WARNING((AE_INFO, + "Ignoring BIOS FADT r%u C-state control", + acpi_gbl_FADT.header.revision)); + acpi_gbl_FADT.cst_control = 0; + } + } /****************************************************************************** diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 2ffcca0..4d63974 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -557,12 +557,30 @@ ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int int i, p = 0; void __iomem * const *iomap; + /* Discard disabled ports. Some controllers show their + unused channels this way */ + if (ata_resources_present(pdev, 0) == 0) + ports &= ~ATA_PORT_PRIMARY; + if (ata_resources_present(pdev, 1) == 0) + ports &= ~ATA_PORT_SECONDARY; + /* iomap BARs */ - for (i = 0; i < 4; i++) { - if (pcim_iomap(pdev, i, 0) == NULL) { - dev_printk(KERN_ERR, &pdev->dev, - "failed to iomap PCI BAR %d\n", i); - return NULL; + if (ports & ATA_PORT_PRIMARY) { + for (i = 0; i <= 1; i++) { + if (pcim_iomap(pdev, i, 0) == NULL) { + dev_printk(KERN_ERR, &pdev->dev, + "failed to iomap PCI BAR %d\n", i); + return NULL; + } + } + } + if (ports & ATA_PORT_SECONDARY) { + for (i = 2; i <= 3; i++) { + if (pcim_iomap(pdev, i, 0) == NULL) { + dev_printk(KERN_ERR, &pdev->dev, + "failed to iomap PCI BAR %d\n", i); + return NULL; + } } } @@ -577,13 +595,6 @@ ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int probe_ent->irq = pdev->irq; probe_ent->irq_flags = IRQF_SHARED; - /* Discard disabled ports. Some controllers show their - unused channels this way */ - if (ata_resources_present(pdev, 0) == 0) - ports &= ~ATA_PORT_PRIMARY; - if (ata_resources_present(pdev, 1) == 0) - ports &= ~ATA_PORT_SECONDARY; - if (ports & ATA_PORT_PRIMARY) { probe_ent->port[p].cmd_addr = iomap[0]; probe_ent->port[p].altstatus_addr = diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c index 598e6a2..ea6efca 100644 --- a/drivers/ata/sata_via.c +++ b/drivers/ata/sata_via.c @@ -97,6 +97,10 @@ static struct pci_driver svia_pci_driver = { .name = DRV_NAME, .id_table = svia_pci_tbl, .probe = svia_init_one, +#ifdef CONFIG_PM + .suspend = ata_pci_device_suspend, + .resume = ata_pci_device_resume, +#endif .remove = ata_pci_remove_one, }; @@ -116,6 +120,10 @@ static struct scsi_host_template svia_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, +#ifdef CONFIG_PM + .suspend = ata_scsi_device_suspend, + .resume = ata_scsi_device_resume, +#endif }; static const struct ata_port_operations vt6420_sata_ops = { diff --git a/drivers/base/core.c b/drivers/base/core.c index d7fcf82..a8dfee2 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -93,6 +93,9 @@ static void device_release(struct kobject * kobj) { struct device * dev = to_dev(kobj); + kfree(dev->devt_attr); + dev->devt_attr = NULL; + if (dev->release) dev->release(dev); else if (dev->type && dev->type->release) @@ -765,10 +768,8 @@ void device_del(struct device * dev) if (parent) klist_del(&dev->knode_parent); - if (dev->devt_attr) { + if (dev->devt_attr) device_remove_file(dev, dev->devt_attr); - kfree(dev->devt_attr); - } if (dev->class) { sysfs_remove_link(&dev->kobj, "subsystem"); /* If this is not a "fake" compatible device, remove the diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index e221465..cc13ebc 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -1859,10 +1859,10 @@ static __devinit int try_init_acpi(struct SPMITable *spmi) if (spmi->addr.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { info->io_setup = mem_setup; - info->io.addr_type = IPMI_IO_ADDR_SPACE; + info->io.addr_type = IPMI_MEM_ADDR_SPACE; } else if (spmi->addr.space_id == ACPI_ADR_SPACE_SYSTEM_IO) { info->io_setup = port_setup; - info->io.addr_type = IPMI_MEM_ADDR_SPACE; + info->io.addr_type = IPMI_IO_ADDR_SPACE; } else { kfree(info); printk("ipmi_si: Unknown ACPI I/O Address type\n"); diff --git a/drivers/char/random.c b/drivers/char/random.c index b9dc7aa..fa5b95b 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -760,7 +760,7 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min, static void extract_buf(struct entropy_store *r, __u8 *out) { - int i, x; + int i; __u32 data[16], buf[5 + SHA_WORKSPACE_WORDS]; sha_init(buf); @@ -772,9 +772,11 @@ static void extract_buf(struct entropy_store *r, __u8 *out) * attempts to find previous ouputs), unless the hash * function can be inverted. */ - for (i = 0, x = 0; i < r->poolinfo->poolwords; i += 16, x+=2) { - sha_transform(buf, (__u8 *)r->pool+i, buf + 5); - add_entropy_words(r, &buf[x % 5], 1); + for (i = 0; i < r->poolinfo->poolwords; i += 16) { + /* hash blocks of 16 words = 512 bits */ + sha_transform(buf, (__u8 *)(r->pool + i), buf + 5); + /* feed back portion of the resulting hash */ + add_entropy_words(r, &buf[i % 5], 1); } /* @@ -782,7 +784,7 @@ static void extract_buf(struct entropy_store *r, __u8 *out) * portion of the pool while mixing, and hash one * final time. */ - __add_entropy_words(r, &buf[x % 5], 1, data); + __add_entropy_words(r, &buf[i % 5], 1, data); sha_transform(buf, (__u8 *)data, buf + 5); /* @@ -1022,37 +1024,44 @@ random_poll(struct file *file, poll_table * wait) return mask; } -static ssize_t -random_write(struct file * file, const char __user * buffer, - size_t count, loff_t *ppos) +static int +write_pool(struct entropy_store *r, const char __user *buffer, size_t count) { - int ret = 0; size_t bytes; __u32 buf[16]; const char __user *p = buffer; - size_t c = count; - while (c > 0) { - bytes = min(c, sizeof(buf)); + while (count > 0) { + bytes = min(count, sizeof(buf)); + if (copy_from_user(&buf, p, bytes)) + return -EFAULT; - bytes -= copy_from_user(&buf, p, bytes); - if (!bytes) { - ret = -EFAULT; - break; - } - c -= bytes; + count -= bytes; p += bytes; - add_entropy_words(&input_pool, buf, (bytes + 3) / 4); - } - if (p == buffer) { - return (ssize_t)ret; - } else { - struct inode *inode = file->f_path.dentry->d_inode; - inode->i_mtime = current_fs_time(inode->i_sb); - mark_inode_dirty(inode); - return (ssize_t)(p - buffer); + add_entropy_words(r, buf, (bytes + 3) / 4); } + + return 0; +} + +static ssize_t +random_write(struct file * file, const char __user * buffer, + size_t count, loff_t *ppos) +{ + size_t ret; + struct inode *inode = file->f_path.dentry->d_inode; + + ret = write_pool(&blocking_pool, buffer, count); + if (ret) + return ret; + ret = write_pool(&nonblocking_pool, buffer, count); + if (ret) + return ret; + + inode->i_mtime = current_fs_time(inode->i_sb); + mark_inode_dirty(inode); + return (ssize_t)count; } static int @@ -1091,8 +1100,8 @@ random_ioctl(struct inode * inode, struct file * file, return -EINVAL; if (get_user(size, p++)) return -EFAULT; - retval = random_write(file, (const char __user *) p, - size, &file->f_pos); + retval = write_pool(&input_pool, (const char __user *)p, + size); if (retval < 0) return retval; credit_entropy_store(&input_pool, ent_count); diff --git a/drivers/crypto/geode-aes.c b/drivers/crypto/geode-aes.c index 6d3840e..6a86958 100644 --- a/drivers/crypto/geode-aes.c +++ b/drivers/crypto/geode-aes.c @@ -102,10 +102,15 @@ geode_aes_crypt(struct geode_aes_op *op) u32 flags = 0; unsigned long iflags; - if (op->len == 0 || op->src == op->dst) + if (op->len == 0) return 0; - if (op->flags & AES_FLAGS_COHERENT) + /* If the source and destination is the same, then + * we need to turn on the coherent flags, otherwise + * we don't need to worry + */ + + if (op->src == op->dst) flags |= (AES_CTRL_DCA | AES_CTRL_SCA); if (op->dir == AES_DIR_ENCRYPT) @@ -120,7 +125,7 @@ geode_aes_crypt(struct geode_aes_op *op) _writefield(AES_WRITEIV0_REG, op->iv); } - if (op->flags & AES_FLAGS_USRKEY) { + if (!(op->flags & AES_FLAGS_HIDDENKEY)) { flags |= AES_CTRL_WRKEY; _writefield(AES_WRITEKEY0_REG, op->key); } @@ -289,6 +294,7 @@ static struct crypto_alg geode_cbc_alg = { .setkey = geode_setkey, .encrypt = geode_cbc_encrypt, .decrypt = geode_cbc_decrypt, + .ivsize = AES_IV_LENGTH, } } }; diff --git a/drivers/crypto/geode-aes.h b/drivers/crypto/geode-aes.h index 8003a36..f479686 100644 --- a/drivers/crypto/geode-aes.h +++ b/drivers/crypto/geode-aes.h @@ -20,8 +20,7 @@ #define AES_DIR_DECRYPT 0 #define AES_DIR_ENCRYPT 1 -#define AES_FLAGS_USRKEY (1 << 0) -#define AES_FLAGS_COHERENT (1 << 1) +#define AES_FLAGS_HIDDENKEY (1 << 0) struct geode_aes_op { diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 97ee870..3a95cc5 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -271,21 +271,25 @@ static int raid1_end_read_request(struct bio *bio, unsigned int bytes_done, int */ update_head_pos(mirror, r1_bio); - if (uptodate || (conf->raid_disks - conf->mddev->degraded) <= 1) { - /* - * Set R1BIO_Uptodate in our master bio, so that - * we will return a good error code for to the higher - * levels even if IO on some other mirrored buffer fails. - * - * The 'master' represents the composite IO operation to - * user-side. So if something waits for IO, then it will - * wait for the 'master' bio. + if (uptodate) + set_bit(R1BIO_Uptodate, &r1_bio->state); + else { + /* If all other devices have failed, we want to return + * the error upwards rather than fail the last device. + * Here we redefine "uptodate" to mean "Don't want to retry" */ - if (uptodate) - set_bit(R1BIO_Uptodate, &r1_bio->state); + unsigned long flags; + spin_lock_irqsave(&conf->device_lock, flags); + if (r1_bio->mddev->degraded == conf->raid_disks || + (r1_bio->mddev->degraded == conf->raid_disks-1 && + !test_bit(Faulty, &conf->mirrors[mirror].rdev->flags))) + uptodate = 1; + spin_unlock_irqrestore(&conf->device_lock, flags); + } + if (uptodate) raid_end_bio_io(r1_bio); - } else { + else { /* * oops, read error: */ @@ -992,13 +996,14 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev) unsigned long flags; spin_lock_irqsave(&conf->device_lock, flags); mddev->degraded++; + set_bit(Faulty, &rdev->flags); spin_unlock_irqrestore(&conf->device_lock, flags); /* * if recovery is running, make sure it aborts. */ set_bit(MD_RECOVERY_ERR, &mddev->recovery); - } - set_bit(Faulty, &rdev->flags); + } else + set_bit(Faulty, &rdev->flags); set_bit(MD_CHANGE_DEVS, &mddev->flags); printk(KERN_ALERT "raid1: Disk failure on %s, disabling device. \n" " Operation continuing on %d devices\n", diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index 85f21b5..2eb5741 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c @@ -726,13 +726,15 @@ static int mptspi_slave_configure(struct scsi_device *sdev) struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)sdev->host->hostdata; VirtTarget *vtarget = scsi_target(sdev)->hostdata; - int ret = mptscsih_slave_configure(sdev); + int ret; + + mptspi_initTarget(hd, vtarget, sdev); + + ret = mptscsih_slave_configure(sdev); if (ret) return ret; - mptspi_initTarget(hd, vtarget, sdev); - ddvprintk((MYIOC_s_INFO_FMT "id=%d min_period=0x%02x" " max_offset=0x%02x max_width=%d\n", hd->ioc->name, sdev->id, spi_min_period(scsi_target(sdev)), diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index a3d46ea..32a3003 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2929,11 +2929,6 @@ endif #NETDEVICES config NETPOLL def_bool NETCONSOLE -config NETPOLL_RX - bool "Netpoll support for trapping incoming packets" - default n - depends on NETPOLL - config NETPOLL_TRAP bool "Netpoll traffic trapping" default n diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index e85f5ec..5006c67 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -54,8 +54,8 @@ #define DRV_MODULE_NAME "bnx2" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "1.5.8" -#define DRV_MODULE_RELDATE "April 24, 2007" +#define DRV_MODULE_VERSION "1.5.8.1" +#define DRV_MODULE_RELDATE "May 7, 2007" #define RUN_AT(x) (jiffies + (x)) @@ -4510,8 +4510,7 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) vlan_tag_flags |= (TX_BD_FLAGS_VLAN_TAG | (vlan_tx_tag_get(skb) << 16)); } - if ((mss = skb_shinfo(skb)->gso_size) && - (skb->len > (bp->dev->mtu + ETH_HLEN))) { + if ((mss = skb_shinfo(skb)->gso_size)) { u32 tcp_opt_len, ip_tcp_len; if (skb_header_cloned(skb) && @@ -5565,6 +5564,9 @@ bnx2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) case SIOCGMIIREG: { u32 mii_regval; + if (!netif_running(dev)) + return -EAGAIN; + spin_lock_bh(&bp->phy_lock); err = bnx2_read_phy(bp, data->reg_num & 0x1f, &mii_regval); spin_unlock_bh(&bp->phy_lock); @@ -5578,6 +5580,9 @@ bnx2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) if (!capable(CAP_NET_ADMIN)) return -EPERM; + if (!netif_running(dev)) + return -EAGAIN; + spin_lock_bh(&bp->phy_lock); err = bnx2_write_phy(bp, data->reg_num & 0x1f, data->val_in); spin_unlock_bh(&bp->phy_lock); @@ -6143,6 +6148,7 @@ bnx2_suspend(struct pci_dev *pdev, pm_message_t state) reset_code = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL; bnx2_reset_chip(bp, reset_code); bnx2_free_skbs(bp); + pci_save_state(pdev); bnx2_set_power_state(bp, pci_choose_state(pdev, state)); return 0; } @@ -6156,6 +6162,7 @@ bnx2_resume(struct pci_dev *pdev) if (!netif_running(dev)) return 0; + pci_restore_state(pdev); bnx2_set_power_state(bp, PCI_D0); netif_device_attach(dev); bnx2_init_nic(bp); diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c index b2a3b19..ce547af 100644 --- a/drivers/net/sis900.c +++ b/drivers/net/sis900.c @@ -1754,6 +1754,7 @@ static int sis900_rx(struct net_device *net_dev) sis_priv->rx_ring[entry].cmdsts = RX_BUF_SIZE; } else { struct sk_buff * skb; + struct sk_buff * rx_skb; pci_unmap_single(sis_priv->pci_dev, sis_priv->rx_ring[entry].bufptr, RX_BUF_SIZE, @@ -1787,10 +1788,10 @@ static int sis900_rx(struct net_device *net_dev) } /* give the socket buffer to upper layers */ - skb = sis_priv->rx_skbuff[entry]; - skb_put(skb, rx_size); - skb->protocol = eth_type_trans(skb, net_dev); - netif_rx(skb); + rx_skb = sis_priv->rx_skbuff[entry]; + skb_put(rx_skb, rx_size); + rx_skb->protocol = eth_type_trans(rx_skb, net_dev); + netif_rx(rx_skb); /* some network statistics */ if ((rx_status & BCAST) == MCAST) diff --git a/drivers/net/skge.c b/drivers/net/skge.c index d476a3c..5ef9023 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -135,10 +135,13 @@ static void skge_get_regs(struct net_device *dev, struct ethtool_regs *regs, /* Wake on Lan only supported on Yukon chips with rev 1 or above */ static u32 wol_supported(const struct skge_hw *hw) { - if (hw->chip_id == CHIP_ID_YUKON && hw->chip_rev != 0) - return WAKE_MAGIC | WAKE_PHY; - else + if (hw->chip_id == CHIP_ID_GENESIS) + return 0; + + if (hw->chip_id == CHIP_ID_YUKON && hw->chip_rev == 0) return 0; + + return WAKE_MAGIC | WAKE_PHY; } static u32 pci_wake_enabled(struct pci_dev *dev) @@ -3583,7 +3586,9 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port, skge->duplex = -1; skge->speed = -1; skge->advertising = skge_supported_modes(hw); - skge->wol = pci_wake_enabled(hw->pdev) ? wol_supported(hw) : 0; + + if (pci_wake_enabled(hw->pdev)) + skge->wol = wol_supported(hw) & WAKE_MAGIC; hw->dev[port] = dev; @@ -3789,6 +3794,9 @@ static int skge_suspend(struct pci_dev *pdev, pm_message_t state) struct skge_hw *hw = pci_get_drvdata(pdev); int i, err, wol = 0; + if (!hw) + return 0; + err = pci_save_state(pdev); if (err) return err; @@ -3817,6 +3825,9 @@ static int skge_resume(struct pci_dev *pdev) struct skge_hw *hw = pci_get_drvdata(pdev); int i, err; + if (!hw) + return 0; + err = pci_set_power_state(pdev, PCI_D0); if (err) goto out; @@ -3855,6 +3866,9 @@ static void skge_shutdown(struct pci_dev *pdev) struct skge_hw *hw = pci_get_drvdata(pdev); int i, wol = 0; + if (!hw) + return; + for (i = 0; i < hw->ports; i++) { struct net_device *dev = hw->dev[i]; struct skge_port *skge = netdev_priv(dev); diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index ac36152..b6b444b 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -123,16 +123,13 @@ static const struct pci_device_id sky2_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4361) }, /* 88E8050 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4362) }, /* 88E8053 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4363) }, /* 88E8055 */ -#ifdef broken - /* This device causes data corruption problems that are not resolved */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4364) }, /* 88E8056 */ -#endif { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4366) }, /* 88EC036 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4367) }, /* 88EC032 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4368) }, /* 88EC034 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4369) }, /* 88EC042 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436A) }, /* 88E8058 */ - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436B) }, /* 88E8071 */ +// { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436B) }, /* 88E8071 */ { 0 } }; @@ -3722,6 +3719,7 @@ err_out_free_regions: pci_release_regions(pdev); pci_disable_device(pdev); err_out: + pci_set_drvdata(pdev, NULL); return err; } @@ -3774,6 +3772,9 @@ static int sky2_suspend(struct pci_dev *pdev, pm_message_t state) struct sky2_hw *hw = pci_get_drvdata(pdev); int i, wol = 0; + if (!hw) + return 0; + del_timer_sync(&hw->idle_timer); netif_poll_disable(hw->dev[0]); @@ -3805,6 +3806,9 @@ static int sky2_resume(struct pci_dev *pdev) struct sky2_hw *hw = pci_get_drvdata(pdev); int i, err; + if (!hw) + return 0; + err = pci_set_power_state(pdev, PCI_D0); if (err) goto out; @@ -3851,6 +3855,9 @@ static void sky2_shutdown(struct pci_dev *pdev) struct sky2_hw *hw = pci_get_drvdata(pdev); int i, wol = 0; + if (!hw) + return; + del_timer_sync(&hw->idle_timer); netif_poll_disable(hw->dev[0]); diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index c956141..0b89812 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -499,7 +499,7 @@ static inline void smc911x_rcv(struct net_device *dev) SMC_SET_RX_CFG(RX_CFG_RX_END_ALGN4_ | ((2<<8) & RX_CFG_RXDOFF_)); SMC_PULL_DATA(data, pkt_len+2+3); - DBG(SMC_DEBUG_PKTS, "%s: Received packet\n", dev->name,); + DBG(SMC_DEBUG_PKTS, "%s: Received packet\n", dev->name); PRINT_PKT(data, ((pkt_len - 4) <= 64) ? pkt_len - 4 : 64); dev->last_rx = jiffies; skb->dev = dev; diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 256969e..3d20115 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -64,8 +64,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.75" -#define DRV_MODULE_RELDATE "March 23, 2007" +#define DRV_MODULE_VERSION "3.75.1" +#define DRV_MODULE_RELDATE "May 7, 2007" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -3895,8 +3895,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) entry = tp->tx_prod; base_flags = 0; mss = 0; - if (skb->len > (tp->dev->mtu + ETH_HLEN) && - (mss = skb_shinfo(skb)->gso_size) != 0) { + if ((mss = skb_shinfo(skb)->gso_size) != 0) { int tcp_opt_len, ip_tcp_len; if (skb_header_cloned(skb) && @@ -4053,8 +4052,7 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev) if (skb->ip_summed == CHECKSUM_PARTIAL) base_flags |= TXD_FLAG_TCPUDP_CSUM; mss = 0; - if (skb->len > (tp->dev->mtu + ETH_HLEN) && - (mss = skb_shinfo(skb)->gso_size) != 0) { + if ((mss = skb_shinfo(skb)->gso_size) != 0) { int tcp_opt_len, ip_tcp_len, hdr_len; if (skb_header_cloned(skb) && @@ -5936,7 +5934,7 @@ static int tg3_load_tso_firmware(struct tg3 *tp) /* tp->lock is held. */ -static void __tg3_set_mac_addr(struct tg3 *tp) +static void __tg3_set_mac_addr(struct tg3 *tp, int skip_mac_1) { u32 addr_high, addr_low; int i; @@ -5948,6 +5946,8 @@ static void __tg3_set_mac_addr(struct tg3 *tp) (tp->dev->dev_addr[4] << 8) | (tp->dev->dev_addr[5] << 0)); for (i = 0; i < 4; i++) { + if (i == 1 && skip_mac_1) + continue; tw32(MAC_ADDR_0_HIGH + (i * 8), addr_high); tw32(MAC_ADDR_0_LOW + (i * 8), addr_low); } @@ -5974,7 +5974,7 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p) { struct tg3 *tp = netdev_priv(dev); struct sockaddr *addr = p; - int err = 0; + int err = 0, skip_mac_1 = 0; if (!is_valid_ether_addr(addr->sa_data)) return -EINVAL; @@ -5985,22 +5985,21 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p) return 0; if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) { - /* Reset chip so that ASF can re-init any MAC addresses it - * needs. - */ - tg3_netif_stop(tp); - tg3_full_lock(tp, 1); + u32 addr0_high, addr0_low, addr1_high, addr1_low; - tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); - err = tg3_restart_hw(tp, 0); - if (!err) - tg3_netif_start(tp); - tg3_full_unlock(tp); - } else { - spin_lock_bh(&tp->lock); - __tg3_set_mac_addr(tp); - spin_unlock_bh(&tp->lock); + addr0_high = tr32(MAC_ADDR_0_HIGH); + addr0_low = tr32(MAC_ADDR_0_LOW); + addr1_high = tr32(MAC_ADDR_1_HIGH); + addr1_low = tr32(MAC_ADDR_1_LOW); + + /* Skip MAC addr 1 if ASF is using it. */ + if ((addr0_high != addr1_high || addr0_low != addr1_low) && + !(addr1_high == 0 && addr1_low == 0)) + skip_mac_1 = 1; } + spin_lock_bh(&tp->lock); + __tg3_set_mac_addr(tp, skip_mac_1); + spin_unlock_bh(&tp->lock); return err; } @@ -6317,7 +6316,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tp->rx_jumbo_ptr); /* Initialize MAC address and backoff seed. */ - __tg3_set_mac_addr(tp); + __tg3_set_mac_addr(tp, 0); /* MTU + ethernet header + FCS + optional VLAN tag */ tw32(MAC_RX_MTU_SIZE, tp->dev->mtu + ETH_HLEN + 8); @@ -6348,8 +6347,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) || (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)) { if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE && - (tp->pci_chip_rev_id == CHIPREV_ID_5705_A1 || - tp->pci_chip_rev_id == CHIPREV_ID_5705_A2)) { + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { rdmac_mode |= RDMAC_MODE_FIFO_SIZE_128; } else if (!(tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH) && !(tp->tg3_flags2 & TG3_FLG2_IS_5788)) { diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 65d6f23..5af9125 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -1737,18 +1737,20 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE, quirk_nvidia_ck804_pcie_aer_ext_cap); #ifdef CONFIG_PCI_MSI -/* The Serverworks PCI-X chipset does not support MSI. We cannot easily rely - * on setting PCI_BUS_FLAGS_NO_MSI in its bus flags because there are actually - * some other busses controlled by the chipset even if Linux is not aware of it. - * Instead of setting the flag on all busses in the machine, simply disable MSI - * globally. +/* Some chipsets do not support MSI. We cannot easily rely on setting + * PCI_BUS_FLAGS_NO_MSI in its bus flags because there are actually + * some other busses controlled by the chipset even if Linux is not + * aware of it. Instead of setting the flag on all busses in the + * machine, simply disable MSI globally. */ -static void __init quirk_svw_msi(struct pci_dev *dev) +static void __init quirk_disable_all_msi(struct pci_dev *dev) { pci_no_msi(); printk(KERN_WARNING "PCI: MSI quirk detected. MSI deactivated.\n"); } -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_GCNB_LE, quirk_svw_msi); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_GCNB_LE, quirk_disable_all_msi); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS400_200, quirk_disable_all_msi); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS480, quirk_disable_all_msi); /* Disable MSI on chipsets that are known to not support it */ static void __devinit quirk_disable_msi(struct pci_dev *dev) diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c index 40d4856..c3a6bd2 100644 --- a/drivers/serial/sunhv.c +++ b/drivers/serial/sunhv.c @@ -493,6 +493,10 @@ static struct of_device_id hv_match[] = { .name = "console", .compatible = "qcn", }, + { + .name = "console", + .compatible = "SUNW,sun4v-console", + }, {}, }; MODULE_DEVICE_TABLE(of, hv_match); diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c index 3dfa3e4..3257d94 100644 --- a/drivers/usb/atm/cxacru.c +++ b/drivers/usb/atm/cxacru.c @@ -146,6 +146,12 @@ enum cxacru_info_idx { CXINF_MAX = 0x1c, }; +enum poll_state { + CX_INIT, + CX_POLLING, + CX_ABORT +}; + struct cxacru_modem_type { u32 pll_f_clk; u32 pll_b_clk; @@ -159,6 +165,8 @@ struct cxacru_data { int line_status; struct delayed_work poll_work; + struct mutex poll_state_serialize; + enum poll_state poll_state; /* contol handles */ struct mutex cm_serialize; @@ -356,7 +364,7 @@ static int cxacru_atm_start(struct usbatm_data *usbatm_instance, /* struct atm_dev *atm_dev = usbatm_instance->atm_dev; */ - int ret; + int ret, start_polling = 1; dbg("cxacru_atm_start"); @@ -376,7 +384,15 @@ static int cxacru_atm_start(struct usbatm_data *usbatm_instance, } /* Start status polling */ - cxacru_poll_status(&instance->poll_work.work); + mutex_lock(&instance->poll_state_serialize); + if (instance->poll_state == CX_INIT) + instance->poll_state = CX_POLLING; + else /* poll_state == CX_ABORT */ + start_polling = 0; + mutex_unlock(&instance->poll_state_serialize); + + if (start_polling) + cxacru_poll_status(&instance->poll_work.work); return 0; } @@ -685,6 +701,9 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance, instance->usbatm = usbatm_instance; instance->modem_type = (struct cxacru_modem_type *) id->driver_info; + mutex_init(&instance->poll_state_serialize); + instance->poll_state = CX_INIT; + instance->rcv_buf = (u8 *) __get_free_page(GFP_KERNEL); if (!instance->rcv_buf) { dbg("cxacru_bind: no memory for rcv_buf"); @@ -744,6 +763,7 @@ static void cxacru_unbind(struct usbatm_data *usbatm_instance, struct usb_interface *intf) { struct cxacru_data *instance = usbatm_instance->driver_data; + int stop_polling = 1; dbg("cxacru_unbind entered"); @@ -752,8 +772,20 @@ static void cxacru_unbind(struct usbatm_data *usbatm_instance, return; } - while (!cancel_delayed_work(&instance->poll_work)) - flush_scheduled_work(); + mutex_lock(&instance->poll_state_serialize); + if (instance->poll_state != CX_POLLING) { + /* Polling hasn't started yet and with + * the mutex locked it can be prevented + * from starting. + */ + instance->poll_state = CX_ABORT; + stop_polling = 0; + } + mutex_unlock(&instance->poll_state_serialize); + + if (stop_polling) + while (!cancel_delayed_work(&instance->poll_work)) + flush_scheduled_work(); usb_kill_urb(instance->snd_urb); usb_kill_urb(instance->rcv_urb); diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c index a8b3d66..488d61b 100644 --- a/drivers/usb/input/hiddev.c +++ b/drivers/usb/input/hiddev.c @@ -51,6 +51,7 @@ struct hiddev { wait_queue_head_t wait; struct hid_device *hid; struct list_head list; + spinlock_t list_lock; }; struct hiddev_list { @@ -161,7 +162,9 @@ static void hiddev_send_event(struct hid_device *hid, { struct hiddev *hiddev = hid->hiddev; struct hiddev_list *list; + unsigned long flags; + spin_lock_irqsave(&hiddev->list_lock, flags); list_for_each_entry(list, &hiddev->list, node) { if (uref->field_index != HID_FIELD_INDEX_NONE || (list->flags & HIDDEV_FLAG_REPORT) != 0) { @@ -171,6 +174,7 @@ static void hiddev_send_event(struct hid_device *hid, kill_fasync(&list->fasync, SIGIO, POLL_IN); } } + spin_unlock_irqrestore(&hiddev->list_lock, flags); wake_up_interruptible(&hiddev->wait); } @@ -235,9 +239,13 @@ static int hiddev_fasync(int fd, struct file *file, int on) static int hiddev_release(struct inode * inode, struct file * file) { struct hiddev_list *list = file->private_data; + unsigned long flags; hiddev_fasync(-1, file, 0); + + spin_lock_irqsave(&list->hiddev->list_lock, flags); list_del(&list->node); + spin_unlock_irqrestore(&list->hiddev->list_lock, flags); if (!--list->hiddev->open) { if (list->hiddev->exist) @@ -257,6 +265,7 @@ static int hiddev_release(struct inode * inode, struct file * file) static int hiddev_open(struct inode *inode, struct file *file) { struct hiddev_list *list; + unsigned long flags; int i = iminor(inode) - HIDDEV_MINOR_BASE; @@ -267,7 +276,11 @@ static int hiddev_open(struct inode *inode, struct file *file) return -ENOMEM; list->hiddev = hiddev_table[i]; + + spin_lock_irqsave(&list->hiddev->list_lock, flags); list_add_tail(&list->node, &hiddev_table[i]->list); + spin_unlock_irqrestore(&list->hiddev->list_lock, flags); + file->private_data = list; if (!list->hiddev->open++) @@ -773,6 +786,7 @@ int hiddev_connect(struct hid_device *hid) init_waitqueue_head(&hiddev->wait); INIT_LIST_HEAD(&hiddev->list); + spin_lock_init(&hiddev->list_lock); hiddev->hid = hid; hiddev->exist = 1; diff --git a/fs/fat/dir.c b/fs/fat/dir.c index c16af24..ccf161d 100644 --- a/fs/fat/dir.c +++ b/fs/fat/dir.c @@ -422,7 +422,7 @@ EODir: EXPORT_SYMBOL_GPL(fat_search_long); struct fat_ioctl_filldir_callback { - struct dirent __user *dirent; + void __user *dirent; int result; /* for dir ioctl */ const char *longname; @@ -647,62 +647,85 @@ static int fat_readdir(struct file *filp, void *dirent, filldir_t filldir) return __fat_readdir(inode, filp, dirent, filldir, 0, 0); } -static int fat_ioctl_filldir(void *__buf, const char *name, int name_len, - loff_t offset, u64 ino, unsigned int d_type) +#define FAT_IOCTL_FILLDIR_FUNC(func, dirent_type) \ +static int func(void *__buf, const char *name, int name_len, \ + loff_t offset, u64 ino, unsigned int d_type) \ +{ \ + struct fat_ioctl_filldir_callback *buf = __buf; \ + struct dirent_type __user *d1 = buf->dirent; \ + struct dirent_type __user *d2 = d1 + 1; \ + \ + if (buf->result) \ + return -EINVAL; \ + buf->result++; \ + \ + if (name != NULL) { \ + /* dirent has only short name */ \ + if (name_len >= sizeof(d1->d_name)) \ + name_len = sizeof(d1->d_name) - 1; \ + \ + if (put_user(0, d2->d_name) || \ + put_user(0, &d2->d_reclen) || \ + copy_to_user(d1->d_name, name, name_len) || \ + put_user(0, d1->d_name + name_len) || \ + put_user(name_len, &d1->d_reclen)) \ + goto efault; \ + } else { \ + /* dirent has short and long name */ \ + const char *longname = buf->longname; \ + int long_len = buf->long_len; \ + const char *shortname = buf->shortname; \ + int short_len = buf->short_len; \ + \ + if (long_len >= sizeof(d1->d_name)) \ + long_len = sizeof(d1->d_name) - 1; \ + if (short_len >= sizeof(d1->d_name)) \ + short_len = sizeof(d1->d_name) - 1; \ + \ + if (copy_to_user(d2->d_name, longname, long_len) || \ + put_user(0, d2->d_name + long_len) || \ + put_user(long_len, &d2->d_reclen) || \ + put_user(ino, &d2->d_ino) || \ + put_user(offset, &d2->d_off) || \ + copy_to_user(d1->d_name, shortname, short_len) || \ + put_user(0, d1->d_name + short_len) || \ + put_user(short_len, &d1->d_reclen)) \ + goto efault; \ + } \ + return 0; \ +efault: \ + buf->result = -EFAULT; \ + return -EFAULT; \ +} + +FAT_IOCTL_FILLDIR_FUNC(fat_ioctl_filldir, dirent) + +static int fat_ioctl_readdir(struct inode *inode, struct file *filp, + void __user *dirent, filldir_t filldir, + int short_only, int both) { - struct fat_ioctl_filldir_callback *buf = __buf; - struct dirent __user *d1 = buf->dirent; - struct dirent __user *d2 = d1 + 1; - - if (buf->result) - return -EINVAL; - buf->result++; - - if (name != NULL) { - /* dirent has only short name */ - if (name_len >= sizeof(d1->d_name)) - name_len = sizeof(d1->d_name) - 1; - - if (put_user(0, d2->d_name) || - put_user(0, &d2->d_reclen) || - copy_to_user(d1->d_name, name, name_len) || - put_user(0, d1->d_name + name_len) || - put_user(name_len, &d1->d_reclen)) - goto efault; - } else { - /* dirent has short and long name */ - const char *longname = buf->longname; - int long_len = buf->long_len; - const char *shortname = buf->shortname; - int short_len = buf->short_len; - - if (long_len >= sizeof(d1->d_name)) - long_len = sizeof(d1->d_name) - 1; - if (short_len >= sizeof(d1->d_name)) - short_len = sizeof(d1->d_name) - 1; - - if (copy_to_user(d2->d_name, longname, long_len) || - put_user(0, d2->d_name + long_len) || - put_user(long_len, &d2->d_reclen) || - put_user(ino, &d2->d_ino) || - put_user(offset, &d2->d_off) || - copy_to_user(d1->d_name, shortname, short_len) || - put_user(0, d1->d_name + short_len) || - put_user(short_len, &d1->d_reclen)) - goto efault; + struct fat_ioctl_filldir_callback buf; + int ret; + + buf.dirent = dirent; + buf.result = 0; + mutex_lock(&inode->i_mutex); + ret = -ENOENT; + if (!IS_DEADDIR(inode)) { + ret = __fat_readdir(inode, filp, &buf, filldir, + short_only, both); } - return 0; -efault: - buf->result = -EFAULT; - return -EFAULT; + mutex_unlock(&inode->i_mutex); + if (ret >= 0) + ret = buf.result; + return ret; } -static int fat_dir_ioctl(struct inode * inode, struct file * filp, - unsigned int cmd, unsigned long arg) +static int fat_dir_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { - struct fat_ioctl_filldir_callback buf; - struct dirent __user *d1; - int ret, short_only, both; + struct dirent __user *d1 = (struct dirent __user *)arg; + int short_only, both; switch (cmd) { case VFAT_IOCTL_READDIR_SHORT: @@ -717,7 +740,6 @@ static int fat_dir_ioctl(struct inode * inode, struct file * filp, return fat_generic_ioctl(inode, filp, cmd, arg); } - d1 = (struct dirent __user *)arg; if (!access_ok(VERIFY_WRITE, d1, sizeof(struct dirent[2]))) return -EFAULT; /* @@ -728,69 +750,48 @@ static int fat_dir_ioctl(struct inode * inode, struct file * filp, if (put_user(0, &d1->d_reclen)) return -EFAULT; - buf.dirent = d1; - buf.result = 0; - mutex_lock(&inode->i_mutex); - ret = -ENOENT; - if (!IS_DEADDIR(inode)) { - ret = __fat_readdir(inode, filp, &buf, fat_ioctl_filldir, - short_only, both); - } - mutex_unlock(&inode->i_mutex); - if (ret >= 0) - ret = buf.result; - return ret; + return fat_ioctl_readdir(inode, filp, d1, fat_ioctl_filldir, + short_only, both); } #ifdef CONFIG_COMPAT #define VFAT_IOCTL_READDIR_BOTH32 _IOR('r', 1, struct compat_dirent[2]) #define VFAT_IOCTL_READDIR_SHORT32 _IOR('r', 2, struct compat_dirent[2]) -static long fat_compat_put_dirent32(struct dirent *d, - struct compat_dirent __user *d32) -{ - if (!access_ok(VERIFY_WRITE, d32, sizeof(struct compat_dirent))) - return -EFAULT; - - __put_user(d->d_ino, &d32->d_ino); - __put_user(d->d_off, &d32->d_off); - __put_user(d->d_reclen, &d32->d_reclen); - if (__copy_to_user(d32->d_name, d->d_name, d->d_reclen)) - return -EFAULT; +FAT_IOCTL_FILLDIR_FUNC(fat_compat_ioctl_filldir, compat_dirent) - return 0; -} - -static long fat_compat_dir_ioctl(struct file *file, unsigned cmd, +static long fat_compat_dir_ioctl(struct file *filp, unsigned cmd, unsigned long arg) { - struct compat_dirent __user *p = compat_ptr(arg); - int ret; - mm_segment_t oldfs = get_fs(); - struct dirent d[2]; + struct inode *inode = filp->f_path.dentry->d_inode; + struct compat_dirent __user *d1 = compat_ptr(arg); + int short_only, both; switch (cmd) { - case VFAT_IOCTL_READDIR_BOTH32: - cmd = VFAT_IOCTL_READDIR_BOTH; - break; case VFAT_IOCTL_READDIR_SHORT32: - cmd = VFAT_IOCTL_READDIR_SHORT; + short_only = 1; + both = 0; + break; + case VFAT_IOCTL_READDIR_BOTH32: + short_only = 0; + both = 1; break; default: return -ENOIOCTLCMD; } - set_fs(KERNEL_DS); - lock_kernel(); - ret = fat_dir_ioctl(file->f_path.dentry->d_inode, file, - cmd, (unsigned long) &d); - unlock_kernel(); - set_fs(oldfs); - if (ret >= 0) { - ret |= fat_compat_put_dirent32(&d[0], p); - ret |= fat_compat_put_dirent32(&d[1], p + 1); - } - return ret; + if (!access_ok(VERIFY_WRITE, d1, sizeof(struct compat_dirent[2]))) + return -EFAULT; + /* + * Yes, we don't need this put_user() absolutely. However old + * code didn't return the right value. So, app use this value, + * in order to check whether it is EOF. + */ + if (put_user(0, &d1->d_reclen)) + return -EFAULT; + + return fat_ioctl_readdir(inode, filp, d1, fat_compat_ioctl_filldir, + short_only, both); } #endif /* CONFIG_COMPAT */ diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c index 5065baa..3760d02 100644 --- a/fs/jfs/jfs_logmgr.c +++ b/fs/jfs/jfs_logmgr.c @@ -2354,12 +2354,13 @@ int jfsIOWait(void *arg) lbmStartIO(bp); spin_lock_irq(&log_redrive_lock); } - spin_unlock_irq(&log_redrive_lock); if (freezing(current)) { + spin_unlock_irq(&log_redrive_lock); refrigerator(); } else { set_current_state(TASK_INTERRUPTIBLE); + spin_unlock_irq(&log_redrive_lock); schedule(); current->state = TASK_RUNNING; } diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 6f24768..79bd03b 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c @@ -469,6 +469,13 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) nd.dentry = NULL; exp.ex_path = NULL; + /* fs locations */ + exp.ex_fslocs.locations = NULL; + exp.ex_fslocs.locations_count = 0; + exp.ex_fslocs.migrated = 0; + + exp.ex_uuid = NULL; + if (mesg[mlen-1] != '\n') return -EINVAL; mesg[mlen-1] = 0; @@ -509,13 +516,6 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) if (exp.h.expiry_time == 0) goto out; - /* fs locations */ - exp.ex_fslocs.locations = NULL; - exp.ex_fslocs.locations_count = 0; - exp.ex_fslocs.migrated = 0; - - exp.ex_uuid = NULL; - /* flags */ err = get_int(&mesg, &an_int); if (err == -ENOENT) diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index c8178b7..2cac562 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c @@ -68,7 +68,7 @@ static struct dentry *get_xa_root(struct super_block *sb, int flags) if (!privroot) return ERR_PTR(-ENODATA); - mutex_lock(&privroot->d_inode->i_mutex); + mutex_lock_nested(&privroot->d_inode->i_mutex, I_MUTEX_XATTR); if (REISERFS_SB(sb)->xattr_root) { xaroot = dget(REISERFS_SB(sb)->xattr_root); goto out; diff --git a/fs/udf/namei.c b/fs/udf/namei.c index fe361cd..b254375 100644 --- a/fs/udf/namei.c +++ b/fs/udf/namei.c @@ -878,7 +878,7 @@ static int udf_rmdir(struct inode * dir, struct dentry * dentry) inode->i_nlink); clear_nlink(inode); inode->i_size = 0; - inode_dec_link_count(inode); + inode_dec_link_count(dir); inode->i_ctime = dir->i_ctime = dir->i_mtime = current_fs_time(dir->i_sb); mark_inode_dirty(dir); diff --git a/include/asm-arm/arch-iop13xx/iop13xx.h b/include/asm-arm/arch-iop13xx/iop13xx.h index d26b755..74d7498 100644 --- a/include/asm-arm/arch-iop13xx/iop13xx.h +++ b/include/asm-arm/arch-iop13xx/iop13xx.h @@ -27,19 +27,24 @@ static inline int iop13xx_cpu_id(void) #define IOP13XX_PCI_OFFSET IOP13XX_MAX_RAM_SIZE /* PCI MAP - * 0x0000.0000 - 0x8000.0000 1:1 mapping with Physical RAM - * 0x8000.0000 - 0x8800.0000 PCIX/PCIE memory window (128MB) -*/ + * bus range cpu phys cpu virt note + * 0x0000.0000 + 2GB (n/a) (n/a) inbound, 1:1 mapping with Physical RAM + * 0x8000.0000 + 928M 0x1.8000.0000 (ioremap) PCIX outbound memory window + * 0x8000.0000 + 928M 0x2.8000.0000 (ioremap) PCIE outbound memory window + * + * IO MAP + * 0x1000 + 64K 0x0.fffb.1000 0xfec6.1000 PCIX outbound i/o window + * 0x1000 + 64K 0x0.fffd.1000 0xfed7.1000 PCIE outbound i/o window + */ #define IOP13XX_PCIX_IO_WINDOW_SIZE 0x10000UL #define IOP13XX_PCIX_LOWER_IO_PA 0xfffb0000UL #define IOP13XX_PCIX_LOWER_IO_VA 0xfec60000UL -#define IOP13XX_PCIX_LOWER_IO_BA 0x0fff0000UL +#define IOP13XX_PCIX_LOWER_IO_BA 0x0UL /* OIOTVR */ +#define IOP13XX_PCIX_IO_BUS_OFFSET 0x1000UL #define IOP13XX_PCIX_UPPER_IO_PA (IOP13XX_PCIX_LOWER_IO_PA +\ IOP13XX_PCIX_IO_WINDOW_SIZE - 1) #define IOP13XX_PCIX_UPPER_IO_VA (IOP13XX_PCIX_LOWER_IO_VA +\ IOP13XX_PCIX_IO_WINDOW_SIZE - 1) -#define IOP13XX_PCIX_IO_OFFSET (IOP13XX_PCIX_LOWER_IO_VA -\ - IOP13XX_PCIX_LOWER_IO_BA) #define IOP13XX_PCIX_IO_PHYS_TO_VIRT(addr) (u32) ((u32) addr -\ (IOP13XX_PCIX_LOWER_IO_PA\ - IOP13XX_PCIX_LOWER_IO_VA)) @@ -65,15 +70,14 @@ static inline int iop13xx_cpu_id(void) #define IOP13XX_PCIE_IO_WINDOW_SIZE 0x10000UL #define IOP13XX_PCIE_LOWER_IO_PA 0xfffd0000UL #define IOP13XX_PCIE_LOWER_IO_VA 0xfed70000UL -#define IOP13XX_PCIE_LOWER_IO_BA 0x0fff0000UL +#define IOP13XX_PCIE_LOWER_IO_BA 0x0UL /* OIOTVR */ +#define IOP13XX_PCIE_IO_BUS_OFFSET 0x1000UL #define IOP13XX_PCIE_UPPER_IO_PA (IOP13XX_PCIE_LOWER_IO_PA +\ IOP13XX_PCIE_IO_WINDOW_SIZE - 1) #define IOP13XX_PCIE_UPPER_IO_VA (IOP13XX_PCIE_LOWER_IO_VA +\ IOP13XX_PCIE_IO_WINDOW_SIZE - 1) #define IOP13XX_PCIE_UPPER_IO_BA (IOP13XX_PCIE_LOWER_IO_BA +\ IOP13XX_PCIE_IO_WINDOW_SIZE - 1) -#define IOP13XX_PCIE_IO_OFFSET (IOP13XX_PCIE_LOWER_IO_VA -\ - IOP13XX_PCIE_LOWER_IO_BA) #define IOP13XX_PCIE_IO_PHYS_TO_VIRT(addr) (u32) ((u32) addr -\ (IOP13XX_PCIE_LOWER_IO_PA\ - IOP13XX_PCIE_LOWER_IO_VA)) diff --git a/include/asm-sparc64/openprom.h b/include/asm-sparc64/openprom.h index e01b805..26ec046 100644 --- a/include/asm-sparc64/openprom.h +++ b/include/asm-sparc64/openprom.h @@ -177,7 +177,7 @@ struct linux_nodeops { /* More fun PROM structures for device probing. */ #define PROMREG_MAX 24 #define PROMVADDR_MAX 16 -#define PROMINTR_MAX 15 +#define PROMINTR_MAX 32 struct linux_prom_registers { unsigned which_io; /* hi part of physical address */ diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h index daa4940..bf92c26 100644 --- a/include/linux/clocksource.h +++ b/include/linux/clocksource.h @@ -48,6 +48,7 @@ struct clocksource; * @shift: cycle to nanosecond divisor (power of two) * @flags: flags describing special properties * @vread: vsyscall based read + * @resume: resume function for the clocksource, if necessary * @cycle_interval: Used internally by timekeeping core, please ignore. * @xtime_interval: Used internally by timekeeping core, please ignore. */ @@ -61,6 +62,7 @@ struct clocksource { u32 shift; unsigned long flags; cycle_t (*vread)(void); + void (*resume)(void); /* timekeeping specific data, ignore */ cycle_t cycle_last, cycle_interval; @@ -198,6 +200,7 @@ static inline void clocksource_calculate_interval(struct clocksource *c, extern int clocksource_register(struct clocksource*); extern struct clocksource* clocksource_get_next(void); extern void clocksource_change_rating(struct clocksource *cs, int rating); +extern void clocksource_resume(void); #ifdef CONFIG_GENERIC_TIME_VSYSCALL extern void update_vsyscall(struct timespec *ts, struct clocksource *c); diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 1a52854..b1b0f68 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -647,8 +647,10 @@ static inline void netif_start_queue(struct net_device *dev) static inline void netif_wake_queue(struct net_device *dev) { #ifdef CONFIG_NETPOLL_TRAP - if (netpoll_trap()) + if (netpoll_trap()) { + clear_bit(__LINK_STATE_XOFF, &dev->state); return; + } #endif if (test_and_clear_bit(__LINK_STATE_XOFF, &dev->state)) __netif_schedule(dev); @@ -656,10 +658,6 @@ static inline void netif_wake_queue(struct net_device *dev) static inline void netif_stop_queue(struct net_device *dev) { -#ifdef CONFIG_NETPOLL_TRAP - if (netpoll_trap()) - return; -#endif set_bit(__LINK_STATE_XOFF, &dev->state); } diff --git a/include/linux/netfilter/nf_conntrack_proto_gre.h b/include/linux/netfilter/nf_conntrack_proto_gre.h index 4e6bbce..535e421 100644 --- a/include/linux/netfilter/nf_conntrack_proto_gre.h +++ b/include/linux/netfilter/nf_conntrack_proto_gre.h @@ -87,24 +87,6 @@ int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir, /* delete keymap entries */ void nf_ct_gre_keymap_destroy(struct nf_conn *ct); -/* get pointer to gre key, if present */ -static inline __be32 *gre_key(struct gre_hdr *greh) -{ - if (!greh->key) - return NULL; - if (greh->csum || greh->routing) - return (__be32 *)(greh+sizeof(*greh)+4); - return (__be32 *)(greh+sizeof(*greh)); -} - -/* get pointer ot gre csum, if present */ -static inline __sum16 *gre_csum(struct gre_hdr *greh) -{ - if (!greh->csum) - return NULL; - return (__sum16 *)(greh+sizeof(*greh)); -} - extern void nf_ct_gre_keymap_flush(void); extern void nf_nat_need_gre(void); diff --git a/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h b/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h index e371e0f..d0f36f5 100644 --- a/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h +++ b/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h @@ -90,25 +90,6 @@ int ip_ct_gre_keymap_add(struct ip_conntrack *ct, /* delete keymap entries */ void ip_ct_gre_keymap_destroy(struct ip_conntrack *ct); - -/* get pointer to gre key, if present */ -static inline __be32 *gre_key(struct gre_hdr *greh) -{ - if (!greh->key) - return NULL; - if (greh->csum || greh->routing) - return (__be32 *) (greh+sizeof(*greh)+4); - return (__be32 *) (greh+sizeof(*greh)); -} - -/* get pointer ot gre csum, if present */ -static inline __sum16 *gre_csum(struct gre_hdr *greh) -{ - if (!greh->csum) - return NULL; - return (__sum16 *) (greh+sizeof(*greh)); -} - #endif /* __KERNEL__ */ #endif /* _CONNTRACK_PROTO_GRE_H */ diff --git a/kernel/cpuset.c b/kernel/cpuset.c index f382b0f..9e45dd1 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -1751,12 +1751,7 @@ static ssize_t cpuset_tasks_read(struct file *file, char __user *buf, { struct ctr_struct *ctr = file->private_data; - if (*ppos + nbytes > ctr->bufsz) - nbytes = ctr->bufsz - *ppos; - if (copy_to_user(buf, ctr->buf + *ppos, nbytes)) - return -EFAULT; - *ppos += nbytes; - return nbytes; + return simple_read_from_buffer(buf, nbytes, ppos, ctr->buf, ctr->bufsz); } static int cpuset_tasks_release(struct inode *unused_inode, struct file *file) diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c index fe5c7db..5baee91 100644 --- a/kernel/time/clocksource.c +++ b/kernel/time/clocksource.c @@ -74,6 +74,8 @@ static struct clocksource *watchdog; static struct timer_list watchdog_timer; static DEFINE_SPINLOCK(watchdog_lock); static cycle_t watchdog_last; +static int watchdog_resumed; + /* * Interval: 0.5sec Treshold: 0.0625s */ @@ -98,15 +100,26 @@ static void clocksource_watchdog(unsigned long data) struct clocksource *cs, *tmp; cycle_t csnow, wdnow; int64_t wd_nsec, cs_nsec; + int resumed; spin_lock(&watchdog_lock); + resumed = watchdog_resumed; + if (unlikely(resumed)) + watchdog_resumed = 0; + wdnow = watchdog->read(); wd_nsec = cyc2ns(watchdog, (wdnow - watchdog_last) & watchdog->mask); watchdog_last = wdnow; list_for_each_entry_safe(cs, tmp, &watchdog_list, wd_list) { csnow = cs->read(); + + if (unlikely(resumed)) { + cs->wd_last = csnow; + continue; + } + /* Initialized ? */ if (!(cs->flags & CLOCK_SOURCE_WATCHDOG)) { if ((cs->flags & CLOCK_SOURCE_IS_CONTINUOUS) && @@ -136,6 +149,13 @@ static void clocksource_watchdog(unsigned long data) } spin_unlock(&watchdog_lock); } +static void clocksource_resume_watchdog(void) +{ + spin_lock(&watchdog_lock); + watchdog_resumed = 1; + spin_unlock(&watchdog_lock); +} + static void clocksource_check_watchdog(struct clocksource *cs) { struct clocksource *cse; @@ -182,9 +202,34 @@ static void clocksource_check_watchdog(struct clocksource *cs) if (cs->flags & CLOCK_SOURCE_IS_CONTINUOUS) cs->flags |= CLOCK_SOURCE_VALID_FOR_HRES; } + +static inline void clocksource_resume_watchdog(void) { } #endif /** + * clocksource_resume - resume the clocksource(s) + */ +void clocksource_resume(void) +{ + struct list_head *tmp; + unsigned long flags; + + spin_lock_irqsave(&clocksource_lock, flags); + + list_for_each(tmp, &clocksource_list) { + struct clocksource *cs; + + cs = list_entry(tmp, struct clocksource, list); + if (cs->resume) + cs->resume(); + } + + clocksource_resume_watchdog(); + + spin_unlock_irqrestore(&clocksource_lock, flags); +} + +/** * clocksource_get_next - Returns the selected clocksource * */ diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c index bfda3f7..a96ec9a 100644 --- a/kernel/time/tick-common.c +++ b/kernel/time/tick-common.c @@ -31,7 +31,7 @@ DEFINE_PER_CPU(struct tick_device, tick_cpu_device); */ ktime_t tick_next_period; ktime_t tick_period; -static int tick_do_timer_cpu = -1; +int tick_do_timer_cpu __read_mostly = -1; DEFINE_SPINLOCK(tick_device_lock); /* @@ -295,6 +295,12 @@ static void tick_shutdown(unsigned int *cpup) clockevents_exchange_device(dev, NULL); td->evtdev = NULL; } + /* Transfer the do_timer job away from this cpu */ + if (*cpup == tick_do_timer_cpu) { + int cpu = first_cpu(cpu_online_map); + + tick_do_timer_cpu = (cpu != NR_CPUS) ? cpu : -1; + } spin_unlock_irqrestore(&tick_device_lock, flags); } diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h index c9d203b..bb13f27 100644 --- a/kernel/time/tick-internal.h +++ b/kernel/time/tick-internal.h @@ -5,6 +5,7 @@ DECLARE_PER_CPU(struct tick_device, tick_cpu_device); extern spinlock_t tick_device_lock; extern ktime_t tick_next_period; extern ktime_t tick_period; +extern int tick_do_timer_cpu __read_mostly; extern void tick_setup_periodic(struct clock_event_device *dev, int broadcast); extern void tick_handle_periodic(struct clock_event_device *dev); diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 51556b9..f4fc867 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -221,6 +221,18 @@ void tick_nohz_stop_sched_tick(void) ts->tick_stopped = 1; ts->idle_jiffies = last_jiffies; } + + /* + * If this cpu is the one which updates jiffies, then + * give up the assignment and let it be taken by the + * cpu which runs the tick timer next, which might be + * this cpu as well. If we don't drop this here the + * jiffies might be stale and do_timer() never + * invoked. + */ + if (cpu == tick_do_timer_cpu) + tick_do_timer_cpu = -1; + /* * calculate the expiry time for the next timer wheel * timer @@ -338,12 +350,24 @@ static void tick_nohz_handler(struct clock_event_device *dev) { struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched); struct pt_regs *regs = get_irq_regs(); + int cpu = smp_processor_id(); ktime_t now = ktime_get(); dev->next_event.tv64 = KTIME_MAX; + /* + * Check if the do_timer duty was dropped. We don't care about + * concurrency: This happens only when the cpu in charge went + * into a long sleep. If two cpus happen to assign themself to + * this duty, then the jiffies update is still serialized by + * xtime_lock. + */ + if (unlikely(tick_do_timer_cpu == -1)) + tick_do_timer_cpu = cpu; + /* Check, if the jiffies need an update */ - tick_do_update_jiffies64(now); + if (tick_do_timer_cpu == cpu) + tick_do_update_jiffies64(now); /* * When we are idle and the tick is stopped, we have to touch @@ -431,9 +455,23 @@ static enum hrtimer_restart tick_sched_timer(struct hrtimer *timer) struct hrtimer_cpu_base *base = timer->base->cpu_base; struct pt_regs *regs = get_irq_regs(); ktime_t now = ktime_get(); + int cpu = smp_processor_id(); + +#ifdef CONFIG_NO_HZ + /* + * Check if the do_timer duty was dropped. We don't care about + * concurrency: This happens only when the cpu in charge went + * into a long sleep. If two cpus happen to assign themself to + * this duty, then the jiffies update is still serialized by + * xtime_lock. + */ + if (unlikely(tick_do_timer_cpu == -1)) + tick_do_timer_cpu = cpu; +#endif /* Check, if the jiffies need an update */ - tick_do_update_jiffies64(now); + if (tick_do_timer_cpu == cpu) + tick_do_update_jiffies64(now); /* * Do not call, when we are not in irq context and have diff --git a/kernel/timer.c b/kernel/timer.c index dd6c2c1..e045774 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -1903,6 +1903,8 @@ unregister_time_interpolator(struct time_interpolator *ti) prev = &curr->next; } + clocksource_resume(); + write_seqlock_irqsave(&xtime_lock, flags); if (ti == time_interpolator) { /* we lost the best time-interpolator: */ diff --git a/lib/zlib_inflate/inflate.c b/lib/zlib_inflate/inflate.c index fceb97c..7e1e311 100644 --- a/lib/zlib_inflate/inflate.c +++ b/lib/zlib_inflate/inflate.c @@ -743,12 +743,14 @@ int zlib_inflate(z_streamp strm, int flush) strm->data_type = state->bits + (state->last ? 64 : 0) + (state->mode == TYPE ? 128 : 0); - if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) - ret = Z_BUF_ERROR; if (flush == Z_PACKET_FLUSH && ret == Z_OK && - (strm->avail_out != 0 || strm->avail_in == 0)) + strm->avail_out != 0 && strm->avail_in == 0) return zlib_inflateSyncPacket(strm); + + if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) + ret = Z_BUF_ERROR; + return ret; } diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 36db012..88e708b 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -140,6 +140,8 @@ static struct page *alloc_huge_page(struct vm_area_struct *vma, return page; fail: + if (vma->vm_flags & VM_MAYSHARE) + resv_huge_pages++; spin_unlock(&hugetlb_lock); return NULL; } diff --git a/mm/oom_kill.c b/mm/oom_kill.c index 3791edf..b3a3dd6 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -397,6 +397,7 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, int order) struct task_struct *p; unsigned long points = 0; unsigned long freed = 0; + int constraint; blocking_notifier_call_chain(&oom_notify_list, 0, &freed); if (freed > 0) @@ -411,14 +412,15 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, int order) show_mem(); } - cpuset_lock(); - read_lock(&tasklist_lock); - /* * Check if there were limitations on the allocation (only relevant for * NUMA) that may require different handling. */ - switch (constrained_alloc(zonelist, gfp_mask)) { + constraint = constrained_alloc(zonelist, gfp_mask); + cpuset_lock(); + read_lock(&tasklist_lock); + + switch (constraint) { case CONSTRAINT_MEMORY_POLICY: oom_kill_process(current, points, "No available memory (MPOL_BIND)"); diff --git a/mm/slob.c b/mm/slob.c index 5adc29c..c683d35 100644 --- a/mm/slob.c +++ b/mm/slob.c @@ -150,15 +150,6 @@ static void slob_free(void *block, int size) spin_unlock_irqrestore(&slob_lock, flags); } -static int FASTCALL(find_order(int size)); -static int fastcall find_order(int size) -{ - int order = 0; - for ( ; size > 4096 ; size >>=1) - order++; - return order; -} - void *__kmalloc(size_t size, gfp_t gfp) { slob_t *m; @@ -174,7 +165,7 @@ void *__kmalloc(size_t size, gfp_t gfp) if (!bb) return 0; - bb->order = find_order(size); + bb->order = get_order(size); bb->pages = (void *)__get_free_pages(gfp, bb->order); if (bb->pages) { @@ -284,7 +275,7 @@ void *kmem_cache_alloc(struct kmem_cache *c, gfp_t flags) if (c->size < PAGE_SIZE) b = slob_alloc(c->size, flags, c->align); else - b = (void *)__get_free_pages(flags, find_order(c->size)); + b = (void *)__get_free_pages(flags, get_order(c->size)); if (c->ctor) c->ctor(b, c, SLAB_CTOR_CONSTRUCTOR); @@ -311,7 +302,7 @@ void kmem_cache_free(struct kmem_cache *c, void *b) if (c->size < PAGE_SIZE) slob_free(b, c->size); else - free_pages((unsigned long)b, find_order(c->size)); + free_pages((unsigned long)b, get_order(c->size)); } EXPORT_SYMBOL(kmem_cache_free); diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index cac06c4..444a56b 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -777,6 +777,10 @@ static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb ) .tos = frn->fl_tos, .scope = frn->fl_scope } } }; +#ifdef CONFIG_IP_MULTIPLE_TABLES + res.r = NULL; +#endif + frn->err = -ENOENT; if (tb) { local_bh_disable(); diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c index 23b99ae..75bd597 100644 --- a/net/ipv4/netfilter/ip_conntrack_core.c +++ b/net/ipv4/netfilter/ip_conntrack_core.c @@ -302,7 +302,6 @@ destroy_conntrack(struct nf_conntrack *nfct) { struct ip_conntrack *ct = (struct ip_conntrack *)nfct; struct ip_conntrack_protocol *proto; - struct ip_conntrack_helper *helper; typeof(ip_conntrack_destroyed) destroyed; DEBUGP("destroy_conntrack(%p)\n", ct); @@ -312,10 +311,6 @@ destroy_conntrack(struct nf_conntrack *nfct) ip_conntrack_event(IPCT_DESTROY, ct); set_bit(IPS_DYING_BIT, &ct->status); - helper = ct->helper; - if (helper && helper->destroy) - helper->destroy(ct); - /* To make sure we don't get any weird locking issues here: * destroy_conntrack() MUST NOT be called with a write lock * to ip_conntrack_lock!!! -HW */ @@ -356,6 +351,11 @@ destroy_conntrack(struct nf_conntrack *nfct) static void death_by_timeout(unsigned long ul_conntrack) { struct ip_conntrack *ct = (void *)ul_conntrack; + struct ip_conntrack_helper *helper; + + helper = ct->helper; + if (helper && helper->destroy) + helper->destroy(ct); write_lock_bh(&ip_conntrack_lock); /* Inside lock so preempt is disabled on module removal path. diff --git a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c index e694299..b86479a 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c @@ -460,7 +460,8 @@ static int sctp_new(struct ip_conntrack *conntrack, SCTP_CONNTRACK_NONE, sch->type); /* Invalid: delete conntrack */ - if (newconntrack == SCTP_CONNTRACK_MAX) { + if (newconntrack == SCTP_CONNTRACK_NONE || + newconntrack == SCTP_CONNTRACK_MAX) { DEBUGP("ip_conntrack_sctp: invalid new deleting.\n"); return 0; } diff --git a/net/ipv4/netfilter/ip_nat_proto_gre.c b/net/ipv4/netfilter/ip_nat_proto_gre.c index 9581020..e3146a3 100644 --- a/net/ipv4/netfilter/ip_nat_proto_gre.c +++ b/net/ipv4/netfilter/ip_nat_proto_gre.c @@ -70,6 +70,11 @@ gre_unique_tuple(struct ip_conntrack_tuple *tuple, __be16 *keyptr; unsigned int min, i, range_size; + /* If there is no master conntrack we are not PPTP, + do not change tuples */ + if (!conntrack->master) + return 0; + if (maniptype == IP_NAT_MANIP_SRC) keyptr = &tuple->src.u.gre.key; else @@ -122,18 +127,9 @@ gre_manip_pkt(struct sk_buff **pskb, if (maniptype == IP_NAT_MANIP_DST) { /* key manipulation is always dest */ switch (greh->version) { - case 0: - if (!greh->key) { - DEBUGP("can't nat GRE w/o key\n"); - break; - } - if (greh->csum) { - /* FIXME: Never tested this code... */ - nf_proto_csum_replace4(gre_csum(greh), *pskb, - *(gre_key(greh)), - tuple->dst.u.gre.key, 0); - } - *(gre_key(greh)) = tuple->dst.u.gre.key; + case GRE_VERSION_1701: + /* We do not currently NAT any GREv0 packets. + * Try to behave like "ip_nat_proto_unknown" */ break; case GRE_VERSION_PPTP: DEBUGP("call_id -> 0x%04x\n", diff --git a/net/ipv4/netfilter/nf_nat_proto_gre.c b/net/ipv4/netfilter/nf_nat_proto_gre.c index e5a34c1..ca3ff84 100644 --- a/net/ipv4/netfilter/nf_nat_proto_gre.c +++ b/net/ipv4/netfilter/nf_nat_proto_gre.c @@ -72,6 +72,11 @@ gre_unique_tuple(struct nf_conntrack_tuple *tuple, __be16 *keyptr; unsigned int min, i, range_size; + /* If there is no master conntrack we are not PPTP, + do not change tuples */ + if (!conntrack->master) + return 0; + if (maniptype == IP_NAT_MANIP_SRC) keyptr = &tuple->src.u.gre.key; else @@ -122,18 +127,9 @@ gre_manip_pkt(struct sk_buff **pskb, unsigned int iphdroff, if (maniptype != IP_NAT_MANIP_DST) return 1; switch (greh->version) { - case 0: - if (!greh->key) { - DEBUGP("can't nat GRE w/o key\n"); - break; - } - if (greh->csum) { - /* FIXME: Never tested this code... */ - nf_proto_csum_replace4(gre_csum(greh), *pskb, - *(gre_key(greh)), - tuple->dst.u.gre.key, 0); - } - *(gre_key(greh)) = tuple->dst.u.gre.key; + case GRE_VERSION_1701: + /* We do not currently NAT any GREv0 packets. + * Try to behave like "nf_nat_proto_unknown" */ break; case GRE_VERSION_PPTP: DEBUGP("call_id -> 0x%04x\n", ntohs(tuple->dst.u.gre.key)); diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 3834b10..824c6b9 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -1759,8 +1759,7 @@ int tcp_disconnect(struct sock *sk, int flags) tcp_clear_retrans(tp); inet_csk_delack_init(sk); sk->sk_send_head = NULL; - tp->rx_opt.saw_tstamp = 0; - tcp_sack_reset(&tp->rx_opt); + memset(&tp->rx_opt, 0, sizeof(tp->rx_opt)); __sk_dst_reset(sk); BUG_TRAP(!inet->num || icsk->icsk_bind_hash); diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 452a82c..a541137 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -2281,8 +2281,9 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, break; case NETDEV_CHANGENAME: -#ifdef CONFIG_SYSCTL if (idev) { + snmp6_unregister_dev(idev); +#ifdef CONFIG_SYSCTL addrconf_sysctl_unregister(&idev->cnf); neigh_sysctl_unregister(idev->nd_parms); neigh_sysctl_register(dev, idev->nd_parms, @@ -2290,8 +2291,9 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, &ndisc_ifinfo_sysctl_change, NULL); addrconf_sysctl_register(idev, &idev->cnf); - } #endif + snmp6_register_dev(idev); + } break; }; @@ -4060,6 +4062,10 @@ int __init addrconf_init(void) return err; ip6_null_entry.rt6i_idev = in6_dev_get(&loopback_dev); +#ifdef CONFIG_IPV6_MULTIPLE_TABLES + ip6_prohibit_entry.rt6i_idev = in6_dev_get(&loopback_dev); + ip6_blk_hole_entry.rt6i_idev = in6_dev_get(&loopback_dev); +#endif register_netdevice_notifier(&ipv6_dev_notf); diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index fb39604..794b930 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c @@ -396,6 +396,7 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp) switch (hdr->type) { #ifdef CONFIG_IPV6_MIP6 + case IPV6_SRCRT_TYPE_2: break; #endif case IPV6_SRCRT_TYPE_0: @@ -651,6 +652,14 @@ EXPORT_SYMBOL_GPL(ipv6_invert_rthdr); Hop-by-hop options. **********************************/ +/* + * Note: we cannot rely on skb->dst before we assign it in ip6_route_input(). + */ +static inline struct inet6_dev *ipv6_skb_idev(struct sk_buff *skb) +{ + return skb->dst ? ip6_dst_idev(skb->dst) : __in6_dev_get(skb->dev); +} + /* Router Alert as of RFC 2711 */ static int ipv6_hop_ra(struct sk_buff **skbp, int optoff) @@ -677,25 +686,25 @@ static int ipv6_hop_jumbo(struct sk_buff **skbp, int optoff) if (skb->nh.raw[optoff+1] != 4 || (optoff&3) != 2) { LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n", skb->nh.raw[optoff+1]); - IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), + IP6_INC_STATS_BH(ipv6_skb_idev(skb), IPSTATS_MIB_INHDRERRORS); goto drop; } pkt_len = ntohl(*(__be32*)(skb->nh.raw+optoff+2)); if (pkt_len <= IPV6_MAXPLEN) { - IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS_BH(ipv6_skb_idev(skb), IPSTATS_MIB_INHDRERRORS); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2); return 0; } if (skb->nh.ipv6h->payload_len) { - IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); + IP6_INC_STATS_BH(ipv6_skb_idev(skb), IPSTATS_MIB_INHDRERRORS); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff); return 0; } if (pkt_len > skb->len - sizeof(struct ipv6hdr)) { - IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INTRUNCATEDPKTS); + IP6_INC_STATS_BH(ipv6_skb_idev(skb), IPSTATS_MIB_INTRUNCATEDPKTS); goto drop; } diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 61e7a6c..1b34ee5 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c @@ -235,7 +235,7 @@ int ip6_mc_input(struct sk_buff *skb) IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INMCASTPKTS); hdr = skb->nh.ipv6h; - deliver = likely(!(skb->dev->flags & (IFF_PROMISC|IFF_ALLMULTI))) || + deliver = unlikely(skb->dev->flags & (IFF_PROMISC|IFF_ALLMULTI)) || ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, NULL); /* diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 3055169..9fa3ffb 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -449,10 +449,17 @@ int ip6_forward(struct sk_buff *skb) */ if (xrlim_allow(dst, 1*HZ)) ndisc_send_redirect(skb, n, target); - } else if (ipv6_addr_type(&hdr->saddr)&(IPV6_ADDR_MULTICAST|IPV6_ADDR_LOOPBACK - |IPV6_ADDR_LINKLOCAL)) { + } else { + int addrtype = ipv6_addr_type(&hdr->saddr); + /* This check is security critical. */ - goto error; + if (addrtype & (IPV6_ADDR_MULTICAST|IPV6_ADDR_LOOPBACK)) + goto error; + if (addrtype & IPV6_ADDR_LINKLOCAL) { + icmpv6_send(skb, ICMPV6_DEST_UNREACH, + ICMPV6_NOT_NEIGHBOUR, 0, skb->dev); + goto error; + } } if (skb->len > dst_mtu(dst)) { diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index fa3fb50..d57853d 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c @@ -236,6 +236,7 @@ int snmp6_unregister_dev(struct inet6_dev *idev) return -EINVAL; remove_proc_entry(idev->stats.proc_dir_entry->name, proc_net_devsnmp6); + idev->stats.proc_dir_entry = NULL; return 0; } diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index 93c4223..dff33cc 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c @@ -261,7 +261,7 @@ static int xfrm6_tunnel_rcv(struct sk_buff *skb) __be32 spi; spi = xfrm6_tunnel_spi_lookup((xfrm_address_t *)&iph->saddr); - return xfrm6_rcv_spi(skb, spi); + return xfrm6_rcv_spi(skb, spi) > 0 ? : 0; } static int xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt, diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index b3a70eb..ce28fdd 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -315,7 +315,6 @@ static void destroy_conntrack(struct nf_conntrack *nfct) { struct nf_conn *ct = (struct nf_conn *)nfct; - struct nf_conn_help *help = nfct_help(ct); struct nf_conntrack_l3proto *l3proto; struct nf_conntrack_l4proto *l4proto; typeof(nf_conntrack_destroyed) destroyed; @@ -327,9 +326,6 @@ destroy_conntrack(struct nf_conntrack *nfct) nf_conntrack_event(IPCT_DESTROY, ct); set_bit(IPS_DYING_BIT, &ct->status); - if (help && help->helper && help->helper->destroy) - help->helper->destroy(ct); - /* To make sure we don't get any weird locking issues here: * destroy_conntrack() MUST NOT be called with a write lock * to nf_conntrack_lock!!! -HW */ @@ -375,6 +371,10 @@ destroy_conntrack(struct nf_conntrack *nfct) static void death_by_timeout(unsigned long ul_conntrack) { struct nf_conn *ct = (void *)ul_conntrack; + struct nf_conn_help *help = nfct_help(ct); + + if (help && help->helper && help->helper->destroy) + help->helper->destroy(ct); write_lock_bh(&nf_conntrack_lock); /* Inside lock so preempt is disabled on module removal path. diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c index 3c80558..b53bc64 100644 --- a/net/netfilter/nf_conntrack_proto_sctp.c +++ b/net/netfilter/nf_conntrack_proto_sctp.c @@ -469,7 +469,8 @@ static int sctp_new(struct nf_conn *conntrack, const struct sk_buff *skb, SCTP_CONNTRACK_NONE, sch->type); /* Invalid: delete conntrack */ - if (newconntrack == SCTP_CONNTRACK_MAX) { + if (newconntrack == SCTP_CONNTRACK_NONE || + newconntrack == SCTP_CONNTRACK_MAX) { DEBUGP("nf_conntrack_sctp: invalid new deleting.\n"); return 0; } diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c index de889f2..a86f36b 100644 --- a/net/sched/sch_prio.c +++ b/net/sched/sch_prio.c @@ -74,7 +74,7 @@ prio_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) band = res.classid; } band = TC_H_MIN(band) - 1; - if (band > q->bands) + if (band >= q->bands) return q->queues[q->prio2band[0]]; return q->queues[band]; diff --git a/net/sctp/socket.c b/net/sctp/socket.c index a1d026f..843c928 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -3847,7 +3847,7 @@ static int sctp_getsockopt_peer_addrs(struct sock *sk, int len, memcpy(&temp, &from->ipaddr, sizeof(temp)); sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp); addrlen = sctp_get_af_specific(sk->sk_family)->sockaddr_len; - if(space_left < addrlen) + if (space_left < addrlen) return -ENOMEM; if (copy_to_user(to, &temp, addrlen)) return -EFAULT; @@ -3936,8 +3936,9 @@ done: /* Helper function that copies local addresses to user and returns the number * of addresses copied. */ -static int sctp_copy_laddrs_to_user_old(struct sock *sk, __u16 port, int max_addrs, - void __user *to) +static int sctp_copy_laddrs_old(struct sock *sk, __u16 port, + int max_addrs, void *to, + int *bytes_copied) { struct list_head *pos, *next; struct sctp_sockaddr_entry *addr; @@ -3954,10 +3955,10 @@ static int sctp_copy_laddrs_to_user_old(struct sock *sk, __u16 port, int max_add sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk), &temp); addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; - if (copy_to_user(to, &temp, addrlen)) - return -EFAULT; + memcpy(to, &temp, addrlen); to += addrlen; + *bytes_copied += addrlen; cnt ++; if (cnt >= max_addrs) break; } @@ -3965,8 +3966,8 @@ static int sctp_copy_laddrs_to_user_old(struct sock *sk, __u16 port, int max_add return cnt; } -static int sctp_copy_laddrs_to_user(struct sock *sk, __u16 port, - void __user **to, size_t space_left) +static int sctp_copy_laddrs(struct sock *sk, __u16 port, void *to, + size_t space_left, int *bytes_copied) { struct list_head *pos, *next; struct sctp_sockaddr_entry *addr; @@ -3983,14 +3984,14 @@ static int sctp_copy_laddrs_to_user(struct sock *sk, __u16 port, sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk), &temp); addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; - if(space_leftaddress_list.next, struct sctp_sockaddr_entry, list); if (sctp_is_any(&addr->a)) { - cnt = sctp_copy_laddrs_to_user_old(sk, bp->port, - getaddrs.addr_num, - to); - if (cnt < 0) { - err = cnt; - goto unlock; - } + cnt = sctp_copy_laddrs_old(sk, bp->port, + getaddrs.addr_num, + addrs, &bytes_copied); goto copy_getaddrs; } } + buf = addrs; list_for_each(pos, &bp->address_list) { addr = list_entry(pos, struct sctp_sockaddr_entry, list); memcpy(&temp, &addr->a, sizeof(temp)); sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp); addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; - if (copy_to_user(to, &temp, addrlen)) { - err = -EFAULT; - goto unlock; - } - to += addrlen; + memcpy(buf, &temp, addrlen); + buf += addrlen; + bytes_copied += addrlen; cnt ++; if (cnt >= getaddrs.addr_num) break; } copy_getaddrs: + sctp_read_unlock(addr_lock); + + /* copy the entire address list into the user provided space */ + if (copy_to_user(to, addrs, bytes_copied)) { + err = -EFAULT; + goto error; + } + + /* copy the leading structure back to user */ getaddrs.addr_num = cnt; if (copy_to_user(optval, &getaddrs, sizeof(struct sctp_getaddrs_old))) err = -EFAULT; -unlock: - sctp_read_unlock(addr_lock); +error: + kfree(addrs); return err; } @@ -4101,7 +4118,9 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len, rwlock_t *addr_lock; int err = 0; size_t space_left; - int bytes_copied; + int bytes_copied = 0; + void *addrs; + void *buf; if (len <= sizeof(struct sctp_getaddrs)) return -EINVAL; @@ -4129,6 +4148,9 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len, to = optval + offsetof(struct sctp_getaddrs,addrs); space_left = len - sizeof(struct sctp_getaddrs) - offsetof(struct sctp_getaddrs,addrs); + addrs = kmalloc(space_left, GFP_KERNEL); + if (!addrs) + return -ENOMEM; sctp_read_lock(addr_lock); @@ -4139,41 +4161,47 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len, addr = list_entry(bp->address_list.next, struct sctp_sockaddr_entry, list); if (sctp_is_any(&addr->a)) { - cnt = sctp_copy_laddrs_to_user(sk, bp->port, - &to, space_left); + cnt = sctp_copy_laddrs(sk, bp->port, addrs, + space_left, &bytes_copied); if (cnt < 0) { err = cnt; - goto unlock; + goto error; } goto copy_getaddrs; } } + buf = addrs; list_for_each(pos, &bp->address_list) { addr = list_entry(pos, struct sctp_sockaddr_entry, list); memcpy(&temp, &addr->a, sizeof(temp)); sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp); addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; - if(space_left < addrlen) - return -ENOMEM; /*fixme: right error?*/ - if (copy_to_user(to, &temp, addrlen)) { - err = -EFAULT; - goto unlock; + if (space_left < addrlen) { + err = -ENOMEM; /*fixme: right error?*/ + goto error; } - to += addrlen; + memcpy(buf, &temp, addrlen); + buf += addrlen; + bytes_copied += addrlen; cnt ++; space_left -= addrlen; } copy_getaddrs: + sctp_read_unlock(addr_lock); + + if (copy_to_user(to, addrs, bytes_copied)) { + err = -EFAULT; + goto error; + } if (put_user(cnt, &((struct sctp_getaddrs __user *)optval)->addr_num)) return -EFAULT; - bytes_copied = ((char __user *)to) - optval; if (put_user(bytes_copied, optlen)) return -EFAULT; -unlock: - sctp_read_unlock(addr_lock); +error: + kfree(addrs); return err; } @@ -4961,7 +4989,12 @@ int sctp_inet_listen(struct socket *sock, int backlog) /* Allocate HMAC for generating cookie. */ if (sctp_hmac_alg) { tfm = crypto_alloc_hash(sctp_hmac_alg, 0, CRYPTO_ALG_ASYNC); - if (!tfm) { + if (IS_ERR(tfm)) { + if (net_ratelimit()) { + printk(KERN_INFO + "SCTP: failed to load transform for %s: %ld\n", + sctp_hmac_alg, PTR_ERR(tfm)); + } err = -ENOSYS; goto out; } diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index db298b5..c678f5f 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c @@ -1196,13 +1196,7 @@ svcauth_gss_wrap_resp_integ(struct svc_rqst *rqstp) if (xdr_buf_subsegment(resbuf, &integ_buf, integ_offset, integ_len)) BUG(); - if (resbuf->page_len == 0 - && resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE - < PAGE_SIZE) { - BUG_ON(resbuf->tail[0].iov_len); - /* Use head for everything */ - resv = &resbuf->head[0]; - } else if (resbuf->tail[0].iov_base == NULL) { + if (resbuf->tail[0].iov_base == NULL) { if (resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE > PAGE_SIZE) goto out_err; resbuf->tail[0].iov_base = resbuf->head[0].iov_base diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 785c3e3..ba89293 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -782,6 +782,10 @@ struct xfrm_policy *xfrm_policy_byid(u8 type, int dir, u32 id, int delete, struct hlist_head *chain; struct hlist_node *entry; + *err = -ENOENT; + if (xfrm_policy_id2dir(id) != dir) + return NULL; + *err = 0; write_lock_bh(&xfrm_policy_lock); chain = xfrm_policy_byidx + idx_hash(id); diff --git a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c index 6bc7e7c..8912c0f 100644 --- a/scripts/basic/fixdep.c +++ b/scripts/basic/fixdep.c @@ -249,6 +249,8 @@ void parse_config_file(char *map, size_t len) found: if (!memcmp(q - 7, "_MODULE", 7)) q -= 7; + if( (q-p-7) < 0 ) + continue; use_config(p+7, q-p-7); } } diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index c94291b..a6f8992 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -1751,6 +1751,7 @@ static int stac92xx_resume(struct hda_codec *codec) stac92xx_init(codec); stac92xx_set_config_regs(codec); + snd_hda_resume_ctls(codec, spec->mixer); for (i = 0; i < spec->num_mixers; i++) snd_hda_resume_ctls(codec, spec->mixers[i]); if (spec->multiout.dig_out_nid)