From: Chris Wright <chrisw@sous-sol.org>
To: linux-kernel@vger.kernel.org,
Andrew Morton <akpm@linux-foundation.org>,
torvalds@linux-foundation.org, stable@kernel.org
Subject: Re: Linux 2.6.21.2
Date: Wed, 23 May 2007 15:13:26 -0700 [thread overview]
Message-ID: <20070523221326.GV3429@sequoia.sous-sol.org> (raw)
In-Reply-To: <20070523221224.GU3429@sequoia.sous-sol.org>
diff --git a/Makefile b/Makefile
index 58c08d1..22839cb 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 21
-EXTRAVERSION = .1
+EXTRAVERSION = .2
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/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/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/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_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 3205ec9..794b930 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -652,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)
@@ -678,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/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_left<addrlen)
+ if (space_left < addrlen)
return -ENOMEM;
- if (copy_to_user(*to, &temp, addrlen))
- return -EFAULT;
+ memcpy(to, &temp, addrlen);
- *to += addrlen;
+ to += addrlen;
cnt ++;
space_left -= addrlen;
+ bytes_copied += addrlen;
}
return cnt;
@@ -4014,6 +4015,9 @@ static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len,
int addrlen;
rwlock_t *addr_lock;
int err = 0;
+ void *addrs;
+ void *buf;
+ int bytes_copied = 0;
if (len != sizeof(struct sctp_getaddrs_old))
return -EINVAL;
@@ -4041,6 +4045,15 @@ static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len,
to = getaddrs.addrs;
+ /* Allocate space for a local instance of packed array to hold all
+ * the data. We store addresses here first and then put write them
+ * to the user in one shot.
+ */
+ addrs = kmalloc(sizeof(union sctp_addr) * getaddrs.addr_num,
+ GFP_KERNEL);
+ if (!addrs)
+ return -ENOMEM;
+
sctp_read_lock(addr_lock);
/* If the endpoint is bound to 0.0.0.0 or ::0, get the valid
@@ -4050,38 +4063,42 @@ static int sctp_getsockopt_local_addrs_old(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_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)
prev parent reply other threads:[~2007-05-23 22:15 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-05-23 22:12 Linux 2.6.21.2 Chris Wright
2007-05-23 22:13 ` Chris Wright [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20070523221326.GV3429@sequoia.sous-sol.org \
--to=chrisw@sous-sol.org \
--cc=akpm@linux-foundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=stable@kernel.org \
--cc=torvalds@linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.