Re: Linux 2.6.21.5

From: Chris Wright
Date: Mon Jun 11 2007 - 16:16:10 EST


diff --git a/Documentation/hrtimer/timer_stats.txt b/Documentation/hrtimer/timer_stats.txt
index 27f782e..22b0814 100644
--- a/Documentation/hrtimer/timer_stats.txt
+++ b/Documentation/hrtimer/timer_stats.txt
@@ -2,9 +2,10 @@ timer_stats - timer usage statistics
------------------------------------

timer_stats is a debugging facility to make the timer (ab)usage in a Linux
-system visible to kernel and userspace developers. It is not intended for
-production usage as it adds significant overhead to the (hr)timer code and the
-(hr)timer data structures.
+system visible to kernel and userspace developers. If enabled in the config
+but not used it has almost zero runtime overhead, and a relatively small
+data structure overhead. Even if collection is enabled runtime all the
+locking is per-CPU and lookup is hashed.

timer_stats should be used by kernel and userspace developers to verify that
their code does not make unduly use of timers. This helps to avoid unnecessary
diff --git a/Makefile b/Makefile
index e5c5531..e7c083b 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 21
-EXTRAVERSION = .4
+EXTRAVERSION = .5
NAME = Nocturnal Monster Puppy

# *DOCUMENTATION*
diff --git a/arch/i386/kernel/hpet.c b/arch/i386/kernel/hpet.c
index 17d7345..cbb4751 100644
--- a/arch/i386/kernel/hpet.c
+++ b/arch/i386/kernel/hpet.c
@@ -226,7 +226,8 @@ int __init hpet_enable(void)
{
unsigned long id;
uint64_t hpet_freq;
- u64 tmp;
+ u64 tmp, start, now;
+ cycle_t t1;

if (!is_hpet_capable())
return 0;
@@ -273,6 +274,27 @@ int __init hpet_enable(void)
/* Start the counter */
hpet_start_counter();

+ /* Verify whether hpet counter works */
+ t1 = read_hpet();
+ rdtscll(start);
+
+ /*
+ * We don't know the TSC frequency yet, but waiting for
+ * 200000 TSC cycles is safe:
+ * 4 GHz == 50us
+ * 1 GHz == 200us
+ */
+ do {
+ rep_nop();
+ rdtscll(now);
+ } while ((now - start) < 200000UL);
+
+ if (t1 == read_hpet()) {
+ printk(KERN_WARNING
+ "HPET counter not counting. HPET disabled\n");
+ goto out_nohpet;
+ }
+
/* Initialize and register HPET clocksource
*
* hpet period is in femto seconds per cycle
diff --git a/arch/i386/kernel/reboot.c b/arch/i386/kernel/reboot.c
index 3514b41..e33f51a 100644
--- a/arch/i386/kernel/reboot.c
+++ b/arch/i386/kernel/reboot.c
@@ -88,6 +88,14 @@ static int __init set_bios_reboot(struct dmi_system_id *d)
}

static struct dmi_system_id __initdata reboot_dmi_table[] = {
+ { /* Handle problems with rebooting on Dell E520's */
+ .callback = set_bios_reboot,
+ .ident = "Dell E520",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Dell DM061"),
+ },
+ },
{ /* Handle problems with rebooting on Dell 1300's */
.callback = set_bios_reboot,
.ident = "Dell PowerEdge 1300",
diff --git a/arch/i386/oprofile/nmi_int.c b/arch/i386/oprofile/nmi_int.c
index 8fda7be..bd00876 100644
--- a/arch/i386/oprofile/nmi_int.c
+++ b/arch/i386/oprofile/nmi_int.c
@@ -131,7 +131,6 @@ static void nmi_save_registers(void * dummy)
{
int cpu = smp_processor_id();
struct op_msrs * msrs = &cpu_msrs[cpu];
- model->fill_in_addresses(msrs);
nmi_cpu_save_registers(msrs);
}

@@ -155,7 +154,7 @@ static int allocate_msrs(void)
size_t counters_size = sizeof(struct op_msr) * model->num_counters;

int i;
- for_each_online_cpu(i) {
+ for_each_possible_cpu(i) {
cpu_msrs[i].counters = kmalloc(counters_size, GFP_KERNEL);
if (!cpu_msrs[i].counters) {
success = 0;
@@ -195,6 +194,7 @@ static struct notifier_block profile_exceptions_nb = {
static int nmi_setup(void)
{
int err=0;
+ int cpu;

if (!allocate_msrs())
return -ENOMEM;
@@ -207,6 +207,19 @@ static int nmi_setup(void)
/* We need to serialize save and setup for HT because the subset
* of msrs are distinct for save and setup operations
*/
+
+ /* Assume saved/restored counters are the same on all CPUs */
+ model->fill_in_addresses(&cpu_msrs[0]);
+ for_each_possible_cpu (cpu) {
+ if (cpu != 0) {
+ memcpy(cpu_msrs[cpu].counters, cpu_msrs[0].counters,
+ sizeof(struct op_msr) * model->num_counters);
+
+ memcpy(cpu_msrs[cpu].controls, cpu_msrs[0].controls,
+ sizeof(struct op_msr) * model->num_controls);
+ }
+
+ }
on_each_cpu(nmi_save_registers, NULL, 0, 1);
on_each_cpu(nmi_cpu_setup, NULL, 0, 1);
nmi_enabled = 1;
diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S
index baea10a..06459ae 100644
--- a/arch/sparc64/kernel/head.S
+++ b/arch/sparc64/kernel/head.S
@@ -653,33 +653,54 @@ setup_tba:
restore
sparc64_boot_end:

-#include "ktlb.S"
-#include "tsb.S"
#include "etrap.S"
#include "rtrap.S"
#include "winfixup.S"
#include "entry.S"
#include "sun4v_tlb_miss.S"
#include "sun4v_ivec.S"
+#include "ktlb.S"
+#include "tsb.S"

/*
* The following skip makes sure the trap table in ttable.S is aligned
* on a 32K boundary as required by the v9 specs for TBA register.
*
* We align to a 32K boundary, then we have the 32K kernel TSB,
- * then the 32K aligned trap table.
+ * the 64K kernel 4MB TSB, and then the 32K aligned trap table.
*/
1:
.skip 0x4000 + _start - 1b

+! 0x0000000000408000
+
.globl swapper_tsb
swapper_tsb:
.skip (32 * 1024)

-! 0x0000000000408000
+ .globl swapper_4m_tsb
+swapper_4m_tsb:
+ .skip (64 * 1024)
+
+! 0x0000000000420000

+ /* Some care needs to be exercised if you try to move the
+ * location of the trap table relative to other things. For
+ * one thing there are br* instructions in some of the
+ * trap table entires which branch back to code in ktlb.S
+ * Those instructions can only handle a signed 16-bit
+ * displacement.
+ *
+ * There is a binutils bug (bugzilla #4558) which causes
+ * the relocation overflow checks for such instructions to
+ * not be done correctly. So bintuils will not notice the
+ * error and will instead write junk into the relocation and
+ * you'll have an unbootable kernel.
+ */
#include "ttable.S"

+! 0x0000000000428000
+
#include "systbls.S"

.data
diff --git a/arch/sparc64/kernel/itlb_miss.S b/arch/sparc64/kernel/itlb_miss.S
index ad46e20..5a8377b 100644
--- a/arch/sparc64/kernel/itlb_miss.S
+++ b/arch/sparc64/kernel/itlb_miss.S
@@ -11,12 +11,12 @@
/* ITLB ** ICACHE line 2: TSB compare and TLB load */
bne,pn %xcc, tsb_miss_itlb ! Miss
mov FAULT_CODE_ITLB, %g3
- andcc %g5, _PAGE_EXEC_4U, %g0 ! Executable?
+ sethi %hi(_PAGE_EXEC_4U), %g4
+ andcc %g5, %g4, %g0 ! Executable?
be,pn %xcc, tsb_do_fault
nop ! Delay slot, fill me
stxa %g5, [%g0] ASI_ITLB_DATA_IN ! Load TLB
retry ! Trap done
- nop

/* ITLB ** ICACHE line 3: */
nop
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c
index ec22cd6..f6fd073 100644
--- a/arch/sparc64/kernel/pci_sun4v.c
+++ b/arch/sparc64/kernel/pci_sun4v.c
@@ -12,6 +12,7 @@
#include <linux/percpu.h>
#include <linux/irq.h>
#include <linux/msi.h>
+#include <linux/log2.h>

#include <asm/pbm.h>
#include <asm/iommu.h>
@@ -996,9 +997,8 @@ static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
{
struct pci_iommu *iommu = pbm->iommu;
struct property *prop;
- unsigned long num_tsb_entries, sz;
+ unsigned long num_tsb_entries, sz, tsbsize;
u32 vdma[2], dma_mask, dma_offset;
- int tsbsize;

prop = of_find_property(pbm->prom_node, "virtual-dma", NULL);
if (prop) {
@@ -1012,31 +1012,15 @@ static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
vdma[1] = 0x80000000;
}

- dma_mask = vdma[0];
- switch (vdma[1]) {
- case 0x20000000:
- dma_mask |= 0x1fffffff;
- tsbsize = 64;
- break;
-
- case 0x40000000:
- dma_mask |= 0x3fffffff;
- tsbsize = 128;
- break;
-
- case 0x80000000:
- dma_mask |= 0x7fffffff;
- tsbsize = 256;
- break;
-
- default:
- prom_printf("PCI-SUN4V: strange virtual-dma size.\n");
- prom_halt();
+ if ((vdma[0] | vdma[1]) & ~IO_PAGE_MASK) {
+ prom_printf("PCI-SUN4V: strange virtual-dma[%08x:%08x].\n",
+ vdma[0], vdma[1]);
+ prom_halt();
};

- tsbsize *= (8 * 1024);
-
- num_tsb_entries = tsbsize / sizeof(iopte_t);
+ dma_mask = (roundup_pow_of_two(vdma[1]) - 1UL);
+ num_tsb_entries = vdma[1] / IO_PAGE_SIZE;
+ tsbsize = num_tsb_entries * sizeof(iopte_t);

dma_offset = vdma[0];

@@ -1047,7 +1031,7 @@ static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
iommu->dma_addr_mask = dma_mask;

/* Allocate and initialize the free area map. */
- sz = num_tsb_entries / 8;
+ sz = (num_tsb_entries + 7) / 8;
sz = (sz + 7UL) & ~7UL;
iommu->arena.map = kzalloc(sz, GFP_KERNEL);
if (!iommu->arena.map) {
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
index f146071..c034d12 100644
--- a/arch/sparc64/mm/init.c
+++ b/arch/sparc64/mm/init.c
@@ -60,8 +60,11 @@ unsigned long kern_linear_pte_xor[2] __read_mostly;
unsigned long kpte_linear_bitmap[KPTE_BITMAP_BYTES / sizeof(unsigned long)];

#ifndef CONFIG_DEBUG_PAGEALLOC
-/* A special kernel TSB for 4MB and 256MB linear mappings. */
-struct tsb swapper_4m_tsb[KERNEL_TSB4M_NENTRIES];
+/* A special kernel TSB for 4MB and 256MB linear mappings.
+ * Space is allocated for this right after the trap table
+ * in arch/sparc64/kernel/head.S
+ */
+extern struct tsb swapper_4m_tsb[KERNEL_TSB4M_NENTRIES];
#endif

#define MAX_BANKS 32
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
index 5178eba..c2502fe 100644
--- a/arch/um/os-Linux/start_up.c
+++ b/arch/um/os-Linux/start_up.c
@@ -144,9 +144,7 @@ static int stop_ptraced_child(int pid, void *stack, int exitcode,
int exit_with = WEXITSTATUS(status);
if (exit_with == 2)
non_fatal("check_ptrace : child exited with status 2. "
- "Serious trouble happening! Try updating "
- "your host skas patch!\nDisabling SYSEMU "
- "support.");
+ "\nDisabling SYSEMU support.\n");
non_fatal("check_ptrace : child exited with exitcode %d, while "
"expecting %d; status 0x%x\n", exit_with,
exitcode, status);
@@ -209,6 +207,7 @@ __uml_setup("nosysemu", nosysemu_cmd_param,
static void __init check_sysemu(void)
{
void *stack;
+ unsigned long regs[MAX_REG_NR];
int pid, n, status, count=0;

non_fatal("Checking syscall emulation patch for ptrace...");
@@ -225,11 +224,20 @@ static void __init check_sysemu(void)
fatal("check_sysemu : expected SIGTRAP, got status = %d",
status);

- n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET,
- os_getpid());
- if(n < 0)
- fatal_perror("check_sysemu : failed to modify system call "
- "return");
+ if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
+ fatal_perror("check_sysemu : PTRACE_GETREGS failed");
+ if(PT_SYSCALL_NR(regs) != __NR_getpid){
+ non_fatal("check_sysemu got system call number %d, "
+ "expected %d...", PT_SYSCALL_NR(regs), __NR_getpid);
+ goto fail;
+ }
+
+ n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, os_getpid());
+ if(n < 0){
+ non_fatal("check_sysemu : failed to modify system call "
+ "return");
+ goto fail;
+ }

if (stop_ptraced_child(pid, stack, 0, 0) < 0)
goto fail_stopped;
diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c
index ec31534..6fd126a 100644
--- a/arch/x86_64/mm/init.c
+++ b/arch/x86_64/mm/init.c
@@ -776,3 +776,9 @@ int in_gate_area_no_task(unsigned long addr)
{
return (addr >= VSYSCALL_START) && (addr < VSYSCALL_END);
}
+
+void *alloc_bootmem_high_node(pg_data_t *pgdat, unsigned long size)
+{
+ return __alloc_bootmem_core(pgdat->bdata, size,
+ SMP_CACHE_BYTES, (4UL*1024*1024*1024), 0);
+}
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index 8fcd6a1..a2efae8 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -40,19 +40,19 @@ static nodemask_t nodes_found_map = NODE_MASK_NONE;
#define NID_INVAL -1

/* maps to convert between proximity domain and logical node ID */
-int __cpuinitdata pxm_to_node_map[MAX_PXM_DOMAINS]
+static int pxm_to_node_map[MAX_PXM_DOMAINS]
= { [0 ... MAX_PXM_DOMAINS - 1] = NID_INVAL };
-int __cpuinitdata node_to_pxm_map[MAX_NUMNODES]
+static int node_to_pxm_map[MAX_NUMNODES]
= { [0 ... MAX_NUMNODES - 1] = PXM_INVAL };

-int __cpuinit pxm_to_node(int pxm)
+int pxm_to_node(int pxm)
{
if (pxm < 0)
return NID_INVAL;
return pxm_to_node_map[pxm];
}

-int __cpuinit node_to_pxm(int node)
+int node_to_pxm(int node)
{
if (node < 0)
return PXM_INVAL;
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index fd27227..efd87d3 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -170,6 +170,7 @@ enum {
AHCI_FLAG_IGN_IRQ_IF_ERR = (1 << 25), /* ignore IRQ_IF_ERR */
AHCI_FLAG_HONOR_PI = (1 << 26), /* honor PORTS_IMPL */
AHCI_FLAG_IGN_SERR_INTERNAL = (1 << 27), /* ignore SERR_INTERNAL */
+ AHCI_FLAG_32BIT_ONLY = (1 << 28), /* force 32bit */
};

struct ahci_cmd_hdr {
@@ -370,7 +371,8 @@ static const struct ata_port_info ahci_port_info[] = {
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
ATA_FLAG_SKIP_D2H_BSY |
- AHCI_FLAG_IGN_SERR_INTERNAL,
+ AHCI_FLAG_IGN_SERR_INTERNAL |
+ AHCI_FLAG_32BIT_ONLY,
.pio_mask = 0x1f, /* pio0-4 */
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
.port_ops = &ahci_ops,
@@ -1579,6 +1581,12 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent)
probe_ent->n_ports = cap_n_ports;

using_dac = hpriv->cap & HOST_CAP_64;
+ if (using_dac && (probe_ent->port_flags & AHCI_FLAG_32BIT_ONLY)) {
+ dev_printk(KERN_INFO, &pdev->dev,
+ "controller can't do 64bit DMA, forcing 32bit\n");
+ using_dac = 0;
+ }
+
if (using_dac &&
!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 65a725c..e0da175 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -3405,13 +3405,39 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
return -1;
}

-static void cciss_remove_one(struct pci_dev *pdev)
+static void cciss_shutdown(struct pci_dev *pdev)
{
ctlr_info_t *tmp_ptr;
- int i, j;
+ int i;
char flush_buf[4];
int return_code;

+ tmp_ptr = pci_get_drvdata(pdev);
+ if (tmp_ptr == NULL)
+ return;
+ i = tmp_ptr->ctlr;
+ if (hba[i] == NULL)
+ return;
+
+ /* Turn board interrupts off and send the flush cache command */
+ /* sendcmd will turn off interrupt, and send the flush...
+ * To write all data in the battery backed cache to disks */
+ memset(flush_buf, 0, 4);
+ return_code = sendcmd(CCISS_CACHE_FLUSH, i, flush_buf, 4, 0, 0, 0, NULL,
+ TYPE_CMD);
+ if (return_code == IO_OK) {
+ printk(KERN_INFO "Completed flushing cache on controller %d\n", i);
+ } else {
+ printk(KERN_WARNING "Error flushing cache on controller %d\n", i);
+ }
+ free_irq(hba[i]->intr[2], hba[i]);
+}
+
+static void __devexit cciss_remove_one(struct pci_dev *pdev)
+{
+ ctlr_info_t *tmp_ptr;
+ int i, j;
+
if (pci_get_drvdata(pdev) == NULL) {
printk(KERN_ERR "cciss: Unable to remove device \n");
return;
@@ -3442,18 +3468,7 @@ static void cciss_remove_one(struct pci_dev *pdev)

cciss_unregister_scsi(i); /* unhook from SCSI subsystem */

- /* Turn board interrupts off and send the flush cache command */
- /* sendcmd will turn off interrupt, and send the flush...
- * To write all data in the battery backed cache to disks */
- memset(flush_buf, 0, 4);
- return_code = sendcmd(CCISS_CACHE_FLUSH, i, flush_buf, 4, 0, 0, 0, NULL,
- TYPE_CMD);
- if (return_code == IO_OK) {
- printk(KERN_INFO "Completed flushing cache on controller %d\n", i);
- } else {
- printk(KERN_WARNING "Error flushing cache on controller %d\n", i);
- }
- free_irq(hba[i]->intr[2], hba[i]);
+ cciss_shutdown(pdev);

#ifdef CONFIG_PCI_MSI
if (hba[i]->msix_vector)
@@ -3486,7 +3501,7 @@ static struct pci_driver cciss_pci_driver = {
.probe = cciss_init_one,
.remove = __devexit_p(cciss_remove_one),
.id_table = cciss_pci_device_id, /* id_table */
- .shutdown = cciss_remove_one,
+ .shutdown = cciss_shutdown,
};

/*
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index 16dc5d1..ab39503 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -1103,6 +1103,7 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip,

if (data & info->ignore_status_mask) {
info->icount.rx++;
+ spin_unlock(&cinfo->card_lock);
return;
}
if (tty_buffer_request_room(tty, 1)) {
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index 6ac3ca4..5a6c649 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -1191,6 +1191,7 @@ static int job_control(struct tty_struct *tty, struct file *file)
is_current_pgrp_orphaned())
return -EIO;
kill_pgrp(task_pgrp(current), SIGTTIN, 1);
+ set_thread_flag(TIF_SIGPENDING);
return -ERESTARTSYS;
}
}
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 7a32df5..2000120 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -1121,7 +1121,8 @@ int tty_check_change(struct tty_struct * tty)
return 0;
if (is_current_pgrp_orphaned())
return -EIO;
- (void) kill_pgrp(task_pgrp(current), SIGTTOU, 1);
+ kill_pgrp(task_pgrp(current), SIGTTOU, 1);
+ set_thread_flag(TIF_SIGPENDING);
return -ERESTARTSYS;
}

diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
index ab6fa27..cf9d344 100644
--- a/drivers/ide/pci/hpt366.c
+++ b/drivers/ide/pci/hpt366.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/hpt366.c Version 1.02 Apr 18, 2007
+ * linux/drivers/ide/pci/hpt366.c Version 1.03 May 4, 2007
*
* Copyright (C) 1999-2003 Andre Hedrick <andre@xxxxxxxxxxxxx>
* Portions Copyright (C) 2001 Sun Microsystems, Inc.
@@ -1527,7 +1527,12 @@ static int __devinit init_setup_hpt366(struct pci_dev *dev, ide_pci_device_t *d)
if (rev > 2)
goto init_single;

+ /*
+ * HPT36x chips are single channel and
+ * do not seem to have the channel enable bit...
+ */
d->channels = 1;
+ d->enablebits[0].reg = 0;

if ((dev2 = pci_get_slot(dev->bus, dev->devfn + 1)) != NULL) {
u8 pin1 = 0, pin2 = 0;
diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c
index 03e44b3..6c81951 100644
--- a/drivers/ieee1394/eth1394.c
+++ b/drivers/ieee1394/eth1394.c
@@ -584,10 +584,9 @@ static void ether1394_add_host (struct hpsb_host *host)
}

SET_MODULE_OWNER(dev);
-#if 0
- /* FIXME - Is this the correct parent device anyway? */
- SET_NETDEV_DEV(dev, &host->device);
-#endif
+
+ /* This used to be &host->device in Linux 2.6.20 and before. */
+ SET_NETDEV_DEV(dev, host->device.parent);

priv = netdev_priv(dev);

diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index db9cca3..23411ab 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -526,6 +526,33 @@ static irqreturn_t __devinit i8042_aux_test_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}

+/*
+ * i8042_toggle_aux - enables or disables AUX port on i8042 via command and
+ * verifies success by readinng CTR. Used when testing for presence of AUX
+ * port.
+ */
+static int __devinit i8042_toggle_aux(int on)
+{
+ unsigned char param;
+ int i;
+
+ if (i8042_command(&param,
+ on ? I8042_CMD_AUX_ENABLE : I8042_CMD_AUX_DISABLE))
+ return -1;
+
+ /* some chips need some time to set the I8042_CTR_AUXDIS bit */
+ for (i = 0; i < 100; i++) {
+ udelay(50);
+
+ if (i8042_command(&param, I8042_CMD_CTL_RCTR))
+ return -1;
+
+ if (!(param & I8042_CTR_AUXDIS) == on)
+ return 0;
+ }
+
+ return -1;
+}

/*
* i8042_check_aux() applies as much paranoia as it can at detecting
@@ -580,16 +607,12 @@ static int __devinit i8042_check_aux(void)
* Bit assignment test - filters out PS/2 i8042's in AT mode
*/

- if (i8042_command(&param, I8042_CMD_AUX_DISABLE))
- return -1;
- if (i8042_command(&param, I8042_CMD_CTL_RCTR) || (~param & I8042_CTR_AUXDIS)) {
+ if (i8042_toggle_aux(0)) {
printk(KERN_WARNING "Failed to disable AUX port, but continuing anyway... Is this a SiS?\n");
printk(KERN_WARNING "If AUX port is really absent please use the 'i8042.noaux' option.\n");
}

- if (i8042_command(&param, I8042_CMD_AUX_ENABLE))
- return -1;
- if (i8042_command(&param, I8042_CMD_CTL_RCTR) || (param & I8042_CTR_AUXDIS))
+ if (i8042_toggle_aux(1))
return -1;

/*
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index e61e0ef..fd563a9 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -255,19 +255,25 @@ static struct page *read_sb_page(mddev_t *mddev, long offset, unsigned long inde

}

-static int write_sb_page(mddev_t *mddev, long offset, struct page *page, int wait)
+static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait)
{
mdk_rdev_t *rdev;
struct list_head *tmp;
+ mddev_t *mddev = bitmap->mddev;

ITERATE_RDEV(mddev, rdev, tmp)
if (test_bit(In_sync, &rdev->flags)
- && !test_bit(Faulty, &rdev->flags))
+ && !test_bit(Faulty, &rdev->flags)) {
+ int size = PAGE_SIZE;
+ if (page->index == bitmap->file_pages-1)
+ size = roundup(bitmap->last_page_size,
+ bdev_hardsect_size(rdev->bdev));
md_super_write(mddev, rdev,
- (rdev->sb_offset<<1) + offset
+ (rdev->sb_offset<<1) + bitmap->offset
+ page->index * (PAGE_SIZE/512),
- PAGE_SIZE,
+ size,
page);
+ }

if (wait)
md_super_wait(mddev);
@@ -282,7 +288,7 @@ static int write_page(struct bitmap *bitmap, struct page *page, int wait)
struct buffer_head *bh;

if (bitmap->file == NULL)
- return write_sb_page(bitmap->mddev, bitmap->offset, page, wait);
+ return write_sb_page(bitmap, page, wait);

bh = page_buffers(page);

@@ -923,6 +929,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
}

bitmap->filemap[bitmap->file_pages++] = page;
+ bitmap->last_page_size = count;
}
paddr = kmap_atomic(page, KM_USER0);
if (bitmap->flags & BITMAP_HOSTENDIAN)
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index dfe3214..2c404f7 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -415,7 +415,7 @@ static int raid0_make_request (request_queue_t *q, struct bio *bio)
raid0_conf_t *conf = mddev_to_conf(mddev);
struct strip_zone *zone;
mdk_rdev_t *tmp_dev;
- unsigned long chunk;
+ sector_t chunk;
sector_t block, rsect;
const int rw = bio_data_dir(bio);

@@ -470,7 +470,6 @@ static int raid0_make_request (request_queue_t *q, struct bio *bio)

sector_div(x, zone->nb_dev);
chunk = x;
- BUG_ON(x != (sector_t)chunk);

x = block >> chunksize_bits;
tmp_dev = zone->dev[sector_div(x, zone->nb_dev)];
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c
index 464feaf..622a329 100644
--- a/drivers/media/dvb/ttpci/budget-ci.c
+++ b/drivers/media/dvb/ttpci/budget-ci.c
@@ -926,7 +926,7 @@ static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struc
band = 1;
} else if (tuner_frequency < 200000000) {
cp = 6;
- band = 2;
+ band = 1;
} else if (tuner_frequency < 290000000) {
cp = 3;
band = 2;
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index b28a915..de907d9 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -1153,13 +1153,16 @@ e1000_probe(struct pci_dev *pdev,
!e1000_check_mng_mode(&adapter->hw))
e1000_get_hw_control(adapter);

- strcpy(netdev->name, "eth%d");
- if ((err = register_netdev(netdev)))
- goto err_register;
-
/* tell the stack to leave us alone until e1000_open() is called */
netif_carrier_off(netdev);
netif_stop_queue(netdev);
+#ifdef CONFIG_E1000_NAPI
+ netif_poll_disable(netdev);
+#endif
+
+ strcpy(netdev->name, "eth%d");
+ if ((err = register_netdev(netdev)))
+ goto err_register;

DPRINTK(PROBE, INFO, "Intel(R) PRO/1000 Network Connection\n");

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 3d20115..2de13cf 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.1"
-#define DRV_MODULE_RELDATE "May 7, 2007"
+#define DRV_MODULE_VERSION "3.75.2"
+#define DRV_MODULE_RELDATE "June 5, 2007"

#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
@@ -10942,6 +10942,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
* upon subsystem IDs.
*/
if (tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 &&
!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
tp->tg3_flags |= (TG3_FLAG_USE_MI_INTERRUPT |
TG3_FLAG_USE_LINKCHG_REG);
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
index 87ee3ee..e0e936a 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.c
+++ b/drivers/net/wireless/zd1211rw/zd_chip.c
@@ -67,11 +67,12 @@ static int scnprint_id(struct zd_chip *chip, char *buffer, size_t size)
i += scnprint_mac_oui(chip->e2p_mac, buffer+i, size-i);
i += scnprintf(buffer+i, size-i, " ");
i += zd_rf_scnprint_id(&chip->rf, buffer+i, size-i);
- i += scnprintf(buffer+i, size-i, " pa%1x %c%c%c%c", chip->pa_type,
+ i += scnprintf(buffer+i, size-i, " pa%1x %c%c%c%c%c", chip->pa_type,
chip->patch_cck_gain ? 'g' : '-',
chip->patch_cr157 ? '7' : '-',
chip->patch_6m_band_edge ? '6' : '-',
- chip->new_phy_layout ? 'N' : '-');
+ chip->new_phy_layout ? 'N' : '-',
+ chip->al2230s_bit ? 'S' : '-');
return i;
}

diff --git a/drivers/net/wireless/zd1211rw/zd_rf.c b/drivers/net/wireless/zd1211rw/zd_rf.c
index f50cff3..e6d604b 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf.c
@@ -34,7 +34,7 @@ static const char *rfs[] = {
[AL2210_RF] = "AL2210_RF",
[MAXIM_NEW_RF] = "MAXIM_NEW_RF",
[UW2453_RF] = "UW2453_RF",
- [AL2230S_RF] = "AL2230S_RF",
+ [UNKNOWN_A_RF] = "UNKNOWN_A_RF",
[RALINK_RF] = "RALINK_RF",
[INTERSIL_RF] = "INTERSIL_RF",
[RF2959_RF] = "RF2959_RF",
diff --git a/drivers/net/wireless/zd1211rw/zd_rf.h b/drivers/net/wireless/zd1211rw/zd_rf.h
index a57732e..ee8ac3a 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf.h
+++ b/drivers/net/wireless/zd1211rw/zd_rf.h
@@ -26,7 +26,7 @@
#define AL2210_RF 0x7
#define MAXIM_NEW_RF 0x8
#define UW2453_RF 0x9
-#define AL2230S_RF 0xa
+#define UNKNOWN_A_RF 0xa
#define RALINK_RF 0xb
#define INTERSIL_RF 0xc
#define RF2959_RF 0xd
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
index 5235a78..85a9ad2 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
@@ -59,6 +59,18 @@ static const struct zd_ioreq16 zd1211b_ioreqs_shared_1[] = {
{ CR240, 0x57 }, { CR9, 0xe0 },
};

+static const struct zd_ioreq16 ioreqs_init_al2230s[] = {
+ { CR47, 0x1e }, /* MARK_002 */
+ { CR106, 0x22 },
+ { CR107, 0x2a }, /* MARK_002 */
+ { CR109, 0x13 }, /* MARK_002 */
+ { CR118, 0xf8 }, /* MARK_002 */
+ { CR119, 0x12 }, { CR122, 0xe0 },
+ { CR128, 0x10 }, /* MARK_001 from 0xe->0x10 */
+ { CR129, 0x0e }, /* MARK_001 from 0xd->0x0e */
+ { CR130, 0x10 }, /* MARK_001 from 0xb->0x0d */
+};
+
static int zd1211b_al2230_finalize_rf(struct zd_chip *chip)
{
int r;
@@ -90,7 +102,7 @@ static int zd1211_al2230_init_hw(struct zd_rf *rf)
int r;
struct zd_chip *chip = zd_rf_to_chip(rf);

- static const struct zd_ioreq16 ioreqs[] = {
+ static const struct zd_ioreq16 ioreqs_init[] = {
{ CR15, 0x20 }, { CR23, 0x40 }, { CR24, 0x20 },
{ CR26, 0x11 }, { CR28, 0x3e }, { CR29, 0x00 },
{ CR44, 0x33 }, { CR106, 0x2a }, { CR107, 0x1a },
@@ -117,10 +129,9 @@ static int zd1211_al2230_init_hw(struct zd_rf *rf)
{ CR119, 0x10 }, { CR120, 0x4f }, { CR121, 0x77 },
{ CR122, 0xe0 }, { CR137, 0x88 }, { CR252, 0xff },
{ CR253, 0xff },
+ };

- /* These following happen separately in the vendor driver */
- { },
-
+ static const struct zd_ioreq16 ioreqs_pll[] = {
/* shdnb(PLL_ON)=0 */
{ CR251, 0x2f },
/* shdnb(PLL_ON)=1 */
@@ -128,7 +139,7 @@ static int zd1211_al2230_init_hw(struct zd_rf *rf)
{ CR138, 0x28 }, { CR203, 0x06 },
};

- static const u32 rv[] = {
+ static const u32 rv1[] = {
/* Channel 1 */
0x03f790,
0x033331,
@@ -137,6 +148,9 @@ static int zd1211_al2230_init_hw(struct zd_rf *rf)
0x0b3331,
0x03b812,
0x00fff3,
+ };
+
+ static const u32 rv2[] = {
0x000da4,
0x0f4dc5, /* fix freq shift, 0x04edc5 */
0x0805b6,
@@ -148,8 +162,9 @@ static int zd1211_al2230_init_hw(struct zd_rf *rf)
0x0bdffc,
0x00000d,
0x00500f,
+ };

- /* These writes happen separately in the vendor driver */
+ static const u32 rv3[] = {
0x00d00f,
0x004c0f,
0x00540f,
@@ -157,11 +172,38 @@ static int zd1211_al2230_init_hw(struct zd_rf *rf)
0x00500f,
};

- r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+ r = zd_iowrite16a_locked(chip, ioreqs_init, ARRAY_SIZE(ioreqs_init));
if (r)
return r;

- r = zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS);
+ if (chip->al2230s_bit) {
+ r = zd_iowrite16a_locked(chip, ioreqs_init_al2230s,
+ ARRAY_SIZE(ioreqs_init_al2230s));
+ if (r)
+ return r;
+ }
+
+ r = zd_rfwritev_locked(chip, rv1, ARRAY_SIZE(rv1), RF_RV_BITS);
+ if (r)
+ return r;
+
+ /* improve band edge for AL2230S */
+ if (chip->al2230s_bit)
+ r = zd_rfwrite_locked(chip, 0x000824, RF_RV_BITS);
+ else
+ r = zd_rfwrite_locked(chip, 0x0005a4, RF_RV_BITS);
+ if (r)
+ return r;
+
+ r = zd_rfwritev_locked(chip, rv2, ARRAY_SIZE(rv2), RF_RV_BITS);
+ if (r)
+ return r;
+
+ r = zd_iowrite16a_locked(chip, ioreqs_pll, ARRAY_SIZE(ioreqs_pll));
+ if (r)
+ return r;
+
+ r = zd_rfwritev_locked(chip, rv3, ARRAY_SIZE(rv3), RF_RV_BITS);
if (r)
return r;

@@ -227,7 +269,9 @@ static int zd1211b_al2230_init_hw(struct zd_rf *rf)
0x481dc0,
0xcfff00,
0x25a000,
+ };

+ static const u32 rv2[] = {
/* To improve AL2230 yield, improve phase noise, 4713 */
0x25a000,
0xa3b2f0,
@@ -250,7 +294,7 @@ static int zd1211b_al2230_init_hw(struct zd_rf *rf)
{ CR251, 0x7f }, /* shdnb(PLL_ON)=1 */
};

- static const u32 rv2[] = {
+ static const u32 rv3[] = {
/* To improve AL2230 yield, 4713 */
0xf01b00,
0xf01e00,
@@ -269,18 +313,37 @@ static int zd1211b_al2230_init_hw(struct zd_rf *rf)
r = zd_iowrite16a_locked(chip, ioreqs1, ARRAY_SIZE(ioreqs1));
if (r)
return r;
+
+ if (chip->al2230s_bit) {
+ r = zd_iowrite16a_locked(chip, ioreqs_init_al2230s,
+ ARRAY_SIZE(ioreqs_init_al2230s));
+ if (r)
+ return r;
+ }
+
r = zd_rfwritev_cr_locked(chip, zd1211b_al2230_table[0], 3);
if (r)
return r;
r = zd_rfwritev_cr_locked(chip, rv1, ARRAY_SIZE(rv1));
if (r)
return r;
- r = zd_iowrite16a_locked(chip, ioreqs2, ARRAY_SIZE(ioreqs2));
+
+ if (chip->al2230s_bit)
+ r = zd_rfwrite_locked(chip, 0x241000, RF_RV_BITS);
+ else
+ r = zd_rfwrite_locked(chip, 0x25a000, RF_RV_BITS);
if (r)
return r;
+
r = zd_rfwritev_cr_locked(chip, rv2, ARRAY_SIZE(rv2));
if (r)
return r;
+ r = zd_iowrite16a_locked(chip, ioreqs2, ARRAY_SIZE(ioreqs2));
+ if (r)
+ return r;
+ r = zd_rfwritev_cr_locked(chip, rv3, ARRAY_SIZE(rv3));
+ if (r)
+ return r;
r = zd_iowrite16a_locked(chip, ioreqs3, ARRAY_SIZE(ioreqs3));
if (r)
return r;
@@ -358,12 +421,6 @@ int zd_rf_init_al2230(struct zd_rf *rf)
{
struct zd_chip *chip = zd_rf_to_chip(rf);

- if (chip->al2230s_bit) {
- dev_err(zd_chip_dev(chip), "AL2230S devices are not yet "
- "supported by this driver.\n");
- return -ENODEV;
- }
-
rf->switch_radio_off = al2230_switch_radio_off;
if (chip->is_zd1211b) {
rf->init_hw = zd1211b_al2230_init_hw;
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 5af9125..e2d81af 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -1751,6 +1751,7 @@ static void __init quirk_disable_all_msi(struct pci_dev *dev)
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);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3351, 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/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index 39ecd0d..1eca9cd 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -1840,6 +1840,7 @@ struct aac_driver_ident* aac_get_driver_ident(int devtype);
int aac_get_adapter_info(struct aac_dev* dev);
int aac_send_shutdown(struct aac_dev *dev);
int aac_probe_container(struct aac_dev *dev, int cid);
+int aac_rx_deliver_producer(struct fib * fib);
extern int numacb;
extern int acbsize;
extern char aac_driver_version[];
diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c
index d242e26..4431a5d 100644
--- a/drivers/scsi/aacraid/rx.c
+++ b/drivers/scsi/aacraid/rx.c
@@ -378,7 +378,7 @@ static int aac_rx_check_health(struct aac_dev *dev)
*
* Will send a fib, returning 0 if successful.
*/
-static int aac_rx_deliver_producer(struct fib * fib)
+int aac_rx_deliver_producer(struct fib * fib)
{
struct aac_dev *dev = fib->dev;
struct aac_queue *q = &dev->queues->queue[AdapNormCmdQueue];
diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c
index 6f1a178..06744f0 100644
--- a/drivers/scsi/aacraid/sa.c
+++ b/drivers/scsi/aacraid/sa.c
@@ -5,7 +5,7 @@
* based on the old aacraid driver that is..
* Adaptec aacraid device driver for Linux.
*
- * Copyright (c) 2000 Adaptec, Inc. (aacraid@xxxxxxxxxxx)
+ * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@xxxxxxxxxxx)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -368,6 +368,7 @@ int aac_sa_init(struct aac_dev *dev)
dev->a_ops.adapter_sync_cmd = sa_sync_cmd;
dev->a_ops.adapter_check_health = aac_sa_check_health;
dev->a_ops.adapter_intr = aac_sa_intr;
+ dev->a_ops.adapter_deliver = aac_rx_deliver_producer;
dev->a_ops.adapter_ioremap = aac_sa_ioremap;

/*
diff --git a/drivers/serial/suncore.c b/drivers/serial/suncore.c
index e35d9ab..b45ba53 100644
--- a/drivers/serial/suncore.c
+++ b/drivers/serial/suncore.c
@@ -30,9 +30,9 @@ void
sunserial_console_termios(struct console *con)
{
char mode[16], buf[16], *s;
- char *mode_prop = "ttyX-mode";
- char *cd_prop = "ttyX-ignore-cd";
- char *dtr_prop = "ttyX-rts-dtr-off";
+ char mode_prop[] = "ttyX-mode";
+ char cd_prop[] = "ttyX-ignore-cd";
+ char dtr_prop[] = "ttyX-rts-dtr-off";
char *ssp_console_modes_prop = "ssp-console-modes";
int baud, bits, stop, cflag;
char parity;
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 217a3d6..2f17468 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -221,15 +221,10 @@ int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,

if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
USB_ENDPOINT_XFER_INT) {
- int interval;
-
- if (usb_dev->speed == USB_SPEED_HIGH)
- interval = 1 << min(15, ep->desc.bInterval - 1);
- else
- interval = ep->desc.bInterval;
pipe = (pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30);
usb_fill_int_urb(urb, usb_dev, pipe, data, len,
- usb_api_blocking_completion, NULL, interval);
+ usb_api_blocking_completion, NULL,
+ ep->desc.bInterval);
} else
usb_fill_bulk_urb(urb, usb_dev, pipe, data, len,
usb_api_blocking_completion, NULL);
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c
index 395cced..fec4d25 100644
--- a/drivers/video/neofb.c
+++ b/drivers/video/neofb.c
@@ -1285,34 +1285,36 @@ static int neofb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
if (regno >= fb->cmap.len || regno > 255)
return -EINVAL;

- switch (fb->var.bits_per_pixel) {
- case 8:
+ if (fb->var.bits_per_pixel <= 8) {
outb(regno, 0x3c8);

outb(red >> 10, 0x3c9);
outb(green >> 10, 0x3c9);
outb(blue >> 10, 0x3c9);
- break;
- case 16:
- ((u32 *) fb->pseudo_palette)[regno] =
+ } else if (regno < 16) {
+ switch (fb->var.bits_per_pixel) {
+ case 16:
+ ((u32 *) fb->pseudo_palette)[regno] =
((red & 0xf800)) | ((green & 0xfc00) >> 5) |
((blue & 0xf800) >> 11);
- break;
- case 24:
- ((u32 *) fb->pseudo_palette)[regno] =
+ break;
+ case 24:
+ ((u32 *) fb->pseudo_palette)[regno] =
((red & 0xff00) << 8) | ((green & 0xff00)) |
((blue & 0xff00) >> 8);
- break;
+ break;
#ifdef NO_32BIT_SUPPORT_YET
- case 32:
- ((u32 *) fb->pseudo_palette)[regno] =
+ case 32:
+ ((u32 *) fb->pseudo_palette)[regno] =
((transp & 0xff00) << 16) | ((red & 0xff00) << 8) |
((green & 0xff00)) | ((blue & 0xff00) >> 8);
- break;
+ break;
#endif
- default:
- return 1;
+ default:
+ return 1;
+ }
}
+
return 0;
}

diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index 8b1c5d8..57c3b1c 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -1178,6 +1178,7 @@ static int vt_check(struct file *file)
{
struct tty_struct *tty;
struct inode *inode = file->f_path.dentry->d_inode;
+ struct vc_data *vc;

if (file->f_op->ioctl != tty_ioctl)
return -EINVAL;
@@ -1188,12 +1189,16 @@ static int vt_check(struct file *file)

if (tty->driver->ioctl != vt_ioctl)
return -EINVAL;
-
+
+ vc = (struct vc_data *)tty->driver_data;
+ if (!vc_cons_allocated(vc->vc_num)) /* impossible? */
+ return -ENOIOCTLCMD;
+
/*
* To have permissions to do most of the vt ioctls, we either have
- * to be the owner of the tty, or super-user.
+ * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG.
*/
- if (current->signal->tty == tty || capable(CAP_SYS_ADMIN))
+ if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG))
return 1;
return 0;
}
@@ -1294,16 +1299,28 @@ static int do_unimap_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg,
struct unimapdesc32 tmp;
struct unimapdesc32 __user *user_ud = compat_ptr(arg);
int perm = vt_check(file);
-
- if (perm < 0) return perm;
+ struct vc_data *vc;
+
+ if (perm < 0)
+ return perm;
if (copy_from_user(&tmp, user_ud, sizeof tmp))
return -EFAULT;
+ if (tmp.entries)
+ if (!access_ok(VERIFY_WRITE, compat_ptr(tmp.entries),
+ tmp.entry_ct*sizeof(struct unipair)))
+ return -EFAULT;
+ vc = ((struct tty_struct *)file->private_data)->driver_data;
switch (cmd) {
case PIO_UNIMAP:
- if (!perm) return -EPERM;
- return con_set_unimap(vc_cons[fg_console].d, tmp.entry_ct, compat_ptr(tmp.entries));
+ if (!perm)
+ return -EPERM;
+ return con_set_unimap(vc, tmp.entry_ct,
+ compat_ptr(tmp.entries));
case GIO_UNIMAP:
- return con_get_unimap(vc_cons[fg_console].d, tmp.entry_ct, &(user_ud->entry_ct), compat_ptr(tmp.entries));
+ if (!perm && fg_console != vc->vc_num)
+ return -EPERM;
+ return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct),
+ compat_ptr(tmp.entries));
}
return 0;
}
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 8890eba..bd5a772 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -485,7 +485,7 @@ static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode,
static int fuse_create(struct inode *dir, struct dentry *entry, int mode,
struct nameidata *nd)
{
- if (nd && (nd->flags & LOOKUP_CREATE)) {
+ if (nd && (nd->flags & LOOKUP_OPEN)) {
int err = fuse_create_open(dir, entry, mode, nd);
if (err != -ENOSYS)
return err;
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
index f8bf8da..461460d 100644
--- a/fs/ntfs/inode.c
+++ b/fs/ntfs/inode.c
@@ -141,7 +141,7 @@ static int ntfs_init_locked_inode(struct inode *vi, ntfs_attr *na)
if (!ni->name)
return -ENOMEM;
memcpy(ni->name, na->name, i);
- ni->name[i] = 0;
+ ni->name[na->name_len] = 0;
}
return 0;
}
diff --git a/include/acpi/acpi_numa.h b/include/acpi/acpi_numa.h
index 1049f2a..13a7c5b 100644
--- a/include/acpi/acpi_numa.h
+++ b/include/acpi/acpi_numa.h
@@ -11,11 +11,8 @@
#define MAX_PXM_DOMAINS (256) /* Old pxm spec is defined 8 bit */
#endif

-extern int __cpuinitdata pxm_to_node_map[MAX_PXM_DOMAINS];
-extern int __cpuinitdata node_to_pxm_map[MAX_NUMNODES];
-
-extern int __cpuinit pxm_to_node(int);
-extern int __cpuinit node_to_pxm(int);
+extern int pxm_to_node(int);
+extern int node_to_pxm(int);
extern int __cpuinit acpi_map_pxm_to_node(int);
extern void __cpuinit acpi_unmap_pxm_to_node(int);

diff --git a/include/asm-sparc64/tsb.h b/include/asm-sparc64/tsb.h
index ab55ffc..76e4299 100644
--- a/include/asm-sparc64/tsb.h
+++ b/include/asm-sparc64/tsb.h
@@ -271,7 +271,7 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
#define KERN_TSB4M_LOOKUP_TL1(TAG, REG1, REG2, REG3, REG4, OK_LABEL) \
sethi %hi(swapper_4m_tsb), REG1; \
or REG1, %lo(swapper_4m_tsb), REG1; \
- and TAG, (KERNEL_TSB_NENTRIES - 1), REG2; \
+ and TAG, (KERNEL_TSB4M_NENTRIES - 1), REG2; \
sllx REG2, 4, REG2; \
add REG1, REG2, REG2; \
KTSB_LOAD_QUAD(REG2, REG3); \
diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h
index 81c07cd..9543a55 100644
--- a/include/linux/bootmem.h
+++ b/include/linux/bootmem.h
@@ -59,6 +59,7 @@ extern void *__alloc_bootmem_core(struct bootmem_data *bdata,
unsigned long align,
unsigned long goal,
unsigned long limit);
+extern void *alloc_bootmem_high_node(pg_data_t *pgdat, unsigned long size);

#ifndef CONFIG_HAVE_ARCH_BOOTMEM_NODE
extern void reserve_bootmem(unsigned long addr, unsigned long size);
diff --git a/include/linux/mii.h b/include/linux/mii.h
index beddc6d..151b7e0 100644
--- a/include/linux/mii.h
+++ b/include/linux/mii.h
@@ -56,8 +56,8 @@
#define BMSR_ANEGCOMPLETE 0x0020 /* Auto-negotiation complete */
#define BMSR_RESV 0x00c0 /* Unused... */
#define BMSR_ESTATEN 0x0100 /* Extended Status in R15 */
-#define BMSR_100FULL2 0x0200 /* Can do 100BASE-T2 HDX */
-#define BMSR_100HALF2 0x0400 /* Can do 100BASE-T2 FDX */
+#define BMSR_100HALF2 0x0200 /* Can do 100BASE-T2 HDX */
+#define BMSR_100FULL2 0x0400 /* Can do 100BASE-T2 FDX */
#define BMSR_10HALF 0x0800 /* Can do 10mbps, half-duplex */
#define BMSR_10FULL 0x1000 /* Can do 10mbps, full-duplex */
#define BMSR_100HALF 0x2000 /* Can do 100mbps, half-duplex */
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 600308f..db2ba30 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -1287,6 +1287,7 @@
#define PCI_DEVICE_ID_VIA_P4M800CE 0x0314
#define PCI_DEVICE_ID_VIA_P4M890 0x0327
#define PCI_DEVICE_ID_VIA_VT3336 0x0336
+#define PCI_DEVICE_ID_VIA_VT3351 0x0351
#define PCI_DEVICE_ID_VIA_8371_0 0x0391
#define PCI_DEVICE_ID_VIA_8501_0 0x0501
#define PCI_DEVICE_ID_VIA_82C561 0x0561
@@ -2259,11 +2260,11 @@
#define PCI_DEVICE_ID_INTEL_ICH8_5 0x283e
#define PCI_DEVICE_ID_INTEL_ICH8_6 0x2850
#define PCI_DEVICE_ID_INTEL_ICH9_0 0x2910
-#define PCI_DEVICE_ID_INTEL_ICH9_1 0x2911
+#define PCI_DEVICE_ID_INTEL_ICH9_1 0x2917
#define PCI_DEVICE_ID_INTEL_ICH9_2 0x2912
#define PCI_DEVICE_ID_INTEL_ICH9_3 0x2913
#define PCI_DEVICE_ID_INTEL_ICH9_4 0x2914
-#define PCI_DEVICE_ID_INTEL_ICH9_5 0x2915
+#define PCI_DEVICE_ID_INTEL_ICH9_5 0x2919
#define PCI_DEVICE_ID_INTEL_ICH9_6 0x2930
#define PCI_DEVICE_ID_INTEL_82855PM_HB 0x3340
#define PCI_DEVICE_ID_INTEL_82830_HB 0x3575
diff --git a/include/linux/raid/bitmap.h b/include/linux/raid/bitmap.h
index 6db9a4c..dd5a05d 100644
--- a/include/linux/raid/bitmap.h
+++ b/include/linux/raid/bitmap.h
@@ -232,6 +232,7 @@ struct bitmap {
struct page **filemap; /* list of cache pages for the file */
unsigned long *filemap_attr; /* attributes associated w/ filemap pages */
unsigned long file_pages; /* number of pages in the file */
+ int last_page_size; /* bytes in the last page */

unsigned long flags;

diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
index 2a7b38d..1a76bda 100644
--- a/include/linux/workqueue.h
+++ b/include/linux/workqueue.h
@@ -162,7 +162,7 @@ extern struct workqueue_struct *__create_workqueue(const char *name,
int singlethread,
int freezeable);
#define create_workqueue(name) __create_workqueue((name), 0, 0)
-#define create_freezeable_workqueue(name) __create_workqueue((name), 0, 1)
+#define create_freezeable_workqueue(name) __create_workqueue((name), 1, 1)
#define create_singlethread_workqueue(name) __create_workqueue((name), 1, 0)

extern void destroy_workqueue(struct workqueue_struct *wq);
diff --git a/include/net/af_unix.h b/include/net/af_unix.h
index c0398f5..65f49fd 100644
--- a/include/net/af_unix.h
+++ b/include/net/af_unix.h
@@ -62,13 +62,11 @@ struct unix_skb_parms {
#define UNIXCREDS(skb) (&UNIXCB((skb)).creds)
#define UNIXSID(skb) (&UNIXCB((skb)).secid)

-#define unix_state_rlock(s) spin_lock(&unix_sk(s)->lock)
-#define unix_state_runlock(s) spin_unlock(&unix_sk(s)->lock)
-#define unix_state_wlock(s) spin_lock(&unix_sk(s)->lock)
-#define unix_state_wlock_nested(s) \
+#define unix_state_lock(s) spin_lock(&unix_sk(s)->lock)
+#define unix_state_unlock(s) spin_unlock(&unix_sk(s)->lock)
+#define unix_state_lock_nested(s) \
spin_lock_nested(&unix_sk(s)->lock, \
SINGLE_DEPTH_NESTING)
-#define unix_state_wunlock(s) spin_unlock(&unix_sk(s)->lock)

#ifdef __KERNEL__
/* The AF_UNIX socket */
diff --git a/kernel/sched.c b/kernel/sched.c
index b9a6837..a3993b9 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -4545,9 +4545,7 @@ int __sched cond_resched_softirq(void)
BUG_ON(!in_softirq());

if (need_resched() && system_state == SYSTEM_RUNNING) {
- raw_local_irq_disable();
- _local_bh_enable();
- raw_local_irq_enable();
+ local_bh_enable();
__cond_resched();
local_bh_disable();
return 1;
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c
index eadfce2..8001d37 100644
--- a/kernel/time/tick-broadcast.c
+++ b/kernel/time/tick-broadcast.c
@@ -243,11 +243,18 @@ void tick_broadcast_on_off(unsigned long reason, int *oncpu)
{
int cpu = get_cpu();

- if (cpu == *oncpu)
- tick_do_broadcast_on_off(&reason);
- else
- smp_call_function_single(*oncpu, tick_do_broadcast_on_off,
- &reason, 1, 1);
+ if (!cpu_isset(*oncpu, cpu_online_map)) {
+ printk(KERN_ERR "tick-braodcast: ignoring broadcast for "
+ "offline CPU #%d\n", *oncpu);
+ } else {
+
+ if (cpu == *oncpu)
+ tick_do_broadcast_on_off(&reason);
+ else
+ smp_call_function_single(*oncpu,
+ tick_do_broadcast_on_off,
+ &reason, 1, 1);
+ }
put_cpu();
}

diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index f4fc867..d9a864f 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -167,9 +167,15 @@ void tick_nohz_stop_sched_tick(void)
goto end;

cpu = smp_processor_id();
- if (unlikely(local_softirq_pending()))
- printk(KERN_ERR "NOHZ: local_softirq_pending %02x\n",
- local_softirq_pending());
+ if (unlikely(local_softirq_pending())) {
+ static int ratelimit;
+
+ if (ratelimit < 10) {
+ printk(KERN_ERR "NOHZ: local_softirq_pending %02x\n",
+ local_softirq_pending());
+ ratelimit++;
+ }
+ }

now = ktime_get();
/*
diff --git a/kernel/time/timer_stats.c b/kernel/time/timer_stats.c
index 1bc4882..73ddbeb 100644
--- a/kernel/time/timer_stats.c
+++ b/kernel/time/timer_stats.c
@@ -117,21 +117,6 @@ static struct entry entries[MAX_ENTRIES];

static atomic_t overflow_count;

-static void reset_entries(void)
-{
- nr_entries = 0;
- memset(entries, 0, sizeof(entries));
- atomic_set(&overflow_count, 0);
-}
-
-static struct entry *alloc_entry(void)
-{
- if (nr_entries >= MAX_ENTRIES)
- return NULL;
-
- return entries + nr_entries++;
-}
-
/*
* The entries are in a hash-table, for fast lookup:
*/
@@ -149,6 +134,22 @@ static struct entry *alloc_entry(void)

static struct entry *tstat_hash_table[TSTAT_HASH_SIZE] __read_mostly;

+static void reset_entries(void)
+{
+ nr_entries = 0;
+ memset(entries, 0, sizeof(entries));
+ memset(tstat_hash_table, 0, sizeof(tstat_hash_table));
+ atomic_set(&overflow_count, 0);
+}
+
+static struct entry *alloc_entry(void)
+{
+ if (nr_entries >= MAX_ENTRIES)
+ return NULL;
+
+ return entries + nr_entries++;
+}
+
static int match_entries(struct entry *entry1, struct entry *entry2)
{
return entry1->timer == entry2->timer &&
@@ -202,12 +203,15 @@ static struct entry *tstat_lookup(struct entry *entry, char *comm)
if (curr) {
*curr = *entry;
curr->count = 0;
+ curr->next = NULL;
memcpy(curr->comm, comm, TASK_COMM_LEN);
+
+ smp_mb(); /* Ensure that curr is initialized before insert */
+
if (prev)
prev->next = curr;
else
*head = curr;
- curr->next = NULL;
}
out_unlock:
spin_unlock(&table_lock);
@@ -232,10 +236,15 @@ void timer_stats_update_stats(void *timer, pid_t pid, void *startf,
/*
* It doesnt matter which lock we take:
*/
- spinlock_t *lock = &per_cpu(lookup_lock, raw_smp_processor_id());
+ spinlock_t *lock;
struct entry *entry, input;
unsigned long flags;

+ if (likely(!active))
+ return;
+
+ lock = &per_cpu(lookup_lock, raw_smp_processor_id());
+
input.timer = timer;
input.start_func = startf;
input.expire_func = timerf;
@@ -364,6 +373,7 @@ static ssize_t tstats_write(struct file *file, const char __user *buf,
if (!active) {
reset_entries();
time_start = ktime_get();
+ smp_mb();
active = 1;
}
break;
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 3f3e740..c93a502 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -143,7 +143,10 @@ config TIMER_STATS
reprogrammed. The statistics can be read from /proc/timer_stats.
The statistics collection is started by writing 1 to /proc/timer_stats,
writing 0 stops it. This feature is useful to collect information
- about timer usage patterns in kernel and userspace.
+ about timer usage patterns in kernel and userspace. This feature
+ is lightweight if enabled in the kernel config but not activated
+ (it defaults to deactivated on bootup and will only be activated
+ if some application like powertop activates it explicitly).

config DEBUG_SLAB
bool "Debug slab memory allocations"
diff --git a/mm/sparse.c b/mm/sparse.c
index ac26eb0..faa08e2 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -209,6 +209,12 @@ static int sparse_init_one_section(struct mem_section *ms,
return 1;
}

+__attribute__((weak))
+void *alloc_bootmem_high_node(pg_data_t *pgdat, unsigned long size)
+{
+ return NULL;
+}
+
static struct page *sparse_early_mem_map_alloc(unsigned long pnum)
{
struct page *map;
@@ -219,6 +225,11 @@ static struct page *sparse_early_mem_map_alloc(unsigned long pnum)
if (map)
return map;

+ map = alloc_bootmem_high_node(NODE_DATA(nid),
+ sizeof(struct page) * PAGES_PER_SECTION);
+ if (map)
+ return map;
+
map = alloc_bootmem_node(NODE_DATA(nid),
sizeof(struct page) * PAGES_PER_SECTION);
if (map)
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 71f5cfb..2f6e1ea 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -656,7 +656,8 @@ static int hci_sock_dev_event(struct notifier_block *this, unsigned long event,
/* Detach sockets from device */
read_lock(&hci_sk_list.lock);
sk_for_each(sk, node, &hci_sk_list.head) {
- lock_sock(sk);
+ local_bh_disable();
+ bh_lock_sock_nested(sk);
if (hci_pi(sk)->hdev == hdev) {
hci_pi(sk)->hdev = NULL;
sk->sk_err = EPIPE;
@@ -665,7 +666,8 @@ static int hci_sock_dev_event(struct notifier_block *this, unsigned long event,

hci_dev_put(hdev);
}
- release_sock(sk);
+ bh_unlock_sock(sk);
+ local_bh_enable();
}
read_unlock(&hci_sk_list.lock);
}
diff --git a/net/core/dev.c b/net/core/dev.c
index 4dc93cc..0caddcf 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3135,7 +3135,6 @@ void netdev_run_todo(void)
continue;
}

- netdev_unregister_sysfs(dev);
dev->reg_state = NETREG_UNREGISTERED;

netdev_wait_allrefs(dev);
@@ -3146,11 +3145,11 @@ void netdev_run_todo(void)
BUG_TRAP(!dev->ip6_ptr);
BUG_TRAP(!dev->dn_ptr);

- /* It must be the very last action,
- * after this 'dev' may point to freed up memory.
- */
if (dev->destructor)
dev->destructor(dev);
+
+ /* Free network device */
+ kobject_put(&dev->dev.kobj);
}

out:
@@ -3305,6 +3304,9 @@ void unregister_netdevice(struct net_device *dev)
/* Notifier chain MUST detach us from master device. */
BUG_TRAP(!dev->master);

+ /* Remove entries from sysfs */
+ netdev_unregister_sysfs(dev);
+
/* Finish processing unregister after unlock */
net_set_todo(dev);

diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index 4cbb129..1fb7aec 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -451,9 +451,15 @@ static struct class net_class = {
#endif
};

+/* Delete sysfs entries but hold kobject reference until after all
+ * netdev references are gone.
+ */
void netdev_unregister_sysfs(struct net_device * net)
{
- device_del(&(net->dev));
+ struct device *dev = &(net->dev);
+
+ kobject_get(&dev->kobj);
+ device_del(dev);
}

/* Create sysfs entries for network device. */
diff --git a/net/core/sock.c b/net/core/sock.c
index 27c4f62..a36a965 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -204,7 +204,19 @@ static int sock_set_timeout(long *timeo_p, char __user *optval, int optlen)
return -EINVAL;
if (copy_from_user(&tv, optval, sizeof(tv)))
return -EFAULT;
-
+ if (tv.tv_usec < 0 || tv.tv_usec >= USEC_PER_SEC)
+ return -EDOM;
+
+ if (tv.tv_sec < 0) {
+ static int warned = 0;
+ *timeo_p = 0;
+ if (warned < 10 && net_ratelimit())
+ warned++;
+ printk(KERN_INFO "sock_set_timeout: `%s' (pid %d) "
+ "tries to set negative timeout\n",
+ current->comm, current->pid);
+ return 0;
+ }
*timeo_p = MAX_SCHEDULE_TIMEOUT;
if (tv.tv_sec == 0 && tv.tv_usec == 0)
return 0;
diff --git a/net/core/utils.c b/net/core/utils.c
index 07236c1..24c30c1 100644
--- a/net/core/utils.c
+++ b/net/core/utils.c
@@ -137,16 +137,16 @@ int in4_pton(const char *src, int srclen,
while(1) {
int c;
c = xdigit2bin(srclen > 0 ? *s : '\0', delim);
- if (!(c & (IN6PTON_DIGIT | IN6PTON_DOT | IN6PTON_DELIM))) {
+ if (!(c & (IN6PTON_DIGIT | IN6PTON_DOT | IN6PTON_DELIM | IN6PTON_COLON_MASK))) {
goto out;
}
- if (c & (IN6PTON_DOT | IN6PTON_DELIM)) {
+ if (c & (IN6PTON_DOT | IN6PTON_DELIM | IN6PTON_COLON_MASK)) {
if (w == 0)
goto out;
*d++ = w & 0xff;
w = 0;
i++;
- if (c & IN6PTON_DELIM) {
+ if (c & (IN6PTON_DELIM | IN6PTON_COLON_MASK)) {
if (i != 4)
goto out;
break;
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index 9e8ef50..5fc4a05 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -43,11 +43,11 @@ config IP_ADVANCED_ROUTER
asymmetric routing (packets from you to a host take a different path
than packets from that host to you) or if you operate a non-routing
host which has several IP addresses on different interfaces. To turn
- rp_filter off use:
+ rp_filter on use:

- echo 0 > /proc/sys/net/ipv4/conf/<device>/rp_filter
+ echo 1 > /proc/sys/net/ipv4/conf/<device>/rp_filter
or
- echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter
+ echo 1 > /proc/sys/net/ipv4/conf/all/rp_filter

If unsure, say N here.

diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 4b7a0d9..03d9659 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -513,9 +513,15 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)

saddr = iph->daddr;
if (!(rt->rt_flags & RTCF_LOCAL)) {
- if (sysctl_icmp_errors_use_inbound_ifaddr)
- saddr = inet_select_addr(skb_in->dev, 0, RT_SCOPE_LINK);
- else
+ struct net_device *dev = NULL;
+
+ if (rt->fl.iif && sysctl_icmp_errors_use_inbound_ifaddr)
+ dev = dev_get_by_index(rt->fl.iif);
+
+ if (dev) {
+ saddr = inet_select_addr(dev, 0, RT_SCOPE_LINK);
+ dev_put(dev);
+ } else
saddr = 0;
}

diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 43fb160..fbe7714 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -31,10 +31,8 @@ EXPORT_SYMBOL(inet_csk_timer_bug_msg);

/*
* This array holds the first and last local port number.
- * For high-usage systems, use sysctl to change this to
- * 32768-61000
*/
-int sysctl_local_port_range[2] = { 1024, 4999 };
+int sysctl_local_port_range[2] = { 32768, 61000 };

int inet_csk_bind_conflict(const struct sock *sk,
const struct inet_bind_bucket *tb)
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 824c6b9..5055190 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2445,13 +2445,10 @@ void __init tcp_init(void)
order++)
;
if (order >= 4) {
- sysctl_local_port_range[0] = 32768;
- sysctl_local_port_range[1] = 61000;
tcp_death_row.sysctl_max_tw_buckets = 180000;
sysctl_tcp_max_orphans = 4096 << (order - 4);
sysctl_max_syn_backlog = 1024;
} else if (order < 3) {
- sysctl_local_port_range[0] = 1024 * (3 - order);
tcp_death_row.sysctl_max_tw_buckets >>= (3 - order);
sysctl_tcp_max_orphans >>= (3 - order);
sysctl_max_syn_backlog = 128;
diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c
index 78e80de..9fcf6d8 100644
--- a/net/ipv4/xfrm4_input.c
+++ b/net/ipv4/xfrm4_input.c
@@ -138,10 +138,8 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
nf_reset(skb);

if (decaps) {
- if (!(skb->dev->flags&IFF_LOOPBACK)) {
- dst_release(skb->dst);
- skb->dst = NULL;
- }
+ dst_release(skb->dst);
+ skb->dst = NULL;
netif_rx(skb);
return 0;
} else {
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
index ceb4376..5115574 100644
--- a/net/ipv4/xfrm4_mode_tunnel.c
+++ b/net/ipv4/xfrm4_mode_tunnel.c
@@ -84,6 +84,8 @@ static int xfrm4_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
top_iph->saddr = x->props.saddr.a4;
top_iph->daddr = x->id.daddr.a4;

+ skb->protocol = htons(ETH_P_IP);
+
memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
return 0;
}
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 268f476..5983c54 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -619,14 +619,6 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,

ins = &fn->leaf;

- if (fn->fn_flags&RTN_TL_ROOT &&
- fn->leaf == &ip6_null_entry &&
- !(rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) ){
- fn->leaf = rt;
- rt->u.dst.rt6_next = NULL;
- goto out;
- }
-
for (iter = fn->leaf; iter; iter=iter->u.dst.rt6_next) {
/*
* Search for duplicates
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
index 31f651f..c53c0d3 100644
--- a/net/ipv6/xfrm6_input.c
+++ b/net/ipv6/xfrm6_input.c
@@ -104,10 +104,8 @@ int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi)
nf_reset(skb);

if (decaps) {
- if (!(skb->dev->flags&IFF_LOOPBACK)) {
- dst_release(skb->dst);
- skb->dst = NULL;
- }
+ dst_release(skb->dst);
+ skb->dst = NULL;
netif_rx(skb);
return -1;
} else {
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c
index 0bc866c..8741bcd 100644
--- a/net/ipv6/xfrm6_mode_tunnel.c
+++ b/net/ipv6/xfrm6_mode_tunnel.c
@@ -80,6 +80,7 @@ static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
top_iph->hop_limit = dst_metric(dst->child, RTAX_HOPLIMIT);
ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr);
ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr);
+ skb->protocol = htons(ETH_P_IPV6);
return 0;
}

diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 6069716..f464c43 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -175,11 +175,11 @@ static struct sock *unix_peer_get(struct sock *s)
{
struct sock *peer;

- unix_state_rlock(s);
+ unix_state_lock(s);
peer = unix_peer(s);
if (peer)
sock_hold(peer);
- unix_state_runlock(s);
+ unix_state_unlock(s);
return peer;
}

@@ -370,7 +370,7 @@ static int unix_release_sock (struct sock *sk, int embrion)
unix_remove_socket(sk);

/* Clear state */
- unix_state_wlock(sk);
+ unix_state_lock(sk);
sock_orphan(sk);
sk->sk_shutdown = SHUTDOWN_MASK;
dentry = u->dentry;
@@ -379,7 +379,7 @@ static int unix_release_sock (struct sock *sk, int embrion)
u->mnt = NULL;
state = sk->sk_state;
sk->sk_state = TCP_CLOSE;
- unix_state_wunlock(sk);
+ unix_state_unlock(sk);

wake_up_interruptible_all(&u->peer_wait);

@@ -387,12 +387,12 @@ static int unix_release_sock (struct sock *sk, int embrion)

if (skpair!=NULL) {
if (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) {
- unix_state_wlock(skpair);
+ unix_state_lock(skpair);
/* No more writes */
skpair->sk_shutdown = SHUTDOWN_MASK;
if (!skb_queue_empty(&sk->sk_receive_queue) || embrion)
skpair->sk_err = ECONNRESET;
- unix_state_wunlock(skpair);
+ unix_state_unlock(skpair);
skpair->sk_state_change(skpair);
read_lock(&skpair->sk_callback_lock);
sk_wake_async(skpair,1,POLL_HUP);
@@ -449,7 +449,7 @@ static int unix_listen(struct socket *sock, int backlog)
err = -EINVAL;
if (!u->addr)
goto out; /* No listens on an unbound socket */
- unix_state_wlock(sk);
+ unix_state_lock(sk);
if (sk->sk_state != TCP_CLOSE && sk->sk_state != TCP_LISTEN)
goto out_unlock;
if (backlog > sk->sk_max_ack_backlog)
@@ -463,7 +463,7 @@ static int unix_listen(struct socket *sock, int backlog)
err = 0;

out_unlock:
- unix_state_wunlock(sk);
+ unix_state_unlock(sk);
out:
return err;
}
@@ -859,6 +859,31 @@ out_mknod_parent:
goto out_up;
}

+static void unix_state_double_lock(struct sock *sk1, struct sock *sk2)
+{
+ if (unlikely(sk1 == sk2) || !sk2) {
+ unix_state_lock(sk1);
+ return;
+ }
+ if (sk1 < sk2) {
+ unix_state_lock(sk1);
+ unix_state_lock_nested(sk2);
+ } else {
+ unix_state_lock(sk2);
+ unix_state_lock_nested(sk1);
+ }
+}
+
+static void unix_state_double_unlock(struct sock *sk1, struct sock *sk2)
+{
+ if (unlikely(sk1 == sk2) || !sk2) {
+ unix_state_unlock(sk1);
+ return;
+ }
+ unix_state_unlock(sk1);
+ unix_state_unlock(sk2);
+}
+
static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
int alen, int flags)
{
@@ -878,11 +903,19 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
!unix_sk(sk)->addr && (err = unix_autobind(sock)) != 0)
goto out;

+restart:
other=unix_find_other(sunaddr, alen, sock->type, hash, &err);
if (!other)
goto out;

- unix_state_wlock(sk);
+ unix_state_double_lock(sk, other);
+
+ /* Apparently VFS overslept socket death. Retry. */
+ if (sock_flag(other, SOCK_DEAD)) {
+ unix_state_double_unlock(sk, other);
+ sock_put(other);
+ goto restart;
+ }

err = -EPERM;
if (!unix_may_send(sk, other))
@@ -897,7 +930,7 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
* 1003.1g breaking connected state with AF_UNSPEC
*/
other = NULL;
- unix_state_wlock(sk);
+ unix_state_double_lock(sk, other);
}

/*
@@ -906,19 +939,19 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
if (unix_peer(sk)) {
struct sock *old_peer = unix_peer(sk);
unix_peer(sk)=other;
- unix_state_wunlock(sk);
+ unix_state_double_unlock(sk, other);

if (other != old_peer)
unix_dgram_disconnected(sk, old_peer);
sock_put(old_peer);
} else {
unix_peer(sk)=other;
- unix_state_wunlock(sk);
+ unix_state_double_unlock(sk, other);
}
return 0;

out_unlock:
- unix_state_wunlock(sk);
+ unix_state_double_unlock(sk, other);
sock_put(other);
out:
return err;
@@ -937,7 +970,7 @@ static long unix_wait_for_peer(struct sock *other, long timeo)
(skb_queue_len(&other->sk_receive_queue) >
other->sk_max_ack_backlog);

- unix_state_runlock(other);
+ unix_state_unlock(other);

if (sched)
timeo = schedule_timeout(timeo);
@@ -995,11 +1028,11 @@ restart:
goto out;

/* Latch state of peer */
- unix_state_rlock(other);
+ unix_state_lock(other);

/* Apparently VFS overslept socket death. Retry. */
if (sock_flag(other, SOCK_DEAD)) {
- unix_state_runlock(other);
+ unix_state_unlock(other);
sock_put(other);
goto restart;
}
@@ -1049,18 +1082,18 @@ restart:
goto out_unlock;
}

- unix_state_wlock_nested(sk);
+ unix_state_lock_nested(sk);

if (sk->sk_state != st) {
- unix_state_wunlock(sk);
- unix_state_runlock(other);
+ unix_state_unlock(sk);
+ unix_state_unlock(other);
sock_put(other);
goto restart;
}

err = security_unix_stream_connect(sock, other->sk_socket, newsk);
if (err) {
- unix_state_wunlock(sk);
+ unix_state_unlock(sk);
goto out_unlock;
}

@@ -1097,7 +1130,7 @@ restart:
smp_mb__after_atomic_inc(); /* sock_hold() does an atomic_inc() */
unix_peer(sk) = newsk;

- unix_state_wunlock(sk);
+ unix_state_unlock(sk);

/* take ten and and send info to listening sock */
spin_lock(&other->sk_receive_queue.lock);
@@ -1106,14 +1139,14 @@ restart:
* is installed to listening socket. */
atomic_inc(&newu->inflight);
spin_unlock(&other->sk_receive_queue.lock);
- unix_state_runlock(other);
+ unix_state_unlock(other);
other->sk_data_ready(other, 0);
sock_put(other);
return 0;

out_unlock:
if (other)
- unix_state_runlock(other);
+ unix_state_unlock(other);

out:
if (skb)
@@ -1179,10 +1212,10 @@ static int unix_accept(struct socket *sock, struct socket *newsock, int flags)
wake_up_interruptible(&unix_sk(sk)->peer_wait);

/* attach accepted sock to socket */
- unix_state_wlock(tsk);
+ unix_state_lock(tsk);
newsock->state = SS_CONNECTED;
sock_graft(tsk, newsock);
- unix_state_wunlock(tsk);
+ unix_state_unlock(tsk);
return 0;

out:
@@ -1209,7 +1242,7 @@ static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_
}

u = unix_sk(sk);
- unix_state_rlock(sk);
+ unix_state_lock(sk);
if (!u->addr) {
sunaddr->sun_family = AF_UNIX;
sunaddr->sun_path[0] = 0;
@@ -1220,7 +1253,7 @@ static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_
*uaddr_len = addr->len;
memcpy(sunaddr, addr->name, *uaddr_len);
}
- unix_state_runlock(sk);
+ unix_state_unlock(sk);
sock_put(sk);
out:
return err;
@@ -1338,7 +1371,7 @@ restart:
goto out_free;
}

- unix_state_rlock(other);
+ unix_state_lock(other);
err = -EPERM;
if (!unix_may_send(sk, other))
goto out_unlock;
@@ -1348,20 +1381,20 @@ restart:
* Check with 1003.1g - what should
* datagram error
*/
- unix_state_runlock(other);
+ unix_state_unlock(other);
sock_put(other);

err = 0;
- unix_state_wlock(sk);
+ unix_state_lock(sk);
if (unix_peer(sk) == other) {
unix_peer(sk)=NULL;
- unix_state_wunlock(sk);
+ unix_state_unlock(sk);

unix_dgram_disconnected(sk, other);
sock_put(other);
err = -ECONNREFUSED;
} else {
- unix_state_wunlock(sk);
+ unix_state_unlock(sk);
}

other = NULL;
@@ -1398,14 +1431,14 @@ restart:
}

skb_queue_tail(&other->sk_receive_queue, skb);
- unix_state_runlock(other);
+ unix_state_unlock(other);
other->sk_data_ready(other, len);
sock_put(other);
scm_destroy(siocb->scm);
return len;

out_unlock:
- unix_state_runlock(other);
+ unix_state_unlock(other);
out_free:
kfree_skb(skb);
out:
@@ -1495,14 +1528,14 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
goto out_err;
}

- unix_state_rlock(other);
+ unix_state_lock(other);

if (sock_flag(other, SOCK_DEAD) ||
(other->sk_shutdown & RCV_SHUTDOWN))
goto pipe_err_free;

skb_queue_tail(&other->sk_receive_queue, skb);
- unix_state_runlock(other);
+ unix_state_unlock(other);
other->sk_data_ready(other, size);
sent+=size;
}
@@ -1513,7 +1546,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
return sent;

pipe_err_free:
- unix_state_runlock(other);
+ unix_state_unlock(other);
kfree_skb(skb);
pipe_err:
if (sent==0 && !(msg->msg_flags&MSG_NOSIGNAL))
@@ -1642,7 +1675,7 @@ static long unix_stream_data_wait(struct sock * sk, long timeo)
{
DEFINE_WAIT(wait);

- unix_state_rlock(sk);
+ unix_state_lock(sk);

for (;;) {
prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
@@ -1655,14 +1688,14 @@ static long unix_stream_data_wait(struct sock * sk, long timeo)
break;

set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
- unix_state_runlock(sk);
+ unix_state_unlock(sk);
timeo = schedule_timeout(timeo);
- unix_state_rlock(sk);
+ unix_state_lock(sk);
clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
}

finish_wait(sk->sk_sleep, &wait);
- unix_state_runlock(sk);
+ unix_state_unlock(sk);
return timeo;
}

@@ -1817,12 +1850,12 @@ static int unix_shutdown(struct socket *sock, int mode)
mode = (mode+1)&(RCV_SHUTDOWN|SEND_SHUTDOWN);

if (mode) {
- unix_state_wlock(sk);
+ unix_state_lock(sk);
sk->sk_shutdown |= mode;
other=unix_peer(sk);
if (other)
sock_hold(other);
- unix_state_wunlock(sk);
+ unix_state_unlock(sk);
sk->sk_state_change(sk);

if (other &&
@@ -1834,9 +1867,9 @@ static int unix_shutdown(struct socket *sock, int mode)
peer_mode |= SEND_SHUTDOWN;
if (mode&SEND_SHUTDOWN)
peer_mode |= RCV_SHUTDOWN;
- unix_state_wlock(other);
+ unix_state_lock(other);
other->sk_shutdown |= peer_mode;
- unix_state_wunlock(other);
+ unix_state_unlock(other);
other->sk_state_change(other);
read_lock(&other->sk_callback_lock);
if (peer_mode == SHUTDOWN_MASK)
@@ -1974,7 +2007,7 @@ static int unix_seq_show(struct seq_file *seq, void *v)
else {
struct sock *s = v;
struct unix_sock *u = unix_sk(s);
- unix_state_rlock(s);
+ unix_state_lock(s);

seq_printf(seq, "%p: %08X %08X %08X %04X %02X %5lu",
s,
@@ -2002,7 +2035,7 @@ static int unix_seq_show(struct seq_file *seq, void *v)
for ( ; i < len; i++)
seq_putc(seq, u->addr->name->sun_path[i]);
}
- unix_state_runlock(s);
+ unix_state_unlock(s);
seq_putc(seq, '\n');
}

diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 1672cac..632da27 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -198,6 +198,7 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
#define RIRB_INT_MASK 0x05

/* STATESTS int mask: SD2,SD1,SD0 */
+#define AZX_MAX_CODECS 3
#define STATESTS_INT_MASK 0x07

/* SD_CTL bits */
@@ -978,7 +979,7 @@ static unsigned int azx_max_codecs[] __devinitdata = {
static int __devinit azx_codec_create(struct azx *chip, const char *model)
{
struct hda_bus_template bus_temp;
- int c, codecs, err;
+ int c, codecs, audio_codecs, err;

memset(&bus_temp, 0, sizeof(bus_temp));
bus_temp.private_data = chip;
@@ -990,16 +991,30 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model)
if ((err = snd_hda_bus_new(chip->card, &bus_temp, &chip->bus)) < 0)
return err;

- codecs = 0;
- for (c = 0; c < azx_max_codecs[chip->driver_type]; c++) {
+ codecs = audio_codecs = 0;
+ for (c = 0; c < AZX_MAX_CODECS; c++) {
if ((chip->codec_mask & (1 << c)) & probe_mask) {
- err = snd_hda_codec_new(chip->bus, c, NULL);
+ struct hda_codec *codec;
+ err = snd_hda_codec_new(chip->bus, c, &codec);
if (err < 0)
continue;
codecs++;
+ if (codec->afg)
+ audio_codecs++;
}
}
- if (! codecs) {
+ if (!audio_codecs) {
+ /* probe additional slots if no codec is found */
+ for (; c < azx_max_codecs[chip->driver_type]; c++) {
+ if ((chip->codec_mask & (1 << c)) & probe_mask) {
+ err = snd_hda_codec_new(chip->bus, c, NULL);
+ if (err < 0)
+ continue;
+ codecs++;
+ }
+ }
+ }
+ if (!codecs) {
snd_printk(KERN_ERR SFX "no codecs initialized\n");
return -ENXIO;
}
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
index 7073e8e..28684ee 100644
--- a/sound/soc/codecs/wm8750.c
+++ b/sound/soc/codecs/wm8750.c
@@ -808,7 +808,7 @@ static int wm8750_init(struct snd_soc_device *socdev)
codec->dai = &wm8750_dai;
codec->num_dai = 1;
codec->reg_cache_size = sizeof(wm8750_reg);
- codec->reg_cache = kmemdup(wm8750_reg, sizeof(wm8750_reg), GFP_KRENEL);
+ codec->reg_cache = kmemdup(wm8750_reg, sizeof(wm8750_reg), GFP_KERNEL);
if (codec->reg_cache == NULL)
return -ENOMEM;

diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h
index 8582620..8fcbe93 100644
--- a/sound/usb/usbquirks.h
+++ b/sound/usb/usbquirks.h
@@ -40,6 +40,29 @@
.bInterfaceClass = USB_CLASS_VENDOR_SPEC

/*
+ * Logitech QuickCam: bDeviceClass is vendor-specific, so generic interface
+ * class matches do not take effect without an explicit ID match.
+ */
+{
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
+ USB_DEVICE_ID_MATCH_INT_CLASS |
+ USB_DEVICE_ID_MATCH_INT_SUBCLASS,
+ .idVendor = 0x046d,
+ .idProduct = 0x08f0,
+ .bInterfaceClass = USB_CLASS_AUDIO,
+ .bInterfaceSubClass = USB_SUBCLASS_AUDIO_CONTROL
+},
+{
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
+ USB_DEVICE_ID_MATCH_INT_CLASS |
+ USB_DEVICE_ID_MATCH_INT_SUBCLASS,
+ .idVendor = 0x046d,
+ .idProduct = 0x08f6,
+ .bInterfaceClass = USB_CLASS_AUDIO,
+ .bInterfaceSubClass = USB_SUBCLASS_AUDIO_CONTROL
+},
+
+/*
* Yamaha devices
*/

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/